diff --git a/drivers/net/wireless/bcmdhd_oo/Kconfig b/drivers/net/wireless/bcmdhd_oo/Kconfig index 1358c981a577dc116d8bf21c832a01cf8f390272..09ce150bc4fd1d37a8765afc21b343a39be15dd8 100644 --- a/drivers/net/wireless/bcmdhd_oo/Kconfig +++ b/drivers/net/wireless/bcmdhd_oo/Kconfig @@ -75,20 +75,13 @@ config BCM43241 This module adds support for wireless adapters based on Broadcom 43241 chipset. -config BCM43456 - tristate "Broadcom 43456 wireless cards support" - depends on BROADCOM_WIFI - ---help--- - This module adds support for wireless adapters based on - Broadcom 43456 chipset. - config BCM43455 tristate "Broadcom 43455 wireless cards support" depends on BROADCOM_WIFI ---help--- This module adds support for wireless adapters based on Broadcom 43455 chipset. - + config BCM4334W tristate "Broadcom 4334W wireless cards support" depends on BROADCOM_WIFI @@ -125,7 +118,7 @@ config BROADCOM_WIFI_RESERVED_MEM config WIFI_BROADCOM_COB bool "BROADCOM WIFI COB" - depends on (BCM43456 || BCM43455 || BCM4343 || BCM43454 || BCM43012) + depends on (BCM43455 || BCM4343 || BCM43454 || BCM43012) ---help--- This is a configuration for Broadcom WIFI COB Type. @@ -187,12 +180,14 @@ config BCMDHD_PREALLOC_PKTIDMAP config BCMDHD_PREALLOC_MEMDUMP bool "BROADCOM PCIE specific memory reserved for MEMDUMP" depends on BROADCOM_WIFI_RESERVED_MEM + default y ---help--- Preallocated memory support for dongle memory dump config BCMDHD_OOB_HOST_WAKE bool "Use the external WLAN_HOST_WAKE pin" depends on BROADCOM_WIFI + default y ---help--- Use the external GPIO pin to wake up host @@ -202,12 +197,6 @@ config SPLIT_ARGOS_SET ---help--- To support SPLIT_ARGOS_SET -config WLAN_GREAT - bool "model code for GREAT" - depends on BROADCOM_WIFI - ---help--- - This is configuration for Great feature - config BCM_DETECT_CONSECUTIVE_HANG bool "Detect consecutive hang event" depends on BROADCOM_WIFI diff --git a/drivers/net/wireless/bcmdhd_oo/Makefile b/drivers/net/wireless/bcmdhd_oo/Makefile index 58db8f8fc797970118f27b538fabf67dd486dbfe..5464097269f5b7ba59cba974cad89ecaffbfdcc7 100644 --- a/drivers/net/wireless/bcmdhd_oo/Makefile +++ b/drivers/net/wireless/bcmdhd_oo/Makefile @@ -1,12 +1,12 @@ # -# Copyright (C) 1999-2017, Broadcom Corporation -# +# Copyright (C) 1999-2018, Broadcom. +# # 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 @@ -14,7 +14,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. @@ -101,19 +101,15 @@ endif DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_TXP -DDHD_LB_STATS # Extended HANG event with reason codes DHDCFLAGS += -DDHD_USE_EXTENDED_HANG_REASON - DHDCFLAGS += -DDHD_RECOVER_TIMEOUT + # DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # HEAP ASLR DHDCFLAGS += -DBCM_ASLR_HEAP - ifneq ($(CONFIG_SOC_EXYNOS8895),) # Default Tx LB Enable DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB endif - endif - - ################# # Common feature ################# @@ -170,6 +166,7 @@ DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND DHDCFLAGS += -DDHD_LOSSLESS_ROAMING +DHDCFLAGS += -DSKIP_ROAM_TRIGGER_RESET # Enable Roam time thresh DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND @@ -210,6 +207,8 @@ DHDCFLAGS += -DUNSET_FW_ROAM_WIPHY_FLAG # For special PNO Event keep wake lock for 10sec DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 +# Enable Scheduled scan +DHDCFLAGS += -DWL_SCHED_SCAN # For IPV6 Neighbor Discovery Offload Support DHDCFLAGS += -DIPV6_NDO_SUPPORT @@ -248,7 +247,7 @@ DHDCFLAGS += -DPKTPRIO_OVERRIDE # Prevent rx thread monopolize DHDCFLAGS += -DWAIT_DEQUEUE -# Control PM related value for MFG process(Read from file) +# Control PM related value for MFG process(Read from file) DHDCFLAGS += -DDHD_PM_CONTROL_FROM_FILE # Use Android wake lock mechanism @@ -261,12 +260,10 @@ DHDCFLAGS += -DUSE_INITIAL_SHORT_DWELL_TIME DHDCFLAGS += -DKEEP_JP_REGREV # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDCFLAGS += -DWL_NAN -endif +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDCFLAGS += -DWL_NAN -DWL_NAN_DISC_CACHE +#endif // endif # FCC power limit control on ch12/13. DHDCFLAGS += -DFCC_PWR_LIMIT_2G @@ -277,9 +274,6 @@ DHDCFLAGS += -DUSE_WFA_CERT_CONF # Change the WL_SCAN_TIMER_INTERVAL_MS of DHD DHDCFLAGS += -DCUSTOMER_SCAN_TIMEOUT_SETTING -# Does not forword internal packet -DHDCFLAGS += -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT - # Enable HANG event test private command DHDCFLAGS += -DSUPPORT_TRIGGER_HANG_EVENT @@ -292,14 +286,9 @@ DHDCFLAGS += -DSUPPORT_RANDOM_MAC_SCAN # WLC_E_SET_SSID fail DHDCFLAGS += -DSET_SSID_FAIL_CUSTOM_RC=100 -# Enable to block Band A(5G), Only support Band B(2G) -ifeq ($(CONFIG_WLAN_5GDISABLE),y) -DHDCFLAGS += -DDHD_2G_ONLY_SUPPORT -endif -# Disable VHT(5G HT80) mode -ifeq ($(CONFIG_WLAN_VHTDISABLE),y) -DHDCFLAGS += -DDHD_DISABLE_VHTMODE -endif +# Use legacy random mac +# Disable the legacy randmac and enable scanmac +#DHDCFLAGS += -DLEGACY_RANDOM_MAC # Android Version Check from Platform source ifneq ($(PLATFORM_VERSION),) @@ -311,7 +300,6 @@ endif # Android Platform Definition ############################## - # bcmdhd ####################### # Android N features @@ -359,8 +347,6 @@ DHDCFLAGS :=$(filter-out -DLINKSTAT_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DWL_VENDOR_EXT_SUPPORT,$(DHDCFLAGS)) endif - - ########################## # driver type # m: module type driver @@ -385,13 +371,17 @@ ifneq ($(CONFIG_BCM4361),) DHDCFLAGS += -DUSE_WL_TXBF DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB + DHDCFLAGS += -DDISABLE_WL_FRAMEBURST_SOFTAP DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT +# Debugability + DHDCFLAGS += -DDEBUGABILITY_ECNTRS_LOGGING + DHDCFLAGS += -DDEBUGABILITY_ETD_PRSRV_LOGS # Customer ant select and set PM DHDCFLAGS += -DCUSTOM_SET_ANTNPM DHDCFLAGS += -DCUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE # Customer ocl disabe DHDCFLAGS += -DCUSTOM_SET_OCLOFF + # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 @@ -399,10 +389,21 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DDHDTCPACK_SUPPRESS endif +ifeq ($(CONFIG_ARCH_QCOM),y) + DHDCFLAGS += -DCONFIG_ARCH_MSM + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) + DHDCFLAGS += -DUSE_DMA_LOCK + DHDCFLAGS += -DDHD_MAP_LOGGING +endif + # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -428,25 +429,45 @@ endif # Remove common feature for BCM4361 DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) DHDCFLAGS += -DDHD_LOG_DUMP -# Higher rate beacon transmission at softAP - DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE -# Enhanced radio power save with NOA at softAP - DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE +ifneq ($(CUSTOM_LOG_DUMP_BUFSIZE_MB),) + DHDCFLAGS += -DCUSTOM_LOG_DUMP_BUFSIZE_MB=$(CUSTOM_LOG_DUMP_BUFSIZE_MB) +endif + + DHDCFLAGS += -DWL_SUPP_EVENT + DHDCFLAGS += -DFILTER_IE + DHDCFLAGS += -DNDO_CONFIG_SUPPORT # WBTEXT (11kv) feature DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DWBTEXT_BTMDELTA=0 # LOGTRACE_EVENT DHDCFLAGS += -DSHOW_LOGTRACE DHDCFLAGS += -DLOGTRACE_FROM_FILE -ifeq ($(CONFIG_ARCH_MSM8998),y) -# Use SMMU for IOMEM - DHDCFLAGS += -DUSE_SMMU_ARCH_MSM - DHDCFLAGS += -DSET_DMA_MASK_64BIT -endif +# LAST ROAM EVENT LOG + DHDCFLAGS += -DWL_LASTEVT +# Higher rate beacon transmission at softAP + DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE +# Enhanced radio power save with NOA at softAP + DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE # Expand TCP tx queue to 10 times of default size DHDCFLAGS += -DTSQ_MULTIPLIER=10 # HANG simulation DHDCFLAGS += -DDHD_HANG_SEND_UP_TEST -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA)),y) +# Support Monitor Mode + DHDCFLAGS += -DWL_MONITOR +# Enable health check event handling + DHDCFLAGS += -DDNGL_EVENT_SUPPORT + DHDCFLAGS += -DHCHK_COMMON_SW_EVENT +# Generate .softap.info + DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE +# Use SMMU for IOMEM +ifeq ($(filter y,$(CONFIG_ARCH_MSM8998) $(CONFIG_ARCH_SDM845)),y) + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM + DHDCFLAGS += -DDHD_DUMP_MNGR +endif + +ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) +# IRQSET in DHD + DHDCFLAGS += -DDHD_LB_IRQSET # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 # Disable SOFTAP_SEND_HANGEVT @@ -454,51 +475,24 @@ ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYN # Enable LQCM DHDCFLAGS += -DSUPPORT_LQCM endif -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895)), y) -# DHD_LB_IRQSET - CPU migration by IRQ Affinity Set - DHDCFLAGS += -DDHD_LB_IRQSET -endif -# Generate .softap.info - DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE -ifneq ($(PLATFORM_VERSION),) -# DREAM Android N OS should not use below features -ifeq ($(shell expr $(PLATFORM_VERSION) \< 8.0),1) -ifneq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT)),y) - DREAM_NOS_DISCARD_FEATURES := y -endif -endif - -# Feature Set used for GREAT N OS and Android O OS -ifneq ($(DREAM_NOS_DISCARD_FEATURES),y) +ifeq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Debugaility - DHDCFLAGS += -DDEBUGABILITY + DHDCFLAGS += -DDHD_EVENT_LOG_FILTER DHDCFLAGS += -DDHD_PKT_LOGGING # Debug Wakeup pkt reason DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS -DDHD_WAKE_EVENT_STATUS DHDCFLAGS += -DDHD_WAKEPKT_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC -# LAST ROAM EVENT LOG - DHDCFLAGS += -DWL_LASTEVT # Use single nvram file DHDCFLAGS += -DDHD_USE_SINGLE_NVRAM_FILE -#STAT REPORT -#stat report shall be defined only if LINK STAT is defined - DHDCFLAGS += -DSTAT_REPORT -#define temp static only when SDK doesn't support static memory for STAT REPORT -# DHDCFLAGS += -DSTAT_REPORT_TEMP_STATIC -endif - -# RSSI_SUM_REPORT is used over Android O OS only -ifeq ($(shell expr $(PLATFORM_VERSION) \>= 8.0),1) # RSSI Logging DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT -# Enable NDO_CONFIG_SUPPORT in HAL - DHDCFLAGS += -DNDO_CONFIG_SUPPORT -# changed assoc timeout - DHDCFLAGS += -DCUSTOM_ASSOC_TIMEOUT=20 -endif +# To send hang evnet for Samsung phone platform + DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT +# Enable BIGDATA_SOFTAP + DHDCFLAGS += -DBIGDATA_SOFTAP endif # Use Legacy dump path @@ -535,7 +529,6 @@ ifneq ($(CONFIG_BCM4359),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) @@ -546,11 +539,14 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 DHDCFLAGS += -DDHDTCPACK_SUPPRESS +ifeq ($(CONFIG_ARCH_MSM8998),y) +# Use SMMU for IOMEM + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM endif - ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +endif # New Features DHDCFLAGS += -DWL11U -DMFP @@ -581,14 +577,14 @@ endif DHDCFLAGS += -DDHD_LOG_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC + ifneq ($(CONFIG_WLAN_GRACE),) DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DDHD_DEBUG_UART endif ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_SOC_EXYNOS8890)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 - # Enable Dongle Isolation - DHDCFLAGS += -DDONGLE_ENABLE_ISOLATION # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) endif @@ -712,7 +708,6 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_AMPDU_RELEASE=16 endif - # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -784,21 +779,8 @@ endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif -ifneq ($(CONFIG_BCM43456),) - DHDCFLAGS += -DBCM43456_CHIP - DHDCFLAGS += -DWLADPS_PRIVATE_CMD -endif ifneq ($(CONFIG_BCM43455),) - DHDCFLAGS += -DBCM43455_CHIP -endif -ifneq ($(CONFIG_BCM43454),) - DHDCFLAGS += -DBCM43454_CHIP -endif - -# BCM43454/43455/43456 common difine. -ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456))) - DHDCFLAGS += -DHW_OOB - DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DBCM43455_CHIP -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR @@ -815,9 +797,10 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 # New Features - DHDCFLAGS += -DWL11U -DMFP + DHDCFLAGS += -DWL11U DHDCFLAGS += -DBCMCCX DHDCFLAGS += -DWES_SUPPORT DHDCFLAGS += -DOKC_SUPPORT @@ -829,35 +812,59 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DSUPPORT_2G_VHT DHDCFLAGS += -DSUPPORT_WL_TXPOWER DHDCFLAGS += -DBCMCCX_S69 -ifeq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),y) +ifeq ($(CONFIG_BCM43455),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 - DHDCFLAGS += -DDHD_LOG_DUMP - - # FCC power limit control on ch12/13. - # DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 - -ifneq ($(filter y,$(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43455) $(CONFIG_BCM43456))) -# Enable Firmware Coredump - DHDCFLAGS += -DDHD_FW_COREDUMP -ifeq ($(CONFIG_BCMDHD_PREALLOC_MEMDUMP),y) - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -endif # Enable concate blob path DHDCFLAGS += -DCONCATE_BLOB # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif + +ifneq ($(CONFIG_BCM43454),) + DHDCFLAGS += -DBCM43454_CHIP -DHW_OOB + DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION -DSUPPORT_MULTIPLE_BOARD_REV_FROM_DT + DHDCFLAGS += -DUSE_CID_CHECK + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR + + # tput enhancement + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DCUSTOM_FRAMEBURST_SET=1 + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 + + # New Features + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DDHD_ENABLE_LPC + DHDCFLAGS += -DWLAIBSS + DHDCFLAGS += -DSUPPORT_LTECX + DHDCFLAGS += -DSUPPORT_2G_VHT + DHDCFLAGS += -DSUPPORT_WL_TXPOWER + DHDCFLAGS += -DBCMCCX_S69 +ifeq ($(CONFIG_BCM43454),y) + DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD + DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC + DRIVER_TYPE = y +endif + DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif ifneq ($(CONFIG_BCM4335),) @@ -914,54 +921,11 @@ ifeq ($(CONFIG_BCM4335),y) endif endif -ifneq ($(CONFIG_BCM4334),) - DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - -ifneq ($(CONFIG_BCM4334W),) - DHDCFLAGS += -DBCM4334W_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334W),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DBCM43430_CHIP -DSUPPORT_MULTIPLE_REVISION -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DCUSTOM_ASSOC_RETRY_MAX=7 - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP # tput enhancement DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 DHDCFLAGS += -DRXFRAME_THREAD -DRXTHREAD_ONLYSTA @@ -975,23 +939,14 @@ ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DOKC_SUPPORT DHDCFLAGS += -DWLFBT DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE - DHDCFLAGS += -DDHD_LOG_DUMP - DHDCFLAGS += -DDHD_UNSUPPORT_IF_CNTS ifeq ($(CONFIG_BCM4343),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif - # FCC power limit control on ch12/13. - DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 # Remove common feature for BCM4343 + DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSUPPORT_P2P_GO_PS,$(DHDCFLAGS)) # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif @@ -1034,45 +989,8 @@ endif DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) endif - -ifneq ($(CONFIG_BCM4330),) - DHDCFLAGS += -DBCM4330_CHIP -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 - DHDCFLAGS += -DWL_CFG80211_GON_COLLISION -ifeq ($(CONFIG_BCM4330),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif - # Remove common feature for BCM4330 - DHDCFLAGS :=$(filter-out -DSUPPORT_AMPDU_MPDU_CMD,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DVSDB,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DPROP_TXSTATUS,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DLIMIT_BORROW,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDHD_USE_IDLECOUNT,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) -endif - -ifneq ($(CONFIG_BCM43241),) - DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMIMO_ANT_SETTING - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 - DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR - DHDCFLAGS += -DAMPDU_HOSTREORDER -ifeq ($(CONFIG_BCM43241),m) - DHDCFLAGS += -fno-pic -endif -ifeq ($(CONFIG_BCM43241),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif endif # chipset supported SDIO only - ############################# # Platform dependent feature ############################# @@ -1106,6 +1024,9 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) endif # Compiler option for specific platform +ifeq ($(CONFIG_SOC_EXYNOS8890),y) + DHDCFLAGS += -Wno-date-time +endif ifeq ($(CONFIG_SOC_EXYNOS7570),y) DHDCFLAGS += -Wno-date-time endif @@ -1121,6 +1042,12 @@ endif ifeq ($(CONFIG_ARCH_MSM8998),y) DHDCFLAGS += -Wno-date-time endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS += -Wno-date-time +endif +ifeq ($(CONFIG_ARCH_SDM845),y) + DHDCFLAGS += -Wno-date-time +endif # DTS Support ifeq ($(CONFIG_OF),y) @@ -1136,16 +1063,17 @@ ifneq ($(CONFIG_SOC_EXYNOS8890),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifneq ($(CONFIG_SOC_EXYNOS8895),) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_EXSOM7420),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8890),) -DHDCFLAGS += -DDHD_OF_SUPPORT -endif -ifneq ($(CONFIG_SOC_EXYNOS8895),) +ifneq ($(CONFIG_SOC_EXYNOS9810),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif @@ -1166,6 +1094,10 @@ ifneq ($(CONFIG_ARCH_MSM8998),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifeq ($(CONFIG_ARCH_SDM845),y) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_UNIVERSAL3475),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1176,10 +1108,6 @@ ifneq ($(CONFIG_SOC_EXYNOS7870),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -Wno-date-time endif -ifneq ($(CONFIG_SOC_EXYNOS7885),) -DHDCFLAGS += -DDHD_OF_SUPPORT -DHDCFLAGS += -Wno-date-time -endif ifneq ($(CONFIG_SOC_EXYNOS7570),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1188,15 +1116,6 @@ DHDCFLAGS += -DDHD_OF_SUPPORT endif endif #CONFIG_OF -# DEBUG UART -ifneq ($(CONFIG_WLAN_GRACE),) -DHDCFLAGS += -DDHD_DEBUG_UART -endif - -#ifneq ($(CONFIG_SOC_EXYNOS8895),) -#DHDCFLAGS += -DDHD_DEBUG_UART -#endif - ifneq ($(CONFIG_ARCH_TEGRA),) DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS := $(filter-out -DDHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL,$(DHDCFLAGS)) @@ -1224,15 +1143,15 @@ EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ EXTRA_CFLAGS += $(call cc-option, -Wunused-but-set-variable) EXTRA_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) -KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) +KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(CURDIR) DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o dhd_custom_sec.o \ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \ - bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \ + bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o linux_pkt.o sbutils.o siutils.o \ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o \ wl_linux_mon.o wl_roam.o dhd_linux_platdev.o dhd_linux_wq.o wl_cfg_btcoex.o \ - hnd_pktq.o hnd_pktpool.o dhd_debug.o dhd_debug_linux.o dhd_custom_cis.o dhd_mschdbg.o \ - dhd_pktlog.o + hnd_pktq.o hnd_pktpool.o dhd_custom_cis.o dhd_debug.o dhd_debug_linux.o dhd_mschdbg.o \ + dhd_dbg_ring.o ifeq ($(BUS_IFACE_SDIO),y) DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o @@ -1254,15 +1173,21 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDOFILES += wl_cfgnan.o bcmxtlv.o +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDOFILES += wl_cfgnan.o bcmxtlv.o bcmbloom.o +#endif // endif + +ifneq ($(filter -DDHD_PKT_LOGGING,$(DHDCFLAGS)),) +DHDOFILES += dhd_pktlog.o +endif + +ifneq ($(filter -DDHD_EVENT_LOG_FILTER, $(DHDCFLAGS)),) +DHDOFILES += dhd_event_log_filter.o endif -ifneq ($(filter -DSTAT_REPORT,$(DHDCFLAGS)),) -DHDOFILES += wl_statreport.o +ifneq ($(filter -DBIGDATA_SOFTAP,$(DHDCFLAGS)),) +DHDOFILES += wl_bigdata.o endif dhd-y := $(DHDOFILES) diff --git a/drivers/net/wireless/bcmdhd_oo/Makefile.jb b/drivers/net/wireless/bcmdhd_oo/Makefile.jb index dea2e5a7c4dd8e97731aa29ad9cb313ff3075592..535d4df6edb33a50a083897c38c4c37288608934 100644 --- a/drivers/net/wireless/bcmdhd_oo/Makefile.jb +++ b/drivers/net/wireless/bcmdhd_oo/Makefile.jb @@ -1,12 +1,12 @@ # -# Copyright (C) 1999-2017, Broadcom Corporation -# +# Copyright (C) 1999-2017, Broadcom. +# # 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 @@ -14,7 +14,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. @@ -104,16 +104,14 @@ endif DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # HEAP ASLR DHDCFLAGS += -DBCM_ASLR_HEAP - ifneq ($(CONFIG_SOC_EXYNOS8895),) # Default Tx LB Enable DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB endif - + # Extended trap data + DHDCFLAGS += -DEXT_TRAP endif - - ################# # Common feature ################# @@ -170,6 +168,7 @@ DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND DHDCFLAGS += -DDHD_LOSSLESS_ROAMING +DHDCFLAGS += -DSKIP_ROAM_TRIGGER_RESET # Enable Roam time thresh DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND @@ -248,7 +247,7 @@ DHDCFLAGS += -DPKTPRIO_OVERRIDE # Prevent rx thread monopolize DHDCFLAGS += -DWAIT_DEQUEUE -# Control PM related value for MFG process(Read from file) +# Control PM related value for MFG process(Read from file) DHDCFLAGS += -DDHD_PM_CONTROL_FROM_FILE # Use Android wake lock mechanism @@ -261,12 +260,10 @@ DHDCFLAGS += -DUSE_INITIAL_SHORT_DWELL_TIME DHDCFLAGS += -DKEEP_JP_REGREV # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDCFLAGS += -DWL_NAN -endif +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDCFLAGS += -DWL_NAN -DWL_NAN_DISC_CACHE +#endif // endif # FCC power limit control on ch12/13. DHDCFLAGS += -DFCC_PWR_LIMIT_2G @@ -292,14 +289,9 @@ DHDCFLAGS += -DSUPPORT_RANDOM_MAC_SCAN # WLC_E_SET_SSID fail DHDCFLAGS += -DSET_SSID_FAIL_CUSTOM_RC=100 -# Enable to block Band A(5G), Only support Band B(2G) -ifeq ($(CONFIG_WLAN_5GDISABLE),y) -DHDCFLAGS += -DDHD_2G_ONLY_SUPPORT -endif -# Disable VHT(5G HT80) mode -ifeq ($(CONFIG_WLAN_VHTDISABLE),y) -DHDCFLAGS += -DDHD_DISABLE_VHTMODE -endif +# Use legacy random mac +# Disable the legacy randmac and enable scanmac +#DHDCFLAGS += -DLEGACY_RANDOM_MAC # Android Version Check from Platform source ifneq ($(PLATFORM_VERSION),) @@ -311,7 +303,6 @@ endif # Android Platform Definition ############################## - ############ # JellyBean ############ @@ -319,8 +310,6 @@ DHDCFLAGS += -DWL_ENABLE_P2P_IF DHDCFLAGS += -DMULTIPLE_SUPPLICANT DHDCFLAGS += -DWL_CFG80211_STA_EVENT - - ########################## # driver type # m: module type driver @@ -346,12 +335,14 @@ ifneq ($(CONFIG_BCM4361),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT +# Debugability + DHDCFLAGS += -DDEBUGABILITY_ECNTRS_LOGGING # Customer ant select and set PM DHDCFLAGS += -DCUSTOM_SET_ANTNPM DHDCFLAGS += -DCUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE # Customer ocl disabe DHDCFLAGS += -DCUSTOM_SET_OCLOFF + # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 @@ -359,10 +350,19 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DDHDTCPACK_SUPPRESS endif +ifeq ($(CONFIG_ARCH_QCOM),y) + DHDCFLAGS += -DCONFIG_ARCH_MSM + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -388,77 +388,68 @@ endif # Remove common feature for BCM4361 DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) DHDCFLAGS += -DDHD_LOG_DUMP -# Higher rate beacon transmission at softAP - DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE -# Enhanced radio power save with NOA at softAP - DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE +ifneq ($(CUSTOM_LOG_DUMP_BUFSIZE_MB),) + DHDCFLAGS += -DCUSTOM_LOG_DUMP_BUFSIZE_MB=$(CUSTOM_LOG_DUMP_BUFSIZE_MB) +endif + + DHDCFLAGS += -DWL_SUPP_EVENT + DHDCFLAGS += -DFILTER_IE + DHDCFLAGS += -DNDO_CONFIG_SUPPORT # WBTEXT (11kv) feature DHDCFLAGS += -DWBTEXT # LOGTRACE_EVENT DHDCFLAGS += -DSHOW_LOGTRACE DHDCFLAGS += -DLOGTRACE_FROM_FILE -ifeq ($(CONFIG_ARCH_MSM8998),y) -# Use SMMU for IOMEM - DHDCFLAGS += -DUSE_SMMU_ARCH_MSM - DHDCFLAGS += -DSET_DMA_MASK_64BIT -endif +# LAST ROAM EVENT LOG + DHDCFLAGS += -DWL_LASTEVT +# Higher rate beacon transmission at softAP + DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE +# Enhanced radio power save with NOA at softAP + DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE # Expand TCP tx queue to 10 times of default size DHDCFLAGS += -DTSQ_MULTIPLIER=10 # HANG simulation DHDCFLAGS += -DDHD_HANG_SEND_UP_TEST +# Support Monitor Mode + DHDCFLAGS += -DWL_MONITOR +# Enable health check event handling + DHDCFLAGS += -DDNGL_EVENT_SUPPORT + DHDCFLAGS += -DHCHK_COMMON_SW_EVENT +# Generate .softap.info + DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE +# Use SMMU for IOMEM +ifeq ($(filter y,$(CONFIG_ARCH_MSM8998) $(CONFIG_ARCH_SDM845)),y) + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM +endif + ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 +endif +ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) # Enable LQCM DHDCFLAGS += -DSUPPORT_LQCM endif -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895)), y) -# DHD_LB_IRQSET - CPU migration by IRQ Affinity Set - DHDCFLAGS += -DDHD_LB_IRQSET -endif -# Generate .softap.info - DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE -ifneq ($(PLATFORM_VERSION),) -# DREAM Android N OS should not use below features -ifeq ($(shell expr $(PLATFORM_VERSION) \< 8.0),1) -ifneq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT)),y) - DREAM_NOS_DISCARD_FEATURES := y -endif -endif - -# Feature Set used for GREAT N OS and Android O OS -ifneq ($(DREAM_NOS_DISCARD_FEATURES),y) +ifeq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Debugaility - DHDCFLAGS += -DDEBUGABILITY + DHDCFLAGS += -DDHD_EVENT_LOG_FILTER DHDCFLAGS += -DDHD_PKT_LOGGING # Debug Wakeup pkt reason DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS -DDHD_WAKE_EVENT_STATUS DHDCFLAGS += -DDHD_WAKEPKT_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC -# LAST ROAM EVENT LOG - DHDCFLAGS += -DWL_LASTEVT # Use single nvram file DHDCFLAGS += -DDHD_USE_SINGLE_NVRAM_FILE -#STAT REPORT -#stat report shall be defined only if LINK STAT is defined - DHDCFLAGS += -DSTAT_REPORT -#define temp static only when SDK doesn't support static memory for STAT REPORT -# DHDCFLAGS += -DSTAT_REPORT_TEMP_STATIC -endif - -# RSSI_SUM_REPORT is used over Android O OS only -ifeq ($(shell expr $(PLATFORM_VERSION) \>= 8.0),1) # RSSI Logging DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT -# Enable NDO_CONFIG_SUPPORT in HAL - DHDCFLAGS += -DNDO_CONFIG_SUPPORT -# changed assoc timeout - DHDCFLAGS += -DCUSTOM_ASSOC_TIMEOUT=20 -endif +# To send hang evnet for Samsung phone platform + DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT +# Enable BIGDATA_SOFTAP + DHDCFLAGS += -DBIGDATA_SOFTAP endif # Use Legacy dump path @@ -468,18 +459,12 @@ else DHDCFLAGS += -DDHD_COMMON_DUMP_PATH="\"/data/log/wifi/\"" endif -# For Samsung factory mode only -ifeq ($(CONFIG_SEC_FACTORY),y) -# Detect NON DMA M2M corruption - DHDCFLAGS += -DDHD_NON_DMA_M2M_CORRUPTION -# Detect FW Memory Corruption - DHDCFLAGS += -DDHD_FW_MEM_CORRUPTION -endif # CONFIG_SEC_FACTORY - ifeq ($(CONFIG_BCM4361),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y +else + DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH endif endif @@ -495,7 +480,6 @@ ifneq ($(CONFIG_BCM4359),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) @@ -506,11 +490,14 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 DHDCFLAGS += -DDHDTCPACK_SUPPRESS +ifeq ($(CONFIG_ARCH_MSM8998),y) +# Use SMMU for IOMEM + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM endif - ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +endif # New Features DHDCFLAGS += -DWL11U -DMFP @@ -541,14 +528,14 @@ endif DHDCFLAGS += -DDHD_LOG_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC + ifneq ($(CONFIG_WLAN_GRACE),) DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DDHD_DEBUG_UART endif ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_SOC_EXYNOS8890)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 - # Enable Dongle Isolation - DHDCFLAGS += -DDONGLE_ENABLE_ISOLATION # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) endif @@ -557,6 +544,8 @@ ifeq ($(CONFIG_BCM4359),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y +else + DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH endif endif @@ -672,7 +661,6 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_AMPDU_RELEASE=16 endif - # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -744,21 +732,8 @@ endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif -ifneq ($(CONFIG_BCM43456),) - DHDCFLAGS += -DBCM43456_CHIP - DHDCFLAGS += -DWLADPS_PRIVATE_CMD -endif ifneq ($(CONFIG_BCM43455),) - DHDCFLAGS += -DBCM43455_CHIP -endif -ifneq ($(CONFIG_BCM43454),) - DHDCFLAGS += -DBCM43454_CHIP -endif - -# BCM43454/43455/43456 common difine. -ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456))) - DHDCFLAGS += -DHW_OOB - DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DBCM43455_CHIP -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR @@ -775,9 +750,10 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 # New Features - DHDCFLAGS += -DWL11U -DMFP + DHDCFLAGS += -DWL11U DHDCFLAGS += -DBCMCCX DHDCFLAGS += -DWES_SUPPORT DHDCFLAGS += -DOKC_SUPPORT @@ -789,35 +765,59 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DSUPPORT_2G_VHT DHDCFLAGS += -DSUPPORT_WL_TXPOWER DHDCFLAGS += -DBCMCCX_S69 -ifeq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),y) +ifeq ($(CONFIG_BCM43455),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 - DHDCFLAGS += -DDHD_LOG_DUMP - - # FCC power limit control on ch12/13. - # DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 - -ifneq ($(filter y,$(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43455) $(CONFIG_BCM43456))) -# Enable Firmware Coredump - DHDCFLAGS += -DDHD_FW_COREDUMP -ifeq ($(CONFIG_BCMDHD_PREALLOC_MEMDUMP),y) - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -endif # Enable concate blob path DHDCFLAGS += -DCONCATE_BLOB # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif + +ifneq ($(CONFIG_BCM43454),) + DHDCFLAGS += -DBCM43454_CHIP -DHW_OOB + DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION -DSUPPORT_MULTIPLE_BOARD_REV_FROM_DT + DHDCFLAGS += -DUSE_CID_CHECK + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR + + # tput enhancement + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DCUSTOM_FRAMEBURST_SET=1 + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 + + # New Features + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DDHD_ENABLE_LPC + DHDCFLAGS += -DWLAIBSS + DHDCFLAGS += -DSUPPORT_LTECX + DHDCFLAGS += -DSUPPORT_2G_VHT + DHDCFLAGS += -DSUPPORT_WL_TXPOWER + DHDCFLAGS += -DBCMCCX_S69 +ifeq ($(CONFIG_BCM43454),y) + DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD + DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC + DRIVER_TYPE = y +endif + DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif ifneq ($(CONFIG_BCM4335),) @@ -874,54 +874,11 @@ ifeq ($(CONFIG_BCM4335),y) endif endif -ifneq ($(CONFIG_BCM4334),) - DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - -ifneq ($(CONFIG_BCM4334W),) - DHDCFLAGS += -DBCM4334W_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334W),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DBCM43430_CHIP -DSUPPORT_MULTIPLE_REVISION -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DCUSTOM_ASSOC_RETRY_MAX=7 - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP # tput enhancement DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 DHDCFLAGS += -DRXFRAME_THREAD -DRXTHREAD_ONLYSTA @@ -935,23 +892,14 @@ ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DOKC_SUPPORT DHDCFLAGS += -DWLFBT DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE - DHDCFLAGS += -DDHD_LOG_DUMP - DHDCFLAGS += -DDHD_UNSUPPORT_IF_CNTS ifeq ($(CONFIG_BCM4343),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif - # FCC power limit control on ch12/13. - DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 # Remove common feature for BCM4343 + DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSUPPORT_P2P_GO_PS,$(DHDCFLAGS)) # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif @@ -994,45 +942,8 @@ endif DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) endif - -ifneq ($(CONFIG_BCM4330),) - DHDCFLAGS += -DBCM4330_CHIP -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 - DHDCFLAGS += -DWL_CFG80211_GON_COLLISION -ifeq ($(CONFIG_BCM4330),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif - # Remove common feature for BCM4330 - DHDCFLAGS :=$(filter-out -DSUPPORT_AMPDU_MPDU_CMD,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DVSDB,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DPROP_TXSTATUS,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DLIMIT_BORROW,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDHD_USE_IDLECOUNT,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) -endif - -ifneq ($(CONFIG_BCM43241),) - DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMIMO_ANT_SETTING - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 - DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR - DHDCFLAGS += -DAMPDU_HOSTREORDER -ifeq ($(CONFIG_BCM43241),m) - DHDCFLAGS += -fno-pic -endif -ifeq ($(CONFIG_BCM43241),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif endif # chipset supported SDIO only - ############################# # Platform dependent feature ############################# @@ -1066,6 +977,9 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) endif # Compiler option for specific platform +ifeq ($(CONFIG_SOC_EXYNOS8890),y) + DHDCFLAGS += -Wno-date-time +endif ifeq ($(CONFIG_SOC_EXYNOS7570),y) DHDCFLAGS += -Wno-date-time endif @@ -1081,6 +995,12 @@ endif ifeq ($(CONFIG_ARCH_MSM8998),y) DHDCFLAGS += -Wno-date-time endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS += -Wno-date-time +endif +ifeq ($(CONFIG_ARCH_SDM845),y) + DHDCFLAGS += -Wno-date-time +endif # DTS Support ifeq ($(CONFIG_OF),y) @@ -1096,16 +1016,16 @@ ifneq ($(CONFIG_SOC_EXYNOS8890),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif -ifneq ($(CONFIG_MACH_EXSOM7420),) +ifneq ($(CONFIG_SOC_EXYNOS8895),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE -DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH -obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8890),) +ifneq ($(CONFIG_MACH_EXSOM7420),) DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8895),) +ifneq ($(CONFIG_SOC_EXYNOS9810),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif @@ -1126,6 +1046,10 @@ ifneq ($(CONFIG_ARCH_MSM8998),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifeq ($(CONFIG_ARCH_SDM845),y) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_UNIVERSAL3475),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1136,10 +1060,6 @@ ifneq ($(CONFIG_SOC_EXYNOS7870),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -Wno-date-time endif -ifneq ($(CONFIG_SOC_EXYNOS7885),) -DHDCFLAGS += -DDHD_OF_SUPPORT -DHDCFLAGS += -Wno-date-time -endif ifneq ($(CONFIG_SOC_EXYNOS7570),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1148,15 +1068,6 @@ DHDCFLAGS += -DDHD_OF_SUPPORT endif endif #CONFIG_OF -# DEBUG UART -ifneq ($(CONFIG_WLAN_GRACE),) -DHDCFLAGS += -DDHD_DEBUG_UART -endif - -#ifneq ($(CONFIG_SOC_EXYNOS8895),) -#DHDCFLAGS += -DDHD_DEBUG_UART -#endif - ifneq ($(CONFIG_ARCH_TEGRA),) DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS := $(filter-out -DDHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL,$(DHDCFLAGS)) @@ -1183,15 +1094,15 @@ EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ EXTRA_CFLAGS += $(call cc-option, -Wunused-but-set-variable) EXTRA_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) -KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) +KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(CURDIR) DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o dhd_custom_sec.o \ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \ - bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \ + bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o linux_pkt.o sbutils.o siutils.o \ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o \ wl_linux_mon.o wl_roam.o dhd_linux_platdev.o dhd_linux_wq.o wl_cfg_btcoex.o \ - hnd_pktq.o hnd_pktpool.o dhd_debug.o dhd_debug_linux.o dhd_custom_cis.o dhd_mschdbg.o \ - dhd_pktlog.o + hnd_pktq.o hnd_pktpool.o dhd_custom_cis.o dhd_debug.o dhd_debug_linux.o dhd_mschdbg.o \ + dhd_dbg_ring.o ifeq ($(BUS_IFACE_SDIO),y) DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o @@ -1213,15 +1124,21 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDOFILES += wl_cfgnan.o bcmxtlv.o +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDOFILES += wl_cfgnan.o bcmxtlv.o bcmbloom.o +#endif // endif + +ifneq ($(filter -DDHD_PKT_LOGGING,$(DHDCFLAGS)),) +DHDOFILES += dhd_pktlog.o +endif + +ifneq ($(filter -DDHD_EVENT_LOG_FILTER, $(DHDCFLAGS)),) +DHDOFILES += dhd_event_log_filter.o endif -ifneq ($(filter -DSTAT_REPORT,$(DHDCFLAGS)),) -DHDOFILES += wl_statreport.o +ifneq ($(filter -DBIGDATA_SOFTAP,$(DHDCFLAGS)),) +DHDOFILES += wl_bigdata.o endif dhd-y := $(DHDOFILES) diff --git a/drivers/net/wireless/bcmdhd_oo/Makefile.jbp b/drivers/net/wireless/bcmdhd_oo/Makefile.jbp index 57be90ff666abb256797721611f0cfdb2d0f0357..4fd97b42bab631be4b53a1dd42cb95bb557f2095 100644 --- a/drivers/net/wireless/bcmdhd_oo/Makefile.jbp +++ b/drivers/net/wireless/bcmdhd_oo/Makefile.jbp @@ -1,12 +1,12 @@ # -# Copyright (C) 1999-2017, Broadcom Corporation -# +# Copyright (C) 1999-2017, Broadcom. +# # 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 @@ -14,7 +14,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. @@ -104,16 +104,14 @@ endif DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # HEAP ASLR DHDCFLAGS += -DBCM_ASLR_HEAP - ifneq ($(CONFIG_SOC_EXYNOS8895),) # Default Tx LB Enable DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB endif - + # Extended trap data + DHDCFLAGS += -DEXT_TRAP endif - - ################# # Common feature ################# @@ -170,6 +168,7 @@ DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND DHDCFLAGS += -DDHD_LOSSLESS_ROAMING +DHDCFLAGS += -DSKIP_ROAM_TRIGGER_RESET # Enable Roam time thresh DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND @@ -248,7 +247,7 @@ DHDCFLAGS += -DPKTPRIO_OVERRIDE # Prevent rx thread monopolize DHDCFLAGS += -DWAIT_DEQUEUE -# Control PM related value for MFG process(Read from file) +# Control PM related value for MFG process(Read from file) DHDCFLAGS += -DDHD_PM_CONTROL_FROM_FILE # Use Android wake lock mechanism @@ -261,12 +260,10 @@ DHDCFLAGS += -DUSE_INITIAL_SHORT_DWELL_TIME DHDCFLAGS += -DKEEP_JP_REGREV # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDCFLAGS += -DWL_NAN -endif +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDCFLAGS += -DWL_NAN -DWL_NAN_DISC_CACHE +#endif // endif # FCC power limit control on ch12/13. DHDCFLAGS += -DFCC_PWR_LIMIT_2G @@ -292,14 +289,9 @@ DHDCFLAGS += -DSUPPORT_RANDOM_MAC_SCAN # WLC_E_SET_SSID fail DHDCFLAGS += -DSET_SSID_FAIL_CUSTOM_RC=100 -# Enable to block Band A(5G), Only support Band B(2G) -ifeq ($(CONFIG_WLAN_5GDISABLE),y) -DHDCFLAGS += -DDHD_2G_ONLY_SUPPORT -endif -# Disable VHT(5G HT80) mode -ifeq ($(CONFIG_WLAN_VHTDISABLE),y) -DHDCFLAGS += -DDHD_DISABLE_VHTMODE -endif +# Use legacy random mac +# Disable the legacy randmac and enable scanmac +#DHDCFLAGS += -DLEGACY_RANDOM_MAC # Android Version Check from Platform source ifneq ($(PLATFORM_VERSION),) @@ -311,7 +303,6 @@ endif # Android Platform Definition ############################## - ############ # JellyBean ############ @@ -324,8 +315,6 @@ DHDCFLAGS += -DWL_CFG80211_STA_EVENT ################# DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES - - ########################## # driver type # m: module type driver @@ -351,12 +340,14 @@ ifneq ($(CONFIG_BCM4361),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT +# Debugability + DHDCFLAGS += -DDEBUGABILITY_ECNTRS_LOGGING # Customer ant select and set PM DHDCFLAGS += -DCUSTOM_SET_ANTNPM DHDCFLAGS += -DCUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE # Customer ocl disabe DHDCFLAGS += -DCUSTOM_SET_OCLOFF + # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 @@ -364,10 +355,19 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DDHDTCPACK_SUPPRESS endif +ifeq ($(CONFIG_ARCH_QCOM),y) + DHDCFLAGS += -DCONFIG_ARCH_MSM + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -393,77 +393,68 @@ endif # Remove common feature for BCM4361 DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) DHDCFLAGS += -DDHD_LOG_DUMP -# Higher rate beacon transmission at softAP - DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE -# Enhanced radio power save with NOA at softAP - DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE +ifneq ($(CUSTOM_LOG_DUMP_BUFSIZE_MB),) + DHDCFLAGS += -DCUSTOM_LOG_DUMP_BUFSIZE_MB=$(CUSTOM_LOG_DUMP_BUFSIZE_MB) +endif + + DHDCFLAGS += -DWL_SUPP_EVENT + DHDCFLAGS += -DFILTER_IE + DHDCFLAGS += -DNDO_CONFIG_SUPPORT # WBTEXT (11kv) feature DHDCFLAGS += -DWBTEXT # LOGTRACE_EVENT DHDCFLAGS += -DSHOW_LOGTRACE DHDCFLAGS += -DLOGTRACE_FROM_FILE -ifeq ($(CONFIG_ARCH_MSM8998),y) -# Use SMMU for IOMEM - DHDCFLAGS += -DUSE_SMMU_ARCH_MSM - DHDCFLAGS += -DSET_DMA_MASK_64BIT -endif +# LAST ROAM EVENT LOG + DHDCFLAGS += -DWL_LASTEVT +# Higher rate beacon transmission at softAP + DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE +# Enhanced radio power save with NOA at softAP + DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE # Expand TCP tx queue to 10 times of default size DHDCFLAGS += -DTSQ_MULTIPLIER=10 # HANG simulation DHDCFLAGS += -DDHD_HANG_SEND_UP_TEST +# Support Monitor Mode + DHDCFLAGS += -DWL_MONITOR +# Enable health check event handling + DHDCFLAGS += -DDNGL_EVENT_SUPPORT + DHDCFLAGS += -DHCHK_COMMON_SW_EVENT +# Generate .softap.info + DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE +# Use SMMU for IOMEM +ifeq ($(filter y,$(CONFIG_ARCH_MSM8998) $(CONFIG_ARCH_SDM845)),y) + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM +endif + ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 +endif +ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) # Enable LQCM DHDCFLAGS += -DSUPPORT_LQCM endif -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895)), y) -# DHD_LB_IRQSET - CPU migration by IRQ Affinity Set - DHDCFLAGS += -DDHD_LB_IRQSET -endif -# Generate .softap.info - DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE -ifneq ($(PLATFORM_VERSION),) -# DREAM Android N OS should not use below features -ifeq ($(shell expr $(PLATFORM_VERSION) \< 8.0),1) -ifneq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT)),y) - DREAM_NOS_DISCARD_FEATURES := y -endif -endif - -# Feature Set used for GREAT N OS and Android O OS -ifneq ($(DREAM_NOS_DISCARD_FEATURES),y) +ifeq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Debugaility - DHDCFLAGS += -DDEBUGABILITY + DHDCFLAGS += -DDHD_EVENT_LOG_FILTER DHDCFLAGS += -DDHD_PKT_LOGGING # Debug Wakeup pkt reason DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS -DDHD_WAKE_EVENT_STATUS DHDCFLAGS += -DDHD_WAKEPKT_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC -# LAST ROAM EVENT LOG - DHDCFLAGS += -DWL_LASTEVT # Use single nvram file DHDCFLAGS += -DDHD_USE_SINGLE_NVRAM_FILE -#STAT REPORT -#stat report shall be defined only if LINK STAT is defined - DHDCFLAGS += -DSTAT_REPORT -#define temp static only when SDK doesn't support static memory for STAT REPORT -# DHDCFLAGS += -DSTAT_REPORT_TEMP_STATIC -endif - -# RSSI_SUM_REPORT is used over Android O OS only -ifeq ($(shell expr $(PLATFORM_VERSION) \>= 8.0),1) # RSSI Logging DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT -# Enable NDO_CONFIG_SUPPORT in HAL - DHDCFLAGS += -DNDO_CONFIG_SUPPORT -# changed assoc timeout - DHDCFLAGS += -DCUSTOM_ASSOC_TIMEOUT=20 -endif +# To send hang evnet for Samsung phone platform + DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT +# Enable BIGDATA_SOFTAP + DHDCFLAGS += -DBIGDATA_SOFTAP endif # Use Legacy dump path @@ -473,18 +464,12 @@ else DHDCFLAGS += -DDHD_COMMON_DUMP_PATH="\"/data/log/wifi/\"" endif -# For Samsung factory mode only -ifeq ($(CONFIG_SEC_FACTORY),y) -# Detect NON DMA M2M corruption - DHDCFLAGS += -DDHD_NON_DMA_M2M_CORRUPTION -# Detect FW Memory Corruption - DHDCFLAGS += -DDHD_FW_MEM_CORRUPTION -endif # CONFIG_SEC_FACTORY - ifeq ($(CONFIG_BCM4361),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y +else + DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH endif endif @@ -500,7 +485,6 @@ ifneq ($(CONFIG_BCM4359),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) @@ -511,11 +495,14 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 DHDCFLAGS += -DDHDTCPACK_SUPPRESS +ifeq ($(CONFIG_ARCH_MSM8998),y) +# Use SMMU for IOMEM + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM endif - ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +endif # New Features DHDCFLAGS += -DWL11U -DMFP @@ -546,14 +533,14 @@ endif DHDCFLAGS += -DDHD_LOG_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC + ifneq ($(CONFIG_WLAN_GRACE),) DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DDHD_DEBUG_UART endif ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_SOC_EXYNOS8890)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 - # Enable Dongle Isolation - DHDCFLAGS += -DDONGLE_ENABLE_ISOLATION # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) endif @@ -562,6 +549,8 @@ ifeq ($(CONFIG_BCM4359),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y +else + DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH endif endif @@ -677,7 +666,6 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_AMPDU_RELEASE=16 endif - # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -749,21 +737,8 @@ endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif -ifneq ($(CONFIG_BCM43456),) - DHDCFLAGS += -DBCM43456_CHIP - DHDCFLAGS += -DWLADPS_PRIVATE_CMD -endif ifneq ($(CONFIG_BCM43455),) - DHDCFLAGS += -DBCM43455_CHIP -endif -ifneq ($(CONFIG_BCM43454),) - DHDCFLAGS += -DBCM43454_CHIP -endif - -# BCM43454/43455/43456 common difine. -ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456))) - DHDCFLAGS += -DHW_OOB - DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DBCM43455_CHIP -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR @@ -780,9 +755,10 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 # New Features - DHDCFLAGS += -DWL11U -DMFP + DHDCFLAGS += -DWL11U DHDCFLAGS += -DBCMCCX DHDCFLAGS += -DWES_SUPPORT DHDCFLAGS += -DOKC_SUPPORT @@ -794,35 +770,59 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DSUPPORT_2G_VHT DHDCFLAGS += -DSUPPORT_WL_TXPOWER DHDCFLAGS += -DBCMCCX_S69 -ifeq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),y) +ifeq ($(CONFIG_BCM43455),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 - DHDCFLAGS += -DDHD_LOG_DUMP - - # FCC power limit control on ch12/13. - # DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 - -ifneq ($(filter y,$(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43455) $(CONFIG_BCM43456))) -# Enable Firmware Coredump - DHDCFLAGS += -DDHD_FW_COREDUMP -ifeq ($(CONFIG_BCMDHD_PREALLOC_MEMDUMP),y) - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -endif # Enable concate blob path DHDCFLAGS += -DCONCATE_BLOB # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif + +ifneq ($(CONFIG_BCM43454),) + DHDCFLAGS += -DBCM43454_CHIP -DHW_OOB + DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION -DSUPPORT_MULTIPLE_BOARD_REV_FROM_DT + DHDCFLAGS += -DUSE_CID_CHECK + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR + + # tput enhancement + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DCUSTOM_FRAMEBURST_SET=1 + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 + + # New Features + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DDHD_ENABLE_LPC + DHDCFLAGS += -DWLAIBSS + DHDCFLAGS += -DSUPPORT_LTECX + DHDCFLAGS += -DSUPPORT_2G_VHT + DHDCFLAGS += -DSUPPORT_WL_TXPOWER + DHDCFLAGS += -DBCMCCX_S69 +ifeq ($(CONFIG_BCM43454),y) + DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD + DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC + DRIVER_TYPE = y +endif + DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif ifneq ($(CONFIG_BCM4335),) @@ -879,54 +879,11 @@ ifeq ($(CONFIG_BCM4335),y) endif endif -ifneq ($(CONFIG_BCM4334),) - DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - -ifneq ($(CONFIG_BCM4334W),) - DHDCFLAGS += -DBCM4334W_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334W),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DBCM43430_CHIP -DSUPPORT_MULTIPLE_REVISION -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DCUSTOM_ASSOC_RETRY_MAX=7 - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP # tput enhancement DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 DHDCFLAGS += -DRXFRAME_THREAD -DRXTHREAD_ONLYSTA @@ -940,23 +897,14 @@ ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DOKC_SUPPORT DHDCFLAGS += -DWLFBT DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE - DHDCFLAGS += -DDHD_LOG_DUMP - DHDCFLAGS += -DDHD_UNSUPPORT_IF_CNTS ifeq ($(CONFIG_BCM4343),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif - # FCC power limit control on ch12/13. - DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 # Remove common feature for BCM4343 + DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSUPPORT_P2P_GO_PS,$(DHDCFLAGS)) # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif @@ -999,45 +947,8 @@ endif DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) endif - -ifneq ($(CONFIG_BCM4330),) - DHDCFLAGS += -DBCM4330_CHIP -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 - DHDCFLAGS += -DWL_CFG80211_GON_COLLISION -ifeq ($(CONFIG_BCM4330),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif - # Remove common feature for BCM4330 - DHDCFLAGS :=$(filter-out -DSUPPORT_AMPDU_MPDU_CMD,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DVSDB,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DPROP_TXSTATUS,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DLIMIT_BORROW,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDHD_USE_IDLECOUNT,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) -endif - -ifneq ($(CONFIG_BCM43241),) - DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMIMO_ANT_SETTING - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 - DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR - DHDCFLAGS += -DAMPDU_HOSTREORDER -ifeq ($(CONFIG_BCM43241),m) - DHDCFLAGS += -fno-pic -endif -ifeq ($(CONFIG_BCM43241),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif endif # chipset supported SDIO only - ############################# # Platform dependent feature ############################# @@ -1071,6 +982,9 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) endif # Compiler option for specific platform +ifeq ($(CONFIG_SOC_EXYNOS8890),y) + DHDCFLAGS += -Wno-date-time +endif ifeq ($(CONFIG_SOC_EXYNOS7570),y) DHDCFLAGS += -Wno-date-time endif @@ -1086,6 +1000,12 @@ endif ifeq ($(CONFIG_ARCH_MSM8998),y) DHDCFLAGS += -Wno-date-time endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS += -Wno-date-time +endif +ifeq ($(CONFIG_ARCH_SDM845),y) + DHDCFLAGS += -Wno-date-time +endif # DTS Support ifeq ($(CONFIG_OF),y) @@ -1101,16 +1021,16 @@ ifneq ($(CONFIG_SOC_EXYNOS8890),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif -ifneq ($(CONFIG_MACH_EXSOM7420),) +ifneq ($(CONFIG_SOC_EXYNOS8895),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE -DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH -obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8890),) +ifneq ($(CONFIG_MACH_EXSOM7420),) DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8895),) +ifneq ($(CONFIG_SOC_EXYNOS9810),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif @@ -1131,6 +1051,10 @@ ifneq ($(CONFIG_ARCH_MSM8998),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifeq ($(CONFIG_ARCH_SDM845),y) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_UNIVERSAL3475),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1141,10 +1065,6 @@ ifneq ($(CONFIG_SOC_EXYNOS7870),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -Wno-date-time endif -ifneq ($(CONFIG_SOC_EXYNOS7885),) -DHDCFLAGS += -DDHD_OF_SUPPORT -DHDCFLAGS += -Wno-date-time -endif ifneq ($(CONFIG_SOC_EXYNOS7570),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1153,15 +1073,6 @@ DHDCFLAGS += -DDHD_OF_SUPPORT endif endif #CONFIG_OF -# DEBUG UART -ifneq ($(CONFIG_WLAN_GRACE),) -DHDCFLAGS += -DDHD_DEBUG_UART -endif - -#ifneq ($(CONFIG_SOC_EXYNOS8895),) -#DHDCFLAGS += -DDHD_DEBUG_UART -#endif - ifneq ($(CONFIG_ARCH_TEGRA),) DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS := $(filter-out -DDHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL,$(DHDCFLAGS)) @@ -1188,15 +1099,15 @@ EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ EXTRA_CFLAGS += $(call cc-option, -Wunused-but-set-variable) EXTRA_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) -KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) +KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(CURDIR) DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o dhd_custom_sec.o \ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \ - bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \ + bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o linux_pkt.o sbutils.o siutils.o \ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o \ wl_linux_mon.o wl_roam.o dhd_linux_platdev.o dhd_linux_wq.o wl_cfg_btcoex.o \ - hnd_pktq.o hnd_pktpool.o dhd_debug.o dhd_debug_linux.o dhd_custom_cis.o dhd_mschdbg.o \ - dhd_pktlog.o + hnd_pktq.o hnd_pktpool.o dhd_custom_cis.o dhd_debug.o dhd_debug_linux.o dhd_mschdbg.o \ + dhd_dbg_ring.o ifeq ($(BUS_IFACE_SDIO),y) DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o @@ -1218,15 +1129,21 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDOFILES += wl_cfgnan.o bcmxtlv.o +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDOFILES += wl_cfgnan.o bcmxtlv.o bcmbloom.o +#endif // endif + +ifneq ($(filter -DDHD_PKT_LOGGING,$(DHDCFLAGS)),) +DHDOFILES += dhd_pktlog.o +endif + +ifneq ($(filter -DDHD_EVENT_LOG_FILTER, $(DHDCFLAGS)),) +DHDOFILES += dhd_event_log_filter.o endif -ifneq ($(filter -DSTAT_REPORT,$(DHDCFLAGS)),) -DHDOFILES += wl_statreport.o +ifneq ($(filter -DBIGDATA_SOFTAP,$(DHDCFLAGS)),) +DHDOFILES += wl_bigdata.o endif dhd-y := $(DHDOFILES) diff --git a/drivers/net/wireless/bcmdhd_oo/Makefile.kk b/drivers/net/wireless/bcmdhd_oo/Makefile.kk index 6a5cac4bda83d4ea2aa24c2a07bd3c7cfc8c546d..279a698290ab51f107f027d40010a10b73a86628 100644 --- a/drivers/net/wireless/bcmdhd_oo/Makefile.kk +++ b/drivers/net/wireless/bcmdhd_oo/Makefile.kk @@ -1,12 +1,12 @@ # -# Copyright (C) 1999-2017, Broadcom Corporation -# +# Copyright (C) 1999-2018, Broadcom. +# # 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 @@ -14,7 +14,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. @@ -101,19 +101,15 @@ endif DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_TXP -DDHD_LB_STATS # Extended HANG event with reason codes DHDCFLAGS += -DDHD_USE_EXTENDED_HANG_REASON - DHDCFLAGS += -DDHD_RECOVER_TIMEOUT + # DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # HEAP ASLR DHDCFLAGS += -DBCM_ASLR_HEAP - ifneq ($(CONFIG_SOC_EXYNOS8895),) # Default Tx LB Enable DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB endif - endif - - ################# # Common feature ################# @@ -170,6 +166,7 @@ DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND DHDCFLAGS += -DDHD_LOSSLESS_ROAMING +DHDCFLAGS += -DSKIP_ROAM_TRIGGER_RESET # Enable Roam time thresh DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND @@ -210,6 +207,8 @@ DHDCFLAGS += -DUNSET_FW_ROAM_WIPHY_FLAG # For special PNO Event keep wake lock for 10sec DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 +# Enable Scheduled scan +DHDCFLAGS += -DWL_SCHED_SCAN # For IPV6 Neighbor Discovery Offload Support DHDCFLAGS += -DIPV6_NDO_SUPPORT @@ -248,7 +247,7 @@ DHDCFLAGS += -DPKTPRIO_OVERRIDE # Prevent rx thread monopolize DHDCFLAGS += -DWAIT_DEQUEUE -# Control PM related value for MFG process(Read from file) +# Control PM related value for MFG process(Read from file) DHDCFLAGS += -DDHD_PM_CONTROL_FROM_FILE # Use Android wake lock mechanism @@ -261,12 +260,10 @@ DHDCFLAGS += -DUSE_INITIAL_SHORT_DWELL_TIME DHDCFLAGS += -DKEEP_JP_REGREV # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDCFLAGS += -DWL_NAN -endif +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDCFLAGS += -DWL_NAN -DWL_NAN_DISC_CACHE +#endif // endif # FCC power limit control on ch12/13. DHDCFLAGS += -DFCC_PWR_LIMIT_2G @@ -277,9 +274,6 @@ DHDCFLAGS += -DUSE_WFA_CERT_CONF # Change the WL_SCAN_TIMER_INTERVAL_MS of DHD DHDCFLAGS += -DCUSTOMER_SCAN_TIMEOUT_SETTING -# Does not forword internal packet -DHDCFLAGS += -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT - # Enable HANG event test private command DHDCFLAGS += -DSUPPORT_TRIGGER_HANG_EVENT @@ -292,14 +286,9 @@ DHDCFLAGS += -DSUPPORT_RANDOM_MAC_SCAN # WLC_E_SET_SSID fail DHDCFLAGS += -DSET_SSID_FAIL_CUSTOM_RC=100 -# Enable to block Band A(5G), Only support Band B(2G) -ifeq ($(CONFIG_WLAN_5GDISABLE),y) -DHDCFLAGS += -DDHD_2G_ONLY_SUPPORT -endif -# Disable VHT(5G HT80) mode -ifeq ($(CONFIG_WLAN_VHTDISABLE),y) -DHDCFLAGS += -DDHD_DISABLE_VHTMODE -endif +# Use legacy random mac +# Disable the legacy randmac and enable scanmac +#DHDCFLAGS += -DLEGACY_RANDOM_MAC # Android Version Check from Platform source ifneq ($(PLATFORM_VERSION),) @@ -311,7 +300,6 @@ endif # Android Platform Definition ############################## - ########## # KitKat ########## @@ -324,8 +312,6 @@ DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS # To support p2p private command on kernel 3.8 or above DHDCFLAGS += -DWL_NEWCFG_PRIVCMD_SUPPORT - - ########################## # driver type # m: module type driver @@ -350,13 +336,17 @@ ifneq ($(CONFIG_BCM4361),) DHDCFLAGS += -DUSE_WL_TXBF DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB + DHDCFLAGS += -DDISABLE_WL_FRAMEBURST_SOFTAP DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT +# Debugability + DHDCFLAGS += -DDEBUGABILITY_ECNTRS_LOGGING + DHDCFLAGS += -DDEBUGABILITY_ETD_PRSRV_LOGS # Customer ant select and set PM DHDCFLAGS += -DCUSTOM_SET_ANTNPM DHDCFLAGS += -DCUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE # Customer ocl disabe DHDCFLAGS += -DCUSTOM_SET_OCLOFF + # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 @@ -364,10 +354,21 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DDHDTCPACK_SUPPRESS endif +ifeq ($(CONFIG_ARCH_QCOM),y) + DHDCFLAGS += -DCONFIG_ARCH_MSM + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) + DHDCFLAGS += -DUSE_DMA_LOCK + DHDCFLAGS += -DDHD_MAP_LOGGING +endif + # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -393,25 +394,45 @@ endif # Remove common feature for BCM4361 DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) DHDCFLAGS += -DDHD_LOG_DUMP -# Higher rate beacon transmission at softAP - DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE -# Enhanced radio power save with NOA at softAP - DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE +ifneq ($(CUSTOM_LOG_DUMP_BUFSIZE_MB),) + DHDCFLAGS += -DCUSTOM_LOG_DUMP_BUFSIZE_MB=$(CUSTOM_LOG_DUMP_BUFSIZE_MB) +endif + + DHDCFLAGS += -DWL_SUPP_EVENT + DHDCFLAGS += -DFILTER_IE + DHDCFLAGS += -DNDO_CONFIG_SUPPORT # WBTEXT (11kv) feature DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DWBTEXT_BTMDELTA=0 # LOGTRACE_EVENT DHDCFLAGS += -DSHOW_LOGTRACE DHDCFLAGS += -DLOGTRACE_FROM_FILE -ifeq ($(CONFIG_ARCH_MSM8998),y) -# Use SMMU for IOMEM - DHDCFLAGS += -DUSE_SMMU_ARCH_MSM - DHDCFLAGS += -DSET_DMA_MASK_64BIT -endif +# LAST ROAM EVENT LOG + DHDCFLAGS += -DWL_LASTEVT +# Higher rate beacon transmission at softAP + DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE +# Enhanced radio power save with NOA at softAP + DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE # Expand TCP tx queue to 10 times of default size DHDCFLAGS += -DTSQ_MULTIPLIER=10 # HANG simulation DHDCFLAGS += -DDHD_HANG_SEND_UP_TEST -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA)),y) +# Support Monitor Mode + DHDCFLAGS += -DWL_MONITOR +# Enable health check event handling + DHDCFLAGS += -DDNGL_EVENT_SUPPORT + DHDCFLAGS += -DHCHK_COMMON_SW_EVENT +# Generate .softap.info + DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE +# Use SMMU for IOMEM +ifeq ($(filter y,$(CONFIG_ARCH_MSM8998) $(CONFIG_ARCH_SDM845)),y) + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM + DHDCFLAGS += -DDHD_DUMP_MNGR +endif + +ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) +# IRQSET in DHD + DHDCFLAGS += -DDHD_LB_IRQSET # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 # Disable SOFTAP_SEND_HANGEVT @@ -419,51 +440,24 @@ ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYN # Enable LQCM DHDCFLAGS += -DSUPPORT_LQCM endif -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895)), y) -# DHD_LB_IRQSET - CPU migration by IRQ Affinity Set - DHDCFLAGS += -DDHD_LB_IRQSET -endif -# Generate .softap.info - DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE -ifneq ($(PLATFORM_VERSION),) -# DREAM Android N OS should not use below features -ifeq ($(shell expr $(PLATFORM_VERSION) \< 8.0),1) -ifneq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT)),y) - DREAM_NOS_DISCARD_FEATURES := y -endif -endif - -# Feature Set used for GREAT N OS and Android O OS -ifneq ($(DREAM_NOS_DISCARD_FEATURES),y) +ifeq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Debugaility - DHDCFLAGS += -DDEBUGABILITY + DHDCFLAGS += -DDHD_EVENT_LOG_FILTER DHDCFLAGS += -DDHD_PKT_LOGGING # Debug Wakeup pkt reason DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS -DDHD_WAKE_EVENT_STATUS DHDCFLAGS += -DDHD_WAKEPKT_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC -# LAST ROAM EVENT LOG - DHDCFLAGS += -DWL_LASTEVT # Use single nvram file DHDCFLAGS += -DDHD_USE_SINGLE_NVRAM_FILE -#STAT REPORT -#stat report shall be defined only if LINK STAT is defined - DHDCFLAGS += -DSTAT_REPORT -#define temp static only when SDK doesn't support static memory for STAT REPORT -# DHDCFLAGS += -DSTAT_REPORT_TEMP_STATIC -endif - -# RSSI_SUM_REPORT is used over Android O OS only -ifeq ($(shell expr $(PLATFORM_VERSION) \>= 8.0),1) # RSSI Logging DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT -# Enable NDO_CONFIG_SUPPORT in HAL - DHDCFLAGS += -DNDO_CONFIG_SUPPORT -# changed assoc timeout - DHDCFLAGS += -DCUSTOM_ASSOC_TIMEOUT=20 -endif +# To send hang evnet for Samsung phone platform + DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT +# Enable BIGDATA_SOFTAP + DHDCFLAGS += -DBIGDATA_SOFTAP endif # Use Legacy dump path @@ -500,7 +494,6 @@ ifneq ($(CONFIG_BCM4359),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) @@ -511,11 +504,14 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 DHDCFLAGS += -DDHDTCPACK_SUPPRESS +ifeq ($(CONFIG_ARCH_MSM8998),y) +# Use SMMU for IOMEM + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM endif - ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +endif # New Features DHDCFLAGS += -DWL11U -DMFP @@ -546,14 +542,14 @@ endif DHDCFLAGS += -DDHD_LOG_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC + ifneq ($(CONFIG_WLAN_GRACE),) DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DDHD_DEBUG_UART endif ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_SOC_EXYNOS8890)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 - # Enable Dongle Isolation - DHDCFLAGS += -DDONGLE_ENABLE_ISOLATION # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) endif @@ -677,7 +673,6 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_AMPDU_RELEASE=16 endif - # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -749,21 +744,8 @@ endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif -ifneq ($(CONFIG_BCM43456),) - DHDCFLAGS += -DBCM43456_CHIP - DHDCFLAGS += -DWLADPS_PRIVATE_CMD -endif ifneq ($(CONFIG_BCM43455),) - DHDCFLAGS += -DBCM43455_CHIP -endif -ifneq ($(CONFIG_BCM43454),) - DHDCFLAGS += -DBCM43454_CHIP -endif - -# BCM43454/43455/43456 common difine. -ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456))) - DHDCFLAGS += -DHW_OOB - DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DBCM43455_CHIP -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR @@ -780,9 +762,10 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 # New Features - DHDCFLAGS += -DWL11U -DMFP + DHDCFLAGS += -DWL11U DHDCFLAGS += -DBCMCCX DHDCFLAGS += -DWES_SUPPORT DHDCFLAGS += -DOKC_SUPPORT @@ -794,35 +777,59 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DSUPPORT_2G_VHT DHDCFLAGS += -DSUPPORT_WL_TXPOWER DHDCFLAGS += -DBCMCCX_S69 -ifeq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),y) +ifeq ($(CONFIG_BCM43455),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 - DHDCFLAGS += -DDHD_LOG_DUMP - - # FCC power limit control on ch12/13. - # DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 - -ifneq ($(filter y,$(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43455) $(CONFIG_BCM43456))) -# Enable Firmware Coredump - DHDCFLAGS += -DDHD_FW_COREDUMP -ifeq ($(CONFIG_BCMDHD_PREALLOC_MEMDUMP),y) - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -endif # Enable concate blob path DHDCFLAGS += -DCONCATE_BLOB # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif + +ifneq ($(CONFIG_BCM43454),) + DHDCFLAGS += -DBCM43454_CHIP -DHW_OOB + DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION -DSUPPORT_MULTIPLE_BOARD_REV_FROM_DT + DHDCFLAGS += -DUSE_CID_CHECK + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR + + # tput enhancement + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DCUSTOM_FRAMEBURST_SET=1 + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 + + # New Features + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DDHD_ENABLE_LPC + DHDCFLAGS += -DWLAIBSS + DHDCFLAGS += -DSUPPORT_LTECX + DHDCFLAGS += -DSUPPORT_2G_VHT + DHDCFLAGS += -DSUPPORT_WL_TXPOWER + DHDCFLAGS += -DBCMCCX_S69 +ifeq ($(CONFIG_BCM43454),y) + DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD + DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC + DRIVER_TYPE = y +endif + DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif ifneq ($(CONFIG_BCM4335),) @@ -879,54 +886,11 @@ ifeq ($(CONFIG_BCM4335),y) endif endif -ifneq ($(CONFIG_BCM4334),) - DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - -ifneq ($(CONFIG_BCM4334W),) - DHDCFLAGS += -DBCM4334W_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334W),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DBCM43430_CHIP -DSUPPORT_MULTIPLE_REVISION -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DCUSTOM_ASSOC_RETRY_MAX=7 - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP # tput enhancement DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 DHDCFLAGS += -DRXFRAME_THREAD -DRXTHREAD_ONLYSTA @@ -940,23 +904,14 @@ ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DOKC_SUPPORT DHDCFLAGS += -DWLFBT DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE - DHDCFLAGS += -DDHD_LOG_DUMP - DHDCFLAGS += -DDHD_UNSUPPORT_IF_CNTS ifeq ($(CONFIG_BCM4343),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif - # FCC power limit control on ch12/13. - DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 # Remove common feature for BCM4343 + DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSUPPORT_P2P_GO_PS,$(DHDCFLAGS)) # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif @@ -999,45 +954,8 @@ endif DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) endif - -ifneq ($(CONFIG_BCM4330),) - DHDCFLAGS += -DBCM4330_CHIP -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 - DHDCFLAGS += -DWL_CFG80211_GON_COLLISION -ifeq ($(CONFIG_BCM4330),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif - # Remove common feature for BCM4330 - DHDCFLAGS :=$(filter-out -DSUPPORT_AMPDU_MPDU_CMD,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DVSDB,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DPROP_TXSTATUS,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DLIMIT_BORROW,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDHD_USE_IDLECOUNT,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) -endif - -ifneq ($(CONFIG_BCM43241),) - DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMIMO_ANT_SETTING - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 - DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR - DHDCFLAGS += -DAMPDU_HOSTREORDER -ifeq ($(CONFIG_BCM43241),m) - DHDCFLAGS += -fno-pic -endif -ifeq ($(CONFIG_BCM43241),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif endif # chipset supported SDIO only - ############################# # Platform dependent feature ############################# @@ -1071,6 +989,9 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) endif # Compiler option for specific platform +ifeq ($(CONFIG_SOC_EXYNOS8890),y) + DHDCFLAGS += -Wno-date-time +endif ifeq ($(CONFIG_SOC_EXYNOS7570),y) DHDCFLAGS += -Wno-date-time endif @@ -1086,6 +1007,12 @@ endif ifeq ($(CONFIG_ARCH_MSM8998),y) DHDCFLAGS += -Wno-date-time endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS += -Wno-date-time +endif +ifeq ($(CONFIG_ARCH_SDM845),y) + DHDCFLAGS += -Wno-date-time +endif # DTS Support ifeq ($(CONFIG_OF),y) @@ -1101,16 +1028,17 @@ ifneq ($(CONFIG_SOC_EXYNOS8890),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifneq ($(CONFIG_SOC_EXYNOS8895),) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_EXSOM7420),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8890),) -DHDCFLAGS += -DDHD_OF_SUPPORT -endif -ifneq ($(CONFIG_SOC_EXYNOS8895),) +ifneq ($(CONFIG_SOC_EXYNOS9810),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif @@ -1131,6 +1059,10 @@ ifneq ($(CONFIG_ARCH_MSM8998),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifeq ($(CONFIG_ARCH_SDM845),y) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_UNIVERSAL3475),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1141,10 +1073,6 @@ ifneq ($(CONFIG_SOC_EXYNOS7870),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -Wno-date-time endif -ifneq ($(CONFIG_SOC_EXYNOS7885),) -DHDCFLAGS += -DDHD_OF_SUPPORT -DHDCFLAGS += -Wno-date-time -endif ifneq ($(CONFIG_SOC_EXYNOS7570),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1153,21 +1081,13 @@ DHDCFLAGS += -DDHD_OF_SUPPORT endif endif #CONFIG_OF -# DEBUG UART -ifneq ($(CONFIG_WLAN_GRACE),) -DHDCFLAGS += -DDHD_DEBUG_UART -endif - -#ifneq ($(CONFIG_SOC_EXYNOS8895),) -#DHDCFLAGS += -DDHD_DEBUG_UART -#endif - ifneq ($(CONFIG_ARCH_TEGRA),) DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS := $(filter-out -DDHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DWL_VENDOR_EXT_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DGSCAN_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DRTT_SUPPORT,$(DHDCFLAGS)) +DHDCFLAGS := $(filter-out -DDHD_LB_IRQSET,$(DHDCFLAGS)) DHD_ANDROID_OFILES := $(filter-out wl_cfgvendor.o,$(DHD_ANDROID_OFILES)) DHD_ANDROID_OFILES := $(filter-out dhd_rtt.o,$(DHD_ANDROID_OFILES)) endif @@ -1188,15 +1108,15 @@ EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ EXTRA_CFLAGS += $(call cc-option, -Wunused-but-set-variable) EXTRA_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) -KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) +KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(CURDIR) DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o dhd_custom_sec.o \ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \ - bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \ + bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o linux_pkt.o sbutils.o siutils.o \ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o \ wl_linux_mon.o wl_roam.o dhd_linux_platdev.o dhd_linux_wq.o wl_cfg_btcoex.o \ - hnd_pktq.o hnd_pktpool.o dhd_debug.o dhd_debug_linux.o dhd_custom_cis.o dhd_mschdbg.o \ - dhd_pktlog.o + hnd_pktq.o hnd_pktpool.o dhd_custom_cis.o dhd_debug.o dhd_debug_linux.o dhd_mschdbg.o \ + dhd_dbg_ring.o ifeq ($(BUS_IFACE_SDIO),y) DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o @@ -1218,15 +1138,21 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDOFILES += wl_cfgnan.o bcmxtlv.o +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDOFILES += wl_cfgnan.o bcmxtlv.o bcmbloom.o +#endif // endif + +ifneq ($(filter -DDHD_PKT_LOGGING,$(DHDCFLAGS)),) +DHDOFILES += dhd_pktlog.o +endif + +ifneq ($(filter -DDHD_EVENT_LOG_FILTER, $(DHDCFLAGS)),) +DHDOFILES += dhd_event_log_filter.o endif -ifneq ($(filter -DSTAT_REPORT,$(DHDCFLAGS)),) -DHDOFILES += wl_statreport.o +ifneq ($(filter -DBIGDATA_SOFTAP,$(DHDCFLAGS)),) +DHDOFILES += wl_bigdata.o endif dhd-y := $(DHDOFILES) diff --git a/drivers/net/wireless/bcmdhd_oo/Makefile.lp b/drivers/net/wireless/bcmdhd_oo/Makefile.lp index 08e64827aa45117bd016b66ff62a06637a2fe617..b6d79f565a5d93f80c7fc2ee1344a7b91fd99c39 100644 --- a/drivers/net/wireless/bcmdhd_oo/Makefile.lp +++ b/drivers/net/wireless/bcmdhd_oo/Makefile.lp @@ -1,12 +1,12 @@ # -# Copyright (C) 1999-2017, Broadcom Corporation -# +# Copyright (C) 1999-2018, Broadcom. +# # 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 @@ -14,7 +14,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. @@ -101,19 +101,15 @@ endif DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_TXP -DDHD_LB_STATS # Extended HANG event with reason codes DHDCFLAGS += -DDHD_USE_EXTENDED_HANG_REASON - DHDCFLAGS += -DDHD_RECOVER_TIMEOUT + # DHDCFLAGS += -DDHD_RECOVER_TIMEOUT # HEAP ASLR DHDCFLAGS += -DBCM_ASLR_HEAP - ifneq ($(CONFIG_SOC_EXYNOS8895),) # Default Tx LB Enable DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB endif - endif - - ################# # Common feature ################# @@ -170,6 +166,7 @@ DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND DHDCFLAGS += -DDHD_LOSSLESS_ROAMING +DHDCFLAGS += -DSKIP_ROAM_TRIGGER_RESET # Enable Roam time thresh DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND @@ -210,6 +207,8 @@ DHDCFLAGS += -DUNSET_FW_ROAM_WIPHY_FLAG # For special PNO Event keep wake lock for 10sec DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10 +# Enable Scheduled scan +DHDCFLAGS += -DWL_SCHED_SCAN # For IPV6 Neighbor Discovery Offload Support DHDCFLAGS += -DIPV6_NDO_SUPPORT @@ -248,7 +247,7 @@ DHDCFLAGS += -DPKTPRIO_OVERRIDE # Prevent rx thread monopolize DHDCFLAGS += -DWAIT_DEQUEUE -# Control PM related value for MFG process(Read from file) +# Control PM related value for MFG process(Read from file) DHDCFLAGS += -DDHD_PM_CONTROL_FROM_FILE # Use Android wake lock mechanism @@ -261,12 +260,10 @@ DHDCFLAGS += -DUSE_INITIAL_SHORT_DWELL_TIME DHDCFLAGS += -DKEEP_JP_REGREV # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDCFLAGS += -DWL_NAN -endif +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDCFLAGS += -DWL_NAN -DWL_NAN_DISC_CACHE +#endif // endif # FCC power limit control on ch12/13. DHDCFLAGS += -DFCC_PWR_LIMIT_2G @@ -277,9 +274,6 @@ DHDCFLAGS += -DUSE_WFA_CERT_CONF # Change the WL_SCAN_TIMER_INTERVAL_MS of DHD DHDCFLAGS += -DCUSTOMER_SCAN_TIMEOUT_SETTING -# Does not forword internal packet -DHDCFLAGS += -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT - # Enable HANG event test private command DHDCFLAGS += -DSUPPORT_TRIGGER_HANG_EVENT @@ -292,14 +286,9 @@ DHDCFLAGS += -DSUPPORT_RANDOM_MAC_SCAN # WLC_E_SET_SSID fail DHDCFLAGS += -DSET_SSID_FAIL_CUSTOM_RC=100 -# Enable to block Band A(5G), Only support Band B(2G) -ifeq ($(CONFIG_WLAN_5GDISABLE),y) -DHDCFLAGS += -DDHD_2G_ONLY_SUPPORT -endif -# Disable VHT(5G HT80) mode -ifeq ($(CONFIG_WLAN_VHTDISABLE),y) -DHDCFLAGS += -DDHD_DISABLE_VHTMODE -endif +# Use legacy random mac +# Disable the legacy randmac and enable scanmac +#DHDCFLAGS += -DLEGACY_RANDOM_MAC # Android Version Check from Platform source ifneq ($(PLATFORM_VERSION),) @@ -311,7 +300,6 @@ endif # Android Platform Definition ############################## - ########### # Lollipop ########### @@ -347,8 +335,6 @@ DHDCFLAGS :=$(filter-out -DRTT_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DWL_VENDOR_EXT_SUPPORT,$(DHDCFLAGS)) endif - - ########################## # driver type # m: module type driver @@ -373,13 +359,17 @@ ifneq ($(CONFIG_BCM4361),) DHDCFLAGS += -DUSE_WL_TXBF DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB + DHDCFLAGS += -DDISABLE_WL_FRAMEBURST_SOFTAP DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT +# Debugability + DHDCFLAGS += -DDEBUGABILITY_ECNTRS_LOGGING + DHDCFLAGS += -DDEBUGABILITY_ETD_PRSRV_LOGS # Customer ant select and set PM DHDCFLAGS += -DCUSTOM_SET_ANTNPM DHDCFLAGS += -DCUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE # Customer ocl disabe DHDCFLAGS += -DCUSTOM_SET_OCLOFF + # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 @@ -387,10 +377,21 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DDHDTCPACK_SUPPRESS endif +ifeq ($(CONFIG_ARCH_QCOM),y) + DHDCFLAGS += -DCONFIG_ARCH_MSM + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) +endif + ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) + DHDCFLAGS += -DUSE_DMA_LOCK + DHDCFLAGS += -DDHD_MAP_LOGGING +endif + # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -416,25 +417,45 @@ endif # Remove common feature for BCM4361 DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) DHDCFLAGS += -DDHD_LOG_DUMP -# Higher rate beacon transmission at softAP - DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE -# Enhanced radio power save with NOA at softAP - DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE +ifneq ($(CUSTOM_LOG_DUMP_BUFSIZE_MB),) + DHDCFLAGS += -DCUSTOM_LOG_DUMP_BUFSIZE_MB=$(CUSTOM_LOG_DUMP_BUFSIZE_MB) +endif + + DHDCFLAGS += -DWL_SUPP_EVENT + DHDCFLAGS += -DFILTER_IE + DHDCFLAGS += -DNDO_CONFIG_SUPPORT # WBTEXT (11kv) feature DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DWBTEXT_BTMDELTA=0 # LOGTRACE_EVENT DHDCFLAGS += -DSHOW_LOGTRACE DHDCFLAGS += -DLOGTRACE_FROM_FILE -ifeq ($(CONFIG_ARCH_MSM8998),y) -# Use SMMU for IOMEM - DHDCFLAGS += -DUSE_SMMU_ARCH_MSM - DHDCFLAGS += -DSET_DMA_MASK_64BIT -endif +# LAST ROAM EVENT LOG + DHDCFLAGS += -DWL_LASTEVT +# Higher rate beacon transmission at softAP + DHDCFLAGS += -DSUPPORT_AP_HIGHER_BEACONRATE +# Enhanced radio power save with NOA at softAP + DHDCFLAGS += -DSUPPORT_AP_RADIO_PWRSAVE # Expand TCP tx queue to 10 times of default size DHDCFLAGS += -DTSQ_MULTIPLIER=10 # HANG simulation DHDCFLAGS += -DDHD_HANG_SEND_UP_TEST -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA)),y) +# Support Monitor Mode + DHDCFLAGS += -DWL_MONITOR +# Enable health check event handling + DHDCFLAGS += -DDNGL_EVENT_SUPPORT + DHDCFLAGS += -DHCHK_COMMON_SW_EVENT +# Generate .softap.info + DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE +# Use SMMU for IOMEM +ifeq ($(filter y,$(CONFIG_ARCH_MSM8998) $(CONFIG_ARCH_SDM845)),y) + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM + DHDCFLAGS += -DDHD_DUMP_MNGR +endif + +ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895) $(CONFIG_ARCH_TEGRA) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) +# IRQSET in DHD + DHDCFLAGS += -DDHD_LB_IRQSET # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 # Disable SOFTAP_SEND_HANGEVT @@ -442,51 +463,24 @@ ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYN # Enable LQCM DHDCFLAGS += -DSUPPORT_LQCM endif -ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_ARCH_MSM8998) $(CONFIG_SOC_EXYNOS8890) $(CONFIG_SOC_EXYNOS8895)), y) -# DHD_LB_IRQSET - CPU migration by IRQ Affinity Set - DHDCFLAGS += -DDHD_LB_IRQSET -endif -# Generate .softap.info - DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE -ifneq ($(PLATFORM_VERSION),) -# DREAM Android N OS should not use below features -ifeq ($(shell expr $(PLATFORM_VERSION) \< 8.0),1) -ifneq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT)),y) - DREAM_NOS_DISCARD_FEATURES := y -endif -endif - -# Feature Set used for GREAT N OS and Android O OS -ifneq ($(DREAM_NOS_DISCARD_FEATURES),y) +ifeq ($(filter y,$(CONFIG_WLAN_GREAT) $(CONFIG_SEC_GREATQLTE_PROJECT) $(CONFIG_SOC_EXYNOS9810) $(CONFIG_ARCH_SDM845)),y) # Debugaility - DHDCFLAGS += -DDEBUGABILITY + DHDCFLAGS += -DDHD_EVENT_LOG_FILTER DHDCFLAGS += -DDHD_PKT_LOGGING # Debug Wakeup pkt reason DHDCFLAGS += -DDHD_WAKE_STATUS -DDHD_WAKE_RX_STATUS -DDHD_WAKE_EVENT_STATUS DHDCFLAGS += -DDHD_WAKEPKT_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC -# LAST ROAM EVENT LOG - DHDCFLAGS += -DWL_LASTEVT # Use single nvram file DHDCFLAGS += -DDHD_USE_SINGLE_NVRAM_FILE -#STAT REPORT -#stat report shall be defined only if LINK STAT is defined - DHDCFLAGS += -DSTAT_REPORT -#define temp static only when SDK doesn't support static memory for STAT REPORT -# DHDCFLAGS += -DSTAT_REPORT_TEMP_STATIC -endif - -# RSSI_SUM_REPORT is used over Android O OS only -ifeq ($(shell expr $(PLATFORM_VERSION) \>= 8.0),1) # RSSI Logging DHDCFLAGS += -DSUPPORT_RSSI_SUM_REPORT -# Enable NDO_CONFIG_SUPPORT in HAL - DHDCFLAGS += -DNDO_CONFIG_SUPPORT -# changed assoc timeout - DHDCFLAGS += -DCUSTOM_ASSOC_TIMEOUT=20 -endif +# To send hang evnet for Samsung phone platform + DHDCFLAGS += -DWL_CFGVENDOR_SEND_HANG_EVENT +# Enable BIGDATA_SOFTAP + DHDCFLAGS += -DBIGDATA_SOFTAP endif # Use Legacy dump path @@ -523,7 +517,6 @@ ifneq ($(CONFIG_BCM4359),) DHDCFLAGS += -DUSE_WL_FRAMEBURST DHDCFLAGS += -DDISABLE_FRAMEBURST_VSDB DHDCFLAGS += -DDISABLE_PM_BCNRX - DHDCFLAGS += -DALLOW_CHSW_EVT # tput enhancement for PCIE ifeq ($(BUS_IFACE_PCIE),y) @@ -534,11 +527,14 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15 DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10 DHDCFLAGS += -DDHDTCPACK_SUPPRESS +ifeq ($(CONFIG_ARCH_MSM8998),y) +# Use SMMU for IOMEM + DHDCFLAGS += -DUSE_SMMU_ARCH_MSM endif - ifeq ($(CONFIG_ARCH_MSM),y) DHDCFLAGS := $(filter-out -DDHDTCPACK_SUPPRESS,$(DHDCFLAGS)) endif +endif # New Features DHDCFLAGS += -DWL11U -DMFP @@ -569,14 +565,14 @@ endif DHDCFLAGS += -DDHD_LOG_DUMP # To support CAC DHDCFLAGS += -DSUPPORT_SET_CAC + ifneq ($(CONFIG_WLAN_GRACE),) DHDCFLAGS += -DWBTEXT + DHDCFLAGS += -DDHD_DEBUG_UART endif ifeq ($(filter y,$(CONFIG_ARCH_MSM8996) $(CONFIG_SOC_EXYNOS8890)),y) # Runtime PM DHDCFLAGS += -DDHD_PCIE_RUNTIMEPM -DMAX_IDLE_COUNT=11 -DCUSTOM_DHD_RUNTIME_MS=100 - # Enable Dongle Isolation - DHDCFLAGS += -DDONGLE_ENABLE_ISOLATION # Disable SOFTAP_SEND_HANGEVT DHDCFLAGS := $(filter-out -DSOFTAP_SEND_HANGEVT,$(DHDCFLAGS)) endif @@ -700,7 +696,6 @@ ifeq ($(BUS_IFACE_PCIE),y) DHDCFLAGS += -DCUSTOM_AMPDU_RELEASE=16 endif - # New Features DHDCFLAGS += -DWL11U -DMFP DHDCFLAGS += -DBCMCCX @@ -772,21 +767,8 @@ endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif -ifneq ($(CONFIG_BCM43456),) - DHDCFLAGS += -DBCM43456_CHIP - DHDCFLAGS += -DWLADPS_PRIVATE_CMD -endif ifneq ($(CONFIG_BCM43455),) - DHDCFLAGS += -DBCM43455_CHIP -endif -ifneq ($(CONFIG_BCM43454),) - DHDCFLAGS += -DBCM43454_CHIP -endif - -# BCM43454/43455/43456 common difine. -ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456))) - DHDCFLAGS += -DHW_OOB - DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DBCM43455_CHIP -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR @@ -803,9 +785,10 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 # New Features - DHDCFLAGS += -DWL11U -DMFP + DHDCFLAGS += -DWL11U DHDCFLAGS += -DBCMCCX DHDCFLAGS += -DWES_SUPPORT DHDCFLAGS += -DOKC_SUPPORT @@ -817,35 +800,59 @@ ifneq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(fi DHDCFLAGS += -DSUPPORT_2G_VHT DHDCFLAGS += -DSUPPORT_WL_TXPOWER DHDCFLAGS += -DBCMCCX_S69 -ifeq ($(filter y,$(CONFIG_BCM43454) $(CONFIG_BCM43455) $(CONFIG_BCM43456)),y) +ifeq ($(CONFIG_BCM43455),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 - DHDCFLAGS += -DDHD_LOG_DUMP - - # FCC power limit control on ch12/13. - # DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 - -ifneq ($(filter y,$(CONFIG_BCM43455) $(CONFIG_BCM43456)),$(filter m,$(CONFIG_BCM43455) $(CONFIG_BCM43456))) -# Enable Firmware Coredump - DHDCFLAGS += -DDHD_FW_COREDUMP -ifeq ($(CONFIG_BCMDHD_PREALLOC_MEMDUMP),y) - DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -endif # Enable concate blob path DHDCFLAGS += -DCONCATE_BLOB # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif + +ifneq ($(CONFIG_BCM43454),) + DHDCFLAGS += -DBCM43454_CHIP -DHW_OOB + DHDCFLAGS += -DSUPPORT_MULTIPLE_REVISION -DSUPPORT_MULTIPLE_BOARD_REV_FROM_DT + DHDCFLAGS += -DUSE_CID_CHECK + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR + + # tput enhancement + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=8 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DCUSTOM_FRAMEBURST_SET=1 + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=64 -DCUSTOM_IBSS_AMPDU_BA_WSIZE=16 + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 + + # New Features + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DDHD_ENABLE_LPC + DHDCFLAGS += -DWLAIBSS + DHDCFLAGS += -DSUPPORT_LTECX + DHDCFLAGS += -DSUPPORT_2G_VHT + DHDCFLAGS += -DSUPPORT_WL_TXPOWER + DHDCFLAGS += -DBCMCCX_S69 +ifeq ($(CONFIG_BCM43454),y) + DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD + DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC + DRIVER_TYPE = y +endif + DHDCFLAGS += -DCUSTOM_PSPRETEND_THR=30 endif ifneq ($(CONFIG_BCM4335),) @@ -902,54 +909,11 @@ ifeq ($(CONFIG_BCM4335),y) endif endif -ifneq ($(CONFIG_BCM4334),) - DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - -ifneq ($(CONFIG_BCM4334W),) - DHDCFLAGS += -DBCM4334W_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DUSE_CID_CHECK - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP - DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 - DHDCFLAGS += -DPROP_TXSTATUS_VSDB - DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DSUPPORT_WL_TXPOWER -ifeq ($(CONFIG_ARCH_MSM8960),y) - DHDCFLAGS += -DDHD_SDALIGN=4 -endif - # New Features - DHDCFLAGS += -DWL11U -ifeq ($(CONFIG_BCM4334W),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif - ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DBCM43430_CHIP -DSUPPORT_MULTIPLE_REVISION -DHW_OOB DHDCFLAGS += -DUSE_CID_CHECK DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DCUSTOM_ASSOC_RETRY_MAX=7 - DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP # tput enhancement DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 DHDCFLAGS += -DRXFRAME_THREAD -DRXTHREAD_ONLYSTA @@ -963,23 +927,14 @@ ifneq ($(CONFIG_BCM4343),) DHDCFLAGS += -DOKC_SUPPORT DHDCFLAGS += -DWLFBT DHDCFLAGS += -DWLTDLS -DWLTDLS_AUTO_ENABLE - DHDCFLAGS += -DDHD_LOG_DUMP - DHDCFLAGS += -DDHD_UNSUPPORT_IF_CNTS ifeq ($(CONFIG_BCM4343),y) DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC DRIVER_TYPE = y endif - # FCC power limit control on ch12/13. - DHDCFLAGS += -DFCC_PWR_LIMIT_2G - # Enable Roam time thresh - DHDCFLAGS += -DENABLE_MAX_DTIM_IN_SUSPEND - DHDCFLAGS += -DCUSTOM_BCN_TIMEOUT_IN_SUSPEND=10 - DHDCFLAGS += -DCUSTOM_ROAM_TIME_THRESH_IN_SUSPEND=6000 - DHDCFLAGS += -DMAX_DTIM_ALLOWED_INTERVAL=925 # Remove common feature for BCM4343 + DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DSUPPORT_P2P_GO_PS,$(DHDCFLAGS)) # Generate .softap.info DHDCFLAGS += -DGEN_SOFTAP_INFO_FILE endif @@ -1022,45 +977,8 @@ endif DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) endif - -ifneq ($(CONFIG_BCM4330),) - DHDCFLAGS += -DBCM4330_CHIP -DSUPPORT_MULTIPLE_REVISION - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 - DHDCFLAGS += -DWL_CFG80211_GON_COLLISION -ifeq ($(CONFIG_BCM4330),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif - # Remove common feature for BCM4330 - DHDCFLAGS :=$(filter-out -DSUPPORT_AMPDU_MPDU_CMD,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DVSDB,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DPROP_TXSTATUS,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DLIMIT_BORROW,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DROAM_AP_ENV_DETECTION,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDHD_USE_IDLECOUNT,$(DHDCFLAGS)) - DHDCFLAGS :=$(filter-out -DDISABLE_11H_SOFTAP,$(DHDCFLAGS)) -endif - -ifneq ($(CONFIG_BCM43241),) - DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMIMO_ANT_SETTING - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 - DHDCFLAGS += -DUSE_SDIOFIFO_IOVAR - DHDCFLAGS += -DAMPDU_HOSTREORDER -ifeq ($(CONFIG_BCM43241),m) - DHDCFLAGS += -fno-pic -endif -ifeq ($(CONFIG_BCM43241),y) - DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD - DHDCFLAGS += -DUSE_LATE_INITCALL_SYNC - DRIVER_TYPE = y -endif -endif endif # chipset supported SDIO only - ############################# # Platform dependent feature ############################# @@ -1094,6 +1012,9 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) endif # Compiler option for specific platform +ifeq ($(CONFIG_SOC_EXYNOS8890),y) + DHDCFLAGS += -Wno-date-time +endif ifeq ($(CONFIG_SOC_EXYNOS7570),y) DHDCFLAGS += -Wno-date-time endif @@ -1109,6 +1030,12 @@ endif ifeq ($(CONFIG_ARCH_MSM8998),y) DHDCFLAGS += -Wno-date-time endif +ifeq ($(CONFIG_SOC_EXYNOS9810),y) + DHDCFLAGS += -Wno-date-time +endif +ifeq ($(CONFIG_ARCH_SDM845),y) + DHDCFLAGS += -Wno-date-time +endif # DTS Support ifeq ($(CONFIG_OF),y) @@ -1124,16 +1051,17 @@ ifneq ($(CONFIG_SOC_EXYNOS8890),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifneq ($(CONFIG_SOC_EXYNOS8895),) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_EXSOM7420),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS += -DEXYNOS_PCIE_MODULE_PATCH obj-$(CONFIG_MACH_EXSOM7420) += dhd_custom_exynos.o dhd_custom_memprealloc.o endif -ifneq ($(CONFIG_SOC_EXYNOS8890),) -DHDCFLAGS += -DDHD_OF_SUPPORT -endif -ifneq ($(CONFIG_SOC_EXYNOS8895),) +ifneq ($(CONFIG_SOC_EXYNOS9810),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif @@ -1154,6 +1082,10 @@ ifneq ($(CONFIG_ARCH_MSM8998),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE endif +ifeq ($(CONFIG_ARCH_SDM845),y) +DHDCFLAGS += -DDHD_OF_SUPPORT +DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE +endif ifneq ($(CONFIG_MACH_UNIVERSAL3475),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1164,10 +1096,6 @@ ifneq ($(CONFIG_SOC_EXYNOS7870),) DHDCFLAGS += -DDHD_OF_SUPPORT DHDCFLAGS += -Wno-date-time endif -ifneq ($(CONFIG_SOC_EXYNOS7885),) -DHDCFLAGS += -DDHD_OF_SUPPORT -DHDCFLAGS += -Wno-date-time -endif ifneq ($(CONFIG_SOC_EXYNOS7570),) DHDCFLAGS += -DDHD_OF_SUPPORT endif @@ -1176,21 +1104,13 @@ DHDCFLAGS += -DDHD_OF_SUPPORT endif endif #CONFIG_OF -# DEBUG UART -ifneq ($(CONFIG_WLAN_GRACE),) -DHDCFLAGS += -DDHD_DEBUG_UART -endif - -#ifneq ($(CONFIG_SOC_EXYNOS8895),) -#DHDCFLAGS += -DDHD_DEBUG_UART -#endif - ifneq ($(CONFIG_ARCH_TEGRA),) DHDCFLAGS += -DBCMPCIE_OOB_HOST_WAKE DHDCFLAGS := $(filter-out -DDHD_ALLOC_COHERENT_MEM_FROM_ATOMIC_POOL,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DWL_VENDOR_EXT_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DGSCAN_SUPPORT,$(DHDCFLAGS)) DHDCFLAGS := $(filter-out -DRTT_SUPPORT,$(DHDCFLAGS)) +DHDCFLAGS := $(filter-out -DDHD_LB_IRQSET,$(DHDCFLAGS)) DHD_ANDROID_OFILES := $(filter-out wl_cfgvendor.o,$(DHD_ANDROID_OFILES)) DHD_ANDROID_OFILES := $(filter-out dhd_rtt.o,$(DHD_ANDROID_OFILES)) endif @@ -1211,15 +1131,15 @@ EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" EXTRA_CFLAGS += -I$(src)/include/ -I$(src)/ EXTRA_CFLAGS += $(call cc-option, -Wunused-but-set-variable) EXTRA_CFLAGS += $(call cc-option, -Wmaybe-uninitialized) -KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(shell pwd) +KBUILD_CFLAGS += -I$(LINUXDIR)/include -I$(CURDIR) DHDOFILES := dhd_pno.o dhd_common.o dhd_ip.o dhd_custom_gpio.o dhd_custom_sec.o \ dhd_linux.o dhd_linux_sched.o dhd_cfg80211.o dhd_linux_wq.o aiutils.o bcmevent.o \ - bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o sbutils.o siutils.o \ + bcmutils.o bcmwifi_channels.o hndpmu.o linux_osl.o linux_pkt.o sbutils.o siutils.o \ wl_android.o wl_cfg80211.o wl_cfgp2p.o wl_cfg_btcoex.o wldev_common.o \ wl_linux_mon.o wl_roam.o dhd_linux_platdev.o dhd_linux_wq.o wl_cfg_btcoex.o \ - hnd_pktq.o hnd_pktpool.o dhd_debug.o dhd_debug_linux.o dhd_custom_cis.o dhd_mschdbg.o \ - dhd_pktlog.o + hnd_pktq.o hnd_pktpool.o dhd_custom_cis.o dhd_debug.o dhd_debug_linux.o dhd_mschdbg.o \ + dhd_dbg_ring.o ifeq ($(BUS_IFACE_SDIO),y) DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o @@ -1241,15 +1161,21 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif # NAN feature -# Temporarily disabled NAN build. -# As changes required as per new wlioctl.h are in RB stage. -# Once RB gets ship it, will revert this change. -ifeq ($(CONFIG_WL_NAN),y) -# DHDOFILES += wl_cfgnan.o bcmxtlv.o +#Until SDK update, uncoditionally enabling NAN for now +#ifeq ($(CONFIG_WL_NAN),y) +DHDOFILES += wl_cfgnan.o bcmxtlv.o bcmbloom.o +#endif // endif + +ifneq ($(filter -DDHD_PKT_LOGGING,$(DHDCFLAGS)),) +DHDOFILES += dhd_pktlog.o +endif + +ifneq ($(filter -DDHD_EVENT_LOG_FILTER, $(DHDCFLAGS)),) +DHDOFILES += dhd_event_log_filter.o endif -ifneq ($(filter -DSTAT_REPORT,$(DHDCFLAGS)),) -DHDOFILES += wl_statreport.o +ifneq ($(filter -DBIGDATA_SOFTAP,$(DHDCFLAGS)),) +DHDOFILES += wl_bigdata.o endif dhd-y := $(DHDOFILES) diff --git a/drivers/net/wireless/bcmdhd_oo/aiutils.c b/drivers/net/wireless/bcmdhd_oo/aiutils.c index f4df6da37b59ce20d1ac9b3ff1843b0956a4e51f..2f083eab6de4a3cfae2db69a6ae9c4407d9ccbee 100644 --- a/drivers/net/wireless/bcmdhd_oo/aiutils.c +++ b/drivers/net/wireless/bcmdhd_oo/aiutils.c @@ -2,14 +2,14 @@ * Misc utility routines for accessing chip-specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: aiutils.c 625027 2016-03-15 08:20:18Z $ + * $Id: aiutils.c 726313 2017-10-12 06:07:22Z $ */ #include #include @@ -40,13 +40,18 @@ #include "siutils_priv.h" #include -#define BCM5357_DMP() (0) #define BCM53573_DMP() (0) #define BCM4707_DMP() (0) #define PMU_DMP() (0) #define GCI_DMP() (0) -#define remap_coreid(sih, coreid) (coreid) -#define remap_corerev(sih, corerev) (corerev) + +#if defined(BCM_BACKPLANE_TIMEOUT) +static bool ai_get_apb_bridge(si_t *sih, uint32 coreidx, uint32 *apb_id, uint32 *apb_coreuinit); +#endif /* BCM_BACKPLANE_TIMEOUT */ + +#if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) +static void ai_reset_axi_to(si_info_t *sii, aidmp_t *ai); +#endif /* defined (AXI_TIMEOUTS) || defined (BCM_BACKPLANE_TIMEOUT) */ /* EROM parsing */ @@ -129,8 +134,10 @@ get_asd(si_t *sih, uint32 **eromptr, uint sp, uint ad, uint st, uint32 *addrl, u return asd; } - -/* parse the enumeration rom to identify all cores */ +/* Parse the enumeration rom to identify all cores + * Erom content format can be found in: + * http://hwnbu-twiki.broadcom.com/twiki/pub/Mwgroup/ArmDocumentation/SystemDiscovery.pdf + */ void ai_scan(si_t *sih, void *regs, uint devid) { @@ -213,20 +220,24 @@ ai_scan(si_t *sih, void *regs, uint devid) mfg, cid, crev, OSL_OBFUSCATE_BUF(eromptr - 1), nmw, nsw, nmp, nsp)); #else BCM_REFERENCE(crev); -#endif +#endif // endif - if (CHIPID(sih->chip) == BCM4347_CHIP_ID) { + if (BCM4347_CHIP(sih->chip)) { /* 4347 has more entries for ARM core * This should apply to all chips but crashes on router * This is a temp fix to be further analyze */ if (nsp == 0) continue; - } else { + } else + { /* Include Default slave wrapper for timeout monitoring */ if ((nsp == 0) || #if !defined(AXI_TIMEOUTS) && !defined(BCM_BACKPLANE_TIMEOUT) ((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || +#else + ((CHIPTYPE(sii->pub.socitype) == SOCI_NAI) && + (mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || #endif /* !defined(AXI_TIMEOUTS) && !defined(BCM_BACKPLANE_TIMEOUT) */ FALSE) { continue; @@ -242,8 +253,9 @@ ai_scan(si_t *sih, void *regs, uint devid) sii->oob_router = addrl; } } - if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID && - cid != PMU_CORE_ID && cid != GCI_CORE_ID) + if (cid != NS_CCB_CORE_ID && + cid != PMU_CORE_ID && cid != GCI_CORE_ID && cid != SR_CORE_ID && + cid != HUB_CORE_ID) continue; } @@ -251,7 +263,7 @@ ai_scan(si_t *sih, void *regs, uint devid) cores_info->cia[idx] = cia; cores_info->cib[idx] = cib; - cores_info->coreid[idx] = remap_coreid(sih, cid); + cores_info->coreid[idx] = cid; for (i = 0; i < nmp; i++) { mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); @@ -293,7 +305,7 @@ ai_scan(si_t *sih, void *regs, uint devid) } cores_info->coresba[idx] = addrl; cores_info->coresba_size[idx] = sizel; - /* Get any more ASDs in port 0 */ + /* Get any more ASDs in first port */ j = 1; do { asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, @@ -311,7 +323,11 @@ ai_scan(si_t *sih, void *regs, uint devid) do { asd = get_asd(sih, &eromptr, i, j, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); - + /* To get the first base address of second slave port */ + if ((asd != 0) && (i == 1) && (j == 0)) { + cores_info->csp2ba[idx] = addrl; + cores_info->csp2ba_size[idx] = sizel; + } if (asd == 0) break; j++; @@ -334,21 +350,26 @@ ai_scan(si_t *sih, void *regs, uint devid) SI_ERROR(("Master wrapper %d is not 4KB\n", i)); goto error; } - if (i == 0) + if (i == 0) { cores_info->wrapba[idx] = addrl; - else if (i == 1) + } else if (i == 1) { cores_info->wrapba2[idx] = addrl; + } else if (i == 2) { + cores_info->wrapba3[idx] = addrl; + } - - ASSERT(sii->axi_num_wrappers < SI_MAX_AXI_WRAPPERS); - axi_wrapper[sii->axi_num_wrappers].mfg = mfg; - axi_wrapper[sii->axi_num_wrappers].cid = cid; - axi_wrapper[sii->axi_num_wrappers].rev = crev; - axi_wrapper[sii->axi_num_wrappers].wrapper_type = AI_MASTER_WRAPPER; - axi_wrapper[sii->axi_num_wrappers].wrapper_addr = addrl; - sii->axi_num_wrappers++; - SI_VMSG(("MASTER WRAPPER: %d, mfg:%x, cid:%x, rev:%x, addr:%x, size:%x\n", + if (axi_wrapper && + (sii->axi_num_wrappers < SI_MAX_AXI_WRAPPERS)) { + axi_wrapper[sii->axi_num_wrappers].mfg = mfg; + axi_wrapper[sii->axi_num_wrappers].cid = cid; + axi_wrapper[sii->axi_num_wrappers].rev = crev; + axi_wrapper[sii->axi_num_wrappers].wrapper_type = AI_MASTER_WRAPPER; + axi_wrapper[sii->axi_num_wrappers].wrapper_addr = addrl; + sii->axi_num_wrappers++; + SI_VMSG(("MASTER WRAPPER: %d, mfg:%x, cid:%x," + "rev:%x, addr:%x, size:%x\n", sii->axi_num_wrappers, mfg, cid, crev, addrl, sizel)); + } } /* And finally slave wrappers */ @@ -371,33 +392,54 @@ ai_scan(si_t *sih, void *regs, uint devid) SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); goto error; } - if ((nmw == 0) && (i == 0)) + if ((nmw == 0) && (i == 0)) { cores_info->wrapba[idx] = addrl; - else if ((nmw == 0) && (i == 1)) + } else if ((nmw == 0) && (i == 1)) { cores_info->wrapba2[idx] = addrl; + } else if ((nmw == 0) && (i == 2)) { + cores_info->wrapba3[idx] = addrl; + } /* Include all slave wrappers to the list to * enable and monitor watchdog timeouts */ - ASSERT(sii->axi_num_wrappers < SI_MAX_AXI_WRAPPERS); - axi_wrapper[sii->axi_num_wrappers].mfg = mfg; - axi_wrapper[sii->axi_num_wrappers].cid = cid; - axi_wrapper[sii->axi_num_wrappers].rev = crev; - axi_wrapper[sii->axi_num_wrappers].wrapper_type = AI_SLAVE_WRAPPER; - axi_wrapper[sii->axi_num_wrappers].wrapper_addr = addrl; - sii->axi_num_wrappers++; + if (axi_wrapper && + (sii->axi_num_wrappers < SI_MAX_AXI_WRAPPERS)) { + axi_wrapper[sii->axi_num_wrappers].mfg = mfg; + axi_wrapper[sii->axi_num_wrappers].cid = cid; + axi_wrapper[sii->axi_num_wrappers].rev = crev; + axi_wrapper[sii->axi_num_wrappers].wrapper_type = AI_SLAVE_WRAPPER; + + /* Software WAR as discussed with hardware team, to ensure proper + * Slave Wrapper Base address is set for 4364 Chip ID. + * Current address is 0x1810c000, Corrected the same to 0x1810e000. + * This ensures AXI default slave wrapper is registered along with + * other slave wrapper cores and is useful while generating trap info + * when write operation is tried on Invalid Core / Wrapper register + */ + + if ((CHIPID(sih->chip) == BCM4364_CHIP_ID) && + (cid == DEF_AI_COMP)) { + axi_wrapper[sii->axi_num_wrappers].wrapper_addr = + 0x1810e000; + } else { + axi_wrapper[sii->axi_num_wrappers].wrapper_addr = addrl; + } - SI_VMSG(("SLAVE WRAPPER: %d, mfg:%x, cid:%x, rev:%x, addr:%x, size:%x\n", - sii->axi_num_wrappers, mfg, cid, crev, addrl, sizel)); - } + sii->axi_num_wrappers++; + SI_VMSG(("SLAVE WRAPPER: %d, mfg:%x, cid:%x," + "rev:%x, addr:%x, size:%x\n", + sii->axi_num_wrappers, mfg, cid, crev, addrl, sizel)); + } + } #ifndef BCM_BACKPLANE_TIMEOUT /* Don't record bridges */ if (br) continue; -#endif +#endif // endif /* Done with core */ sii->numcores++; @@ -417,11 +459,11 @@ error: * Return the current core's virtual address. */ static volatile void * -_ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2) +_ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrapn) { si_info_t *sii = SI_INFO(sih); si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - uint32 addr, wrap, wrap2; + uint32 addr, wrap, wrap2, wrap3; volatile void *regs; if (coreidx >= MIN(sii->numcores, SI_MAXCORES)) @@ -430,6 +472,7 @@ _ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2) addr = cores_info->coresba[coreidx]; wrap = cores_info->wrapba[coreidx]; wrap2 = cores_info->wrapba2[coreidx]; + wrap3 = cores_info->wrapba3[coreidx]; #ifdef BCM_BACKPLANE_TIMEOUT /* No need to disable interrupts while entering/exiting APB bridge core */ @@ -462,10 +505,18 @@ _ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2) cores_info->wrappers2[coreidx] = REG_MAP(wrap2, SI_CORE_SIZE); ASSERT(GOODREGS(cores_info->wrappers2[coreidx])); } - if (use_wrap2) + if (!cores_info->wrappers3[coreidx] && (wrap3 != 0)) { + cores_info->wrappers3[coreidx] = REG_MAP(wrap3, SI_CORE_SIZE); + ASSERT(GOODREGS(cores_info->wrappers3[coreidx])); + } + + if (use_wrapn == 2) { + sii->curwrap = cores_info->wrappers3[coreidx]; + } else if (use_wrapn == 1) { sii->curwrap = cores_info->wrappers2[coreidx]; - else + } else { sii->curwrap = cores_info->wrappers[coreidx]; + } break; case PCI_BUS: @@ -482,7 +533,7 @@ _ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2) regs = sii->curmap; /* point bar0 2nd 4KB window to the primary wrapper */ - if (use_wrap2) + if (use_wrapn) wrap = wrap2; if (PCIE_GEN2(sii)) OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 4, wrap); @@ -494,7 +545,7 @@ _ai_setcoreidx(si_t *sih, uint coreidx, uint use_wrap2) case SPI_BUS: case SDIO_BUS: sii->curmap = regs = (void *)((uintptr)addr); - if (use_wrap2) + if (use_wrapn) sii->curwrap = (void *)((uintptr)wrap2); else sii->curwrap = (void *)((uintptr)wrap); @@ -526,6 +577,12 @@ ai_setcoreidx_2ndwrap(si_t *sih, uint coreidx) return _ai_setcoreidx(sih, coreidx, 1); } +volatile void * +ai_setcoreidx_3rdwrap(si_t *sih, uint coreidx) +{ + return _ai_setcoreidx(sih, coreidx, 2); +} + void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) { @@ -622,9 +679,14 @@ ai_numaddrspaces(si_t *sih) return 2; } -/* Return the address of the nth address space in the current core */ +/* Return the address of the nth address space in the current core + * Arguments: + * sih : Pointer to struct si_t + * spidx : slave port index + * baidx : base address index + */ uint32 -ai_addrspace(si_t *sih, uint asidx) +ai_addrspace(si_t *sih, uint spidx, uint baidx) { si_info_t *sii = SI_INFO(sih); si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; @@ -632,36 +694,53 @@ ai_addrspace(si_t *sih, uint asidx) cidx = sii->curidx; - if (asidx == 0) - return cores_info->coresba[cidx]; - else if (asidx == 1) - return cores_info->coresba2[cidx]; - else { - SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", - __FUNCTION__, asidx)); - return 0; + if (spidx == CORE_SLAVE_PORT_0) { + if (baidx == CORE_BASE_ADDR_0) + return cores_info->coresba[cidx]; + else if (baidx == CORE_BASE_ADDR_1) + return cores_info->coresba2[cidx]; + } + else if (spidx == CORE_SLAVE_PORT_1) { + if (baidx == CORE_BASE_ADDR_0) + return cores_info->csp2ba[cidx]; } + + SI_ERROR(("%s: Need to parse the erom again to find %d base addr in %d slave port\n", + __FUNCTION__, baidx, spidx)); + + return 0; + } -/* Return the size of the nth address space in the current core */ +/* Return the size of the nth address space in the current core +* Arguments: +* sih : Pointer to struct si_t +* spidx : slave port index +* baidx : base address index +*/ uint32 -ai_addrspacesize(si_t *sih, uint asidx) +ai_addrspacesize(si_t *sih, uint spidx, uint baidx) { si_info_t *sii = SI_INFO(sih); si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint cidx; cidx = sii->curidx; - - if (asidx == 0) - return cores_info->coresba_size[cidx]; - else if (asidx == 1) - return cores_info->coresba2_size[cidx]; - else { - SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", - __FUNCTION__, asidx)); - return 0; + if (spidx == CORE_SLAVE_PORT_0) { + if (baidx == CORE_BASE_ADDR_0) + return cores_info->coresba_size[cidx]; + else if (baidx == CORE_BASE_ADDR_1) + return cores_info->coresba2_size[cidx]; } + else if (spidx == CORE_SLAVE_PORT_1) { + if (baidx == CORE_BASE_ADDR_0) + return cores_info->csp2ba_size[cidx]; + } + + SI_ERROR(("%s: Need to parse the erom again to find %d base addr in %d slave port\n", + __FUNCTION__, baidx, spidx)); + + return 0; } uint @@ -670,10 +749,6 @@ ai_flag(si_t *sih) si_info_t *sii = SI_INFO(sih); aidmp_t *ai; - if (BCM5357_DMP()) { - 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__)); @@ -683,13 +758,6 @@ ai_flag(si_t *sih) SI_ERROR(("%s: Attempting to read DMP registers on 53573\n", __FUNCTION__)); return sii->curidx; } -#ifdef REROUTE_OOBINT - if (PMU_DMP()) { - SI_ERROR(("%s: Attempting to read PMU DMP registers\n", - __FUNCTION__)); - return PMU_OOB_BIT; - } -#else if (PMU_DMP()) { uint idx, flag; idx = sii->curidx; @@ -698,7 +766,6 @@ ai_flag(si_t *sih) ai_setcoreidx(sih, idx); return flag; } -#endif /* REROUTE_OOBINT */ ai = sii->curwrap; ASSERT(ai != NULL); @@ -712,22 +779,11 @@ ai_flag_alt(si_t *sih) si_info_t *sii = SI_INFO(sih); aidmp_t *ai; - if (BCM5357_DMP()) { - 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; } -#ifdef REROUTE_OOBINT - if (PMU_DMP()) { - SI_ERROR(("%s: Attempting to read PMU DMP registers\n", - __FUNCTION__)); - return PMU_OOB_BIT; - } -#endif /* REROUTE_OOBINT */ ai = sii->curwrap; @@ -746,16 +802,15 @@ uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val) { si_info_t *sii = SI_INFO(sih); - uint32 *map = (uint32 *) sii->curwrap; + uint32 *addr = (uint32 *) ((uchar *)(sii->curwrap) + offset); if (mask || val) { - uint32 w = R_REG(sii->osh, map+(offset/4)); + uint32 w = R_REG(sii->osh, addr); w &= ~mask; w |= val; - W_REG(sii->osh, map+(offset/4), w); + W_REG(sii->osh, addr, w); } - - return (R_REG(sii->osh, map+(offset/4))); + return (R_REG(sii->osh, addr)); } uint @@ -776,9 +831,15 @@ ai_corerev(si_t *sih) si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint32 cib; - cib = cores_info->cib[sii->curidx]; - return remap_corerev(sih, (cib & CIB_REV_MASK) >> CIB_REV_SHIFT); + return ((cib & CIB_REV_MASK) >> CIB_REV_SHIFT); +} + +uint +ai_corerev_minor(si_t *sih) +{ + return (ai_core_sflags(sih, 0, 0) >> SISF_MINORREV_D11_SHIFT) & + SISF_MINORREV_D11_MASK; } bool @@ -813,7 +874,6 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) si_info_t *sii = SI_INFO(sih); si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - ASSERT(GOODIDX(coreidx)); ASSERT(regoff < SI_CORE_SIZE); ASSERT((val & ~mask) == 0); @@ -905,7 +965,6 @@ ai_corereg_addr(si_t *sih, uint coreidx, uint regoff) si_info_t *sii = SI_INFO(sih); si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - ASSERT(GOODIDX(coreidx)); ASSERT(regoff < SI_CORE_SIZE); @@ -963,7 +1022,6 @@ ai_core_disable(si_t *sih, uint32 bits) uint32 status; aidmp_t *ai; - ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; @@ -1004,6 +1062,9 @@ static void _ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) { si_info_t *sii = SI_INFO(sih); +#if defined(UCM_CORRUPTION_WAR) + si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; +#endif // endif aidmp_t *ai; volatile uint32 dummy; uint loop_counter = 10; @@ -1011,12 +1072,9 @@ _ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; - /* if core is already out of reset, just return */ - /* ensure there are no pending backplane operations */ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); - /* put core into reset state */ W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); OSL_DELAY(10); @@ -1027,16 +1085,20 @@ _ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) W_REG(sii->osh, &ai->ioctrl, (bits | resetbits | SICF_FGC | SICF_CLOCK_EN)); dummy = R_REG(sii->osh, &ai->ioctrl); BCM_REFERENCE(dummy); - +#ifdef UCM_CORRUPTION_WAR + if (cores_info->coreid[sii->curidx] == D11_CORE_ID) { + /* Reset FGC */ + OSL_DELAY(1); + W_REG(sii->osh, &ai->ioctrl, (dummy & (~SICF_FGC))); + } +#endif /* UCM_CORRUPTION_WAR */ /* ensure there are no pending backplane operations */ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); - while (R_REG(sii->osh, &ai->resetctrl) != 0 && --loop_counter != 0) { /* ensure there are no pending backplane operations */ SPINWAIT(((dummy = R_REG(sii->osh, &ai->resetstatus)) != 0), 300); - /* take core out of reset */ W_REG(sii->osh, &ai->resetctrl, 0); @@ -1044,11 +1106,23 @@ _ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300); } - +#ifdef UCM_CORRUPTION_WAR + /* Pulse FGC after lifting Reset */ + W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); +#else W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); +#endif /* UCM_CORRUPTION_WAR */ dummy = R_REG(sii->osh, &ai->ioctrl); BCM_REFERENCE(dummy); +#ifdef UCM_CORRUPTION_WAR + if (cores_info->coreid[sii->curidx] == D11_CORE_ID) { + /* Reset FGC */ + OSL_DELAY(1); + W_REG(sii->osh, &ai->ioctrl, (dummy & (~SICF_FGC))); + } +#endif /* UCM_CORRUPTION_WAR */ OSL_DELAY(1); + } void @@ -1058,6 +1132,12 @@ ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint idx = sii->curidx; + if (cores_info->wrapba3[idx] != 0) { + ai_setcoreidx_3rdwrap(sih, idx); + _ai_core_reset(sih, bits, resetbits); + ai_setcoreidx(sih, idx); + } + if (cores_info->wrapba2[idx] != 0) { ai_setcoreidx_2ndwrap(sih, idx); _ai_core_reset(sih, bits, resetbits); @@ -1074,11 +1154,6 @@ ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) aidmp_t *ai; uint32 w; - if (BCM5357_DMP()) { - SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", - __FUNCTION__)); - return; - } if (BCM4707_DMP()) { SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", __FUNCTION__)); @@ -1108,11 +1183,6 @@ ai_core_cflags(si_t *sih, uint32 mask, uint32 val) aidmp_t *ai; uint32 w; - if (BCM5357_DMP()) { - SI_ERROR(("%s: Accessing USB20H DMP register (ioctrl) on 5357\n", - __FUNCTION__)); - return 0; - } if (BCM4707_DMP()) { SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", __FUNCTION__)); @@ -1144,11 +1214,6 @@ ai_core_sflags(si_t *sih, uint32 mask, uint32 val) aidmp_t *ai; uint32 w; - if (BCM5357_DMP()) { - SI_ERROR(("%s: Accessing USB20H DMP register (iostatus) on 5357\n", - __FUNCTION__)); - return 0; - } if (BCM4707_DMP()) { SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", __FUNCTION__)); @@ -1190,7 +1255,6 @@ ai_dumpregs(si_t *sih, struct bcmstrbuf *b) osh = sii->osh; - /* Save and restore wrapper access window */ if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { if (PCIE_GEN2(sii)) { @@ -1229,15 +1293,6 @@ ai_dumpregs(si_t *sih, struct bcmstrbuf *b) axi_wrapper[i].wrapper_type == AI_SLAVE_WRAPPER ? "SLAVE" : "MASTER", axi_wrapper[i].wrapper_addr); - /* BCM5357_DMP() */ - if (((CHIPID(sih->chip) == BCM5357_CHIP_ID) || - (CHIPID(sih->chip) == BCM4749_CHIP_ID)) && - (sih->chippkg == BCM5357_PKG_ID) && - (axi_wrapper[i].cid == USB20H_CORE_ID)) { - bcm_bprintf(b, "Skipping usb20h in 5357\n"); - continue; - } - /* BCM4707_DMP() */ if (BCM4707_CHIP(CHIPID(sih->chip)) && (axi_wrapper[i].cid == NS_CCB_CORE_ID)) { @@ -1276,22 +1331,24 @@ ai_dumpregs(si_t *sih, struct bcmstrbuf *b) } /* Restore the initial wrapper space */ - if (prev_value && cfg_reg) { - OSL_PCI_WRITE_CONFIG(osh, cfg_reg, 4, prev_value); + if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { + if (prev_value && cfg_reg) { + OSL_PCI_WRITE_CONFIG(osh, cfg_reg, 4, prev_value); + } } - } -#endif - +#endif // endif void -ai_enable_backplane_timeouts(si_t *sih) +ai_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout_exp, uint32 cid) { #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) si_info_t *sii = SI_INFO(sih); aidmp_t *ai; uint32 i; axi_wrapper_t * axi_wrapper = sii->axi_wrapper; + uint32 errlogctrl = (enable << AIELC_TO_ENAB_SHIFT) | + ((timeout_exp << AIELC_TO_EXP_SHIFT) & AIELC_TO_EXP_MASK); #ifdef BCM_BACKPLANE_TIMEOUT uint32 prev_value = 0; @@ -1322,7 +1379,7 @@ ai_enable_backplane_timeouts(si_t *sih) offset = PCIE2_BAR0_CORE2_WIN2_OFFSET; } else { - osl_panic("!PCIE_GEN1 && !PCIE_GEN2\n"); + ASSERT(!"!PCIE_GEN1 && !PCIE_GEN2"); } prev_value = OSL_PCI_READ_CONFIG(osh, cfg_reg, 4); @@ -1331,7 +1388,6 @@ ai_enable_backplane_timeouts(si_t *sih) return; } } - #endif /* BCM_BACKPLANE_TIMEOUT */ for (i = 0; i < sii->axi_num_wrappers; ++i) { @@ -1344,14 +1400,19 @@ ai_enable_backplane_timeouts(si_t *sih) continue; } + /* Update only given core if requested */ + if ((cid != 0) && (axi_wrapper[i].cid != cid)) { + continue; + } + #ifdef BCM_BACKPLANE_TIMEOUT if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { - /* Set BAR0_CORE2_WIN2 to wapper base address */ + /* Set BAR0_CORE2_WIN2 to bridge wapper base address */ OSL_PCI_WRITE_CONFIG(osh, cfg_reg, 4, axi_wrapper[i].wrapper_addr); /* set AI to BAR0 + Offset corresponding to Gen1 or gen2 */ - ai = (aidmp_t *) ((uint8*)sii->curmap + offset); + ai = (aidmp_t *) (DISCARD_QUAL(sii->curmap, uint8) + offset); } else #endif /* BCM_BACKPLANE_TIMEOUT */ @@ -1359,8 +1420,7 @@ ai_enable_backplane_timeouts(si_t *sih) ai = (aidmp_t *)(uintptr) axi_wrapper[i].wrapper_addr; } - W_REG(sii->osh, &ai->errlogctrl, (1 << AIELC_TO_ENAB_SHIFT) | - ((AXI_TO_VAL << AIELC_TO_EXP_SHIFT) & AIELC_TO_EXP_MASK)); + W_REG(sii->osh, &ai->errlogctrl, errlogctrl); SI_VMSG(("ENABLED BPT: MFG:%x, CID:%x, ADDR:%x, ERR_CTRL:%x\n", axi_wrapper[i].mfg, @@ -1385,9 +1445,17 @@ ai_enable_backplane_timeouts(si_t *sih) static uint32 si_ignore_errlog_cnt = 0; static bool -ai_ignore_errlog(si_info_t *sii, uint32 lo_addr, uint32 hi_addr, uint32 err_axi_id, uint32 errsts) +ai_ignore_errlog(si_info_t *sii, aidmp_t *ai, + uint32 lo_addr, uint32 hi_addr, uint32 err_axi_id, uint32 errsts) { uint32 axi_id; +#ifdef BCMPCIE_BTLOG + uint32 axi_id2 = BCM4347_UNUSED_AXI_ID; +#endif /* BCMPCIE_BTLOG */ + uint32 ignore_errsts = AIELS_SLAVE_ERR; + uint32 ignore_hi = BT_CC_SPROM_BADREG_HI; + uint32 ignore_lo = BT_CC_SPROM_BADREG_LO; + uint32 ignore_size = BT_CC_SPROM_BADREG_SIZE; /* ignore the BT slave errors if the errlog is to chipcommon addr 0x190 */ switch (CHIPID(sii->pub.chip)) { @@ -1397,22 +1465,55 @@ ai_ignore_errlog(si_info_t *sii, uint32 lo_addr, uint32 hi_addr, uint32 err_axi_ case BCM4345_CHIP_ID: axi_id = BCM4345_BT_AXI_ID; break; + case BCM4349_CHIP_GRPID: + axi_id = BCM4349_BT_AXI_ID; + break; + case BCM4364_CHIP_ID: + case BCM4373_CHIP_ID: + axi_id = BCM4364_BT_AXI_ID; + break; +#ifdef BCMPCIE_BTLOG + case BCM4347_CHIP_ID: + case BCM4357_CHIP_ID: + axi_id = BCM4347_CC_AXI_ID; + axi_id2 = BCM4347_PCIE_AXI_ID; + ignore_errsts = AIELS_TIMEOUT; + ignore_hi = BCM4347_BT_ADDR_HI; + ignore_lo = BCM4347_BT_ADDR_LO; + ignore_size = BCM4347_BT_SIZE; + break; +#endif /* BCMPCIE_BTLOG */ + default: return FALSE; } /* AXI ID check */ - if ((err_axi_id & AI_ERRLOGID_AXI_ID_MASK) != axi_id) + err_axi_id &= AI_ERRLOGID_AXI_ID_MASK; + if (!(err_axi_id == axi_id || +#ifdef BCMPCIE_BTLOG + (axi_id2 != BCM4347_UNUSED_AXI_ID && err_axi_id == axi_id2))) +#else + FALSE)) +#endif /* BCMPCIE_BTLOG */ return FALSE; /* slave errors */ - if ((errsts & AIELS_TIMEOUT_MASK) != AIELS_SLAVE_ERR) + if ((errsts & AIELS_TIMEOUT_MASK) != ignore_errsts) return FALSE; - /* chipc reg 0x190 */ - if ((hi_addr != BT_CC_SPROM_BADREG_HI) || (lo_addr != BT_CC_SPROM_BADREG_LO)) + /* address range check */ + if ((hi_addr != ignore_hi) || + (lo_addr < ignore_lo) || (lo_addr >= (ignore_lo + ignore_size))) return FALSE; +#ifdef BCMPCIE_BTLOG + if (ignore_errsts == AIELS_TIMEOUT) { + /* reset AXI timeout */ + ai_reset_axi_to(sii, ai); + } +#endif /* BCMPCIE_BTLOG */ + return TRUE; } #endif /* defined (AXI_TIMEOUTS) || defined (BCM_BACKPLANE_TIMEOUT) */ @@ -1420,7 +1521,7 @@ ai_ignore_errlog(si_info_t *sii, uint32 lo_addr, uint32 hi_addr, uint32 err_axi_ #ifdef BCM_BACKPLANE_TIMEOUT /* Function to return the APB bridge details corresponding to the core */ -bool +static bool ai_get_apb_bridge(si_t * sih, uint32 coreidx, uint32 *apb_id, uint32 * apb_coreuinit) { uint i; @@ -1470,14 +1571,15 @@ ai_get_apb_bridge(si_t * sih, uint32 coreidx, uint32 *apb_id, uint32 * apb_coreu } uint32 -ai_clear_backplane_to_fast(si_t *sih, void * addr) +ai_clear_backplane_to_fast(si_t *sih, void *addr) { si_info_t *sii = SI_INFO(sih); - void * curmap = sii->curmap; + volatile void *curmap = sii->curmap; bool core_reg = FALSE; /* Use fast path only for core register access */ - if ((addr >= curmap) && (addr < (curmap + SI_CORE_SIZE))) { + if (((uintptr)addr >= (uintptr)curmap) && + ((uintptr)addr < ((uintptr)curmap + SI_CORE_SIZE))) { /* address being accessed is within current core reg map */ core_reg = TRUE; } @@ -1501,6 +1603,14 @@ ai_clear_backplane_to_fast(si_t *sih, void * addr) #endif /* BCM_BACKPLANE_TIMEOUT */ #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) +static bool g_disable_backplane_logs = FALSE; + +#if defined(ETD) +static uint32 last_axi_error = AXI_WRAP_STS_NONE; +static uint32 last_axi_error_core = 0; +static uint32 last_axi_error_wrap = 0; +#endif /* ETD */ + /* * API to clear the back plane timeout per core. * Caller may passs optional wrapper address. If present this will be used as @@ -1510,7 +1620,7 @@ ai_clear_backplane_to_fast(si_t *sih, void * addr) * will be verified. */ uint32 -ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wrap) +ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void *wrap) { int ret = AXI_WRAP_STS_NONE; aidmp_t *ai = NULL; @@ -1521,7 +1631,8 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra uint32 target_coreidx = si_findcoreidx(sih, coreid, coreunit); #if defined(BCM_BACKPLANE_TIMEOUT) - si_axi_error_t * axi_error = &sih->err_info->axi_error[sih->err_info->count]; + si_axi_error_t * axi_error = sih->err_info ? + &sih->err_info->axi_error[sih->err_info->count] : NULL; #endif /* BCM_BACKPLANE_TIMEOUT */ bool restore_core = FALSE; @@ -1567,7 +1678,7 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra SI_PRINT(("%s, errlogstatus:%x - Slave Wrapper:%x\n", __FUNCTION__, errlog_status, coreid)); ret = AXI_WRAP_STS_WRAP_RD_ERR; - errlog_lo = (uint32)&ai->errlogstatus; + errlog_lo = (uint32)(uintptr)&ai->errlogstatus; goto end; } @@ -1584,7 +1695,7 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra SI_PRINT(("%s: prev errlogstatus:%x, errlogstatus:%x\n", __FUNCTION__, errlog_status, tmp)); ret = AXI_WRAP_STS_WRAP_RD_ERR; - errlog_lo = (uint32)&ai->errlogstatus; + errlog_lo = (uint32)(uintptr)&ai->errlogstatus; goto end; } /* @@ -1607,7 +1718,7 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra errlog_flags = R_REG(sii->osh, &ai->errlogflags); /* we are already in the error path, so OK to check for the slave error */ - if (ai_ignore_errlog(sii, errlog_lo, errlog_hi, errlog_id, + if (ai_ignore_errlog(sii, ai, errlog_lo, errlog_hi, errlog_id, errlog_status)) { si_ignore_errlog_cnt++; goto end; @@ -1616,25 +1727,17 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra /* only reset APB Bridge on timeout (not slave error, or dec error) */ switch (errlog_status & AIELS_TIMEOUT_MASK) { case AIELS_SLAVE_ERR: - SI_PRINT(("AXI slave error")); + SI_PRINT(("AXI slave error\n")); ret = AXI_WRAP_STS_SLAVE_ERR; break; case AIELS_TIMEOUT: - /* reset APB Bridge */ - OR_REG(sii->osh, &ai->resetctrl, AIRC_RESET); - /* sync write */ - (void)R_REG(sii->osh, &ai->resetctrl); - /* clear Reset bit */ - AND_REG(sii->osh, &ai->resetctrl, ~(AIRC_RESET)); - /* sync write */ - (void)R_REG(sii->osh, &ai->resetctrl); - SI_PRINT(("AXI timeout")); + ai_reset_axi_to(sii, ai); ret = AXI_WRAP_STS_TIMEOUT; break; case AIELS_DECODE: - SI_PRINT(("AXI decode error")); + SI_PRINT(("AXI decode error\n")); ret = AXI_WRAP_STS_DECODE_ERR; break; default: @@ -1649,6 +1752,13 @@ ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra } end: +#if defined(ETD) + if (ret != AXI_WRAP_STS_NONE) { + last_axi_error = ret; + last_axi_error_core = coreid; + last_axi_error_wrap = (uint32)ai; + } +#endif /* ETD */ #if defined(BCM_BACKPLANE_TIMEOUT) if (axi_error && (ret != AXI_WRAP_STS_NONE)) { @@ -1677,6 +1787,25 @@ end: return ret; } + +/* reset AXI timeout */ +static void +ai_reset_axi_to(si_info_t *sii, aidmp_t *ai) +{ + /* reset APB Bridge */ + OR_REG(sii->osh, &ai->resetctrl, AIRC_RESET); + /* sync write */ + (void)R_REG(sii->osh, &ai->resetctrl); + /* clear Reset bit */ + AND_REG(sii->osh, &ai->resetctrl, ~(AIRC_RESET)); + /* sync write */ + (void)R_REG(sii->osh, &ai->resetctrl); + SI_PRINT(("AXI timeout\n")); + if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) { + SI_PRINT(("reset failed on wrapper %p\n", ai)); + g_disable_backplane_logs = TRUE; + } +} #endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ /* @@ -1715,7 +1844,7 @@ ai_clear_backplane_to(si_t *sih) if ((sii->axi_num_wrappers == 0) || (!PCIE(sii))) #else if (sii->axi_num_wrappers == 0) -#endif +#endif // endif { SI_VMSG((" %s, axi_num_wrappers:%d, Is_PCIE:%d, BUS_TYPE:%d, ID:%x\n", __FUNCTION__, sii->axi_num_wrappers, PCIE(sii), @@ -1734,23 +1863,27 @@ ai_clear_backplane_to(si_t *sih) offset = PCIE2_BAR0_CORE2_WIN2_OFFSET; } else { - osl_panic("!PCIE_GEN1 && !PCIE_GEN2\n"); + ASSERT(!"!PCIE_GEN1 && !PCIE_GEN2"); } prev_value = OSL_PCI_READ_CONFIG(osh, cfg_reg, 4); if (prev_value == ID32_INVALID) { si_axi_error_t * axi_error = - &sih->err_info->axi_error[sih->err_info->count]; - SI_PRINT(("%s, PCI_BAR0_WIN2 - %x\n", __FUNCTION__, prev_value)); + sih->err_info ? + &sih->err_info->axi_error[sih->err_info->count] : + NULL; - axi_error->error = ret = AXI_WRAP_STS_PCI_RD_ERR; - axi_error->errlog_lo = cfg_reg; - sih->err_info->count++; - - if (sih->err_info->count == SI_MAX_ERRLOG_SIZE) { - sih->err_info->count = SI_MAX_ERRLOG_SIZE - 1; - SI_PRINT(("AXI Error log overflow\n")); + SI_PRINT(("%s, PCI_BAR0_WIN2 - %x\n", __FUNCTION__, prev_value)); + if (axi_error) { + axi_error->error = ret = AXI_WRAP_STS_PCI_RD_ERR; + axi_error->errlog_lo = cfg_reg; + sih->err_info->count++; + + if (sih->err_info->count == SI_MAX_ERRLOG_SIZE) { + sih->err_info->count = SI_MAX_ERRLOG_SIZE - 1; + SI_PRINT(("AXI Error log overflow\n")); + } } return ret; @@ -1766,14 +1899,13 @@ ai_clear_backplane_to(si_t *sih) } #ifdef BCM_BACKPLANE_TIMEOUT - if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { /* Set BAR0_CORE2_WIN2 to bridge wapper base address */ OSL_PCI_WRITE_CONFIG(osh, cfg_reg, 4, axi_wrapper[i].wrapper_addr); /* set AI to BAR0 + Offset corresponding to Gen1 or gen2 */ - ai = (aidmp_t *) ((uint8*)sii->curmap + offset); + ai = (aidmp_t *) (DISCARD_QUAL(sii->curmap, uint8) + offset); } else #endif /* BCM_BACKPLANE_TIMEOUT */ @@ -1781,7 +1913,8 @@ ai_clear_backplane_to(si_t *sih) ai = (aidmp_t *)(uintptr) axi_wrapper[i].wrapper_addr; } - tmp = ai_clear_backplane_to_per_core(sih, axi_wrapper[i].cid, 0, (void*)ai); + tmp = ai_clear_backplane_to_per_core(sih, axi_wrapper[i].cid, 0, + DISCARD_QUAL(ai, void)); ret |= tmp; } @@ -1808,3 +1941,66 @@ ai_num_slaveports(si_t *sih, uint coreidx) cib = cores_info->cib[coreidx]; return ((cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT); } + +#ifdef UART_TRAP_DBG +void +ai_dump_APB_Bridge_registers(si_t *sih) +{ +aidmp_t *ai; +si_info_t *sii = SI_INFO(sih); + + ai = (aidmp_t *) sii->br_wrapba[0]; + printf("APB Bridge 0\n"); + printf("lo 0x%08x, hi 0x%08x, id 0x%08x, flags 0x%08x", + R_REG(sii->osh, &ai->errlogaddrlo), + R_REG(sii->osh, &ai->errlogaddrhi), + R_REG(sii->osh, &ai->errlogid), + R_REG(sii->osh, &ai->errlogflags)); + printf("\n status 0x%08x\n", R_REG(sii->osh, &ai->errlogstatus)); +} +#endif /* UART_TRAP_DBG */ + +void +ai_force_clocks(si_t *sih, uint clock_state) +{ + + si_info_t *sii = SI_INFO(sih); + aidmp_t *ai, *ai_sec = NULL; + volatile uint32 dummy; + uint32 ioctrl; + si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; + + ASSERT(GOODREGS(sii->curwrap)); + ai = sii->curwrap; + if (cores_info->wrapba2[sii->curidx]) + ai_sec = REG_MAP(cores_info->wrapba2[sii->curidx], SI_CORE_SIZE); + + /* ensure there are no pending backplane operations */ + SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300); + + if (clock_state == FORCE_CLK_ON) { + ioctrl = R_REG(sii->osh, &ai->ioctrl); + W_REG(sii->osh, &ai->ioctrl, (ioctrl | SICF_FGC)); + dummy = R_REG(sii->osh, &ai->ioctrl); + BCM_REFERENCE(dummy); + if (ai_sec) { + ioctrl = R_REG(sii->osh, &ai_sec->ioctrl); + W_REG(sii->osh, &ai_sec->ioctrl, (ioctrl | SICF_FGC)); + dummy = R_REG(sii->osh, &ai_sec->ioctrl); + BCM_REFERENCE(dummy); + } + } else { + ioctrl = R_REG(sii->osh, &ai->ioctrl); + W_REG(sii->osh, &ai->ioctrl, (ioctrl & (~SICF_FGC))); + dummy = R_REG(sii->osh, &ai->ioctrl); + BCM_REFERENCE(dummy); + if (ai_sec) { + ioctrl = R_REG(sii->osh, &ai_sec->ioctrl); + W_REG(sii->osh, &ai_sec->ioctrl, (ioctrl & (~SICF_FGC))); + dummy = R_REG(sii->osh, &ai_sec->ioctrl); + BCM_REFERENCE(dummy); + } + } + /* ensure there are no pending backplane operations */ + SPINWAIT((R_REG(sii->osh, &ai->resetstatus) != 0), 300); +} diff --git a/drivers/net/wireless/bcmdhd_oo/bcm_app_utils.c b/drivers/net/wireless/bcmdhd_oo/bcm_app_utils.c index a5a7a5b23d3df54a0b5ff7c62c745a6efd847fa6..e88dcef0ae8b22a2e8cc1080028a76326719131e 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcm_app_utils.c +++ b/drivers/net/wireless/bcmdhd_oo/bcm_app_utils.c @@ -3,14 +3,14 @@ * Contents are wifi-specific, used by any kernel or app-level * software that might want wifi things as it grows. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,7 +26,7 @@ * * <> * - * $Id: bcm_app_utils.c 623866 2016-03-09 11:58:34Z $ + * $Id: bcm_app_utils.c 667243 2016-10-26 11:37:48Z $ */ #include @@ -42,13 +42,13 @@ #include #ifndef ASSERT #define ASSERT(exp) -#endif +#endif // endif #endif /* BCMDRIVER */ #include #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) #include /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */ -#endif +#endif // endif #include #include @@ -280,8 +280,8 @@ cca_analyze(cca_congest_channel_req_t *input[], int num_chans, uint flags, chans #define NUM_OF_CNT_IN_WL_CNT_VER_11_T \ ((sizeof(wl_cnt_ver_11_t) - 2 * sizeof(uint16)) / sizeof(uint32)) /* Exclude 64 macstat cnt variables. */ -#define NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T \ - (NUM_OF_CNT_IN_WL_CNT_VER_11_T - WL_CNT_MCST_VAR_NUM) +#define NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T \ + ((sizeof(wl_cnt_wlc_t)) / sizeof(uint32)) /* Index conversion table from wl_cnt_ver_6_t to wl_cnt_wlc_t */ static const uint8 wlcntver6t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T] = { @@ -411,6 +411,8 @@ static const uint8 wlcntver6t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_6_T] = { IDX_IN_WL_CNT_VER_6_T(wepexcluded_mcst) }; +#define INVALID_IDX ((uint8)(-1)) + /* Index conversion table from wl_cnt_ver_11_t to wl_cnt_wlc_t */ static const uint8 wlcntver11t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T] = { IDX_IN_WL_CNT_VER_11_T(txframe), @@ -594,7 +596,18 @@ static const uint8 wlcntver11t_to_wlcntwlct[NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T] = IDX_IN_WL_CNT_VER_11_T(ampdu_wds), IDX_IN_WL_CNT_VER_11_T(txlost), IDX_IN_WL_CNT_VER_11_T(txdatamcast), - IDX_IN_WL_CNT_VER_11_T(txdatabcast) + IDX_IN_WL_CNT_VER_11_T(txdatabcast), + INVALID_IDX, + IDX_IN_WL_CNT_VER_11_T(rxback), + IDX_IN_WL_CNT_VER_11_T(txback), + INVALID_IDX, + INVALID_IDX, + INVALID_IDX, + INVALID_IDX, + IDX_IN_WL_CNT_VER_11_T(txbcast), + IDX_IN_WL_CNT_VER_11_T(txdropped), + IDX_IN_WL_CNT_VER_11_T(rxbcast), + IDX_IN_WL_CNT_VER_11_T(rxdropped) }; /* Index conversion table from wl_cnt_ver_11_t to @@ -737,7 +750,6 @@ static const uint8 wlcntver11t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = { IDX_IN_WL_CNT_VER_11_T(bphy_badplcp) }; - /* Index conversion table from wl_cnt_ver_6_t to wl_cnt_v_le10_mcst_t */ static const uint8 wlcntver6t_to_wlcntvle10mcstt[WL_CNT_MCST_VAR_NUM] = { IDX_IN_WL_CNT_VER_6_T(txallfrm), @@ -831,8 +843,13 @@ wl_copy_wlccnt(uint16 cntver, uint32 *dst, uint32 *src, uint8 src_max_idx) } else { for (i = 0; i < NUM_OF_WLCCNT_IN_WL_CNT_VER_11_T; i++) { if (wlcntver11t_to_wlcntwlct[i] >= src_max_idx) { - /* src buffer does not have counters from here */ - break; + if (wlcntver11t_to_wlcntwlct[i] == INVALID_IDX) { + continue; + } + else { + /* src buffer does not have counters from here */ + break; + } } dst[i] = src[wlcntver11t_to_wlcntwlct[i]]; } @@ -904,7 +921,7 @@ wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev) uint16 mcst_xtlv_id; int res = BCME_OK; wl_cnt_info_t *cntinfo = cntbuf; - void *xtlvbuf_p = cntinfo->data; + uint8 *xtlvbuf_p = cntinfo->data; uint16 ver = cntinfo->version; uint16 xtlvbuflen = (uint16)buflen; uint16 src_max_idx; @@ -912,7 +929,7 @@ wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev) osl_t *osh = ctx; #else BCM_REFERENCE(ctx); -#endif +#endif // endif if (ver >= WL_CNT_VERSION_XTLV) { /* Already in xtlv format. */ @@ -925,7 +942,7 @@ wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, int buflen, uint32 corerev) #else wlccnt = (wl_cnt_wlc_t *)malloc(sizeof(*wlccnt)); macstat = (uint32 *)malloc(WL_CNT_MCST_STRUCT_SZ); -#endif +#endif // endif if (!wlccnt || !macstat) { printf("%s: malloc fail!\n", __FUNCTION__); res = BCME_NOMEM; @@ -1010,6 +1027,6 @@ exit: if (macstat) { free(macstat); } -#endif +#endif // endif return res; } diff --git a/drivers/net/wireless/bcmdhd_oo/bcmbloom.c b/drivers/net/wireless/bcmdhd_oo/bcmbloom.c new file mode 100644 index 0000000000000000000000000000000000000000..420a09be54c2c3d5828927ba3df4801d9271b2ab --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/bcmbloom.c @@ -0,0 +1,240 @@ +/* + * Bloom filter support + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: bcmbloom.c 714397 2017-08-04 08:24:38Z $ + */ + +#include +#include + +#include + +#ifdef BCMDRIVER +#include +#include +#else /* !BCMDRIVER */ +#include +#include +#ifndef ASSERT +#define ASSERT(exp) +#endif // endif +#endif /* !BCMDRIVER */ +#include + +#include + +#define BLOOM_BIT_LEN(_x) ((_x) << 3) + +struct bcm_bloom_filter { + void *cb_ctx; + uint max_hash; + bcm_bloom_hash_t *hash; /* array of hash functions */ + uint filter_size; /* in bytes */ + uint8 *filter; /* can be NULL for validate only */ +}; + +/* public interface */ +int +bcm_bloom_create(bcm_bloom_alloc_t alloc_cb, + bcm_bloom_free_t free_cb, void *cb_ctx, uint max_hash, + uint filter_size, bcm_bloom_filter_t **bloom) +{ + int err = BCME_OK; + bcm_bloom_filter_t *bp = NULL; + + if (!bloom || !alloc_cb || (max_hash == 0)) { + err = BCME_BADARG; + goto done; + } + + bp = (*alloc_cb)(cb_ctx, sizeof(*bp)); + if (!bp) { + err = BCME_NOMEM; + goto done; + } + + memset(bp, 0, sizeof(*bp)); + bp->cb_ctx = cb_ctx; + bp->max_hash = max_hash; + bp->hash = (*alloc_cb)(cb_ctx, sizeof(*bp->hash) * max_hash); + memset(bp->hash, 0, sizeof(*bp->hash) * max_hash); + + if (!bp->hash) { + err = BCME_NOMEM; + goto done; + } + + if (filter_size > 0) { + bp->filter = (*alloc_cb)(cb_ctx, filter_size); + if (!bp->filter) { + err = BCME_NOMEM; + goto done; + } + bp->filter_size = filter_size; + memset(bp->filter, 0, filter_size); + } + + *bloom = bp; + +done: + if (err != BCME_OK) + bcm_bloom_destroy(&bp, free_cb); + + return err; +} + +int +bcm_bloom_destroy(bcm_bloom_filter_t **bloom, bcm_bloom_free_t free_cb) +{ + int err = BCME_OK; + bcm_bloom_filter_t *bp; + + if (!bloom || !*bloom || !free_cb) + goto done; + + bp = *bloom; + *bloom = NULL; + + if (bp->filter) + (*free_cb)(bp->cb_ctx, bp->filter, bp->filter_size); + if (bp->hash) + (*free_cb)(bp->cb_ctx, bp->hash, + sizeof(*bp->hash) * bp->max_hash); + (*free_cb)(bp->cb_ctx, bp, sizeof(*bp)); + +done: + return err; +} + +int +bcm_bloom_add_hash(bcm_bloom_filter_t *bp, bcm_bloom_hash_t hash, uint *idx) +{ + uint i; + + if (!bp || !hash || !idx) + return BCME_BADARG; + + for (i = 0; i < bp->max_hash; ++i) { + if (bp->hash[i] == NULL) + break; + } + + if (i >= bp->max_hash) + return BCME_NORESOURCE; + + bp->hash[i] = hash; + *idx = i; + return BCME_OK; +} + +int +bcm_bloom_remove_hash(bcm_bloom_filter_t *bp, uint idx) +{ + if (!bp) + return BCME_BADARG; + + if (idx >= bp->max_hash) + return BCME_NOTFOUND; + + bp->hash[idx] = NULL; + return BCME_OK; +} + +bool +bcm_bloom_is_member(bcm_bloom_filter_t *bp, + const uint8 *tag, uint tag_len, const uint8 *buf, uint buf_len) +{ + uint i; + int err = BCME_OK; + + if (!tag || (tag_len == 0)) /* empty tag is always a member */ + goto done; + + /* use internal buffer if none was specified */ + if (!buf || (buf_len == 0)) { + if (!bp->filter) /* every one is a member of empty filter */ + goto done; + + buf = bp->filter; + buf_len = bp->filter_size; + } + + for (i = 0; i < bp->max_hash; ++i) { + uint pos; + if (!bp->hash[i]) + continue; + pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len); + + /* all bits must be set for a match */ + if (isclr(buf, pos % BLOOM_BIT_LEN(buf_len))) { + err = BCME_NOTFOUND; + break; + } + } + +done: + return err; +} + +int +bcm_bloom_add_member(bcm_bloom_filter_t *bp, const uint8 *tag, uint tag_len) +{ + uint i; + + if (!bp || !tag || (tag_len == 0)) + return BCME_BADARG; + + if (!bp->filter) /* validate only */ + return BCME_UNSUPPORTED; + + for (i = 0; i < bp->max_hash; ++i) { + uint pos; + if (!bp->hash[i]) + continue; + pos = (*bp->hash[i])(bp->cb_ctx, i, tag, tag_len); + setbit(bp->filter, pos % BLOOM_BIT_LEN(bp->filter_size)); + } + + return BCME_OK; +} + +int bcm_bloom_get_filter_data(bcm_bloom_filter_t *bp, + uint buf_size, uint8 *buf, uint *buf_len) +{ + if (!bp) + return BCME_BADARG; + + if (buf_len) + *buf_len = bp->filter_size; + + if (buf_size < bp->filter_size) + return BCME_BUFTOOSHORT; + + if (bp->filter && bp->filter_size) + memcpy(buf, bp->filter, bp->filter_size); + + return BCME_OK; +} diff --git a/drivers/net/wireless/bcmdhd_oo/bcmevent.c b/drivers/net/wireless/bcmdhd_oo/bcmevent.c index be982ce04aeb9e17d571980d27a2cff646e1f6a9..0f32c95503ec33574610e9ae08ddda665d2a353b 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmevent.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmevent.c @@ -1,14 +1,14 @@ /* * bcmevent read-only data shared by kernel or app layers * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmevent.c 707287 2017-06-27 06:44:29Z $ + * $Id: bcmevent.c 739966 2018-01-10 09:01:47Z $ */ #include @@ -101,10 +101,9 @@ static const bcmevent_name_str_t bcmevent_names[] = { BCMEVENT_NAME(WLC_E_IF), #ifdef WLP2P BCMEVENT_NAME(WLC_E_P2P_DISC_LISTEN_COMPLETE), -#endif +#endif // endif BCMEVENT_NAME(WLC_E_RSSI), BCMEVENT_NAME(WLC_E_PFN_SCAN_COMPLETE), - BCMEVENT_NAME(WLC_E_EXTLOG_MSG), BCMEVENT_NAME(WLC_E_ACTION_FRAME), BCMEVENT_NAME(WLC_E_ACTION_FRAME_RX), BCMEVENT_NAME(WLC_E_ACTION_FRAME_COMPLETE), @@ -117,10 +116,10 @@ static const bcmevent_name_str_t bcmevent_names[] = { #ifdef WLP2P BCMEVENT_NAME(WLC_E_PROBRESP_MSG), BCMEVENT_NAME(WLC_E_P2P_PROBREQ_MSG), -#endif +#endif // endif #ifdef PROP_TXSTATUS BCMEVENT_NAME(WLC_E_FIFO_CREDIT_MAP), -#endif +#endif // endif BCMEVENT_NAME(WLC_E_WAKE_EVENT), BCMEVENT_NAME(WLC_E_DCS_REQUEST), BCMEVENT_NAME(WLC_E_RM_COMPLETE), @@ -131,7 +130,7 @@ static const bcmevent_name_str_t bcmevent_names[] = { BCMEVENT_NAME(WLC_E_PFN_SCAN_ALLGONE), #ifdef SOFTAP BCMEVENT_NAME(WLC_E_GTK_PLUMBED), -#endif +#endif // endif BCMEVENT_NAME(WLC_E_ASSOC_REQ_IE), BCMEVENT_NAME(WLC_E_ASSOC_RESP_IE), BCMEVENT_NAME(WLC_E_BEACON_FRAME_RX), @@ -152,12 +151,12 @@ static const bcmevent_name_str_t bcmevent_names[] = { #endif /* WLWNM */ #if defined(WL_PROXDETECT) BCMEVENT_NAME(WLC_E_PROXD), -#endif +#endif // endif BCMEVENT_NAME(WLC_E_CCA_CHAN_QUAL), BCMEVENT_NAME(WLC_E_BSSID), #ifdef PROP_TXSTATUS BCMEVENT_NAME(WLC_E_BCMC_CREDIT_SUPPORT), -#endif +#endif // endif BCMEVENT_NAME(WLC_E_PSTA_PRIMARY_INTF_IND), BCMEVENT_NAME(WLC_E_TXFAIL_THRESH), #ifdef WLAIBSS @@ -169,12 +168,12 @@ static const bcmevent_name_str_t bcmevent_names[] = { #endif /* GSCAN_SUPPORT */ #ifdef WLBSSLOAD_REPORT BCMEVENT_NAME(WLC_E_BSS_LOAD), -#endif +#endif // endif #if defined(BT_WIFI_HANDOVER) || defined(WL_TBOW) BCMEVENT_NAME(WLC_E_BT_WIFI_HANDOVER_REQ), -#endif +#endif // endif #ifdef WLFBT - BCMEVENT_NAME(WLC_E_FBT_AUTH_REQ_IND), + BCMEVENT_NAME(WLC_E_FBT), #endif /* WLFBT */ BCMEVENT_NAME(WLC_E_AUTHORIZED), BCMEVENT_NAME(WLC_E_PROBREQ_MSG_RX), @@ -186,11 +185,17 @@ static const bcmevent_name_str_t bcmevent_names[] = { BCMEVENT_NAME(WLC_E_ALLOW_CREDIT_BORROW), BCMEVENT_NAME(WLC_E_MSCH), BCMEVENT_NAME(WLC_E_ULP), + BCMEVENT_NAME(WLC_E_NAN), + BCMEVENT_NAME(WLC_E_PKT_FILTER), + BCMEVENT_NAME(WLC_E_DMA_TXFLUSH_COMPLETE), BCMEVENT_NAME(WLC_E_PSK_AUTH), BCMEVENT_NAME(WLC_E_SDB_TRANSITION), + BCMEVENT_NAME(WLC_E_PFN_SCAN_BACKOFF), + BCMEVENT_NAME(WLC_E_PFN_BSSID_SCAN_BACKOFF), + BCMEVENT_NAME(WLC_E_AGGR_EVENT), + BCMEVENT_NAME(WLC_E_TVPM_MITIGATION), }; - const char *bcmevent_get_name(uint event_type) { /* note: first coded this as a static const but some @@ -372,7 +377,7 @@ is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, #else err = BCME_UNSUPPORTED; break; -#endif +#endif // endif default: err = BCME_NOTFOUND; diff --git a/drivers/net/wireless/bcmdhd_oo/bcmsdh.c b/drivers/net/wireless/bcmdhd_oo/bcmsdh.c index eae09abf79b8a36baf675734711ea528e955ec08..2e058a409d13eeae7c1df518e178b2d9141689c3 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmsdh.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmsdh.c @@ -2,14 +2,14 @@ * BCMSDH interface glue * implement bcmsdh API for SDIOH driver * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: bcmsdh.c 671319 2016-11-21 14:27:29Z $ + * $Id: bcmsdh.c 727623 2017-10-21 01:00:32Z $ */ /** @@ -64,7 +64,6 @@ static dhd_hang_notification process_dhd_hang_notification = NULL; static dhd_hang_state_t g_dhd_hang_state = NO_HANG_STATE; #endif /* defined (BT_OVER_SDIO) */ - #if defined(OOB_INTR_ONLY) && defined(HW_OOB) extern int sdioh_enable_hw_oob_intr(void *sdioh, bool enable); @@ -74,7 +73,7 @@ bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable) { sdioh_enable_hw_oob_intr(sdh->sdioh, enable); } -#endif +#endif // endif #if defined(BT_OVER_SDIO) void bcmsdh_btsdio_process_hang_state(dhd_hang_state_t new_state) @@ -97,6 +96,7 @@ void bcmsdh_btsdio_process_hang_state(dhd_hang_state_t new_state) if (HANG_RECOVERY_STATE == new_state || NO_HANG_STATE == new_state) state_change = true; + break; case HANG_RECOVERY_STATE: @@ -173,12 +173,12 @@ bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva) bcmsdh->sdioh = sdioh; bcmsdh->osh = osh; bcmsdh->init_success = TRUE; - *regsva = SI_ENUM_BASE; + *regsva = si_enum_base(0); bcmsdh_force_sbwad_calc(bcmsdh, FALSE); /* Report the BAR, to fix if needed */ - bcmsdh->sbwad = SI_ENUM_BASE; + bcmsdh->sbwad = si_enum_base(0); /* save the handler locally */ l_bcmsdh = bcmsdh; @@ -202,7 +202,7 @@ bcmsdh_detach(osl_t *osh, void *sdh) int bcmsdh_iovar_op(void *sdh, const char *name, - void *params, int plen, void *arg, int len, bool set) + void *params, uint plen, void *arg, uint len, bool set) { bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set); @@ -300,8 +300,7 @@ bcmsdh_intr_pending(void *sdh) ASSERT(sdh); return sdioh_interrupt_pending(bcmsdh->sdioh); } -#endif - +#endif // endif int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) @@ -327,7 +326,7 @@ bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err) SDIOH_API_RC status; #ifdef SDIOH_API_ACCESS_RETRY_LIMIT int32 retry = 0; -#endif +#endif // endif uint8 data = 0; if (!bcmsdh) @@ -339,11 +338,11 @@ bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err) do { if (retry) /* wait for 1 ms till bus get settled down */ OSL_DELAY(1000); -#endif +#endif // endif status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); #ifdef SDIOH_API_ACCESS_RETRY_LIMIT } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -#endif +#endif // endif if (err) *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); @@ -360,7 +359,7 @@ bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err) SDIOH_API_RC status; #ifdef SDIOH_API_ACCESS_RETRY_LIMIT int32 retry = 0; -#endif +#endif // endif if (!bcmsdh) bcmsdh = l_bcmsdh; @@ -371,11 +370,11 @@ bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err) do { if (retry) /* wait for 1 ms till bus get settled down */ OSL_DELAY(1000); -#endif +#endif // endif status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); #ifdef SDIOH_API_ACCESS_RETRY_LIMIT } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -#endif +#endif // endif if (err) *err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR; @@ -428,7 +427,6 @@ bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *er addr, data)); } - int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length) { @@ -468,7 +466,6 @@ bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length) return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); } - int bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address, bool force_set) { @@ -816,7 +813,7 @@ bcmsdh_sleep(void *sdh, bool enab) return sdioh_sleep(sd, enab); #else return BCME_UNSUPPORTED; -#endif +#endif // endif } int diff --git a/drivers/net/wireless/bcmdhd_oo/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd_oo/bcmsdh_linux.c index ce05e4475f7616b440c827609731a77d9cce5c72..62af0c610dcd6ea785b22ed83cbf3997ef54a110 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmsdh_linux.c @@ -1,14 +1,14 @@ /* * SDIO access interface for drivers - linux specific (pci only) * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmsdh_linux.c 672609 2016-11-29 07:00:46Z $ + * $Id: bcmsdh_linux.c 689948 2017-03-14 05:21:03Z $ */ /** @@ -289,7 +289,7 @@ bcmsdh_unregister(void) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) if (bcmsdh_pci_driver.node.next == NULL) return; -#endif +#endif // endif bcmsdh_unregister_client_driver(); } @@ -457,7 +457,7 @@ module_param(sd_delay_value, uint, 0); extern char dhd_sdiod_uhsi_ds_override[2]; module_param_string(dhd_sdiod_uhsi_ds_override, dhd_sdiod_uhsi_ds_override, 2, 0); -#endif +#endif // endif #ifdef BCMSDH_MODULE EXPORT_SYMBOL(bcmsdh_attach); @@ -470,7 +470,7 @@ EXPORT_SYMBOL(bcmsdh_intr_dereg); #if defined(DHD_DEBUG) EXPORT_SYMBOL(bcmsdh_intr_pending); -#endif +#endif // endif #if defined(BT_OVER_SDIO) EXPORT_SYMBOL(bcmsdh_btsdio_interface_init); diff --git a/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc.c index b7fac58e7b71f2f597e65df843a8e3b85fc660dc..be7d656c8643e371b4f6829f3fd9c37c7d5b630f 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc.c @@ -1,14 +1,14 @@ /* * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmsdh_sdmmc.c 731653 2017-11-14 03:29:19Z $ + * $Id: bcmsdh_sdmmc.c 709805 2017-07-10 17:48:19Z $ */ #include @@ -58,27 +58,6 @@ mmc_host_clk_release(struct mmc_host *host) #else #include #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 0)) */ - -#ifdef CONFIG_SOC_EXYNOS7885 -void -mmc_host_clk_hold(struct mmc_host *host) -{ - BCM_REFERENCE(host); - return; -} -void -mmc_host_clk_release(struct mmc_host *host) -{ - BCM_REFERENCE(host); - return; -} -unsigned int -mmc_host_clk_rate(struct mmc_host *host) -{ - return host->ios.clock; -} -#endif /* CONFIG_SOC_EXYNOS7885 */ - #include #include #include @@ -90,7 +69,7 @@ mmc_host_clk_rate(struct mmc_host *host) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) #include extern volatile bool dhd_mmc_suspend; -#endif +#endif // endif #include "bcmsdh_sdmmc.h" #ifndef BCMSDH_MODULE @@ -108,12 +87,12 @@ extern int sdio_reset_comm(struct mmc_card *card); #define DEFAULT_SDIO_F2_BLKSIZE 512 #ifndef CUSTOM_SDIO_F2_BLKSIZE #define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE -#endif +#endif // endif #define DEFAULT_SDIO_F1_BLKSIZE 64 #ifndef CUSTOM_SDIO_F1_BLKSIZE #define CUSTOM_SDIO_F1_BLKSIZE DEFAULT_SDIO_F1_BLKSIZE -#endif +#endif // endif #define MAX_IO_RW_EXTENDED_BLK 511 @@ -135,7 +114,7 @@ uint sd_use_dma = TRUE; #ifndef CUSTOM_RXCHAIN #define CUSTOM_RXCHAIN 0 -#endif +#endif // endif DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); @@ -147,9 +126,6 @@ DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); -void sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz); -uint sdmmc_get_clock_rate(sdioh_info_t *sd); -void sdmmc_set_clock_divisor(sdioh_info_t *sd, uint sd_div); #if defined(BT_OVER_SDIO) extern void sdioh_sdmmc_card_enable_func_f3(sdioh_info_t *sd, struct sdio_func *func) @@ -159,6 +135,10 @@ void sdioh_sdmmc_card_enable_func_f3(sdioh_info_t *sd, struct sdio_func *func) } #endif /* defined (BT_OVER_SDIO) */ +void sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz); +uint sdmmc_get_clock_rate(sdioh_info_t *sd); +void sdmmc_set_clock_divisor(sdioh_info_t *sd, uint sd_div); + static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) { @@ -269,7 +249,6 @@ fail: return NULL; } - extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *sd) { @@ -357,7 +336,7 @@ sdioh_disable_func_intr(sdioh_info_t *sd) reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); #if defined(BT_OVER_SDIO) reg &= ~INTR_CTL_FUNC3_EN; -#endif +#endif // endif /* Disable master interrupt with the last function interrupt */ if (!(reg & 0xFE)) reg = 0; @@ -450,7 +429,7 @@ sdioh_interrupt_pending(sdioh_info_t *sd) { return (0); } -#endif +#endif // endif uint sdioh_query_iofnum(sdioh_info_t *sd) @@ -809,7 +788,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by int err_ret = 0; #if defined(MMC_SDIO_ABORT) int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; -#endif +#endif // endif sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); @@ -960,7 +939,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add int err_ret = SDIOH_API_RC_FAIL; #if defined(MMC_SDIO_ABORT) int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; -#endif +#endif // endif if (func == 0) { sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); @@ -1193,7 +1172,6 @@ sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func, return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); } - /* * This function takes a buffer or packet, and fixes everything up so that in the * end, a DMA-able packet is created. @@ -1320,7 +1298,6 @@ sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize if (sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize)) { return BCME_SDIO_ERROR; } - if (regsize == 2) *data &= 0xffff; @@ -1469,7 +1446,7 @@ sdioh_start(sdioh_info_t *sd, int stage) #else /* defined(OOB_INTR_ONLY) */ #if defined(HW_OOB) sdioh_enable_func_intr(sd); -#endif +#endif // endif bcmsdh_oob_intr_set(sd->bcmsdh, TRUE); #endif /* !defined(OOB_INTR_ONLY) */ } @@ -1500,7 +1477,7 @@ sdioh_stop(sdioh_info_t *sd) #else /* defined(OOB_INTR_ONLY) */ #if defined(HW_OOB) sdioh_disable_func_intr(sd); -#endif +#endif // endif bcmsdh_oob_intr_set(sd->bcmsdh, FALSE); #endif /* !defined(OOB_INTR_ONLY) */ } @@ -1515,7 +1492,6 @@ sdioh_waitlockfree(sdioh_info_t *sd) return (1); } - SDIOH_API_RC sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio) { @@ -1548,7 +1524,6 @@ sdmmc_get_clock_rate(sdioh_info_t *sd) return mmc_host_clk_rate(host); } - void sdmmc_set_clock_rate(sdioh_info_t *sd, uint hz) { diff --git a/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc_linux.c index 0563c47a93fc70274e711cd72229e066db98ee92..35c846a3b13ba39066565a4a55121682603cf72d 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmsdh_sdmmc_linux.c @@ -1,14 +1,14 @@ /* * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmsdh_sdmmc_linux.c 644124 2016-06-17 07:59:34Z $ + * $Id: bcmsdh_sdmmc_linux.c 689795 2017-03-13 14:57:21Z $ */ #include @@ -50,31 +50,6 @@ #define SDIO_DEVICE_ID_BROADCOM_DEFAULT 0x0000 -#if !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) -#define SDIO_DEVICE_ID_BROADCOM_4325_SDGWB 0x0492 /* BCM94325SDGWB */ -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4325) -#define SDIO_DEVICE_ID_BROADCOM_4325 0x0493 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4329) -#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4319) -#define SDIO_DEVICE_ID_BROADCOM_4319 0x4319 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4319) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4330) -#define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4334) -#define SDIO_DEVICE_ID_BROADCOM_4334 0x4334 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4334) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4324) -#define SDIO_DEVICE_ID_BROADCOM_4324 0x4324 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4324) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_43239) -#define SDIO_DEVICE_ID_BROADCOM_43239 43239 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_43239) */ - extern void wl_cfg80211_set_parent_dev(void *dev); extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); @@ -116,7 +91,7 @@ static int sdioh_probe(struct sdio_func *func) #ifdef WL_CFG80211 wl_cfg80211_set_parent_dev(&func->dev); -#endif +#endif // endif /* allocate SDIO Host Controller state info */ osh = osl_attach(&func->dev, SDIO_BUS, TRUE); @@ -205,14 +180,6 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func) /* devices we support, null terminated */ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_DEFAULT) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325_SDGWB) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4319) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4324) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43239) }, { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, { 0, 0, 0, 0 /* end: all zeroes */ }, diff --git a/drivers/net/wireless/bcmdhd_oo/bcmutils.c b/drivers/net/wireless/bcmdhd_oo/bcmutils.c index ca5428bd8f67101b17ef8c9905ab0a3b0ca0acca..19adcbde6dfbb83c18490b98899b203d1d92873f 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmutils.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmutils.c @@ -1,14 +1,14 @@ /* * Driver O/S-independent utility routines * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmutils.c 699163 2017-05-12 05:18:23Z $ + * $Id: bcmutils.c 735061 2017-12-07 06:01:20Z $ */ #include @@ -32,7 +32,6 @@ #include #include #ifdef BCMDRIVER - #include #include @@ -40,18 +39,26 @@ #include #include +#include #include #if defined(BCMEXTSUP) #include -#endif +#endif // endif #ifndef ASSERT #define ASSERT(exp) -#endif +#endif // endif #endif /* !BCMDRIVER */ +#ifdef WL_UNITTEST +#ifdef ASSERT +#undef ASSERT +#endif /* ASSERT */ +#define ASSERT(exp) +#endif /* WL_UNITTEST */ + #include #include #include @@ -63,49 +70,60 @@ #include #include -/* Look-up table to calculate head room present in a number */ -static const uint8 msb_table[] = { - 0, 1, 2, 2, 3, 3, 3, 3, - 4, 4, 4, 4, 4, 4, 4, 4, - 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, -}; +#ifdef BCMDRIVER -void *_bcmutils_dummy_fn = NULL; +/* return total length of buffer chain */ +uint BCMFASTPATH +pkttotlen(osl_t *osh, void *p) +{ + uint total; + int len; + + total = 0; + for (; p; p = PKTNEXT(osh, p)) { + len = PKTLEN(osh, p); + total += len; +#ifdef BCMLFRAG + if (BCMLFRAG_ENAB()) { + if (PKTISFRAG(osh, p)) { + total += PKTFRAGTOTLEN(osh, p); + } + } +#endif // endif + } + + return (total); +} +/* return the last buffer of chained pkt */ +void * +pktlast(osl_t *osh, void *p) +{ + for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) + ; + return (p); +} +/* count segments of a chained packet */ +uint BCMFASTPATH +pktsegcnt(osl_t *osh, void *p) +{ + uint cnt; -#ifdef BCMDRIVER + for (cnt = 0; p; p = PKTNEXT(osh, p)) { + cnt++; +#ifdef BCMLFRAG + if (BCMLFRAG_ENAB()) { + if (PKTISFRAG(osh, p)) { + cnt += PKTFRAGTOTNUM(osh, p); + } + } +#endif // endif + } + return cnt; +} /* copy a pkt buffer chain into a buffer */ uint @@ -145,7 +163,6 @@ pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) { uint n, ret = 0; - /* skip 'offset' bytes */ for (; p && offset; p = PKTNEXT(osh, p)) { if (offset < (uint)PKTLEN(osh, p)) @@ -169,92 +186,6 @@ pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) return ret; } - - -/* return total length of buffer chain */ -uint BCMFASTPATH -pkttotlen(osl_t *osh, void *p) -{ - uint total; - int len; - - total = 0; - for (; p; p = PKTNEXT(osh, p)) { - len = PKTLEN(osh, p); - total += len; -#ifdef BCMLFRAG - if (BCMLFRAG_ENAB()) { - if (PKTISFRAG(osh, p)) { - total += PKTFRAGTOTLEN(osh, p); - } - } -#endif - } - - return (total); -} - -/* return the last buffer of chained pkt */ -void * -pktlast(osl_t *osh, void *p) -{ - for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) - ; - - return (p); -} - -/* count segments of a chained packet */ -uint BCMFASTPATH -pktsegcnt(osl_t *osh, void *p) -{ - uint cnt; - - for (cnt = 0; p; p = PKTNEXT(osh, p)) { - cnt++; -#ifdef BCMLFRAG - if (BCMLFRAG_ENAB()) { - if (PKTISFRAG(osh, p)) { - cnt += PKTFRAGTOTNUM(osh, p); - } - } -#endif - } - - return cnt; -} - - -/* count segments of a chained packet */ -uint BCMFASTPATH -pktsegcnt_war(osl_t *osh, void *p) -{ - uint cnt; - uint8 *pktdata; - uint len, remain, align64; - - for (cnt = 0; p; p = PKTNEXT(osh, p)) { - cnt++; - len = PKTLEN(osh, p); - if (len > 128) { - pktdata = (uint8 *)PKTDATA(osh, p); /* starting address of data */ - /* Check for page boundary straddle (2048B) */ - if (((uintptr)pktdata & ~0x7ff) != ((uintptr)(pktdata+len) & ~0x7ff)) - cnt++; - - align64 = (uint)((uintptr)pktdata & 0x3f); /* aligned to 64B */ - align64 = (64 - align64) & 0x3f; - len -= align64; /* bytes from aligned 64B to end */ - /* if aligned to 128B, check for MOD 128 between 1 to 4B */ - remain = len % 128; - if (remain > 0 && remain <= 4) - cnt++; /* add extra seg */ - } - } - - return cnt; -} - uint8 * BCMFASTPATH pktdataoffset(osl_t *osh, void *p, uint offset) { @@ -275,7 +206,6 @@ pktdataoffset(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) @@ -294,3535 +224,3400 @@ pktoffset(osl_t *osh, void *p, uint offset) return p; } -#endif /* BCMDRIVER */ - -#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) -const unsigned char bcm_ctype[] = { +void +bcm_mdelay(uint ms) +{ + uint i; - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ - _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, - _BCM_C, /* 8-15 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ - _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ - _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ - _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ - _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ - _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, - _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ - _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, - _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ - _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ -}; + for (i = 0; i < ms; i++) { + OSL_DELAY(1000); + } +} -ulong -bcm_strtoul(const char *cp, char **endp, uint base) +#if defined(DHD_DEBUG) +/* pretty hex print a pkt buffer chain */ +void +prpkt(const char *msg, osl_t *osh, void *p0) { - ulong result, last_result = 0, value; - bool minus; - - minus = FALSE; + void *p; - while (bcm_isspace(*cp)) - cp++; + if (msg && (msg[0] != '\0')) + printf("%s:\n", msg); - if (cp[0] == '+') - cp++; - else if (cp[0] == '-') { - minus = TRUE; - cp++; - } + for (p = p0; p; p = PKTNEXT(osh, p)) + prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); +} +#endif // endif - if (base == 0) { - if (cp[0] == '0') { - if ((cp[1] == 'x') || (cp[1] == 'X')) { - base = 16; - cp = &cp[2]; - } else { - base = 8; - cp = &cp[1]; - } - } else - base = 10; - } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { - cp = &cp[2]; - } +/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. + * Also updates the inplace vlan tag if requested. + * For debugging, it returns an indication of what it did. + */ +uint BCMFASTPATH +pktsetprio(void *pkt, bool update_vtag) +{ + struct ether_header *eh; + struct ethervlan_header *evh; + uint8 *pktdata; + int priority = 0; + int rc = 0; - result = 0; + pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt); + ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); - while (bcm_isxdigit(*cp) && - (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { - result = result*base + value; - /* Detected overflow */ - if (result < last_result && !minus) { - if (endp) { - /* Go to the end of current number */ - while (bcm_isxdigit(*cp)) { - cp++; - } - *endp = DISCARD_QUAL(cp, char); - } - return (ulong)-1; - } - last_result = result; - cp++; - } + eh = (struct ether_header *) pktdata; - if (minus) - result = (ulong)(-(long)result); + if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { + uint16 vlan_tag; + int vlan_prio, dscp_prio = 0; - if (endp) - *endp = DISCARD_QUAL(cp, char); + evh = (struct ethervlan_header *)eh; - return (result); -} + vlan_tag = ntoh16(evh->vlan_tag); + vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; -int -bcm_atoi(const char *s) -{ - return (int)bcm_strtoul(s, NULL, 10); -} - -/* return pointer to location of substring 'needle' in 'haystack' */ -char * -bcmstrstr(const char *haystack, const char *needle) -{ - int len, nlen; - int i; - - if ((haystack == NULL) || (needle == NULL)) - return DISCARD_QUAL(haystack, char); - - nlen = (int)strlen(needle); - len = (int)strlen(haystack) - nlen + 1; + if ((evh->ether_type == hton16(ETHER_TYPE_IP)) || + (evh->ether_type == hton16(ETHER_TYPE_IPV6))) { + uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); + uint8 tos_tc = IP_TOS46(ip_body); + dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); + } - for (i = 0; i < len; i++) - if (memcmp(needle, &haystack[i], nlen) == 0) - return DISCARD_QUAL(&haystack[i], char); - return (NULL); -} + /* DSCP priority gets precedence over 802.1P (vlan tag) */ + if (dscp_prio != 0) { + priority = dscp_prio; + rc |= PKTPRIO_VDSCP; + } else { + priority = vlan_prio; + rc |= PKTPRIO_VLAN; + } + /* + * If the DSCP priority is not the same as the VLAN priority, + * then overwrite the priority field in the vlan tag, with the + * DSCP priority value. This is required for Linux APs because + * the VLAN driver on Linux, overwrites the skb->priority field + * with the priority value in the vlan tag + */ + if (update_vtag && (priority != vlan_prio)) { + vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); + vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; + evh->vlan_tag = hton16(vlan_tag); + rc |= PKTPRIO_UPD; + } +#if defined(EAPOL_PKT_PRIO) || defined(DHD_LOSSLESS_ROAMING) + } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) { + priority = PRIO_8021D_NC; + rc = PKTPRIO_DSCP; +#endif /* EAPOL_PKT_PRIO || DHD_LOSSLESS_ROAMING */ + } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) || + (eh->ether_type == hton16(ETHER_TYPE_IPV6))) { + uint8 *ip_body = pktdata + sizeof(struct ether_header); + uint8 tos_tc = IP_TOS46(ip_body); + uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT; + switch (dscp) { + case DSCP_EF: + priority = PRIO_8021D_VO; + break; + case DSCP_AF31: + case DSCP_AF32: + case DSCP_AF33: + priority = PRIO_8021D_CL; + break; + case DSCP_AF21: + case DSCP_AF22: + case DSCP_AF23: + case DSCP_AF11: + case DSCP_AF12: + case DSCP_AF13: + priority = PRIO_8021D_EE; + break; + default: + priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); + break; + } -char * -bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len) -{ - for (; s_len >= substr_len; s++, s_len--) - if (strncmp(s, substr, substr_len) == 0) - return DISCARD_QUAL(s, char); + rc |= PKTPRIO_DSCP; + } - return NULL; + ASSERT(priority >= 0 && priority <= MAXPRIO); + PKTSETPRIO(pkt, priority); + return (rc | priority); } -char * -bcmstrcat(char *dest, const char *src) +/* lookup user priority for specified DSCP */ +static uint8 +dscp2up(uint8 *up_table, uint8 dscp) { - char *p; + uint8 user_priority = 255; - p = dest + strlen(dest); + /* lookup up from table if parameters valid */ + if (up_table != NULL && dscp < UP_TABLE_MAX) { + user_priority = up_table[dscp]; + } - while ((*p++ = *src++) != '\0') - ; + /* 255 is unused value so return up from dscp */ + if (user_priority == 255) { + user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT); + } - return (dest); + return user_priority; } -char * -bcmstrncat(char *dest, const char *src, uint size) +/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */ +uint BCMFASTPATH +pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag) { - char *endp; - char *p; + if (up_table) { + uint8 *pktdata; + uint pktlen; + uint8 dscp; + uint user_priority = 0; + uint rc = 0; - p = dest + strlen(dest); - endp = p + size; + pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt); + pktlen = PKTLEN(OSH_NULL, pkt); - while (p != endp && (*p++ = *src++) != '\0') - ; + if (pktgetdscp(pktdata, pktlen, &dscp)) { + rc = PKTPRIO_DSCP; + user_priority = dscp2up(up_table, dscp); + PKTSETPRIO(pkt, user_priority); + } - return (dest); + return (rc | user_priority); + } else { + return pktsetprio(pkt, update_vtag); + } } - -/**************************************************************************** -* Function: bcmstrtok -* -* Purpose: -* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), -* but allows strToken() to be used by different strings or callers at the same -* time. Each call modifies '*string' by substituting a NULL character for the -* first delimiter that is encountered, and updates 'string' to point to the char -* after the delimiter. Leading delimiters are skipped. -* -* Parameters: -* string (mod) Ptr to string ptr, updated by token. -* delimiters (in) Set of delimiter characters. -* tokdelim (out) Character that delimits the returned token. (May -* be set to NULL if token delimiter is not required). -* -* Returns: Pointer to the next token found. NULL when no more tokens are found. -***************************************************************************** -*/ -char * -bcmstrtok(char **string, const char *delimiters, char *tokdelim) +/* Returns TRUE and DSCP if IP header found, FALSE otherwise. + */ +bool BCMFASTPATH +pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp) { - unsigned char *str; - unsigned long map[8]; - int count; - char *nextoken; + struct ether_header *eh; + struct ethervlan_header *evh; + uint8 *ip_body; + bool rc = FALSE; - if (tokdelim != NULL) { - /* Prime the token delimiter */ - *tokdelim = '\0'; - } + /* minimum length is ether header and IP header */ + if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN) + return FALSE; - /* Clear control map */ - for (count = 0; count < 8; count++) { - map[count] = 0; - } + eh = (struct ether_header *) pktdata; - /* Set bits in delimiter table */ - do { - map[*delimiters >> 5] |= (1 << (*delimiters & 31)); + if (eh->ether_type == HTON16(ETHER_TYPE_IP)) { + ip_body = pktdata + sizeof(struct ether_header); + *dscp = IP_DSCP46(ip_body); + rc = TRUE; } - while (*delimiters++); - - str = (unsigned char*)*string; + else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) { + evh = (struct ethervlan_header *)eh; - /* Find beginning of token (skip over leading delimiters). Note that - * there is no token iff this loop sets str to point to the terminal - * null (*str == '\0') - */ - while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { - str++; + /* minimum length is ethervlan header and IP header */ + if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN && + evh->ether_type == HTON16(ETHER_TYPE_IP)) { + ip_body = pktdata + sizeof(struct ethervlan_header); + *dscp = IP_DSCP46(ip_body); + rc = TRUE; + } } - nextoken = (char*)str; + return rc; +} - /* Find the end of the token. If it is not the end of the string, - * put a null there. - */ - for (; *str; str++) { - if (map[*str >> 5] & (1 << (*str & 31))) { - if (tokdelim != NULL) { - *tokdelim = *str; - } +/* usr_prio range from low to high with usr_prio value */ +static bool +up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high) +{ + int i; - *str++ = '\0'; - break; - } + if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) { + return FALSE; } - *string = (char*)str; - - /* Determine if a token has been found. */ - if (nextoken == (char *) str) { - return NULL; - } - else { - return nextoken; + for (i = low; i <= high; i++) { + up_table[i] = usr_prio; } -} + return TRUE; +} -#define xToLower(C) \ - ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) +/* set user priority table */ +int BCMFASTPATH +wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie) +{ + uint8 len; + if (up_table == NULL || qos_map_ie == NULL) { + return BCME_ERROR; + } -/**************************************************************************** -* Function: bcmstricmp -* -* Purpose: Compare to strings case insensitively. -* -* Parameters: s1 (in) First string to compare. -* s2 (in) Second string to compare. -* -* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -* t1 > t2, when ignoring case sensitivity. -***************************************************************************** -*/ -int -bcmstricmp(const char *s1, const char *s2) -{ - char dc, sc; + /* clear table to check table was set or not */ + memset(up_table, 0xff, UP_TABLE_MAX); - while (*s2 && *s1) { - dc = xToLower(*s1); - sc = xToLower(*s2); - if (dc < sc) return -1; - if (dc > sc) return 1; - s1++; - s2++; - } + /* length of QoS Map IE must be 16+n*2, n is number of exceptions */ + if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID && + (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH && + (len % 2) == 0) { + uint8 *except_ptr = (uint8 *)qos_map_ie->data; + uint8 except_len = len - QOS_MAP_FIXED_LENGTH; + uint8 *range_ptr = except_ptr + except_len; + int i; - if (*s1 && !*s2) return 1; - if (!*s1 && *s2) return -1; - return 0; -} + /* fill in ranges */ + for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) { + uint8 low = range_ptr[i]; + uint8 high = range_ptr[i + 1]; + if (low == 255 && high == 255) { + continue; + } + if (!up_table_set(up_table, i / 2, low, high)) { + /* clear the table on failure */ + memset(up_table, 0xff, UP_TABLE_MAX); + return BCME_ERROR; + } + } -/**************************************************************************** -* Function: bcmstrnicmp -* -* Purpose: Compare to strings case insensitively, upto a max of 'cnt' -* characters. -* -* Parameters: s1 (in) First string to compare. -* s2 (in) Second string to compare. -* cnt (in) Max characters to compare. -* -* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -* t1 > t2, when ignoring case sensitivity. -***************************************************************************** -*/ -int -bcmstrnicmp(const char* s1, const char* s2, int cnt) -{ - char dc, sc; + /* update exceptions */ + for (i = 0; i < except_len; i += 2) { + uint8 dscp = except_ptr[i]; + uint8 usr_prio = except_ptr[i+1]; - while (*s2 && *s1 && cnt) { - dc = xToLower(*s1); - sc = xToLower(*s2); - if (dc < sc) return -1; - if (dc > sc) return 1; - s1++; - s2++; - cnt--; + /* exceptions with invalid dscp/usr_prio are ignored */ + up_table_set(up_table, usr_prio, dscp, dscp); + } } - if (!cnt) return 0; - if (*s1 && !*s2) return 1; - if (!*s1 && *s2) return -1; - return 0; + return BCME_OK; } -/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ -int -bcm_ether_atoe(const char *p, struct ether_addr *ea) -{ - int i = 0; - char *ep; - - for (;;) { - ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); - p = ep; - if (!*p++ || i == 6) - break; - } +/* The 0.5KB string table is not removed by compiler even though it's unused */ - return (i == 6); -} +static char bcm_undeferrstr[32]; +static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; -int -bcm_atoipv4(const char *p, struct ipv4_addr *ip) +/* Convert the error codes into related error strings */ +const char * +BCMRAMFN(bcmerrorstr)(int bcmerror) { + /* check if someone added a bcmerror code but forgot to add errorstring */ + ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); - int i = 0; - char *c; - for (;;) { - ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0); - if (*c++ != '.' || i == IPV4_ADDR_LEN) - break; - p = c; + if (bcmerror > 0 || bcmerror < BCME_LAST) { + snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); + return bcm_undeferrstr; } - return (i == IPV4_ADDR_LEN); -} -#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ + ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); -#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) -/* registry routine buffer preparation utility functions: - * parameter order is like strncpy, but returns count - * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) - */ -ulong -wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) + return bcmerrorstrtable[-bcmerror]; +} + +/* iovar table lookup */ +/* could mandate sorted tables and do a binary search */ +const bcm_iovar_t* +bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) { - ulong copyct = 1; - ushort i; + const bcm_iovar_t *vi; + const char *lookup_name; - if (abuflen == 0) - return 0; + /* skip any ':' delimited option prefixes */ + lookup_name = strrchr(name, ':'); + if (lookup_name != NULL) + lookup_name++; + else + lookup_name = name; - /* wbuflen is in bytes */ - wbuflen /= sizeof(ushort); + ASSERT(table != NULL); - for (i = 0; i < wbuflen; ++i) { - if (--abuflen == 0) - break; - *abuf++ = (char) *wbuf++; - ++copyct; + for (vi = table; vi->name; vi++) { + if (!strcmp(vi->name, lookup_name)) + return vi; } - *abuf = '\0'; + /* ran to end of table */ - return copyct; + return NULL; /* var name not found */ } -#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ -char * -bcm_ether_ntoa(const struct ether_addr *ea, char *buf) +int +bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) { - static const char hex[] = - { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' - }; - const uint8 *octet = ea->octet; - char *p = buf; - int i; + int bcmerror = 0; + BCM_REFERENCE(arg); - for (i = 0; i < 6; i++, octet++) { - *p++ = hex[(*octet >> 4) & 0xf]; - *p++ = hex[*octet & 0xf]; - *p++ = ':'; - } + /* length check on io buf */ + switch (vi->type) { + case IOVT_BOOL: + case IOVT_INT8: + case IOVT_INT16: + case IOVT_INT32: + case IOVT_UINT8: + case IOVT_UINT16: + case IOVT_UINT32: + /* all integers are int32 sized args at the ioctl interface */ + if (len < (int)sizeof(int)) { + bcmerror = BCME_BUFTOOSHORT; + } + break; - *(p-1) = '\0'; + case IOVT_BUFFER: + /* buffer must meet minimum length requirement */ + if (len < vi->minlen) { + bcmerror = BCME_BUFTOOSHORT; + } + break; - return (buf); -} + case IOVT_VOID: + if (!set) { + /* Cannot return nil... */ + bcmerror = BCME_UNSUPPORTED; + } + break; -char * -bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) -{ - snprintf(buf, 16, "%d.%d.%d.%d", - ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); - return (buf); -} + default: + /* unknown type for length check in iovar info */ + ASSERT(0); + bcmerror = BCME_UNSUPPORTED; + } -char * -bcm_ipv6_ntoa(void *ipv6, char *buf) -{ - /* Implementing RFC 5952 Sections 4 + 5 */ - /* Not thoroughly tested */ - uint16 tmp[8]; - uint16 *a = &tmp[0]; - char *p = buf; - int i, i_max = -1, cnt = 0, cnt_max = 1; - uint8 *a4 = NULL; - memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN); + return bcmerror; +} - for (i = 0; i < IPV6_ADDR_LEN/2; i++) { - if (a[i]) { - if (cnt > cnt_max) { - cnt_max = cnt; - i_max = i - cnt; - } - cnt = 0; - } else - cnt++; - } - if (cnt > cnt_max) { - cnt_max = cnt; - i_max = i - cnt; - } - if (i_max == 0 && - /* IPv4-translated: ::ffff:0:a.b.c.d */ - ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) || - /* IPv4-mapped: ::ffff:a.b.c.d */ - (cnt_max == 5 && a[5] == 0xffff))) - a4 = (uint8*) (a + 6); +#if !defined(_CFEZ_) +/* + * Hierarchical Multiword bitmap based small id allocator. + * + * Multilevel hierarchy bitmap. (maximum 2 levels) + * First hierarchy uses a multiword bitmap to identify 32bit words in the + * second hierarchy that have at least a single bit set. Each bit in a word of + * the second hierarchy represents a unique ID that may be allocated. + * + * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed. + * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word + * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs. + * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non + * non-zero bitmap word carrying at least one free ID. + * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations. + * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID + * + * Design Notes: + * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many + * bits are computed each time on allocation and deallocation, requiring 4 + * array indexed access and 3 arithmetic operations. When not defined, a runtime + * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed. + * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation. + * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may + * be used by defining BCM_MWBMAP_USE_CNTSETBITS. + * + * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array + * size is fixed. No intention to support larger than 4K indice allocation. ID + * allocators for ranges smaller than 4K will have a wastage of only 12Bytes + * with savings in not having to use an indirect access, had it been dynamically + * allocated. + */ +#define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */ - for (i = 0; i < IPV6_ADDR_LEN/2; i++) { - if ((uint8*) (a + i) == a4) { - snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]); - break; - } else if (i == i_max) { - *p++ = ':'; - i += cnt_max - 1; - p[0] = ':'; - p[1] = '\0'; - } else { - if (i) - *p++ = ':'; - p += snprintf(p, 8, "%x", ntoh16(a[i])); - } - } +#define BCM_MWBMAP_BITS_WORD (NBITS(uint32)) +#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD) +#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD) +#define BCM_MWBMAP_SHIFT_OP (5) +#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1)) +#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP) +#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP) - return buf; -} -#ifdef BCMDRIVER +/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */ +#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl)) +#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr)) -void -bcm_mdelay(uint ms) +#if defined(BCM_MWBMAP_DEBUG) +#define BCM_MWBMAP_AUDIT(mwb) \ + do { \ + ASSERT((mwb != NULL) && \ + (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \ + bcm_mwbmap_audit(mwb); \ + } while (0) +#define MWBMAP_ASSERT(exp) ASSERT(exp) +#define MWBMAP_DBG(x) printf x +#else /* !BCM_MWBMAP_DEBUG */ +#define BCM_MWBMAP_AUDIT(mwb) do {} while (0) +#define MWBMAP_ASSERT(exp) do {} while (0) +#define MWBMAP_DBG(x) +#endif /* !BCM_MWBMAP_DEBUG */ + +typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */ + uint16 wmaps; /* Total number of words in free wd bitmap */ + uint16 imaps; /* Total number of words in free id bitmap */ + int32 ifree; /* Count of free indices. Used only in audits */ + uint16 total; /* Total indices managed by multiword bitmap */ + + void * magic; /* Audit handle parameter from user */ + + uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */ +#if !defined(BCM_MWBMAP_USE_CNTSETBITS) + int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */ +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + + uint32 id_bitmap[0]; /* Second level bitmap */ +} bcm_mwbmap_t; + +/* Incarnate a hierarchical multiword bitmap based small index allocator. */ +struct bcm_mwbmap * +bcm_mwbmap_init(osl_t *osh, uint32 items_max) { - uint i; + struct bcm_mwbmap * mwbmap_p; + uint32 wordix, size, words, extra; - for (i = 0; i < ms; i++) { - OSL_DELAY(1000); + /* Implementation Constraint: Uses 32bit word bitmap */ + MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U); + MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U); + MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX)); + MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U); + + ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX); + + /* Determine the number of words needed in the multiword bitmap */ + extra = BCM_MWBMAP_MODOP(items_max); + words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U); + + /* Allocate runtime state of multiword bitmap */ + /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */ + size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words); + mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size); + if (mwbmap_p == (bcm_mwbmap_t *)NULL) { + ASSERT(0); + goto error1; } -} + memset(mwbmap_p, 0, size); + /* Initialize runtime multiword bitmap state */ + mwbmap_p->imaps = (uint16)words; + mwbmap_p->ifree = (int32)items_max; + mwbmap_p->total = (uint16)items_max; + + /* Setup magic, for use in audit of handle */ + mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p); + + /* Setup the second level bitmap of free indices */ + /* Mark all indices as available */ + for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) { + mwbmap_p->id_bitmap[wordix] = (uint32)(~0U); +#if !defined(BCM_MWBMAP_USE_CNTSETBITS) + mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD; +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + } + /* Ensure that extra indices are tagged as un-available */ + if (extra) { /* fixup the free ids in last bitmap and wd_count */ + uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1]; + *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ +#if !defined(BCM_MWBMAP_USE_CNTSETBITS) + mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */ +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + } + /* Setup the first level bitmap hierarchy */ + extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps); + words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U); + mwbmap_p->wmaps = (uint16)words; -#if defined(DHD_DEBUG) -/* pretty hex print a pkt buffer chain */ + for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++) + mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U); + if (extra) { + uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1]; + *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ + } + + return mwbmap_p; + +error1: + return BCM_MWBMAP_INVALID_HDL; +} + +/* Release resources used by multiword bitmap based small index allocator. */ void -prpkt(const char *msg, osl_t *osh, void *p0) +bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl) { - void *p; + bcm_mwbmap_t * mwbmap_p; - if (msg && (msg[0] != '\0')) - printf("%s:\n", msg); + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - for (p = p0; p; p = PKTNEXT(osh, p)) - prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); + MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap) + + (sizeof(uint32) * mwbmap_p->imaps)); + return; } -#endif -/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. - * Also updates the inplace vlan tag if requested. - * For debugging, it returns an indication of what it did. - */ -uint BCMFASTPATH -pktsetprio(void *pkt, bool update_vtag) +/* Allocate a unique small index using a multiword bitmap index allocator. */ +uint32 BCMFASTPATH +bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl) { - struct ether_header *eh; - struct ethervlan_header *evh; - uint8 *pktdata; - int priority = 0; - int rc = 0; + bcm_mwbmap_t * mwbmap_p; + uint32 wordix, bitmap; - pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt); - ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - eh = (struct ether_header *) pktdata; + /* Start with the first hierarchy */ + for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) { - if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { - uint16 vlan_tag; - int vlan_prio, dscp_prio = 0; + bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */ - evh = (struct ethervlan_header *)eh; + if (bitmap != 0U) { - vlan_tag = ntoh16(evh->vlan_tag); - vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; + uint32 count, bitix, *bitmap_p; - if ((evh->ether_type == hton16(ETHER_TYPE_IP)) || - (evh->ether_type == hton16(ETHER_TYPE_IPV6))) { - uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); - uint8 tos_tc = IP_TOS46(ip_body); - dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); - } + bitmap_p = &mwbmap_p->wd_bitmap[wordix]; - /* DSCP priority gets precedence over 802.1P (vlan tag) */ - if (dscp_prio != 0) { - priority = dscp_prio; - rc |= PKTPRIO_VDSCP; - } else { - priority = vlan_prio; - rc |= PKTPRIO_VLAN; - } - /* - * If the DSCP priority is not the same as the VLAN priority, - * then overwrite the priority field in the vlan tag, with the - * DSCP priority value. This is required for Linux APs because - * the VLAN driver on Linux, overwrites the skb->priority field - * with the priority value in the vlan tag - */ - if (update_vtag && (priority != vlan_prio)) { - vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); - vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; - evh->vlan_tag = hton16(vlan_tag); - rc |= PKTPRIO_UPD; - } -#if defined(EAPOL_PKT_PRIO) || defined(DHD_LOSSLESS_ROAMING) - } else if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) { - priority = PRIO_8021D_NC; - rc = PKTPRIO_DSCP; -#endif /* EAPOL_PKT_PRIO || DHD_LOSSLESS_ROAMING */ - } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) || - (eh->ether_type == hton16(ETHER_TYPE_IPV6))) { - uint8 *ip_body = pktdata + sizeof(struct ether_header); - uint8 tos_tc = IP_TOS46(ip_body); - uint8 dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT; - switch (dscp) { - case DSCP_EF: - priority = PRIO_8021D_VO; - break; - case DSCP_AF31: - case DSCP_AF32: - case DSCP_AF33: - priority = PRIO_8021D_CL; - break; - case DSCP_AF21: - case DSCP_AF22: - case DSCP_AF23: - case DSCP_AF11: - case DSCP_AF12: - case DSCP_AF13: - priority = PRIO_8021D_EE; - break; - default: - priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); - break; - } - - rc |= PKTPRIO_DSCP; - } - - ASSERT(priority >= 0 && priority <= MAXPRIO); - PKTSETPRIO(pkt, priority); - return (rc | priority); -} - -/* lookup user priority for specified DSCP */ -static uint8 -dscp2up(uint8 *up_table, uint8 dscp) -{ - uint8 user_priority = 255; - - /* lookup up from table if parameters valid */ - if (up_table != NULL && dscp < UP_TABLE_MAX) { - user_priority = up_table[dscp]; - } + /* clear all except trailing 1 */ + bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); + MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == + bcm_count_leading_zeros(bitmap)); + bitix = (BCM_MWBMAP_BITS_WORD - 1) + - bcm_count_leading_zeros(bitmap); /* use asm clz */ + wordix = BCM_MWBMAP_MULOP(wordix) + bitix; - /* 255 is unused value so return up from dscp */ - if (user_priority == 255) { - user_priority = dscp >> (IPV4_TOS_PREC_SHIFT - IPV4_TOS_DSCP_SHIFT); - } + /* Clear bit if wd count is 0, without conditional branch */ +#if defined(BCM_MWBMAP_USE_CNTSETBITS) + count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1; +#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ + mwbmap_p->wd_count[wordix]--; + count = mwbmap_p->wd_count[wordix]; + MWBMAP_ASSERT(count == + (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1)); +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + MWBMAP_ASSERT(count >= 0); - return user_priority; -} + /* clear wd_bitmap bit if id_map count is 0 */ + bitmap = (count == 0) << bitix; -/* set user priority by QoS Map Set table (UP table), table size is UP_TABLE_MAX */ -uint BCMFASTPATH -pktsetprio_qms(void *pkt, uint8* up_table, bool update_vtag) -{ - if (up_table) { - uint8 *pktdata; - uint pktlen; - uint8 dscp; - uint user_priority = 0; - uint rc = 0; + MWBMAP_DBG(( + "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d", + bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count)); - pktdata = (uint8 *)PKTDATA(OSH_NULL, pkt); - pktlen = PKTLEN(OSH_NULL, pkt); + *bitmap_p ^= bitmap; - if (pktgetdscp(pktdata, pktlen, &dscp)) { - rc = PKTPRIO_DSCP; - user_priority = dscp2up(up_table, dscp); - PKTSETPRIO(pkt, user_priority); - } + /* Use bitix in the second hierarchy */ + bitmap_p = &mwbmap_p->id_bitmap[wordix]; - return (rc | user_priority); - } else { - return pktsetprio(pkt, update_vtag); - } -} + bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */ + MWBMAP_ASSERT(bitmap != 0U); -/* Returns TRUE and DSCP if IP header found, FALSE otherwise. - */ -bool BCMFASTPATH -pktgetdscp(uint8 *pktdata, uint pktlen, uint8 *dscp) -{ - struct ether_header *eh; - struct ethervlan_header *evh; - uint8 *ip_body; - bool rc = FALSE; + /* clear all except trailing 1 */ + bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); + MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == + bcm_count_leading_zeros(bitmap)); + bitix = BCM_MWBMAP_MULOP(wordix) + + (BCM_MWBMAP_BITS_WORD - 1) + - bcm_count_leading_zeros(bitmap); /* use asm clz */ - /* minimum length is ether header and IP header */ - if (pktlen < sizeof(struct ether_header) + IPV4_MIN_HEADER_LEN) - return FALSE; + mwbmap_p->ifree--; /* decrement system wide free count */ + MWBMAP_ASSERT(mwbmap_p->ifree >= 0); - eh = (struct ether_header *) pktdata; + MWBMAP_DBG(( + "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d", + bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, + mwbmap_p->ifree)); - if (eh->ether_type == HTON16(ETHER_TYPE_IP)) { - ip_body = pktdata + sizeof(struct ether_header); - *dscp = IP_DSCP46(ip_body); - rc = TRUE; - } - else if (eh->ether_type == HTON16(ETHER_TYPE_8021Q)) { - evh = (struct ethervlan_header *)eh; + *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */ - /* minimum length is ethervlan header and IP header */ - if (pktlen >= sizeof(struct ethervlan_header) + IPV4_MIN_HEADER_LEN && - evh->ether_type == HTON16(ETHER_TYPE_IP)) { - ip_body = pktdata + sizeof(struct ethervlan_header); - *dscp = IP_DSCP46(ip_body); - rc = TRUE; + return bitix; } } - return rc; + ASSERT(mwbmap_p->ifree == 0); + + return BCM_MWBMAP_INVALID_IDX; } -/* usr_prio range from low to high with usr_prio value */ -static bool -up_table_set(uint8 *up_table, uint8 usr_prio, uint8 low, uint8 high) +/* Force an index at a specified position to be in use */ +void +bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) { - int i; + bcm_mwbmap_t * mwbmap_p; + uint32 count, wordix, bitmap, *bitmap_p; - if (usr_prio > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) { - return FALSE; - } + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - for (i = low; i <= high; i++) { - up_table[i] = usr_prio; - } + ASSERT(bitix < mwbmap_p->total); - return TRUE; -} + /* Start with second hierarchy */ + wordix = BCM_MWBMAP_DIVOP(bitix); + bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix)); + bitmap_p = &mwbmap_p->id_bitmap[wordix]; -/* set user priority table */ -int BCMFASTPATH -wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie) -{ - uint8 len; + ASSERT((*bitmap_p & bitmap) == bitmap); - if (up_table == NULL || qos_map_ie == NULL) { - return BCME_ERROR; - } + mwbmap_p->ifree--; /* update free count */ + ASSERT(mwbmap_p->ifree >= 0); - /* clear table to check table was set or not */ - memset(up_table, 0xff, UP_TABLE_MAX); + MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d", + bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, + mwbmap_p->ifree)); - /* length of QoS Map IE must be 16+n*2, n is number of exceptions */ - if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID && - (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH && - (len % 2) == 0) { - uint8 *except_ptr = (uint8 *)qos_map_ie->data; - uint8 except_len = len - QOS_MAP_FIXED_LENGTH; - uint8 *range_ptr = except_ptr + except_len; - int i; + *bitmap_p ^= bitmap; /* mark as in use */ - /* fill in ranges */ - for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) { - uint8 low = range_ptr[i]; - uint8 high = range_ptr[i + 1]; - if (low == 255 && high == 255) { - continue; - } + /* Update first hierarchy */ + bitix = wordix; - if (!up_table_set(up_table, i / 2, low, high)) { - /* clear the table on failure */ - memset(up_table, 0xff, UP_TABLE_MAX); - return BCME_ERROR; - } - } + wordix = BCM_MWBMAP_DIVOP(bitix); + bitmap_p = &mwbmap_p->wd_bitmap[wordix]; - /* update exceptions */ - for (i = 0; i < except_len; i += 2) { - uint8 dscp = except_ptr[i]; - uint8 usr_prio = except_ptr[i+1]; +#if defined(BCM_MWBMAP_USE_CNTSETBITS) + count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); +#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ + mwbmap_p->wd_count[bitix]--; + count = mwbmap_p->wd_count[bitix]; + MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + MWBMAP_ASSERT(count >= 0); - /* exceptions with invalid dscp/usr_prio are ignored */ - up_table_set(up_table, usr_prio, dscp, dscp); - } - } + bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix); - return BCME_OK; -} + MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d", + BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap, + (*bitmap_p) ^ bitmap, count)); -/* The 0.5KB string table is not removed by compiler even though it's unused */ + *bitmap_p ^= bitmap; /* mark as in use */ -static char bcm_undeferrstr[32]; -static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; + return; +} -/* Convert the error codes into related error strings */ -const char * -bcmerrorstr(int bcmerror) +/* Free a previously allocated index back into the multiword bitmap allocator */ +void BCMFASTPATH +bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) { - /* check if someone added a bcmerror code but forgot to add errorstring */ - ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); + bcm_mwbmap_t * mwbmap_p; + uint32 wordix, bitmap, *bitmap_p; - if (bcmerror > 0 || bcmerror < BCME_LAST) { - snprintf(bcm_undeferrstr, sizeof(bcm_undeferrstr), "Undefined error %d", bcmerror); - return bcm_undeferrstr; - } + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); + ASSERT(bitix < mwbmap_p->total); - return bcmerrorstrtable[-bcmerror]; -} + /* Start with second level hierarchy */ + wordix = BCM_MWBMAP_DIVOP(bitix); + bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); + bitmap_p = &mwbmap_p->id_bitmap[wordix]; + ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */ -/* iovar table lookup */ -/* could mandate sorted tables and do a binary search */ -const bcm_iovar_t* -bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) -{ - const bcm_iovar_t *vi; - const char *lookup_name; + mwbmap_p->ifree++; /* update free count */ + ASSERT(mwbmap_p->ifree <= mwbmap_p->total); - /* skip any ':' delimited option prefixes */ - lookup_name = strrchr(name, ':'); - if (lookup_name != NULL) - lookup_name++; - else - lookup_name = name; + MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d", + bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, + mwbmap_p->ifree)); - ASSERT(table != NULL); + *bitmap_p |= bitmap; /* mark as available */ - for (vi = table; vi->name; vi++) { - if (!strcmp(vi->name, lookup_name)) - return vi; - } - /* ran to end of table */ + /* Now update first level hierarchy */ - return NULL; /* var name not found */ -} + bitix = wordix; -int -bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) -{ - int bcmerror = 0; - BCM_REFERENCE(arg); + wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */ + bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); + bitmap_p = &mwbmap_p->wd_bitmap[wordix]; - /* length check on io buf */ - switch (vi->type) { - case IOVT_BOOL: - case IOVT_INT8: - case IOVT_INT16: - case IOVT_INT32: - case IOVT_UINT8: - case IOVT_UINT16: - case IOVT_UINT32: - /* all integers are int32 sized args at the ioctl interface */ - if (len < (int)sizeof(int)) { - bcmerror = BCME_BUFTOOSHORT; - } - break; +#if !defined(BCM_MWBMAP_USE_CNTSETBITS) + mwbmap_p->wd_count[bitix]++; +#endif // endif - case IOVT_BUFFER: - /* buffer must meet minimum length requirement */ - if (len < vi->minlen) { - bcmerror = BCME_BUFTOOSHORT; - } - break; +#if defined(BCM_MWBMAP_DEBUG) + { + uint32 count; +#if defined(BCM_MWBMAP_USE_CNTSETBITS) + count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); +#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ + count = mwbmap_p->wd_count[bitix]; + MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - case IOVT_VOID: - if (!set) { - /* Cannot return nil... */ - bcmerror = BCME_UNSUPPORTED; - } else if (len) { - /* Set is an action w/o parameters */ - bcmerror = BCME_BUFTOOLONG; - } - break; + MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD); - default: - /* unknown type for length check in iovar info */ - ASSERT(0); - bcmerror = BCME_UNSUPPORTED; + MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d", + bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count)); } +#endif /* BCM_MWBMAP_DEBUG */ - return bcmerror; + *bitmap_p |= bitmap; + + return; } -#endif /* BCMDRIVER */ +/* Fetch the toal number of free indices in the multiword bitmap allocator */ +uint32 +bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl) +{ + bcm_mwbmap_t * mwbmap_p; -#ifdef BCM_OBJECT_TRACE + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); -#define BCM_OBJECT_MERGE_SAME_OBJ 0 + ASSERT(mwbmap_p->ifree >= 0); -/* some place may add / remove the object to trace list for Linux: */ -/* add: osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */ -/* remove: osl_pktfree dev_kfree_skb netif_rx */ + return mwbmap_p->ifree; +} -#define BCM_OBJDBG_COUNT (1024 * 100) -static spinlock_t dbgobj_lock; -#define BCM_OBJDBG_LOCK_INIT() spin_lock_init(&dbgobj_lock) -#define BCM_OBJDBG_LOCK_DESTROY() -#define BCM_OBJDBG_LOCK spin_lock_irqsave -#define BCM_OBJDBG_UNLOCK spin_unlock_irqrestore +/* Determine whether an index is inuse or free */ +bool +bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) +{ + bcm_mwbmap_t * mwbmap_p; + uint32 wordix, bitmap; -#define BCM_OBJDBG_ADDTOHEAD 0 -#define BCM_OBJDBG_ADDTOTAIL 1 + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); -#define BCM_OBJDBG_CALLER_LEN 32 -struct bcm_dbgobj { - struct bcm_dbgobj *prior; - struct bcm_dbgobj *next; - uint32 flag; - void *obj; - uint32 obj_sn; - uint32 obj_state; - uint32 line; - char caller[BCM_OBJDBG_CALLER_LEN]; -}; + ASSERT(bitix < mwbmap_p->total); -static struct bcm_dbgobj *dbgobj_freehead = NULL; -static struct bcm_dbgobj *dbgobj_freetail = NULL; -static struct bcm_dbgobj *dbgobj_objhead = NULL; -static struct bcm_dbgobj *dbgobj_objtail = NULL; + wordix = BCM_MWBMAP_DIVOP(bitix); + bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); -static uint32 dbgobj_sn = 0; -static int dbgobj_count = 0; -static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT]; + return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U); +} +/* Debug dump a multiword bitmap allocator */ void -bcm_object_trace_init(void) +bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl) { - int i = 0; - BCM_OBJDBG_LOCK_INIT(); - memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT); - dbgobj_freehead = &bcm_dbg_objs[0]; - dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1]; + uint32 ix, count; + bcm_mwbmap_t * mwbmap_p; - for (i = 0; i < BCM_OBJDBG_COUNT; ++i) { - bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ? - dbgobj_freehead : &bcm_dbg_objs[i + 1]; - bcm_dbg_objs[i].prior = (i == 0) ? - dbgobj_freetail : &bcm_dbg_objs[i - 1]; + BCM_MWBMAP_AUDIT(mwbmap_hdl); + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + + printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", + OSL_OBFUSCATE_BUF((void *)mwbmap_p), + mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total); + for (ix = 0U; ix < mwbmap_p->wmaps; ix++) { + printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]); + bcm_bitprint32(mwbmap_p->wd_bitmap[ix]); + printf("\n"); + } + for (ix = 0U; ix < mwbmap_p->imaps; ix++) { +#if defined(BCM_MWBMAP_USE_CNTSETBITS) + count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]); +#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ + count = mwbmap_p->wd_count[ix]; + MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix])); +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count); + bcm_bitprint32(mwbmap_p->id_bitmap[ix]); + printf("\n"); } + + return; } +/* Audit a hierarchical multiword bitmap */ void -bcm_object_trace_deinit(void) +bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl) { - if (dbgobj_objhead || dbgobj_objtail) { - printf("%s: not all objects are released\n", __FUNCTION__); - ASSERT(0); - } - BCM_OBJDBG_LOCK_DESTROY(); -} + bcm_mwbmap_t * mwbmap_p; + uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p; -static void -bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, - struct bcm_dbgobj *dbgobj) -{ - if ((dbgobj == *head) && (dbgobj == *tail)) { - *head = NULL; - *tail = NULL; - } else if (dbgobj == *head) { - *head = (*head)->next; - } else if (dbgobj == *tail) { - *tail = (*tail)->prior; - } - dbgobj->next->prior = dbgobj->prior; - dbgobj->prior->next = dbgobj->next; -} + mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); -static void -bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, - struct bcm_dbgobj *dbgobj, int addtotail) -{ - if (!(*head) && !(*tail)) { - *head = dbgobj; - *tail = dbgobj; - dbgobj->next = dbgobj; - dbgobj->prior = dbgobj; - } else if ((*head) && (*tail)) { - (*tail)->next = dbgobj; - (*head)->prior = dbgobj; - dbgobj->next = *head; - dbgobj->prior = *tail; - if (addtotail == BCM_OBJDBG_ADDTOTAIL) - *tail = dbgobj; - else - *head = dbgobj; - } else { - ASSERT(0); /* can't be this case */ - } -} + for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) { -static INLINE void -bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, - struct bcm_dbgobj *dbgobj, int movetotail) -{ - if ((*head) && (*tail)) { - if (movetotail == BCM_OBJDBG_ADDTOTAIL) { - if (dbgobj != (*tail)) { - bcm_object_rm_list(head, tail, dbgobj); - bcm_object_add_list(head, tail, dbgobj, movetotail); - } - } else { - if (dbgobj != (*head)) { - bcm_object_rm_list(head, tail, dbgobj); - bcm_object_add_list(head, tail, dbgobj, movetotail); + bitmap_p = &mwbmap_p->wd_bitmap[wordix]; + + for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) { + if ((*bitmap_p) & (1 << bitix)) { + idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix; +#if defined(BCM_MWBMAP_USE_CNTSETBITS) + count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]); +#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ + count = mwbmap_p->wd_count[idmap_ix]; + ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix])); +#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + ASSERT(count != 0U); + free_cnt += count; } } - } else { - ASSERT(0); /* can't be this case */ } -} -void -bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line) -{ - struct bcm_dbgobj *dbgobj; - unsigned long flags; + ASSERT((int)free_cnt == mwbmap_p->ifree); +} +/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */ - BCM_REFERENCE(flags); - BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - - if (opt == BCM_OBJDBG_ADD_PKT || - opt == BCM_OBJDBG_ADD) { - dbgobj = dbgobj_objtail; - while (dbgobj) { - if (dbgobj->obj == obj) { - printf("%s: obj %p allocated from %s(%d)," - " allocate again from %s(%d)\n", - __FUNCTION__, dbgobj->obj, - dbgobj->caller, dbgobj->line, - caller, line); - ASSERT(0); - goto EXIT; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; - } +/* Simple 16bit Id allocator using a stack implementation. */ +typedef struct id16_map { + uint32 failures; /* count of failures */ + void *dbg; /* debug placeholder */ + uint16 total; /* total number of ids managed by allocator */ + uint16 start; /* start value of 16bit ids to be managed */ + int stack_idx; /* index into stack of available ids */ + uint16 stack[0]; /* stack of 16 bit ids */ +} id16_map_t; -#if BCM_OBJECT_MERGE_SAME_OBJ - dbgobj = dbgobj_freetail; - while (dbgobj) { - if (dbgobj->obj == obj) { - goto FREED_ENTRY_FOUND; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_freetail) - break; - } -#endif /* BCM_OBJECT_MERGE_SAME_OBJ */ +#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \ + (sizeof(uint16) * (items))) - dbgobj = dbgobj_freehead; -#if BCM_OBJECT_MERGE_SAME_OBJ -FREED_ENTRY_FOUND: -#endif /* BCM_OBJECT_MERGE_SAME_OBJ */ - if (!dbgobj) { - printf("%s: already got %d objects ?????????????????????\n", - __FUNCTION__, BCM_OBJDBG_COUNT); - ASSERT(0); - goto EXIT; - } +#if defined(BCM_DBG) - bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj); - dbgobj->obj = obj; - strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN); - dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0'; - dbgobj->line = line; - dbgobj->flag = 0; - if (opt == BCM_OBJDBG_ADD_PKT) { - dbgobj->obj_sn = dbgobj_sn++; - dbgobj->obj_state = 0; - /* first 4 bytes is pkt sn */ - if (((unsigned long)PKTTAG(obj)) & 0x3) - printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj)); - *(uint32*)PKTTAG(obj) = dbgobj->obj_sn; - } - bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj, - BCM_OBJDBG_ADDTOTAIL); +/* Uncomment BCM_DBG_ID16 to debug double free */ +/* #define BCM_DBG_ID16 */ - dbgobj_count++; +typedef struct id16_map_dbg { + uint16 total; + bool avail[0]; +} id16_map_dbg_t; +#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \ + (sizeof(bool) * (items))) +#define ID16_MAP_MSG(x) print x +#else +#define ID16_MAP_MSG(x) +#endif /* BCM_DBG */ - } else if (opt == BCM_OBJDBG_REMOVE) { - dbgobj = dbgobj_objtail; - while (dbgobj) { - if (dbgobj->obj == obj) { - if (dbgobj->flag) { - printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n", - __FUNCTION__, obj, dbgobj->flag, caller, line); - } - bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj); - memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN); - strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN); - dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0'; - dbgobj->line = line; - bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj, - BCM_OBJDBG_ADDTOTAIL); - dbgobj_count--; - goto EXIT; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; - } +void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */ +id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16) +{ + uint16 idx, val16; + id16_map_t * id16_map; - dbgobj = dbgobj_freetail; - while (dbgobj && dbgobj->obj) { - if (dbgobj->obj == obj) { - printf("%s: obj %p already freed from from %s(%d)," - " try free again from %s(%d)\n", - __FUNCTION__, obj, - dbgobj->caller, dbgobj->line, - caller, line); - //ASSERT(0); /* release same obj more than one time? */ - goto EXIT; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_freetail) - break; - } + ASSERT(total_ids > 0); - printf("%s: ################### release none-existing obj %p from %s(%d)\n", - __FUNCTION__, obj, caller, line); - //ASSERT(0); /* release same obj more than one time? */ + /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map + * with random values. + */ + ASSERT((start_val16 == ID16_UNDEFINED) || + (start_val16 + total_ids) < ID16_INVALID); + id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids)); + if (id16_map == NULL) { + return NULL; } -EXIT: - BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); - return; -} + id16_map->total = total_ids; + id16_map->start = start_val16; + id16_map->failures = 0; + id16_map->dbg = NULL; -void -bcm_object_trace_upd(void *obj, void *obj_new) -{ - struct bcm_dbgobj *dbgobj; - unsigned long flags; + /* + * Populate stack with 16bit id values, commencing with start_val16. + * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map. + */ + id16_map->stack_idx = -1; - BCM_REFERENCE(flags); - BCM_OBJDBG_LOCK(&dbgobj_lock, flags); + if (id16_map->start != ID16_UNDEFINED) { + val16 = start_val16; - dbgobj = dbgobj_objtail; - while (dbgobj) { - if (dbgobj->obj == obj) { - dbgobj->obj = obj_new; - if (dbgobj != dbgobj_objtail) { - bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, - dbgobj, BCM_OBJDBG_ADDTOTAIL); + for (idx = 0; idx < total_ids; idx++, val16++) { + id16_map->stack_idx = idx; + id16_map->stack[id16_map->stack_idx] = val16; + } + } + +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + if (id16_map->start != ID16_UNDEFINED) { + id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids)); + + if (id16_map->dbg) { + id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + + id16_map_dbg->total = total_ids; + for (idx = 0; idx < total_ids; idx++) { + id16_map_dbg->avail[idx] = TRUE; } - goto EXIT; } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; } +#endif /* BCM_DBG && BCM_DBG_ID16 */ -EXIT: - BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); - return; + return (void *)id16_map; } -void -bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn, - const char *caller, int line) +void * /* Destruct an id16 allocator instance */ +id16_map_fini(osl_t *osh, void * id16_map_hndl) { - struct bcm_dbgobj *dbgobj; - unsigned long flags; + uint16 total_ids; + id16_map_t * id16_map; - BCM_REFERENCE(flags); - BCM_OBJDBG_LOCK(&dbgobj_lock, flags); + if (id16_map_hndl == NULL) + return NULL; - dbgobj = dbgobj_objtail; - while (dbgobj) { - if ((dbgobj->obj == obj) && - ((!chksn) || (dbgobj->obj_sn == sn))) { - if (dbgobj != dbgobj_objtail) { - bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, - dbgobj, BCM_OBJDBG_ADDTOTAIL); - } - goto EXIT; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; - } + id16_map = (id16_map_t *)id16_map_hndl; - dbgobj = dbgobj_freetail; - while (dbgobj) { - if ((dbgobj->obj == obj) && - ((!chksn) || (dbgobj->obj_sn == sn))) { - printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n", - __FUNCTION__, caller, line, - dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state, - dbgobj->caller, dbgobj->line); - goto EXIT; - } - else if (dbgobj->obj == NULL) { - break; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_freetail) - break; - } + total_ids = id16_map->total; + ASSERT(total_ids > 0); - printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n", - __FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn); - dbgobj = dbgobj_objtail; - while (dbgobj) { - printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n", - __FUNCTION__, caller, line, - dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line); - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + if (id16_map->dbg) { + MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids)); + id16_map->dbg = NULL; } +#endif /* BCM_DBG && BCM_DBG_ID16 */ -EXIT: - BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); - return; + id16_map->total = 0; + MFREE(osh, id16_map, ID16_MAP_SZ(total_ids)); + + return NULL; } void -bcm_object_feature_set(void *obj, uint32 type, uint32 value) +id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16) { - struct bcm_dbgobj *dbgobj; - unsigned long flags; + uint16 idx, val16; + id16_map_t * id16_map; - BCM_REFERENCE(flags); - BCM_OBJDBG_LOCK(&dbgobj_lock, flags); + ASSERT(total_ids > 0); + /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map + * with random values. + */ + ASSERT((start_val16 == ID16_UNDEFINED) || + (start_val16 + total_ids) < ID16_INVALID); - dbgobj = dbgobj_objtail; - while (dbgobj) { - if (dbgobj->obj == obj) { - if (type == BCM_OBJECT_FEATURE_FLAG) { - if (value & BCM_OBJECT_FEATURE_CLEAR) - dbgobj->flag &= ~(value); - else - dbgobj->flag |= (value); - } else if (type == BCM_OBJECT_FEATURE_PKT_STATE) { - dbgobj->obj_state = value; - } - if (dbgobj != dbgobj_objtail) { - bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, - dbgobj, BCM_OBJDBG_ADDTOTAIL); - } - goto EXIT; - } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; + id16_map = (id16_map_t *)id16_map_hndl; + if (id16_map == NULL) { + return; } - printf("%s: obj %p not found in active list\n", __FUNCTION__, obj); - ASSERT(0); - -EXIT: - BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); - return; -} + id16_map->total = total_ids; + id16_map->start = start_val16; + id16_map->failures = 0; -int -bcm_object_feature_get(void *obj, uint32 type, uint32 value) -{ - int rtn = 0; - struct bcm_dbgobj *dbgobj; - unsigned long flags; + /* Populate stack with 16bit id values, commencing with start_val16 */ + id16_map->stack_idx = -1; - BCM_REFERENCE(flags); - BCM_OBJDBG_LOCK(&dbgobj_lock, flags); + if (id16_map->start != ID16_UNDEFINED) { + val16 = start_val16; - dbgobj = dbgobj_objtail; - while (dbgobj) { - if (dbgobj->obj == obj) { - if (type == BCM_OBJECT_FEATURE_FLAG) { - rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR); - } - if (dbgobj != dbgobj_objtail) { - bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, - dbgobj, BCM_OBJDBG_ADDTOTAIL); - } - goto EXIT; + for (idx = 0; idx < total_ids; idx++, val16++) { + id16_map->stack_idx = idx; + id16_map->stack[id16_map->stack_idx] = val16; } - dbgobj = dbgobj->prior; - if (dbgobj == dbgobj_objtail) - break; } - printf("%s: obj %p not found in active list\n", __FUNCTION__, obj); - ASSERT(0); +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + if (id16_map->start != ID16_UNDEFINED) { + if (id16_map->dbg) { + id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; -EXIT: - BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); - return rtn; + id16_map_dbg->total = total_ids; + for (idx = 0; idx < total_ids; idx++) { + id16_map_dbg->avail[idx] = TRUE; + } + } + } +#endif /* BCM_DBG && BCM_DBG_ID16 */ } -#endif /* BCM_OBJECT_TRACE */ - -uint8 * -bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst) +uint16 BCMFASTPATH /* Allocate a unique 16bit id */ +id16_map_alloc(void * id16_map_hndl) { - uint8 *new_dst = dst; - bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst; + uint16 val16; + id16_map_t * id16_map; - /* dst buffer should always be valid */ - ASSERT(dst); + ASSERT(id16_map_hndl != NULL); - /* data len must be within valid range */ - ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)); + id16_map = (id16_map_t *)id16_map_hndl; - /* source data buffer pointer should be valid, unless datalen is 0 - * meaning no data with this TLV - */ - ASSERT((data != NULL) || (datalen == 0)); + ASSERT(id16_map->total > 0); - /* only do work if the inputs are valid - * - must have a dst to write to AND - * - datalen must be within range AND - * - the source data pointer must be non-NULL if datalen is non-zero - * (this last condition detects datalen > 0 with a NULL data pointer) - */ - if ((dst != NULL) && - ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) && - ((data != NULL) || (datalen == 0))) { + if (id16_map->stack_idx < 0) { + id16_map->failures++; + return ID16_INVALID; + } - /* write type, len fields */ - dst_tlv->id = (uint8)type; - dst_tlv->len = (uint8)datalen; + val16 = id16_map->stack[id16_map->stack_idx]; + id16_map->stack_idx--; - /* if data is present, copy to the output buffer and update - * pointer to output buffer - */ - if (datalen > 0) { +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + ASSERT((id16_map->start == ID16_UNDEFINED) || + (val16 < (id16_map->start + id16_map->total))); - memcpy(dst_tlv->data, data, datalen); - } + if (id16_map->dbg) { /* Validate val16 */ + id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; - /* update the output destination poitner to point past - * the TLV written - */ - new_dst = dst + BCM_TLV_HDR_SIZE + datalen; + ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE); + id16_map_dbg->avail[val16 - id16_map->start] = FALSE; } +#endif /* BCM_DBG && BCM_DBG_ID16 */ - return (new_dst); + return val16; } -uint8 * -bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen) +void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */ +id16_map_free(void * id16_map_hndl, uint16 val16) { - uint8 *new_dst = dst; + id16_map_t * id16_map; - if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) { + ASSERT(id16_map_hndl != NULL); - /* if len + tlv hdr len is more than destlen, don't do anything - * just return the buffer untouched - */ - if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) { + id16_map = (id16_map_t *)id16_map_hndl; - new_dst = bcm_write_tlv(type, data, datalen, dst); - } +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + ASSERT((id16_map->start == ID16_UNDEFINED) || + (val16 < (id16_map->start + id16_map->total))); + + if (id16_map->dbg) { /* Validate val16 */ + id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + + ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE); + id16_map_dbg->avail[val16 - id16_map->start] = TRUE; } +#endif /* BCM_DBG && BCM_DBG_ID16 */ - return (new_dst); + id16_map->stack_idx++; + id16_map->stack[id16_map->stack_idx] = val16; } -uint8 * -bcm_copy_tlv(const void *src, uint8 *dst) +uint32 /* Returns number of failures to allocate an unique id16 */ +id16_map_failures(void * id16_map_hndl) { - uint8 *new_dst = dst; - const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src; - uint totlen; + ASSERT(id16_map_hndl != NULL); + return ((id16_map_t *)id16_map_hndl)->failures; +} - ASSERT(dst && src); - if (dst && src) { +bool +id16_map_audit(void * id16_map_hndl) +{ + int idx; + int insane = 0; + id16_map_t * id16_map; - totlen = BCM_TLV_HDR_SIZE + src_tlv->len; - memcpy(dst, src_tlv, totlen); - new_dst = dst + totlen; - } + ASSERT(id16_map_hndl != NULL); - return (new_dst); -} + id16_map = (id16_map_t *)id16_map_hndl; + ASSERT(id16_map->stack_idx >= -1); + ASSERT(id16_map->stack_idx < (int)id16_map->total); -uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen) -{ - uint8 *new_dst = dst; - const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src; + if (id16_map->start == ID16_UNDEFINED) + goto done; - ASSERT(src); - if (src) { - if (bcm_valid_tlv(src_tlv, dst_maxlen)) { - new_dst = bcm_copy_tlv(src, dst); + for (idx = 0; idx <= id16_map->stack_idx; idx++) { + ASSERT(id16_map->stack[idx] >= id16_map->start); + ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total)); + +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + if (id16_map->dbg) { + uint16 val16 = id16_map->stack[idx]; + if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) { + insane |= 1; + ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n", + OSL_OBFUSATE_BUF(id16_map_hndl), idx, val16)); + } } +#endif /* BCM_DBG && BCM_DBG_ID16 */ } - return (new_dst); -} +#if defined(BCM_DBG) && defined(BCM_DBG_ID16) + if (id16_map->dbg) { + uint16 avail = 0; /* Audit available ids counts */ + for (idx = 0; idx < id16_map_dbg->total; idx++) { + if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE) + avail++; + } + if (avail && (avail != (id16_map->stack_idx + 1))) { + insane |= 1; + ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n", + OSL_OBFUSCATE_BUF(id16_map_hndl), + avail, id16_map->stack_idx)); + } + } +#endif /* BCM_DBG && BCM_DBG_ID16 */ - -#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) -/******************************************************************************* - * crc8 - * - * Computes a crc8 over the input data using the polynomial: - * - * x^8 + x^7 +x^6 + x^4 + x^2 + 1 - * - * The caller provides the initial value (either CRC8_INIT_VALUE - * or the previous returned value) to allow for processing of - * discontiguous blocks of data. When generating the CRC the - * caller is responsible for complementing the final return value - * and inserting it into the byte stream. When checking, a final - * return value of CRC8_GOOD_VALUE indicates a valid CRC. - * - * Reference: Dallas Semiconductor Application Note 27 - * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", - * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., - * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt - * - * **************************************************************************** - */ - -static const uint8 crc8_table[256] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F -}; - -#define CRC_INNER_LOOP(n, c, x) \ - (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] - -uint8 -hndcrc8( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint8 crc /* either CRC8_INIT_VALUE or previous return value */ -) -{ - /* hard code the crc loop instead of using CRC_INNER_LOOP macro - * to avoid the undefined and unnecessary (uint8 >> 8) operation. - */ - while (nbytes-- > 0) - crc = crc8_table[(crc ^ *pdata++) & 0xff]; - - return crc; -} - -/******************************************************************************* - * crc16 - * - * Computes a crc16 over the input data using the polynomial: - * - * x^16 + x^12 +x^5 + 1 - * - * The caller provides the initial value (either CRC16_INIT_VALUE - * or the previous returned value) to allow for processing of - * discontiguous blocks of data. When generating the CRC the - * caller is responsible for complementing the final return value - * and inserting it into the byte stream. When checking, a final - * return value of CRC16_GOOD_VALUE indicates a valid CRC. - * - * Reference: Dallas Semiconductor Application Note 27 - * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", - * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., - * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt - * - * **************************************************************************** - */ - -static const uint16 crc16_table[256] = { - 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, - 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, - 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, - 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, - 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, - 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, - 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, - 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, - 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, - 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, - 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, - 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, - 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, - 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, - 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, - 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, - 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, - 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, - 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, - 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, - 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, - 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, - 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, - 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, - 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, - 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, - 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, - 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, - 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, - 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, - 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, - 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 -}; - -uint16 -hndcrc16( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint16 crc /* either CRC16_INIT_VALUE or previous return value */ -) -{ - while (nbytes-- > 0) - CRC_INNER_LOOP(16, crc, *pdata++); - return crc; -} - -static const uint32 crc32_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; - -/* - * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if - * accumulating over multiple pieces. - */ -uint32 -hndcrc32(uint8 *pdata, uint nbytes, uint32 crc) -{ - uint8 *pend; - pend = pdata + nbytes; - while (pdata < pend) - CRC_INNER_LOOP(32, crc, *pdata++); - - return crc; -} - -#ifdef notdef -#define CLEN 1499 /* CRC Length */ -#define CBUFSIZ (CLEN+4) -#define CNBUFS 5 /* # of bufs */ +done: + /* invoke any other system audits */ + return (!!insane); +} +/* END: Simple id16 allocator */ void -testcrc32(void) -{ - uint j, k, l; - uint8 *buf; - uint len[CNBUFS]; - uint32 crcr; - uint32 crc32tv[CNBUFS] = - {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; - - ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); - - /* step through all possible alignments */ - for (l = 0; l <= 4; l++) { - for (j = 0; j < CNBUFS; j++) { - len[j] = CLEN; - for (k = 0; k < len[j]; k++) - *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; - } - - for (j = 0; j < CNBUFS; j++) { - crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); - ASSERT(crcr == crc32tv[j]); - } - } - - MFREE(buf, CBUFSIZ*CNBUFS); - return; -} -#endif /* notdef */ - -/* - * Advance from the current 1-byte tag/1-byte length/variable-length value - * triple, to the next, returning a pointer to the next. - * If the current or next TLV is invalid (does not fit in given buffer length), - * NULL is returned. - * *buflen is not modified if the TLV elt parameter is invalid, or is decremented - * by the TLV parameter's length if it is valid. - */ -bcm_tlv_t * -bcm_next_tlv(bcm_tlv_t *elt, int *buflen) -{ - int len; - - /* validate current elt */ - if (!bcm_valid_tlv(elt, *buflen)) { - return NULL; - } - - /* advance to next elt */ - len = elt->len; - elt = (bcm_tlv_t*)(elt->data + len); - *buflen -= (TLV_HDR_LEN + len); - - /* validate next elt */ - if (!bcm_valid_tlv(elt, *buflen)) { - return NULL; - } - - return elt; -} - -/* - * Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag - */ -bcm_tlv_t * -bcm_parse_tlvs(void *buf, int buflen, uint key) -{ - bcm_tlv_t *elt; - int totlen; - - if ((elt = (bcm_tlv_t*)buf) == NULL) { - return NULL; - } - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= TLV_HDR_LEN) { - int len = elt->len; - - /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) { - - return (elt); - } - - elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); - totlen -= (len + TLV_HDR_LEN); - } - - return NULL; -} - -bcm_tlv_t * -bcm_parse_tlvs_dot11(void *buf, int buflen, uint key, bool id_ext) -{ - bcm_tlv_t *elt; - int totlen; - - elt = (bcm_tlv_t*)buf; - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= TLV_HDR_LEN) { - int len = elt->len; - - do { - /* validate remaining totlen */ - if (totlen < (int)(len + TLV_HDR_LEN)) - break; - - if (id_ext) { - if (!DOT11_MNG_IE_ID_EXT_MATCH(elt, key)) - break; - } else if (elt->id != key) { - break; - } - - return (elt); - } while (0); - - elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); - totlen -= (len + TLV_HDR_LEN); - } - - return NULL; -} - -/* - * Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag - * return NULL if not found or length field < min_varlen - */ -bcm_tlv_t * -bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen) +dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size) { - bcm_tlv_t * ret; - ret = bcm_parse_tlvs(buf, buflen, key); - if (ret == NULL || ret->len < min_bodylen) { - return NULL; - } - return ret; + uint32 mem_size; + mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); + if (pool) + MFREE(osh, pool, mem_size); } - -/* - * Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag. Stop parsing when we see an element whose ID is greater - * than the target key. - */ -bcm_tlv_t * -bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) +dll_pool_t * +dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size) { - bcm_tlv_t *elt; - int totlen; - - elt = (bcm_tlv_t*)buf; - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= TLV_HDR_LEN) { - uint id = elt->id; - int len = elt->len; - - /* Punt if we start seeing IDs > than target key */ - if (id > key) { - return (NULL); - } - - /* validate remaining totlen */ - if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) { - return (elt); - } - - elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); - totlen -= (len + TLV_HDR_LEN); - } - return NULL; -} -#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ + uint32 mem_size, i; + dll_pool_t * dll_pool_p; + dll_t * elem_p; -#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; + ASSERT(elem_size > sizeof(dll_t)); - buf[0] = '\0'; + mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); - 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; - } + if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) { + printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n", + elems_max, elem_size); + ASSERT(0); + return dll_pool_p; } - return slen; -} - -int -bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) -{ - int i; - char* p = buf; - char hexstr[16]; - int slen = 0, nlen = 0; - uint32 bit; - const char* name; - - if (len < 2 || !buf) - return 0; - buf[0] = '\0'; + dll_init(&dll_pool_p->free_list); + dll_pool_p->elems_max = elems_max; + dll_pool_p->elem_size = elem_size; - for (i = 0; flags != 0; i++) { - bit = bd[i].bit; - name = bd[i].name; - if (bit == 0 && flags != 0) { - /* print any unnamed bits */ - snprintf(hexstr, 16, "0x%X", flags); - name = hexstr; - flags = 0; /* exit loop */ - } else if ((flags & bit) == 0) - continue; - flags &= ~bit; - nlen = strlen(name); - slen += nlen; - /* count btwn flag space */ - if (flags != 0) - slen += 1; - /* need NULL char as well */ - if (len <= slen) - break; - /* copy NULL char but don't count it */ - strncpy(p, name, nlen + 1); - p += nlen; - /* copy btwn flag space and NULL char */ - if (flags != 0) - p += snprintf(p, 2, " "); + elem_p = dll_pool_p->elements; + for (i = 0; i < elems_max; i++) { + dll_append(&dll_pool_p->free_list, elem_p); + elem_p = (dll_t *)((uintptr)elem_p + elem_size); } - /* indicate the str was too short */ - if (flags != 0) { - p += snprintf(p, 2, ">"); - } + dll_pool_p->free_count = elems_max; - return (int)(p - buf); + return dll_pool_p; } -#endif -/* print bytes formatted as hex to a string. return the resulting string length */ -int -bcm_format_hex(char *str, const void *bytes, int len) +void * +dll_pool_alloc(dll_pool_t * dll_pool_p) { - int i; - char *p = str; - const uint8 *src = (const uint8*)bytes; + dll_t * elem_p; - for (i = 0; i < len; i++) { - p += snprintf(p, 3, "%02X", *src); - src++; + if (dll_pool_p->free_count == 0) { + ASSERT(dll_empty(&dll_pool_p->free_list)); + return NULL; } - return (int)(p - str); + + elem_p = dll_head_p(&dll_pool_p->free_list); + dll_delete(elem_p); + dll_pool_p->free_count -= 1; + + return (void *)elem_p; } -/* pretty hex print a contiguous buffer */ void -prhex(const char *msg, volatile uchar *buf, uint nbytes) +dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p) { - char line[128], *p; - int len = sizeof(line); - int nchar; - uint i; + dll_t * node_p = (dll_t *)elem_p; + dll_prepend(&dll_pool_p->free_list, node_p); + dll_pool_p->free_count += 1; +} - if (msg && (msg[0] != '\0')) - printf("%s:\n", msg); +void +dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p) +{ + dll_t * node_p = (dll_t *)elem_p; + dll_append(&dll_pool_p->free_list, node_p); + dll_pool_p->free_count += 1; +} - p = line; - for (i = 0; i < nbytes; i++) { - if (i % 16 == 0) { - nchar = snprintf(p, len, " %04x: ", i); /* line prefix */ - p += nchar; - len -= nchar; - } - if (len > 0) { - nchar = snprintf(p, len, "%02x ", buf[i]); - p += nchar; - len -= nchar; - } +#endif // endif - if (i % 16 == 15) { - printf("%s\n", line); /* flush line */ - p = line; - len = sizeof(line); - } - } +#endif /* BCMDRIVER */ - /* flush last partial line */ - if (p != line) - printf("%s\n", line); -} +#if defined(BCMDRIVER) || defined(WL_UNITTEST) -static const char *crypto_algo_names[] = { - "NONE", - "WEP1", - "TKIP", - "WEP128", - "AES_CCM", - "AES_OCB_MSDU", - "AES_OCB_MPDU", -#ifdef BCMCCX - "CKIP", - "CKIP_MMH", - "WEP_MMH", - "NALG", -#else - "NALG", - "UNDEF", - "UNDEF", - "UNDEF", -#endif /* BCMCCX */ -#ifdef BCMWAPI_WAI - "WAPI", -#else - "UNDEF" -#endif - "PMK", - "BIP", - "AES_GCM", - "AES_CCM256", - "AES_GCM256", - "BIP_CMAC256", - "BIP_GMAC", - "BIP_GMAC256", - "UNDEF" -}; +/* triggers bcm_bprintf to print to kernel log */ +bool bcm_bprintf_bypass = FALSE; -const char * -bcm_crypto_algo_name(uint algo) +/* Initialization of bcmstrbuf structure */ +void +bcm_binit(struct bcmstrbuf *b, char *buf, uint size) { - return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; + b->origsize = b->size = size; + b->origbuf = b->buf = buf; + if (size > 0) { + buf[0] = '\0'; + } } - -char * -bcm_chipname(uint chipid, char *buf, uint len) +/* Buffer sprintf wrapper to guard against buffer overflow */ +int +bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) { - const char *fmt; + va_list ap; + int r; - fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; - snprintf(buf, len, fmt, chipid); - return buf; + va_start(ap, fmt); + + r = vsnprintf(b->buf, b->size, fmt, ap); + if (bcm_bprintf_bypass == TRUE) { + printf("%s", b->buf); + goto exit; + } + + /* Non Ansi C99 compliant returns -1, + * Ansi compliant return r >= b->size, + * bcmstdlib returns 0, handle all + */ + /* r == 0 is also the case when strlen(fmt) is zero. + * typically the case when "" is passed as argument. + */ + if ((r == -1) || (r >= (int)b->size)) { + b->size = 0; + } else { + b->size -= r; + b->buf += r; + } + +exit: + va_end(ap); + + return r; } -/* Produce a human-readable string for boardrev */ -char * -bcm_brev_str(uint32 brev, char *buf) +void +bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len) { - if (brev < 0x100) - snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); - else - snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); + int i; - return (buf); + if (msg != NULL && msg[0] != '\0') + bcm_bprintf(b, "%s", msg); + for (i = 0; i < len; i ++) + bcm_bprintf(b, "%02X", buf[i]); + if (newline) + bcm_bprintf(b, "\n"); } -#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ - -/* dump large strings to console */ void -printbig(char *buf) +bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) { - uint len, max_len; - char c; - - len = (uint)strlen(buf); + int i; - max_len = BUFSIZE_TODUMP_ATONCE; + for (i = 0; i < num_bytes; i++) { + num[i] += amount; + if (num[i] >= amount) + break; + amount = 1; + } +} - while (len > max_len) { - c = buf[max_len]; - buf[max_len] = '\0'; - printf("%s", buf); - buf[max_len] = c; +int +bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) +{ + int i; - buf += max_len; - len -= max_len; + for (i = nbytes - 1; i >= 0; i--) { + if (arg1[i] != arg2[i]) + return (arg1[i] - arg2[i]); } - /* print the remaining string */ - printf("%s\n", buf); - return; + return 0; +} + +void +bcm_print_bytes(const char *name, const uchar *data, int len) +{ + int i; + int per_line = 0; + + printf("%s: %d \n", name ? name : "", len); + for (i = 0; i < len; i++) { + printf("%02x ", *data++); + per_line++; + if (per_line == 16) { + per_line = 0; + printf("\n"); + } + } + printf("\n"); } -/* routine to dump fields in a fileddesc structure */ -uint -bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, - char *buf, uint32 bufsize) +/* Look for vendor-specific IE with specified OUI and optional type */ +bcm_tlv_t * +bcm_find_vendor_ie(const void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len) { - uint filled_len; - int len; - struct fielddesc *cur_ptr; + const bcm_tlv_t *ie; + uint8 ie_len; - filled_len = 0; - cur_ptr = fielddesc_array; + ie = (const bcm_tlv_t*)tlvs; - while (bufsize > 1) { - if (cur_ptr->nameandfmt == NULL) - break; - len = snprintf(buf, bufsize, cur_ptr->nameandfmt, - read_rtn(arg0, arg1, cur_ptr->offset)); - /* check for snprintf overflow or error */ - if (len < 0 || (uint32)len >= bufsize) - len = bufsize - 1; - buf += len; - bufsize -= len; - filled_len += len; - cur_ptr++; + /* make sure we are looking at a valid IE */ + if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) { + return NULL; } - return filled_len; -} -uint -bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint buflen) -{ - uint len; + /* Walk through the IEs looking for an OUI match */ + do { + ie_len = ie->len; + if ((ie->id == DOT11_MNG_VS_ID) && + (ie_len >= (DOT11_OUI_LEN + type_len)) && + !bcmp(ie->data, voui, DOT11_OUI_LEN)) + { + /* compare optional type */ + if (type_len == 0 || + !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) { + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); + return (bcm_tlv_t *)(ie); /* a match */ + GCC_DIAGNOSTIC_POP(); + } + } + } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL); - len = (uint)strlen(name) + 1; + return NULL; +} - if ((len + datalen) > buflen) - return 0; +#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ + defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) +#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) - strncpy(buf, name, buflen); +int +bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) +{ + uint i, c; + char *p = buf; + char *endp = buf + SSID_FMT_BUF_LEN; - /* append data onto the end of the name string */ - if (data && datalen != 0) { - memcpy(&buf[len], data, datalen); - len += datalen; + if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; + + for (i = 0; i < ssid_len; i++) { + c = (uint)ssid[i]; + if (c == '\\') { + *p++ = '\\'; + *p++ = '\\'; + } else if (bcm_isprint((uchar)c)) { + *p++ = (char)c; + } else { + p += snprintf(p, (endp - p), "\\x%02X", c); + } } + *p = '\0'; + ASSERT(p < endp); - return len; + return (int)(p - buf); } +#endif // endif -/* Quarter dBm units to mW - * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 - * Table is offset so the last entry is largest mW value that fits in - * a uint16. - */ +#endif /* BCMDRIVER || WL_UNITTEST */ -#define QDBM_OFFSET 153 /* Offset for first entry */ -#define QDBM_TABLE_LEN 40 /* Table size */ +char * +bcm_ether_ntoa(const struct ether_addr *ea, char *buf) +{ + static const char hex[] = + { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' + }; + const uint8 *octet = ea->octet; + char *p = buf; + int i; -/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. - * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 - */ -#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ + for (i = 0; i < 6; i++, octet++) { + *p++ = hex[(*octet >> 4) & 0xf]; + *p++ = hex[*octet & 0xf]; + *p++ = ':'; + } -/* Largest mW value that will round down to the last table entry, - * QDBM_OFFSET + QDBM_TABLE_LEN-1. - * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. + *(p-1) = '\0'; + + return (buf); +} + +/* Find the position of first bit set + * in the given number. */ -#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ +int +bcm_find_fsb(uint32 num) +{ + uint8 pos = 0; + if (!num) + return pos; + while (!(num & 1)) { + num >>= 1; + pos++; + } + return (pos+1); +} -static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -}; +char * +bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) +{ + snprintf(buf, 16, "%d.%d.%d.%d", + ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); + return (buf); +} -uint16 -bcm_qdbm_to_mw(uint8 qdbm) +char * +bcm_ipv6_ntoa(void *ipv6, char *buf) { - uint factor = 1; - int idx = qdbm - QDBM_OFFSET; + /* Implementing RFC 5952 Sections 4 + 5 */ + /* Not thoroughly tested */ + uint16 tmp[8]; + uint16 *a = &tmp[0]; + char *p = buf; + int i, i_max = -1, cnt = 0, cnt_max = 1; + uint8 *a4 = NULL; + memcpy((uint8 *)&tmp[0], (uint8 *)ipv6, IPV6_ADDR_LEN); - if (idx >= QDBM_TABLE_LEN) { - /* clamp to max uint16 mW value */ - return 0xFFFF; + for (i = 0; i < IPV6_ADDR_LEN/2; i++) { + if (a[i]) { + if (cnt > cnt_max) { + cnt_max = cnt; + i_max = i - cnt; + } + cnt = 0; + } else + cnt++; + } + if (cnt > cnt_max) { + cnt_max = cnt; + i_max = i - cnt; } + if (i_max == 0 && + /* IPv4-translated: ::ffff:0:a.b.c.d */ + ((cnt_max == 4 && a[4] == 0xffff && a[5] == 0) || + /* IPv4-mapped: ::ffff:a.b.c.d */ + (cnt_max == 5 && a[5] == 0xffff))) + a4 = (uint8*) (a + 6); - /* scale the qdBm index up to the range of the table 0-40 - * where an offset of 40 qdBm equals a factor of 10 mW. - */ - while (idx < 0) { - idx += 40; - factor *= 10; + for (i = 0; i < IPV6_ADDR_LEN/2; i++) { + if ((uint8*) (a + i) == a4) { + snprintf(p, 16, ":%u.%u.%u.%u", a4[0], a4[1], a4[2], a4[3]); + break; + } else if (i == i_max) { + *p++ = ':'; + i += cnt_max - 1; + p[0] = ':'; + p[1] = '\0'; + } else { + if (i) + *p++ = ':'; + p += snprintf(p, 8, "%x", ntoh16(a[i])); + } } - /* return the mW value scaled down to the correct factor of 10, - * adding in factor/2 to get proper rounding. - */ - return ((nqdBm_to_mW_map[idx] + factor/2) / factor); + return buf; } -uint8 -bcm_mw_to_qdbm(uint16 mw) -{ - uint8 qdbm; - int offset; - uint mw_uint = mw; - uint boundary; +#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) +const unsigned char bcm_ctype[] = { - /* handle boundary case */ - if (mw_uint <= 1) - return 0; + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ + _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, + _BCM_C, /* 8-15 */ + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ + _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ + _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ + _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ + _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ + _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ + _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, + _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ + _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ + _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ + _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, + _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ + _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ + _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ + _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, + _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, + _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, + _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ +}; - offset = QDBM_OFFSET; +uint64 +bcm_strtoull(const char *cp, char **endp, uint base) +{ + uint64 result, last_result = 0, value; + bool minus; - /* move mw into the range of the table */ - while (mw_uint < QDBM_TABLE_LOW_BOUND) { - mw_uint *= 10; - offset -= 40; - } + minus = FALSE; + + while (bcm_isspace(*cp)) + cp++; - for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { - boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - - nqdBm_to_mW_map[qdbm])/2; - if (mw_uint < boundary) break; + if (cp[0] == '+') + cp++; + else if (cp[0] == '-') { + minus = TRUE; + cp++; } - qdbm += (uint8)offset; - - return (qdbm); -} + if (base == 0) { + if (cp[0] == '0') { + if ((cp[1] == 'x') || (cp[1] == 'X')) { + base = 16; + cp = &cp[2]; + } else { + base = 8; + cp = &cp[1]; + } + } else + base = 10; + } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { + cp = &cp[2]; + } + result = 0; -uint -bcm_bitcount(uint8 *bitmap, uint length) -{ - uint bitcount = 0, i; - uint8 tmp; - for (i = 0; i < length; i++) { - tmp = bitmap[i]; - while (tmp) { - bitcount++; - tmp &= (tmp - 1); + while (bcm_isxdigit(*cp) && + (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { + result = result*base + value; + /* Detected overflow */ + if (result < last_result && !minus) { + if (endp) { + /* Go to the end of current number */ + while (bcm_isxdigit(*cp)) { + cp++; + } + *endp = DISCARD_QUAL(cp, char); + } + return (ulong)-1; } + last_result = result; + cp++; } - return bitcount; -} -#if defined(BCMDRIVER) || defined(WL_UNITTEST) + if (minus) + result = (ulong)(-(long)result); -/* triggers bcm_bprintf to print to kernel log */ -bool bcm_bprintf_bypass = FALSE; + if (endp) + *endp = DISCARD_QUAL(cp, char); -/* Initialization of bcmstrbuf structure */ -void -bcm_binit(struct bcmstrbuf *b, char *buf, uint size) + return (result); +} + +ulong +bcm_strtoul(const char *cp, char **endp, uint base) { - b->origsize = b->size = size; - b->origbuf = b->buf = buf; + return (ulong) bcm_strtoull(cp, endp, base); } -/* Buffer sprintf wrapper to guard against buffer overflow */ int -bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) +bcm_atoi(const char *s) { - va_list ap; - int r; - - va_start(ap, fmt); + return (int)bcm_strtoul(s, NULL, 10); +} - r = vsnprintf(b->buf, b->size, fmt, ap); - if (bcm_bprintf_bypass == TRUE) { - printf("%s", b->buf); - goto exit; - } +/* return pointer to location of substring 'needle' in 'haystack' */ +char * +bcmstrstr(const char *haystack, const char *needle) +{ + int len, nlen; + int i; - /* Non Ansi C99 compliant returns -1, - * Ansi compliant return r >= b->size, - * bcmstdlib returns 0, handle all - */ - /* r == 0 is also the case when strlen(fmt) is zero. - * typically the case when "" is passed as argument. - */ - if ((r == -1) || (r >= (int)b->size)) { - b->size = 0; - } else { - b->size -= r; - b->buf += r; - } + if ((haystack == NULL) || (needle == NULL)) + return DISCARD_QUAL(haystack, char); -exit: - va_end(ap); + nlen = (int)strlen(needle); + len = (int)strlen(haystack) - nlen + 1; - return r; + for (i = 0; i < len; i++) + if (memcmp(needle, &haystack[i], nlen) == 0) + return DISCARD_QUAL(&haystack[i], char); + return (NULL); } -void -bcm_bprhex(struct bcmstrbuf *b, const char *msg, bool newline, const uint8 *buf, int len) +char * +bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len) { - int i; + for (; s_len >= substr_len; s++, s_len--) + if (strncmp(s, substr, substr_len) == 0) + return DISCARD_QUAL(s, char); - if (msg != NULL && msg[0] != '\0') - bcm_bprintf(b, "%s", msg); - for (i = 0; i < len; i ++) - bcm_bprintf(b, "%02X", buf[i]); - if (newline) - bcm_bprintf(b, "\n"); + return NULL; } -void -bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) +char * +bcmstrcat(char *dest, const char *src) { - int i; + char *p; - for (i = 0; i < num_bytes; i++) { - num[i] += amount; - if (num[i] >= amount) - break; - amount = 1; - } -} + p = dest + strlen(dest); -int -bcm_cmp_bytes(const uchar *arg1, const uchar *arg2, uint8 nbytes) -{ - int i; + while ((*p++ = *src++) != '\0') + ; - for (i = nbytes - 1; i >= 0; i--) { - if (arg1[i] != arg2[i]) - return (arg1[i] - arg2[i]); - } - return 0; + return (dest); } -void -bcm_print_bytes(const char *name, const uchar *data, int len) +char * +bcmstrncat(char *dest, const char *src, uint size) { - int i; - int per_line = 0; + char *endp; + char *p; - printf("%s: %d \n", name ? name : "", len); - for (i = 0; i < len; i++) { - printf("%02x ", *data++); - per_line++; - if (per_line == 16) { - per_line = 0; - printf("\n"); - } - } - printf("\n"); + p = dest + strlen(dest); + endp = p + size; + + while (p != endp && (*p++ = *src++) != '\0') + ; + + return (dest); } -/* Look for vendor-specific IE with specified OUI and optional type */ -bcm_tlv_t * -bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, int type_len) +/**************************************************************************** +* Function: bcmstrtok +* +* Purpose: +* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), +* but allows strToken() to be used by different strings or callers at the same +* time. Each call modifies '*string' by substituting a NULL character for the +* first delimiter that is encountered, and updates 'string' to point to the char +* after the delimiter. Leading delimiters are skipped. +* +* Parameters: +* string (mod) Ptr to string ptr, updated by token. +* delimiters (in) Set of delimiter characters. +* tokdelim (out) Character that delimits the returned token. (May +* be set to NULL if token delimiter is not required). +* +* Returns: Pointer to the next token found. NULL when no more tokens are found. +***************************************************************************** +*/ +char * +bcmstrtok(char **string, const char *delimiters, char *tokdelim) { - bcm_tlv_t *ie; - uint8 ie_len; + unsigned char *str; + unsigned long map[8]; + int count; + char *nextoken; - ie = (bcm_tlv_t*)tlvs; + if (tokdelim != NULL) { + /* Prime the token delimiter */ + *tokdelim = '\0'; + } - /* make sure we are looking at a valid IE */ - if (ie == NULL || !bcm_valid_tlv(ie, tlvs_len)) { - return NULL; + /* Clear control map */ + for (count = 0; count < 8; count++) { + map[count] = 0; } - /* Walk through the IEs looking for an OUI match */ + /* Set bits in delimiter table */ do { - ie_len = ie->len; - if ((ie->id == DOT11_MNG_PROPR_ID) && - (ie_len >= (DOT11_OUI_LEN + type_len)) && - !bcmp(ie->data, voui, DOT11_OUI_LEN)) - { - /* compare optional type */ - if (type_len == 0 || - !bcmp(&ie->data[DOT11_OUI_LEN], type, type_len)) { - return (ie); /* a match */ + map[*delimiters >> 5] |= (1 << (*delimiters & 31)); + } + while (*delimiters++); + + str = (unsigned char*)*string; + + /* Find beginning of token (skip over leading delimiters). Note that + * there is no token iff this loop sets str to point to the terminal + * null (*str == '\0') + */ + while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { + str++; + } + + nextoken = (char*)str; + + /* Find the end of the token. If it is not the end of the string, + * put a null there. + */ + for (; *str; str++) { + if (map[*str >> 5] & (1 << (*str & 31))) { + if (tokdelim != NULL) { + *tokdelim = *str; } + + *str++ = '\0'; + break; } - } while ((ie = bcm_next_tlv(ie, &tlvs_len)) != NULL); + } - return NULL; + *string = (char*)str; + + /* Determine if a token has been found. */ + if (nextoken == (char *) str) { + return NULL; + } + else { + return nextoken; + } } -#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ - defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) -#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) +#define xToLower(C) \ + ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) +/**************************************************************************** +* Function: bcmstricmp +* +* Purpose: Compare to strings case insensitively. +* +* Parameters: s1 (in) First string to compare. +* s2 (in) Second string to compare. +* +* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if +* t1 > t2, when ignoring case sensitivity. +***************************************************************************** +*/ int -bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) +bcmstricmp(const char *s1, const char *s2) { - uint i, c; - char *p = buf; - char *endp = buf + SSID_FMT_BUF_LEN; - - if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; + char dc, sc; - for (i = 0; i < ssid_len; i++) { - c = (uint)ssid[i]; - if (c == '\\') { - *p++ = '\\'; - *p++ = '\\'; - } else if (bcm_isprint((uchar)c)) { - *p++ = (char)c; - } else { - p += snprintf(p, (endp - p), "\\x%02X", c); - } + while (*s2 && *s1) { + dc = xToLower(*s1); + sc = xToLower(*s2); + if (dc < sc) return -1; + if (dc > sc) return 1; + s1++; + s2++; } - *p = '\0'; - ASSERT(p < endp); - return (int)(p - buf); + if (*s1 && !*s2) return 1; + if (!*s1 && *s2) return -1; + return 0; } -#endif -#endif /* BCMDRIVER || WL_UNITTEST */ - -/* - * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. - * also accepts nvram files which are already in the format of =\0\=\0 - * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. - * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. +/**************************************************************************** +* Function: bcmstrnicmp +* +* Purpose: Compare to strings case insensitively, upto a max of 'cnt' +* characters. +* +* Parameters: s1 (in) First string to compare. +* s2 (in) Second string to compare. +* cnt (in) Max characters to compare. +* +* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if +* t1 > t2, when ignoring case sensitivity. +***************************************************************************** */ - -unsigned int -process_nvram_vars(char *varbuf, unsigned int len) +int +bcmstrnicmp(const char* s1, const char* s2, int cnt) { - char *dp; - bool findNewline; - int column; - unsigned int buf_len, n; - unsigned int pad = 0; - - dp = varbuf; - - findNewline = FALSE; - column = 0; + char dc, sc; - for (n = 0; n < len; n++) { - if (varbuf[n] == '\r') - continue; - if (findNewline && varbuf[n] != '\n') - continue; - findNewline = FALSE; - if (varbuf[n] == '#') { - findNewline = TRUE; - continue; - } - if (varbuf[n] == '\n') { - if (column == 0) - continue; - *dp++ = 0; - column = 0; - continue; - } - *dp++ = varbuf[n]; - column++; - } - buf_len = (unsigned int)(dp - varbuf); - if (buf_len % 4) { - pad = 4 - buf_len % 4; - if (pad && (buf_len + pad <= len)) { - buf_len += pad; - } + while (*s2 && *s1 && cnt) { + dc = xToLower(*s1); + sc = xToLower(*s2); + if (dc < sc) return -1; + if (dc > sc) return 1; + s1++; + s2++; + cnt--; } - while (dp < varbuf + n) - *dp++ = 0; - - return buf_len; + if (!cnt) return 0; + if (*s1 && !*s2) return 1; + if (!*s1 && *s2) return -1; + return 0; } -/* calculate a * b + c */ -void -bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c) +/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ +int +bcm_ether_atoe(const char *p, struct ether_addr *ea) { -#define FORMALIZE(var) {cc += (var & 0x80000000) ? 1 : 0; var &= 0x7fffffff;} - uint32 r1, r0; - uint32 a1, a0, b1, b0, t, cc = 0; - - a1 = a >> 16; - a0 = a & 0xffff; - b1 = b >> 16; - b0 = b & 0xffff; + int i = 0; + char *ep; - r0 = a0 * b0; - FORMALIZE(r0); + for (;;) { + ea->octet[i++] = (char) bcm_strtoul(p, &ep, 16); + p = ep; + if (!*p++ || i == 6) + break; + } - t = (a1 * b0) << 16; - FORMALIZE(t); + return (i == 6); +} - r0 += t; - FORMALIZE(r0); +int +bcm_atoipv4(const char *p, struct ipv4_addr *ip) +{ - t = (a0 * b1) << 16; - FORMALIZE(t); + int i = 0; + char *c; + for (;;) { + ip->addr[i++] = (uint8)bcm_strtoul(p, &c, 0); + if (*c++ != '.' || i == IPV4_ADDR_LEN) + break; + p = c; + } + return (i == IPV4_ADDR_LEN); +} +#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ - r0 += t; - FORMALIZE(r0); +#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) +/* registry routine buffer preparation utility functions: + * parameter order is like strncpy, but returns count + * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) + */ +ulong +wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) +{ + ulong copyct = 1; + ushort i; - FORMALIZE(c); + if (abuflen == 0) + return 0; - r0 += c; - FORMALIZE(r0); + /* wbuflen is in bytes */ + wbuflen /= sizeof(ushort); - r0 |= (cc % 2) ? 0x80000000 : 0; - r1 = a1 * b1 + ((a1 * b0) >> 16) + ((b1 * a0) >> 16) + (cc / 2); + for (i = 0; i < wbuflen; ++i) { + if (--abuflen == 0) + break; + *abuf++ = (char) *wbuf++; + ++copyct; + } + *abuf = '\0'; - *r_high = r1; - *r_low = r0; + return copyct; } +#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ -/* calculate a / b */ -void -bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b) -{ - uint32 a1 = a_high, a0 = a_low, r0 = 0; +#ifdef BCM_OBJECT_TRACE - if (b < 2) - return; +#define BCM_OBJECT_MERGE_SAME_OBJ 0 - while (a1 != 0) { - r0 += (0xffffffff / b) * a1; - bcm_uint64_multiple_add(&a1, &a0, ((0xffffffff % b) + 1) % b, a1, a0); - } +/* some place may add / remove the object to trace list for Linux: */ +/* add: osl_alloc_skb dev_alloc_skb skb_realloc_headroom dhd_start_xmit */ +/* remove: osl_pktfree dev_kfree_skb netif_rx */ - r0 += a0 / b; - *r = r0; -} +#define BCM_OBJDBG_COUNT (1024 * 100) +static spinlock_t dbgobj_lock; +#define BCM_OBJDBG_LOCK_INIT() spin_lock_init(&dbgobj_lock) +#define BCM_OBJDBG_LOCK_DESTROY() +#define BCM_OBJDBG_LOCK spin_lock_irqsave +#define BCM_OBJDBG_UNLOCK spin_unlock_irqrestore -#ifndef setbit /* As in the header file */ -#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS -/* Set bit in byte array. */ -void -setbit(void *array, uint bit) -{ - ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY); -} +#define BCM_OBJDBG_ADDTOHEAD 0 +#define BCM_OBJDBG_ADDTOTAIL 1 -/* Clear bit in byte array. */ -void -clrbit(void *array, uint bit) -{ - ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY)); -} +#define BCM_OBJDBG_CALLER_LEN 32 +struct bcm_dbgobj { + struct bcm_dbgobj *prior; + struct bcm_dbgobj *next; + uint32 flag; + void *obj; + uint32 obj_sn; + uint32 obj_state; + uint32 line; + char caller[BCM_OBJDBG_CALLER_LEN]; +}; -/* Test if bit is set in byte array. */ -bool -isset(const void *array, uint bit) -{ - return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))); -} +static struct bcm_dbgobj *dbgobj_freehead = NULL; +static struct bcm_dbgobj *dbgobj_freetail = NULL; +static struct bcm_dbgobj *dbgobj_objhead = NULL; +static struct bcm_dbgobj *dbgobj_objtail = NULL; -/* Test if bit is clear in byte array. */ -bool -isclr(const void *array, uint bit) -{ - return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0); -} -#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */ -#endif /* setbit */ +static uint32 dbgobj_sn = 0; +static int dbgobj_count = 0; +static struct bcm_dbgobj bcm_dbg_objs[BCM_OBJDBG_COUNT]; void -set_bitrange(void *array, uint start, uint end, uint maxbit) +bcm_object_trace_init(void) { - uint startbyte = start/NBBY; - uint endbyte = end/NBBY; - uint i, startbytelastbit, endbytestartbit; + int i = 0; + BCM_OBJDBG_LOCK_INIT(); + memset(&bcm_dbg_objs, 0x00, sizeof(struct bcm_dbgobj) * BCM_OBJDBG_COUNT); + dbgobj_freehead = &bcm_dbg_objs[0]; + dbgobj_freetail = &bcm_dbg_objs[BCM_OBJDBG_COUNT - 1]; - if (end >= start) { - if (endbyte - startbyte > 1) - { - startbytelastbit = (startbyte+1)*NBBY - 1; - endbytestartbit = endbyte*NBBY; - for (i = startbyte+1; i < endbyte; i++) - ((uint8 *)array)[i] = 0xFF; - for (i = start; i <= startbytelastbit; i++) - setbit(array, i); - for (i = endbytestartbit; i <= end; i++) - setbit(array, i); - } else { - for (i = start; i <= end; i++) - setbit(array, i); - } - } - else { - set_bitrange(array, start, maxbit, maxbit); - set_bitrange(array, 0, end, maxbit); + for (i = 0; i < BCM_OBJDBG_COUNT; ++i) { + bcm_dbg_objs[i].next = (i == (BCM_OBJDBG_COUNT - 1)) ? + dbgobj_freehead : &bcm_dbg_objs[i + 1]; + bcm_dbg_objs[i].prior = (i == 0) ? + dbgobj_freetail : &bcm_dbg_objs[i - 1]; } } void -bcm_bitprint32(const uint32 u32arg) +bcm_object_trace_deinit(void) { - int i; - for (i = NBITS(uint32) - 1; i >= 0; i--) { - if (isbitset(u32arg, i)) { - printf("1"); - } else { - printf("0"); - } - - if ((i % NBBY) == 0) printf(" "); + if (dbgobj_objhead || dbgobj_objtail) { + printf("%s: not all objects are released\n", __FUNCTION__); + ASSERT(0); } - printf("\n"); + BCM_OBJDBG_LOCK_DESTROY(); } -/* calculate checksum for ip header, tcp / udp header / data */ -uint16 -bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum) +static void +bcm_object_rm_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, + struct bcm_dbgobj *dbgobj) { - while (len > 1) { - sum += (buf[0] << 8) | buf[1]; - buf += 2; - len -= 2; + if ((dbgobj == *head) && (dbgobj == *tail)) { + *head = NULL; + *tail = NULL; + } else if (dbgobj == *head) { + *head = (*head)->next; + } else if (dbgobj == *tail) { + *tail = (*tail)->prior; } + dbgobj->next->prior = dbgobj->prior; + dbgobj->prior->next = dbgobj->next; +} - if (len > 0) { - sum += (*buf) << 8; +static void +bcm_object_add_list(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, + struct bcm_dbgobj *dbgobj, int addtotail) +{ + if (!(*head) && !(*tail)) { + *head = dbgobj; + *tail = dbgobj; + dbgobj->next = dbgobj; + dbgobj->prior = dbgobj; + } else if ((*head) && (*tail)) { + (*tail)->next = dbgobj; + (*head)->prior = dbgobj; + dbgobj->next = *head; + dbgobj->prior = *tail; + if (addtotail == BCM_OBJDBG_ADDTOTAIL) + *tail = dbgobj; + else + *head = dbgobj; + } else { + ASSERT(0); /* can't be this case */ } +} - while (sum >> 16) { - sum = (sum & 0xffff) + (sum >> 16); +static INLINE void +bcm_object_movetoend(struct bcm_dbgobj **head, struct bcm_dbgobj **tail, + struct bcm_dbgobj *dbgobj, int movetotail) +{ + if ((*head) && (*tail)) { + if (movetotail == BCM_OBJDBG_ADDTOTAIL) { + if (dbgobj != (*tail)) { + bcm_object_rm_list(head, tail, dbgobj); + bcm_object_add_list(head, tail, dbgobj, movetotail); + } + } else { + if (dbgobj != (*head)) { + bcm_object_rm_list(head, tail, dbgobj); + bcm_object_add_list(head, tail, dbgobj, movetotail); + } + } + } else { + ASSERT(0); /* can't be this case */ } - - return ((uint16)~sum); } -#if defined(BCMDRIVER) && !defined(_CFEZ_) -/* - * Hierarchical Multiword bitmap based small id allocator. - * - * Multilevel hierarchy bitmap. (maximum 2 levels) - * First hierarchy uses a multiword bitmap to identify 32bit words in the - * second hierarchy that have at least a single bit set. Each bit in a word of - * the second hierarchy represents a unique ID that may be allocated. - * - * BCM_MWBMAP_ITEMS_MAX: Maximum number of IDs managed. - * BCM_MWBMAP_BITS_WORD: Number of bits in a bitmap word word - * BCM_MWBMAP_WORDS_MAX: Maximum number of bitmap words needed for free IDs. - * BCM_MWBMAP_WDMAP_MAX: Maximum number of bitmap wordss identifying first non - * non-zero bitmap word carrying at least one free ID. - * BCM_MWBMAP_SHIFT_OP: Used in MOD, DIV and MUL operations. - * BCM_MWBMAP_INVALID_IDX: Value ~0U is treated as an invalid ID - * - * Design Notes: - * BCM_MWBMAP_USE_CNTSETBITS trades CPU for memory. A runtime count of how many - * bits are computed each time on allocation and deallocation, requiring 4 - * array indexed access and 3 arithmetic operations. When not defined, a runtime - * count of set bits state is maintained. Upto 32 Bytes per 1024 IDs is needed. - * In a 4K max ID allocator, up to 128Bytes are hence used per instantiation. - * In a memory limited system e.g. dongle builds, a CPU for memory tradeoff may - * be used by defining BCM_MWBMAP_USE_CNTSETBITS. - * - * Note: wd_bitmap[] is statically declared and is not ROM friendly ... array - * size is fixed. No intention to support larger than 4K indice allocation. ID - * allocators for ranges smaller than 4K will have a wastage of only 12Bytes - * with savings in not having to use an indirect access, had it been dynamically - * allocated. - */ -#define BCM_MWBMAP_ITEMS_MAX (64 * 1024) /* May increase to 64K */ - -#define BCM_MWBMAP_BITS_WORD (NBITS(uint32)) -#define BCM_MWBMAP_WORDS_MAX (BCM_MWBMAP_ITEMS_MAX / BCM_MWBMAP_BITS_WORD) -#define BCM_MWBMAP_WDMAP_MAX (BCM_MWBMAP_WORDS_MAX / BCM_MWBMAP_BITS_WORD) -#define BCM_MWBMAP_SHIFT_OP (5) -#define BCM_MWBMAP_MODOP(ix) ((ix) & (BCM_MWBMAP_BITS_WORD - 1)) -#define BCM_MWBMAP_DIVOP(ix) ((ix) >> BCM_MWBMAP_SHIFT_OP) -#define BCM_MWBMAP_MULOP(ix) ((ix) << BCM_MWBMAP_SHIFT_OP) - -/* Redefine PTR() and/or HDL() conversion to invoke audit for debugging */ -#define BCM_MWBMAP_PTR(hdl) ((struct bcm_mwbmap *)(hdl)) -#define BCM_MWBMAP_HDL(ptr) ((void *)(ptr)) - -#if defined(BCM_MWBMAP_DEBUG) -#define BCM_MWBMAP_AUDIT(mwb) \ - do { \ - ASSERT((mwb != NULL) && \ - (((struct bcm_mwbmap *)(mwb))->magic == (void *)(mwb))); \ - bcm_mwbmap_audit(mwb); \ - } while (0) -#define MWBMAP_ASSERT(exp) ASSERT(exp) -#define MWBMAP_DBG(x) printf x -#else /* !BCM_MWBMAP_DEBUG */ -#define BCM_MWBMAP_AUDIT(mwb) do {} while (0) -#define MWBMAP_ASSERT(exp) do {} while (0) -#define MWBMAP_DBG(x) -#endif /* !BCM_MWBMAP_DEBUG */ - - -typedef struct bcm_mwbmap { /* Hierarchical multiword bitmap allocator */ - uint16 wmaps; /* Total number of words in free wd bitmap */ - uint16 imaps; /* Total number of words in free id bitmap */ - int32 ifree; /* Count of free indices. Used only in audits */ - uint16 total; /* Total indices managed by multiword bitmap */ - void * magic; /* Audit handle parameter from user */ +void +bcm_object_trace_opr(void *obj, uint32 opt, const char *caller, int line) +{ + struct bcm_dbgobj *dbgobj; + unsigned long flags; - uint32 wd_bitmap[BCM_MWBMAP_WDMAP_MAX]; /* 1st level bitmap of */ -#if !defined(BCM_MWBMAP_USE_CNTSETBITS) - int8 wd_count[BCM_MWBMAP_WORDS_MAX]; /* free id running count, 1st lvl */ -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ + BCM_REFERENCE(flags); + BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - uint32 id_bitmap[0]; /* Second level bitmap */ -} bcm_mwbmap_t; + if (opt == BCM_OBJDBG_ADD_PKT || + opt == BCM_OBJDBG_ADD) { + dbgobj = dbgobj_objtail; + while (dbgobj) { + if (dbgobj->obj == obj) { + printf("%s: obj %p allocated from %s(%d)," + " allocate again from %s(%d)\n", + __FUNCTION__, dbgobj->obj, + dbgobj->caller, dbgobj->line, + caller, line); + ASSERT(0); + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } -/* Incarnate a hierarchical multiword bitmap based small index allocator. */ -struct bcm_mwbmap * -bcm_mwbmap_init(osl_t *osh, uint32 items_max) -{ - struct bcm_mwbmap * mwbmap_p; - uint32 wordix, size, words, extra; +#if BCM_OBJECT_MERGE_SAME_OBJ + dbgobj = dbgobj_freetail; + while (dbgobj) { + if (dbgobj->obj == obj) { + goto FREED_ENTRY_FOUND; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_freetail) + break; + } +#endif /* BCM_OBJECT_MERGE_SAME_OBJ */ - /* Implementation Constraint: Uses 32bit word bitmap */ - MWBMAP_ASSERT(BCM_MWBMAP_BITS_WORD == 32U); - MWBMAP_ASSERT(BCM_MWBMAP_SHIFT_OP == 5U); - MWBMAP_ASSERT(ISPOWEROF2(BCM_MWBMAP_ITEMS_MAX)); - MWBMAP_ASSERT((BCM_MWBMAP_ITEMS_MAX % BCM_MWBMAP_BITS_WORD) == 0U); + dbgobj = dbgobj_freehead; +#if BCM_OBJECT_MERGE_SAME_OBJ +FREED_ENTRY_FOUND: +#endif /* BCM_OBJECT_MERGE_SAME_OBJ */ + if (!dbgobj) { + printf("%s: already got %d objects ?????????????????????\n", + __FUNCTION__, BCM_OBJDBG_COUNT); + ASSERT(0); + goto EXIT; + } - ASSERT(items_max <= BCM_MWBMAP_ITEMS_MAX); + bcm_object_rm_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj); + dbgobj->obj = obj; + strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN); + dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0'; + dbgobj->line = line; + dbgobj->flag = 0; + if (opt == BCM_OBJDBG_ADD_PKT) { + dbgobj->obj_sn = dbgobj_sn++; + dbgobj->obj_state = 0; + /* first 4 bytes is pkt sn */ + if (((unsigned long)PKTTAG(obj)) & 0x3) + printf("pkt tag address not aligned by 4: %p\n", PKTTAG(obj)); + *(uint32*)PKTTAG(obj) = dbgobj->obj_sn; + } + bcm_object_add_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj, + BCM_OBJDBG_ADDTOTAIL); - /* Determine the number of words needed in the multiword bitmap */ - extra = BCM_MWBMAP_MODOP(items_max); - words = BCM_MWBMAP_DIVOP(items_max) + ((extra != 0U) ? 1U : 0U); + dbgobj_count++; - /* Allocate runtime state of multiword bitmap */ - /* Note: wd_count[] or wd_bitmap[] are not dynamically allocated */ - size = sizeof(bcm_mwbmap_t) + (sizeof(uint32) * words); - mwbmap_p = (bcm_mwbmap_t *)MALLOC(osh, size); - if (mwbmap_p == (bcm_mwbmap_t *)NULL) { - ASSERT(0); - goto error1; - } - memset(mwbmap_p, 0, size); + } else if (opt == BCM_OBJDBG_REMOVE) { + dbgobj = dbgobj_objtail; + while (dbgobj) { + if (dbgobj->obj == obj) { + if (dbgobj->flag) { + printf("%s: rm flagged obj %p flag 0x%08x from %s(%d)\n", + __FUNCTION__, obj, dbgobj->flag, caller, line); + } + bcm_object_rm_list(&dbgobj_objhead, &dbgobj_objtail, dbgobj); + memset(dbgobj->caller, 0x00, BCM_OBJDBG_CALLER_LEN); + strncpy(dbgobj->caller, caller, BCM_OBJDBG_CALLER_LEN); + dbgobj->caller[BCM_OBJDBG_CALLER_LEN-1] = '\0'; + dbgobj->line = line; + bcm_object_add_list(&dbgobj_freehead, &dbgobj_freetail, dbgobj, + BCM_OBJDBG_ADDTOTAIL); + dbgobj_count--; + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } - /* Initialize runtime multiword bitmap state */ - mwbmap_p->imaps = (uint16)words; - mwbmap_p->ifree = (int32)items_max; - mwbmap_p->total = (uint16)items_max; + dbgobj = dbgobj_freetail; + while (dbgobj && dbgobj->obj) { + if (dbgobj->obj == obj) { + printf("%s: obj %p already freed from from %s(%d)," + " try free again from %s(%d)\n", + __FUNCTION__, obj, + dbgobj->caller, dbgobj->line, + caller, line); + //ASSERT(0); /* release same obj more than one time? */ + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_freetail) + break; + } - /* Setup magic, for use in audit of handle */ - mwbmap_p->magic = BCM_MWBMAP_HDL(mwbmap_p); + printf("%s: ################### release none-existing obj %p from %s(%d)\n", + __FUNCTION__, obj, caller, line); + //ASSERT(0); /* release same obj more than one time? */ - /* Setup the second level bitmap of free indices */ - /* Mark all indices as available */ - for (wordix = 0U; wordix < mwbmap_p->imaps; wordix++) { - mwbmap_p->id_bitmap[wordix] = (uint32)(~0U); -#if !defined(BCM_MWBMAP_USE_CNTSETBITS) - mwbmap_p->wd_count[wordix] = BCM_MWBMAP_BITS_WORD; -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ } - /* Ensure that extra indices are tagged as un-available */ - if (extra) { /* fixup the free ids in last bitmap and wd_count */ - uint32 * bmap_p = &mwbmap_p->id_bitmap[mwbmap_p->imaps - 1]; - *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ -#if !defined(BCM_MWBMAP_USE_CNTSETBITS) - mwbmap_p->wd_count[mwbmap_p->imaps - 1] = (int8)extra; /* fixup count */ -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - } +EXIT: + BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); + return; +} - /* Setup the first level bitmap hierarchy */ - extra = BCM_MWBMAP_MODOP(mwbmap_p->imaps); - words = BCM_MWBMAP_DIVOP(mwbmap_p->imaps) + ((extra != 0U) ? 1U : 0U); +void +bcm_object_trace_upd(void *obj, void *obj_new) +{ + struct bcm_dbgobj *dbgobj; + unsigned long flags; - mwbmap_p->wmaps = (uint16)words; + BCM_REFERENCE(flags); + BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - for (wordix = 0U; wordix < mwbmap_p->wmaps; wordix++) - mwbmap_p->wd_bitmap[wordix] = (uint32)(~0U); - if (extra) { - uint32 * bmap_p = &mwbmap_p->wd_bitmap[mwbmap_p->wmaps - 1]; - *bmap_p ^= (uint32)(~0U << extra); /* fixup bitmap */ + dbgobj = dbgobj_objtail; + while (dbgobj) { + if (dbgobj->obj == obj) { + dbgobj->obj = obj_new; + if (dbgobj != dbgobj_objtail) { + bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, + dbgobj, BCM_OBJDBG_ADDTOTAIL); + } + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; } - return mwbmap_p; - -error1: - return BCM_MWBMAP_INVALID_HDL; +EXIT: + BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); + return; } -/* Release resources used by multiword bitmap based small index allocator. */ void -bcm_mwbmap_fini(osl_t * osh, struct bcm_mwbmap * mwbmap_hdl) +bcm_object_trace_chk(void *obj, uint32 chksn, uint32 sn, + const char *caller, int line) { - bcm_mwbmap_t * mwbmap_p; + struct bcm_dbgobj *dbgobj; + unsigned long flags; - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + BCM_REFERENCE(flags); + BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - MFREE(osh, mwbmap_p, sizeof(struct bcm_mwbmap) - + (sizeof(uint32) * mwbmap_p->imaps)); + dbgobj = dbgobj_objtail; + while (dbgobj) { + if ((dbgobj->obj == obj) && + ((!chksn) || (dbgobj->obj_sn == sn))) { + if (dbgobj != dbgobj_objtail) { + bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, + dbgobj, BCM_OBJDBG_ADDTOTAIL); + } + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } + + dbgobj = dbgobj_freetail; + while (dbgobj) { + if ((dbgobj->obj == obj) && + ((!chksn) || (dbgobj->obj_sn == sn))) { + printf("%s: (%s:%d) obj %p (sn %d state %d) was freed from %s(%d)\n", + __FUNCTION__, caller, line, + dbgobj->obj, dbgobj->obj_sn, dbgobj->obj_state, + dbgobj->caller, dbgobj->line); + goto EXIT; + } + else if (dbgobj->obj == NULL) { + break; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_freetail) + break; + } + + printf("%s: obj %p not found, check from %s(%d), chksn %s, sn %d\n", + __FUNCTION__, obj, caller, line, chksn ? "yes" : "no", sn); + dbgobj = dbgobj_objtail; + while (dbgobj) { + printf("%s: (%s:%d) obj %p sn %d was allocated from %s(%d)\n", + __FUNCTION__, caller, line, + dbgobj->obj, dbgobj->obj_sn, dbgobj->caller, dbgobj->line); + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } + +EXIT: + BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); return; } -/* Allocate a unique small index using a multiword bitmap index allocator. */ -uint32 BCMFASTPATH -bcm_mwbmap_alloc(struct bcm_mwbmap * mwbmap_hdl) +void +bcm_object_feature_set(void *obj, uint32 type, uint32 value) { - bcm_mwbmap_t * mwbmap_p; - uint32 wordix, bitmap; - - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + struct bcm_dbgobj *dbgobj; + unsigned long flags; - /* Start with the first hierarchy */ - for (wordix = 0; wordix < mwbmap_p->wmaps; ++wordix) { + BCM_REFERENCE(flags); + BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - bitmap = mwbmap_p->wd_bitmap[wordix]; /* get the word bitmap */ + dbgobj = dbgobj_objtail; + while (dbgobj) { + if (dbgobj->obj == obj) { + if (type == BCM_OBJECT_FEATURE_FLAG) { + if (value & BCM_OBJECT_FEATURE_CLEAR) + dbgobj->flag &= ~(value); + else + dbgobj->flag |= (value); + } else if (type == BCM_OBJECT_FEATURE_PKT_STATE) { + dbgobj->obj_state = value; + } + if (dbgobj != dbgobj_objtail) { + bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, + dbgobj, BCM_OBJDBG_ADDTOTAIL); + } + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } - if (bitmap != 0U) { + printf("%s: obj %p not found in active list\n", __FUNCTION__, obj); + ASSERT(0); - uint32 count, bitix, *bitmap_p; +EXIT: + BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); + return; +} - bitmap_p = &mwbmap_p->wd_bitmap[wordix]; +int +bcm_object_feature_get(void *obj, uint32 type, uint32 value) +{ + int rtn = 0; + struct bcm_dbgobj *dbgobj; + unsigned long flags; - /* clear all except trailing 1 */ - bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); - MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == - bcm_count_leading_zeros(bitmap)); - bitix = (BCM_MWBMAP_BITS_WORD - 1) - - bcm_count_leading_zeros(bitmap); /* use asm clz */ - wordix = BCM_MWBMAP_MULOP(wordix) + bitix; + BCM_REFERENCE(flags); + BCM_OBJDBG_LOCK(&dbgobj_lock, flags); - /* Clear bit if wd count is 0, without conditional branch */ -#if defined(BCM_MWBMAP_USE_CNTSETBITS) - count = bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1; -#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ - mwbmap_p->wd_count[wordix]--; - count = mwbmap_p->wd_count[wordix]; - MWBMAP_ASSERT(count == - (bcm_cntsetbits(mwbmap_p->id_bitmap[wordix]) - 1)); -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - MWBMAP_ASSERT(count >= 0); + dbgobj = dbgobj_objtail; + while (dbgobj) { + if (dbgobj->obj == obj) { + if (type == BCM_OBJECT_FEATURE_FLAG) { + rtn = (dbgobj->flag & value) & (~BCM_OBJECT_FEATURE_CLEAR); + } + if (dbgobj != dbgobj_objtail) { + bcm_object_movetoend(&dbgobj_objhead, &dbgobj_objtail, + dbgobj, BCM_OBJDBG_ADDTOTAIL); + } + goto EXIT; + } + dbgobj = dbgobj->prior; + if (dbgobj == dbgobj_objtail) + break; + } - /* clear wd_bitmap bit if id_map count is 0 */ - bitmap = (count == 0) << bitix; + printf("%s: obj %p not found in active list\n", __FUNCTION__, obj); + ASSERT(0); - MWBMAP_DBG(( - "Lvl1: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x wfree %d", - bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, count)); +EXIT: + BCM_OBJDBG_UNLOCK(&dbgobj_lock, flags); + return rtn; +} - *bitmap_p ^= bitmap; +#endif /* BCM_OBJECT_TRACE */ - /* Use bitix in the second hierarchy */ - bitmap_p = &mwbmap_p->id_bitmap[wordix]; +uint8 * +bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst) +{ + uint8 *new_dst = dst; + bcm_tlv_t *dst_tlv = (bcm_tlv_t *)dst; - bitmap = mwbmap_p->id_bitmap[wordix]; /* get the id bitmap */ - MWBMAP_ASSERT(bitmap != 0U); + /* dst buffer should always be valid */ + ASSERT(dst); - /* clear all except trailing 1 */ - bitmap = (uint32)(((int)(bitmap)) & (-((int)(bitmap)))); - MWBMAP_ASSERT(C_bcm_count_leading_zeros(bitmap) == - bcm_count_leading_zeros(bitmap)); - bitix = BCM_MWBMAP_MULOP(wordix) - + (BCM_MWBMAP_BITS_WORD - 1) - - bcm_count_leading_zeros(bitmap); /* use asm clz */ + /* data len must be within valid range */ + ASSERT((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)); - mwbmap_p->ifree--; /* decrement system wide free count */ - MWBMAP_ASSERT(mwbmap_p->ifree >= 0); + /* source data buffer pointer should be valid, unless datalen is 0 + * meaning no data with this TLV + */ + ASSERT((data != NULL) || (datalen == 0)); - MWBMAP_DBG(( - "Lvl2: bitix<%02u> wordix<%02u>: %08x ^ %08x = %08x ifree %d", - bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, - mwbmap_p->ifree)); + /* only do work if the inputs are valid + * - must have a dst to write to AND + * - datalen must be within range AND + * - the source data pointer must be non-NULL if datalen is non-zero + * (this last condition detects datalen > 0 with a NULL data pointer) + */ + if ((dst != NULL) && + ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) && + ((data != NULL) || (datalen == 0))) { - *bitmap_p ^= bitmap; /* mark as allocated = 1b0 */ + /* write type, len fields */ + dst_tlv->id = (uint8)type; + dst_tlv->len = (uint8)datalen; - return bitix; + /* if data is present, copy to the output buffer and update + * pointer to output buffer + */ + if (datalen > 0) { + + memcpy(dst_tlv->data, data, datalen); } - } - ASSERT(mwbmap_p->ifree == 0); + /* update the output destination poitner to point past + * the TLV written + */ + new_dst = dst + BCM_TLV_HDR_SIZE + datalen; + } - return BCM_MWBMAP_INVALID_IDX; + return (new_dst); } -/* Force an index at a specified position to be in use */ -void -bcm_mwbmap_force(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) +uint8 * +bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst) { - bcm_mwbmap_t * mwbmap_p; - uint32 count, wordix, bitmap, *bitmap_p; - - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + uint8 *new_dst = dst; + bcm_tlv_ext_t *dst_tlv = (bcm_tlv_ext_t *)dst; - ASSERT(bitix < mwbmap_p->total); + /* dst buffer should always be valid */ + ASSERT(dst); - /* Start with second hierarchy */ - wordix = BCM_MWBMAP_DIVOP(bitix); - bitmap = (uint32)(1U << BCM_MWBMAP_MODOP(bitix)); - bitmap_p = &mwbmap_p->id_bitmap[wordix]; + /* data len must be within valid range */ + ASSERT(datalen <= BCM_TLV_EXT_MAX_DATA_SIZE); - ASSERT((*bitmap_p & bitmap) == bitmap); + /* source data buffer pointer should be valid, unless datalen is 0 + * meaning no data with this TLV + */ + ASSERT((data != NULL) || (datalen == 0)); - mwbmap_p->ifree--; /* update free count */ - ASSERT(mwbmap_p->ifree >= 0); + /* only do work if the inputs are valid + * - must have a dst to write to AND + * - datalen must be within range AND + * - the source data pointer must be non-NULL if datalen is non-zero + * (this last condition detects datalen > 0 with a NULL data pointer) + */ + if ((dst != NULL) && + (datalen <= BCM_TLV_EXT_MAX_DATA_SIZE) && + ((data != NULL) || (datalen == 0))) { - MWBMAP_DBG(("Lvl2: bitix<%u> wordix<%u>: %08x ^ %08x = %08x ifree %d", - bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) ^ bitmap, - mwbmap_p->ifree)); + /* write type, len fields */ + dst_tlv->id = (uint8)type; + dst_tlv->ext = ext; + dst_tlv->len = 1 + (uint8)datalen; - *bitmap_p ^= bitmap; /* mark as in use */ + /* if data is present, copy to the output buffer and update + * pointer to output buffer + */ + if (datalen > 0) { + memcpy(dst_tlv->data, data, datalen); + } - /* Update first hierarchy */ - bitix = wordix; + /* update the output destination poitner to point past + * the TLV written + */ + new_dst = dst + BCM_TLV_EXT_HDR_SIZE + datalen; + } - wordix = BCM_MWBMAP_DIVOP(bitix); - bitmap_p = &mwbmap_p->wd_bitmap[wordix]; + return (new_dst); +} -#if defined(BCM_MWBMAP_USE_CNTSETBITS) - count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); -#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ - mwbmap_p->wd_count[bitix]--; - count = mwbmap_p->wd_count[bitix]; - MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - MWBMAP_ASSERT(count >= 0); +uint8 * +bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, int dst_maxlen) +{ + uint8 *new_dst = dst; - bitmap = (count == 0) << BCM_MWBMAP_MODOP(bitix); + if ((datalen >= 0) && (datalen <= BCM_TLV_MAX_DATA_SIZE)) { - MWBMAP_DBG(("Lvl1: bitix<%02lu> wordix<%02u>: %08x ^ %08x = %08x wfree %d", - BCM_MWBMAP_MODOP(bitix), wordix, *bitmap_p, bitmap, - (*bitmap_p) ^ bitmap, count)); + /* if len + tlv hdr len is more than destlen, don't do anything + * just return the buffer untouched + */ + if ((int)(datalen + BCM_TLV_HDR_SIZE) <= dst_maxlen) { - *bitmap_p ^= bitmap; /* mark as in use */ + new_dst = bcm_write_tlv(type, data, datalen, dst); + } + } - return; + return (new_dst); } -/* Free a previously allocated index back into the multiword bitmap allocator */ -void BCMFASTPATH -bcm_mwbmap_free(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) +uint8 * +bcm_copy_tlv(const void *src, uint8 *dst) { - bcm_mwbmap_t * mwbmap_p; - uint32 wordix, bitmap, *bitmap_p; - - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - - ASSERT(bitix < mwbmap_p->total); + uint8 *new_dst = dst; + const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src; + uint totlen; - /* Start with second level hierarchy */ - wordix = BCM_MWBMAP_DIVOP(bitix); - bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); - bitmap_p = &mwbmap_p->id_bitmap[wordix]; + ASSERT(dst && src); + if (dst && src) { - ASSERT((*bitmap_p & bitmap) == 0U); /* ASSERT not a double free */ + totlen = BCM_TLV_HDR_SIZE + src_tlv->len; + memcpy(dst, src_tlv, totlen); + new_dst = dst + totlen; + } - mwbmap_p->ifree++; /* update free count */ - ASSERT(mwbmap_p->ifree <= mwbmap_p->total); + return (new_dst); +} - MWBMAP_DBG(("Lvl2: bitix<%02u> wordix<%02u>: %08x | %08x = %08x ifree %d", - bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, - mwbmap_p->ifree)); +uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen) +{ + uint8 *new_dst = dst; + const bcm_tlv_t *src_tlv = (const bcm_tlv_t *)src; - *bitmap_p |= bitmap; /* mark as available */ + ASSERT(src); + if (src) { + if (bcm_valid_tlv(src_tlv, dst_maxlen)) { + new_dst = bcm_copy_tlv(src, dst); + } + } - /* Now update first level hierarchy */ + return (new_dst); +} - bitix = wordix; +#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) +/******************************************************************************* + * crc8 + * + * Computes a crc8 over the input data using the polynomial: + * + * x^8 + x^7 +x^6 + x^4 + x^2 + 1 + * + * The caller provides the initial value (either CRC8_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC8_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ - wordix = BCM_MWBMAP_DIVOP(bitix); /* first level's word index */ - bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); - bitmap_p = &mwbmap_p->wd_bitmap[wordix]; +static const uint8 crc8_table[256] = { + 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, + 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, + 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, + 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, + 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, + 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, + 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, + 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, + 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, + 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, + 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, + 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, + 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, + 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, + 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, + 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, + 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, + 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, + 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, + 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, + 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, + 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, + 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, + 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, + 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, + 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, + 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, + 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, + 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, + 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, + 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, + 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F +}; -#if !defined(BCM_MWBMAP_USE_CNTSETBITS) - mwbmap_p->wd_count[bitix]++; -#endif +#define CRC_INNER_LOOP(n, c, x) \ + (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] -#if defined(BCM_MWBMAP_DEBUG) - { - uint32 count; -#if defined(BCM_MWBMAP_USE_CNTSETBITS) - count = bcm_cntsetbits(mwbmap_p->id_bitmap[bitix]); -#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ - count = mwbmap_p->wd_count[bitix]; - MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[bitix])); -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ +uint8 +hndcrc8( + const uint8 *pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint8 crc /* either CRC8_INIT_VALUE or previous return value */ +) +{ + /* hard code the crc loop instead of using CRC_INNER_LOOP macro + * to avoid the undefined and unnecessary (uint8 >> 8) operation. + */ + while (nbytes-- > 0) + crc = crc8_table[(crc ^ *pdata++) & 0xff]; - MWBMAP_ASSERT(count <= BCM_MWBMAP_BITS_WORD); + return crc; +} - MWBMAP_DBG(("Lvl1: bitix<%02u> wordix<%02u>: %08x | %08x = %08x wfree %d", - bitix, wordix, *bitmap_p, bitmap, (*bitmap_p) | bitmap, count)); - } -#endif /* BCM_MWBMAP_DEBUG */ +/******************************************************************************* + * crc16 + * + * Computes a crc16 over the input data using the polynomial: + * + * x^16 + x^12 +x^5 + 1 + * + * The caller provides the initial value (either CRC16_INIT_VALUE + * or the previous returned value) to allow for processing of + * discontiguous blocks of data. When generating the CRC the + * caller is responsible for complementing the final return value + * and inserting it into the byte stream. When checking, a final + * return value of CRC16_GOOD_VALUE indicates a valid CRC. + * + * Reference: Dallas Semiconductor Application Note 27 + * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", + * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., + * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt + * + * **************************************************************************** + */ - *bitmap_p |= bitmap; +static const uint16 crc16_table[256] = { + 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, + 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, + 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, + 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, + 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, + 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, + 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, + 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, + 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, + 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, + 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, + 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, + 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, + 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, + 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, + 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, + 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, + 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, + 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, + 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, + 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, + 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, + 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, + 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, + 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, + 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, + 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, + 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, + 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, + 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, + 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, + 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 +}; - return; +uint16 +hndcrc16( + const uint8 *pdata, /* pointer to array of data to process */ + uint nbytes, /* number of input data bytes to process */ + uint16 crc /* either CRC16_INIT_VALUE or previous return value */ +) +{ + while (nbytes-- > 0) + CRC_INNER_LOOP(16, crc, *pdata++); + return crc; } -/* Fetch the toal number of free indices in the multiword bitmap allocator */ +static const uint32 crc32_table[256] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D +}; + +/* + * crc input is CRC32_INIT_VALUE for a fresh start, or previous return value if + * accumulating over multiple pieces. + */ uint32 -bcm_mwbmap_free_cnt(struct bcm_mwbmap * mwbmap_hdl) +hndcrc32(const uint8 *pdata, uint nbytes, uint32 crc) { - bcm_mwbmap_t * mwbmap_p; - - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); - - ASSERT(mwbmap_p->ifree >= 0); + const uint8 *pend; + pend = pdata + nbytes; + while (pdata < pend) + CRC_INNER_LOOP(32, crc, *pdata++); - return mwbmap_p->ifree; + return crc; } -/* Determine whether an index is inuse or free */ -bool -bcm_mwbmap_isfree(struct bcm_mwbmap * mwbmap_hdl, uint32 bitix) +#ifdef notdef +#define CLEN 1499 /* CRC Length */ +#define CBUFSIZ (CLEN+4) +#define CNBUFS 5 /* # of bufs */ + +void +testcrc32(void) { - bcm_mwbmap_t * mwbmap_p; - uint32 wordix, bitmap; + uint j, k, l; + uint8 *buf; + uint len[CNBUFS]; + uint32 crcr; + uint32 crc32tv[CNBUFS] = + {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); - ASSERT(bitix < mwbmap_p->total); + /* step through all possible alignments */ + for (l = 0; l <= 4; l++) { + for (j = 0; j < CNBUFS; j++) { + len[j] = CLEN; + for (k = 0; k < len[j]; k++) + *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; + } - wordix = BCM_MWBMAP_DIVOP(bitix); - bitmap = (1U << BCM_MWBMAP_MODOP(bitix)); + for (j = 0; j < CNBUFS; j++) { + crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); + ASSERT(crcr == crc32tv[j]); + } + } - return ((mwbmap_p->id_bitmap[wordix] & bitmap) != 0U); + MFREE(buf, CBUFSIZ*CNBUFS); + return; } +#endif /* notdef */ -/* Debug dump a multiword bitmap allocator */ -void -bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl) +/* + * Advance from the current 1-byte tag/1-byte length/variable-length value + * triple, to the next, returning a pointer to the next. + * If the current or next TLV is invalid (does not fit in given buffer length), + * NULL is returned. + * *buflen is not modified if the TLV elt parameter is invalid, or is decremented + * by the TLV parameter's length if it is valid. + */ +bcm_tlv_t * +bcm_next_tlv(const bcm_tlv_t *elt, int *buflen) { - uint32 ix, count; - bcm_mwbmap_t * mwbmap_p; - - BCM_MWBMAP_AUDIT(mwbmap_hdl); - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + int len; - printf("mwbmap_p %p wmaps %u imaps %u ifree %d total %u\n", mwbmap_p, - mwbmap_p->wmaps, mwbmap_p->imaps, mwbmap_p->ifree, mwbmap_p->total); - for (ix = 0U; ix < mwbmap_p->wmaps; ix++) { - printf("\tWDMAP:%2u. 0x%08x\t", ix, mwbmap_p->wd_bitmap[ix]); - bcm_bitprint32(mwbmap_p->wd_bitmap[ix]); - printf("\n"); + /* validate current elt */ + if (!bcm_valid_tlv(elt, *buflen)) { + return NULL; } - for (ix = 0U; ix < mwbmap_p->imaps; ix++) { -#if defined(BCM_MWBMAP_USE_CNTSETBITS) - count = bcm_cntsetbits(mwbmap_p->id_bitmap[ix]); -#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ - count = mwbmap_p->wd_count[ix]; - MWBMAP_ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[ix])); -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - printf("\tIDMAP:%2u. 0x%08x %02u\t", ix, mwbmap_p->id_bitmap[ix], count); - bcm_bitprint32(mwbmap_p->id_bitmap[ix]); - printf("\n"); + + /* advance to next elt */ + len = elt->len; + elt = (const bcm_tlv_t*)(elt->data + len); + *buflen -= (TLV_HDR_LEN + len); + + /* validate next elt */ + if (!bcm_valid_tlv(elt, *buflen)) { + return NULL; } - return; + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); + return (bcm_tlv_t *)(elt); + GCC_DIAGNOSTIC_POP(); } -/* Audit a hierarchical multiword bitmap */ -void -bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl) +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + */ +bcm_tlv_t * +bcm_parse_tlvs(const void *buf, int buflen, uint key) { - bcm_mwbmap_t * mwbmap_p; - uint32 count, free_cnt = 0U, wordix, idmap_ix, bitix, *bitmap_p; - - mwbmap_p = BCM_MWBMAP_PTR(mwbmap_hdl); + const bcm_tlv_t *elt; + int totlen; - for (wordix = 0U; wordix < mwbmap_p->wmaps; ++wordix) { + if ((elt = (const bcm_tlv_t*)buf) == NULL) { + return NULL; + } + totlen = buflen; - bitmap_p = &mwbmap_p->wd_bitmap[wordix]; + /* find tagged parameter */ + while (totlen >= TLV_HDR_LEN) { + int len = elt->len; - for (bitix = 0U; bitix < BCM_MWBMAP_BITS_WORD; bitix++) { - if ((*bitmap_p) & (1 << bitix)) { - idmap_ix = BCM_MWBMAP_MULOP(wordix) + bitix; -#if defined(BCM_MWBMAP_USE_CNTSETBITS) - count = bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix]); -#else /* ! BCM_MWBMAP_USE_CNTSETBITS */ - count = mwbmap_p->wd_count[idmap_ix]; - ASSERT(count == bcm_cntsetbits(mwbmap_p->id_bitmap[idmap_ix])); -#endif /* ! BCM_MWBMAP_USE_CNTSETBITS */ - ASSERT(count != 0U); - free_cnt += count; - } + /* validate remaining totlen */ + if ((elt->id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) { + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); + return (bcm_tlv_t *)(elt); + GCC_DIAGNOSTIC_POP(); } + + elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN)); + totlen -= (len + TLV_HDR_LEN); } - ASSERT((int)free_cnt == mwbmap_p->ifree); + return NULL; } -/* END : Multiword bitmap based 64bit to Unique 32bit Id allocator. */ -/* Simple 16bit Id allocator using a stack implementation. */ -typedef struct id16_map { - uint32 failures; /* count of failures */ - void *dbg; /* debug placeholder */ - uint16 total; /* total number of ids managed by allocator */ - uint16 start; /* start value of 16bit ids to be managed */ - int stack_idx; /* index into stack of available ids */ - uint16 stack[0]; /* stack of 16 bit ids */ -} id16_map_t; +bcm_tlv_t * +bcm_parse_tlvs_dot11(const void *buf, int buflen, uint key, bool id_ext) +{ + bcm_tlv_t *elt; + int totlen; -#define ID16_MAP_SZ(items) (sizeof(id16_map_t) + \ - (sizeof(uint16) * (items))) + /* + ideally, we don't want to do that, but returning a const pointer + from these parse function spreads casting everywhere in the code + */ + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); + elt = (bcm_tlv_t*)buf; + GCC_DIAGNOSTIC_POP(); -#if defined(BCM_DBG) + totlen = buflen; -/* Uncomment BCM_DBG_ID16 to debug double free */ -/* #define BCM_DBG_ID16 */ + /* find tagged parameter */ + while (totlen >= TLV_HDR_LEN) { + int len = elt->len; -typedef struct id16_map_dbg { - uint16 total; - bool avail[0]; -} id16_map_dbg_t; -#define ID16_MAP_DBG_SZ(items) (sizeof(id16_map_dbg_t) + \ - (sizeof(bool) * (items))) -#define ID16_MAP_MSG(x) print x -#else -#define ID16_MAP_MSG(x) -#endif /* BCM_DBG */ + do { + /* validate remaining totlen */ + if (totlen < (int)(len + TLV_HDR_LEN)) + break; -void * /* Construct an id16 allocator: [start_val16 .. start_val16+total_ids) */ -id16_map_init(osl_t *osh, uint16 total_ids, uint16 start_val16) -{ - uint16 idx, val16; - id16_map_t * id16_map; + if (id_ext) { + if (!DOT11_MNG_IE_ID_EXT_MATCH(elt, key)) + break; + } else if (elt->id != key) { + break; + } - ASSERT(total_ids > 0); + return (bcm_tlv_t *)(elt); /* a match */ + } while (0); - /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map - * with random values. - */ - ASSERT((start_val16 == ID16_UNDEFINED) || - (start_val16 + total_ids) < ID16_INVALID); + elt = (bcm_tlv_t*)((uint8*)elt + (len + TLV_HDR_LEN)); + totlen -= (len + TLV_HDR_LEN); + } - id16_map = (id16_map_t *) MALLOC(osh, ID16_MAP_SZ(total_ids)); - if (id16_map == NULL) { + return NULL; +} + +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag + * return NULL if not found or length field < min_varlen + */ +bcm_tlv_t * +bcm_parse_tlvs_min_bodylen(const void *buf, int buflen, uint key, int min_bodylen) +{ + bcm_tlv_t * ret; + ret = bcm_parse_tlvs(buf, buflen, key); + if (ret == NULL || ret->len < min_bodylen) { return NULL; } + return ret; +} - id16_map->total = total_ids; - id16_map->start = start_val16; - id16_map->failures = 0; - id16_map->dbg = NULL; +/* + * Traverse a string of 1-byte tag/1-byte length/variable-length value + * triples, returning a pointer to the substring whose first element + * matches tag. Stop parsing when we see an element whose ID is greater + * than the target key. + */ +const bcm_tlv_t * +bcm_parse_ordered_tlvs(const void *buf, int buflen, uint key) +{ + const bcm_tlv_t *elt; + int totlen; - /* - * Populate stack with 16bit id values, commencing with start_val16. - * if start_val16 is ID16_UNDEFINED, then do not populate the id16 map. - */ - id16_map->stack_idx = -1; + elt = (const bcm_tlv_t*)buf; + totlen = buflen; - if (id16_map->start != ID16_UNDEFINED) { - val16 = start_val16; + /* find tagged parameter */ + while (totlen >= TLV_HDR_LEN) { + uint id = elt->id; + int len = elt->len; - for (idx = 0; idx < total_ids; idx++, val16++) { - id16_map->stack_idx = idx; - id16_map->stack[id16_map->stack_idx] = val16; + /* Punt if we start seeing IDs > than target key */ + if (id > key) { + return (NULL); + } + + /* validate remaining totlen */ + if ((id == key) && (totlen >= (int)(len + TLV_HDR_LEN))) { + return (elt); } + + elt = (const bcm_tlv_t*)((const uint8*)elt + (len + TLV_HDR_LEN)); + totlen -= (len + TLV_HDR_LEN); } + return NULL; +} +#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - if (id16_map->start != ID16_UNDEFINED) { - id16_map->dbg = MALLOC(osh, ID16_MAP_DBG_SZ(total_ids)); +#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; - if (id16_map->dbg) { - id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + buf[0] = '\0'; - id16_map_dbg->total = total_ids; - for (idx = 0; idx < total_ids; idx++) { - id16_map_dbg->avail[idx] = TRUE; + 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; } } -#endif /* BCM_DBG && BCM_DBG_ID16 */ + return slen; +} - return (void *)id16_map; +int +bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) +{ + int i; + char* p = buf; + char hexstr[16]; + int slen = 0, nlen = 0; + uint32 bit; + const char* name; + + if (len < 2 || !buf) + return 0; + + buf[0] = '\0'; + + for (i = 0; flags != 0; i++) { + bit = bd[i].bit; + name = bd[i].name; + if (bit == 0 && flags != 0) { + /* print any unnamed bits */ + snprintf(hexstr, 16, "0x%X", flags); + name = hexstr; + flags = 0; /* exit loop */ + } else if ((flags & bit) == 0) + continue; + flags &= ~bit; + nlen = strlen(name); + slen += nlen; + /* count btwn flag space */ + if (flags != 0) + slen += 1; + /* need NULL char as well */ + if (len <= slen) + break; + /* copy NULL char but don't count it */ + strncpy(p, name, nlen + 1); + p += nlen; + /* copy btwn flag space and NULL char */ + if (flags != 0) + p += snprintf(p, 2, " "); + } + + /* indicate the str was too short */ + if (flags != 0) { + p += snprintf(p, 2, ">"); + } + + return (int)(p - buf); } -void * /* Destruct an id16 allocator instance */ -id16_map_fini(osl_t *osh, void * id16_map_hndl) +/* print out whcih bits in octet array 'addr' are set. bcm_bit_desc_t:bit is a bit offset. */ +int +bcm_format_octets(const bcm_bit_desc_t *bd, uint bdsz, + const uint8 *addr, uint size, char *buf, int len) { - uint16 total_ids; - id16_map_t * id16_map; + uint i; + char *p = buf; + int slen = 0, nlen = 0; + uint32 bit; + const char* name; + bool more = FALSE; - if (id16_map_hndl == NULL) - return NULL; + BCM_REFERENCE(size); - id16_map = (id16_map_t *)id16_map_hndl; + if (len < 2 || !buf) + return 0; - total_ids = id16_map->total; - ASSERT(total_ids > 0); + buf[0] = '\0'; -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - if (id16_map->dbg) { - MFREE(osh, id16_map->dbg, ID16_MAP_DBG_SZ(total_ids)); - id16_map->dbg = NULL; + for (i = 0; i < bdsz; i++) { + bit = bd[i].bit; + name = bd[i].name; + if (isset(addr, bit)) { + nlen = strlen(name); + slen += nlen; + /* need SPACE - for simplicity */ + slen += 1; + /* need NULL as well */ + if (len < slen + 1) { + more = TRUE; + break; + } + memcpy(p, name, nlen); + p += nlen; + p[0] = ' '; + p += 1; + p[0] = '\0'; + } } -#endif /* BCM_DBG && BCM_DBG_ID16 */ - id16_map->total = 0; - MFREE(osh, id16_map, ID16_MAP_SZ(total_ids)); + if (more) { + p[0] = '>'; + p += 1; + p[0] = '\0'; + } - return NULL; + return (int)(p - buf); } +#endif // endif -void -id16_map_clear(void * id16_map_hndl, uint16 total_ids, uint16 start_val16) +/* print bytes formatted as hex to a string. return the resulting string length */ +int +bcm_format_hex(char *str, const void *bytes, int len) { - uint16 idx, val16; - id16_map_t * id16_map; - - ASSERT(total_ids > 0); - /* A start_val16 of ID16_UNDEFINED, allows the caller to fill the id16 map - * with random values. - */ - ASSERT((start_val16 == ID16_UNDEFINED) || - (start_val16 + total_ids) < ID16_INVALID); + int i; + char *p = str; + const uint8 *src = (const uint8*)bytes; - id16_map = (id16_map_t *)id16_map_hndl; - if (id16_map == NULL) { - return; + for (i = 0; i < len; i++) { + p += snprintf(p, 3, "%02X", *src); + src++; } + return (int)(p - str); +} - id16_map->total = total_ids; - id16_map->start = start_val16; - id16_map->failures = 0; +/* pretty hex print a contiguous buffer */ +void +prhex(const char *msg, const uchar *buf, uint nbytes) +{ + char line[128], *p; + int len = sizeof(line); + int nchar; + uint i; - /* Populate stack with 16bit id values, commencing with start_val16 */ - id16_map->stack_idx = -1; + if (msg && (msg[0] != '\0')) + printf("%s:\n", msg); - if (id16_map->start != ID16_UNDEFINED) { - val16 = start_val16; + p = line; + for (i = 0; i < nbytes; i++) { + if (i % 16 == 0) { + nchar = snprintf(p, len, " %04x: ", i); /* line prefix */ + p += nchar; + len -= nchar; + } + if (len > 0) { + nchar = snprintf(p, len, "%02x ", buf[i]); + p += nchar; + len -= nchar; + } - for (idx = 0; idx < total_ids; idx++, val16++) { - id16_map->stack_idx = idx; - id16_map->stack[id16_map->stack_idx] = val16; + if (i % 16 == 15) { + printf("%s\n", line); /* flush line */ + p = line; + len = sizeof(line); } } -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - if (id16_map->start != ID16_UNDEFINED) { - if (id16_map->dbg) { - id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + /* flush last partial line */ + if (p != line) + printf("%s\n", line); +} - id16_map_dbg->total = total_ids; - for (idx = 0; idx < total_ids; idx++) { - id16_map_dbg->avail[idx] = TRUE; - } - } - } -#endif /* BCM_DBG && BCM_DBG_ID16 */ +static const char *crypto_algo_names[] = { + "NONE", + "WEP1", + "TKIP", + "WEP128", + "AES_CCM", + "AES_OCB_MSDU", + "AES_OCB_MPDU", +#ifdef BCMCCX + "CKIP", + "CKIP_MMH", + "WEP_MMH", + "NALG", +#else + "NALG", + "UNDEF", + "UNDEF", + "UNDEF", +#endif /* BCMCCX */ +#ifdef BCMWAPI_WAI + "WAPI", +#else + "UNDEF", +#endif // endif + "PMK", + "BIP", + "AES_GCM", + "AES_CCM256", + "AES_GCM256", + "BIP_CMAC256", + "BIP_GMAC", + "BIP_GMAC256", + "UNDEF" +}; + +const char * +bcm_crypto_algo_name(uint algo) +{ + return (algo < ARRAYSIZE(crypto_algo_names)) ? crypto_algo_names[algo] : "ERR"; } -uint16 BCMFASTPATH /* Allocate a unique 16bit id */ -id16_map_alloc(void * id16_map_hndl) +char * +bcm_chipname(uint chipid, char *buf, uint len) { - uint16 val16; - id16_map_t * id16_map; + const char *fmt; - ASSERT(id16_map_hndl != NULL); + fmt = ((chipid > 0xa000) || (chipid < 0x4000)) ? "%d" : "%x"; + snprintf(buf, len, fmt, chipid); + return buf; +} - id16_map = (id16_map_t *)id16_map_hndl; +/* Produce a human-readable string for boardrev */ +char * +bcm_brev_str(uint32 brev, char *buf) +{ + if (brev < 0x100) + snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); + else + snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); - ASSERT(id16_map->total > 0); + return (buf); +} - if (id16_map->stack_idx < 0) { - id16_map->failures++; - return ID16_INVALID; - } +#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ - val16 = id16_map->stack[id16_map->stack_idx]; - id16_map->stack_idx--; +/* dump large strings to console */ +void +printbig(char *buf) +{ + uint len, max_len; + char c; -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - ASSERT((id16_map->start == ID16_UNDEFINED) || - (val16 < (id16_map->start + id16_map->total))); + len = (uint)strlen(buf); - if (id16_map->dbg) { /* Validate val16 */ - id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + max_len = BUFSIZE_TODUMP_ATONCE; - ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == TRUE); - id16_map_dbg->avail[val16 - id16_map->start] = FALSE; - } -#endif /* BCM_DBG && BCM_DBG_ID16 */ + while (len > max_len) { + c = buf[max_len]; + buf[max_len] = '\0'; + printf("%s", buf); + buf[max_len] = c; - return val16; + buf += max_len; + len -= max_len; + } + /* print the remaining string */ + printf("%s\n", buf); + return; } - -void BCMFASTPATH /* Free a 16bit id value into the id16 allocator */ -id16_map_free(void * id16_map_hndl, uint16 val16) +/* routine to dump fields in a fileddesc structure */ +uint +bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, + char *buf, uint32 bufsize) { - id16_map_t * id16_map; + uint filled_len; + int len; + struct fielddesc *cur_ptr; - ASSERT(id16_map_hndl != NULL); + filled_len = 0; + cur_ptr = fielddesc_array; - id16_map = (id16_map_t *)id16_map_hndl; + while (bufsize > 1) { + if (cur_ptr->nameandfmt == NULL) + break; + len = snprintf(buf, bufsize, cur_ptr->nameandfmt, + read_rtn(arg0, arg1, cur_ptr->offset)); + /* check for snprintf overflow or error */ + if (len < 0 || (uint32)len >= bufsize) + len = bufsize - 1; + buf += len; + bufsize -= len; + filled_len += len; + cur_ptr++; + } + return filled_len; +} -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - ASSERT((id16_map->start == ID16_UNDEFINED) || - (val16 < (id16_map->start + id16_map->total))); +uint +bcm_mkiovar(const char *name, const char *data, uint datalen, char *buf, uint buflen) +{ + uint len; - if (id16_map->dbg) { /* Validate val16 */ - id16_map_dbg_t *id16_map_dbg = (id16_map_dbg_t *)id16_map->dbg; + len = (uint)strlen(name) + 1; - ASSERT(id16_map_dbg->avail[val16 - id16_map->start] == FALSE); - id16_map_dbg->avail[val16 - id16_map->start] = TRUE; - } -#endif /* BCM_DBG && BCM_DBG_ID16 */ + if ((len + datalen) > buflen) + return 0; - id16_map->stack_idx++; - id16_map->stack[id16_map->stack_idx] = val16; -} + strncpy(buf, name, buflen); -uint32 /* Returns number of failures to allocate an unique id16 */ -id16_map_failures(void * id16_map_hndl) -{ - ASSERT(id16_map_hndl != NULL); - return ((id16_map_t *)id16_map_hndl)->failures; + /* append data onto the end of the name string */ + if (data && datalen != 0) { + memcpy(&buf[len], data, datalen); + len += datalen; + } + + return len; } -bool -id16_map_audit(void * id16_map_hndl) -{ - int idx; - int insane = 0; - id16_map_t * id16_map; +/* Quarter dBm units to mW + * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 + * Table is offset so the last entry is largest mW value that fits in + * a uint16. + */ - ASSERT(id16_map_hndl != NULL); +#define QDBM_OFFSET 153 /* Offset for first entry */ +#define QDBM_TABLE_LEN 40 /* Table size */ - id16_map = (id16_map_t *)id16_map_hndl; +/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. + * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 + */ +#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ - ASSERT(id16_map->stack_idx >= -1); - ASSERT(id16_map->stack_idx < (int)id16_map->total); +/* Largest mW value that will round down to the last table entry, + * QDBM_OFFSET + QDBM_TABLE_LEN-1. + * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. + */ +#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ - if (id16_map->start == ID16_UNDEFINED) - goto done; +static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { +/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ +/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, +/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, +/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, +/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, +/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 +}; - for (idx = 0; idx <= id16_map->stack_idx; idx++) { - ASSERT(id16_map->stack[idx] >= id16_map->start); - ASSERT(id16_map->stack[idx] < (id16_map->start + id16_map->total)); +uint16 +bcm_qdbm_to_mw(uint8 qdbm) +{ + uint factor = 1; + int idx = qdbm - QDBM_OFFSET; -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - if (id16_map->dbg) { - uint16 val16 = id16_map->stack[idx]; - if (((id16_map_dbg_t *)(id16_map->dbg))->avail[val16] != TRUE) { - insane |= 1; - ID16_MAP_MSG(("id16_map<%p>: stack_idx %u invalid val16 %u\n", - id16_map_hndl, idx, val16)); - } - } -#endif /* BCM_DBG && BCM_DBG_ID16 */ + if (idx >= QDBM_TABLE_LEN) { + /* clamp to max uint16 mW value */ + return 0xFFFF; } -#if defined(BCM_DBG) && defined(BCM_DBG_ID16) - if (id16_map->dbg) { - uint16 avail = 0; /* Audit available ids counts */ - for (idx = 0; idx < id16_map_dbg->total; idx++) { - if (((id16_map_dbg_t *)(id16_map->dbg))->avail[idx16] == TRUE) - avail++; - } - if (avail && (avail != (id16_map->stack_idx + 1))) { - insane |= 1; - ID16_MAP_MSG(("id16_map<%p>: avail %u stack_idx %u\n", - id16_map_hndl, avail, id16_map->stack_idx)); - } + /* scale the qdBm index up to the range of the table 0-40 + * where an offset of 40 qdBm equals a factor of 10 mW. + */ + while (idx < 0) { + idx += 40; + factor *= 10; } -#endif /* BCM_DBG && BCM_DBG_ID16 */ -done: - /* invoke any other system audits */ - return (!!insane); + /* return the mW value scaled down to the correct factor of 10, + * adding in factor/2 to get proper rounding. + */ + return ((nqdBm_to_mW_map[idx] + factor/2) / factor); } -/* END: Simple id16 allocator */ +uint8 +bcm_mw_to_qdbm(uint16 mw) +{ + uint8 qdbm; + int offset; + uint mw_uint = mw; + uint boundary; -#endif + /* handle boundary case */ + if (mw_uint <= 1) + return 0; -/* calculate a >> b; and returns only lower 32 bits */ -void -bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b) -{ - uint32 a1 = a_high, a0 = a_low, r0 = 0; + offset = QDBM_OFFSET; - if (b == 0) { - r0 = a_low; - *r = r0; - return; + /* move mw into the range of the table */ + while (mw_uint < QDBM_TABLE_LOW_BOUND) { + mw_uint *= 10; + offset -= 40; } - if (b < 32) { - a0 = a0 >> b; - a1 = a1 & ((1 << b) - 1); - a1 = a1 << (32 - b); - r0 = a0 | a1; - *r = r0; - return; - } else { - r0 = a1 >> (b - 32); - *r = r0; - return; + for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { + boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - + nqdBm_to_mW_map[qdbm])/2; + if (mw_uint < boundary) break; } -} - -/* calculate a + b where a is a 64 bit number and b is a 32 bit number */ -void -bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset) -{ - uint32 r1_lo = *r_lo; - (*r_lo) += offset; - if (*r_lo < r1_lo) - (*r_hi) ++; -} + qdbm += (uint8)offset; -/* calculate a - b where a is a 64 bit number and b is a 32 bit number */ -void -bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset) -{ - uint32 r1_lo = *r_lo; - (*r_lo) -= offset; - if (*r_lo > r1_lo) - (*r_hi) --; + return (qdbm); } -/* Does unsigned 64 bit fixed point multiplication */ -uint64 -fp_mult_64(uint64 val1, uint64 val2, uint8 nf1, uint8 nf2, uint8 nf_res) +uint +bcm_bitcount(uint8 *bitmap, uint length) { - uint64 mult_out_tmp, mult_out, rnd_val; - uint8 shift_amt; - - shift_amt = nf1 + nf2 - nf_res; - /* 0.5 in 1.0.shift_amt */ - rnd_val = bcm_shl_64(1, (shift_amt - 1)); - rnd_val = (shift_amt == 0) ? 0 : rnd_val; - mult_out_tmp = (uint64)((uint64)val1 * (uint64)val2) + (uint64)rnd_val; - mult_out = bcm_shr_64(mult_out_tmp, shift_amt); - - return mult_out; + uint bitcount = 0, i; + uint8 tmp; + for (i = 0; i < length; i++) { + tmp = bitmap[i]; + while (tmp) { + bitcount++; + tmp &= (tmp - 1); + } + } + return bitcount; } +/* + * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. + * also accepts nvram files which are already in the format of =\0\=\0 + * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. + * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. +*/ -/* Does unsigned 64 bit by 32 bit fixed point division */ -uint8 -fp_div_64(uint64 num, uint32 den, uint8 nf_num, uint8 nf_den, uint32 *div_out) +unsigned int +process_nvram_vars(char *varbuf, unsigned int len) { - uint8 shift_amt1, shift_amt2, shift_amt, nf_res, hd_rm_nr, hd_rm_dr; - uint32 num_hi, num_lo; - uint64 num_scale; - - /* Worst case shift possible */ - hd_rm_nr = fp_calc_head_room_64(num); - hd_rm_dr = fp_calc_head_room_32(den); - - /* (Nr / Dr) <= 2^32 */ - shift_amt1 = hd_rm_nr - hd_rm_dr - 1; - /* Shift <= 32 + N2 - N1 */ - shift_amt2 = 31 + nf_den - nf_num; - shift_amt = MINIMUM(shift_amt1, shift_amt2); - - /* Scale numerator */ - num_scale = bcm_shl_64(num, shift_amt); - - /* Do division */ - num_hi = (uint32)((uint64)num_scale >> 32) & MASK_32_BITS; - num_lo = (uint32)(num_scale & MASK_32_BITS); - bcm_uint64_divide(div_out, num_hi, num_lo, den); - - /* Result format */ - nf_res = nf_num - nf_den + shift_amt; - return nf_res; -} + char *dp; + bool findNewline; + int column; + unsigned int buf_len, n; + unsigned int pad = 0; -/* Finds the number of bits available for shifting in unsigned 64 bit number */ -uint8 -fp_calc_head_room_64(uint64 num) -{ - uint8 n_room_bits = 0, msb_pos; - uint32 num_hi, num_lo, x; + dp = varbuf; - num_hi = (uint32)((uint64)num >> 32) & MASK_32_BITS; - num_lo = (uint32)(num & MASK_32_BITS); + findNewline = FALSE; + column = 0; - if (num_hi > 0) { - x = num_hi; - n_room_bits = 0; - } else { - x = num_lo; - n_room_bits = 32; + for (n = 0; n < len; n++) { + if (varbuf[n] == '\r') + continue; + if (findNewline && varbuf[n] != '\n') + continue; + findNewline = FALSE; + if (varbuf[n] == '#') { + findNewline = TRUE; + continue; + } + if (varbuf[n] == '\n') { + if (column == 0) + continue; + *dp++ = 0; + column = 0; + continue; + } + *dp++ = varbuf[n]; + column++; + } + buf_len = (unsigned int)(dp - varbuf); + if (buf_len % 4) { + pad = 4 - buf_len % 4; + if (pad && (buf_len + pad <= len)) { + buf_len += pad; + } } - msb_pos = (x >> 16) ? ((x >> 24) ? (24 + msb_table[(x >> 24) & MASK_8_BITS]) - : (16 + msb_table[(x >> 16) & MASK_8_BITS])) - : ((x >> 8) ? (8 + msb_table[(x >> 8) & MASK_8_BITS]) - : msb_table[x & MASK_8_BITS]); + while (dp < varbuf + n) + *dp++ = 0; - return (n_room_bits + 32 - msb_pos); + return buf_len; } -/* Finds the number of bits available for shifting in unsigned 32 bit number */ -uint8 -fp_calc_head_room_32(uint32 x) +#ifndef setbit /* As in the header file */ +#ifdef BCMUTILS_BIT_MACROS_USE_FUNCS +/* Set bit in byte array. */ +void +setbit(void *array, uint bit) { - uint8 msb_pos; - - msb_pos = (x >> 16) ? ((x >> 24) ? (24 + msb_table[(x >> 24) & MASK_8_BITS]) - : (16 + msb_table[(x >> 16) & MASK_8_BITS])) - : ((x >> 8) ? (8 + msb_table[(x >> 8) & MASK_8_BITS]) - : msb_table[x & MASK_8_BITS]); - - return (32 - msb_pos); + ((uint8 *)array)[bit / NBBY] |= 1 << (bit % NBBY); } -/* Does unsigned 64 bit fixed point floor */ -uint32 -fp_floor_64(uint64 num, uint8 floor_pos) +/* Clear bit in byte array. */ +void +clrbit(void *array, uint bit) { - uint32 floor_out; - - floor_out = (uint32)bcm_shr_64(num, floor_pos); - - return floor_out; + ((uint8 *)array)[bit / NBBY] &= ~(1 << (bit % NBBY)); } -/* Does unsigned 32 bit fixed point floor */ -uint32 -fp_floor_32(uint32 num, uint8 floor_pos) +/* Test if bit is set in byte array. */ +bool +isset(const void *array, uint bit) { - return num >> floor_pos; + return (((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))); } -/* Does unsigned 64 bit fixed point rounding */ -uint32 -fp_round_64(uint64 num, uint8 rnd_pos) +/* Test if bit is clear in byte array. */ +bool +isclr(const void *array, uint bit) { - uint64 rnd_val, rnd_out_tmp; - uint32 rnd_out; - - /* 0.5 in 1.0.rnd_pos */ - rnd_val = bcm_shl_64(1, (rnd_pos - 1)); - rnd_val = (rnd_pos == 0) ? 0 : rnd_val; - rnd_out_tmp = num + rnd_val; - rnd_out = (uint32)bcm_shr_64(rnd_out_tmp, rnd_pos); - - return rnd_out; + return ((((const uint8 *)array)[bit / NBBY] & (1 << (bit % NBBY))) == 0); } +#endif /* BCMUTILS_BIT_MACROS_USE_FUNCS */ +#endif /* setbit */ -/* Does unsigned 32 bit fixed point rounding */ -uint32 -fp_round_32(uint32 num, uint8 rnd_pos) +void +set_bitrange(void *array, uint start, uint end, uint maxbit) { - uint32 rnd_val, rnd_out_tmp; + uint startbyte = start/NBBY; + uint endbyte = end/NBBY; + uint i, startbytelastbit, endbytestartbit; - /* 0.5 in 1.0.rnd_pos */ - rnd_val = 1 << (rnd_pos - 1); - rnd_val = (rnd_pos == 0) ? 0 : rnd_val; - rnd_out_tmp = num + rnd_val; - return (rnd_out_tmp >> rnd_pos); + if (end >= start) { + if (endbyte - startbyte > 1) + { + startbytelastbit = (startbyte+1)*NBBY - 1; + endbytestartbit = endbyte*NBBY; + for (i = startbyte+1; i < endbyte; i++) + ((uint8 *)array)[i] = 0xFF; + for (i = start; i <= startbytelastbit; i++) + setbit(array, i); + for (i = endbytestartbit; i <= end; i++) + setbit(array, i); + } else { + for (i = start; i <= end; i++) + setbit(array, i); + } + } + else { + set_bitrange(array, start, maxbit, maxbit); + set_bitrange(array, 0, end, maxbit); + } } -/* Does unsigned fixed point ceiling */ -uint32 -fp_ceil_64(uint64 num, uint8 ceil_pos) +void +bcm_bitprint32(const uint32 u32arg) { - uint64 ceil_val, ceil_out_tmp; - uint32 ceil_out; - - /* 0.999 in 1.0.rnd_pos */ - ceil_val = bcm_shl_64(1, ceil_pos) - 1; - ceil_out_tmp = num + ceil_val; - ceil_out = (uint32)bcm_shr_64(ceil_out_tmp, ceil_pos); + int i; + for (i = NBITS(uint32) - 1; i >= 0; i--) { + if (isbitset(u32arg, i)) { + printf("1"); + } else { + printf("0"); + } - return ceil_out; + if ((i % NBBY) == 0) printf(" "); + } + printf("\n"); } -/* Does left shift of unsigned 64 bit number */ -uint64 -bcm_shl_64(uint64 input, uint8 shift_amt) +/* calculate checksum for ip header, tcp / udp header / data */ +uint16 +bcm_ip_cksum(uint8 *buf, uint32 len, uint32 sum) { - uint32 in_hi, in_lo; - uint32 masked_lo = 0; - uint32 mask; - uint64 shl_out; - - if (shift_amt == 0) { - return input; + while (len > 1) { + sum += (buf[0] << 8) | buf[1]; + buf += 2; + len -= 2; } - /* Get hi and lo part */ - in_hi = (uint32)((uint64)input >> 32) & MASK_32_BITS; - in_lo = (uint32)(input & MASK_32_BITS); - - if (shift_amt < 32) { - /* Extract bit which belongs to hi part after shifting */ - mask = ((uint32)~0) << (32 - shift_amt); - masked_lo = (in_lo & mask) >> (32 - shift_amt); - - /* Shift hi and lo and prepare output */ - in_hi = (in_hi << shift_amt) | masked_lo; - in_lo = in_lo << shift_amt; - } else { - /* Extract bit which belongs to hi part after shifting */ - shift_amt = shift_amt - 32; + if (len > 0) { + sum += (*buf) << 8; + } - /* Shift hi and lo and prepare output */ - in_hi = in_lo << shift_amt; - in_lo = 0; + while (sum >> 16) { + sum = (sum & 0xffff) + (sum >> 16); } - shl_out = (((uint64)in_hi << 32) | in_lo); - return shl_out; + return ((uint16)~sum); } -/* Does right shift of unsigned 64 bit number */ -uint64 -bcm_shr_64(uint64 input, uint8 shift_amt) +int +BCMRAMFN(valid_bcmerror)(int e) { - uint32 in_hi, in_lo; - uint32 masked_hi = 0; - uint32 mask; - uint64 shr_out; - - if (shift_amt == 0) { - return input; - } - - /* Get hi and lo part */ - in_hi = (uint32)((uint64)input >> 32) & MASK_32_BITS; - in_lo = (uint32)(input & MASK_32_BITS); - - if (shift_amt < 32) { - /* Extract bit which belongs to lo part after shifting */ - mask = (1 << shift_amt) - 1; - masked_hi = in_hi & mask; - - /* Shift hi and lo and prepare output */ - in_hi = (uint32)in_hi >> shift_amt; - in_lo = ((uint32)in_lo >> shift_amt) | (masked_hi << (32 - shift_amt)); - } else { - shift_amt = shift_amt - 32; - in_lo = in_hi >> shift_amt; - in_hi = 0; - } - - shr_out = (((uint64)in_hi << 32) | in_lo); - return shr_out; + return ((e <= 0) && (e >= BCME_LAST)); } #ifdef DEBUG_COUNTER @@ -3855,85 +3650,6 @@ void counter_printlog(counter_tbl_t *ctr_tbl) #endif /* OSL_SYSUPTIME_SUPPORT == TRUE */ #endif /* DEBUG_COUNTER */ -#if defined(BCMDRIVER) && !defined(_CFEZ_) -void -dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size) -{ - uint32 mem_size; - mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); - if (pool) - MFREE(osh, pool, mem_size); -} -dll_pool_t * -dll_pool_init(void * osh, uint16 elems_max, uint16 elem_size) -{ - uint32 mem_size, i; - dll_pool_t * dll_pool_p; - dll_t * elem_p; - - ASSERT(elem_size > sizeof(dll_t)); - - mem_size = sizeof(dll_pool_t) + (elems_max * elem_size); - - if ((dll_pool_p = (dll_pool_t *)MALLOCZ(osh, mem_size)) == NULL) { - printf("dll_pool_init: elems_max<%u> elem_size<%u> malloc failure\n", - elems_max, elem_size); - ASSERT(0); - return dll_pool_p; - } - - dll_init(&dll_pool_p->free_list); - dll_pool_p->elems_max = elems_max; - dll_pool_p->elem_size = elem_size; - - elem_p = dll_pool_p->elements; - for (i = 0; i < elems_max; i++) { - dll_append(&dll_pool_p->free_list, elem_p); - elem_p = (dll_t *)((uintptr)elem_p + elem_size); - } - - dll_pool_p->free_count = elems_max; - - return dll_pool_p; -} - - -void * -dll_pool_alloc(dll_pool_t * dll_pool_p) -{ - dll_t * elem_p; - - if (dll_pool_p->free_count == 0) { - ASSERT(dll_empty(&dll_pool_p->free_list)); - return NULL; - } - - elem_p = dll_head_p(&dll_pool_p->free_list); - dll_delete(elem_p); - dll_pool_p->free_count -= 1; - - return (void *)elem_p; -} - -void -dll_pool_free(dll_pool_t * dll_pool_p, void * elem_p) -{ - dll_t * node_p = (dll_t *)elem_p; - dll_prepend(&dll_pool_p->free_list, node_p); - dll_pool_p->free_count += 1; -} - - -void -dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p) -{ - dll_t * node_p = (dll_t *)elem_p; - dll_append(&dll_pool_p->free_list, node_p); - dll_pool_p->free_count += 1; -} - -#endif - /* calculate partial checksum */ static uint32 ip_cksum_partial(uint32 sum, uint8 *val8, uint32 count) @@ -4086,3 +3802,357 @@ ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len) /* return calculated TCP header chksum */ return tcp_hdr_chksum(sum, tcp, tcp_len); } + +void *_bcmutils_dummy_fn = NULL; + +/* GROUP 1 --- start + * These function under GROUP 1 are general purpose functions to do complex number + * calculations and square root calculation. + */ + +uint32 sqrt_int(uint32 value) +{ + uint32 root = 0, shift = 0; + + /* Compute integer nearest to square root of input integer value */ + for (shift = 0; shift < 32; shift += 2) { + if (((0x40000000 >> shift) + root) <= value) { + value -= ((0x40000000 >> shift) + root); + root = (root >> 1) | (0x40000000 >> shift); + } + else { + root = root >> 1; + } + } + + /* round to the nearest integer */ + if (root < value) ++root; + + return root; +} +/* GROUP 1 --- end */ + +/* read/write field in a consecutive bits in an octet array. + * 'addr' is the octet array's start byte address + * 'size' is the octet array's byte size + * 'stbit' is the value's start bit offset + * 'nbits' is the value's bit size + * This set of utilities are for convenience. Don't use them + * in time critical/data path as there's a great overhead in them. + */ +void +setbits(uint8 *addr, uint size, uint stbit, uint nbits, uint32 val) +{ + uint fbyte = stbit >> 3; /* first byte */ + uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */ + uint fbit = stbit & 7; /* first bit in the first byte */ + uint rbits = (nbits > 8 - fbit ? + nbits - (8 - fbit) : + 0) & 7; /* remaining bits of the last byte when not 0 */ + uint8 mask; + uint byte; + + BCM_REFERENCE(size); + + ASSERT(fbyte < size); + ASSERT(lbyte < size); + ASSERT(nbits <= (sizeof(val) << 3)); + + /* all bits are in the same byte */ + if (fbyte == lbyte) { + mask = ((1 << nbits) - 1) << fbit; + addr[fbyte] &= ~mask; + addr[fbyte] |= (uint8)(val << fbit); + return; + } + + /* first partial byte */ + if (fbit > 0) { + mask = (0xff << fbit); + addr[fbyte] &= ~mask; + addr[fbyte] |= (uint8)(val << fbit); + val >>= (8 - fbit); + nbits -= (8 - fbit); + fbyte ++; /* first full byte */ + } + + /* last partial byte */ + if (rbits > 0) { + mask = (1 << rbits) - 1; + addr[lbyte] &= ~mask; + addr[lbyte] |= (uint8)(val >> (nbits - rbits)); + lbyte --; /* last full byte */ + } + + /* remaining full byte(s) */ + for (byte = fbyte; byte <= lbyte; byte ++) { + addr[byte] = (uint8)val; + val >>= 8; + } +} + +uint32 +getbits(const uint8 *addr, uint size, uint stbit, uint nbits) +{ + uint fbyte = stbit >> 3; /* first byte */ + uint lbyte = (stbit + nbits - 1) >> 3; /* last byte */ + uint fbit = stbit & 7; /* first bit in the first byte */ + uint rbits = (nbits > 8 - fbit ? + nbits - (8 - fbit) : + 0) & 7; /* remaining bits of the last byte when not 0 */ + uint32 val = 0; + uint bits = 0; /* bits in first partial byte */ + uint8 mask; + uint byte; + + BCM_REFERENCE(size); + + ASSERT(fbyte < size); + ASSERT(lbyte < size); + ASSERT(nbits <= (sizeof(val) << 3)); + + /* all bits are in the same byte */ + if (fbyte == lbyte) { + mask = ((1 << nbits) - 1) << fbit; + val = (addr[fbyte] & mask) >> fbit; + return val; + } + + /* first partial byte */ + if (fbit > 0) { + bits = 8 - fbit; + mask = (0xff << fbit); + val |= (addr[fbyte] & mask) >> fbit; + fbyte ++; /* first full byte */ + } + + /* last partial byte */ + if (rbits > 0) { + mask = (1 << rbits) - 1; + val |= (addr[lbyte] & mask) << (nbits - rbits); + lbyte --; /* last full byte */ + } + + /* remaining full byte(s) */ + for (byte = fbyte; byte <= lbyte; byte ++) { + val |= (addr[byte] << (((byte - fbyte) << 3) + bits)); + } + + return val; +} + +#ifdef BCMDRIVER + +/** allocate variable sized data with 'size' bytes. note: vld should NOT be null. + */ +int +bcm_vdata_alloc(osl_t *osh, var_len_data_t *vld, uint32 size) +{ + int ret = BCME_ERROR; + uint8 *dat = NULL; + + if (vld == NULL) { + ASSERT(0); + goto done; + } + + /* trying to allocate twice? */ + if (vld->vdata != NULL) { + ASSERT(0); + goto done; + } + + /* trying to allocate 0 size? */ + if (size == 0) { + ASSERT(0); + ret = BCME_BADARG; + goto done; + } + + dat = MALLOCZ(osh, size); + if (dat == NULL) { + ret = BCME_NOMEM; + goto done; + } + vld->vlen = size; + vld->vdata = dat; + ret = BCME_OK; +done: + return ret; +} + +/** free memory associated with variable sized data. note: vld should NOT be null. + */ +int +bcm_vdata_free(osl_t *osh, var_len_data_t *vld) +{ + int ret = BCME_ERROR; + + if (vld == NULL) { + ASSERT(0); + goto done; + } + + if (vld->vdata) { + MFREE(osh, vld->vdata, vld->vlen); + vld->vdata = NULL; + vld->vlen = 0; + ret = BCME_OK; + } +done: + return ret; +} + +#endif /* BCMDRIVER */ + +/* Count the number of elements not matching a given value in a null terminated array */ +int +array_value_mismatch_count(uint8 value, uint8 *array, int array_size) +{ + int i; + int count = 0; + + for (i = 0; i < array_size; i++) { + /* exit if a null terminator is found */ + if (array[i] == 0) { + break; + } + if (array[i] != value) { + count++; + } + } + return count; +} + +/* Count the number of non-zero elements in an uint8 array */ +int +array_nonzero_count(uint8 *array, int array_size) +{ + return array_value_mismatch_count(0, array, array_size); +} + +/* Count the number of non-zero elements in an int16 array */ +int +array_nonzero_count_int16(int16 *array, int array_size) +{ + int i; + int count = 0; + + for (i = 0; i < array_size; i++) { + if (array[i] != 0) { + count++; + } + } + return count; +} + +/* Count the number of zero elements in an uint8 array */ +int +array_zero_count(uint8 *array, int array_size) +{ + int i; + int count = 0; + + for (i = 0; i < array_size; i++) { + if (array[i] == 0) { + count++; + } + } + return count; +} + +/* Validate an array that can be 1 of 2 data types. + * One of array1 or array2 should be non-NULL. The other should be NULL. + */ +static int +verify_ordered_array(uint8 *array1, int16 *array2, int array_size, + int range_lo, int range_hi, bool err_if_no_zero_term, bool is_ordered) +{ + int ret; + int i; + int val = 0; + int prev_val = 0; + + ret = err_if_no_zero_term ? BCME_NOTFOUND : BCME_OK; + + /* Check that: + * - values are in strict descending order. + * - values are within the valid range. + */ + for (i = 0; i < array_size; i++) { + if (array1) { + val = (int)array1[i]; + } else if (array2) { + val = (int)array2[i]; + } else { + /* both array parameters are NULL */ + return BCME_NOTFOUND; + } + if (val == 0) { + /* array is zero-terminated */ + ret = BCME_OK; + break; + } + + if (is_ordered && i > 0 && val >= prev_val) { + /* array is not in descending order */ + ret = BCME_BADOPTION; + break; + } + prev_val = val; + + if (val < range_lo || val > range_hi) { + /* array value out of range */ + ret = BCME_RANGE; + break; + } + } + + return ret; +} + +/* Validate an ordered uint8 configuration array */ +int +verify_ordered_array_uint8(uint8 *array, int array_size, + uint8 range_lo, uint8 range_hi) +{ + return verify_ordered_array(array, NULL, array_size, (int)range_lo, (int)range_hi, + TRUE, TRUE); +} + +/* Validate an ordered int16 non-zero-terminated configuration array */ +int +verify_ordered_array_int16(int16 *array, int array_size, + int16 range_lo, int16 range_hi) +{ + return verify_ordered_array(NULL, array, array_size, (int)range_lo, (int)range_hi, + FALSE, TRUE); +} + +/* Validate all values in an array are in range */ +int +verify_array_values(uint8 *array, int array_size, + int range_lo, int range_hi, bool zero_terminated) +{ + int ret = BCME_OK; + int i; + int val = 0; + + /* Check that: + * - values are in strict descending order. + * - values are within the valid range. + */ + for (i = 0; i < array_size; i++) { + val = (int)array[i]; + if (val == 0 && zero_terminated) { + ret = BCME_OK; + break; + } + if (val < range_lo || val > range_hi) { + /* array value out of range */ + ret = BCME_RANGE; + break; + } + } + return ret; +} diff --git a/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.c b/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.c index 40fc3f7578fb4a7ce967620d3ba93208f8cb7e24..531246e9a8270a87c19760bde67bbf4bd98d238e 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.c @@ -3,14 +3,14 @@ * Contents are wifi-specific, used by any kernel or app-level * software that might want wifi things as it grows. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,7 +26,7 @@ * * <> * - * $Id: bcmwifi_channels.c 612483 2016-01-14 03:44:27Z $ + * $Id: bcmwifi_channels.c 695288 2017-04-19 17:20:39Z $ */ #include @@ -43,19 +43,21 @@ #include #ifndef ASSERT #define ASSERT(exp) -#endif +#endif // endif #endif /* BCMDRIVER */ #include #if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) #include /* For wl/exe/GNUmakefile.brcm_wlu and GNUmakefile.wlm_dll */ -#endif +#endif // endif + +#include <802.11.h> -/* Definitions for D11AC capable Chanspec type */ +/* Definitions for D11AC capable (80MHz+) Chanspec type */ -/* Chanspec ASCII representation with 802.11ac capability: - * [ 'g'] ['/' []['/'<1st80channel>'-'<2nd80channel>]] +/* Chanspec ASCII representation: + * [ 'g'] ['/' []['/'<1st80channel>'-'<2nd80channel>]] * * : * (optional) 2, 3, 4, 5 for 2.4GHz, 3GHz, 4GHz, and 5GHz respectively. @@ -81,18 +83,18 @@ * <1st80Channel>: * <2nd80Channel>: * Required for 80+80, otherwise not allowed. - * Specifies the center channel of the first and second 80MHz band. + * Specifies the center channel of the primary and secondary 80MHz band. * * In its simplest form, it is a 20MHz channel number, with the implied band * of 2.4GHz if channel number <= 14, and 5GHz otherwise. * * To allow for backward compatibility with scripts, the old form for - * 40MHz channels is also allowed: + * 40MHz channels is also allowed: * * : * primary channel of 40MHz, channel <= 14 is 2GHz, otherwise 5GHz - * : - * "U" for upper, "L" for lower (or lower case "u" "l") + * : + * "U" for upper, "L" for lower (or lower case "u" "l") * * 5 GHz Examples: * Chanspec BW Center Ch Channel Range Primary Ch @@ -129,11 +131,7 @@ static const char *wf_chspec_bw_str[] = "80", "160", "80+80", -#ifdef WL11ULB - "2.5" -#else /* WL11ULB */ "na" -#endif /* WL11ULB */ }; static const uint8 wf_chspec_bw_mhz[] = @@ -144,13 +142,13 @@ static const uint8 wf_chspec_bw_mhz[] = /* 40MHz channels in 5GHz band */ static const uint8 wf_5g_40m_chans[] = -{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159}; +{38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159, 167, 175}; #define WF_NUM_5G_40M_CHANS \ (sizeof(wf_5g_40m_chans)/sizeof(uint8)) /* 80MHz channels in 5GHz band */ static const uint8 wf_5g_80m_chans[] = -{42, 58, 106, 122, 138, 155}; +{42, 58, 106, 122, 138, 155, 171}; #define WF_NUM_5G_80M_CHANS \ (sizeof(wf_5g_80m_chans)/sizeof(uint8)) @@ -197,9 +195,16 @@ static const uint16 opclass_data[] = { (WL_CHANSPEC_BAND_2G |((WL_CHANSPEC_BW_40)&WL_CHANSPEC_BW_MASK)|WL_CHANSPEC_CTL_SB_UPPER), }; -/* convert bandwidth from chanspec to MHz */ -static uint -bw_chspec_to_mhz(chanspec_t chspec) +/** + * Return the chanspec bandwidth in MHz + * Bandwidth of 160 MHz will be returned for 80+80MHz chanspecs. + * + * @param chspec chanspec_t + * + * @return bandwidth of chspec in MHz units + */ +uint +wf_bw_chspec_to_mhz(chanspec_t chspec) { uint bw; @@ -229,34 +234,34 @@ channel_low_edge(uint center_ch, uint bw) return (uint8)(center_ch - center_chan_to_edge(bw)); } -/* return side band number given center channel and control channel +/* return side band number given center channel and primary20 channel * return -1 on error */ static int -channel_to_sb(uint center_ch, uint ctl_ch, uint bw) +channel_to_sb(uint center_ch, uint primary_ch, uint bw) { uint lowest = channel_low_edge(center_ch, bw); uint sb; - if ((ctl_ch - lowest) % 4) { - /* bad ctl channel, not mult 4 */ + if ((primary_ch - lowest) % 4) { + /* bad primary channel, not mult 4 */ return -1; } - sb = ((ctl_ch - lowest) / 4); + sb = ((primary_ch - lowest) / 4); /* sb must be a index to a 20MHz channel in range */ if (sb >= (bw / 20)) { - /* ctl_ch must have been too high for the center_ch */ + /* primary_ch must have been too high for the center_ch */ return -1; } return sb; } -/* return control channel given center channel and side band */ +/* return primary20 channel given center channel and side band */ static uint8 -channel_to_ctl_chan(uint center_ch, uint bw, uint sb) +channel_to_primary20_chan(uint center_ch, uint bw, uint sb) { return (uint8)(channel_low_edge(center_ch, bw) + sb * 4); } @@ -297,7 +302,7 @@ char * wf_chspec_ntoa(chanspec_t chspec, char *buf) { const char *band; - uint ctl_chan; + uint pri_chan; if (wf_chspec_malformed(chspec)) return NULL; @@ -309,32 +314,32 @@ wf_chspec_ntoa(chanspec_t chspec, char *buf) (CHSPEC_IS5G(chspec) && CHSPEC_CHANNEL(chspec) <= CH_MAX_2G_CHANNEL)) band = (CHSPEC_IS2G(chspec)) ? "2g" : "5g"; - /* ctl channel */ - ctl_chan = wf_chspec_ctlchan(chspec); + /* primary20 channel */ + pri_chan = wf_chspec_primary20_chan(chspec); - /* bandwidth and ctl sideband */ + /* bandwidth and primary20 sideband */ if (CHSPEC_IS20(chspec)) { - snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, ctl_chan); + snprintf(buf, CHANSPEC_STR_LEN, "%s%d", band, pri_chan); } else if (!CHSPEC_IS8080(chspec)) { const char *bw; const char *sb = ""; - bw = wf_chspec_bw_str[(chspec & WL_CHANSPEC_BW_MASK) >> WL_CHANSPEC_BW_SHIFT]; + bw = wf_chspec_to_bw_str(chspec); #ifdef CHANSPEC_NEW_40MHZ_FORMAT - /* ctl sideband string if needed for 2g 40MHz */ + /* primary20 sideband string if needed for 2g 40MHz */ if (CHSPEC_IS40(chspec) && CHSPEC_IS2G(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; } - snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, ctl_chan, bw, sb); + snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s%s", band, pri_chan, bw, sb); #else - /* ctl sideband string instead of BW for 40MHz */ + /* primary20 sideband string instead of BW for 40MHz */ if (CHSPEC_IS40(chspec)) { sb = CHSPEC_SB_UPPER(chspec) ? "u" : "l"; - snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, ctl_chan, sb); + snprintf(buf, CHANSPEC_STR_LEN, "%s%d%s", band, pri_chan, sb); } else { - snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, ctl_chan, bw); + snprintf(buf, CHANSPEC_STR_LEN, "%s%d/%s", band, pri_chan, bw); } #endif /* CHANSPEC_NEW_40MHZ_FORMAT */ @@ -348,7 +353,7 @@ wf_chspec_ntoa(chanspec_t chspec, char *buf) chan2 = (chan2 < WF_NUM_5G_80M_CHANS) ? wf_5g_80m_chans[chan2] : 0; /* Outputs a max of CHANSPEC_STR_LEN chars including '\0' */ - snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", ctl_chan, chan1, chan2); + snprintf(buf, CHANSPEC_STR_LEN, "%d/80+80/%d-%d", pri_chan, chan1, chan2); } return (buf); @@ -381,7 +386,7 @@ wf_chspec_aton(const char *a) { chanspec_t chspec; uint chspec_ch, chspec_band, bw, chspec_bw, chspec_sb; - uint num, ctl_ch; + uint num, pri_ch; uint ch1, ch2; char c, sb_ul = '\0'; int i; @@ -407,15 +412,15 @@ wf_chspec_aton(const char *a) return 0; /* read the channel number */ - if (!read_uint(&a, &ctl_ch)) + if (!read_uint(&a, &pri_ch)) return 0; c = tolower((int)a[0]); } else { /* first number is channel, use default for band */ - ctl_ch = num; - chspec_band = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? + pri_ch = num; + chspec_band = ((pri_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); } @@ -443,9 +448,7 @@ wf_chspec_aton(const char *a) return 0; /* convert to chspec value */ - if (bw == 2) { - chspec_bw = WL_CHANSPEC_BW_2P5; - } else if (bw == 5) { + if (bw == 5) { chspec_bw = WL_CHANSPEC_BW_5; } else if (bw == 10) { chspec_bw = WL_CHANSPEC_BW_10; @@ -463,8 +466,7 @@ wf_chspec_aton(const char *a) /* So far we have g/ * Can now be followed by u/l if bw = 40, - * or '+80' if bw = 80, to make '80+80' bw, - * or '.5' if bw = 2.5 to make '2.5' bw . + * or '+80' if bw = 80, to make '80+80' bw. */ c = tolower((int)a[0]); @@ -509,19 +511,6 @@ wf_chspec_aton(const char *a) /* read secondary 80MHz channel */ if (!read_uint(&a, &ch2)) return 0; - } else if (c == '.') { - /* 2.5 */ - /* must be looking at '.5' - * check and consume this string. - */ - chspec_bw = WL_CHANSPEC_BW_2P5; - - a ++; /* consume the char '.' */ - - /* consume the '5' string */ - if (*a++ != '5') { - return 0; - } } done_read: @@ -535,9 +524,9 @@ done_read: return 0; /* Now have all the chanspec string parts read; - * chspec_band, ctl_ch, chspec_bw, sb_ul, ch1, ch2. + * chspec_band, pri_ch, chspec_bw, sb_ul, ch1, ch2. * chspec_band and chspec_bw are chanspec values. - * Need to convert ctl_ch, sb_ul, and ch1,ch2 into + * Need to convert pri_ch, sb_ul, and ch1,ch2 into * a center channel (or two) and sideband. */ @@ -546,23 +535,23 @@ done_read: */ if (sb_ul != '\0') { if (sb_ul == 'l') { - chspec_ch = UPPER_20_SB(ctl_ch); + chspec_ch = UPPER_20_SB(pri_ch); chspec_sb = WL_CHANSPEC_CTL_SB_LLL; } else if (sb_ul == 'u') { - chspec_ch = LOWER_20_SB(ctl_ch); + chspec_ch = LOWER_20_SB(pri_ch); chspec_sb = WL_CHANSPEC_CTL_SB_LLU; } } /* if the bw is 20, center and sideband are trivial */ - else if (BW_LE20(chspec_bw)) { - chspec_ch = ctl_ch; + else if (chspec_bw == WL_CHANSPEC_BW_20) { + chspec_ch = pri_ch; chspec_sb = WL_CHANSPEC_CTL_SB_NONE; } /* if the bw is 40/80/160, not 80+80, a single method * can be used to to find the center and sideband */ else if (chspec_bw != WL_CHANSPEC_BW_8080) { - /* figure out ctl sideband based on ctl channel and bandwidth */ + /* figure out primary20 sideband based on primary20 channel and bandwidth */ const uint8 *center_ch = NULL; int num_ch = 0; int sb = -1; @@ -581,7 +570,7 @@ done_read: } for (i = 0; i < num_ch; i ++) { - sb = channel_to_sb(center_ch[i], ctl_ch, bw); + sb = channel_to_sb(center_ch[i], pri_ch, bw); if (sb >= 0) { chspec_ch = center_ch[i]; chspec_sb = sb << WL_CHANSPEC_CTL_SB_SHIFT; @@ -614,9 +603,9 @@ done_read: /* figure out primary 20 MHz sideband */ /* is the primary channel contained in the 1st 80MHz channel? */ - sb = channel_to_sb(ch1, ctl_ch, bw); + sb = channel_to_sb(ch1, pri_ch, bw); if (sb < 0) { - /* no match for primary channel 'ctl_ch' in segment0 80MHz channel */ + /* no match for primary channel 'pri_ch' in segment0 80MHz channel */ return 0; } @@ -633,7 +622,7 @@ done_read: /* * Verify the chanspec is using a legal set of parameters, i.e. that the - * chanspec specified a band, bw, ctl_sb and channel and that the + * chanspec specified a band, bw, pri_sb and channel and that the * combination could be legal given any set of circumstances. * RETURNS: TRUE is the chanspec is malformed, false if it looks good. */ @@ -659,7 +648,9 @@ wf_chspec_malformed(chanspec_t chanspec) if (ch1_id >= WF_NUM_5G_80M_CHANS || ch2_id >= WF_NUM_5G_80M_CHANS) return TRUE; - } else if (BW_LE160(chspec_bw)) { + } else if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40 || + chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_160) { + if (chspec_ch > MAXCHANNEL) { return TRUE; } @@ -673,7 +664,7 @@ wf_chspec_malformed(chanspec_t chanspec) } /* side band needs to be consistent with bandwidth */ - if (BW_LE20(chspec_bw)) { + if (chspec_bw == WL_CHANSPEC_BW_20) { if (CHSPEC_CTL_SB(chanspec) != WL_CHANSPEC_CTL_SB_LLL) return TRUE; } else if (chspec_bw == WL_CHANSPEC_BW_40) { @@ -681,6 +672,9 @@ wf_chspec_malformed(chanspec_t chanspec) return TRUE; } else if (chspec_bw == WL_CHANSPEC_BW_80 || chspec_bw == WL_CHANSPEC_BW_8080) { + /* both 80MHz and 80+80MHz use 80MHz side bands. + * 80+80 SB info is relative to the primary 80MHz sub-band. + */ if (CHSPEC_CTL_SB(chanspec) > WL_CHANSPEC_CTL_SB_LUU) return TRUE; } @@ -705,7 +699,7 @@ wf_chspec_valid(chanspec_t chanspec) if (CHSPEC_IS2G(chanspec)) { /* must be valid bandwidth and channel range */ - if (BW_LE20(chspec_bw)) { + if (chspec_bw == WL_CHANSPEC_BW_20) { if (chspec_ch >= 1 && chspec_ch <= 14) return TRUE; } else if (chspec_bw == WL_CHANSPEC_BW_40) { @@ -727,7 +721,7 @@ wf_chspec_valid(chanspec_t chanspec) const uint8 *center_ch; uint num_ch, i; - if (BW_LE40(chspec_bw)) { + if (chspec_bw == WL_CHANSPEC_BW_20 || chspec_bw == WL_CHANSPEC_BW_40) { center_ch = wf_5g_40m_chans; num_ch = WF_NUM_5G_40M_CHANS; } else if (chspec_bw == WL_CHANSPEC_BW_80) { @@ -742,7 +736,7 @@ wf_chspec_valid(chanspec_t chanspec) } /* check for a valid center channel */ - if (BW_LE20(chspec_bw)) { + if (chspec_bw == WL_CHANSPEC_BW_20) { /* We don't have an array of legal 20MHz 5G channels, but they are * each side of the legal 40MHz channels. Check the chanspec * channel against either side of the 40MHz channels. @@ -784,12 +778,37 @@ wf_chspec_valid(chanspec_t chanspec) } /* - * This function returns the channel number that control traffic is being sent on, for 20MHz - * channels this is just the channel number, for 40MHZ, 80MHz, 160MHz channels it is the 20MHZ - * sideband depending on the chanspec selected + * This function returns TRUE if both the chanspec can co-exist in PHY. + * Addition to primary20 channel, the function checks for side band for 2g 40 channels + */ +bool +wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2) +{ + bool same_primary; + + same_primary = (wf_chspec_primary20_chan(chspec1) == wf_chspec_primary20_chan(chspec2)); + + if (same_primary && CHSPEC_IS2G(chspec1)) { + if (CHSPEC_IS40(chspec1) && CHSPEC_IS40(chspec2)) { + return (CHSPEC_CTL_SB(chspec1) == CHSPEC_CTL_SB(chspec2)); + } + } + return same_primary; +} + +/** + * Return the primary 20MHz channel. + * + * This function returns the channel number of the primary 20MHz channel. For + * 20MHz channels this is just the channel number. For 40MHz or wider channels + * it is the primary 20MHz channel specified by the chanspec. + * + * @param chspec input chanspec + * + * @return Returns the channel number of the primary 20MHz channel */ uint8 -wf_chspec_ctlchan(chanspec_t chspec) +wf_chspec_primary20_chan(chanspec_t chspec) { uint center_chan; uint bw_mhz; @@ -798,7 +817,7 @@ wf_chspec_ctlchan(chanspec_t chspec) ASSERT(!wf_chspec_malformed(chspec)); /* Is there a sideband ? */ - if (CHSPEC_BW_LE20(chspec)) { + if (CHSPEC_IS20(chspec)) { return CHSPEC_CHANNEL(chspec); } else { sb = CHSPEC_CTL_SB(chspec) >> WL_CHANSPEC_CTL_SB_SHIFT; @@ -815,46 +834,46 @@ wf_chspec_ctlchan(chanspec_t chspec) center_chan = wf_5g_80m_chans[chan_id]; } else { - bw_mhz = bw_chspec_to_mhz(chspec); + bw_mhz = wf_bw_chspec_to_mhz(chspec); center_chan = CHSPEC_CHANNEL(chspec) >> WL_CHANSPEC_CHAN_SHIFT; } - return (channel_to_ctl_chan(center_chan, bw_mhz, sb)); + return (channel_to_primary20_chan(center_chan, bw_mhz, sb)); } } /* given a chanspec, return the bandwidth string */ const char * -wf_chspec_to_bw_str(chanspec_t chspec) +BCMRAMFN(wf_chspec_to_bw_str)(chanspec_t chspec) { return wf_chspec_bw_str[(CHSPEC_BW(chspec) >> WL_CHANSPEC_BW_SHIFT)]; } /* - * This function returns the chanspec of the control channel of a given chanspec + * Return the primary 20MHz chanspec of the given chanspec */ chanspec_t -wf_chspec_ctlchspec(chanspec_t chspec) +wf_chspec_primary20_chspec(chanspec_t chspec) { - chanspec_t ctl_chspec = chspec; - uint8 ctl_chan; + chanspec_t pri_chspec = chspec; + uint8 pri_chan; ASSERT(!wf_chspec_malformed(chspec)); /* Is there a sideband ? */ - if (!CHSPEC_BW_LE20(chspec)) { - ctl_chan = wf_chspec_ctlchan(chspec); - ctl_chspec = ctl_chan | WL_CHANSPEC_BW_20; - ctl_chspec |= CHSPEC_BAND(chspec); + if (!CHSPEC_IS20(chspec)) { + pri_chan = wf_chspec_primary20_chan(chspec); + pri_chspec = pri_chan | WL_CHANSPEC_BW_20; + pri_chspec |= CHSPEC_BAND(chspec); } - return ctl_chspec; + return pri_chspec; } -/* return chanspec given control channel and bandwidth +/* return chanspec given primary 20MHz channel and bandwidth * return 0 on error */ uint16 -wf_channel2chspec(uint ctl_ch, uint bw) +wf_channel2chspec(uint pri_ch, uint bw) { uint16 chspec; const uint8 *center_ch = NULL; @@ -862,7 +881,7 @@ wf_channel2chspec(uint ctl_ch, uint bw) int sb = -1; int i = 0; - chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); + chspec = ((pri_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); chspec |= bw; @@ -878,15 +897,15 @@ wf_channel2chspec(uint ctl_ch, uint bw) center_ch = wf_5g_160m_chans; num_ch = WF_NUM_5G_160M_CHANS; bw = 160; - } else if (BW_LE20(bw)) { - chspec |= ctl_ch; + } else if (bw == WL_CHANSPEC_BW_20) { + chspec |= pri_ch; return chspec; } else { return 0; } for (i = 0; i < num_ch; i ++) { - sb = channel_to_sb(center_ch[i], ctl_ch, bw); + sb = channel_to_sb(center_ch[i], pri_ch, bw); if (sb >= 0) { chspec |= center_ch[i]; chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT); @@ -903,9 +922,9 @@ wf_channel2chspec(uint ctl_ch, uint bw) } /* - * This function returns the chanspec for the primary 40MHz of an 80MHz channel. - * The control sideband specifies the same 20MHz channel that the 80MHz channel is using - * as the primary 20MHz channel. + * This function returns the chanspec for the primary 40MHz of an 80MHz or wider channel. + * The primary 20MHz channel of the returned 40MHz chanspec is the same as the primary 20MHz + * channel of the input chanspec. */ extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec) { @@ -961,7 +980,7 @@ extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec) * frequency is not a 2.4 GHz channel, or if the frequency is not and even * multiple of 5 MHz from the base frequency to the base plus 1 GHz. * - * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 + * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 */ int wf_mhz2channel(uint freq, uint start_factor) @@ -1015,7 +1034,7 @@ wf_mhz2channel(uint freq, uint start_factor) * the answer is rounded down to an integral MHz. * -1 is returned for an out of range channel. * - * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 + * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 */ int wf_channel2mhz(uint ch, uint start_factor) @@ -1061,7 +1080,7 @@ wf_chspec_80(uint8 center_channel, uint8 primary_channel) for (i = 0; i < WF_NUM_SIDEBANDS_80MHZ; i++) { chanspec_cur = CH80MHZ_CHSPEC(center_channel, sidebands[i]); - if (primary_channel == wf_chspec_ctlchan(chanspec_cur)) { + if (primary_channel == wf_chspec_primary20_chan(chanspec_cur)) { chanspec = chanspec_cur; break; } @@ -1086,7 +1105,7 @@ wf_chspec_80(uint8 center_channel, uint8 primary_channel) * * Returns INVCHANSPEC in case of error. * - * Refer to IEEE802.11ac section 22.3.14 "Channelization". + * Refer to 802.11-2016 section 22.3.14 "Channelization". */ chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1) @@ -1113,7 +1132,7 @@ wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0, uint8 chan1) /* no, so does the primary channel fit with the 2nd 80MHz channel ? */ sb = channel_to_sb(chan1, primary_20mhz, 80); if (sb < 0) { - /* no match for ctl_ch to either 80MHz center channel */ + /* no match for pri_ch to either 80MHz center channel */ return INVCHANSPEC; } /* swapped, so chan1 is frequency segment 0, and chan0 is seg 1 */ @@ -1143,93 +1162,47 @@ wf_chspec_get80Mhz_ch(uint8 chan_80Mhz_id) } /* - * Returns the primary 80 Mhz channel for the provided chanspec - * - * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved - * - * returns -1 in case the provided channel is 20/40 Mhz chanspec + * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec */ - uint8 wf_chspec_primary80_channel(chanspec_t chanspec) { + chanspec_t primary80_chspec; uint8 primary80_chan; - if (CHSPEC_IS80(chanspec)) { - primary80_chan = CHSPEC_CHANNEL(chanspec); - } - else if (CHSPEC_IS8080(chanspec)) { - /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ - primary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chanspec)); - } - else if (CHSPEC_IS160(chanspec)) { - uint8 center_chan = CHSPEC_CHANNEL(chanspec); - uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; + primary80_chspec = wf_chspec_primary80_chspec(chanspec); - /* based on the sb value primary 80 channel can be retrieved - * if sb is in range 0 to 3 the lower band is the 80Mhz primary band - */ - if (sb < 4) { - primary80_chan = center_chan - CH_40MHZ_APART; - } - /* if sb is in range 4 to 7 the upper band is the 80Mhz primary band */ - else - { - primary80_chan = center_chan + CH_40MHZ_APART; - } - } - else { - /* for 20 and 40 Mhz */ - primary80_chan = -1; + if (primary80_chspec == INVCHANSPEC) { + primary80_chan = INVCHANNEL; + } else { + primary80_chan = CHSPEC_CHANNEL(primary80_chspec); } + return primary80_chan; } /* - * Returns the secondary 80 Mhz channel for the provided chanspec - * - * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved - * - * returns -1 in case the provided channel is 20/40/80 Mhz chanspec + * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec */ uint8 wf_chspec_secondary80_channel(chanspec_t chanspec) { + chanspec_t secondary80_chspec; uint8 secondary80_chan; - if (CHSPEC_IS8080(chanspec)) { - secondary80_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chanspec)); - } - else if (CHSPEC_IS160(chanspec)) { - uint8 center_chan = CHSPEC_CHANNEL(chanspec); - uint sb = CHSPEC_CTL_SB(chanspec) >> WL_CHANSPEC_CTL_SB_SHIFT; + secondary80_chspec = wf_chspec_secondary80_chspec(chanspec); - /* based on the sb value secondary 80 channel can be retrieved - * if sb is in range 0 to 3 upper band is the secondary 80Mhz band - */ - if (sb < 4) { - secondary80_chan = center_chan + CH_40MHZ_APART; - } - /* if sb is in range 4 to 7 the lower band is the secondary 80Mhz band */ - else - { - secondary80_chan = center_chan - CH_40MHZ_APART; - } - } - else { - /* for 20, 40, and 80 Mhz */ - secondary80_chan = -1; + if (secondary80_chspec == INVCHANSPEC) { + secondary80_chan = INVCHANNEL; + } else { + secondary80_chan = CHSPEC_CHANNEL(secondary80_chspec); } + return secondary80_chan; } /* - * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel. - * - * chanspec - Input chanspec for which the primary 80Mhz chanspec has to be retreived - * - * returns the input chanspec in case the provided chanspec is an 80 MHz chanspec - * returns INVCHANSPEC in case the provided channel is 20/40 MHz chanspec + * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel */ chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec) @@ -1239,16 +1212,16 @@ wf_chspec_primary80_chspec(chanspec_t chspec) uint sb; ASSERT(!wf_chspec_malformed(chspec)); + if (CHSPEC_IS80(chspec)) { chspec80 = chspec; } else if (CHSPEC_IS8080(chspec)) { + sb = CHSPEC_CTL_SB(chspec); - /* Channel ID 1 corresponds to frequency segment 0, the primary 80 MHz segment */ + /* primary sub-band is stored in seg0 */ center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec)); - sb = CHSPEC_CTL_SB(chspec); - /* Create primary 80MHz chanspec */ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); } @@ -1265,6 +1238,7 @@ wf_chspec_primary80_chspec(chanspec_t chspec) center_chan += CH_40MHZ_APART; sb -= WL_CHANSPEC_CTL_SB_ULL; } + /* Create primary 80MHz chanspec */ chspec80 = (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_80 | sb | center_chan); } @@ -1275,6 +1249,79 @@ wf_chspec_primary80_chspec(chanspec_t chspec) return chspec80; } +/* + * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel + */ +chanspec_t +wf_chspec_secondary80_chspec(chanspec_t chspec) +{ + chanspec_t chspec80; + uint center_chan; + + ASSERT(!wf_chspec_malformed(chspec)); + + if (CHSPEC_IS8080(chspec)) { + /* secondary sub-band is stored in seg1 */ + center_chan = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec)); + + /* Create secondary 80MHz chanspec */ + chspec80 = (WL_CHANSPEC_BAND_5G | + WL_CHANSPEC_BW_80 | + WL_CHANSPEC_CTL_SB_LL | + center_chan); + } + else if (CHSPEC_IS160(chspec)) { + center_chan = CHSPEC_CHANNEL(chspec); + + if (CHSPEC_CTL_SB(chspec) < WL_CHANSPEC_CTL_SB_ULL) { + /* Primary 80MHz is on lower side */ + center_chan -= CH_40MHZ_APART; + } + else { + /* Primary 80MHz is on upper side */ + center_chan += CH_40MHZ_APART; + } + + /* Create secondary 80MHz chanspec */ + chspec80 = (WL_CHANSPEC_BAND_5G | + WL_CHANSPEC_BW_80 | + WL_CHANSPEC_CTL_SB_LL | + center_chan); + } + else { + chspec80 = INVCHANSPEC; + } + + return chspec80; +} + +/* + * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels + * + * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1 + */ +void +wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch) +{ + + if (CHSPEC_IS8080(chspec)) { + ch[0] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN1(chspec)); + ch[1] = wf_chspec_get80Mhz_ch(CHSPEC_CHAN2(chspec)); + } + else if (CHSPEC_IS160(chspec)) { + uint8 center_chan = CHSPEC_CHANNEL(chspec); + ch[0] = center_chan - CH_40MHZ_APART; + ch[1] = center_chan + CH_40MHZ_APART; + } + else { + /* for 20, 40, and 80 Mhz */ + ch[0] = CHSPEC_CHANNEL(chspec); + ch[1] = -1; + } + return; + +} + #ifdef WL11AC_80P80 uint8 wf_chspec_channel(chanspec_t chspec) @@ -1347,3 +1394,71 @@ wf_channel_create_opclass_frm_chspec(chanspec_t chspec) /* TODO: Implement this function ! */ return 12; /* opclass 12 for basic 2G channels */ } + +/* Populates array with all 20MHz side bands of a given chanspec_t in the following order: + * primary20, secondary20, two secondary40s, four secondary80s. + * 'chspec' is the chanspec of interest + * 'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec + * + * Works with 20, 40, 80, 80p80 and 160MHz chspec + */ +void +wf_get_all_ext(chanspec_t chspec, uint8 *pext) +{ +#ifdef WL11N_20MHZONLY + GET_ALL_SB(chspec, pext); +#else /* !WL11N_20MHZONLY */ + chanspec_t t = (CHSPEC_IS160(chspec) || CHSPEC_IS8080(chspec)) ? /* if bw > 80MHz */ + wf_chspec_primary80_chspec(chspec) : (chspec); /* extract primary 80 */ + /* primary20 channel as first element */ + uint8 pri_ch = (pext)[0] = wf_chspec_primary20_chan(t); + if (CHSPEC_IS20(chspec)) return; /* nothing more to do since 20MHz chspec */ + /* 20MHz EXT */ + (pext)[1] = pri_ch + (IS_CTL_IN_L20(t) ? CH_20MHZ_APART : -CH_20MHZ_APART); + if (CHSPEC_IS40(chspec)) return; /* nothing more to do since 40MHz chspec */ + /* center 40MHz EXT */ + t = wf_channel2chspec(pri_ch + (IS_CTL_IN_L40(chspec) ? + CH_40MHZ_APART : -CH_40MHZ_APART), WL_CHANSPEC_BW_40); + GET_ALL_SB(t, &((pext)[2])); /* get the 20MHz side bands in 40MHz EXT */ + if (CHSPEC_IS80(chspec)) return; /* nothing more to do since 80MHz chspec */ + t = CH80MHZ_CHSPEC(wf_chspec_secondary80_channel(chspec), WL_CHANSPEC_CTL_SB_LLL); + /* get the 20MHz side bands in 80MHz EXT (secondary) */ + GET_ALL_SB(t, &((pext)[4])); +#endif /* !WL11N_20MHZONLY */ +} + +/* + * Given two chanspecs, returns true if they overlap. + * (Overlap: At least one 20MHz subband is common between the two chanspecs provided) + */ +bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1) +{ + uint8 ch0, ch1; + + FOREACH_20_SB(chspec0, ch0) { + FOREACH_20_SB(chspec1, ch1) { + if (ABS(ch0 - ch1) < CH_20MHZ_APART) { + return TRUE; + } + } + } + + return FALSE; +} + +uint8 +channel_bw_to_width(chanspec_t chspec) +{ + uint8 channel_width; + + if (CHSPEC_IS80(chspec)) + channel_width = VHT_OP_CHAN_WIDTH_80; + else if (CHSPEC_IS160(chspec)) + channel_width = VHT_OP_CHAN_WIDTH_160; + else if (CHSPEC_IS8080(chspec)) + channel_width = VHT_OP_CHAN_WIDTH_80_80; + else + channel_width = VHT_OP_CHAN_WIDTH_20_40; + + return channel_width; +} diff --git a/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.h b/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.h index 28c6e2739303cfa8f41416e954d00cf543540873..6376dd9a1e34a90da7975f4737a62c0a24193074 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.h +++ b/drivers/net/wireless/bcmdhd_oo/bcmwifi_channels.h @@ -3,14 +3,14 @@ * This header file housing the define and function prototype use by * both the wl driver, tools & Apps. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,20 +26,16 @@ * * <> * - * $Id: bcmwifi_channels.h 612483 2016-01-14 03:44:27Z $ + * $Id: bcmwifi_channels.h 695288 2017-04-19 17:20:39Z $ */ #ifndef _bcmwifi_channels_h_ #define _bcmwifi_channels_h_ - -/* A chanspec holds the channel number, band, bandwidth and control sideband */ +/* A chanspec holds the channel number, band, bandwidth and primary 20MHz sideband */ typedef uint16 chanspec_t; /* channel defines */ -#define CH_UPPER_SB 0x01 -#define CH_LOWER_SB 0x02 -#define CH_EWA_VALID 0x04 #define CH_80MHZ_APART 16 #define CH_40MHZ_APART 8 #define CH_20MHZ_APART 4 @@ -54,6 +50,8 @@ typedef uint16 chanspec_t; */ #define MAXCHANNEL_NUM (MAXCHANNEL - 1) /* max channel number */ +#define INVCHANNEL 255 /* error value for a bad channel */ + /* channel bitvec */ typedef struct { uint8 vec[MAXCHANNEL/8]; /* bitvec of channels */ @@ -105,7 +103,6 @@ typedef struct { #define WL_CHANSPEC_BW_80 0x2000 #define WL_CHANSPEC_BW_160 0x2800 #define WL_CHANSPEC_BW_8080 0x3000 -#define WL_CHANSPEC_BW_2P5 0x3800 #define WL_CHANSPEC_BAND_MASK 0xc000 #define WL_CHANSPEC_BAND_SHIFT 14 @@ -125,8 +122,9 @@ typedef struct { #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ((channel) + CH_10MHZ_APART) : 0) +/* pass a 80MHz channel number (uint8) to get respective LL, UU, LU, UL */ #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)) ? \ +#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) @@ -137,15 +135,6 @@ typedef struct { #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ (((channel) <= CH_MAX_2G_CHANNEL) ? \ WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -#define CH2P5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_2P5 | \ - (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -#define CH5MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_5 | \ - (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -#define CH10MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_10 | \ - (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) #define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ ((channel) + CH_20MHZ_APART) : 0) #define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ @@ -158,16 +147,13 @@ typedef struct { #define CH160MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ ((channel) | (ctlsb) | \ WL_CHANSPEC_BW_160 | WL_CHANSPEC_BAND_5G) -#define CHBW_CHSPEC(bw, channel) (chanspec_t)((chanspec_t)(channel) | (bw) | \ - (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) /* simple MACROs to get different fields of chanspec */ #ifdef WL11AC_80P80 #define CHSPEC_CHANNEL(chspec) wf_chspec_channel(chspec) #else #define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) -#endif +#endif // endif #define CHSPEC_CHAN1(chspec) ((chspec) & WL_CHANSPEC_CHAN1_MASK) >> WL_CHANSPEC_CHAN1_SHIFT #define CHSPEC_CHAN2(chspec) ((chspec) & WL_CHANSPEC_CHAN2_MASK) >> WL_CHANSPEC_CHAN2_SHIFT #define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) @@ -175,77 +161,211 @@ typedef struct { #define CHSPEC_BW(chspec) ((chspec) & WL_CHANSPEC_BW_MASK) #ifdef WL11N_20MHZONLY -#ifdef WL11ULB -#define CHSPEC_IS2P5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5) -#define CHSPEC_IS5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5) -#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) -#else -#define CHSPEC_IS2P5(chspec) 0 -#define CHSPEC_IS5(chspec) 0 -#define CHSPEC_IS10(chspec) 0 -#endif #define CHSPEC_IS20(chspec) 1 #define CHSPEC_IS20_2G(chspec) ((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ CHSPEC_IS2G(chspec)) #ifndef CHSPEC_IS40 #define CHSPEC_IS40(chspec) 0 -#endif +#endif // endif #ifndef CHSPEC_IS80 #define CHSPEC_IS80(chspec) 0 -#endif +#endif // endif #ifndef CHSPEC_IS160 #define CHSPEC_IS160(chspec) 0 -#endif +#endif // endif #ifndef CHSPEC_IS8080 #define CHSPEC_IS8080(chspec) 0 -#endif -#define BW_LE20(bw) TRUE -#define CHSPEC_ISLE20(chspec) TRUE +#endif // endif + +/* see FOREACH_20_SB in !WL11N_20MHZONLY section */ +#define FOREACH_20_SB(chspec, channel) \ + for (channel = CHSPEC_CHANNEL(chspec); channel; channel = 0) + +/* see GET_ALL_SB in !WL11N_20MHZONLY section */ +#define GET_ALL_SB(chspec, psb) do { \ + psb[0] = CHSPEC_CHANNEL(chspec); \ +} while (0) + #else /* !WL11N_20MHZONLY */ -#define CHSPEC_IS2P5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_2P5) -#define CHSPEC_IS5(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_5) -#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) #define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) #define CHSPEC_IS20_5G(chspec) ((((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) && \ CHSPEC_IS5G(chspec)) #ifndef CHSPEC_IS40 #define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) -#endif +#endif // endif #ifndef CHSPEC_IS80 #define CHSPEC_IS80(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_80) -#endif +#endif // endif #ifndef CHSPEC_IS160 #define CHSPEC_IS160(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_160) -#endif +#endif // endif #ifndef CHSPEC_IS8080 #define CHSPEC_IS8080(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_8080) -#endif - -#ifdef WL11ULB -#define BW_LT20(bw) (((bw) == WL_CHANSPEC_BW_2P5) || \ - ((bw) == WL_CHANSPEC_BW_5) || \ - ((bw) == WL_CHANSPEC_BW_10)) -#define CHSPEC_BW_LT20(chspec) (BW_LT20(CHSPEC_BW(chspec))) -/* This MACRO is strictly to avoid abandons in existing code with ULB feature and is in no way - * optimial to use. Should be replaced with CHSPEC_BW_LE() instead - */ -#define BW_LE20(bw) (((bw) == WL_CHANSPEC_BW_2P5) || \ - ((bw) == WL_CHANSPEC_BW_5) || \ - ((bw) == WL_CHANSPEC_BW_10) || \ - ((bw) == WL_CHANSPEC_BW_20)) -#define CHSPEC_ISLE20(chspec) (BW_LE20(CHSPEC_BW(chspec))) - -#else /* WL11ULB */ -#define BW_LE20(bw) ((bw) == WL_CHANSPEC_BW_20) -#define CHSPEC_ISLE20(chspec) (CHSPEC_IS20(chspec)) -#endif /* WL11ULB */ +#endif // endif + +/* pass a center channel and get channel offset from it by 10MHz */ +#define CH_OFF_10MHZ_MULTIPLES(channel, offset) ((uint8) (((offset) < 0) ? \ + (((channel) > (WL_CHANSPEC_CHAN_MASK & ((uint16)((-(offset)) * CH_10MHZ_APART)))) ?\ + ((channel) + (offset) * CH_10MHZ_APART) : 0) : \ + (((channel) < (uint16)(MAXCHANNEL - (offset) * CH_10MHZ_APART)) ? \ + ((channel) + (offset) * CH_10MHZ_APART) : 0))) + +#if defined(WL11AC_80P80) || defined(WL11AC_160) +/* pass a 160MHz center channel to get 20MHz subband channel numbers */ +#define LLL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -7) +#define LLU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -5) +#define LUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -3) +#define LUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, -1) +#define ULL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 1) +#define ULU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 3) +#define UUL_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 5) +#define UUU_20_SB_160(channel) CH_OFF_10MHZ_MULTIPLES(channel, 7) + +/* given an 80p80 channel, return the lower 80MHz sideband */ +#define LOWER_80_SB(chspec) (wf_chspec_primary80_channel(chspec) < \ + wf_chspec_secondary80_channel(chspec) ? \ + wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec)) + +/* given an 80p80 channel, return the upper 80MHz sideband */ +#define UPPER_80_SB(chspec) (wf_chspec_primary80_channel(chspec) > \ + wf_chspec_secondary80_channel(chspec) ? \ + wf_chspec_primary80_channel(chspec) : wf_chspec_secondary80_channel(chspec)) + +/* pass an 80P80 chanspec (not channel) to get 20MHz subnand channel numbers */ +#define LLL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -3) +#define LLU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), -1) +#define LUL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), 1) +#define LUU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(LOWER_80_SB(chspec), 3) +#define ULL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -3) +#define ULU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), -1) +#define UUL_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), 1) +#define UUU_20_SB_8080(chspec) CH_OFF_10MHZ_MULTIPLES(UPPER_80_SB(chspec), 3) + +/* get lowest 20MHz sideband of a given chspec + * (works with 20, 40, 80, 160, 80p80) + */ +#define CH_FIRST_20_SB(chspec) ((uint8) (\ + CHSPEC_IS160(chspec) ? LLL_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS8080(chspec) ? LLL_20_SB_8080(chspec) : (\ + CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ + CHSPEC_CHANNEL(chspec)))))) + +/* get upper most 20MHz sideband of a given chspec + * (works with 20, 40, 80, 160, 80p80) + */ +#define CH_LAST_20_SB(chspec) ((uint8) (\ + CHSPEC_IS160(chspec) ? UUU_20_SB_160(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS8080(chspec) ? UUU_20_SB_8080(chspec) : (\ + CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ + CHSPEC_CHANNEL(chspec)))))) + +/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband + * (works with 80p80 only) + * resolves to 0 if called with upper most channel + */ +#define CH_NEXT_20_SB_IN_8080(chspec, channel) ((uint8) (\ + ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ + ((channel) == LUU_20_SB_8080(chspec) ? ULL_20_SB_8080(chspec) : \ + (channel) + CH_20MHZ_APART)))) + +/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband + * (works with 20, 40, 80, 160, 80p80) + * resolves to 0 if called with upper most channel + */ +#define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ + (CHSPEC_IS8080(chspec) ? CH_NEXT_20_SB_IN_8080((chspec), (channel)) : \ + ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ + ((channel) + CH_20MHZ_APART))))) + +#else /* WL11AC_80P80, WL11AC_160 */ + +#define LLL_20_SB_160(channel) 0 +#define LLU_20_SB_160(channel) 0 +#define LUL_20_SB_160(channel) 0 +#define LUU_20_SB_160(channel) 0 +#define ULL_20_SB_160(channel) 0 +#define ULU_20_SB_160(channel) 0 +#define UUL_20_SB_160(channel) 0 +#define UUU_20_SB_160(channel) 0 + +#define LOWER_80_SB(chspec) 0 + +#define UPPER_80_SB(chspec) 0 + +#define LLL_20_SB_8080(chspec) 0 +#define LLU_20_SB_8080(chspec) 0 +#define LUL_20_SB_8080(chspec) 0 +#define LUU_20_SB_8080(chspec) 0 +#define ULL_20_SB_8080(chspec) 0 +#define ULU_20_SB_8080(chspec) 0 +#define UUL_20_SB_8080(chspec) 0 +#define UUU_20_SB_8080(chspec) 0 + +/* get lowest 20MHz sideband of a given chspec + * (works with 20, 40, 80) + */ +#define CH_FIRST_20_SB(chspec) ((uint8) (\ + CHSPEC_IS80(chspec) ? LL_20_SB(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS40(chspec) ? LOWER_20_SB(CHSPEC_CHANNEL(chspec)) : \ + CHSPEC_CHANNEL(chspec)))) +/* get upper most 20MHz sideband of a given chspec + * (works with 20, 40, 80, 160, 80p80) + */ +#define CH_LAST_20_SB(chspec) ((uint8) (\ + CHSPEC_IS80(chspec) ? UU_20_SB(CHSPEC_CHANNEL(chspec)) : (\ + CHSPEC_IS40(chspec) ? UPPER_20_SB(CHSPEC_CHANNEL(chspec)) : \ + CHSPEC_CHANNEL(chspec)))) + +/* call this with chspec and a valid 20MHz sideband of this channel to get the next 20MHz sideband + * (works with 20, 40, 80, 160, 80p80) + * resolves to 0 if called with upper most channel + */ +#define CH_NEXT_20_SB(chspec, channel) ((uint8) (\ + ((uint8) ((channel) + CH_20MHZ_APART) > CH_LAST_20_SB(chspec) ? 0 : \ + ((channel) + CH_20MHZ_APART)))) + +#endif /* WL11AC_80P80, WL11AC_160 */ + +/* Iterator for 20MHz side bands of a chanspec: (chanspec_t chspec, uint8 channel) + * 'chspec' chanspec_t of interest (used in loop, better to pass a resolved value than a macro) + * 'channel' must be a variable (not an expression). + */ +#define FOREACH_20_SB(chspec, channel) \ + for (channel = CH_FIRST_20_SB(chspec); channel; \ + channel = CH_NEXT_20_SB((chspec), channel)) + +/* Uses iterator to populate array with all side bands involved (sorted lower to upper). + * 'chspec' chanspec_t of interest + * 'psb' pointer to uint8 array of enough size to hold all side bands for the given chspec + */ +#define GET_ALL_SB(chspec, psb) do { \ + uint8 channel, idx = 0; \ + chanspec_t chspec_local = chspec; \ + FOREACH_20_SB(chspec_local, channel) \ + (psb)[idx++] = channel; \ +} while (0) + +/* given a chanspec of any bw, tests if primary20 SB is in lower 20, 40, 80 respectively */ +#define IS_CTL_IN_L20(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_U) /* CTL SB is in low 20 of any 40 */ +#define IS_CTL_IN_L40(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_UL) /* in low 40 of any 80 */ +#define IS_CTL_IN_L80(chspec) !((chspec) & WL_CHANSPEC_CTL_SB_ULL) /* in low 80 of 80p80/160 */ + #endif /* !WL11N_20MHZONLY */ -#define BW_LE40(bw) (BW_LE20(bw) || ((bw) == WL_CHANSPEC_BW_40)) +/* ULB introduced macros. Remove once ULB is cleaned from phy code */ +#define CHSPEC_IS2P5(chspec) 0 +#define CHSPEC_IS5(chspec) 0 +#define CHSPEC_IS10(chspec) 0 +#define CHSPEC_ISLE20(chspec) (CHSPEC_IS20(chspec)) +#define CHSPEC_BW_LE20(chspec) (CHSPEC_IS20(chspec)) + +#define BW_LE40(bw) ((bw) == WL_CHANSPEC_BW_20 || ((bw) == WL_CHANSPEC_BW_40)) #define BW_LE80(bw) (BW_LE40(bw) || ((bw) == WL_CHANSPEC_BW_80)) #define BW_LE160(bw) (BW_LE80(bw) || ((bw) == WL_CHANSPEC_BW_160)) -#define CHSPEC_BW_LE20(chspec) (BW_LE20(CHSPEC_BW(chspec))) + #define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) #define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) #define CHSPEC_SB_UPPER(chspec) \ @@ -261,6 +381,11 @@ typedef struct { */ #define CHANSPEC_STR_LEN 20 +/* + * This function returns TRUE if both the chanspec can co-exist in PHY. + * Addition to primary20 channel, the function checks for side band for 2g 40 channels + */ +extern bool wf_chspec_coexist(chanspec_t chspec1, chanspec_t chspec2); #define CHSPEC_IS_BW_160_WIDE(chspec) (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_160 ||\ CHSPEC_BW(chspec) == WL_CHANSPEC_BW_8080) @@ -272,57 +397,25 @@ typedef struct { * The LT/LE/GT/GE macros check first checks whether both chspec bandwidth and bw are 160 wide. * If both chspec bandwidth and bw is not 160 wide, then the comparison is made. */ -#ifdef WL11ULB -#define CHSPEC_BW_GE(chspec, bw) \ - (((CHSPEC_IS_BW_160_WIDE(chspec) &&\ - ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ - (CHSPEC_BW(chspec) >= (bw))) && \ - (!(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5))) -#else /* WL11ULB */ #define CHSPEC_BW_GE(chspec, bw) \ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ (CHSPEC_BW(chspec) >= (bw))) -#endif /* WL11ULB */ -#ifdef WL11ULB -#define CHSPEC_BW_LE(chspec, bw) \ - (((CHSPEC_IS_BW_160_WIDE(chspec) &&\ - ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ - (CHSPEC_BW(chspec) <= (bw))) || \ - (CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5)) -#else /* WL11ULB */ #define CHSPEC_BW_LE(chspec, bw) \ ((CHSPEC_IS_BW_160_WIDE(chspec) &&\ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) ||\ (CHSPEC_BW(chspec) <= (bw))) -#endif /* WL11ULB */ -#ifdef WL11ULB -#define CHSPEC_BW_GT(chspec, bw) \ - ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ - ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ - (CHSPEC_BW(chspec) > (bw))) && \ - (CHSPEC_BW(chspec) != WL_CHANSPEC_BW_2P5)) -#else /* WL11ULB */ #define CHSPEC_BW_GT(chspec, bw) \ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ (CHSPEC_BW(chspec) > (bw))) -#endif /* WL11ULB */ -#ifdef WL11ULB -#define CHSPEC_BW_LT(chspec, bw) \ - ((!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ - ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ - (CHSPEC_BW(chspec) < (bw))) || \ - ((CHSPEC_BW(chspec) == WL_CHANSPEC_BW_2P5 && (bw) != WL_CHANSPEC_BW_2P5))) -#else /* WL11ULB */ #define CHSPEC_BW_LT(chspec, bw) \ (!(CHSPEC_IS_BW_160_WIDE(chspec) &&\ ((bw) == WL_CHANSPEC_BW_160 || (bw) == WL_CHANSPEC_BW_8080)) &&\ (CHSPEC_BW(chspec) < (bw))) -#endif /* WL11ULB */ /* Legacy Chanspec defines * These are the defines for the previous format of the chanspec_t @@ -371,6 +464,8 @@ typedef struct { WL_LCHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ WL_LCHANSPEC_BAND_2G : WL_LCHANSPEC_BAND_5G)) +#define GET_ALL_EXT wf_get_all_ext + /* * WF_CHAN_FACTOR_* constants are used to calculate channel frequency * given a channel number. @@ -405,6 +500,16 @@ typedef struct { #define WF_NUM_SIDEBANDS_8080MHZ 4 #define WF_NUM_SIDEBANDS_160MHZ 8 +/** + * Return the chanspec bandwidth in MHz + * Bandwidth of 160 MHz will be returned for 80+80MHz chanspecs. + * + * @param chspec chanspec_t + * + * @return bandwidth of chspec in MHz units + */ +extern uint wf_bw_chspec_to_mhz(chanspec_t chspec); + /** * Convert chanspec to ascii string * @@ -444,7 +549,7 @@ extern chanspec_t wf_chspec_aton(const char *a); * Verify the chanspec fields are valid. * * Verify the chanspec is using a legal set field values, i.e. that the chanspec - * specified a band, bw, ctl_sb and channel and that the combination could be + * specified a band, bw, primary_sb, and channel and that the combination could be * legal given some set of circumstances. * * @param chanspec input chanspec to verify @@ -463,7 +568,7 @@ extern bool wf_chspec_malformed(chanspec_t chanspec); extern bool wf_chspec_valid(chanspec_t chanspec); /** - * Return the primary (control) channel. + * Return the primary 20MHz channel. * * This function returns the channel number of the primary 20MHz channel. For * 20MHz channels this is just the channel number. For 40MHz or wider channels @@ -473,21 +578,25 @@ extern bool wf_chspec_valid(chanspec_t chanspec); * * @return Returns the channel number of the primary 20MHz channel */ -extern uint8 wf_chspec_ctlchan(chanspec_t chspec); +extern uint8 wf_chspec_primary20_chan(chanspec_t chspec); -/* +/* alias for old function name */ +#define wf_chspec_ctlchan(c) wf_chspec_primary20_chan(c) + +/** * Return the bandwidth string. * * This function returns the bandwidth string for the passed chanspec. * * @param chspec input chanspec * - * @return Returns the bandwidth string + * @return Returns the bandwidth string: + * "5", "10", "20", "40", "80", "160", "80+80" */ extern const char *wf_chspec_to_bw_str(chanspec_t chspec); /** - * Return the primary (control) chanspec. + * Return the primary 20MHz chanspec. * * This function returns the chanspec of the primary 20MHz channel. For 20MHz * channels this is just the chanspec. For 40MHz or wider channels it is the @@ -497,14 +606,17 @@ extern const char *wf_chspec_to_bw_str(chanspec_t chspec); * * @return Returns the chanspec of the primary 20MHz channel */ -extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); +extern chanspec_t wf_chspec_primary20_chspec(chanspec_t chspec); + +/* alias for old function name */ +#define wf_chspec_ctlchspec(c) wf_chspec_primary20_chspec(c) /** - * Return a channel number corresponding to a frequency. + * Return the primary 40MHz chanspec. * - * This function returns the chanspec for the primary 40MHz of an 80MHz channel. - * The control sideband specifies the same 20MHz channel that the 80MHz channel is using - * as the primary 20MHz channel. + * This function returns the chanspec for the primary 40MHz of an 80MHz or wider channel. + * The primary 20MHz channel of the returned 40MHz chanspec is the same as the primary 20MHz + * channel of the input chanspec. */ extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); @@ -525,7 +637,7 @@ extern chanspec_t wf_chspec_primary40_chspec(chanspec_t chspec); * frequency is not a 2.4 GHz channel, or if the frequency is not and even * multiple of 5 MHz from the base frequency to the base plus 1 GHz. * - * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 + * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 * * @param freq frequency in MHz * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz @@ -553,7 +665,7 @@ extern int wf_mhz2channel(uint freq, uint start_factor); * the answer is rounded down to an integral MHz. * -1 is returned for an out of range channel. * - * Reference 802.11 REVma, section 17.3.8.3, and 802.11B section 18.4.6.2 + * Reference 802.11-2016, section 17.3.8.3 and section 16.3.6.3 * * @param channel input channel number * @param start_factor base frequency in 500 kHz units, e.g. 10000 for 5 GHz @@ -605,41 +717,87 @@ extern uint wf_freq2channel(uint freq); * * Returns INVCHANSPEC in case of error. * - * Refer to IEEE802.11ac section 22.3.14 "Channelization". + * Refer to 802.11-2016 section 22.3.14 "Channelization". */ extern chanspec_t wf_chspec_get8080_chspec(uint8 primary_20mhz, uint8 chan0_80Mhz, uint8 chan1_80Mhz); -/* - * Returns the primary 80 Mhz channel for the provided chanspec +/** + * Returns the center channel of the primary 80 MHz sub-band of the provided chanspec * - * chanspec - Input chanspec for which the 80MHz primary channel has to be retrieved + * @param chspec input chanspec * - * returns -1 in case the provided channel is 20/40 Mhz chanspec + * @return center channel number of the primary 80MHz sub-band of the input. + * Will return the center channel of an input 80MHz chspec. + * Will return INVCHANNEL if the chspec is malformed or less than 80MHz bw. */ extern uint8 wf_chspec_primary80_channel(chanspec_t chanspec); -/* - * Returns the secondary 80 Mhz channel for the provided chanspec +/** + * Returns the center channel of the secondary 80 MHz sub-band of the provided chanspec * - * chanspec - Input chanspec for which the 80MHz secondary channel has to be retrieved + * @param chspec input chanspec * - * returns -1 in case the provided channel is 20/40 Mhz chanspec + * @return center channel number of the secondary 80MHz sub-band of the input. + * Will return INVCHANNEL if the chspec is malformed or bw is not greater than 80MHz. */ extern uint8 wf_chspec_secondary80_channel(chanspec_t chanspec); -/* - * This function returns the chanspec for the primary 80MHz of an 160MHz or 80+80 channel. +/** + * Returns the chanspec for the primary 80MHz sub-band of an 160MHz or 80+80 channel + * + * @param chspec input chanspec + * + * @return An 80MHz chanspec describing the primary 80MHz sub-band of the input. + * Will return an input 80MHz chspec as is. + * Will return INVCHANSPEC if the chspec is malformed or less than 80MHz bw. */ extern chanspec_t wf_chspec_primary80_chspec(chanspec_t chspec); +/** + * Returns the chanspec for the secondary 80MHz sub-band of an 160MHz or 80+80 channel + * The sideband in the chanspec is always set to WL_CHANSPEC_CTL_SB_LL since this sub-band + * does not contain the primary 20MHz channel. + * + * @param chspec input chanspec + * + * @return An 80MHz chanspec describing the secondary 80MHz sub-band of the input. + * Will return INVCHANSPEC if the chspec is malformed or bw is not greater than 80MHz. + */ +extern chanspec_t wf_chspec_secondary80_chspec(chanspec_t chspec); + +/* + * For 160MHz or 80P80 chanspec, set ch[0]/ch[1] to be the low/high 80 Mhz channels + * + * For 20/40/80MHz chanspec, set ch[0] to be the center freq, and chan[1]=-1 + */ +extern void wf_chspec_get_80p80_channels(chanspec_t chspec, uint8 *ch); + #ifdef WL11AC_80P80 /* * This function returns the centre chanel for the given chanspec. * In case of 80+80 chanspec it returns the primary 80 Mhz centre channel */ extern uint8 wf_chspec_channel(chanspec_t chspec); -#endif +#endif // endif extern chanspec_t wf_channel_create_chspec_frm_opclass(uint8 opclass, uint8 channel); extern int wf_channel_create_opclass_frm_chspec(chanspec_t chspec); + +/* Populates array with all 20MHz side bands of a given chanspec_t in the following order: + * primary20, ext20, two ext40s, four ext80s. + * 'chspec' is the chanspec of interest + * 'pext' must point to an uint8 array of long enough to hold all side bands of the given chspec + * + * Works with 20, 40, 80, 80p80 and 160MHz chspec + */ + +extern void wf_get_all_ext(chanspec_t chspec, uint8 *chan_ptr); + +/* + * Given two chanspecs, returns true if they overlap. + * (Overlap: At least one 20MHz subband is common between the two chanspecs provided) + */ +extern bool wf_chspec_overlap(chanspec_t chspec0, chanspec_t chspec1); + +extern uint8 channel_bw_to_width(chanspec_t chspec); #endif /* _bcmwifi_channels_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/bcmwifi_rates.h b/drivers/net/wireless/bcmdhd_oo/bcmwifi_rates.h index fef0cc413c12efe24b90bd00fd07e4c0255fd654..da2c15bed12324d216f550fa28ac70b207634f43 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmwifi_rates.h +++ b/drivers/net/wireless/bcmdhd_oo/bcmwifi_rates.h @@ -1,14 +1,14 @@ /* * Indices for 802.11 a/b/g/n/ac 1-3 chain symmetric transmit rates * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,21 +24,23 @@ * * <> * - * $Id: bcmwifi_rates.h 612483 2016-01-14 03:44:27Z $ + * $Id: bcmwifi_rates.h 697006 2017-05-01 19:13:40Z $ */ #ifndef _bcmwifi_rates_h_ #define _bcmwifi_rates_h_ +#include + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ - #define WL_RATESET_SZ_DSSS 4 #define WL_RATESET_SZ_OFDM 8 -#define WL_RATESET_SZ_VHT_MCS 10 -#define WL_RATESET_SZ_VHT_MCS_P 12 +#define WL_RATESET_SZ_VHT_MCS 10 +#define WL_RATESET_SZ_VHT_MCS_P 12 /* 10 VHT rates + 2 proprietary rates */ +#define WL_RATESET_SZ_HE_MCS 12 /* 12 HE rates (mcs 0-11) */ #define WL_RATESET_SZ_HT_MCS 8 @@ -71,7 +73,6 @@ typedef enum wl_tx_bw { WL_TX_BW_10 } wl_tx_bw_t; - /* * Transmit modes. * Not all modes are listed here, only those required for disambiguation. e.g. SPEXP is not listed @@ -84,7 +85,6 @@ typedef enum wl_tx_mode { WL_NUM_TX_MODES } wl_tx_mode_t; - /* Number of transmit chains */ typedef enum wl_tx_chains { WL_TX_CHAINS_1 = 1, @@ -93,7 +93,6 @@ typedef enum wl_tx_chains { WL_TX_CHAINS_4 } wl_tx_chains_t; - /* Number of transmit streams */ typedef enum wl_tx_nss { WL_TX_NSS_1 = 1, @@ -102,7 +101,6 @@ typedef enum wl_tx_nss { WL_TX_NSS_4 } wl_tx_nss_t; - /* This enum maps each rate to a CLM index */ typedef enum clm_rates { @@ -150,7 +148,6 @@ typedef enum clm_rates { WL_RATE_P_1X1_VHT10SS1 = 22, WL_RATE_P_1X1_VHT11SS1 = 23, - /************ * 2 chains * ************ @@ -308,7 +305,6 @@ typedef enum clm_rates { WL_RATE_P_2X2_TXBF_VHT10SS2 = 102, WL_RATE_P_2X2_TXBF_VHT11SS2 = 103, - /************ * 3 chains * ************ @@ -427,7 +423,6 @@ typedef enum clm_rates { WL_RATE_P_3X3_VHT10SS3 = 162, WL_RATE_P_3X3_VHT11SS3 = 163, - /**************************** * TX Beamforming, 3 chains * **************************** @@ -517,7 +512,6 @@ typedef enum clm_rates { WL_RATE_P_3X3_TXBF_VHT10SS3 = 206, WL_RATE_P_3X3_TXBF_VHT11SS3 = 207, - /************ * 4 chains * ************ @@ -636,7 +630,6 @@ typedef enum clm_rates { WL_RATE_P_3X4_VHT10SS3 = 266, WL_RATE_P_3X4_VHT11SS3 = 267, - /* 4 Streams */ WL_RATE_4X4_SDM_MCS24 = 268, WL_RATE_4X4_SDM_MCS25 = 269, @@ -662,7 +655,6 @@ typedef enum clm_rates { WL_RATE_P_4X4_VHT10SS4 = 278, WL_RATE_P_4X4_VHT11SS4 = 279, - /**************************** * TX Beamforming, 4 chains * **************************** @@ -782,6 +774,56 @@ typedef enum clm_rates { /* Number of rate codes */ #define WL_NUMRATES 336 +/* MCS rates */ +#define WLC_MAX_VHT_MCS 11 /**< Std VHT MCS 0-9 plus prop VHT MCS 10-11 */ +#define WLC_MAX_HE_MCS 11 /**< Std HE MCS 0-11 */ + +/* Convert encoded rate value in plcp header to numerical rates in 500 KHz increments */ +#define OFDM_PHY2MAC_RATE(rlpt) plcp_ofdm_rate_tbl[(rlpt) & 0x7] +#define CCK_PHY2MAC_RATE(signal) ((signal)/5) + +/* given a proprietary MCS, get number of spatial streams */ +#define GET_PROPRIETARY_11N_MCS_NSS(mcs) (1 + ((mcs) - 85) / 8) + +#define GET_11N_MCS_NSS(mcs) ((mcs) < 32 ? (1 + ((mcs) / 8)) : \ + ((mcs) == 32 ? 1 : GET_PROPRIETARY_11N_MCS_NSS(mcs))) + +#define IS_PROPRIETARY_11N_MCS(mcs) FALSE +#define IS_PROPRIETARY_11N_SS_MCS(mcs) FALSE /**< is proprietary HT single stream MCS */ + +/* Store HE mcs map for all NSS in a compact form: + * + * bit[0:2] mcs code for NSS 1 + * bit[3:5] mcs code for NSS 2 + * ... + * bit[21:23] mcs code for NSS 8 + */ + +/** + * 3 bits are used for encoding each NSS mcs map (HE MCS MAP is 24 bits) + */ +#define HE_CAP_MCS_CODE_NONE 7 + +/* macros to access above compact format */ +#define HE_CAP_MCS_NSS_SET_MASK 0x00ffffff /* Field is to be 24 bits long */ +#define HE_CAP_MCS_NSS_GET_SS_IDX(nss) (((nss)-1) * HE_CAP_MCS_CODE_SIZE) +#define HE_CAP_MCS_NSS_GET_MCS(nss, mcs_nss_map) \ + (((mcs_nss_map) >> HE_CAP_MCS_NSS_GET_SS_IDX(nss)) & HE_CAP_MCS_CODE_MASK) +#define HE_CAP_MCS_NSS_SET_MCS(nss, mcs_code, mcs_nss_map) \ + do { \ + (mcs_nss_map) &= (~(HE_CAP_MCS_CODE_MASK << HE_CAP_MCS_NSS_GET_SS_IDX(nss))); \ + (mcs_nss_map) |= (((mcs_code) & HE_CAP_MCS_CODE_MASK) << HE_CAP_MCS_NSS_GET_SS_IDX(nss)); \ + (mcs_nss_map) &= (HE_CAP_MCS_NSS_SET_MASK); \ + } while (0) + +extern const uint8 plcp_ofdm_rate_tbl[]; + +uint8 wf_get_single_stream_mcs(uint mcs); + +uint8 wf_vht_plcp_to_rate(uint8 *plcp); +uint wf_mcs_to_rate(uint mcs, uint nss, uint bw, int sgi); +uint wf_he_mcs_to_rate(uint mcs, uint nss, uint bw, uint gi, bool dcm); +uint wf_mcs_to_Ndbps(uint mcs, uint nss, uint bw); #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/drivers/net/wireless/bcmdhd_oo/bcmwifi_rspec.h b/drivers/net/wireless/bcmdhd_oo/bcmwifi_rspec.h new file mode 100644 index 0000000000000000000000000000000000000000..37494fd4224fa3c23c48c7a96665b1220308fcd6 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/bcmwifi_rspec.h @@ -0,0 +1,212 @@ +/* + * Common OS-independent driver header for rate management. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: bcmwifi_rspec.h 736703 2017-12-18 06:55:37Z $ + */ + +#ifndef _bcmwifi_rspec_h_ +#define _bcmwifi_rspec_h_ + +#include + +/** + * =================================================================================== + * rate spec : holds rate and mode specific information required to generate a tx frame. + * Legacy CCK and OFDM information is held in the same manner as was done in the past. + * (in the lower byte) the upper 3 bytes primarily hold MIMO specific information + * =================================================================================== + */ +typedef uint32 ratespec_t; + +/* Rate spec. definitions */ +#define WL_RSPEC_RATE_MASK 0x000000FF /**< Legacy rate or MCS or MCS + NSS */ +#define WL_RSPEC_TXEXP_MASK 0x00000300 /**< Tx chain expansion beyond Nsts */ +#define WL_RSPEC_TXEXP_SHIFT 8 +#define WL_RSPEC_HE_GI_MASK 0x00000C00 /* HE GI indices */ +#define WL_RSPEC_HE_GI_SHIFT 10 +#define WL_RSPEC_BW_MASK 0x00070000 /**< Band width */ +#define WL_RSPEC_BW_SHIFT 16 +#define WL_RSPEC_DCM 0x00080000 /**< Dual Carrier Modulation */ +#define WL_RSPEC_STBC 0x00100000 /**< STBC expansion, Nsts = 2 * Nss */ +#define WL_RSPEC_TXBF 0x00200000 +#define WL_RSPEC_LDPC 0x00400000 +#define WL_RSPEC_SGI 0x00800000 +#define WL_RSPEC_SHORT_PREAMBLE 0x00800000 /**< DSSS short preable - Encoding 0 */ +#define WL_RSPEC_ENCODING_MASK 0x03000000 /**< Encoding of RSPEC_RATE field */ +#define WL_RSPEC_ENCODING_SHIFT 24 + +#define WL_RSPEC_OVERRIDE_RATE 0x40000000 /**< override rate only */ +#define WL_RSPEC_OVERRIDE_MODE 0x80000000 /**< override both rate & mode */ + +/* ======== RSPEC_HE_GI|RSPEC_SGI fields for HE ======== */ + +/* GI for HE */ +#define RSPEC_HE_LTF_GI(rspec) (((rspec) & WL_RSPEC_HE_GI_MASK) >> WL_RSPEC_HE_GI_SHIFT) +#define WL_RSPEC_HE_1x_LTF_GI_0_8us (0x0) +#define WL_RSPEC_HE_2x_LTF_GI_0_8us (0x1) +#define WL_RSPEC_HE_2x_LTF_GI_1_6us (0x2) +#define WL_RSPEC_HE_4x_LTF_GI_3_2us (0x3) +#define RSPEC_ISHEGI(rspec) (RSPEC_HE_LTF_GI(rspec) > WL_RSPEC_HE_1x_LTF_GI_0_8us) +#define HE_GI_TO_RSPEC(gi) (((gi) << WL_RSPEC_HE_GI_SHIFT) & WL_RSPEC_HE_GI_MASK) +/* ======== RSPEC_RATE field ======== */ + +/* Encoding 0 - legacy rate */ +/* DSSS, CCK, and OFDM rates in [500kbps] units */ +#define WL_RSPEC_LEGACY_RATE_MASK 0x0000007F +#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 + +/* Encoding 1 - HT MCS */ +#define WL_RSPEC_HT_MCS_MASK 0x0000007F /**< HT MCS value mask in rspec */ + +/* Encoding 2 - VHT MCS + NSS */ +#define WL_RSPEC_VHT_MCS_MASK 0x0000000F /**< VHT MCS value mask in rspec */ +#define WL_RSPEC_VHT_NSS_MASK 0x000000F0 /**< VHT Nss value mask in rspec */ +#define WL_RSPEC_VHT_NSS_SHIFT 4 /**< VHT Nss value shift in rspec */ + +/* Encoding 3 - HE MCS + NSS */ +#define WL_RSPEC_HE_MCS_MASK 0x0000000F /**< HE MCS value mask in rspec */ +#define WL_RSPEC_HE_NSS_MASK 0x000000F0 /**< HE Nss value mask in rspec */ +#define WL_RSPEC_HE_NSS_SHIFT 4 /**< HE Nss value shift in rpsec */ + +/* ======== RSPEC_BW field ======== */ + +#define WL_RSPEC_BW_UNSPECIFIED 0 +#define WL_RSPEC_BW_20MHZ 0x00010000 +#define WL_RSPEC_BW_40MHZ 0x00020000 +#define WL_RSPEC_BW_80MHZ 0x00030000 +#define WL_RSPEC_BW_160MHZ 0x00040000 + +/* ======== RSPEC_ENCODING field ======== */ + +#define WL_RSPEC_ENCODE_RATE 0x00000000 /**< Legacy rate is stored in RSPEC_RATE */ +#define WL_RSPEC_ENCODE_HT 0x01000000 /**< HT MCS is stored in RSPEC_RATE */ +#define WL_RSPEC_ENCODE_VHT 0x02000000 /**< VHT MCS and NSS are stored in RSPEC_RATE */ +#define WL_RSPEC_ENCODE_HE 0x03000000 /**< HE MCS and NSS are stored in RSPEC_RATE */ + +/** + * =============================== + * Handy macros to parse rate spec + * =============================== + */ +#define RSPEC_BW(rspec) ((rspec) & WL_RSPEC_BW_MASK) +#define RSPEC_IS20MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_20MHZ) +#define RSPEC_IS40MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_40MHZ) +#define RSPEC_IS80MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_80MHZ) +#define RSPEC_IS160MHZ(rspec) (RSPEC_BW(rspec) == WL_RSPEC_BW_160MHZ) + +#define RSPEC_ISSGI(rspec) (((rspec) & WL_RSPEC_SGI) != 0) +#define RSPEC_ISLDPC(rspec) (((rspec) & WL_RSPEC_LDPC) != 0) +#define RSPEC_ISSTBC(rspec) (((rspec) & WL_RSPEC_STBC) != 0) +#define RSPEC_ISTXBF(rspec) (((rspec) & WL_RSPEC_TXBF) != 0) + +#define RSPEC_TXEXP(rspec) (((rspec) & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT) + +#define RSPEC_ENCODE(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) >> WL_RSPEC_ENCODING_SHIFT) +#define RSPEC_ISLEGACY(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE) + +#define RSPEC_ISCCK(rspec) (RSPEC_ISLEGACY(rspec) && \ + (int8)rate_info[(rspec) & WL_RSPEC_LEGACY_RATE_MASK] > 0) +#define RSPEC_ISOFDM(rspec) (RSPEC_ISLEGACY(rspec) && \ + (int8)rate_info[(rspec) & WL_RSPEC_LEGACY_RATE_MASK] < 0) + +#define RSPEC_ISHT(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) +#ifdef WL11AC +#define RSPEC_ISVHT(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT) +#else /* WL11AC */ +#define RSPEC_ISVHT(rspec) 0 +#endif /* WL11AC */ +#ifdef WL11AX +#define RSPEC_ISHE(rspec) (((rspec) & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HE) +#else /* WL11AX */ +#define RSPEC_ISHE(rspec) 0 +#endif /* WL11AX */ + +/** + * ================================ + * Handy macros to create rate spec + * ================================ + */ +/* create ratespecs */ +#define LEGACY_RSPEC(rate) (WL_RSPEC_ENCODE_RATE | WL_RSPEC_BW_20MHZ | \ + ((rate) & WL_RSPEC_LEGACY_RATE_MASK)) +#define CCK_RSPEC(cck) LEGACY_RSPEC(cck) +#define OFDM_RSPEC(ofdm) LEGACY_RSPEC(ofdm) +#define HT_RSPEC(mcs) (WL_RSPEC_ENCODE_HT | ((mcs) & WL_RSPEC_HT_MCS_MASK)) +#define VHT_RSPEC(mcs, nss) (WL_RSPEC_ENCODE_VHT | \ + (((nss) << WL_RSPEC_VHT_NSS_SHIFT) & WL_RSPEC_VHT_NSS_MASK) | \ + ((mcs) & WL_RSPEC_VHT_MCS_MASK)) +#define HE_RSPEC(mcs, nss) (WL_RSPEC_ENCODE_HE | \ + (((nss) << WL_RSPEC_HE_NSS_SHIFT) & WL_RSPEC_HE_NSS_MASK) | \ + ((mcs) & WL_RSPEC_HE_MCS_MASK)) + +/** + * ================== + * Other handy macros + * ================== + */ + +/* return rate in unit of Kbps */ +#define RSPEC2KBPS(rspec) wf_rspec_to_rate(rspec) + +/* return rate in unit of 500Kbps */ +#define RSPEC2RATE(rspec) ((rspec) & WL_RSPEC_LEGACY_RATE_MASK) + +/** + * ================================= + * Macros to use the rate_info table + * ================================= + */ +/* phy_rate table index is in [500kbps] units */ +#define WLC_MAXRATE 108 /**< in 500kbps units */ +extern const uint8 rate_info[]; +/* phy_rate table value is encoded */ +#define RATE_INFO_OFDM_MASK 0x80 /* ofdm mask */ +#define RATE_INFO_RATE_MASK 0x7f /* rate signal index mask */ +#define RATE_INFO_M_RATE_MASK 0x0f /* M_RATE_TABLE index mask */ +#define RATE_INFO_RATE_ISCCK(r) ((r) <= WLC_MAXRATE && (int8)rate_info[r] > 0) +#define RATE_INFO_RATE_ISOFDM(r) ((r) <= WLC_MAXRATE && (int8)rate_info[r] < 0) + +/** + * =================== + * function prototypes + * =================== + */ +ratespec_t wf_vht_plcp_to_rspec(uint8 *plcp); +ratespec_t wf_he_plcp_to_rspec(uint8 *plcp); +uint wf_rspec_to_rate(ratespec_t rspec); + +#endif /* _bcmwifi_rspec_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/bcmxtlv.c b/drivers/net/wireless/bcmdhd_oo/bcmxtlv.c index d6bef6fa2c37fe54503248e9684f9a2dad127a3e..d15a3d36eeca27f6541502611548159707112558 100644 --- a/drivers/net/wireless/bcmdhd_oo/bcmxtlv.c +++ b/drivers/net/wireless/bcmdhd_oo/bcmxtlv.c @@ -1,14 +1,14 @@ /* * Driver O/S-independent utility routines * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmxtlv.c 628611 2016-03-31 17:53:25Z $ + * $Id: bcmxtlv.c 700655 2017-05-20 06:09:06Z $ */ #include @@ -37,40 +37,102 @@ #ifdef BCMDRIVER #include #else /* !BCMDRIVER */ - #include /* AS!!! */ #include #include #include #ifndef ASSERT #define ASSERT(exp) -#endif -INLINE void* MALLOCZ(void *o, size_t s) { BCM_REFERENCE(o); return calloc(1, s); } -INLINE void MFREE(void *o, void *p, size_t s) { BCM_REFERENCE(o); BCM_REFERENCE(s); free(p); } +#endif // endif #endif /* !BCMDRIVER */ +#include #include #include -static INLINE int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts) +int +bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts) +{ + int len = (int)OFFSETOF(bcm_xtlv_t, data); /* nominal */ + if (opts & BCM_XTLV_OPTION_LENU8) --len; + if (opts & BCM_XTLV_OPTION_IDU8) --len; + + return len; +} + +bool +bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts) +{ + return elt != NULL && + buf_len >= bcm_xtlv_hdr_size(opts) && + buf_len >= bcm_xtlv_size(elt, opts); +} + +int +bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts) +{ + int hsz; + + hsz = bcm_xtlv_hdr_size(opts); + return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + hsz, 4) + : (dlen + hsz)); +} + +int +bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts) +{ + int size; /* size including header, data, and any pad */ + int len; /* length wthout padding */ + + len = BCM_XTLV_LEN_EX(elt, opts); + size = bcm_xtlv_size_for_data(len, opts); + return size; +} + +int +bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts) { - return ((opts & BCM_XTLV_OPTION_ALIGN32) ? ALIGN_SIZE(dlen + BCM_XTLV_HDR_SIZE, 4) - : (dlen + BCM_XTLV_HDR_SIZE)); + const uint8 *lenp; + int len; + + lenp = (const uint8 *)&elt->len; /* nominal */ + if (opts & BCM_XTLV_OPTION_IDU8) --lenp; + + if (opts & BCM_XTLV_OPTION_LENU8) + len = *lenp; + else + len = ltoh16_ua(lenp); + + return len; +} + +int +bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts) +{ + int id = 0; + if (opts & BCM_XTLV_OPTION_IDU8) + id = *(const uint8 *)elt; + else + id = ltoh16_ua((const uint8 *)elt); + + return id; } bcm_xtlv_t * -bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts) +bcm_next_xtlv(const bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts) { int sz; /* advance to next elt */ - sz = BCM_XTLV_SIZE(elt, opts); - elt = (bcm_xtlv_t*)((uint8 *)elt + sz); + sz = BCM_XTLV_SIZE_EX(elt, opts); + elt = (const bcm_xtlv_t*)((const uint8 *)elt + sz); *buflen -= sz; /* validate next elt */ if (!bcm_valid_xtlv(elt, *buflen, opts)) return NULL; - return elt; + GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); + return (bcm_xtlv_t *)(elt); + GCC_DIAGNOSTIC_POP(); } int @@ -89,99 +151,189 @@ bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, bcm_xtlv_opts_ uint16 bcm_xtlv_buf_len(bcm_xtlvbuf_t *tbuf) { - if (tbuf == NULL) return 0; - return (uint16)(tbuf->buf - tbuf->head); + uint16 len; + + if (tbuf) + len = (uint16)(tbuf->buf - tbuf->head); + else + len = 0; + + return len; } + uint16 bcm_xtlv_buf_rlen(bcm_xtlvbuf_t *tbuf) { - if (tbuf == NULL) return 0; - return tbuf->size - bcm_xtlv_buf_len(tbuf); + uint16 rlen; + if (tbuf) + rlen = tbuf->size - bcm_xtlv_buf_len(tbuf); + else + rlen = 0; + + return rlen; } + uint8 * bcm_xtlv_buf(bcm_xtlvbuf_t *tbuf) { - if (tbuf == NULL) return NULL; - return tbuf->buf; + return tbuf ? tbuf->buf : NULL; } + uint8 * bcm_xtlv_head(bcm_xtlvbuf_t *tbuf) { - if (tbuf == NULL) return NULL; - return tbuf->head; + return tbuf ? tbuf->head : NULL; } -int -bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen) + +void +bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, const uint8 *data, + bcm_xtlv_opts_t opts) { - bcm_xtlv_t *xtlv; - int size; + uint8 *data_buf; + bcm_xtlv_opts_t mask = BCM_XTLV_OPTION_IDU8 | BCM_XTLV_OPTION_LENU8; + + if (!(opts & mask)) { /* default */ + uint8 *idp = (uint8 *)xtlv; + uint8 *lenp = idp + sizeof(xtlv->id); + htol16_ua_store(type, idp); + htol16_ua_store(len, lenp); + data_buf = lenp + sizeof(uint16); + } else if ((opts & mask) == mask) { /* u8 id and u8 len */ + uint8 *idp = (uint8 *)xtlv; + uint8 *lenp = idp + 1; + *idp = (uint8)type; + *lenp = (uint8)len; + data_buf = lenp + sizeof(uint8); + } else if (opts & BCM_XTLV_OPTION_IDU8) { /* u8 id, u16 len */ + uint8 *idp = (uint8 *)xtlv; + uint8 *lenp = idp + 1; + *idp = (uint8)type; + htol16_ua_store(len, lenp); + data_buf = lenp + sizeof(uint16); + } else if (opts & BCM_XTLV_OPTION_LENU8) { /* u16 id, u8 len */ + uint8 *idp = (uint8 *)xtlv; + uint8 *lenp = idp + sizeof(uint16); + htol16_ua_store(type, idp); + *lenp = (uint8)len; + data_buf = lenp + sizeof(uint8); + } else { + ASSERT(!"Unexpected xtlv option"); + return; + } - if (tbuf == NULL) - return BCME_BADARG; - size = bcm_xtlv_size_for_data(dlen, tbuf->opts); - if (bcm_xtlv_buf_rlen(tbuf) < size) - return BCME_NOMEM; - xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf); - xtlv->id = htol16(type); - xtlv->len = htol16(dlen); - memcpy(xtlv->data, data, dlen); - tbuf->buf += size; - return BCME_OK; + if (opts & BCM_XTLV_OPTION_LENU8) { + ASSERT(len <= 0x00ff); + len &= 0xff; + } + + if (data != NULL) + memcpy(data_buf, data, len); +} + +/* xtlv header is always packed in LE order */ +void +bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len, + const uint8 **data, bcm_xtlv_opts_t opts) +{ + if (type) + *type = (uint16)bcm_xtlv_id(xtlv, opts); + if (len) + *len = (uint16)bcm_xtlv_len(xtlv, opts); + if (data) + *data = (const uint8 *)xtlv + BCM_XTLV_HDR_SIZE_EX(opts); } + int -bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data) +bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n) { bcm_xtlv_t *xtlv; int size; if (tbuf == NULL) return BCME_BADARG; - size = bcm_xtlv_size_for_data(1, tbuf->opts); + + size = bcm_xtlv_size_for_data(n, tbuf->opts); if (bcm_xtlv_buf_rlen(tbuf) < size) return BCME_NOMEM; + xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf); - xtlv->id = htol16(type); - xtlv->len = htol16(sizeof(data)); - xtlv->data[0] = data; - tbuf->buf += size; + bcm_xtlv_pack_xtlv(xtlv, type, (uint16)n, data, tbuf->opts); + tbuf->buf += size; /* note: data may be NULL, reserves space */ return BCME_OK; } -int -bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data) + +static int +bcm_xtlv_put_int(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n, int int_sz) { bcm_xtlv_t *xtlv; - int size; + int xtlv_len; + uint8 *xtlv_data; + int err = BCME_OK; - if (tbuf == NULL) - return BCME_BADARG; - size = bcm_xtlv_size_for_data(2, tbuf->opts); - if (bcm_xtlv_buf_rlen(tbuf) < size) - return BCME_NOMEM; + if (tbuf == NULL) { + err = BCME_BADARG; + goto done; + } xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf); - xtlv->id = htol16(type); - xtlv->len = htol16(sizeof(data)); - htol16_ua_store(data, xtlv->data); - tbuf->buf += size; - return BCME_OK; + + /* put type and length in xtlv and reserve data space */ + xtlv_len = n * int_sz; + err = bcm_xtlv_put_data(tbuf, type, NULL, xtlv_len); + if (err != BCME_OK) + goto done; + + xtlv_data = (uint8 *)xtlv + bcm_xtlv_hdr_size(tbuf->opts); + + /* write data w/ little-endianness into buffer - single loop, aligned access */ + for (; n != 0; --n, xtlv_data += int_sz, data += int_sz) { + switch (int_sz) { + case sizeof(uint8): + break; + case sizeof(uint16): + { + uint16 v = load16_ua(data); + htol16_ua_store(v, xtlv_data); + break; + } + case sizeof(uint32): + { + uint32 v = load32_ua(data); + htol32_ua_store(v, xtlv_data); + break; + } + case sizeof(uint64): + { + uint64 v = load64_ua(data); + htol64_ua_store(v, xtlv_data); + break; + } + default: + err = BCME_UNSUPPORTED; + goto done; + } + } + +done: + return err; } + int -bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data) +bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n) { - bcm_xtlv_t *xtlv; - int size; + return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint16)); +} - if (tbuf == NULL) - return BCME_BADARG; - size = bcm_xtlv_size_for_data(4, tbuf->opts); - if (bcm_xtlv_buf_rlen(tbuf) < size) - return BCME_NOMEM; - xtlv = (bcm_xtlv_t *)bcm_xtlv_buf(tbuf); - xtlv->id = htol16(type); - xtlv->len = htol16(sizeof(data)); - htol32_ua_store(data, xtlv->data); - tbuf->buf += size; - return BCME_OK; +int +bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n) +{ + return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint32)); +} + +int +bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n) +{ + return bcm_xtlv_put_int(tbuf, type, (const uint8 *)data, n, sizeof(uint64)); } /* @@ -191,62 +343,48 @@ bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data) * caller's resposible for dst space check */ int -bcm_unpack_xtlv_entry(uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len, void *dst, - bcm_xtlv_opts_t opts) +bcm_unpack_xtlv_entry(const uint8 **tlv_buf, uint16 xpct_type, uint16 xpct_len, + uint8 *dst_data, bcm_xtlv_opts_t opts) { - bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf; + const bcm_xtlv_t *ptlv = (const bcm_xtlv_t *)*tlv_buf; uint16 len; uint16 type; + const uint8 *data; ASSERT(ptlv); - /* tlv headr is always packed in LE order */ - len = ltoh16(ptlv->len); - type = ltoh16(ptlv->id); - if (len == 0) { - /* z-len tlv headers: allow, but don't process */ - printf("z-len, skip unpack\n"); - } else { - if ((type != xpct_type) || - (len > xpct_len)) { - printf("xtlv_unpack Error: found[type:%d,len:%d] != xpct[type:%d,len:%d]\n", - type, len, xpct_type, xpct_len); + + bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts); + if (len) { + if ((type != xpct_type) || (len > xpct_len)) return BCME_BADARG; - } - /* copy tlv record to caller's buffer */ - memcpy(dst, ptlv->data, ptlv->len); + if (dst_data && data) + memcpy(dst_data, data, len); /* copy data to dst */ } - *tlv_buf = (uint8*)(*tlv_buf) + BCM_XTLV_SIZE(ptlv, opts); + + *tlv_buf += BCM_XTLV_SIZE_EX(ptlv, opts); return BCME_OK; } /* - * packs user data into tlv record - * advances tlv pointer to next xtlv slot + * packs user data into tlv record and advances tlv pointer to next xtlv slot * buflen is used for tlv_buf space check */ int -bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, void *src, - bcm_xtlv_opts_t opts) +bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, + const uint8 *src_data, bcm_xtlv_opts_t opts) { bcm_xtlv_t *ptlv = (bcm_xtlv_t *)*tlv_buf; int size; ASSERT(ptlv); - ASSERT(src); size = bcm_xtlv_size_for_data(len, opts); /* copy data from tlv buffer to dst provided by user */ - if (size > *buflen) { - printf("bcm_pack_xtlv_entry: no space tlv_buf: requested:%d, available:%d\n", - size, *buflen); + if (size > *buflen) return BCME_BADLEN; - } - ptlv->id = htol16(type); - ptlv->len = htol16(len); - /* copy callers data */ - memcpy(ptlv->data, src, len); + bcm_xtlv_pack_xtlv(ptlv, type, len, src_data, opts); /* advance callers pointer to tlv buff */ *tlv_buf = (uint8*)(*tlv_buf) + size; @@ -260,42 +398,41 @@ bcm_pack_xtlv_entry(uint8 **tlv_buf, uint16 *buflen, uint16 type, uint16 len, vo * to set function one call per found tlv record */ int -bcm_unpack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, +bcm_unpack_xtlv_buf(void *ctx, const uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn) { uint16 len; uint16 type; int res = BCME_OK; int size; - bcm_xtlv_t *ptlv; + const bcm_xtlv_t *ptlv; int sbuflen = buflen; + const uint8 *data; + int hdr_size; ASSERT(!buflen || tlv_buf); ASSERT(!buflen || cbfn); - while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) { - ptlv = (bcm_xtlv_t *)tlv_buf; - - /* tlv header is always packed in LE order */ - len = ltoh16(ptlv->len); - type = ltoh16(ptlv->id); + hdr_size = BCM_XTLV_HDR_SIZE_EX(opts); + while (sbuflen >= hdr_size) { + ptlv = (const bcm_xtlv_t *)tlv_buf; + bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts); size = bcm_xtlv_size_for_data(len, opts); sbuflen -= size; - /* check for possible buffer overrun */ - if (sbuflen < 0) + if (sbuflen < 0) /* check for buffer overrun */ break; - if ((res = cbfn(ctx, ptlv->data, type, len)) != BCME_OK) + if ((res = cbfn(ctx, data, type, len)) != BCME_OK) break; - tlv_buf = (uint8*)tlv_buf + size; + tlv_buf += size; } return res; } int -bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, +bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next, bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen) { @@ -307,13 +444,16 @@ bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, uint8 *buf; bool more; int size; + int hdr_size; ASSERT(get_next && pack_next); - buf = (uint8 *)tlv_buf; + buf = tlv_buf; startp = buf; endp = (uint8 *)buf + buflen; more = TRUE; + hdr_size = BCM_XTLV_HDR_SIZE_EX(opts); + while (more && (buf < endp)) { more = get_next(ctx, &tlv_id, &tlv_len); size = bcm_xtlv_size_for_data(tlv_len, opts); @@ -322,9 +462,8 @@ bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, bcm_xtlv_opts_t opts, goto done; } - htol16_ua_store(tlv_id, buf); - htol16_ua_store(tlv_len, buf + sizeof(tlv_id)); - pack_next(ctx, tlv_id, tlv_len, buf + BCM_XTLV_HDR_SIZE); + bcm_xtlv_pack_xtlv((bcm_xtlv_t *)buf, tlv_id, tlv_len, NULL, opts); + pack_next(ctx, tlv_id, tlv_len, buf + hdr_size); buf += size; } @@ -342,20 +481,22 @@ done: * pack xtlv buffer from memory according to xtlv_desc_t */ int -bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items, +bcm_pack_xtlv_buf_from_mem(uint8 **tlv_buf, uint16 *buflen, const xtlv_desc_t *items, bcm_xtlv_opts_t opts) { int res = BCME_OK; - uint8 *ptlv = (uint8 *)*tlv_buf; + uint8 *ptlv = *tlv_buf; while (items->type != 0) { - if ((items->len > 0) && (res = bcm_pack_xtlv_entry(&ptlv, - buflen, items->type, - items->len, items->ptr, opts) != BCME_OK)) { - break; + if (items->len && items->ptr) { + res = bcm_pack_xtlv_entry(&ptlv, buflen, items->type, + items->len, items->ptr, opts); + if (res != BCME_OK) + break; } items++; } + *tlv_buf = ptlv; /* update the external pointer */ return res; } @@ -365,7 +506,8 @@ bcm_pack_xtlv_buf_from_mem(void **tlv_buf, uint16 *buflen, xtlv_desc_t *items, * */ int -bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_xtlv_opts_t opts) +bcm_unpack_xtlv_buf_to_mem(uint8 *tlv_buf, int *buflen, xtlv_desc_t *items, + bcm_xtlv_opts_t opts) { int res = BCME_OK; bcm_xtlv_t *elt; @@ -379,14 +521,16 @@ bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_x for (; elt != NULL && res == BCME_OK; elt = bcm_next_xtlv(elt, buflen, opts)) { /* find matches in desc_t items */ xtlv_desc_t *dst_desc = items; - uint16 len = ltoh16(elt->len); + uint16 len, type; + const uint8 *data; + bcm_xtlv_unpack_xtlv(elt, &type, &len, &data, opts); while (dst_desc->type != 0) { - if (ltoh16(elt->id) == dst_desc->type) { + if (type == dst_desc->type) { if (len != dst_desc->len) { res = BCME_BADLEN; } else { - memcpy(dst_desc->ptr, elt->data, len); + memcpy(dst_desc->ptr, data, len); } break; } @@ -402,56 +546,67 @@ bcm_unpack_xtlv_buf_to_mem(void *tlv_buf, int *buflen, xtlv_desc_t *items, bcm_x /* * return data pointer of a given ID from xtlv buffer. - * If the specified xTLV ID is found, on return *data_len_out will contain + * If the specified xTLV ID is found, on return *datalen will contain * the the data length of the xTLV ID. */ -void * -bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id, - uint16 *datalen_out, bcm_xtlv_opts_t opts) +const uint8* +bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, uint16 id, + uint16 *datalen, bcm_xtlv_opts_t opts) { - void *retptr = NULL; + const uint8 *retptr = NULL; uint16 type, len; int size; - bcm_xtlv_t *ptlv; + const bcm_xtlv_t *ptlv; int sbuflen = buflen; + const uint8 *data; + int hdr_size; - while (sbuflen >= (int)BCM_XTLV_HDR_SIZE) { - ptlv = (bcm_xtlv_t *)tlv_buf; + hdr_size = BCM_XTLV_HDR_SIZE_EX(opts); - /* tlv header is always packed in LE order */ - type = ltoh16(ptlv->id); - len = ltoh16(ptlv->len); - size = bcm_xtlv_size_for_data(len, opts); + /* Init the datalength */ + if (datalen) { + *datalen = 0; + } + while (sbuflen >= hdr_size) { + ptlv = (const bcm_xtlv_t *)tlv_buf; + bcm_xtlv_unpack_xtlv(ptlv, &type, &len, &data, opts); + size = bcm_xtlv_size_for_data(len, opts); sbuflen -= size; - /* check for possible buffer overrun */ - if (sbuflen < 0) { - printf("%s %d: Invalid sbuflen %d\n", - __FUNCTION__, __LINE__, sbuflen); + if (sbuflen < 0) /* buffer overrun? */ break; - } if (id == type) { - retptr = ptlv->data; - if (datalen_out) { - *datalen_out = len; - } + retptr = data; + if (datalen) + *datalen = len; break; } + tlv_buf += size; } return retptr; } -int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts) +bcm_xtlv_t* +bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst, + int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts) { - int size; /* entire size of the XTLV including header, data, and optional padding */ - int len; /* XTLV's value real length wthout padding */ - - len = BCM_XTLV_LEN(elt); - - size = bcm_xtlv_size_for_data(len, opts); + bcm_xtlv_t *dst_next = NULL; + src = (src && bcm_valid_xtlv(src, src_buf_len, opts)) ? src : NULL; + if (src && dst) { + uint16 type; + uint16 len; + const uint8 *data; + int size; + bcm_xtlv_unpack_xtlv(src, &type, &len, &data, opts); + size = bcm_xtlv_size_for_data(len, opts); + if (size <= dst_buf_len) { + bcm_xtlv_pack_xtlv(dst, type, len, data, opts); + dst_next = (bcm_xtlv_t *)((uint8 *)dst + size); + } + } - return size; + return dst_next; } diff --git a/drivers/net/wireless/bcmdhd_oo/dhd.h b/drivers/net/wireless/bcmdhd_oo/dhd.h index 8ad68da12de62cc1654fb271d120c863a3add8aa..0349d0335e457164a70cf46d59f804a6d48fed2f 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd.h @@ -4,14 +4,14 @@ * Provides type definitions and function prototypes used to link the * DHD OS, bus, and protocol modules. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: dhd.h 736671 2017-12-18 05:40:38Z $ + * $Id: dhd.h 739343 2018-01-08 06:31:00Z $ */ /**************** @@ -46,11 +46,16 @@ #include #include #include +#include +#include #include #include #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) #include #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) +#include +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */ /* The kernel threading is sdio-specific */ struct task_struct; struct sched_param; @@ -64,6 +69,7 @@ int get_scheduler_policy(struct task_struct *p); #define ALL_INTERFACES 0xff #include +#include #include #include #if defined(DUMP_IOCTL_IOV_LIST) || defined(DHD_DEBUG) @@ -75,6 +81,10 @@ int get_scheduler_policy(struct task_struct *p); #include #endif /* (BCMWDF) */ +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT +#include +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ + #ifdef DEBUG_DPC_THREAD_WATCHDOG #define MAX_RESCHED_CNT 600 #endif /* DEBUG_DPC_THREAD_WATCHDOG */ @@ -107,6 +117,15 @@ enum dhd_bus_state { DHD_BUS_DOWN_IN_PROGRESS, /* Bus going Down */ }; +/* The level of bus communication with the dongle */ +enum dhd_bus_devreset_type { + DHD_BUS_DEVRESET_ON = 0, /* ON */ + DHD_BUS_DEVRESET_OFF = 1, /* OFF */ + DHD_BUS_DEVRESET_FLR = 2, /* FLR */ + DHD_BUS_DEVRESET_FLR_FORCE_FAIL = 3, /* FLR FORCE FAIL */ + DHD_BUS_DEVRESET_QUIESCE = 4, /* FLR */ +}; + /* * Bit fields to Indicate clean up process that wait till they are finished. * Future synchronizable processes can add their bit filed below and update @@ -127,6 +146,9 @@ enum dhd_bus_state { DHD_BUS_BUSY_RPM_SUSPEND_IN_PROGRESS | \ DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS) #define DHD_BUS_BUSY_IN_CHECKDIED 0x800 +#define DHD_BUS_BUSY_IN_MEMDUMP 0x1000 +#define DHD_BUS_BUSY_IN_SSSRDUMP 0x2000 +#define DHD_BUS_BUSY_IN_LOGDUMP 0x4000 #define DHD_BUS_BUSY_SET_IN_TX(dhdp) \ (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_TX @@ -152,6 +174,12 @@ enum dhd_bus_state { (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS #define DHD_BUS_BUSY_SET_IN_CHECKDIED(dhdp) \ (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_CHECKDIED +#define DHD_BUS_BUSY_SET_IN_MEMDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_MEMDUMP +#define DHD_BUS_BUSY_SET_IN_SSSRDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_SSSRDUMP +#define DHD_BUS_BUSY_SET_IN_LOGDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state |= DHD_BUS_BUSY_IN_LOGDUMP #define DHD_BUS_BUSY_CLEAR_IN_TX(dhdp) \ (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_TX @@ -177,6 +205,12 @@ enum dhd_bus_state { (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_RPM_RESUME_IN_PROGRESS #define DHD_BUS_BUSY_CLEAR_IN_CHECKDIED(dhdp) \ (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_CHECKDIED +#define DHD_BUS_BUSY_CLEAR_IN_MEMDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_MEMDUMP +#define DHD_BUS_BUSY_CLEAR_IN_SSSRDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_SSSRDUMP +#define DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp) \ + (dhdp)->dhd_bus_busy_state &= ~DHD_BUS_BUSY_IN_LOGDUMP #define DHD_BUS_BUSY_CHECK_IN_TX(dhdp) \ ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_IN_TX) @@ -204,12 +238,17 @@ enum dhd_bus_state { ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_RPM_ALL) #define DHD_BUS_BUSY_CHECK_IN_CHECKDIED(dhdp) \ ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_IN_CHECKDIED) +#define DHD_BUS_BUSY_CHECK_IN_MEMDUMP(dhdp) \ + ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_IN_MEMDUMP) +#define DHD_BUS_BUSY_CHECK_IN_SSSRDUMP(dhdp) \ + ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_IN_SSSRDUMP) +#define DHD_BUS_BUSY_CHECK_IN_LOGDUMP(dhdp) \ + ((dhdp)->dhd_bus_busy_state & DHD_BUS_BUSY_IN_LOGDUMP) #define DHD_BUS_BUSY_CHECK_IDLE(dhdp) \ ((dhdp)->dhd_bus_busy_state == 0) #define DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp) \ - ((dhdp)->busstate == DHD_BUS_SUSPEND || DHD_BUS_BUSY_CHECK_SUSPEND_IN_PROGRESS(dhdp) || \ - DHD_BUS_BUSY_CHECK_RPM_SUSPEND_IN_PROGRESS(dhdp)) + ((dhdp)->busstate == DHD_BUS_SUSPEND || DHD_BUS_BUSY_CHECK_SUSPEND_IN_PROGRESS(dhdp)) #define DHD_BUS_CHECK_ANY_SUSPEND_IN_PROGRESS(dhdp) \ (DHD_BUS_BUSY_CHECK_SUSPEND_IN_PROGRESS(dhdp) || \ @@ -222,15 +261,16 @@ enum dhd_bus_state { typedef enum download_type { FW, NVRAM, - CLM_BLOB + CLM_BLOB, + TXCAP_BLOB } download_type_t; - /* For supporting multiple interfaces */ #define DHD_MAX_IFS 16 #define DHD_DEL_IF -0xE #define DHD_BAD_IF -0xF -#define DHD_EVENT_IF 0xFFFF /* Hack i/f to handle events from INFO Ring */ +#define DHD_DUMMY_INFO_IF 0xDEAF /* Hack i/f to handle events from INFO Ring */ +#define DHD_EVENT_IF DHD_DUMMY_INFO_IF enum dhd_op_flags { /* Firmware requested operation mode */ @@ -254,6 +294,9 @@ enum dhd_op_flags { #define DHD_OPMODE_SUPPORTED(dhd, opmode_flag) \ (dhd ? ((((dhd_pub_t *)dhd)->op_mode) & opmode_flag) : -1) +#define DHD_OPMODE_STA_SOFTAP_CONCURR(dhd) \ + (dhd ? (((dhd->op_mode) & DHD_FLAG_CONCURR_STA_HOSTAP_MODE) == \ + DHD_FLAG_CONCURR_STA_HOSTAP_MODE) : 0) /* Max sequential TX/RX Control timeouts to set HANG event */ #ifndef MAX_CNTL_TX_TIMEOUT @@ -271,10 +314,10 @@ enum dhd_op_flags { #ifndef POWERUP_MAX_RETRY #define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ -#endif +#endif // endif #ifndef POWERUP_WAIT_MS #define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ -#endif +#endif // endif /* * MAX_NVRAMBUF_SIZE determines the size of the Buffer in the DHD that holds * the NVRAM data. That is the size of the buffer pointed by bus->vars @@ -282,10 +325,11 @@ enum dhd_op_flags { */ #define MAX_NVRAMBUF_SIZE (16 * 1024) /* max nvram buf size */ #define MAX_CLM_BUF_SIZE (48 * 1024) /* max clm blob size */ +#define MAX_TXCAP_BUF_SIZE (16 * 1024) /* max txcap blob size */ #ifdef DHD_DEBUG #define DHD_JOIN_MAX_TIME_DEFAULT 10000 /* ms: Max time out for joining AP */ #define DHD_SCAN_DEF_TIMEOUT 10000 /* ms: Max time out for scan in progress */ -#endif +#endif // endif #ifndef CONFIG_BCMDHD_CLM_PATH #if defined(CUSTOMER_HW4) && defined(PLATFORM_SLP) @@ -317,21 +361,6 @@ enum dhd_bus_wake_state { WAKE_LOCK_SOFTAP_THREAD }; -#ifdef PCIE_INB_DW -enum dhd_bus_ds_state { - DW_DEVICE_DS_INVALID = -1, - DW_DEVICE_DS_DEV_SLEEP = 0, - DW_DEVICE_DS_DEV_SLEEP_PEND, - DW_DEVICE_DS_DISABLED_WAIT, - DW_DEVICE_DS_DEV_WAKE, - DW_DEVICE_DS_ACTIVE, - DW_DEVICE_HOST_SLEEP_WAIT, - DW_DEVICE_HOST_SLEEP, - DW_DEVICE_HOST_WAKE_WAIT, - DW_DEVICE_DS_D3_INFORM_WAIT -}; -#endif /* PCIE_INB_DW */ - enum dhd_prealloc_index { DHD_PREALLOC_PROT = 0, DHD_PREALLOC_RXBUF, @@ -353,8 +382,7 @@ enum dhd_prealloc_index { DHD_PREALLOC_PKTID_MAP_IOCTL = 14, DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16, - DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17, - DHD_PREALLOC_STAT_REPORT_BUF = 18 + DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17 }; enum dhd_dongledump_mode { @@ -373,7 +401,6 @@ enum dhd_dongledump_type { DUMP_TYPE_PKTID_AUDIT_FAILURE, DUMP_TYPE_PKTID_INVALID, DUMP_TYPE_SCAN_TIMEOUT, - DUMP_TYPE_JOIN_TIMEOUT, DUMP_TYPE_SCAN_BUSY, DUMP_TYPE_BY_SYSDUMP, DUMP_TYPE_BY_LIVELOCK, @@ -383,16 +410,17 @@ enum dhd_dongledump_type { DUMP_TYPE_RESUMED_ON_TIMEOUT_TX, DUMP_TYPE_RESUMED_ON_TIMEOUT_RX, DUMP_TYPE_RESUMED_ON_INVALID_RING_RDWR, - DUMP_TYPE_DONGLE_HOST_EVENT, - DUMP_TYPE_RESUMED_UNKNOWN, DUMP_TYPE_TRANS_ID_MISMATCH, - DUMP_TYPE_HANG_ON_IFACE_OP_FAIL, + DUMP_TYPE_IFACE_OP_FAILURE, #ifdef DEBUG_DNGL_INIT_FAIL DUMP_TYPE_DONGLE_INIT_FAILURE, #endif /* DEBUG_DNGL_INIT_FAIL */ #ifdef SUPPORT_LINKDOWN_RECOVERY - DUMP_TYPE_READ_SHM_FAIL + DUMP_TYPE_READ_SHM_FAIL, #endif /* SUPPORT_LINKDOWN_RECOVERY */ + DUMP_TYPE_DONGLE_HOST_EVENT, + DUMP_TYPE_SMMU_FAULT, + DUMP_TYPE_RESUMED_UNKNOWN }; enum dhd_hang_reason { @@ -402,10 +430,11 @@ enum dhd_hang_reason { HANG_REASON_D3_ACK_TIMEOUT = 0x8003, HANG_REASON_BUS_DOWN = 0x8004, HANG_REASON_MSGBUF_LIVELOCK = 0x8006, - HANG_REASON_IFACE_OP_FAILURE = 0x8007, + HANG_REASON_IFACE_DEL_FAILURE = 0x8007, HANG_REASON_HT_AVAIL_ERROR = 0x8008, HANG_REASON_PCIE_RC_LINK_UP_FAIL = 0x8009, HANG_REASON_PCIE_PKTID_ERROR = 0x800A, + HANG_REASON_IFACE_ADD_FAILURE = 0x800B, HANG_REASON_PCIE_LINK_DOWN = 0x8805, HANG_REASON_INVALID_EVENT_OR_DATA = 0x8806, HANG_REASON_UNKNOWN = 0x8807, @@ -425,10 +454,30 @@ enum dhd_rsdb_scan_features { RSDB_SCAN_DOWNGRADED_CH_PRUNE_ALL = 0x20 }; +#define VENDOR_SEND_HANG_EXT_INFO_LEN (800 + 1) +#define VENDOR_SEND_HANG_EXT_INFO_VER 20170905 +#define HANG_INFO_TRAP_T_NAME_MAX 6 +#define HANG_INFO_TRAP_T_REASON_IDX 0 +#define HANG_INFO_TRAP_T_SUBTYPE_IDX 2 +#define HANG_INFO_TRAP_T_OFFSET_IDX 3 +#define HANG_INFO_TRAP_T_EPC_IDX 4 +#define HANG_FIELD_STR_MAX_LEN 9 +#define HANG_FIELD_CNT_MAX 69 +#define HANG_FIELD_IF_FAILURE_CNT 10 +#define HANG_FIELD_IOCTL_RESP_TIMEOUT_CNT 8 +#define HANG_FIELD_TRAP_T_STACK_CNT_MAX 16 +#define HANG_FIELD_MISMATCH_CNT 10 +#define HANG_INFO_BIGDATA_KEY_STACK_CNT 4 + +#define DEBUG_DUMP_TIME_BUF_LEN (16 + 1) +/* delimiter between values */ +#define HANG_KEY_DEL ' ' +#define HANG_RAW_DEL '_' + /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN #define DHD_SDALIGN 32 -#endif +#endif // endif /** * DMA-able buffer parameters @@ -456,6 +505,26 @@ typedef struct reorder_info { uint8 pend_pkts; } reorder_info_t; +/* throughput test packet format */ +typedef struct tput_pkt { + /* header */ + uint8 mac_sta[ETHER_ADDR_LEN]; + uint8 mac_ap[ETHER_ADDR_LEN]; + uint16 pkt_type; + uint8 PAD[2]; + /* data */ + uint32 crc32; + uint32 pkt_id; + uint32 num_pkts; +} tput_pkt_t; + +typedef enum { + TPUT_PKT_TYPE_NORMAL, + TPUT_PKT_TYPE_STOP +} tput_pkt_type_t; + +#define TPUT_TEST_WAIT_TIMEOUT_DEFAULT 5000 + #ifdef DHDTCPACK_SUPPRESS enum { @@ -472,47 +541,8 @@ enum { TCPACK_SUP_HOLD, TCPACK_SUP_LAST_MODE }; - -#ifdef ARGOS_CPU_SCHEDULER -#define TCPACK_SUP_DEFAULT TCPACK_SUP_OFF -#ifdef BCMSDIO -#define TCPACK_SUP_ON TCPACK_SUP_DELAYTX -#elif defined(BCMPCIE) -#define TCPACK_SUP_ON TCPACK_SUP_HOLD -#else -#define TCPACK_SUP_ON TCPACK_SUP_OFF -#endif /* BCMSDIO */ -#else -#ifdef BCMSDIO -#define TCPACK_SUP_DEFAULT TCPACK_SUP_DELAYTX -#elif defined(BCMPCIE) -#define TCPACK_SUP_DEFAULT TCPACK_SUP_OFF -#endif /* BCMSDIO */ -#endif /* ARGOS_CPU_SCHEDULER */ #endif /* DHDTCPACK_SUPPRESS */ -#if defined(TRAFFIC_MGMT_DWM) -#define DHD_DWM_TBL_SIZE 57 -/* DSCP WMM AC Mapping macros and structures */ -#define DHD_TRF_MGMT_DWM_FILTER_BIT 0x8 -#define DHD_TRF_MGMT_DWM_PRIO_BITS 0x7 -#define DHD_TRF_MGMT_DWM_FAVORED_BIT 0x10 -#define DHD_TRF_MGMT_DWM_PRIO(dwm_tbl_entry) ((dwm_tbl_entry) & DHD_TRF_MGMT_DWM_PRIO_BITS) -#define DHD_TRF_MGMT_DWM_IS_FAVORED_SET(dwm_tbl_entry) \ - ((dwm_tbl_entry) & DHD_TRF_MGMT_DWM_FAVORED_BIT) -#define DHD_TRF_MGMT_DWM_SET_FAVORED(dwm_tbl_entry) \ - ((dwm_tbl_entry) |= DHD_TRF_MGMT_DWM_FAVORED_BIT) -#define DHD_TRF_MGMT_DWM_IS_FILTER_SET(dwm_tbl_entry) \ - ((dwm_tbl_entry) & DHD_TRF_MGMT_DWM_FILTER_BIT) -#define DHD_TRF_MGMT_DWM_SET_FILTER(dwm_tbl_entry) \ - ((dwm_tbl_entry) |= DHD_TRF_MGMT_DWM_FILTER_BIT) - -typedef struct { - uint8 dhd_dwm_enabled; - uint8 dhd_dwm_tbl[DHD_DWM_TBL_SIZE]; -} dhd_trf_mgmt_dwm_tbl_t; -#endif - #define DHD_NULL_CHK_AND_RET(cond) \ if (!cond) { \ DHD_ERROR(("%s " #cond " is NULL\n", __FUNCTION__)); \ @@ -576,10 +606,39 @@ typedef struct { #endif /* defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ #ifdef DHD_LOG_DUMP +#define LOG_DUMP_MAGIC 0xDEB3DEB3 +#define HEALTH_CHK_BUF_SIZE 256 + +#ifdef DEBUGABILITY_ECNTRS_LOGGING +#define ECNTR_RING_ID 0xECDB +#define ECNTR_RING_NAME "ewp_ecntr_ring" +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + +typedef enum { + LOG_DUMP_SECTION_GENERAL = 0, + LOG_DUMP_SECTION_ECNTRS, + LOG_DUMP_SECTION_SPECIAL, + LOG_DUMP_SECTION_DHD_DUMP, + LOG_DUMP_SECTION_EXT_TRAP, + LOG_DUMP_SECTION_HEALTH_CHK, + LOG_DUMP_SECTION_PRESERVE, + LOG_DUMP_SECTION_COOKIE +} log_dump_section_type_t; + +/* Each section in the debug_dump log file shall begin with a header */ +typedef struct { + uint32 magic; /* 0xDEB3DEB3 */ + uint32 type; /* of type log_dump_section_type_t */ + uint64 timestamp; + uint32 length; /* length of the section that follows */ + uint32 pad; +} log_dump_section_hdr_t; + /* below structure describe ring buffer. */ struct dhd_log_dump_buf { spinlock_t lock; + void *dhd_pub; unsigned int enable; unsigned int wraparound; unsigned long max; @@ -590,13 +649,40 @@ struct dhd_log_dump_buf }; #define DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE 256 -extern void dhd_log_dump_write(int type, const char *fmt, ...); +#define DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE (80 * 1024) + +extern void dhd_log_dump_write(int type, char *binary_data, + int binary_len, const char *fmt, ...); extern char *dhd_log_dump_get_timestamp(void); +bool dhd_log_dump_ecntr_enabled(void); #endif /* DHD_LOG_DUMP */ +/* DEBUG_DUMP SUB COMMAND */ +enum { + CMD_DEFAULT, + CMD_UNWANTED, + CMD_DISCONNECTED, + CMD_MAX +}; + +#define DHD_LOG_DUMP_TS_MULTIPLIER_VALUE 60 +#define DHD_LOG_DUMP_TS_FMT_YYMMDDHHMMSSMSMS "%02d%02d%02d%02d%02d%02d%04d" +#define DHD_DEBUG_DUMP_TYPE "debug_dump_FORUSER" +#define DHD_DUMP_SUBSTR_UNWANTED "_unwanted" +#define DHD_DUMP_SUBSTR_DISCONNECTED "_disconnected" + +extern void get_debug_dump_time(char *str); +extern void clear_debug_dump_time(char *str); +#if defined(WL_CFGVENDOR_SEND_HANG_EVENT) || defined(DHD_PKT_LOGGING) +extern void copy_debug_dump_time(char *dest, char *src); +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT || DHD_PKT_LOGGING */ + +#define WL_MAX_PRESERVE_BUFFER 8 +#define FW_LOGSET_MASK_ALL 0xFF + #if defined(CUSTOMER_HW4) #ifndef DHD_COMMON_DUMP_PATH -#define DHD_COMMON_DUMP_PATH "/data/log/wifi/" +#define DHD_COMMON_DUMP_PATH "/data/media/wifi/log/" #endif /* !DHD_COMMON_DUMP_PATH */ #else #define DHD_COMMON_DUMP_PATH "/installmedia/" @@ -608,38 +694,7 @@ struct cntry_locales_custom { int32 custom_locale_rev; /* Custom local revisin default -1 */ }; -#ifdef REPORT_FATAL_TIMEOUTS -typedef struct timeout_info { - void *scan_timer_lock; - void *join_timer_lock; - void *cmd_timer_lock; - void *bus_timer_lock; - uint32 scan_timeout_val; - uint32 join_timeout_val; - uint32 cmd_timeout_val; - uint32 bus_timeout_val; - bool scan_timer_active; - bool join_timer_active; - bool cmd_timer_active; - bool bus_timer_active; - osl_timer_t *scan_timer; - osl_timer_t *join_timer; - osl_timer_t *cmd_timer; - osl_timer_t *bus_timer; - uint16 cmd_request_id; - uint32 cmd; - uint32 cmd_join_error; -} timeout_info_t; -#endif /* REPORT_FATAL_TIMEOUTS */ - -#ifdef HOFFLOAD_MODULES -/* Metadata structure containing module information */ -struct module_metadata { - void *data; /* module data */ - uint32_t size; /* module size */ - u64 data_addr; /* address of module data in host */ -}; -#endif +int dhd_send_msg_to_daemon(struct sk_buff *skb, void *data, int size); #ifdef DMAMAP_STATS typedef struct dmamap_stats { @@ -658,7 +713,10 @@ typedef struct dmamap_stats { } dma_stats_t; #endif /* DMAMAP_STATS */ -/* Common structure for module and instance linkage */ +/** + * Common structure for module and instance linkage. + * Instantiated once per hardware (dongle) instance that this DHD manages. + */ typedef struct dhd_pub { /* Linkage ponters */ osl_t *osh; /* OSL handle */ @@ -671,7 +729,6 @@ typedef struct dhd_pub { * please do NOT merge it back from other branches !!! */ - /* Internal dhd items */ bool up; /* Driver up/down (to OS) */ #ifdef WL_CFG80211 @@ -741,7 +798,7 @@ typedef struct dhd_pub { #ifdef PKT_FILTER_SUPPORT int early_suspended; /* Early suspend status */ int dhcp_in_progress; /* DHCP period */ -#endif +#endif // endif /* Pkt filter defination */ char * pktfilter[100]; @@ -767,7 +824,7 @@ typedef struct dhd_pub { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ -#endif +#endif // endif #ifdef PROP_TXSTATUS bool wlfc_enabled; @@ -807,13 +864,13 @@ typedef struct dhd_pub { #endif /* PROP_TXSTATUS */ #ifdef PNO_SUPPORT void *pno_state; -#endif +#endif // endif #ifdef RTT_SUPPORT void *rtt_state; -#endif +#endif // endif #ifdef ROAM_AP_ENV_DETECTION bool roam_env_detection; -#endif +#endif // endif bool dongle_isolation; bool is_pcie_watchdog_reset; bool dongle_trap_occured; /* flag for sending HANG event to upper layer */ @@ -823,7 +880,7 @@ typedef struct dhd_pub { #endif /* PCIE_FULL_DONGLE */ #ifdef BT_OVER_SDIO bool is_bt_recovery_required; -#endif +#endif // endif int hang_was_sent; int rxcnt_timeout; /* counter rxcnt timeout to send HANG */ int txcnt_timeout; /* counter txcnt timeout to send HANG */ @@ -840,9 +897,9 @@ typedef struct dhd_pub { #endif /* CONFIG_BCM_DETECT_CONSECUTIVE_HANG */ #ifdef WLTDLS bool tdls_enable; -#endif +#endif // endif struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; - #define WLC_IOCTL_MAXBUF_FWCAP 512 + #define WLC_IOCTL_MAXBUF_FWCAP 1024 char fw_capabilities[WLC_IOCTL_MAXBUF_FWCAP]; #define MAXSKBPEND 1024 void *skbbuf[MAXSKBPEND]; @@ -856,10 +913,10 @@ typedef struct dhd_pub { #endif /* DHDTCPACK_SUPPRESS */ #if defined(ARP_OFFLOAD_SUPPORT) uint32 arp_version; -#endif +#endif // endif #if defined(BCMSUP_4WAY_HANDSHAKE) bool fw_4way_handshake; /* Whether firmware will to do the 4way handshake. */ -#endif +#endif // endif #ifdef DEBUG_DPC_THREAD_WATCHDOG bool dhd_bug_on; #endif /* DEBUG_DPC_THREAD_WATCHDOG */ @@ -876,7 +933,6 @@ typedef struct dhd_pub { bool affinity_isrxf; #endif /* ARGOS_CPU_SCHEDULER */ - void *sta_pool; /* pre-allocated pool of sta objects */ void *staid_allocator; /* allocator of sta indexes */ #ifdef PCIE_FULL_DONGLE @@ -900,14 +956,15 @@ typedef struct dhd_pub { bool idma_enable; uint idma_inited; - bool idma_retention_ds; /* Implicit DMA memory retention */ bool ifrm_enable; /* implicit frm enable */ uint ifrm_inited; /* implicit frm init */ -#if defined(TRAFFIC_MGMT_DWM) - dhd_trf_mgmt_dwm_tbl_t dhd_tm_dwm_tbl; -#endif + bool dar_enable; /* use DAR registers */ + uint dar_inited; + + bool fast_delete_ring_support; /* fast delete ring supported */ + #ifdef DHD_L2_FILTER unsigned long l2_filter_cnt; /* for L2_FILTER ARP table timeout */ #endif /* DHD_L2_FILTER */ @@ -918,15 +975,17 @@ typedef struct dhd_pub { uint *sssr_d11_before[MAX_NUM_D11CORES]; uint *sssr_d11_after[MAX_NUM_D11CORES]; bool sssr_d11_outofreset[MAX_NUM_D11CORES]; - uint *sssr_vasip_buf_before; - uint *sssr_vasip_buf_after; + uint *sssr_dig_buf_before; + uint *sssr_dig_buf_after; #endif /* DHD_SSSR_DUMP */ uint8 *soc_ram; uint32 soc_ram_length; uint32 memdump_type; #ifdef DHD_FW_COREDUMP uint32 memdump_enabled; +#ifdef DHD_DEBUG_UART bool memdump_success; +#endif /* DHD_DEBUG_UART */ #endif /* DHD_FW_COREDUMP */ #ifdef PCIE_FULL_DONGLE #ifdef WLTDLS @@ -936,31 +995,24 @@ typedef struct dhd_pub { #endif /* PCIE_FULL_DONGLE */ #ifdef DHD_ULP void *dhd_ulp; -#endif -#ifdef CACHE_FW_IMAGES - char *cached_fw; - int cached_fw_length; - char *cached_nvram; - int cached_nvram_length; - char *cached_clm; - int cached_clm_length; -#endif +#endif // endif #ifdef KEEP_JP_REGREV char vars_ccode[WLC_CNTRY_BUF_SZ]; uint vars_regrev; #endif /* KEEP_JP_REGREV */ #ifdef WLTDLS uint32 tdls_mode; -#endif +#endif // endif #ifdef GSCAN_SUPPORT bool lazy_roam_enable; -#endif +#endif // endif #if defined(PKT_FILTER_SUPPORT) && defined(APF) bool apf_set; #endif /* PKT_FILTER_SUPPORT && APF */ + void *macdbg_info; #ifdef DHD_WET void *wet_info; -#endif +#endif // endif bool h2d_phase_supported; bool force_dongletrap_on_bad_h2d_phase; uint32 dongle_trap_data; @@ -972,67 +1024,96 @@ typedef struct dhd_pub { #ifdef DHD_LOSSLESS_ROAMING uint8 dequeue_prec_map; uint8 prio_8021x; -#endif -#ifdef REPORT_FATAL_TIMEOUTS - timeout_info_t *timeout_info; -#endif /* REPORT_FATAL_TIMEOUTS */ +#endif // endif +#ifdef WL_NATOE + struct dhd_nfct_info *nfct; + spinlock_t nfct_lock; +#endif /* WL_NATOE */ /* timesync link */ struct dhd_ts *ts; bool d2h_hostrdy_supported; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_t block_bus; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING) bool d11_tx_status; #endif /* DBG_PKT_MON || DHD_PKT_LOGGING */ - uint16 ndo_version; /* ND offload version supported */ + uint16 ndo_version; /* ND offload version supported */ #ifdef NDO_CONFIG_SUPPORT bool ndo_enable; /* ND offload feature enable */ bool ndo_host_ip_overflow; /* # of host ip addr exceed FW capacity */ uint32 ndo_max_host_ip; /* # of host ip addr supported by FW */ #endif /* NDO_CONFIG_SUPPORT */ -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) - uint8 log_capture_enable; -#endif /* DHD_EFI && DHD_LOG_DUMP */ - bool max_dtim_enable; /* use MAX bcn_li_dtim value in suspend mode */ -#ifdef PCIE_OOB - bool d2h_no_oob_dw; -#endif /* PCIE_OOB */ -#ifdef PCIE_INB_DW - bool d2h_inband_dw; - enum dhd_bus_ds_state ds_state; -#endif /* PCIE_INB_DW */ +#if defined(DHD_LOG_DUMP) + /* buffer to hold 'dhd dump' data before dumping to file */ + uint8 *concise_dbg_buf; + uint64 last_file_posn; + int logdump_periodic_flush; + /* ecounter debug ring */ +#ifdef DEBUGABILITY_ECNTRS_LOGGING + void *ecntr_dbg_ring; +#endif // endif +#ifdef DNGL_EVENT_SUPPORT + uint8 health_chk_event_data[HEALTH_CHK_BUF_SIZE]; +#endif // endif + void *logdump_cookie; +#endif /* DHD_LOG_DUMP */ + uint32 dhd_console_ms; /** interval for polling the dongle for console (log) messages */ + bool ext_trap_data_supported; + uint32 *extended_trap_data; +#ifdef DUMP_IOCTL_IOV_LIST + /* dump iovar list */ + dll_t dump_iovlist_head; + uint8 dump_iovlist_len; +#endif /* DUMP_IOCTL_IOV_LIST */ #ifdef CUSTOM_SET_ANTNPM uint32 mimo_ant_set; #endif /* CUSTOM_SET_ANTNPM */ #ifdef CUSTOM_SET_OCLOFF bool ocl_off; #endif /* CUSTOM_SET_OCLOFF */ -#ifdef HOFFLOAD_MODULES - struct module_metadata hmem; -#endif - bool wbtext_support; -#ifdef DUMP_IOCTL_IOV_LIST - /* dump iovar list */ - dll_t dump_iovlist_head; - uint8 dump_iovlist_len; -#endif /* DUMP_IOCTL_IOV_LIST */ #ifdef DHD_DEBUG -/* memwaste feature */ + /* memwaste feature */ dll_t mw_list_head; /* memwaste list head */ uint32 mw_id; /* memwaste list unique id */ #endif /* DHD_DEBUG */ #ifdef WLTDLS spinlock_t tdls_lock; #endif /* WLTDLS */ -#ifdef WLADPS_SEAK_AP_WAR - uint32 disabled_adps; -#endif /* WLADPS_SEAK_AP_WAR */ - bool ext_trap_data_supported; - uint32 *extended_trap_data; + uint pcie_txs_metadata_enable; + bool wbtext_support; +#ifdef SHOW_LOGTRACE +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + struct mutex dhd_trace_lock; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ +#endif /* SHOW_LOGTRACE */ + + bool max_dtim_enable; /* use MAX bcn_li_dtim value in suspend mode */ + tput_test_t tput_data; + uint64 tput_start_ts; + uint64 tput_stop_ts; +#ifdef WL_MONITOR + bool monitor_enable; +#endif // endif #ifdef DHD_PKT_LOGGING struct dhd_pktlog *pktlog; + char debug_dump_time_pktlog_str[DEBUG_DUMP_TIME_BUF_LEN]; #endif /* DHD_PKT_LOGGING */ -#if defined(STAT_REPORT) - void *stat_report_info; -#endif + uint dhd_watchdog_ms_backup; + void *event_log_filter; +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT + char *hang_info; + int hang_info_cnt; + char debug_dump_time_hang_str[DEBUG_DUMP_TIME_BUF_LEN]; +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ + char debug_dump_time_str[DEBUG_DUMP_TIME_BUF_LEN]; + uint32 logset_prsrv_mask; + bool wl_event_enabled; + bool logtrace_pkt_sendup; +#ifdef DHD_DUMP_MNGR + struct _dhd_dump_file_manage *dump_file_manage; +#endif /* DHD_DUMP_MNGR */ + int debug_dump_subcmd; } dhd_pub_t; typedef struct { @@ -1164,10 +1245,6 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(dhd_workitem_context_t, dhd_get_dhd_workitem_ int dhd_pno_clean(dhd_pub_t *dhd); #endif /* PNO_SUPPORT */ -#ifdef HOFFLOAD_MODULES -void dhd_linux_get_modfw_address(dhd_pub_t *dhd); -#endif - /* * Wake locks are an Android power management concept. They are used by applications and services * to request CPU resources. @@ -1217,118 +1294,142 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) } #ifdef DHD_DEBUG_WAKE_LOCK -#define PRINT_CALL_INFO(str) printf("%s: %s %d\n", \ - str, __FUNCTION__, __LINE__) - -#define PRINT_CALL_INFO_TIMEOUT(str, val) \ - printf("%s[%d]: %s %d\n", str, val, __FUNCTION__, __LINE__) - -#else -#define PRINT_CALL_INFO(str) -#define PRINT_CALL_INFO_TIMEOUT(str, val) -#endif /* DHD_DEBUG_WAKE_LOCK */ #define DHD_OS_WAKE_LOCK(pub) \ do { \ - PRINT_CALL_INFO("call wakelock"); \ + printf("call wake_lock: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock(pub); \ } while (0) #define DHD_OS_WAKE_UNLOCK(pub) \ do { \ - PRINT_CALL_INFO("call wake_unlock"); \ + printf("call wake_unlock: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_unlock(pub); \ } while (0) #define DHD_EVENT_WAKE_LOCK(pub) \ do { \ - PRINT_CALL_INFO("call event_wake lock"); \ - dhd_event_wake_lock(pub); \ + printf("call event wake_lock: %s %d\n", \ + __FUNCTION__, __LINE__); \ + dhd_event_wake_lock(pub); \ } while (0) #define DHD_EVENT_WAKE_UNLOCK(pub) \ do { \ - PRINT_CALL_INFO("call event_wake unlock"); \ - dhd_event_wake_unlock(pub); \ + printf("call event wake_unlock: %s %d\n", \ + __FUNCTION__, __LINE__); \ + dhd_event_wake_unlock(pub); \ } while (0) #define DHD_PM_WAKE_LOCK_TIMEOUT(pub, val) \ do { \ - PRINT_CALL_INFO("call pm_wake_timeout enable"); \ + printf("call pm_wake_timeout enable\n"); \ dhd_pm_wake_lock_timeout(pub, val); \ } while (0) #define DHD_PM_WAKE_UNLOCK(pub) \ do { \ - PRINT_CALL_INFO("call pm_wake unlock"); \ + printf("call pm_wake unlock\n"); \ dhd_pm_wake_unlock(pub); \ } while (0) #define DHD_TXFL_WAKE_LOCK_TIMEOUT(pub, val) \ do { \ - PRINT_CALL_INFO("call pm_wake_timeout enable"); \ + printf("call pm_wake_timeout enable\n"); \ dhd_txfl_wake_lock_timeout(pub, val); \ } while (0) #define DHD_TXFL_WAKE_UNLOCK(pub) \ do { \ - PRINT_CALL_INFO("call pm_wake unlock"); \ + printf("call pm_wake unlock\n"); \ dhd_txfl_wake_unlock(pub); \ } while (0) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) \ do { \ - PRINT_CALL_INFO("call wake_lock_timeout"); \ + printf("call wake_lock_timeout: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_timeout(pub); \ } while (0) #define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ do { \ - PRINT_CALL_INFO_TIMEOUT("call wake_lock_rx_timeout_enable", val); \ + 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 { \ - PRINT_CALL_INFO_TIMEOUT("call wake_lock_ctrl_timeout_enable", val); \ + 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) #define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \ do { \ - PRINT_CALL_INFO("call wake_lock_ctrl_timeout_cancel"); \ + printf("call wake_lock_ctrl_timeout_cancel: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_ctrl_timeout_cancel(pub); \ } while (0) #define DHD_OS_WAKE_LOCK_WAIVE(pub) \ do { \ - PRINT_CALL_INFO("call wake_lock_waive"); \ + printf("call wake_lock_waive: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_waive(pub); \ } while (0) #define DHD_OS_WAKE_LOCK_RESTORE(pub) \ do { \ - PRINT_CALL_INFO("call wake_lock_restore"); \ + printf("call wake_lock_restore: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_restore(pub); \ } while (0) #define DHD_OS_WAKE_LOCK_INIT(dhd) \ do { \ - PRINT_CALL_INFO("call wake_lock_init"); \ + printf("call wake_lock_init: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_init(dhd); \ } while (0) #define DHD_OS_WAKE_LOCK_DESTROY(dhd) \ do { \ - PRINT_CALL_INFO("call wake_lock_destroy"); \ + printf("call wake_lock_destroy: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_wake_lock_destroy(dhd); \ } 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_EVENT_WAKE_LOCK(pub) dhd_event_wake_lock(pub) +#define DHD_EVENT_WAKE_UNLOCK(pub) dhd_event_wake_unlock(pub) +#define DHD_PM_WAKE_LOCK_TIMEOUT(pub, val) dhd_pm_wake_lock_timeout(pub, val) +#define DHD_PM_WAKE_UNLOCK(pub) dhd_pm_wake_unlock(pub) +#define DHD_TXFL_WAKE_LOCK_TIMEOUT(pub, val) dhd_txfl_wake_lock_timeout(pub, val) +#define DHD_TXFL_WAKE_UNLOCK(pub) dhd_txfl_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) +#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ + dhd_os_wake_lock_ctrl_timeout_enable(pub, val) +#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL(pub) \ + dhd_os_wake_lock_ctrl_timeout_cancel(pub) +#define DHD_OS_WAKE_LOCK_WAIVE(pub) dhd_os_wake_lock_waive(pub) +#define DHD_OS_WAKE_LOCK_RESTORE(pub) dhd_os_wake_lock_restore(pub) +#define DHD_OS_WAKE_LOCK_INIT(dhd) dhd_os_wake_lock_init(dhd); +#define DHD_OS_WAKE_LOCK_DESTROY(dhd) dhd_os_wake_lock_destroy(dhd); +#endif /* DHD_DEBUG_WAKE_LOCK */ #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) #ifdef DHD_USE_SCAN_WAKELOCK #ifdef DHD_DEBUG_SCAN_WAKELOCK -#define PRINT_SCAN_CALL(str) printf("%s: %s %d\n", \ - str, __FUNCTION__, __LINE__) -#else -#define PRINT_SCAN_CALL(str) -#endif /* DHD_DEBUG_SCAN_WAKELOCK */ #define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val) \ do { \ - PRINT_SCAN_CALL("call wake_lock_scan"); \ + printf("call wake_lock_scan: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_scan_wake_lock_timeout(pub, val); \ } while (0) #define DHD_OS_SCAN_WAKE_UNLOCK(pub) \ do { \ - PRINT_SCAN_CALL("call wake_unlock_scan"); \ + printf("call wake_unlock_scan: %s %d\n", \ + __FUNCTION__, __LINE__); \ dhd_os_scan_wake_unlock(pub); \ } while (0) #else +#define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val) dhd_os_scan_wake_lock_timeout(pub, val) +#define DHD_OS_SCAN_WAKE_UNLOCK(pub) dhd_os_scan_wake_unlock(pub) +#endif /* DHD_DEBUG_SCAN_WAKELOCK */ +#else #define DHD_OS_SCAN_WAKE_LOCK_TIMEOUT(pub, val) #define DHD_OS_SCAN_WAKE_UNLOCK(pub) #endif /* DHD_USE_SCAN_WAKELOCK */ @@ -1337,6 +1438,7 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define OOB_WAKE_LOCK_TIMEOUT 500 extern void dhd_os_oob_irq_wake_lock_timeout(dhd_pub_t *pub, int val); extern void dhd_os_oob_irq_wake_unlock(dhd_pub_t *pub); +extern int dhdpcie_get_oob_irq_num(struct dhd_bus *bus); #define DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(pub, val) dhd_os_oob_irq_wake_lock_timeout(pub, val) #define DHD_OS_OOB_IRQ_WAKE_UNLOCK(pub) dhd_os_oob_irq_wake_unlock(pub) #endif /* BCMPCIE_OOB_HOST_WAKE */ @@ -1365,7 +1467,7 @@ void dhd_net_if_unlock(struct net_device *dev); #if defined(MULTIPLE_SUPPLICANT) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && defined(BCMSDIO) extern struct mutex _dhd_sdio_mutex_lock_; -#endif +#endif // endif #endif /* MULTIPLE_SUPPLICANT */ typedef enum dhd_attach_states @@ -1391,6 +1493,40 @@ typedef enum dhd_attach_states /* Value -2 means we are unsuccessful in both creating the kthread and tasklet */ #define DHD_PID_KT_TL_INVALID -2 +/* default reporting period */ +#define ECOUNTERS_DEFAULT_PERIOD 0 + +/* default number of reports. '0' indicates forever */ +#define ECOUNTERS_NUM_REPORTS 0 + +typedef struct ecounters_cfg { + uint16 type; + uint16 if_slice_idx; + uint16 stats_rep; +} ecounters_cfg_t; + +typedef struct event_ecounters_cfg { + uint16 event_id; + uint16 type; + uint16 if_slice_idx; + uint16 stats_rep; +} event_ecounters_cfg_t; + +typedef struct ecountersv2_xtlv_list_elt { + /* Not quite the exact bcm_xtlv_t type as data could be pointing to other pieces in + * memory at the time of parsing arguments. + */ + uint16 id; + uint16 len; + uint8 *data; + struct ecountersv2_xtlv_list_elt *next; +} ecountersv2_xtlv_list_elt_t; + +typedef struct ecountersv2_processed_xtlv_list_elt { + uint8 *data; + struct ecountersv2_processed_xtlv_list_elt *next; +} ecountersv2_processed_xtlv_list_elt; + /* * Exported from dhd OS modules (dhd_linux/dhd_ndis) */ @@ -1437,6 +1573,10 @@ extern void dhd_sched_dpc(dhd_pub_t *dhdp); /* Notify tx completion */ extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +extern void dhd_bus_wakeup_work(dhd_pub_t *dhdp); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #define WIFI_FEATURE_INFRA 0x0001 /* Basic infrastructure mode */ #define WIFI_FEATURE_INFRA_5G 0x0002 /* Support for 5 GHz Band */ #define WIFI_FEATURE_HOTSPOT 0x0004 /* Support for GAS/ANQP */ @@ -1455,12 +1595,15 @@ extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); #define WIFI_FEATURE_AP_STA 0x8000 /* Support for AP STA Concurrency */ #define WIFI_FEATURE_LINKSTAT 0x10000 /* Support for Linkstats */ #define WIFI_FEATURE_LOGGER 0x20000 /* WiFi Logger */ -#define WIFI_FEATURE_HAL_EPNO 0x40000 /* WiFi PNO enhanced */ -#define WIFI_FEATURE_RSSI_MONITOR 0x80000 /* RSSI Monitor */ +#define WIFI_FEATURE_HAL_EPNO 0x40000 /* WiFi PNO enhanced */ +#define WIFI_FEATURE_RSSI_MONITOR 0x80000 /* RSSI Monitor */ #define WIFI_FEATURE_MKEEP_ALIVE 0x100000 /* WiFi mkeep_alive */ -#define WIFI_FEATURE_CONFIG_NDO 0x200000 /* ND offload configure */ -#define WIFI_FEATURE_TX_TRANSMIT_POWER 0x400000 /* Capture Tx transmit power levels */ -#define WIFI_FEATURE_INVALID 0xFFFFFFFF /* Invalid Feature */ +#define WIFI_FEATURE_CONFIG_NDO 0x200000 /* ND offload configure */ +#define WIFI_FEATURE_TX_TRANSMIT_POWER 0x400000 /* Capture Tx transmit power levels */ +#define WIFI_FEATURE_CONTROL_ROAMING 0x800000 /* Enable/Disable firmware roaming */ +#define WIFI_FEATURE_FILTER_IE 0x1000000 /* Probe req ie filter */ +#define WIFI_FEATURE_SCAN_RAND 0x2000000 /* Support MAC & Prb SN randomization */ +#define WIFI_FEATURE_INVALID 0xFFFFFFFF /* Invalid Feature */ #define MAX_FEATURE_SET_CONCURRRENT_GROUPS 3 @@ -1470,11 +1613,11 @@ extern int dhd_dev_cfg_rand_mac_oui(struct net_device *dev, uint8 *oui); #ifdef CUSTOM_FORCE_NODFS_FLAG extern int dhd_dev_set_nodfs(struct net_device *dev, uint nodfs); #endif /* CUSTOM_FORCE_NODFS_FLAG */ - #ifdef NDO_CONFIG_SUPPORT #ifndef NDO_MAX_HOST_IP_ENTRIES #define NDO_MAX_HOST_IP_ENTRIES 10 #endif /* NDO_MAX_HOST_IP_ENTRIES */ + extern int dhd_dev_ndo_cfg(struct net_device *dev, u8 enable); extern int dhd_dev_ndo_update_inet6addr(struct net_device * dev); #endif /* NDO_CONFIG_SUPPORT */ @@ -1485,15 +1628,19 @@ extern int dhd_dev_set_lazy_roam_cfg(struct net_device *dev, extern int dhd_dev_lazy_roam_enable(struct net_device *dev, uint32 enable); extern int dhd_dev_set_lazy_roam_bssid_pref(struct net_device *dev, wl_bssid_pref_cfg_t *bssid_pref, uint32 flush); +#endif /* GSCAN_SUPPORT */ +#if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT) extern int dhd_dev_set_blacklist_bssid(struct net_device *dev, maclist_t *blacklist, uint32 len, uint32 flush); extern int dhd_dev_set_whitelist_ssid(struct net_device *dev, wl_ssid_whitelist_t *whitelist, uint32 len, uint32 flush); -#endif /* GSCAN_SUPPORT */ +#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */ /* OS independent layer functions */ extern void dhd_os_dhdiovar_lock(dhd_pub_t *pub); extern void dhd_os_dhdiovar_unlock(dhd_pub_t *pub); +void dhd_os_logdump_lock(dhd_pub_t *pub); +void dhd_os_logdump_unlock(dhd_pub_t *pub); extern int dhd_os_proto_block(dhd_pub_t * pub); extern int dhd_os_proto_unblock(dhd_pub_t * pub); extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition); @@ -1507,20 +1654,18 @@ extern void dhd_wakeup_ioctl_event(dhd_pub_t *pub, dhd_ioctl_recieved_status_t r #else static INLINE void dhd_wakeup_ioctl_event(dhd_pub_t *pub, dhd_ioctl_recieved_status_t reason) { printf("%s is NOT implemented for SDIO", __FUNCTION__); return; } -#endif +#endif // endif #ifdef SHOW_LOGTRACE extern int dhd_os_read_file(void *file, char *buf, uint32 size); extern int dhd_os_seek_file(void *file, int64 offset); #endif /* SHOW_LOGTRACE */ +int dhd_os_write_file_posn(void *fp, unsigned long *posn, + void *buf, unsigned long buflen); extern void dhd_pcie_dump_core_regs(dhd_pub_t * pub, uint32 index, uint32 first_addr, uint32 last_addr); extern void wl_dhdpcie_dump_regs(void * context); -#define DHD_OS_IOCTL_RESP_LOCK(x) -#define DHD_OS_IOCTL_RESP_UNLOCK(x) - - extern int dhd_os_get_image_block(char * buf, int len, void * image); extern int dhd_os_get_image_size(void * image); #if defined(BT_OVER_SDIO) @@ -1528,8 +1673,8 @@ extern int dhd_os_gets_image(dhd_pub_t *pub, char *str, int len, void *image); extern void dhdsdio_bus_usr_cnt_inc(dhd_pub_t *pub); extern void dhdsdio_bus_usr_cnt_dec(dhd_pub_t *pub); #endif /* (BT_OVER_SDIO) */ -extern void * dhd_os_open_image(char * filename); -extern void dhd_os_close_image(void * image); +extern void *dhd_os_open_image1(dhd_pub_t *pub, char *filename); /* rev1 function signature */ +extern void dhd_os_close_image1(dhd_pub_t *pub, void *image); extern void dhd_os_wd_timer(void *bus, uint wdtick); #ifdef DHD_PCIE_RUNTIMEPM extern void dhd_os_runtimepm_timer(void *bus, uint tick); @@ -1580,7 +1725,6 @@ void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size); void dhd_schedule_sssr_dump(dhd_pub_t *dhdp); - #ifdef PKT_FILTER_SUPPORT #define DHD_UNICAST_FILTER_NUM 0 #define DHD_BROADCAST_FILTER_NUM 1 @@ -1590,18 +1734,24 @@ void dhd_schedule_sssr_dump(dhd_pub_t *dhdp); #define DHD_ARP_FILTER_NUM 5 #define DHD_BROADCAST_ARP_FILTER_NUM 6 #define DHD_IP4BCAST_DROP_FILTER_NUM 7 -#define DHD_CISCO_STP_DROP_FILTER_NUM 8 -#define DHD_CISCO_XID_DROP_FILTER_NUM 9 +#define DHD_LLC_STP_DROP_FILTER_NUM 8 +#define DHD_LLC_XID_DROP_FILTER_NUM 9 #define DISCARD_IPV4_MCAST "102 1 6 IP4_H:16 0xf0 0xe0" #define DISCARD_IPV6_MCAST "103 1 6 IP6_H:24 0xff 0xff" #define DISCARD_IPV4_BCAST "107 1 6 IP4_H:16 0xffffffff 0xffffffff" +#define DISCARD_LLC_STP "108 1 6 ETH_H:14 0xFFFFFFFFFFFF 0xAAAA0300000C" +#define DISCARD_LLC_XID "109 1 6 ETH_H:14 0xFFFFFF 0x0001AF" 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 dhd_packet_filter_add_remove(dhd_pub_t *dhdp, int add_remove, int num); 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 */ +#define MAX_PKTFLT_BUF_SIZE 2048 +#define MAX_PKTFLT_FIXED_PATTERN_SIZE 32 +#define MAX_PKTFLT_FIXED_BUF_SIZE \ + (WL_PKT_FILTER_FIXED_LEN + MAX_PKTFLT_FIXED_PATTERN_SIZE * 2) +#endif /* PKT_FILTER_SUPPORT */ #if defined(BCMPCIE) extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd, int *dtim_period, int *bcn_interval); @@ -1618,7 +1768,7 @@ extern int dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, #endif /* RSSI_MONITOR_SUPPORT */ #ifdef DHDTCPACK_SUPPRESS -extern int dhd_dev_set_tcpack_sup_mode_cfg(struct net_device *dev, uint8 enable); +int dhd_dev_set_tcpack_sup_mode_cfg(struct net_device *dev, uint8 enable); #endif /* DHDTCPACK_SUPPRESS */ #define DHD_RSSI_MONITOR_EVT_VERSION 1 @@ -1693,7 +1843,7 @@ extern int dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id); */ #define PKT_FILTER_APF_ID 200 #define DHD_APF_LOCK(ndev) dhd_apf_lock(ndev) -#define DHD_APF_UNLOCK(ndev) dhd_apf_unlock(ndev) +#define DHD_APF_UNLOCK(ndev) dhd_apf_unlock(ndev) extern void dhd_apf_lock(struct net_device *dev); extern void dhd_apf_unlock(struct net_device *dev); @@ -1745,6 +1895,10 @@ extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); +#ifdef WL_NATOE +extern int dhd_natoe_ct_event(dhd_pub_t *dhd, char *data); +#endif /* WL_NATOE */ + /* Send packet to dongle via data channel */ extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); @@ -1780,23 +1934,28 @@ extern void dhd_os_spin_lock_deinit(osl_t *osh, void *lock); extern unsigned long dhd_os_spin_lock(void *lock); void dhd_os_spin_unlock(void *lock, unsigned long flags); -#ifdef DHD_EFI -extern int dhd_os_ds_enter_wait(dhd_pub_t * pub, uint * condition); -extern int dhd_os_ds_enter_wake(dhd_pub_t * pub); -#else -static INLINE int dhd_os_ds_enter_wait(dhd_pub_t * pub, uint * condition) -{ printf("%s is Not supported for this platform", __FUNCTION__); return 0; } -static INLINE int dhd_os_ds_enter_wake(dhd_pub_t * pub) +/* linux is defined for DHD EFI builds also, +* since its cross-compiled for EFI from linux. +* dbgring_lock apis are meant only for linux +* to use mutexes, other OSes will continue to +* use dhd_os_spin_lock +*/ +void *dhd_os_dbgring_lock_init(osl_t *osh); +void dhd_os_dbgring_lock_deinit(osl_t *osh, void *mtx); +unsigned long dhd_os_dbgring_lock(void *lock); +void dhd_os_dbgring_unlock(void *lock, unsigned long flags); + +static INLINE int dhd_os_tput_test_wait(dhd_pub_t *pub, uint *condition, + uint timeout_ms) +{ return 0; } +static INLINE int dhd_os_tput_test_wake(dhd_pub_t * pub) { return 0; } -#endif /* DHD_EFI */ -#ifdef PCIE_INB_DW -extern int dhd_os_ds_exit_wait(dhd_pub_t * pub, uint * condition); -extern int dhd_os_ds_exit_wake(dhd_pub_t * pub); -#endif /* PCIE_INB_DW */ +extern int dhd_os_busbusy_wait_negation(dhd_pub_t * pub, uint * condition); extern int dhd_os_busbusy_wake(dhd_pub_t * pub); extern int dhd_os_busbusy_wait_condition(dhd_pub_t *pub, uint *var, uint condition); -extern int dhd_os_busbusy_wait_negation(dhd_pub_t * pub, uint * condition); +int dhd_os_busbusy_wait_bitmask(dhd_pub_t *pub, uint *var, + uint bitmask, uint condition); extern int dhd_os_d3ack_wait(dhd_pub_t * pub, uint * condition); extern int dhd_os_d3ack_wake(dhd_pub_t * pub); extern int dhd_os_dmaxfer_wait(dhd_pub_t *pub, uint *condition); @@ -1826,7 +1985,7 @@ extern int dhd_getiovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, #ifdef DHD_MCAST_REGEN extern int dhd_get_mcast_regen_bss_enable(dhd_pub_t *dhdp, uint32 idx); extern int dhd_set_mcast_regen_bss_enable(dhd_pub_t *dhdp, uint32 idx, int val); -#endif +#endif // endif typedef enum cust_gpio_modes { WLAN_RESET_ON, WLAN_RESET_OFF, @@ -1841,6 +2000,11 @@ typedef struct dmaxref_mem_map { extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +extern void dhd_flush_rx_tx_wq(dhd_pub_t *dhdp); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + /* * Insmod parameters for debug/test */ @@ -1851,8 +2015,9 @@ extern uint dhd_watchdog_ms; extern uint dhd_runtimepm_ms; #endif /* DHD_PCIE_RUNTIMEPM */ -/* Console output poll interval */ +/** Default console output poll interval */ extern uint dhd_console_ms; + #if defined(DHD_DEBUG) extern uint wl_msg_level; #endif /* defined(DHD_DEBUG) */ @@ -1907,7 +2072,7 @@ extern uint dhd_force_tx_queueing; #define DEFAULT_BCN_TIMEOUT_VALUE 4 #ifndef CUSTOM_BCN_TIMEOUT_SETTING #define CUSTOM_BCN_TIMEOUT_SETTING DEFAULT_BCN_TIMEOUT_VALUE -#endif +#endif // endif /* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ #define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */ @@ -1921,21 +2086,21 @@ extern uint dhd_force_tx_queueing; #define DEFAULT_GLOM_VALUE -1 #ifndef CUSTOM_GLOM_SETTING #define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE -#endif +#endif // 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 #ifndef CUSTOM_ROAM_TRIGGER_SETTING #define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE -#endif +#endif // endif /* hooks for custom Roaming Romaing setting via Makefile */ #define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ #define DEFAULT_ROAM_DELTA_SETTING -1 #ifndef CUSTOM_ROAM_DELTA_SETTING #define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE -#endif +#endif // endif /* hooks for custom PNO Event wake lock to guarantee enough time for the Platform to detect Event before system suspended @@ -1943,12 +2108,12 @@ extern uint dhd_force_tx_queueing; #define DEFAULT_PNO_EVENT_LOCK_xTIME 2 /* multiplay of DHD_PACKET_TIMEOUT_MS */ #ifndef CUSTOM_PNO_EVENT_LOCK_xTIME #define CUSTOM_PNO_EVENT_LOCK_xTIME DEFAULT_PNO_EVENT_LOCK_xTIME -#endif +#endif // 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 -#endif +#endif // endif #ifndef CUSTOM_LISTEN_INTERVAL #define CUSTOM_LISTEN_INTERVAL LISTEN_INTERVAL @@ -1957,15 +2122,15 @@ extern uint dhd_force_tx_queueing; #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 +#endif // endif #ifndef BCN_TIMEOUT_IN_SUSPEND #define BCN_TIMEOUT_IN_SUSPEND 6 /* bcn timeout value in suspend mode */ -#endif +#endif // endif #ifndef CUSTOM_RXF_PRIO_SETTING #define CUSTOM_RXF_PRIO_SETTING MAX((CUSTOM_DPC_PRIO_SETTING - 1), 1) -#endif +#endif // endif #define DEFAULT_WIFI_TURNOFF_DELAY 0 #ifndef WIFI_TURNOFF_DELAY @@ -2000,13 +2165,19 @@ extern uint dhd_force_tx_queueing; #ifdef WLTDLS #ifndef CUSTOM_TDLS_IDLE_MODE_SETTING #define CUSTOM_TDLS_IDLE_MODE_SETTING 60000 /* 60sec to tear down TDLS of not active */ -#endif +#endif // endif #ifndef CUSTOM_TDLS_RSSI_THRESHOLD_HIGH #define CUSTOM_TDLS_RSSI_THRESHOLD_HIGH -70 /* rssi threshold for establishing TDLS link */ -#endif +#endif // endif #ifndef CUSTOM_TDLS_RSSI_THRESHOLD_LOW #define CUSTOM_TDLS_RSSI_THRESHOLD_LOW -80 /* rssi threshold for tearing down TDLS link */ -#endif +#endif // endif +#ifndef CUSTOM_TDLS_PCKTCNT_THRESHOLD_HIGH +#define CUSTOM_TDLS_PCKTCNT_THRESHOLD_HIGH 100 /* pkt/sec threshold for establishing TDLS link */ +#endif // endif +#ifndef CUSTOM_TDLS_PCKTCNT_THRESHOLD_LOW +#define CUSTOM_TDLS_PCKTCNT_THRESHOLD_LOW 10 /* pkt/sec threshold for tearing down TDLS link */ +#endif // endif #endif /* WLTDLS */ #if defined(VSDB) || defined(ROAM_ENABLE) @@ -2017,16 +2188,16 @@ extern uint dhd_force_tx_queueing; #ifndef CUSTOM_BCN_TIMEOUT #define CUSTOM_BCN_TIMEOUT DEFAULT_BCN_TIMEOUT -#endif +#endif // endif #define MAX_DTIM_SKIP_BEACON_INTERVAL 100 /* max allowed associated AP beacon for DTIM skip */ #ifndef MAX_DTIM_ALLOWED_INTERVAL #define MAX_DTIM_ALLOWED_INTERVAL 600 /* max allowed total beacon interval for DTIM skip */ -#endif +#endif // endif #ifndef MIN_DTIM_FOR_ROAM_THRES_EXTEND #define MIN_DTIM_FOR_ROAM_THRES_EXTEND 600 /* minimum dtim interval to extend roam threshold */ -#endif +#endif // endif #define NO_DTIM_SKIP 1 #ifdef SDTEST @@ -2036,17 +2207,16 @@ extern uint dhd_pktgen; /* Echo packet len (0 => sawtooth, max 1800) */ extern uint dhd_pktgen_len; #define MAX_PKTGEN_LEN 1800 -#endif - +#endif // endif /* optionally set by a module_param_string() */ #define MOD_PARAM_PATHLEN 2048 #define MOD_PARAM_INFOLEN 512 -#define MOD_PARAM_SRLEN 64 +#define MOD_PARAM_SRLEN 64 #ifdef SOFTAP extern char fw_path2[MOD_PARAM_PATHLEN]; -#endif +#endif // endif #if defined(ANDROID_PLATFORM_VERSION) #if (ANDROID_PLATFORM_VERSION < 7) @@ -2122,14 +2292,6 @@ static INLINE int dhd_read_cis(dhd_pub_t *dhdp) { return 0; } static INLINE void dhd_clear_cis(dhd_pub_t *dhdp) { } #endif /* DHD_USE_CISINFO */ -#ifdef WLAIBSS -#define IBSS_COALESCE_DEFAULT 0 -#define IBSS_INITIAL_SCAN_ALLOWED_DEFAULT 0 -#else /* WLAIBSS */ -#define IBSS_COALESCE_DEFAULT 1 -#define IBSS_INITIAL_SCAN_ALLOWED_DEFAULT 1 -#endif /* WLAIBSS */ - #if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) /* Flags to indicate if we distingish power off policy when * user set the memu "Keep Wi-Fi on during sleep" to "Never" @@ -2204,6 +2366,8 @@ int dhd_os_socram_dump(struct net_device *dev, uint32 *dump_size); int dhd_os_get_socram_dump(struct net_device *dev, char **buf, uint32 *size); int dhd_common_socram_dump(dhd_pub_t *dhdp); +int dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen); + int dhd_os_get_version(struct net_device *dev, bool dhd_ver, char **buf, uint32 size); uint8* dhd_os_prealloc(dhd_pub_t *dhdpub, int section, uint size, bool kmalloc_if_fail); @@ -2276,6 +2440,12 @@ extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags); #define DHD_SPIN_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) #define DHD_SPIN_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) +#define DHD_RING_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) +#define DHD_RING_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) + +#define DHD_BUS_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) +#define DHD_BUS_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) + #define DHD_BUS_INB_DW_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) #define DHD_BUS_INB_DW_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) @@ -2285,6 +2455,9 @@ extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags); #define DHD_TDLS_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) #endif /* WLTDLS */ +#define DHD_BUS_INB_DW_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) +#define DHD_BUS_INB_DW_UNLOCK(lock, flags) dhd_os_spin_unlock((lock), (flags)) + #ifdef DBG_PKT_MON /* Enable DHD PKT MON spin lock/unlock */ #define DHD_PKT_MON_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) @@ -2294,8 +2467,17 @@ extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags); #define DHD_LINUX_GENERAL_LOCK(dhdp, flags) DHD_GENERAL_LOCK(dhdp, flags) #define DHD_LINUX_GENERAL_UNLOCK(dhdp, flags) DHD_GENERAL_UNLOCK(dhdp, flags) +/* linux is defined for DHD EFI builds also, +* since its cross-compiled for EFI from linux +*/ +#define DHD_DBG_RING_LOCK_INIT(osh) dhd_os_dbgring_lock_init(osh) +#define DHD_DBG_RING_LOCK_DEINIT(osh, lock) dhd_os_dbgring_lock_deinit(osh, (lock)) +#define DHD_DBG_RING_LOCK(lock, flags) (flags) = dhd_os_dbgring_lock(lock) +#define DHD_DBG_RING_UNLOCK(lock, flags) dhd_os_dbgring_unlock((lock), flags) + extern void dhd_dump_to_kernelog(dhd_pub_t *dhdp); +extern void dhd_print_tasklet_status(dhd_pub_t *dhd); #ifdef DHD_L2_FILTER extern int dhd_get_parp_status(dhd_pub_t *dhdp, uint32 idx); @@ -2306,9 +2488,10 @@ extern int dhd_get_block_ping_status(dhd_pub_t *dhdp, uint32 idx); extern int dhd_set_block_ping_status(dhd_pub_t *dhdp, uint32 idx, int val); extern int dhd_get_grat_arp_status(dhd_pub_t *dhdp, uint32 idx); extern int dhd_set_grat_arp_status(dhd_pub_t *dhdp, uint32 idx, int val); +extern int dhd_get_block_tdls_status(dhd_pub_t *dhdp, uint32 idx); +extern int dhd_set_block_tdls_status(dhd_pub_t *dhdp, uint32 idx, int val); #endif /* DHD_L2_FILTER */ - typedef struct wl_io_pport { dhd_pub_t *dhd_pub; uint ifidx; @@ -2352,9 +2535,13 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length); -int dhd_download_blob(dhd_pub_t *dhd, unsigned char *image, +int dhd_download_blob(dhd_pub_t *dhd, unsigned char *buf, uint32 len, char *iovar); +int dhd_download_blob_cached(dhd_pub_t *dhd, char *file_path, + uint32 len, char *iovar); + +int dhd_apply_default_txcap(dhd_pub_t *dhd, char *txcap_path); int dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path); #ifdef SHOW_LOGTRACE @@ -2455,13 +2642,15 @@ void dhd_get_read_buf_ptr(dhd_pub_t *dhd_pub, trace_buf_info_t *read_buf_info); #ifdef BCMPCIE extern int dhd_prot_debug_info_print(dhd_pub_t *dhd); +extern bool dhd_bus_skip_clm(dhd_pub_t *dhdp); #else #define dhd_prot_debug_info_print(x) +static INLINE bool dhd_bus_skip_clm(dhd_pub_t *dhd_pub) +{ return 0; } #endif /* BCMPCIE */ -extern bool dhd_prot_is_cmpl_ring_empty(dhd_pub_t *dhd, void *prot_info); - bool dhd_fw_download_status(dhd_pub_t * dhd_pub); +void dhd_show_kirqstats(dhd_pub_t *dhd); /* Bitmask used for Join Timeout */ #define WLC_SSID_MASK 0x01 @@ -2518,6 +2707,9 @@ do { \ #define DHD_ENABLE_RUNTIME_PM(dhdp) #endif /* DHD_PCIE_RUNTIMEPM */ +extern bool dhd_prot_is_cmpl_ring_empty(dhd_pub_t *dhd, void *prot_info); +extern void dhd_prot_dump_ring_ptrs(void *prot_info); + /* * Enable this macro if you want to track the calls to wake lock * This records can be printed using the following command @@ -2530,10 +2722,16 @@ do { \ #if defined(DHD_TRACE_WAKE_LOCK) void dhd_wk_lock_stats_dump(dhd_pub_t *dhdp); -#endif +#endif // endif extern bool dhd_query_bus_erros(dhd_pub_t *dhdp); +#if defined(CONFIG_64BIT) +#define DHD_SUPPORT_64BIT +#endif /* (linux || LINUX) && CONFIG_64BIT */ + +static INLINE void dhd_schedule_reset(dhd_pub_t *dhdp) {;} + extern void init_dhd_timeouts(dhd_pub_t *pub); extern void deinit_dhd_timeouts(dhd_pub_t *pub); @@ -2544,35 +2742,19 @@ typedef enum timeout_resons { DHD_REASON_OQS_TO } timeout_reasons_t; -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) -extern int dhd_bus_set_device_wake(struct dhd_bus *bus, bool val); -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ - -#ifdef DHD_EFI -extern void dhd_schedule_reset(dhd_pub_t *dhdp); -#else -static INLINE void dhd_schedule_reset(dhd_pub_t *dhdp) {;} -#endif - -#ifdef ENABLE_TEMP_THROTTLING -#ifndef TEMP_THROTTLE_CONTROL_BIT -#define TEMP_THROTTLE_CONTROL_BIT 0xd -#endif -#endif /* ENABLE_TEMP_THROTTLING */ - -int dhd_send_msg_to_daemon(struct sk_buff *skb, void *data, int size); -#ifdef REPORT_FATAL_TIMEOUTS -void dhd_send_trap_to_fw_for_timeout(dhd_pub_t * pub, timeout_reasons_t reason); -#endif - extern void dhd_prhex(const char *msg, volatile uchar *buf, uint nbytes, uint8 dbg_level); - -#if defined(CONFIG_64BIT) -#define DHD_SUPPORT_64BIT -#elif defined(DHD_EFI) -#define DHD_SUPPORT_64BIT -/* by default disabled for other platforms, can enable appropriate macro to enable 64 bit support */ -#endif /* (linux || LINUX) && CONFIG_64BIT */ +int dhd_tput_test(dhd_pub_t *dhd, tput_test_t *tput_data); +void dhd_tput_test_rx(dhd_pub_t *dhd, void *pkt); +static INLINE int dhd_get_max_txbufs(dhd_pub_t *dhdp) +{ return -1; } + +#ifdef FILTER_IE +int dhd_read_from_file(dhd_pub_t *dhd); +int dhd_parse_filter_ie(dhd_pub_t *dhd, uint8 *buf); +int dhd_get_filter_ie_count(dhd_pub_t *dhd, uint8 *buf); +int dhd_parse_oui(dhd_pub_t *dhd, uint8 *inbuf, uint8 *oui, int len); +int dhd_check_valid_ie(dhd_pub_t *dhdp, uint8 *buf, int len); +#endif /* FILTER_IE */ #ifdef SET_PCIE_IRQ_CPU_CORE extern void dhd_set_irq_cpucore(dhd_pub_t *dhdp, int set); @@ -2582,15 +2764,83 @@ extern void set_irq_cpucore(unsigned int irq, int set); extern void dhd_make_hang_with_reason(struct net_device *dev, const char *string_num); #endif /* DHD_HANG_SEND_UP_TEST */ +#ifdef DHD_WAKE_STATUS +wake_counts_t* dhd_get_wakecount(dhd_pub_t *dhdp); +#endif /* DHD_WAKE_STATUS */ + +extern void dhd_get_random_bytes(uint8 *buf, uint len); + #if defined(DHD_BLOB_EXISTENCE_CHECK) extern void dhd_set_blob_support(dhd_pub_t *dhdp, char *fw_path); #endif /* DHD_BLOB_EXISTENCE_CHECK */ -#ifdef DHD_WAKE_STATUS -wake_counts_t* dhd_get_wakecount(dhd_pub_t *dhdp); -#endif /* DHD_WAKE_STATUS */ +/* configuration of ecounters. API's tp start/stop. currently supported only for linux */ +extern int dhd_start_ecounters(dhd_pub_t *dhd); +extern int dhd_stop_ecounters(dhd_pub_t *dhd); +extern int dhd_start_event_ecounters(dhd_pub_t *dhd); +extern int dhd_stop_event_ecounters(dhd_pub_t *dhd); + +int dhd_get_preserve_log_numbers(dhd_pub_t *dhd, uint32 *logset_mask); + +#ifdef DHD_LOG_DUMP +int dhd_log_dump_ring_to_file(dhd_pub_t *dhdp, void *ring_ptr, void *file, + unsigned long *file_posn, log_dump_section_hdr_t *sec_hdr); +int dhd_log_dump_cookie_to_file(dhd_pub_t *dhdp, void *fp, unsigned long *f_pos); +int dhd_logdump_cookie_init(dhd_pub_t *dhdp, uint8 *buf, uint32 buf_size); +void dhd_logdump_cookie_deinit(dhd_pub_t *dhdp); +void dhd_logdump_cookie_save(dhd_pub_t *dhdp, char *cookie, char *type); +int dhd_logdump_cookie_get(dhd_pub_t *dhdp, char *ret_cookie, uint32 buf_size); +int dhd_logdump_cookie_count(dhd_pub_t *dhdp); +#endif /* DHD_LOG_DUMP */ -#ifdef BCM_ASLR_HEAP -extern uint32 dhd_get_random_number(void); -#endif /* BCM_ASLR_HEAP */ +#define DHD_PCIE_CONFIG_SAVE(bus) pci_save_state(bus->dev) +#define DHD_PCIE_CONFIG_RESTORE(bus) pci_restore_state(bus->dev) + +#ifdef BIGDATA_SOFTAP +void dhd_schedule_gather_ap_stadata(void *bcm_cfg, void *ndev, const wl_event_msg_t *e); +#endif /* BIGDATA_SOFTAP */ + +typedef struct dhd_pkt_parse { + uint32 proto; /* Network layer protocol */ + uint32 t1; /* n-tuple */ + uint32 t2; +} dhd_pkt_parse_t; + +/* ========= RING API functions : exposed to others ============= */ +#define DHD_RING_TYPE_FIXED 1 +uint32 dhd_ring_get_hdr_size(void); +void *dhd_ring_init(uint8 *buf, uint32 buf_size, uint32 elem_size, uint32 elem_cnt); +void dhd_ring_deinit(void *_ring); +void *dhd_ring_get_first(void *_ring); +void dhd_ring_free_first(void *_ring); +void *dhd_ring_get_last(void *_ring); +void *dhd_ring_get_next(void *_ring, void *cur); +void *dhd_ring_get_prev(void *_ring, void *cur); +void *dhd_ring_get_empty(void *_ring); +int dhd_ring_get_cur_size(void *_ring); +void dhd_ring_lock(void *ring, void *fist_ptr, void *last_ptr); +void dhd_ring_lock_free(void *ring); +void *dhd_ring_lock_get_first(void *_ring); +void *dhd_ring_lock_get_last(void *_ring); +int dhd_ring_lock_get_count(void *_ring); +void dhd_ring_lock_free_first(void *ring); + +#define DHD_DUMP_TYPE_NAME_SIZE 32 +#define DHD_DUMP_FILE_PATH_SIZE 256 +#define DHD_DUMP_FILE_COUNT_MAX 5 +#define DHD_DUMP_TYPE_COUNT_MAX 10 + +#ifdef DHD_DUMP_MNGR +typedef struct _DFM_elem { + char type_name[DHD_DUMP_TYPE_NAME_SIZE]; + char file_path[DHD_DUMP_FILE_COUNT_MAX][DHD_DUMP_FILE_PATH_SIZE]; + int file_idx; +} DFM_elem_t; + +typedef struct _dhd_dump_file_manage { + DFM_elem_t elems[DHD_DUMP_TYPE_COUNT_MAX]; +} dhd_dump_file_manage_t; + +extern void dhd_dump_file_manage_enqueue(dhd_pub_t *dhd, char *dump_path, char *fname); +#endif /* DHD_DUMP_MNGR */ #endif /* _dhd_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_bus.h b/drivers/net/wireless/bcmdhd_oo/dhd_bus.h index d92dc4db6cfa14b1366f01bf68fcedaaaddbd53c..7e3b9063d1e764dec042752f49b0107a2e008336 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_bus.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_bus.h @@ -4,14 +4,14 @@ * Provides type definitions and function prototypes used to link the * DHD OS, bus, and protocol modules. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: dhd_bus.h 698895 2017-05-11 02:55:17Z $ + * $Id: dhd_bus.h 739566 2018-01-09 01:24:24Z $ */ #ifndef _dhd_bus_h_ @@ -59,19 +59,12 @@ extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime); /* Set the Bus Idle Time */ extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time); -/* Size of Extended Trap data Buffer */ -#ifdef BCMPCIE -#define BCMPCIE_EXT_TRAP_DATA_MAXLEN 4096 -#endif - /* Send a data frame to the dongle. Callee disposes of txp. */ #ifdef BCMPCIE extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx); #else extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp); -#endif - -extern struct device * dhd_bus_to_dev(struct dhd_bus *bus); +#endif // endif /* Send/receive a control message to/from the dongle. * Expects caller to enforce a single outstanding transaction. @@ -96,7 +89,6 @@ extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen); extern bool dhd_bus_dpc(struct dhd_bus *bus); extern void dhd_bus_isr(bool * InterruptRecognized, bool * QueueMiniportHandleInterrupt, void *arg); - /* Check for and handle local prot-specific iovar commands */ extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, void *params, int plen, void *arg, int len, bool set); @@ -118,7 +110,7 @@ extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_par extern void *dhd_bus_pub(struct dhd_bus *bus); extern void *dhd_bus_txq(struct dhd_bus *bus); -extern const void *dhd_bus_sih(struct dhd_bus *bus); +extern void *dhd_bus_sih(struct dhd_bus *bus); extern uint dhd_bus_hdrlen(struct dhd_bus *bus); #ifdef BCMSDIO extern void dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val); @@ -126,7 +118,7 @@ extern void dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val); extern uint8 dhd_bus_is_ioready(struct dhd_bus *bus); #else #define dhd_bus_set_dotxinrx(a, b) do {} while (0) -#endif +#endif // endif #define DHD_SET_BUS_STATE_DOWN(_bus) do { \ (_bus)->dhd->busstate = DHD_BUS_DOWN; \ @@ -183,10 +175,7 @@ enum { TOTAL_LFRAG_PACKET_CNT, MAX_HOST_RXBUFS, HOST_API_VERSION, - DNGL_TO_HOST_TRAP_ADDR, -#ifdef HOFFLOAD_MODULES - WRT_HOST_MODULE_ADDR -#endif + DNGL_TO_HOST_TRAP_ADDR }; typedef void (*dhd_mb_ring_t) (struct dhd_bus *, uint32); @@ -221,7 +210,6 @@ extern void dhd_bus_set_linkdown(dhd_pub_t *dhdp, bool val); extern void dhd_bus_flow_ring_resume_response(struct dhd_bus *bus, uint16 flowid, int32 status); #endif /* IDLE_TX_FLOW_MGMT */ - extern int dhdpcie_bus_clock_start(struct dhd_bus *bus); extern int dhdpcie_bus_clock_stop(struct dhd_bus *bus); extern int dhdpcie_bus_enable_device(struct dhd_bus *bus); @@ -233,8 +221,9 @@ extern int dhd_bus_release_dongle(struct dhd_bus *bus); extern int dhd_bus_request_irq(struct dhd_bus *bus); extern int dhdpcie_get_pcieirq(struct dhd_bus *bus, unsigned int *irq); -extern void dhdpcie_cto_init(struct dhd_bus *bus, bool enable); +extern struct device * dhd_bus_to_dev(struct dhd_bus *bus); +extern void dhdpcie_cto_init(struct dhd_bus *bus, bool enable); #ifdef DHD_FW_COREDUMP extern struct dhd_bus *g_dhd_bus; @@ -249,18 +238,43 @@ extern void dhd_bus_handle_mb_data(struct dhd_bus *bus, uint32 d2h_mb_data); /* dump the device trap informtation */ extern void dhd_bus_dump_trap_info(struct dhd_bus *bus, struct bcmstrbuf *b); - +extern void dhd_bus_copy_trap_sig(struct dhd_bus *bus, trap_t *tr); +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT +void copy_ext_trap_sig(dhd_pub_t *dhd, trap_t *tr); +void copy_hang_info_trap(dhd_pub_t *dhd); +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ /* Function to set default min res mask */ extern bool dhd_bus_set_default_min_res_mask(struct dhd_bus *bus); /* Function to reset PMU registers */ extern void dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp); +extern void dhd_bus_ucode_download(struct dhd_bus *bus); + #ifdef DHD_ULP extern void dhd_bus_ulp_disable_console(dhd_pub_t *dhdp); -extern void dhd_bus_ucode_download(struct dhd_bus *bus); #endif /* DHD_ULP */ extern int dhd_bus_readwrite_bp_addr(dhd_pub_t *dhdp, uint addr, uint size, uint* data, bool read); +extern int dhd_get_idletime(dhd_pub_t *dhd); +#ifdef BCMPCIE +extern void dhd_bus_dump_console_buffer(struct dhd_bus *bus); +extern void dhd_bus_intr_count_dump(dhd_pub_t *dhdp); +#else +#define dhd_bus_dump_console_buffer(x) +static INLINE void dhd_bus_intr_count_dump(dhd_pub_t *dhdp) { UNUSED_PARAMETER(dhdp); } +#endif /* BCMPCIE */ + +#if defined(BCMPCIE) && defined(DHD_LOG_DUMP) +void dhdpcie_get_etd_preserve_logs(dhd_pub_t *dhd, uint8 *ext_trap_data, + void *event_decode_data); +#endif // endif + +extern uint16 dhd_get_chipid(dhd_pub_t *dhd); + +#ifdef DHD_WAKE_STATUS +extern wake_counts_t* dhd_bus_get_wakecount(dhd_pub_t *dhd); +extern int dhd_bus_get_bus_wake(dhd_pub_t * dhd); +#endif /* DHD_WAKE_STATUS */ #ifdef BT_OVER_SDIO /* @@ -273,18 +287,12 @@ int __dhdsdio_clk_enable(struct dhd_bus *bus, bus_owner_t owner, int can_wait); int __dhdsdio_clk_disable(struct dhd_bus *bus, bus_owner_t owner, int can_wait); void dhdsdio_reset_bt_use_count(struct dhd_bus *bus); #endif /* BT_OVER_SDIO */ -#ifdef BCMPCIE -extern void dhd_bus_dump_console_buffer(struct dhd_bus *bus); -#else -#define dhd_bus_dump_console_buffer(x) -#endif /* BCMPCIE */ -extern uint16 dhd_get_chipid(dhd_pub_t *dhd); +int dhd_bus_perform_flr(struct dhd_bus *bus, bool force_fail); -extern int dhd_get_idletime(dhd_pub_t *dhd); +#ifdef BCMPCIE +extern void dhdpcie_advertise_bus_cleanup(dhd_pub_t *dhdp); +extern void dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd); +#endif /* BCMPCIE */ -#ifdef DHD_WAKE_STATUS -extern wake_counts_t* dhd_bus_get_wakecount(dhd_pub_t *dhd); -extern int dhd_bus_get_bus_wake(dhd_pub_t * dhd); -#endif /* DHD_WAKE_STATUS */ #endif /* _dhd_bus_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_cdc.c b/drivers/net/wireless/bcmdhd_oo/dhd_cdc.c index 8ebe62e52c84d2e7cd7399dd00daa0e659e9b4a7..e620274c3adc8c5dae46411d37678fb388cdee79 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_cdc.c @@ -1,14 +1,14 @@ /* * DHD Protocol Module for CDC and BDC. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_cdc.c 699163 2017-05-12 05:18:23Z $ + * $Id: dhd_cdc.c 692135 2017-03-26 17:19:39Z $ * * 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 @@ -44,17 +44,15 @@ #include #include - #ifdef PROP_TXSTATUS #include #include -#endif +#endif // endif #ifdef DHD_ULP #include #endif /* DHD_ULP */ - #define RETRIES 2 /* # of retries to retrieve matching ioctl response */ #define BUS_HEADER_LEN (24+DHD_SDALIGN) /* Must be at least SDPCM_RESERVE * defined in dhd_sdio.c (amount of header tha might be added) @@ -73,7 +71,6 @@ typedef struct dhd_prot { unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN]; } dhd_prot_t; - static int dhdcdc_msg(dhd_pub_t *dhd) { @@ -128,7 +125,6 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uin DHD_TRACE(("%s: Enter\n", __FUNCTION__)); DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len)); - /* Respond "bcmerror" and "bcmerrorstr" with local cache */ if (cmd == WLC_GET_VAR && buf) { @@ -313,7 +309,6 @@ done: return ret; } - int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) { @@ -397,7 +392,7 @@ 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_wlfc_dump(dhdp, strbuf); -#endif +#endif // endif } /* The FreeBSD PKTPUSH could change the packet buf pinter @@ -424,7 +419,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF) if (PKTSUMNEEDED(PKTBUF)) h->flags |= BDC_FLAG_SUM_NEEDED; - h->priority = (PKTPRIO(PKTBUF) & BDC_PRIORITY_MASK); h->flags2 = 0; h->dataOffset = 0; @@ -440,7 +434,7 @@ dhd_prot_hdrlen(dhd_pub_t *dhd, void *PKTBUF) #ifdef BDC /* Length of BDC(+WLFC) headers pushed */ hdrlen = BDC_HEADER_LEN + (((struct bdc_header *)PKTBUF)->dataOffset * 4); -#endif +#endif // endif return hdrlen; } @@ -450,7 +444,7 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in { #ifdef BDC struct bdc_header *h; -#endif +#endif // endif uint8 data_offset = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -497,7 +491,6 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); #endif /* BDC */ - #ifdef PROP_TXSTATUS if (!DHD_PKTTAG_PKTDIR(PKTTAG(pktbuf))) { /* @@ -514,7 +507,6 @@ exit: return 0; } - int dhd_prot_attach(dhd_pub_t *dhd) { @@ -535,7 +527,7 @@ dhd_prot_attach(dhd_pub_t *dhd) dhd->prot = cdc; #ifdef BDC dhd->hdrlen += BDC_HEADER_LEN; -#endif +#endif // endif dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN; return 0; @@ -551,7 +543,7 @@ dhd_prot_detach(dhd_pub_t *dhd) { #ifdef PROP_TXSTATUS dhd_wlfc_deinit(dhd); -#endif +#endif // endif DHD_OS_PREFREE(dhd, dhd->prot, sizeof(dhd_prot_t)); dhd->prot = NULL; } @@ -592,7 +584,6 @@ dhd_sync_with_dongle(dhd_pub_t *dhd) if (ret < 0) goto done; - DHD_SSSR_DUMP_INIT(dhd); dhd_process_cid_mac(dhd, TRUE); @@ -617,7 +608,6 @@ dhd_prot_stop(dhd_pub_t *dhd) /* Nothing to do for CDC */ } - static void dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt, uint32 *pkt_count, void **pplast, uint8 start, uint8 end) @@ -763,7 +753,6 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord cur_idx = reorder_info_buf[WLHOST_REORDERDATA_CURIDX_OFFSET]; exp_idx = reorder_info_buf[WLHOST_REORDERDATA_EXPIDX_OFFSET]; - if ((exp_idx == ptr->exp_idx) && (cur_idx != ptr->exp_idx)) { /* still in the current hole */ /* enqueue the current on the buffer chain */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.c index d01e7680142da2b7aef35149a67e4d79977ec107..b9b8b23f233b0a36228c6d4b1c939cbc68d86b80 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.c @@ -1,14 +1,14 @@ /* * Linux cfg80211 driver - Dongle Host Driver (DHD) related * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_cfg80211.c 699163 2017-05-12 05:18:23Z $ + * $Id: dhd_cfg80211.c 722772 2017-09-21 09:52:00Z $ */ #include @@ -38,13 +38,13 @@ #ifdef PKT_FILTER_SUPPORT #include #include -#endif +#endif // endif #ifdef PKT_FILTER_SUPPORT extern uint dhd_pkt_filter_enable; extern uint dhd_master_mode; extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); -#endif +#endif // endif static int dhd_dongle_up = FALSE; @@ -78,17 +78,19 @@ s32 dhd_cfg80211_down(struct bcm_cfg80211 *cfg) { struct net_device *ndev; s32 err = 0; + dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub); WL_TRACE(("In\n")); - if (!dhd_dongle_up) { - WL_ERR(("Dongle is already down\n")); - return err; + if ((!dhd_dongle_up) || (!dhd->up)) { + WL_INFORM_MEM(("Dongle is already down\n")); + err = 0; + goto done; } - ndev = bcmcfg_to_prmry_ndev(cfg); wl_dongle_down(ndev); +done: dhd_dongle_up = FALSE; - return 0; + return err; } s32 dhd_cfg80211_set_p2p_info(struct bcm_cfg80211 *cfg, int val) @@ -144,9 +146,12 @@ int wl_cfg80211_remove_if(struct bcm_cfg80211 *cfg, struct net_device * dhd_cfg80211_netdev_free(struct net_device *ndev) { + struct bcm_cfg80211 *cfg; + if (ndev) { + cfg = wl_get_cfg(ndev); if (ndev->ieee80211_ptr) { - kfree(ndev->ieee80211_ptr); + MFREE(cfg->osh, ndev->ieee80211_ptr, sizeof(struct wireless_dev)); ndev->ieee80211_ptr = NULL; } free_netdev(ndev); @@ -160,7 +165,7 @@ void dhd_netdev_free(struct net_device *ndev) { #ifdef WL_CFG80211 ndev = dhd_cfg80211_netdev_free(ndev); -#endif +#endif // endif if (ndev) free_netdev(ndev); } @@ -191,12 +196,11 @@ wl_dongle_down(struct net_device *ndev) return err; } - s32 dhd_config_dongle(struct bcm_cfg80211 *cfg) { #ifndef DHD_SDALIGN #define DHD_SDALIGN 32 -#endif +#endif // endif struct net_device *ndev; s32 err = 0; @@ -235,14 +239,6 @@ int dhd_cfgvendor_priv_string_handler(struct bcm_cfg80211 *cfg, struct wireless_ dhd = cfg->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); - } - ndev = wdev_to_wlc_ndev(wdev, cfg); index = dhd_net2idx(dhd->info, ndev); if (index == DHD_BAD_IF) { diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.h index 20923ce5fda823315afba6f1a0c8d2cab40810a8..4db847c1cd6a19765f0e002439c8fc5bd86245f0 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_cfg80211.h @@ -1,14 +1,14 @@ /* * Linux cfg80211 driver - Dongle Host Driver (DHD) related * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,10 +24,9 @@ * * <> * - * $Id: dhd_cfg80211.h 612483 2016-01-14 03:44:27Z $ + * $Id: dhd_cfg80211.h 659395 2016-09-14 03:09:14Z $ */ - #ifndef __DHD_CFG80211__ #define __DHD_CFG80211__ @@ -37,10 +36,10 @@ #ifndef WL_ERR #define WL_ERR CFG80211_ERR -#endif +#endif // endif #ifndef WL_TRACE #define WL_TRACE CFG80211_TRACE -#endif +#endif // endif s32 dhd_cfg80211_init(struct bcm_cfg80211 *cfg); s32 dhd_cfg80211_deinit(struct bcm_cfg80211 *cfg); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_common.c b/drivers/net/wireless/bcmdhd_oo/dhd_common.c index 61a95488a585f46c026bf5cfd0ba8c6a02d55d43..570ef620270613e39b14fd8c278b6644e6dcc0b2 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_common.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_common.c @@ -1,14 +1,14 @@ /* * Broadcom Dongle Host Driver (DHD), common DHD core. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_common.c 736294 2017-12-14 10:37:03Z $ + * $Id: dhd_common.c 740023 2018-01-10 12:15:20Z $ */ #include #include @@ -34,10 +34,10 @@ #include #include -#include #include #include #include +#include #ifdef PCIE_FULL_DONGLE #include @@ -49,28 +49,30 @@ #ifdef BCMPCIE #include -#endif +#endif // endif #include #include #include +#include <802.1d.h> #include +#include #include #include #ifdef WL_CFG80211 #include -#endif +#endif // endif #ifdef PNO_SUPPORT #include -#endif +#endif // endif #ifdef RTT_SUPPORT #include -#endif +#endif // endif #ifdef DNGL_EVENT_SUPPORT #include -#endif +#endif // endif #define htod32(i) (i) #define htod16(i) (i) @@ -82,8 +84,7 @@ #ifdef PROP_TXSTATUS #include #include -#endif - +#endif // endif #ifdef DHD_L2_FILTER #include @@ -92,33 +93,21 @@ #ifdef DHD_PSTA #include #endif /* DHD_PSTA */ -#ifdef DHD_TIMESYNC -#include -#endif /* DHD_TIMESYNC */ #ifdef DHD_WET #include #endif /* DHD_WET */ -#if defined(BCMEMBEDIMAGE) && defined(DHD_EFI) -#include -#endif - - -extern int is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype, - bcm_event_msg_u_t *out_event); - -#if defined(CUSTOMER_HW4) -/* For CUSTOMER_HW4 do not enable DHD_EVENT_VAL and DHD_ERROR_MEM_VAL */ -int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL | DHD_EVENT_VAL | - DHD_PKT_MON_VAL; -#else -/* By default all logs are enabled */ -int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL | DHD_EVENT_VAL | - DHD_ERROR_MEM_VAL; -#endif /* defined(CUSTOMER_HW4) */ - +int dhd_msg_level = DHD_ERROR_VAL | DHD_FWLOG_VAL | DHD_EVENT_VAL + /* For CUSTOMER_HW4 do not enable DHD_IOVAR_MEM_VAL by default */ +#if !defined(CUSTOMER_HW4) + | DHD_IOVAR_MEM_VAL +#endif /* !defined(CUSTOMER_HW4) */ + | DHD_PKT_MON_VAL; +#if defined(WL_WIRELESS_EXT) +#include +#endif // endif #ifdef DHD_ULP #include @@ -128,23 +117,14 @@ int dhd_msg_level = DHD_ERROR_VAL | DHD_MSGTRACE_VAL | DHD_FWLOG_VAL | DHD_EVENT #include #endif /* DHD_DEBUG */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#include +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef SOFTAP char fw_path2[MOD_PARAM_PATHLEN]; extern bool softap_enabled; -#endif - -#ifdef REPORT_FATAL_TIMEOUTS -/* Default timeout value in ms */ -#define SCAN_TIMEOUT_DEFAULT 1 -#define JOIN_TIMEOUT_DEFAULT 7500 -#ifdef DHD_EFI -#define BUS_TIMEOUT_DEFAULT 8000000 /* 800ms, in units of 100ns */ -#define CMD_TIMEOUT_DEFAULT 15000000 /* 1.5sec, in units of 100ns */ -#else -#define BUS_TIMEOUT_DEFAULT 800 -#define CMD_TIMEOUT_DEFAULT 1200 -#endif /* DHD_EFI */ -#endif /* REPORT_FATAL_TIMEOUTS */ +#endif // endif #ifdef SHOW_LOGTRACE #define BYTES_AHEAD_NUM 11 /* address in map file is before these many bytes */ @@ -159,6 +139,14 @@ static char *rodata_end_str = "rodata_end"; /* string in mapfile has addr rodata #define ALL_MAP_VAL (RAMSTART_BIT | RDSTART_BIT | RDEND_BIT) #endif /* SHOW_LOGTRACE */ +#ifdef SHOW_LOGTRACE +/* the fw file path is taken from either the module parameter at + * insmod time or is defined as a constant of different values + * for different platforms + */ +extern char *st_str_file_path; +#endif /* SHOW_LOGTRACE */ + /* Last connection success/failure status */ uint32 dhd_conn_event; uint32 dhd_conn_status; @@ -172,9 +160,10 @@ void dhd_iscan_unlock(void); extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx); #if !defined(AP) && defined(WLP2P) extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd); -#endif +#endif // endif extern int dhd_socram_dump(struct dhd_bus *bus); +extern void dhd_set_packet_filter(dhd_pub_t *dhd); #ifdef DNGL_EVENT_SUPPORT static void dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event, @@ -183,6 +172,10 @@ static int dngl_host_event(dhd_pub_t *dhdp, void *pktdata, bcm_dngl_event_msg_t size_t pktlen); #endif /* DNGL_EVENT_SUPPORT */ +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT +static void copy_hang_info_ioctl_timeout(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc); +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ + #define MAX_CHUNK_LEN 1408 /* 8 * 8 * 22 */ bool ap_cfg_running = FALSE; @@ -192,7 +185,7 @@ bool ap_fw_loaded = FALSE; #ifdef DHD_DEBUG #ifndef SRCBASE #define SRCBASE "drivers/net/wireless/bcmdhd" -#endif +#endif // endif #define DHD_COMPILED "\nCompiled in " SRCBASE #endif /* DHD_DEBUG */ @@ -203,7 +196,7 @@ const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR DHD_COMPILED " on " __DATE__ " at " __TIME__; #else const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nCompiled from "; -#endif +#endif // endif char fw_version[FW_VER_STR_LEN] = "\0"; char clm_version[CLM_VER_STR_LEN] = "\0"; @@ -211,10 +204,7 @@ char bus_api_revision[BUS_API_REV_STR_LEN] = "\0"; void dhd_set_timer(void *bus, uint wdtick); -#if defined(TRAFFIC_MGMT_DWM) -static int traffic_mgmt_add_dwm_filter(dhd_pub_t *dhd, - trf_mgmt_filter_list_t * trf_mgmt_filter_list, int len); -#endif +static char* ioctl2str(uint32 ioctl); /* IOVar table */ enum { @@ -236,6 +226,9 @@ enum { IOV_DHD_JOIN_TIMEOUT_DBG, IOV_SCAN_TIMEOUT, IOV_MEM_DEBUG, +#ifdef BCMPCIE + IOV_FLOW_RING_DEBUG, +#endif /* BCMPCIE */ #endif /* defined(DHD_DEBUG) */ #ifdef PROP_TXSTATUS IOV_PROPTXSTATUS_ENABLE, @@ -252,15 +245,13 @@ enum { #ifdef DHDTCPACK_SUPPRESS IOV_TCPACK_SUPPRESS, #endif /* DHDTCPACK_SUPPRESS */ -#if defined(TRAFFIC_MGMT_DWM) - IOV_TRAFFIC_MGMT_DWM, -#endif IOV_AP_ISOLATE, #ifdef DHD_L2_FILTER IOV_DHCP_UNICAST, IOV_BLOCK_PING, IOV_PROXY_ARP, IOV_GRAT_ARP, + IOV_BLOCK_TDLS, #endif /* DHD_L2_FILTER */ IOV_DHD_IE, #ifdef DHD_PSTA @@ -276,43 +267,39 @@ enum { IOV_LMTEST, #ifdef DHD_MCAST_REGEN IOV_MCAST_REGEN_BSS_ENABLE, -#endif +#endif // endif #ifdef SHOW_LOGTRACE IOV_DUMP_TRACE_LOG, #endif /* SHOW_LOGTRACE */ -#ifdef REPORT_FATAL_TIMEOUTS - IOV_SCAN_TO, - IOV_JOIN_TO, - IOV_CMD_TO, - IOV_OQS_TO, -#endif /* REPORT_FATAL_TIMEOUTS */ IOV_DONGLE_TRAP_TYPE, IOV_DONGLE_TRAP_INFO, IOV_BPADDR, - IOV_LAST, -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) - IOV_LOG_CAPTURE_ENABLE, - IOV_LOG_DUMP -#endif /* DHD_EFI && DHD_LOG_DUMP */ + IOV_DUMP_DONGLE, /**< dumps core registers and d11 memories */ + IOV_TPUT_TEST, + IOV_LAST }; const bcm_iovar_t dhd_iovars[] = { - {"version", IOV_VERSION, 0, 0, IOVT_BUFFER, sizeof(dhd_version) }, + /* name varid flags flags2 type minlen */ + {"version", IOV_VERSION, 0, 0, IOVT_BUFFER, sizeof(dhd_version)}, #ifdef DHD_DEBUG - {"msglevel", IOV_MSGLEVEL, 0, 0, IOVT_UINT32, 0 }, + {"msglevel", IOV_MSGLEVEL, 0, 0, IOVT_UINT32, 0}, {"mem_debug", IOV_MEM_DEBUG, 0, 0, IOVT_BUFFER, 0 }, +#ifdef BCMPCIE + {"flow_ring_debug", IOV_FLOW_RING_DEBUG, 0, 0, IOVT_BUFFER, 0 }, +#endif /* BCMPCIE */ #endif /* DHD_DEBUG */ - {"bcmerrorstr", IOV_BCMERRORSTR, 0, 0, IOVT_BUFFER, BCME_STRLEN }, - {"bcmerror", IOV_BCMERROR, 0, 0, IOVT_INT8, 0 }, - {"wdtick", IOV_WDTICK, 0, 0, IOVT_UINT32, 0 }, - {"dump", IOV_DUMP, 0, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, - {"cons", IOV_CONS, 0, 0, IOVT_BUFFER, 0 }, - {"dconpoll", IOV_DCONSOLE_POLL, 0, 0, IOVT_UINT32, 0 }, - {"clearcounts", IOV_CLEARCOUNTS, 0, 0, IOVT_VOID, 0 }, - {"gpioob", IOV_GPIOOB, 0, 0, IOVT_UINT32, 0 }, - {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, 0, IOVT_UINT32, 0 }, + {"bcmerrorstr", IOV_BCMERRORSTR, 0, 0, IOVT_BUFFER, BCME_STRLEN}, + {"bcmerror", IOV_BCMERROR, 0, 0, IOVT_INT8, 0}, + {"wdtick", IOV_WDTICK, 0, 0, IOVT_UINT32, 0}, + {"dump", IOV_DUMP, 0, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN}, + {"cons", IOV_CONS, 0, 0, IOVT_BUFFER, 0}, + {"dconpoll", IOV_DCONSOLE_POLL, 0, 0, IOVT_UINT32, 0}, + {"clearcounts", IOV_CLEARCOUNTS, 0, 0, IOVT_VOID, 0}, + {"gpioob", IOV_GPIOOB, 0, 0, IOVT_UINT32, 0}, + {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, 0, IOVT_UINT32, 0}, #ifdef PROP_TXSTATUS - {"proptx", IOV_PROPTXSTATUS_ENABLE, 0, 0, IOVT_BOOL, 0 }, + {"proptx", IOV_PROPTXSTATUS_ENABLE, 0, 0, IOVT_BOOL, 0 }, /* set the proptxtstatus operation mode: 0 - Do not do any proptxtstatus flow control @@ -323,7 +310,7 @@ const bcm_iovar_t dhd_iovars[] = { {"proptx_opt", IOV_PROPTXSTATUS_OPT, 0, 0, IOVT_UINT32, 0 }, {"pmodule_ignore", IOV_PROPTXSTATUS_MODULE_IGNORE, 0, 0, IOVT_BOOL, 0 }, {"pcredit_ignore", IOV_PROPTXSTATUS_CREDIT_IGNORE, 0, 0, IOVT_BOOL, 0 }, - {"ptxstatus_ignore", IOV_PROPTXSTATUS_TXSTATUS_IGNORE, 0, 0, IOVT_BOOL, 0 }, + {"ptxstatus_ignore", IOV_PROPTXSTATUS_TXSTATUS_IGNORE, 0, 0, IOVT_BOOL, 0 }, {"rxpkt_chk", IOV_PROPTXSTATUS_RXPKT_CHK, 0, 0, IOVT_BOOL, 0 }, #endif /* PROP_TXSTATUS */ {"bustype", IOV_BUS_TYPE, 0, 0, IOVT_UINT32, 0}, @@ -333,9 +320,6 @@ const bcm_iovar_t dhd_iovars[] = { #ifdef DHDTCPACK_SUPPRESS {"tcpack_suppress", IOV_TCPACK_SUPPRESS, 0, 0, IOVT_UINT8, 0 }, #endif /* DHDTCPACK_SUPPRESS */ -#if defined(TRAFFIC_MGMT_DWM) - {"trf_mgmt_filters_add", IOV_TRAFFIC_MGMT_DWM, (0), 0, IOVT_BUFFER, 0}, -#endif #ifdef DHD_L2_FILTER {"dhcp_unicast", IOV_DHCP_UNICAST, (0), 0, IOVT_BOOL, 0 }, #endif /* DHD_L2_FILTER */ @@ -344,6 +328,7 @@ const bcm_iovar_t dhd_iovars[] = { {"block_ping", IOV_BLOCK_PING, (0), 0, IOVT_BOOL, 0}, {"proxy_arp", IOV_PROXY_ARP, (0), 0, IOVT_BOOL, 0}, {"grat_arp", IOV_GRAT_ARP, (0), 0, IOVT_BOOL, 0}, + {"block_tdls", IOV_BLOCK_TDLS, (0), IOVT_BOOL, 0}, #endif /* DHD_L2_FILTER */ {"dhd_ie", IOV_DHD_IE, (0), 0, IOVT_BUFFER, 0}, #ifdef DHD_PSTA @@ -361,25 +346,17 @@ const bcm_iovar_t dhd_iovars[] = { {"lmtest", IOV_LMTEST, 0, 0, IOVT_UINT32, 0 }, #ifdef DHD_MCAST_REGEN {"mcast_regen_bss_enable", IOV_MCAST_REGEN_BSS_ENABLE, 0, 0, IOVT_BOOL, 0}, -#endif +#endif // endif #ifdef SHOW_LOGTRACE {"dump_trace_buf", IOV_DUMP_TRACE_LOG, 0, 0, IOVT_BUFFER, sizeof(trace_buf_info_t) }, #endif /* SHOW_LOGTRACE */ -#ifdef REPORT_FATAL_TIMEOUTS - {"scan_timeout", IOV_SCAN_TO, 0, 0, IOVT_UINT32, 0 }, - {"join_timeout", IOV_JOIN_TO, 0, 0, IOVT_UINT32, 0 }, - {"cmd_timeout", IOV_CMD_TO, 0, 0, IOVT_UINT32, 0 }, - {"oqs_timeout", IOV_OQS_TO, 0, 0, IOVT_UINT32, 0 }, -#endif /* REPORT_FATAL_TIMEOUTS */ {"trap_type", IOV_DONGLE_TRAP_TYPE, 0, 0, IOVT_UINT32, 0 }, {"trap_info", IOV_DONGLE_TRAP_INFO, 0, 0, IOVT_BUFFER, sizeof(trap_t) }, #ifdef DHD_DEBUG {"bpaddr", IOV_BPADDR, 0, 0, IOVT_BUFFER, sizeof(sdreg_t) }, #endif /* DHD_DEBUG */ -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) - {"log_capture_enable", IOV_LOG_CAPTURE_ENABLE, 0, 0, IOVT_UINT8, 0}, - {"log_dump", IOV_LOG_DUMP, 0, 0, IOVT_UINT8, 0}, -#endif /* DHD_EFI && DHD_LOG_DUMP */ + {"dump_dongle", IOV_DUMP_DONGLE, 0, 0, IOVT_BUFFER, + MAX(sizeof(dump_dongle_in_t), sizeof(dump_dongle_out_t)) }, {NULL, 0, 0, 0, 0, 0 } }; @@ -448,22 +425,18 @@ dhd_sssr_mempool_deinit(dhd_pub_t *dhd) int dhd_get_sssr_reg_info(dhd_pub_t *dhd) { - int ret = BCME_ERROR; - - DHD_ERROR(("%s: get sssr_reg_info\n", __FUNCTION__)); + int ret; /* get sssr_reg_info from firmware */ memset((void *)&dhd->sssr_reg_info, 0, sizeof(dhd->sssr_reg_info)); - if (bcm_mkiovar("sssr_reg_info", 0, 0, (char *)&dhd->sssr_reg_info, - sizeof(dhd->sssr_reg_info))) { - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, &dhd->sssr_reg_info, - sizeof(dhd->sssr_reg_info), FALSE, 0)) < 0) { - DHD_ERROR(("%s: dhd_wl_ioctl_cmd failed (error=%d)\n", __FUNCTION__, ret)); - } - } else { - DHD_ERROR(("%s: bcm_mkiovar failed\n", __FUNCTION__)); + ret = dhd_iovar(dhd, 0, "sssr_reg_info", NULL, 0, (char *)&dhd->sssr_reg_info, + sizeof(dhd->sssr_reg_info), FALSE); + if (ret < 0) { + DHD_ERROR(("%s: sssr_reg_info failed (error=%d)\n", + __FUNCTION__, ret)); + return BCME_ERROR; } - return ret; + return BCME_OK; } uint32 @@ -533,8 +506,8 @@ dhd_sssr_dump_init(dhd_pub_t *dhd) dhd->sssr_d11_before[i] = NULL; dhd->sssr_d11_after[i] = NULL; } - dhd->sssr_vasip_buf_before = NULL; - dhd->sssr_vasip_buf_after = NULL; + dhd->sssr_dig_buf_before = NULL; + dhd->sssr_dig_buf_after = NULL; /* Allocate memory */ for (i = 0; i < MAX_NUM_D11CORES; i++) { @@ -548,10 +521,10 @@ dhd_sssr_dump_init(dhd_pub_t *dhd) } if (dhd->sssr_reg_info.vasip_regs.vasip_sr_size) { - dhd->sssr_vasip_buf_before = (uint32 *)(dhd->sssr_mempool + mempool_used); + dhd->sssr_dig_buf_before = (uint32 *)(dhd->sssr_mempool + mempool_used); mempool_used += dhd->sssr_reg_info.vasip_regs.vasip_sr_size; - dhd->sssr_vasip_buf_after = (uint32 *)(dhd->sssr_mempool + mempool_used); + dhd->sssr_dig_buf_after = (uint32 *)(dhd->sssr_mempool + mempool_used); mempool_used += dhd->sssr_reg_info.vasip_regs.vasip_sr_size; } @@ -572,8 +545,8 @@ dhd_sssr_dump_deinit(dhd_pub_t *dhd) dhd->sssr_d11_before[i] = NULL; dhd->sssr_d11_after[i] = NULL; } - dhd->sssr_vasip_buf_before = NULL; - dhd->sssr_vasip_buf_after = NULL; + dhd->sssr_dig_buf_before = NULL; + dhd->sssr_dig_buf_after = NULL; return; } @@ -616,7 +589,7 @@ dhd_common_socram_dump(dhd_pub_t *dhdp) return dhd_socram_dump(dhdp->bus); } -static int +int dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) { char eabuf[ETHER_ADDR_STR_LEN]; @@ -664,7 +637,6 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) bcm_bprintf(strbuf, "tx_pktgetfail %lu rx_pktgetfail %lu\n", dhdp->tx_pktgetfail, dhdp->rx_pktgetfail); bcm_bprintf(strbuf, "\n"); - #ifdef DMAMAP_STATS /* Add DMA MAP info */ bcm_bprintf(strbuf, "DMA MAP stats: \n"); @@ -693,7 +665,6 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) /* Add any bus info */ dhd_bus_dump(dhdp, strbuf); - #if defined(DHD_LB_STATS) dhd_lb_stats_dump(dhdp, strbuf); #endif /* DHD_LB_STATS */ @@ -703,7 +674,9 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) dhd_wet_dump(dhdp, strbuf); } #endif /* DHD_WET */ - return (!strbuf->size ? BCME_BUFTOOSHORT : 0); + + /* return remaining buffer length */ + return (!strbuf->size ? BCME_BUFTOOSHORT : strbuf->size); } void @@ -758,7 +731,7 @@ int dhd_wl_ioctl_set_intiovar(dhd_pub_t *dhd_pub, char *name, uint val, int cmd, uint8 set, int ifidx) { - char iovbuf[WLC_IOCTL_SMLEN] = {0}; + char iovbuf[WLC_IOCTL_SMLEN]; int ret = -1; int lval = htol32(val); uint len; @@ -779,6 +752,53 @@ dhd_wl_ioctl_set_intiovar(dhd_pub_t *dhd_pub, char *name, uint val, return ret; } +static struct ioctl2str_s { + uint32 ioctl; + char *name; +} ioctl2str_array[] = { + {WLC_UP, "UP"}, + {WLC_DOWN, "DOWN"}, + {WLC_SET_PROMISC, "SET_PROMISC"}, + {WLC_SET_INFRA, "SET_INFRA"}, + {WLC_SET_AUTH, "SET_AUTH"}, + {WLC_SET_SSID, "SET_SSID"}, + {WLC_RESTART, "RESTART"}, + {WLC_SET_CHANNEL, "SET_CHANNEL"}, + {WLC_SET_RATE_PARAMS, "SET_RATE_PARAMS"}, + {WLC_SET_KEY, "SET_KEY"}, + {WLC_SCAN, "SCAN"}, + {WLC_DISASSOC, "DISASSOC"}, + {WLC_REASSOC, "REASSOC"}, + {WLC_SET_COUNTRY, "SET_COUNTRY"}, + {WLC_SET_WAKE, "SET_WAKE"}, + {WLC_SET_SCANSUPPRESS, "SET_SCANSUPPRESS"}, + {WLC_SCB_DEAUTHORIZE, "SCB_DEAUTHORIZE"}, + {WLC_SET_WSEC, "SET_WSEC"}, + {WLC_SET_INTERFERENCE_MODE, "SET_INTERFERENCE_MODE"}, + {WLC_SET_RADAR, "SET_RADAR"}, + {0, NULL} +}; + +static char * +ioctl2str(uint32 ioctl) +{ + struct ioctl2str_s *p = ioctl2str_array; + + while (p->name != NULL) { + if (p->ioctl == ioctl) { + return p->name; + } + p++; + } + + return ""; +} + +/** + * @param ioc IO control struct, members are partially used by this function. + * @param buf [inout] Contains parameters to send to dongle, contains dongle response on return. + * @param len Maximum number of bytes that dongle is allowed to write into 'buf'. + */ int dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) { @@ -787,14 +807,28 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) #ifdef DUMP_IOCTL_IOV_LIST dhd_iov_li_t *iov_li; #endif /* DUMP_IOCTL_IOV_LIST */ + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + DHD_OS_WAKE_LOCK(dhd_pub); + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd_pub->bus)) < 0) { + DHD_RPM(("%s: pm_runtime_get_sync error. \n", __FUNCTION__)); + DHD_OS_WAKE_UNLOCK(dhd_pub); + return BCME_ERROR; + } +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef KEEPIF_ON_DEVICE_RESET if (ioc->cmd == WLC_GET_VAR) { dbus_config_t config; config.general_param = 0; - if (!strcmp(buf, "wowl_activate")) { - config.general_param = 2; /* 1 (TRUE) after decreased by 1 */ - } else if (!strcmp(buf, "wowl_clear")) { - config.general_param = 1; /* 0 (FALSE) after decreased by 1 */ + if (buf) { + if (!strcmp(buf, "wowl_activate")) { + /* 1 (TRUE) after decreased by 1 */ + config.general_param = 2; + } else if (!strcmp(buf, "wowl_clear")) { + /* 0 (FALSE) after decreased by 1 */ + config.general_param = 1; + } } if (config.general_param) { config.config_id = DBUS_CONFIG_ID_KEEPIF_ON_DEVRESET; @@ -811,22 +845,38 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) char *msg, tmp[64]; /* WLC_GET_VAR */ - if (ioc->cmd == WLC_GET_VAR) { + if (ioc->cmd == WLC_GET_VAR && buf) { min_len = MIN(sizeof(tmp) - 1, strlen(buf)); memset(tmp, 0, sizeof(tmp)); bcopy(buf, tmp, min_len); tmp[min_len] = '\0'; } #endif /* DHD_LOG_DUMP */ + /* logging of iovars that are send to the dongle, ./dhd msglevel +iovar */ + if (ioc->set == TRUE) { + char *pars = (char *)buf; // points at user buffer + if (ioc->cmd == WLC_SET_VAR && buf) { + DHD_DNGL_IOVAR_SET(("iovar:%d: set %s", ifidx, pars)); + if (ioc->len > 1 + sizeof(uint32)) { + // skip iovar name: + pars += strnlen(pars, ioc->len - 1 - sizeof(uint32)); + pars++; // skip NULL character + } + } else { + DHD_DNGL_IOVAR_SET(("ioctl:%d: set %d %s", + ifidx, ioc->cmd, ioctl2str(ioc->cmd))); + } + if (pars != NULL) { + DHD_DNGL_IOVAR_SET((" 0x%x\n", *(uint32*)pars)); + } else { + DHD_DNGL_IOVAR_SET((" NULL\n")); + } + } + DHD_LINUX_GENERAL_LOCK(dhd_pub, flags); if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd_pub)) { -#ifdef DHD_EFI DHD_INFO(("%s: returning as busstate=%d\n", __FUNCTION__, dhd_pub->busstate)); -#else - DHD_ERROR(("%s: returning as busstate=%d\n", - __FUNCTION__, dhd_pub->busstate)); -#endif /* DHD_EFI */ DHD_LINUX_GENERAL_UNLOCK(dhd_pub, flags); dhd_os_proto_unblock(dhd_pub); return -ENODEV; @@ -856,9 +906,10 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) DHD_ERROR(("iovar dump list item allocation Failed\n")); } else { iov_li->cmd = ioc->cmd; - bcopy((char *)buf, iov_li->buff, strlen((char *)buf)+1); + if (buf) + bcopy((char *)buf, iov_li->buff, strlen((char *)buf)+1); dhd_iov_li_append(dhd_pub, &dhd_pub->dump_iovlist_head, - &iov_li->list); + &iov_li->list); } } #endif /* DUMP_IOCTL_IOV_LIST */ @@ -870,36 +921,52 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) dhd_iov_li_print(&dhd_pub->dump_iovlist_head); } #endif /* DUMP_IOCTL_IOV_LIST */ +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT + if (ret == -ETIMEDOUT) { + copy_hang_info_ioctl_timeout(dhd_pub, ifidx, ioc); + } +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ #ifdef DHD_LOG_DUMP - if (ioc->cmd == WLC_GET_VAR || ioc->cmd == WLC_SET_VAR) { - lval = 0; - slen = strlen(buf) + 1; - msg = (char*)buf; - if (len >= slen + sizeof(lval)) { - if (ioc->cmd == WLC_GET_VAR) { - msg = tmp; - lval = *(int*)buf; - } else { - min_len = MIN(ioc->len - slen, sizeof(int)); - bcopy((msg + slen), &lval, min_len); - } - } - if (!strncmp(msg, "cur_etheraddr", strlen("cur_etheraddr"))) { + if ((ioc->cmd == WLC_GET_VAR || ioc->cmd == WLC_SET_VAR) && + buf != NULL) { + if (buf) { lval = 0; + slen = strlen(buf) + 1; + msg = (char*)buf; + if (len >= slen + sizeof(lval)) { + if (ioc->cmd == WLC_GET_VAR) { + msg = tmp; + lval = *(int*)buf; + } else { + min_len = MIN(ioc->len - slen, sizeof(int)); + bcopy((msg + slen), &lval, min_len); + } + if (!strncmp(msg, "cur_etheraddr", + strlen("cur_etheraddr"))) { + lval = 0; + } + } + DHD_IOVAR_MEM(( + "%s: cmd: %d, msg: %s val: 0x%x," + " len: %d, set: %d\n", + ioc->cmd == WLC_GET_VAR ? + "WLC_GET_VAR" : "WLC_SET_VAR", + ioc->cmd, msg, lval, ioc->len, ioc->set)); + } else { + DHD_IOVAR_MEM(("%s: cmd: %d, len: %d, set: %d\n", + ioc->cmd == WLC_GET_VAR ? "WLC_GET_VAR" : "WLC_SET_VAR", + ioc->cmd, ioc->len, ioc->set)); } - DHD_ERROR_MEM(("%s: cmd: %d, msg: %s, val: 0x%x, len: %d, set: %d\n", - ioc->cmd == WLC_GET_VAR ? "WLC_GET_VAR" : "WLC_SET_VAR", - ioc->cmd, msg, lval, ioc->len, ioc->set)); } else { slen = ioc->len; if (buf != NULL) { val = *(int*)buf; /* Do not dump for WLC_GET_MAGIC and WLC_GET_VERSION */ if (ioc->cmd != WLC_GET_MAGIC && ioc->cmd != WLC_GET_VERSION) - DHD_ERROR_MEM(("WLC_IOCTL: cmd: %d, val: %d, len: %d, " - "set: %d\n", ioc->cmd, val, ioc->len, ioc->set)); + DHD_IOVAR_MEM(("WLC_IOCTL: cmd: %d, val: %d, len: %d, " + "set: %d\n", ioc->cmd, val, ioc->len, ioc->set)); } else { - DHD_ERROR_MEM(("WLC_IOCTL: cmd: %d, buf is NULL\n", ioc->cmd)); + DHD_IOVAR_MEM(("WLC_IOCTL: cmd: %d, buf is NULL\n", ioc->cmd)); } } #endif /* DHD_LOG_DUMP */ @@ -923,12 +990,13 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) dhd_os_proto_unblock(dhd_pub); if (ret < 0) { - if (ioc->cmd == WLC_GET_VAR || ioc->cmd == WLC_SET_VAR) { + if ((ioc->cmd == WLC_GET_VAR || ioc->cmd == WLC_SET_VAR) && + buf != NULL) { if (ret == BCME_UNSUPPORTED || ret == BCME_NOTASSOCIATED) { DHD_ERROR(("%s: %s: %s, %s\n", __FUNCTION__, ioc->cmd == WLC_GET_VAR ? "WLC_GET_VAR" : "WLC_SET_VAR", - (char *)buf, + buf? (char *)buf:"NO MESSAGE", ret == BCME_UNSUPPORTED ? "UNSUPPORTED" : "NOT ASSOCIATED")); } else { @@ -951,6 +1019,13 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifidx, wl_ioctl_t *ioc, void *buf, int len) } } +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd_pub->bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd_pub->bus)); + + DHD_OS_WAKE_UNLOCK(dhd_pub); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + return ret; } @@ -1014,7 +1089,7 @@ int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen) #ifdef DHD_DEBUG int -dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) +dhd_mem_debug(dhd_pub_t *dhd, uchar *msg, uint msglen) { unsigned long int_arg = 0; char *p; @@ -1022,7 +1097,7 @@ dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) dhd_dbg_mwli_t *mw_li; dll_t *item, *next; /* check if mwalloc, mwquery or mwfree was supplied arguement with space */ - p = bcmstrstr(msg, " "); + p = bcmstrstr((char *)msg, " "); if (p != NULL) { /* space should be converted to null as separation flag for firmware */ *p = '\0'; @@ -1034,8 +1109,6 @@ dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) /* lets query the list inetrnally */ if (dll_empty(dll_head_p(&dhd->mw_list_head))) { DHD_ERROR(("memwaste list is empty, call mwalloc < size > to allocate\n")); - /* reset the id */ - dhd->mw_id = 0; } else { for (item = dll_head_p(&dhd->mw_list_head); !dll_end(&dhd->mw_list_head, item); item = next) { @@ -1051,10 +1124,10 @@ dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) *(p+1+sizeof(int32)) = '\0'; /* recalculated length -> 5 bytes for "alloc" + 4 bytes for size + - *1 bytes for null caracter + * 1 bytes for null caracter */ msglen = strlen(msg) + sizeof(int32) + 1; - if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, msg, msglen, FALSE, 0) < 0) { + if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, msg, msglen+1, FALSE, 0) < 0) { DHD_ERROR(("IOCTL failed for memdebug alloc\n")); } @@ -1087,6 +1160,10 @@ dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) size = mw_li->size; dll_delete(item); MFREE(dhd->osh, mw_li, sizeof(*mw_li)); + if (dll_empty(dll_head_p(&dhd->mw_list_head))) { + /* reset the id */ + dhd->mw_id = 0; + } } } if (handle) { @@ -1115,7 +1192,6 @@ dhd_mem_debug(dhd_pub_t *dhd, char *msg, uint msglen) } return 0; } - extern void dhd_mw_list_delete(dhd_pub_t *dhd, dll_t *list_head) { @@ -1128,6 +1204,112 @@ dhd_mw_list_delete(dhd_pub_t *dhd, dll_t *list_head) MFREE(dhd->osh, mw_li, sizeof(*mw_li)); } } +#ifdef BCMPCIE +int +dhd_flow_ring_debug(dhd_pub_t *dhd, char *msg, uint msglen) +{ + flow_ring_table_t *flow_ring_table; + char *cmd; + char *end_ptr = NULL; + uint8 prio; + uint16 flowid; + int i; + int ret = 0; + cmd = bcmstrstr(msg, " "); + BCM_REFERENCE(prio); + if (cmd != NULL) { + /* in order to use string operations append null */ + *cmd = '\0'; + } else { + DHD_ERROR(("missing: create/delete args\n")); + return BCME_ERROR; + } + if (cmd && !strcmp(msg, "create")) { + /* extract <"source address", "destination address", "priority"> */ + uint8 sa[ETHER_ADDR_LEN], da[ETHER_ADDR_LEN]; + BCM_REFERENCE(sa); + BCM_REFERENCE(da); + msg = msg + strlen("create") + 1; + /* fill ethernet source address */ + for (i = 0; i < ETHER_ADDR_LEN; i++) { + sa[i] = (uint8)bcm_strtoul(msg, &end_ptr, 16); + if (*end_ptr == ':') { + msg = (end_ptr + 1); + } else if (i != 5) { + DHD_ERROR(("not a valid source mac addr\n")); + return BCME_ERROR; + } + } + if (*end_ptr != ' ') { + DHD_ERROR(("missing: destiantion mac id\n")); + return BCME_ERROR; + } else { + /* skip space */ + msg = end_ptr + 1; + } + /* fill ethernet destination address */ + for (i = 0; i < ETHER_ADDR_LEN; i++) { + da[i] = (uint8)bcm_strtoul(msg, &end_ptr, 16); + if (*end_ptr == ':') { + msg = (end_ptr + 1); + } else if (i != 5) { + DHD_ERROR(("not a valid destination mac addr\n")); + return BCME_ERROR; + } + } + if (*end_ptr != ' ') { + DHD_ERROR(("missing: priority\n")); + return BCME_ERROR; + } else { + msg = end_ptr + 1; + } + /* parse priority */ + prio = (uint8)bcm_strtoul(msg, &end_ptr, 10); + if (prio > MAXPRIO) { + DHD_ERROR(("%s: invalid priority. Must be between 0-7 inclusive\n", + __FUNCTION__)); + return BCME_ERROR; + } + + if (*end_ptr != '\0') { + DHD_ERROR(("msg not truncated with NULL character\n")); + return BCME_ERROR; + } + ret = dhd_flowid_debug_create(dhd, 0, prio, (char *)sa, (char *)da, &flowid); + if (ret != BCME_OK) { + DHD_ERROR(("%s: flowring creation failed ret: %d\n", __FUNCTION__, ret)); + return BCME_ERROR; + } + return BCME_OK; + + } else if (cmd && !strcmp(msg, "delete")) { + msg = msg + strlen("delete") + 1; + /* parse flowid */ + flowid = (uint16)bcm_strtoul(msg, &end_ptr, 10); + if (*end_ptr != '\0') { + DHD_ERROR(("msg not truncated with NULL character\n")); + return BCME_ERROR; + } + + /* Find flowid from ifidx 0 since this IOVAR creating flowring with ifidx 0 */ + if (dhd_flowid_find_by_ifidx(dhd, 0, flowid) != BCME_OK) + { + DHD_ERROR(("%s : Deleting not created flowid: %u\n", __FUNCTION__, flowid)); + return BCME_ERROR; + } + + flow_ring_table = (flow_ring_table_t *)dhd->flow_ring_table; + ret = dhd_bus_flow_ring_delete_request(dhd->bus, (void *)&flow_ring_table[flowid]); + if (ret != BCME_OK) { + DHD_ERROR(("%s: flowring deletion failed ret: %d\n", __FUNCTION__, ret)); + return BCME_ERROR; + } + return BCME_OK; + } + DHD_ERROR(("%s: neither create nor delete\n", __FUNCTION__)); + return BCME_ERROR; +} +#endif /* BCMPCIE */ #endif /* DHD_DEBUG */ static int @@ -1196,30 +1378,33 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch break; } - if (CUSTOM_DHD_WATCHDOG_MS == 0 && int_val == 0) { - dhd_watchdog_ms = (uint)int_val; - } + dhd_watchdog_ms = (uint)int_val; dhd_os_wd_timer(dhd_pub, (uint)int_val); break; case IOV_GVAL(IOV_DUMP): - bcmerror = dhd_dump(dhd_pub, arg, len); + if (dhd_dump(dhd_pub, arg, len) <= 0) + bcmerror = BCME_ERROR; + else + bcmerror = BCME_OK; break; case IOV_GVAL(IOV_DCONSOLE_POLL): - int_val = (int32)dhd_console_ms; + int_val = (int32)dhd_pub->dhd_console_ms; bcopy(&int_val, arg, val_size); break; case IOV_SVAL(IOV_DCONSOLE_POLL): - dhd_console_ms = (uint)int_val; + dhd_pub->dhd_console_ms = (uint)int_val; break; +#if defined(DHD_DEBUG) case IOV_SVAL(IOV_CONS): if (len > 0) bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1); break; +#endif /* DHD_DEBUG */ case IOV_SVAL(IOV_CLEARCOUNTS): dhd_pub->tx_packets = dhd_pub->rx_packets = 0; @@ -1244,7 +1429,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch #endif /* DHD_LB_STATS */ break; - case IOV_GVAL(IOV_IOCTLTIMEOUT): { int_val = (int32)dhd_os_get_ioctl_resp_timeout(); bcopy(&int_val, arg, sizeof(int_val)); @@ -1347,17 +1531,16 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch /* The dhd application queries the driver to check if its usb or sdio. */ #ifdef BCMDHDUSB int_val = BUS_TYPE_USB; -#endif +#endif // endif #ifdef BCMSDIO int_val = BUS_TYPE_SDIO; -#endif +#endif // endif #ifdef PCIE_FULL_DONGLE int_val = BUS_TYPE_PCIE; -#endif +#endif // endif bcopy(&int_val, arg, val_size); break; - case IOV_SVAL(IOV_CHANGEMTU): int_val &= 0xffff; bcmerror = dhd_change_mtu(dhd_pub, int_val, 0); @@ -1393,15 +1576,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch } #endif /* DHDTCPACK_SUPPRESS */ -#if defined(TRAFFIC_MGMT_DWM) - case IOV_SVAL(IOV_TRAFFIC_MGMT_DWM): { - trf_mgmt_filter_list_t *trf_mgmt_filter_list = - (trf_mgmt_filter_list_t *)(arg); - bcmerror = traffic_mgmt_add_dwm_filter(dhd_pub, trf_mgmt_filter_list, len); - } - break; -#endif - #ifdef DHD_L2_FILTER case IOV_GVAL(IOV_DHCP_UNICAST): { uint32 bssidx; @@ -1515,6 +1689,32 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch bcmerror = dhd_set_grat_arp_status(dhd_pub, bssidx, int_val ? 1 : 0); break; } + case IOV_GVAL(IOV_BLOCK_TDLS): { + uint32 bssidx; + const char *val; + + if (dhd_iovar_parse_bssidx(dhd_pub, name, &bssidx, &val) != BCME_OK) { + DHD_ERROR(("%s: IOV_BLOCK_TDLS: bad parameter\n", __FUNCTION__)); + bcmerror = BCME_BADARG; + break; + } + int_val = dhd_get_block_tdls_status(dhd_pub, bssidx); + memcpy(arg, &int_val, val_size); + break; + } + case IOV_SVAL(IOV_BLOCK_TDLS): { + uint32 bssidx; + const char *val; + + if (dhd_iovar_parse_bssidx(dhd_pub, name, &bssidx, &val) != BCME_OK) { + DHD_ERROR(("%s: IOV_BLOCK_TDLS: bad parameter\n", __FUNCTION__)); + bcmerror = BCME_BADARG; + break; + } + memcpy(&int_val, val, sizeof(int_val)); + bcmerror = dhd_set_block_tdls_status(dhd_pub, bssidx, int_val ? 1 : 0); + break; + } #endif /* DHD_L2_FILTER */ case IOV_SVAL(IOV_DHD_IE): { uint32 bssidx; @@ -1651,7 +1851,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch g_assert_type = (uint32)int_val; break; - #if !defined(MACOSX_DHD) case IOV_GVAL(IOV_LMTEST): { *(uint32 *)arg = (uint32)lmtest; @@ -1669,7 +1868,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch } break; } -#endif +#endif // endif #ifdef SHOW_LOGTRACE case IOV_GVAL(IOV_DUMP_TRACE_LOG): { @@ -1688,44 +1887,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch break; } #endif /* SHOW_LOGTRACE */ -#ifdef REPORT_FATAL_TIMEOUTS - case IOV_GVAL(IOV_SCAN_TO): { - dhd_get_scan_to_val(dhd_pub, (uint32 *)&int_val); - bcopy(&int_val, arg, val_size); - break; - } - case IOV_SVAL(IOV_SCAN_TO): { - dhd_set_scan_to_val(dhd_pub, (uint32)int_val); - break; - } - case IOV_GVAL(IOV_JOIN_TO): { - dhd_get_join_to_val(dhd_pub, (uint32 *)&int_val); - bcopy(&int_val, arg, val_size); - break; - } - case IOV_SVAL(IOV_JOIN_TO): { - dhd_set_join_to_val(dhd_pub, (uint32)int_val); - break; - } - case IOV_GVAL(IOV_CMD_TO): { - dhd_get_cmd_to_val(dhd_pub, (uint32 *)&int_val); - bcopy(&int_val, arg, val_size); - break; - } - case IOV_SVAL(IOV_CMD_TO): { - dhd_set_cmd_to_val(dhd_pub, (uint32)int_val); - break; - } - case IOV_GVAL(IOV_OQS_TO): { - dhd_get_bus_to_val(dhd_pub, (uint32 *)&int_val); - bcopy(&int_val, arg, val_size); - break; - } - case IOV_SVAL(IOV_OQS_TO): { - dhd_set_bus_to_val(dhd_pub, (uint32)int_val); - break; - } -#endif /* REPORT_FATAL_TIMEOUTS */ case IOV_GVAL(IOV_DONGLE_TRAP_TYPE): if (dhd_pub->dongle_trap_occured) int_val = ltoh32(dhd_pub->last_trap_info.type); @@ -1783,33 +1944,19 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch break; } #endif /* BCMSDIO || BCMPCIE */ +#ifdef BCMPCIE + case IOV_SVAL(IOV_FLOW_RING_DEBUG): + { + bcmerror = dhd_flow_ring_debug(dhd_pub, arg, len); + break; + } +#endif /* BCMPCIE */ case IOV_SVAL(IOV_MEM_DEBUG): if (len > 0) { bcmerror = dhd_mem_debug(dhd_pub, arg, len - 1); } break; #endif /* DHD_DEBUG */ -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) - case IOV_GVAL(IOV_LOG_CAPTURE_ENABLE): - { - int_val = dhd_pub->log_capture_enable; - bcopy(&int_val, arg, val_size); - break; - } - - case IOV_SVAL(IOV_LOG_CAPTURE_ENABLE): - { - dhd_pub->log_capture_enable = (uint8)int_val; - break; - } - - case IOV_GVAL(IOV_LOG_DUMP): - { - dhd_prot_debug_info_print(dhd_pub); - dhd_bus_mem_dump(dhd_pub); - break; - } -#endif /* DHD_EFI && DHD_LOG_DUMP */ default: bcmerror = BCME_UNSUPPORTED; break; @@ -1846,13 +1993,13 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) /* Fast case, precedence queue is not full and we are also not * exceeding total queue length */ - if (!pktq_pfull(q, prec) && !pktq_full(q)) { + if (!pktqprec_full(q, prec) && !pktq_full(q)) { pktq_penq(q, prec, pkt); return TRUE; } /* Determine precedence from which to evict packet, if any */ - if (pktq_pfull(q, prec)) + if (pktqprec_full(q, prec)) eprec = prec; else if (pktq_full(q)) { p = pktq_peek_tail(q, &eprec); @@ -1864,7 +2011,7 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) /* Evict if needed */ if (eprec >= 0) { /* Detect queueing to unconfigured precedence */ - ASSERT(!pktq_pempty(q, eprec)); + ASSERT(!pktqprec_empty(q, eprec)); discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec); if (eprec == prec && !discard_oldest) return FALSE; /* refuse newer (incoming) packet */ @@ -1949,8 +2096,12 @@ dhd_prec_drop_pkts(dhd_pub_t *dhdp, struct pktq *pq, int prec, f_droppkt_t fn) p = first; while (p) { next = PKTLINK(p); - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); @@ -2062,7 +2213,8 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) uint arglen; DHD_LINUX_GENERAL_LOCK(dhd_pub, flags); - if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd_pub)) { + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd_pub) && + bcmstricmp((char *)buf, "devreset")) { /* In platforms like FC19, the FW download is done via IOCTL * and should not return error for IOCTLs fired before FW * Download is done @@ -2089,18 +2241,10 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) * other IOVARs, also include pciecfgreg and devreset to go * through. */ -#ifdef DHD_EFI - if (bcmstricmp((char *)buf, "pcie_suspend") && - bcmstricmp((char *)buf, "pciecfgreg") && - bcmstricmp((char *)buf, "devreset") && - bcmstricmp((char *)buf, "sdio_suspend") && - bcmstricmp((char *)buf, "control_signal")) { -#else if (bcmstricmp((char *)buf, "pcie_suspend") && bcmstricmp((char *)buf, "pciecfgreg") && bcmstricmp((char *)buf, "devreset") && bcmstricmp((char *)buf, "sdio_suspend")) { -#endif /* DHD_EFI */ DHD_ERROR(("%s: bus is in suspend(%d)" "or suspending(0x%x) state\n", __FUNCTION__, dhd_pub->busstate, @@ -2171,15 +2315,6 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) goto unlock_exit; } -#ifdef DHD_TIMESYNC - /* check TS module */ - if (ioc->cmd == DHD_GET_VAR) - bcmerror = dhd_timesync_iovar_op(dhd_pub->ts, buf, arg, - arglen, buf, buflen, IOV_GET); - else - bcmerror = dhd_timesync_iovar_op(dhd_pub->ts, buf, - NULL, 0, arg, arglen, IOV_SET); -#endif /* DHD_TIMESYNC */ } goto unlock_exit; @@ -2244,6 +2379,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, case WLC_E_REASSOC_IND: DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); + break; case WLC_E_ASSOC: @@ -2259,6 +2395,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status %d\n", event_name, eabuf, (int)status)); } + break; case WLC_E_DEAUTH_IND: @@ -2277,7 +2414,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, auth_str = err_msg; } - if (event_type == WLC_E_AUTH_IND) { + if (event_type == WLC_E_AUTH_IND) { DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str)); } else if (status == WLC_E_STATUS_SUCCESS) { DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n", @@ -2298,13 +2435,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, case WLC_E_SET_SSID: if (status == WLC_E_STATUS_SUCCESS) { DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); -#ifdef REPORT_FATAL_TIMEOUTS - dhd_clear_join_error(dhd_pub, WLC_SSID_MASK); -#endif /* REPORT_FATAL_TIMEOUTS */ } else { -#ifdef REPORT_FATAL_TIMEOUTS - dhd_set_join_error(dhd_pub, WLC_SSID_MASK); -#endif /* REPORT_FATAL_TIMEOUTS */ if (status == WLC_E_STATUS_FAIL) { DHD_EVENT(("MACEVENT: %s, failed\n", event_name)); } else if (status == WLC_E_STATUS_NO_NETWORKS) { @@ -2327,7 +2458,8 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, break; case WLC_E_LINK: - DHD_EVENT(("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN")); + DHD_EVENT(("MACEVENT: %s %s flags:0x%x status:%d\n", + event_name, link?"UP":"DOWN", flags, status)); BCM_REFERENCE(link); break; @@ -2357,9 +2489,6 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, case WLC_E_SCAN_COMPLETE: DHD_EVENT(("MACEVENT: %s\n", event_name)); -#ifdef REPORT_FATAL_TIMEOUTS - dhd_stop_scan_timer(dhd_pub); -#endif /* REPORT_FATAL_TIMEOUTS */ break; case WLC_E_RSSI_LQM: case WLC_E_PFN_NET_FOUND: @@ -2372,18 +2501,16 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, DHD_EVENT(("PNOEVENT: %s\n", event_name)); break; + case WLC_E_PFN_SCAN_BACKOFF: + case WLC_E_PFN_BSSID_SCAN_BACKOFF: + DHD_EVENT(("PNOEVENT: %s, status %d, reason %d\n", + event_name, (int)status, (int)reason)); + break; + case WLC_E_PSK_SUP: case WLC_E_PRUNE: DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n", event_name, (int)status, (int)reason)); -#ifdef REPORT_FATAL_TIMEOUTS - if ((status == WLC_E_STATUS_SUCCESS || status == WLC_E_STATUS_UNSOLICITED) && - (reason == WLC_E_SUP_OTHER)) { - dhd_clear_join_error(dhd_pub, WLC_WPA_MASK); - } else { - dhd_set_join_error(dhd_pub, WLC_WPA_MASK); - } -#endif /* REPORT_FATAL_TIMEOUTS */ break; #ifdef WIFI_ACT_FRAME @@ -2394,9 +2521,10 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, #ifdef SHOW_LOGTRACE case WLC_E_TRACE: - DHD_EVENT(("MACEVENT: %s Logtrace\n", event_name)); + { dhd_dbg_trace_evnt_handler(dhd_pub, event_data, raw_event_ptr, datalen); break; + } #endif /* SHOW_LOGTRACE */ case WLC_E_RSSI: @@ -2413,44 +2541,74 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, case WLC_E_BT_WIFI_HANDOVER_REQ: DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); break; -#endif +#endif // endif case WLC_E_CCA_CHAN_QUAL: if (datalen) { - buf = (uchar *) event_data; - DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d, " - "channel 0x%02x \n", event_name, event_type, eabuf, (int)status, - (int)reason, (int)auth_type, *(buf + 4))); + cca_chan_qual_event_t *cca_event = (cca_chan_qual_event_t *)event_data; + if (cca_event->id == WL_CHAN_QUAL_FULL_CCA) { + DHD_EVENT(( + "MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d," + " channel 0x%02x (dur %dms ibss %dms obss %dms interf %dms" + " ts 0x%08x)\n", + event_name, event_type, eabuf, (int)status, + (int)reason, (int)auth_type, cca_event->chanspec, + cca_event->cca_busy_ext.duration, + cca_event->cca_busy_ext.congest_ibss, + cca_event->cca_busy_ext.congest_obss, + cca_event->cca_busy_ext.interference, + cca_event->cca_busy_ext.timestamp)); + } else if (cca_event->id == WL_CHAN_QUAL_CCA) { + DHD_EVENT(( + "MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d," + " channel 0x%02x (dur %dms busy %dms ts 0x%08x)\n", + event_name, event_type, eabuf, (int)status, + (int)reason, (int)auth_type, cca_event->chanspec, + cca_event->cca_busy.duration, + cca_event->cca_busy.congest, + cca_event->cca_busy.timestamp)); + } else if ((cca_event->id == WL_CHAN_QUAL_NF) || + (cca_event->id == WL_CHAN_QUAL_NF_LTE)) { + DHD_EVENT(( + "MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d," + " channel 0x%02x (NF[%d] %ddB)\n", + event_name, event_type, eabuf, (int)status, + (int)reason, (int)auth_type, cca_event->chanspec, + cca_event->id, cca_event->noise)); + } else { + DHD_EVENT(( + "MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d," + " channel 0x%02x (unknown ID %d)\n", + event_name, event_type, eabuf, (int)status, + (int)reason, (int)auth_type, cca_event->chanspec, + cca_event->id)); + } } break; case WLC_E_ESCAN_RESULT: { -#ifdef CUSTOMER_HW4 - /* Because WLC_E_ESCAN_RESULT event log are being print too many. - * So, DHD_EVENT() changes to be used DHD_TRACE() in HW4 platform. - */ - DHD_TRACE(("MACEVENT: %s %d, MAC %s, status %d \n", - event_name, event_type, eabuf, (int)status)); -#else - DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d \n", - event_name, event_type, eabuf, (int)status)); -#endif /* CUSTOMER_HW4 */ - } - break; - case WLC_E_PSK_AUTH: - DHD_EVENT(("MACEVENT: %s, RA %s status %d Reason:%d\n", - event_name, eabuf, status, reason)); + wl_escan_result_v2_t *escan_result = + (wl_escan_result_v2_t *)event_data; + BCM_REFERENCE(escan_result); + if ((status == WLC_E_STATUS_SUCCESS) || (status == WLC_E_STATUS_ABORT)) { + DHD_EVENT(("MACEVENT: %s %d, status %d sync-id %u\n", + event_name, event_type, (int)status, + dtoh16(escan_result->sync_id))); + } else { + DHD_TRACE(("MACEVENT: %s %d, MAC %s, status %d \n", + event_name, event_type, eabuf, (int)status)); + } break; + } case WLC_E_IF: { struct wl_event_data_if *ifevent = (struct wl_event_data_if *)event_data; BCM_REFERENCE(ifevent); - DHD_EVENT(("MACEVENT: %s, opcode:0x%d ifidx:%d\n", - event_name, ifevent->opcode, ifevent->ifidx)); + DHD_EVENT(("MACEVENT: %s, opcode:0x%d ifidx:%d role:%d\n", + event_name, ifevent->opcode, ifevent->ifidx, ifevent->role)); break; } - #ifdef SHOW_LOGTRACE case WLC_E_MSCH: { @@ -2459,8 +2617,46 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, } #endif /* SHOW_LOGTRACE */ + case WLC_E_PSK_AUTH: + DHD_EVENT(("MACEVENT: %s, RA %s status %d Reason:%d\n", + event_name, eabuf, status, reason)); + break; + case WLC_E_AGGR_EVENT: + { + event_aggr_data_t *aggrbuf = event_data; + int j = 0, len = 0; + uint8 *data = aggrbuf->data; + DHD_EVENT(("MACEVENT: %s, num of events %d total len %d sub events: ", + event_name, aggrbuf->num_events, aggrbuf->len)); + for (j = 0; j < aggrbuf->num_events; j++) + { + wl_event_msg_t * sub_event = (wl_event_msg_t *)data; + if (len > aggrbuf->len) { + DHD_ERROR(("%s: Aggr events corrupted!", + __FUNCTION__)); + break; + } + DHD_EVENT(("\n Event type: %d ", ntoh32(sub_event->event_type))); + len += ALIGN_SIZE((ntoh32(sub_event->datalen) + + sizeof(wl_event_msg_t)), sizeof(uint64)); + buf = (uchar *)(data + sizeof(wl_event_msg_t)); + BCM_REFERENCE(buf); + DHD_EVENT((" data (%d) : ", ntoh32(sub_event->datalen))); + for (i = 0; i < ntoh32(sub_event->datalen); i++) { + DHD_EVENT((" 0x%02x ", buf[i])); + } + data = aggrbuf->data + len; + } + DHD_EVENT(("\n")); + } + break; + case WLC_E_NAN_CRITICAL: + { + DHD_EVENT(("MACEVENT: %s, type:%d\n", event_name, reason)); + break; + } default: - DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", + DHD_INFO(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", event_name, event_type, eabuf, (int)status, (int)reason, (int)auth_type)); break; @@ -2476,12 +2672,12 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data, } DHD_EVENT(("\n")); } -} +} /* wl_show_host_event */ #endif /* SHOW_EVENTS */ #ifdef DNGL_EVENT_SUPPORT /* Check whether packet is a BRCM dngl event pkt. If it is, process event data. */ -int + int dngl_host_event(dhd_pub_t *dhdp, void *pktdata, bcm_dngl_event_msg_t *dngl_event, size_t pktlen) { bcm_dngl_event_t *pvt_data = (bcm_dngl_event_t *)pktdata; @@ -2546,6 +2742,12 @@ dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event, if (DHD_EVENT_ON()) { prhex("HEALTHCHECK", p, ltoh32(dngl_hc->top_module_len)); } +#ifdef DHD_LOG_DUMP + memset(dhdp->health_chk_event_data, 0, HEALTH_CHK_BUF_SIZE); + memcpy(dhdp->health_chk_event_data, p, + MIN(ltoh32(dngl_hc->top_module_len), + HEALTH_CHK_BUF_SIZE)); +#endif /* DHD_LOG_DUMP */ p = (uint8 *)dngl_hc->value; switch (ltoh32(dngl_hc->top_module_tag)) { @@ -2568,11 +2770,31 @@ dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event, ltoh32(pcie_hc->pcie_control_reg))); break; } +#ifdef HCHK_COMMON_SW_EVENT + case HCHK_SW_ENTITY_WL_PRIMARY: + case HCHK_SW_ENTITY_WL_SECONDARY: + { + bcm_xtlv_t *wl_hc = (bcm_xtlv_t*)p; + + if (ltoh32(dngl_hc->top_module_len) < + sizeof(bcm_xtlv_t)) { + DHD_ERROR(("WL SW HC Wrong length:%d\n", + ltoh32(dngl_hc->top_module_len))); + return; + } + BCM_REFERENCE(wl_hc); + DHD_EVENT(("WL SW HC type %d len %d", + ltoh16(wl_hc->id), ltoh16(wl_hc->len))); + break; + } +#endif /* HCHK_COMMON_SW_EVENT */ default: + { DHD_ERROR(("%s:Unknown module TAG:%d\n", __FUNCTION__, ltoh32(dngl_hc->top_module_tag))); break; + } } break; } @@ -2593,15 +2815,17 @@ dngl_host_event_process(dhd_pub_t *dhdp, bcm_dngl_event_t *event, break; } #ifdef DHD_FW_COREDUMP - dhdp->memdump_type = DUMP_TYPE_DONGLE_HOST_EVENT; -#endif /* DHD_FW_COREDUMP */ - if (dhd_socram_dump(dhdp->bus)) { - DHD_ERROR(("%s: socram dump failed\n", __FUNCTION__)); - } else { - /* Notify framework */ - dhd_dbg_send_urgent_evt(dhdp, p, datalen); + if (dhdp->memdump_enabled) { + dhdp->memdump_type = DUMP_TYPE_DONGLE_HOST_EVENT; + if (dhd_socram_dump(dhdp->bus)) { + DHD_ERROR(("%s: socram dump failed\n", __FUNCTION__)); + } } +#else + dhd_dbg_send_urgent_evt(dhdp, p, datalen); +#endif /* DHD_FW_COREDUMP */ } + #endif /* DNGL_EVENT_SUPPORT */ /* Stub for now. Will become real function as soon as shim @@ -2644,7 +2868,7 @@ wl_event_process(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, ret = wl_event_process_default(&event, &evt_pport); return ret; -} +} /* wl_event_process */ /* Check whether packet is a BRCM event pkt. If it is, record event data. */ int @@ -2668,7 +2892,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen bcm_event_t *pvt_data = (bcm_event_t *)pktdata; bcm_event_msg_u_t evu; uint8 *event_data; - uint32 type, status, datalen; + uint32 type, status, datalen, reason; uint16 flags; uint evlen; int ret; @@ -2706,6 +2930,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen type = ntoh32_ua((void *)&event->event_type); flags = ntoh16_ua((void *)&event->flags); status = ntoh32_ua((void *)&event->status); + reason = ntoh32_ua((void *)&event->reason); datalen = ntoh32_ua((void *)&event->datalen); evlen = datalen + sizeof(bcm_event_t); @@ -2730,7 +2955,6 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen #endif /* LIMIT_BORROW */ #endif /* PROP_TXSTATUS */ - case WLC_E_ULP: #ifdef DHD_ULP { @@ -2753,7 +2977,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen { dhd_tdls_event_handler(dhd_pub, event); } -#endif +#endif // endif break; case WLC_E_IF: @@ -2768,15 +2992,15 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen #ifdef PCIE_FULL_DONGLE dhd_update_interface_flow_info(dhd_pub, ifevent->ifidx, ifevent->opcode, ifevent->role); -#endif +#endif // endif #ifdef PROP_TXSTATUS { uint8* ea = pvt_data->eth.ether_dhost; - WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, ["MACDBG"]\n", - ifevent->ifidx, - ((ifevent->opcode == WLC_E_IF_ADD) ? "ADD":"DEL"), - ((ifevent->role == 0) ? "STA":"AP "), - MAC2STRDBG(ea))); + WLFC_DBGMESG(("WLC_E_IF: idx:%d, action:%s, iftype:%s, ["MACDBG"]\n" + ifevent->ifidx, + ((ifevent->opcode == WLC_E_IF_ADD) ? "ADD":"DEL"), + ((ifevent->role == 0) ? "STA":"AP "), + MAC2STRDBG(ea))); (void)ea; if (ifevent->opcode == WLC_E_IF_CHANGE) @@ -2812,12 +3036,6 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen #endif /* PCIE_FULL_DONGLE */ dhd_event_ifdel(dhd_pub->info, ifevent, event->ifname, event->addr.octet); - /* Return ifidx (for vitual i/f, it will be > 0) - * so that no other operations on deleted interface - * are carried out - */ - ret = ifevent->ifidx; - goto exit; } else if (ifevent->opcode == WLC_E_IF_CHANGE) { #ifdef WL_CFG80211 dhd_event_ifchange(dhd_pub->info, ifevent, event->ifname, @@ -2848,7 +3066,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen case WLC_E_PFN_BEST_BATCHING: dhd_pno_event_handler(dhd_pub, event, (void *)event_data); break; -#endif +#endif // endif #if defined(RTT_SUPPORT) case WLC_E_PROXD: dhd_rtt_event_handler(dhd_pub, event, (void *)event_data); @@ -2869,11 +3087,15 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen DHD_ERROR(("%s: socram dump ERROR : \n", __FUNCTION__)); } break; -#endif +#endif // endif + case WLC_E_NATOE_NFCT: +#ifdef WL_NATOE + DHD_EVENT(("%s: WLC_E_NATOE_NFCT event received \n", __FUNCTION__)); + dhd_natoe_ct_event(dhd_pub, event_data); +#endif /* WL_NATOE */ + break; case WLC_E_LINK: #ifdef PCIE_FULL_DONGLE - DHD_EVENT(("%s: Link event %d, flags %x, status %x\n", - __FUNCTION__, type, flags, status)); if (dhd_update_interface_link_status(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info, event->ifname), (uint8)flags) != BCME_OK) { DHD_ERROR(("%s: dhd_update_interface_link_status Failed.\n", @@ -2936,6 +3158,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen __FUNCTION__, type, flags, status)); BCM_REFERENCE(flags); BCM_REFERENCE(status); + BCM_REFERENCE(reason); break; } @@ -2945,9 +3168,7 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen * to host with its registered interface name */ memcpy(pvt_data->event.ifname, dhd_ifname(dhd_pub, *ifidx), IFNAMSIZ); -#endif - -exit: +#endif // endif #ifdef SHOW_EVENTS if (DHD_FWLOG_ON() || DHD_EVENT_ON()) { @@ -2956,8 +3177,8 @@ exit: } #endif /* SHOW_EVENTS */ - return ret; -} + return (BCME_OK); +} /* wl_process_host_event */ int wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen, @@ -2993,7 +3214,7 @@ dhd_print_buf(void *pbuf, int len, int bytes_per_line) } #ifndef strtoul #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) -#endif +#endif // endif #if defined(PKT_FILTER_SUPPORT) || defined(DHD_PKT_LOGGING) /* Convert user's input in hex pattern to byte-size mask */ @@ -3077,9 +3298,20 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_ /* Enable/disable the specified filter. */ rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); rc = rc >= 0 ? 0 : rc; - if (rc) + if (rc) { DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", __FUNCTION__, arg, rc)); + dhd_set_packet_filter(dhd); + rc = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); + rc = rc >= 0 ? 0 : rc; + if (rc) { + DHD_TRACE_HW4(("%s: 2nd retry failed to add pktfilter %s, retcode = %d\n", + __FUNCTION__, arg, rc)); + } else { + DHD_TRACE_HW4(("%s: 2nd retry successfully added pktfilter %s\n", + __FUNCTION__, arg)); + } + } else DHD_TRACE(("%s: successfully added pktfilter %s\n", __FUNCTION__, arg)); @@ -3144,7 +3376,6 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) char *argv[16], * buf = 0; int i = 0; char *arg_save = 0, *arg_org = 0; -#define BUF_SIZE 2048 if (!arg) return; @@ -3156,14 +3387,15 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) arg_org = arg_save; - if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) { + if (!(buf = MALLOC(dhd->osh, MAX_PKTFLT_BUF_SIZE))) { DHD_ERROR(("%s: malloc failed\n", __FUNCTION__)); goto fail; } - memset(buf, 0, BUF_SIZE); + + memset(buf, 0, MAX_PKTFLT_BUF_SIZE); memcpy(arg_save, arg, strlen(arg) + 1); - if (strlen(arg) > BUF_SIZE) { + if (strlen(arg) > MAX_PKTFLT_BUF_SIZE) { DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf))); goto fail; } @@ -3180,7 +3412,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) str = "pkt_filter_add"; str_len = strlen(str); - bcm_strncpy_s(buf, BUF_SIZE, str, str_len); + bcm_strncpy_s(buf, MAX_PKTFLT_BUF_SIZE, str, str_len); buf[ str_len ] = '\0'; buf_len = str_len + 1; @@ -3261,9 +3493,16 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) } else if ((pkt_filter.type == 2) || (pkt_filter.type == 6)) { int list_cnt = 0; char *endptr = '\0'; - wl_pkt_filter_pattern_listel_t *pf_el = &pkt_filterp->u.patlist.patterns[0]; + wl_pkt_filter_pattern_listel_t *pf_el = + (wl_pkt_filter_pattern_listel_t *)&pkt_filterp->u.patlist.patterns[0]; while (argv[++i] != NULL) { + /* Check valid buffer size. */ + if ((buf_len + MAX_PKTFLT_FIXED_BUF_SIZE) > MAX_PKTFLT_BUF_SIZE) { + DHD_ERROR(("buffer over length MAX_PKTFLT_FIXED_BUF_SIZE\n")); + goto fail; + } + /* Parse pattern filter base and offset. */ if (bcm_isdigit(*argv[i])) { /* Numeric base */ @@ -3285,11 +3524,11 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) } if (*endptr == ':') { - pkt_filter.u.patlist.patterns[0].base_offs = htod16(rc); + pf_el->base_offs = htod16(rc); rc = strtoul(endptr + 1, &endptr, 0); } else { /* Must have had a numeric offset only */ - pkt_filter.u.patlist.patterns[0].base_offs = htod16(0); + pf_el->base_offs = htod16(0); } if (*endptr) { @@ -3300,10 +3539,10 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) printf("Offset too large\n"); goto fail; } - pkt_filter.u.patlist.patterns[0].rel_offs = htod16(rc); + pf_el->rel_offs = htod16(rc); /* Clear match_flag (may be set in parsing which follows) */ - pkt_filter.u.patlist.patterns[0].match_flags = htod16(0); + pf_el->match_flags = htod16(0); /* Parse pattern filter mask and pattern directly into ioctl buffer */ if (argv[++i] == NULL) { @@ -3311,7 +3550,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) goto fail; } rc = wl_pattern_atoh(argv[i], (char*)pf_el->mask_and_data); - if (rc == -1) { + if ((rc == -1) || (rc > MAX_PKTFLT_FIXED_PATTERN_SIZE)) { printf("Rejecting: %s\n", argv[i]); goto fail; } @@ -3323,7 +3562,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) } if (*argv[i] == '!') { - pkt_filter.u.patlist.patterns[0].match_flags = + pf_el->match_flags = htod16(WL_PKT_FILTER_MFLAG_NEG); (argv[i])++; } @@ -3332,7 +3571,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) goto fail; } rc = wl_pattern_atoh(argv[i], (char*)&pf_el->mask_and_data[rc]); - if (rc == -1) { + if ((rc == -1) || (rc > MAX_PKTFLT_FIXED_PATTERN_SIZE)) { printf("Rejecting: %s\n", argv[i]); goto fail; } @@ -3343,17 +3582,11 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) goto fail; } - pkt_filter.u.patlist.patterns[0].size_bytes = mask_size; + pf_el->size_bytes = mask_size; /* Account for the size of this pattern element */ buf_len += WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN + 2 * rc; - /* And the pattern element fields that were put in a local for - * alignment purposes now get copied to the ioctl buffer. - */ - memcpy((char*)pf_el, &pkt_filter.u.patlist.patterns[0], - WL_PKT_FILTER_PATTERN_FIXED_LEN); - /* Move to next element location in ioctl buffer */ pf_el = (wl_pkt_filter_pattern_listel_t*) ((uint8*)pf_el + WL_PKT_FILTER_PATTERN_LISTEL_FIXED_LEN + 2 * rc); @@ -3365,7 +3598,11 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) /* Account for initial fixed size, and copy initial fixed fields */ buf_len += WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_LIST_FIXED_LEN; - /* Update list count and total size */ + if (buf_len > MAX_PKTFLT_BUF_SIZE) { + DHD_ERROR(("buffer over length MAX_PKTFLT_BUF_SIZE\n")); + goto fail; + } + /* Update list count and total size */ pkt_filter.u.patlist.list_cnt = list_cnt; pkt_filter.u.patlist.PAD1[0] = 0; pkt_filter.u.patlist.totsize = buf + buf_len - (char*)pkt_filterp; @@ -3393,7 +3630,7 @@ fail: MFREE(dhd->osh, arg_org, strlen(arg) + 1); if (buf) - MFREE(dhd->osh, buf, BUF_SIZE); + MFREE(dhd->osh, buf, MAX_PKTFLT_BUF_SIZE); } void @@ -3557,6 +3794,13 @@ dhd_ndo_enable(dhd_pub_t * dhd, int ndo_enable) if (dhd == NULL) return -1; +#if defined(WL_CFG80211) && defined(WL_NAN) + if (wl_cfgnan_is_dp_active(dhd_linux_get_primary_netdev(dhd))) { + /* If nan dp is active, skip NDO */ + DHD_INFO(("Active NAN DP, skip NDO\n")); + return 0; + } +#endif /* WL_CFG80211 && WL_NAN */ #ifdef WL_CFG80211 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { /* NDO disable on STA+SOFTAP mode */ @@ -3583,7 +3827,7 @@ int dhd_ndo_add_ip(dhd_pub_t *dhd, char* ipv6addr, int idx) { int iov_len = 0; - char iovbuf[DHD_IOVAR_BUF_SIZE] = {0}; + char iovbuf[DHD_IOVAR_BUF_SIZE]; int retcode; if (dhd == NULL) @@ -3615,7 +3859,7 @@ int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx) { int iov_len = 0; - char iovbuf[DHD_IOVAR_BUF_SIZE] = {0}; + char iovbuf[DHD_IOVAR_BUF_SIZE]; int retcode; if (dhd == NULL) @@ -3639,7 +3883,6 @@ dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx) return retcode; } - /* Enhanced ND offload */ uint16 dhd_ndo_get_version(dhd_pub_t *dhdp) @@ -3660,7 +3903,8 @@ dhd_ndo_get_version(dhd_pub_t *dhdp) ndo_get_ver.length = htod32(WL_ND_HOSTIP_FIXED_LEN + sizeof(uint16)); ndo_get_ver.u.version = 0; iov_len = bcm_mkiovar("nd_hostip", (char *)&ndo_get_ver, - WL_ND_HOSTIP_FIXED_LEN + sizeof(uint16), iovbuf, sizeof(iovbuf)); + WL_ND_HOSTIP_FIXED_LEN + sizeof(uint16), iovbuf, sizeof(iovbuf)); + if (!iov_len) { DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n", __FUNCTION__, sizeof(iovbuf))); @@ -3668,6 +3912,7 @@ dhd_ndo_get_version(dhd_pub_t *dhdp) } retcode = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, iov_len, FALSE, 0); + if (retcode) { DHD_ERROR(("%s: failed, retcode = %d\n", __FUNCTION__, retcode)); /* ver iovar not supported. NDO version is 0 */ @@ -3726,7 +3971,7 @@ dhd_ndo_add_ip_with_type(dhd_pub_t *dhdp, char *ipv6addr, uint8 type, int idx) DHD_INFO(("%s: Host IP count exceed device capacity," "ND offload deactivated\n", __FUNCTION__)); dhdp->ndo_host_ip_overflow = TRUE; - dhd_ndo_enable(dhdp, 0); + dhd_ndo_enable(dhdp, FALSE); } #endif /* NDO_CONFIG_SUPPORT */ } else { @@ -3758,6 +4003,7 @@ dhd_ndo_remove_ip_by_addr(dhd_pub_t *dhdp, char *ipv6addr, int idx) iov_len = bcm_mkiovar("nd_hostip", (char *)&ndo_del_addr, WL_ND_HOSTIP_WITH_ADDR_LEN, iovbuf, sizeof(iovbuf)); + if (!iov_len) { DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n", __FUNCTION__, sizeof(iovbuf))); @@ -3799,6 +4045,7 @@ dhd_ndo_remove_ip_by_type(dhd_pub_t *dhdp, uint8 type, int idx) iov_len = bcm_mkiovar("nd_hostip", (char *)&ndo_del_addr, WL_ND_HOSTIP_FIXED_LEN, iovbuf, sizeof(iovbuf)); + if (!iov_len) { DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n", __FUNCTION__, sizeof(iovbuf))); @@ -3828,11 +4075,13 @@ dhd_ndo_unsolicited_na_filter_enable(dhd_pub_t *dhdp, int enable) iov_len = bcm_mkiovar("nd_unsolicited_na_filter", (char *)&enable, sizeof(int), iovbuf, sizeof(iovbuf)); + if (!iov_len) { DHD_ERROR(("%s: Insufficient iovar buffer size %zu \n", __FUNCTION__, sizeof(iovbuf))); return BCME_ERROR; } + retcode = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0); if (retcode) DHD_ERROR(("%s: failed to enable Unsolicited NA filter to %d, retcode = %d\n", @@ -3844,7 +4093,6 @@ dhd_ndo_unsolicited_na_filter_enable(dhd_pub_t *dhdp, int enable) return retcode; } - #ifdef SIMPLE_ISCAN uint iscan_thread_id = 0; @@ -3944,6 +4192,7 @@ dhd_iscan_issue_request(void * dhdp, wl_iscan_params_t *pParams, uint32 size) char iovar[] = "iscan"; uint32 allocSize = 0; wl_ioctl_t ioctl; + int len; if (pParams) { allocSize = (size + strlen(iovar) + 1); @@ -3961,8 +4210,12 @@ dhd_iscan_issue_request(void * dhdp, wl_iscan_params_t *pParams, uint32 size) goto cleanUp; } ioctl.cmd = WLC_SET_VAR; - bcm_mkiovar(iovar, (char *)pParams, size, buf, allocSize); - rc = dhd_wl_ioctl(dhd, 0, &ioctl, buf, allocSize); + len = bcm_mkiovar(iovar, (char *)pParams, size, buf, allocSize); + if (len == 0) { + rc = BCME_BUFTOOSHORT; + goto cleanUp; + } + rc = dhd_wl_ioctl(dhd, 0, &ioctl, buf, len); } cleanUp: @@ -3984,6 +4237,7 @@ dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) dhd_pub_t *dhd = dhd_bus_pub(dhdp); int rc; wl_ioctl_t ioctl; + int len; DHD_ISCAN(("%s: Enter\n", __FUNCTION__)); @@ -4007,8 +4261,15 @@ dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) memset(&list, 0, sizeof(list)); list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); - bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE, + len = bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); + if (len == 0) { + dhd_iscan_free_buf(dhdp, 0); + dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT); + dhd_ind_scan_confirm(dhdp, FALSE); + status = BCME_BUFTOOSHORT; + goto fail; + } ioctl.cmd = WLC_GET_VAR; ioctl.set = FALSE; rc = dhd_wl_ioctl(dhd, 0, &ioctl, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); @@ -4147,6 +4408,7 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) int dtim_period = 0; int ap_beacon = 0; int allowed_skip_dtim_cnt = 0; + /* Check if associated */ if (dhd_is_associated(dhd, 0, NULL) == FALSE) { DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret)); @@ -4173,7 +4435,8 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) } if (dhd->max_dtim_enable) { - bcn_li_dtim = (int) (MAX_DTIM_ALLOWED_INTERVAL / (ap_beacon * dtim_period)); + bcn_li_dtim = + (int) (MAX_DTIM_ALLOWED_INTERVAL / (ap_beacon * dtim_period)); if (bcn_li_dtim == 0) { bcn_li_dtim = 1; } @@ -4265,8 +4528,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) return res; } #endif /* defined(KEEP_ALIVE) */ - -#define CSCAN_TLV_TYPE_SSID_IE 'S' +#define CSCAN_TLV_TYPE_SSID_IE 'S' /* * SSIDs list parsing from cscan tlv list */ @@ -4341,8 +4603,6 @@ wl_parse_ssid_list_tlv(char** list_str, wlc_ssid_ext_t* ssid, int max, int *byte *list_str = str; return idx; } - -#if defined(WL_WIRELESS_EXT) /* Android ComboSCAN support */ /* @@ -4364,7 +4624,7 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, /* Clean all dest bytes */ memset(dst, 0, dst_size); - while (*bytes_left > 0) { + if (*bytes_left > 0) { if (str[0] != token) { DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n", @@ -4524,61 +4784,10 @@ wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) return num; } -#endif - -#if defined(TRAFFIC_MGMT_DWM) -static int traffic_mgmt_add_dwm_filter(dhd_pub_t *dhd, - trf_mgmt_filter_list_t * trf_mgmt_filter_list, int len) -{ - int ret = 0; - uint32 i; - trf_mgmt_filter_t *trf_mgmt_filter; - uint8 dwm_tbl_entry; - uint32 dscp = 0; - uint16 dwm_filter_enabled = 0; - - - /* Check parameter length is adequate */ - if (len < (OFFSETOF(trf_mgmt_filter_list_t, filter) + - trf_mgmt_filter_list->num_filters * sizeof(trf_mgmt_filter_t))) { - ret = BCME_BUFTOOSHORT; - return ret; - } - - bzero(&dhd->dhd_tm_dwm_tbl, sizeof(dhd_trf_mgmt_dwm_tbl_t)); - - for (i = 0; i < trf_mgmt_filter_list->num_filters; i++) { - trf_mgmt_filter = &trf_mgmt_filter_list->filter[i]; - - dwm_filter_enabled = (trf_mgmt_filter->flags & TRF_FILTER_DWM); - - if (dwm_filter_enabled) { - dscp = trf_mgmt_filter->dscp; - if (dscp >= DHD_DWM_TBL_SIZE) { - ret = BCME_BADARG; - return ret; - } - } - - dhd->dhd_tm_dwm_tbl.dhd_dwm_enabled = 1; - /* set WMM AC bits */ - dwm_tbl_entry = (uint8) trf_mgmt_filter->priority; - DHD_TRF_MGMT_DWM_SET_FILTER(dwm_tbl_entry); - - /* set favored bits */ - if (trf_mgmt_filter->flags & TRF_FILTER_FAVORED) - DHD_TRF_MGMT_DWM_SET_FAVORED(dwm_tbl_entry); - - dhd->dhd_tm_dwm_tbl.dhd_dwm_tbl[dscp] = dwm_tbl_entry; - } - return ret; -} -#endif - /* Given filename and download type, returns a buffer pointer and length - * for download to f/w. Type can be FW or NVRAM. - * - */ +* for download to f/w. Type can be FW or NVRAM. +* +*/ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t component, char ** buffer, int *length) @@ -4590,35 +4799,13 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com uint8 *buf = NULL; /* Point to cache if available. */ -#ifdef CACHE_FW_IMAGES - if (component == FW) { - if (dhd->cached_fw_length) { - len = dhd->cached_fw_length; - buf = dhd->cached_fw; - } - } - else if (component == NVRAM) { - if (dhd->cached_nvram_length) { - len = dhd->cached_nvram_length; - buf = dhd->cached_nvram; - } - } - else if (component == CLM_BLOB) { - if (dhd->cached_clm_length) { - len = dhd->cached_clm_length; - buf = dhd->cached_clm; - } - } else { - return ret; - } -#endif /* CACHE_FW_IMAGES */ /* No Valid cache found on this call */ if (!len) { file_len = *length; *length = 0; if (file_path) { - image = dhd_os_open_image(file_path); + image = dhd_os_open_image1(dhd, file_path); if (image == NULL) { goto err; } @@ -4632,24 +4819,11 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com } /* Download image */ -#if defined(BCMEMBEDIMAGE) && defined(DHD_EFI) - if (!image) { - memcpy(buf, nvram_arr, sizeof(nvram_arr)); - len = sizeof(nvram_arr); - } else { - len = dhd_os_get_image_block((char *)buf, file_len, image); - if ((len <= 0 || len > file_len)) { - MFREE(dhd->osh, buf, file_len); - goto err; - } - } -#else len = dhd_os_get_image_block((char *)buf, file_len, image); if ((len <= 0 || len > file_len)) { MFREE(dhd->osh, buf, file_len); goto err; } -#endif /* DHD_EFI */ } ret = BCME_OK; @@ -4657,30 +4831,10 @@ int dhd_get_download_buffer(dhd_pub_t *dhd, char *file_path, download_type_t com *buffer = (char *)buf; /* Cache if first call. */ -#ifdef CACHE_FW_IMAGES - if (component == FW) { - if (!dhd->cached_fw_length) { - dhd->cached_fw = buf; - dhd->cached_fw_length = len; - } - } - else if (component == NVRAM) { - if (!dhd->cached_nvram_length) { - dhd->cached_nvram = buf; - dhd->cached_nvram_length = len; - } - } - else if (component == CLM_BLOB) { - if (!dhd->cached_clm_length) { - dhd->cached_clm = buf; - dhd->cached_clm_length = len; - } - } -#endif /* CACHE_FW_IMAGES */ err: if (image) - dhd_os_close_image(image); + dhd_os_close_image1(dhd, image); return ret; } @@ -4719,8 +4873,9 @@ dhd_download_2_dongle(dhd_pub_t *dhd, char *iovar, uint16 flag, uint16 dload_typ } int -dhd_download_blob(dhd_pub_t *dhd, unsigned char *image, +dhd_download_blob(dhd_pub_t *dhd, unsigned char *buf, uint32 len, char *iovar) + { int chunk_len; int size2alloc; @@ -4735,14 +4890,13 @@ dhd_download_blob(dhd_pub_t *dhd, unsigned char *image, if ((new_buf = (unsigned char *)MALLOCZ(dhd->osh, size2alloc)) != NULL) { do { chunk_len = dhd_os_get_image_block((char *)(new_buf + data_offset), - MAX_CHUNK_LEN, image); + MAX_CHUNK_LEN, buf); if (chunk_len < 0) { DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, chunk_len)); err = BCME_ERROR; goto exit; } - if (len - chunk_len == 0) dl_flag |= DL_END; @@ -4760,24 +4914,34 @@ exit: if (new_buf) { MFREE(dhd->osh, new_buf, size2alloc); } - return err; } +int +dhd_apply_default_txcap(dhd_pub_t *dhd, char *path) +{ + return 0; +} + int dhd_check_current_clm_data(dhd_pub_t *dhd) { - char iovbuf[WLC_IOCTL_SMLEN] = {0}; + char iovbuf[WLC_IOCTL_SMLEN]; wl_country_t *cspec; int err = BCME_OK; - bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf)); + memset(iovbuf, 0, sizeof(iovbuf)); + err = bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf)); + if (err == 0) { + err = BCME_BUFTOOSHORT; + DHD_ERROR(("%s: bcm_mkiovar failed.", __FUNCTION__)); + return err; + } err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0); if (err) { DHD_ERROR(("%s: country code get failed\n", __FUNCTION__)); return err; } - cspec = (wl_country_t *)iovbuf; if ((strncmp(cspec->ccode, WL_CCODE_NULL_COUNTRY, WLC_CNTRY_BUF_SZ)) == 0) { DHD_ERROR(("%s: ----- This FW is not included CLM data -----\n", @@ -4794,9 +4958,9 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) { char *clm_blob_path; int len; - unsigned char *imgbuf = NULL; + char *memblock = NULL; int err = BCME_OK; - char iovbuf[WLC_IOCTL_SMLEN] = {0}; + char iovbuf[WLC_IOCTL_SMLEN]; int status = FALSE; if (clm_path[0] != '\0') { @@ -4815,9 +4979,8 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) * validate the country code before proceeding with the initialization. * If country code is not valid, fail the initialization. */ - - imgbuf = dhd_os_open_image((char *)clm_blob_path); - if (imgbuf == NULL) { + memblock = dhd_os_open_image1(dhd, (char *)clm_blob_path); + if (memblock == NULL) { #if defined(DHD_BLOB_EXISTENCE_CHECK) if (dhd->is_blob) { err = BCME_ERROR; @@ -4826,16 +4989,16 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) if (status == TRUE) { err = BCME_OK; } else { - err = BCME_ERROR; + err = status; } } #endif /* DHD_BLOB_EXISTENCE_CHECK */ goto exit; } - len = dhd_os_get_image_size(imgbuf); + len = dhd_os_get_image_size(memblock); - if ((len > 0) && (len < MAX_CLM_BUF_SIZE) && imgbuf) { + if ((len > 0) && (len < MAX_CLM_BUF_SIZE) && memblock) { status = dhd_check_current_clm_data(dhd); if (status == TRUE) { #if defined(DHD_BLOB_EXISTENCE_CHECK) @@ -4850,15 +5013,23 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) "new CLM data will be added to the end of existing CLM data!\n", __FUNCTION__)); #endif /* DHD_BLOB_EXISTENCE_CHECK */ + } else if (status != FALSE) { + err = status; + goto exit; } /* Found blob file. Download the file */ - DHD_ERROR(("clm file download from %s \n", clm_blob_path)); - err = dhd_download_blob(dhd, imgbuf, len, "clmload"); + DHD_TRACE(("clm file download from %s \n", clm_blob_path)); + err = dhd_download_blob(dhd, (unsigned char*)memblock, len, "clmload"); if (err) { DHD_ERROR(("%s: CLM download failed err=%d\n", __FUNCTION__, err)); /* Retrieve clmload_status and print */ - bcm_mkiovar("clmload_status", NULL, 0, iovbuf, sizeof(iovbuf)); + memset(iovbuf, 0, sizeof(iovbuf)); + len = bcm_mkiovar("clmload_status", NULL, 0, iovbuf, sizeof(iovbuf)); + if (len == 0) { + err = BCME_BUFTOOSHORT; + goto exit; + } err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0); if (err) { DHD_ERROR(("%s: clmload_status get failed err=%d \n", @@ -4876,7 +5047,7 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) DHD_INFO(("%s: CLM download succeeded \n", __FUNCTION__)); } } else { - DHD_INFO(("Skipping the clm download. len:%d memblk:%p \n", len, imgbuf)); + DHD_INFO(("Skipping the clm download. len:%d memblk:%p \n", len, memblock)); } /* Verify country code */ @@ -4885,12 +5056,12 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path) if (status != TRUE) { /* Country code not initialized or CLM download not proper */ DHD_ERROR(("country code not initialized\n")); - err = BCME_ERROR; + err = status; } exit: - if (imgbuf) { - dhd_os_close_image(imgbuf); + if (memblock) { + dhd_os_close_image1(dhd, memblock); } return err; @@ -4898,9 +5069,6 @@ exit: void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length) { -#ifdef CACHE_FW_IMAGES - return; -#endif MFREE(dhd->osh, buffer, length); } @@ -4910,7 +5078,7 @@ void dhd_free_download_buffer(dhd_pub_t *dhd, void *buffer, int length) ifname, direction ? "TX" : "RX")); /* Parse EAPOL 4 way handshake messages */ void -dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) +dhd_dump_eapol_4way_message(char *ifname, unsigned char *dump_data, bool direction) { unsigned char type; int pair, ack, mic, kerr, req, sec, install; @@ -4982,992 +5150,1180 @@ dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction) } #endif /* DHD_8021X_DUMP */ -#ifdef REPORT_FATAL_TIMEOUTS -void init_dhd_timeouts(dhd_pub_t *pub) -{ - pub->timeout_info = MALLOC(pub->osh, sizeof(timeout_info_t)); - if (pub->timeout_info == NULL) { - DHD_ERROR(("%s: Failed to alloc timeout_info\n", __FUNCTION__)); - } else { - DHD_INFO(("Initializing dhd_timeouts\n")); - pub->timeout_info->scan_timer_lock = dhd_os_spin_lock_init(pub->osh); - pub->timeout_info->join_timer_lock = dhd_os_spin_lock_init(pub->osh); - pub->timeout_info->bus_timer_lock = dhd_os_spin_lock_init(pub->osh); - pub->timeout_info->cmd_timer_lock = dhd_os_spin_lock_init(pub->osh); - pub->timeout_info->scan_timeout_val = SCAN_TIMEOUT_DEFAULT; - pub->timeout_info->join_timeout_val = JOIN_TIMEOUT_DEFAULT; - pub->timeout_info->cmd_timeout_val = CMD_TIMEOUT_DEFAULT; - pub->timeout_info->bus_timeout_val = BUS_TIMEOUT_DEFAULT; - pub->timeout_info->scan_timer_active = FALSE; - pub->timeout_info->join_timer_active = FALSE; - pub->timeout_info->cmd_timer_active = FALSE; - pub->timeout_info->bus_timer_active = FALSE; - pub->timeout_info->cmd_join_error = WLC_SSID_MASK; - pub->timeout_info->cmd_request_id = 0; - } -} - -void -deinit_dhd_timeouts(dhd_pub_t *pub) +#ifdef SHOW_LOGTRACE +int +dhd_parse_logstrs_file(osl_t *osh, char *raw_fmts, int logstrs_size, + dhd_event_log_t *event_log) { - /* stop the join, scan bus, cmd timers - * as failing to do so may cause a kernel panic if - * an rmmod is done - */ - if (!pub->timeout_info) { - DHD_ERROR(("timeout_info pointer is NULL\n")); - ASSERT(0); - return; - } - if (dhd_stop_scan_timer(pub)) { - DHD_ERROR(("dhd_stop_scan_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_bus_timer(pub)) { - DHD_ERROR(("dhd_stop_bus_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_cmd_timer(pub)) { - DHD_ERROR(("dhd_stop_cmd_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_join_timer(pub)) { - DHD_ERROR(("dhd_stop_join_timer failed\n")); - ASSERT(0); - } + uint32 *lognums = NULL; + char *logstrs = NULL; + logstr_trailer_t *trailer = NULL; + int ram_index = 0; + char **fmts = NULL; + int num_fmts = 0; + bool match_fail = TRUE; + int32 i = 0; + uint8 *pfw_id = NULL; + uint32 fwid = 0; + void *file = NULL; + int file_len = 0; + char fwid_str[64]; + uint32 hdr_logstrs_size = 0; + + /* Read last three words in the logstrs.bin file */ + trailer = (logstr_trailer_t *) (raw_fmts + logstrs_size - + sizeof(logstr_trailer_t)); + + if (trailer->log_magic == LOGSTRS_MAGIC) { + /* + * logstrs.bin has a header. + */ + if (trailer->version == 1) { + logstr_header_v1_t *hdr_v1 = (logstr_header_v1_t *) (raw_fmts + + logstrs_size - sizeof(logstr_header_v1_t)); + DHD_INFO(("%s: logstr header version = %u\n", + __FUNCTION__, hdr_v1->version)); + num_fmts = hdr_v1->rom_logstrs_offset / sizeof(uint32); + ram_index = (hdr_v1->ram_lognums_offset - + hdr_v1->rom_lognums_offset) / sizeof(uint32); + lognums = (uint32 *) &raw_fmts[hdr_v1->rom_lognums_offset]; + logstrs = (char *) &raw_fmts[hdr_v1->rom_logstrs_offset]; + hdr_logstrs_size = hdr_v1->logstrs_size; + } else if (trailer->version == 2) { + logstr_header_t *hdr = (logstr_header_t *) (raw_fmts + logstrs_size - + sizeof(logstr_header_t)); + DHD_INFO(("%s: logstr header version = %u; flags = %x\n", + __FUNCTION__, hdr->trailer.version, hdr->trailer.flags)); + + /* For ver. 2 of the header, need to match fwid of + * both logstrs.bin and fw bin + */ - dhd_os_spin_lock_deinit(pub->osh, pub->timeout_info->scan_timer_lock); - dhd_os_spin_lock_deinit(pub->osh, pub->timeout_info->join_timer_lock); - dhd_os_spin_lock_deinit(pub->osh, pub->timeout_info->bus_timer_lock); - dhd_os_spin_lock_deinit(pub->osh, pub->timeout_info->cmd_timer_lock); - MFREE(pub->osh, pub->timeout_info, sizeof(timeout_info_t)); - pub->timeout_info = NULL; -} + /* read the FWID from fw bin */ + file = dhd_os_open_image1(NULL, st_str_file_path); + if (!file) { + DHD_ERROR(("%s: cannot open fw file !\n", __FUNCTION__)); + goto error; + } + file_len = dhd_os_get_image_size(file); + if (file_len <= 0) { + DHD_ERROR(("%s: bad fw file length !\n", __FUNCTION__)); + goto error; + } + /* fwid is at the end of fw bin in string format */ + if (dhd_os_seek_file(file, file_len - 32) < 0) { + DHD_ERROR(("%s: can't seek file \n", __FUNCTION__)); + goto error; + } -static void -dhd_cmd_timeout(void *ctx) -{ - dhd_pub_t *pub = (dhd_pub_t *)ctx; - unsigned long flags; + memset(fwid_str, 0, 64); + if (dhd_os_get_image_block(fwid_str, 32, file) <= 0) { + DHD_ERROR(("%s: read fw file failed !\n", __FUNCTION__)); + goto error; + } + pfw_id = (uint8 *)bcmstrnstr(fwid_str, 64, "FWID: 01-", 9); + if (!pfw_id) { + DHD_ERROR(("%s: could not find id in FW bin!\n", __FUNCTION__)); + goto error; + } + /* search for the '-' in the fw id str, after which the + * actual 4 byte fw id is present + */ + while (pfw_id && *pfw_id != '-') { + ++pfw_id; + } + ++pfw_id; + fwid = bcm_strtoul((char *)pfw_id, NULL, 16); - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ASSERT(0); - return; - } + /* check if fw id in logstrs.bin matches the fw one */ + if (hdr->trailer.fw_id != fwid) { + DHD_ERROR(("%s: logstr id does not match FW!\n", __FUNCTION__)); + goto error; + } - DHD_TIMER_LOCK(pub->timeout_info->cmd_timer_lock, flags); - if (pub->timeout_info && pub->timeout_info->cmd_timer_active) { - DHD_ERROR(("\nERROR COMMAND TIMEOUT TO:%d\n", pub->timeout_info->cmd_timeout_val)); - DHD_TIMER_UNLOCK(pub->timeout_info->cmd_timer_lock, flags); -#ifdef PCIE_OOB - /* Assert device_wake so that UART_Rx is available */ - if (dhd_bus_set_device_wake(pub->bus, TRUE)) { - DHD_ERROR(("%s: dhd_bus_set_device_wake() failed\n", __FUNCTION__)); - ASSERT(0); - } -#endif /* PCIE_OOB */ - if (dhd_stop_cmd_timer(pub)) { - DHD_ERROR(("%s: dhd_stop_cmd_timer() failed\n", __FUNCTION__)); - ASSERT(0); - } - dhd_wakeup_ioctl_event(pub, IOCTL_RETURN_ON_ERROR); - if (!dhd_query_bus_erros(pub)) - dhd_send_trap_to_fw_for_timeout(pub, DHD_REASON_COMMAND_TO); + match_fail = FALSE; + num_fmts = hdr->rom_logstrs_offset / sizeof(uint32); + ram_index = (hdr->ram_lognums_offset - + hdr->rom_lognums_offset) / sizeof(uint32); + lognums = (uint32 *) &raw_fmts[hdr->rom_lognums_offset]; + logstrs = (char *) &raw_fmts[hdr->rom_logstrs_offset]; + hdr_logstrs_size = hdr->logstrs_size; + +error: + if (file) { + dhd_os_close_image1(NULL, file); + } + if (match_fail) { + return BCME_DECERR; + } + } else { + DHD_ERROR(("%s: Invalid logstr version %u\n", __FUNCTION__, + trailer->version)); + return BCME_ERROR; + } + if (logstrs_size != hdr_logstrs_size) { + DHD_ERROR(("%s: bad logstrs_size %d\n", __FUNCTION__, hdr_logstrs_size)); + return BCME_ERROR; + } } else { - DHD_TIMER_UNLOCK(pub->timeout_info->cmd_timer_lock, flags); - } -} - -int -dhd_start_cmd_timer(dhd_pub_t *pub) -{ - int ret = BCME_OK; - unsigned long flags = 0; - uint32 cmd_to_ms; - - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit_null; - } - DHD_TIMER_LOCK(pub->timeout_info->cmd_timer_lock, flags); - cmd_to_ms = pub->timeout_info->cmd_timeout_val; + /* + * Legacy logstrs.bin format without header. + */ + num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32); - if (pub->timeout_info->cmd_timeout_val == 0) { - /* Disable Command timer timeout */ - DHD_INFO(("DHD: Command Timeout Disabled\n")); - goto exit; - } - if (pub->timeout_info->cmd_timer_active) { - DHD_ERROR(("%s:Timer already active\n", __FUNCTION__)); - ret = BCME_ERROR; - ASSERT(0); - } else { - pub->timeout_info->cmd_timer = osl_timer_init(pub->osh, - "cmd_timer", dhd_cmd_timeout, pub); - osl_timer_update(pub->osh, pub->timeout_info->cmd_timer, - cmd_to_ms, 0); - pub->timeout_info->cmd_timer_active = TRUE; - } - if (ret == BCME_OK) { - DHD_INFO(("%s Cmd Timer started\n", __FUNCTION__)); + /* Legacy RAM-only logstrs.bin format: + * - RAM 'lognums' section + * - RAM 'logstrs' section. + * + * 'lognums' is an array of indexes for the strings in the + * 'logstrs' section. The first uint32 is an index to the + * start of 'logstrs'. Therefore, if this index is divided + * by 'sizeof(uint32)' it provides the number of logstr + * entries. + */ + ram_index = 0; + lognums = (uint32 *) raw_fmts; + logstrs = (char *) &raw_fmts[num_fmts << 2]; } -exit: - DHD_TIMER_UNLOCK(pub->timeout_info->cmd_timer_lock, flags); -exit_null: - return ret; -} - -int -dhd_stop_cmd_timer(dhd_pub_t *pub) -{ - int ret = BCME_OK; - unsigned long flags = 0; - - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit; + if (num_fmts) + fmts = MALLOC(osh, num_fmts * sizeof(char *)); + if (fmts == NULL) { + DHD_ERROR(("%s: Failed to allocate fmts memory\n", __FUNCTION__)); + return BCME_ERROR; } - DHD_TIMER_LOCK(pub->timeout_info->cmd_timer_lock, flags); + event_log->fmts_size = num_fmts * sizeof(char *); - if (pub->timeout_info->cmd_timer_active) { - osl_timer_del(pub->osh, pub->timeout_info->cmd_timer); - pub->timeout_info->cmd_timer_active = FALSE; - } - else { - DHD_INFO(("DHD: CMD timer is not active\n")); - } - if (ret == BCME_OK) { - DHD_INFO(("%s Cmd Timer Stopped\n", __FUNCTION__)); + for (i = 0; i < num_fmts; i++) { + /* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base + * (they are 0-indexed relative to 'rom_logstrs_offset'). + * + * RAM lognums are already indexed to point to the correct RAM logstrs (they + * are 0-indexed relative to the start of the logstrs.bin file). + */ + if (i == ram_index) { + logstrs = raw_fmts; + } + fmts[i] = &logstrs[lognums[i]]; } - DHD_TIMER_UNLOCK(pub->timeout_info->cmd_timer_lock, flags); -exit: - return ret; -} + event_log->fmts = fmts; + event_log->raw_fmts_size = logstrs_size; + event_log->raw_fmts = raw_fmts; + event_log->num_fmts = num_fmts; + return BCME_OK; +} /* dhd_parse_logstrs_file */ -static int -__dhd_stop_join_timer(dhd_pub_t *pub) +int dhd_parse_map_file(osl_t *osh, void *file, uint32 *ramstart, uint32 *rodata_start, + uint32 *rodata_end) { - int ret = BCME_OK; - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ASSERT(0); - return BCME_ERROR; - } + char *raw_fmts = NULL, *raw_fmts_loc = NULL; + uint32 read_size = READ_NUM_BYTES; + int error = 0; + char * cptr = NULL; + char c; + uint8 count = 0; - if (pub->timeout_info->join_timer_active) { - osl_timer_del(pub->osh, pub->timeout_info->join_timer); - pub->timeout_info->join_timer_active = FALSE; - } else { - DHD_INFO(("DHD: JOIN timer is not active\n")); - } - if (ret == BCME_OK) { - DHD_INFO(("%s: Join Timer Stopped\n", __FUNCTION__)); + *ramstart = 0; + *rodata_start = 0; + *rodata_end = 0; + + /* Allocate 1 byte more than read_size to terminate it with NULL */ + raw_fmts = MALLOCZ(osh, read_size + 1); + if (raw_fmts == NULL) { + DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__)); + goto fail; } - return ret; -} -static void -dhd_join_timeout(void *ctx) -{ - dhd_pub_t *pub = (dhd_pub_t *)ctx; - unsigned long flags; + /* read ram start, rodata_start and rodata_end values from map file */ + while (count != ALL_MAP_VAL) + { + error = dhd_os_read_file(file, raw_fmts, read_size); + if (error < 0) { + DHD_ERROR(("%s: map file read failed err:%d \n", __FUNCTION__, + error)); + goto fail; + } - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ASSERT(0); - return; - } + /* End raw_fmts with NULL as strstr expects NULL terminated strings */ + raw_fmts[read_size] = '\0'; - DHD_TIMER_LOCK(pub->timeout_info->join_timer_lock, flags); - if (pub->timeout_info->join_timer_active) { - DHD_TIMER_UNLOCK(pub->timeout_info->join_timer_lock, flags); - if (dhd_stop_join_timer(pub)) { - DHD_ERROR(("%s: dhd_stop_join_timer() failed\n", __FUNCTION__)); - ASSERT(0); + /* Get ramstart address */ + raw_fmts_loc = raw_fmts; + if ((cptr = bcmstrnstr(raw_fmts_loc, read_size, ramstart_str, + strlen(ramstart_str)))) { + cptr = cptr - BYTES_AHEAD_NUM; + sscanf(cptr, "%x %c text_start", ramstart, &c); + count |= RAMSTART_BIT; } - if (pub->timeout_info->cmd_join_error) { - DHD_ERROR(("\nERROR JOIN TIMEOUT TO:%d:0x%x\n", - pub->timeout_info->join_timeout_val, - pub->timeout_info->cmd_join_error)); -#ifdef DHD_FW_COREDUMP - /* collect core dump and crash */ - pub->memdump_enabled = DUMP_MEMFILE_BUGON; - pub->memdump_type = DUMP_TYPE_JOIN_TIMEOUT; - dhd_bus_mem_dump(pub); -#endif /* DHD_FW_COREDUMP */ + /* Get ram rodata start address */ + raw_fmts_loc = raw_fmts; + if ((cptr = bcmstrnstr(raw_fmts_loc, read_size, rodata_start_str, + strlen(rodata_start_str)))) { + cptr = cptr - BYTES_AHEAD_NUM; + sscanf(cptr, "%x %c rodata_start", rodata_start, &c); + count |= RDSTART_BIT; } - } else { - DHD_TIMER_UNLOCK(pub->timeout_info->join_timer_lock, flags); - } -} -int -dhd_start_join_timer(dhd_pub_t *pub) -{ - int ret = BCME_OK; - unsigned long flags = 0; - uint32 join_to_ms; + /* Get ram rodata end address */ + raw_fmts_loc = raw_fmts; + if ((cptr = bcmstrnstr(raw_fmts_loc, read_size, rodata_end_str, + strlen(rodata_end_str)))) { + cptr = cptr - BYTES_AHEAD_NUM; + sscanf(cptr, "%x %c rodata_end", rodata_end, &c); + count |= RDEND_BIT; + } - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit; + if (error < (int)read_size) { + /* + * since we reset file pos back to earlier pos by + * GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF. + * The reason for this is if string is spreaded across + * bytes, the read function should not miss it. + * So if ret value is less than read_size, reached EOF don't read further + */ + break; + } + memset(raw_fmts, 0, read_size); + /* + * go back to predefined NUM of bytes so that we won't miss + * the string and addr even if it comes as splited in next read. + */ + dhd_os_seek_file(file, -GO_BACK_FILE_POS_NUM_BYTES); } - join_to_ms = pub->timeout_info->join_timeout_val; - DHD_TIMER_LOCK(pub->timeout_info->join_timer_lock, flags); - if (pub->timeout_info->join_timer_active) { - DHD_ERROR(("%s:Stoping active timer\n", __FUNCTION__)); - __dhd_stop_join_timer(pub); - } - if (pub->timeout_info->join_timeout_val == 0) { - /* Disable Join timer timeout */ - DHD_INFO(("DHD: Join Timeout Disabled\n")); - } else { - pub->timeout_info->join_timer = osl_timer_init(pub->osh, - "join_timer", dhd_join_timeout, pub); - osl_timer_update(pub->osh, pub->timeout_info->join_timer, join_to_ms, 0); - pub->timeout_info->join_timer_active = TRUE; - pub->timeout_info->cmd_join_error |= WLC_SSID_MASK; +fail: + if (raw_fmts) { + MFREE(osh, raw_fmts, read_size + 1); + raw_fmts = NULL; } - if (ret == BCME_OK) { - DHD_INFO(("%s:Join Timer started 0x%x\n", __FUNCTION__, - pub->timeout_info->cmd_join_error)); + if (count == ALL_MAP_VAL) + return BCME_OK; + else { + DHD_ERROR(("%s: readmap error 0X%x \n", __FUNCTION__, + count)); + return BCME_ERROR; } - DHD_TIMER_UNLOCK(pub->timeout_info->join_timer_lock, flags); -exit: - return ret; -} - -int -dhd_stop_join_timer(dhd_pub_t *pub) -{ - int ret = BCME_OK; - unsigned long flags; - - DHD_TIMER_LOCK(pub->timeout_info->join_timer_lock, flags); - ret = __dhd_stop_join_timer(pub); - DHD_TIMER_UNLOCK(pub->timeout_info->join_timer_lock, flags); - return ret; -} - -static void -dhd_scan_timeout(void *ctx) -{ - dhd_pub_t *pub = (dhd_pub_t *)ctx; - unsigned long flags; - if (pub->timeout_info == NULL) { - DHD_ERROR(("timeout_info pointer is NULL\n")); - ASSERT(0); - return; - } - - DHD_TIMER_LOCK(pub->timeout_info->scan_timer_lock, flags); - if (pub->timeout_info && pub->timeout_info->scan_timer_active) { - DHD_ERROR(("\nERROR SCAN TIMEOUT TO:%d\n", pub->timeout_info->scan_timeout_val)); - DHD_TIMER_UNLOCK(pub->timeout_info->scan_timer_lock, flags); - dhd_stop_scan_timer(pub); - if (!dhd_query_bus_erros(pub)) - dhd_send_trap_to_fw_for_timeout(pub, DHD_REASON_SCAN_TO); - } else { - DHD_TIMER_UNLOCK(pub->timeout_info->scan_timer_lock, flags); - } -} +} /* dhd_parse_map_file */ +#ifdef PCIE_FULL_DONGLE int -dhd_start_scan_timer(dhd_pub_t *pub) +dhd_event_logtrace_infobuf_pkt_process(dhd_pub_t *dhdp, void *pktbuf, + dhd_event_log_t *event_data) { - int ret = BCME_OK; - unsigned long flags = 0; - uint32 scan_to_ms; + uint32 infobuf_version; + info_buf_payload_hdr_t *payload_hdr_ptr; + uint16 payload_hdr_type; + uint16 payload_hdr_length; - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit_null; - } - DHD_TIMER_LOCK(pub->timeout_info->scan_timer_lock, flags); - scan_to_ms = pub->timeout_info->scan_timeout_val; + DHD_TRACE(("%s:Enter\n", __FUNCTION__)); - if (pub->timeout_info->scan_timer_active) { - /* NOTE : New scan timeout value will be effective - * only once current scan is completed. - */ - DHD_ERROR(("%s:Timer already active\n", __FUNCTION__)); - ret = BCME_ERROR; + if (PKTLEN(dhdp->osh, pktbuf) < sizeof(uint32)) { + DHD_ERROR(("%s: infobuf too small for version field\n", + __FUNCTION__)); + goto exit; + } + infobuf_version = *((uint32 *)PKTDATA(dhdp->osh, pktbuf)); + PKTPULL(dhdp->osh, pktbuf, sizeof(uint32)); + if (infobuf_version != PCIE_INFOBUF_V1) { + DHD_ERROR(("%s: infobuf version %d is not PCIE_INFOBUF_V1\n", + __FUNCTION__, infobuf_version)); goto exit; } - if (pub->timeout_info->scan_timeout_val == 0) { - /* Disable Scan timer timeout */ - DHD_INFO(("DHD: Scan Timeout Disabled\n")); - } else { - pub->timeout_info->scan_timer = osl_timer_init(pub->osh, "scan_timer", - dhd_scan_timeout, pub); - pub->timeout_info->scan_timer_active = TRUE; - osl_timer_update(pub->osh, pub->timeout_info->scan_timer, scan_to_ms, 0); + /* Version 1 infobuf has a single type/length (and then value) field */ + if (PKTLEN(dhdp->osh, pktbuf) < sizeof(info_buf_payload_hdr_t)) { + DHD_ERROR(("%s: infobuf too small for v1 type/length fields\n", + __FUNCTION__)); + goto exit; } - if (ret == BCME_OK) { - DHD_INFO(("%s Scan Timer started\n", __FUNCTION__)); + /* Process/parse the common info payload header (type/length) */ + payload_hdr_ptr = (info_buf_payload_hdr_t *)PKTDATA(dhdp->osh, pktbuf); + payload_hdr_type = ltoh16(payload_hdr_ptr->type); + payload_hdr_length = ltoh16(payload_hdr_ptr->length); + if (payload_hdr_type != PCIE_INFOBUF_V1_TYPE_LOGTRACE) { + DHD_ERROR(("%s: payload_hdr_type %d is not V1_TYPE_LOGTRACE\n", + __FUNCTION__, payload_hdr_type)); + goto exit; } -exit: - DHD_TIMER_UNLOCK(pub->timeout_info->scan_timer_lock, flags); -exit_null: - return ret; -} - -int -dhd_stop_scan_timer(dhd_pub_t *pub) -{ - int ret = BCME_OK; - unsigned long flags = 0; + PKTPULL(dhdp->osh, pktbuf, sizeof(info_buf_payload_hdr_t)); - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); + /* Validate that the specified length isn't bigger than the + * provided data. + */ + if (payload_hdr_length > PKTLEN(dhdp->osh, pktbuf)) { + DHD_ERROR(("%s: infobuf logtrace length is bigger" + " than actual buffer data\n", __FUNCTION__)); goto exit; } - DHD_TIMER_LOCK(pub->timeout_info->scan_timer_lock, flags); + dhd_dbg_trace_evnt_handler(dhdp, PKTDATA(dhdp->osh, pktbuf), + event_data, payload_hdr_length); - if (pub->timeout_info->scan_timer_active) { - osl_timer_del(pub->osh, pub->timeout_info->scan_timer); - pub->timeout_info->scan_timer_active = FALSE; - } - else { - DHD_INFO(("DHD: SCAN timer is not active\n")); - } + return BCME_OK; - if (ret == BCME_OK) { - DHD_INFO(("%s Scan Timer Stopped\n", __FUNCTION__)); - } - DHD_TIMER_UNLOCK(pub->timeout_info->scan_timer_lock, flags); exit: - return ret; -} - -static void -dhd_bus_timeout(void *ctx) -{ - dhd_pub_t *pub = (dhd_pub_t *)ctx; - unsigned long flags; + return BCME_ERROR; +} /* dhd_event_logtrace_infobuf_pkt_process */ +#endif /* PCIE_FULL_DONGLE */ +#endif /* SHOW_LOGTRACE */ - if (pub->timeout_info == NULL) { - DHD_ERROR(("timeout_info pointer is NULL\n")); - ASSERT(0); - return; - } +#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) - DHD_TIMER_LOCK(pub->timeout_info->bus_timer_lock, flags); - if (pub->timeout_info->bus_timer_active) { - DHD_ERROR(("\nERROR BUS TIMEOUT TO:%d\n", pub->timeout_info->bus_timeout_val)); - DHD_TIMER_UNLOCK(pub->timeout_info->bus_timer_lock, flags); -#ifdef PCIE_OOB - /* Assert device_wake so that UART_Rx is available */ - if (dhd_bus_set_device_wake(pub->bus, TRUE)) { - DHD_ERROR(("%s: dhd_bus_set_device_wake() failed\n", __FUNCTION__)); - ASSERT(0); - } -#endif /* PCIE_OOB */ - if (dhd_stop_bus_timer(pub)) { - DHD_ERROR(("%s: dhd_stop_bus_timer() failed\n", __FUNCTION__)); - ASSERT(0); - } - if (!dhd_query_bus_erros(pub)) - dhd_send_trap_to_fw_for_timeout(pub, DHD_REASON_OQS_TO); - } else { - DHD_TIMER_UNLOCK(pub->timeout_info->bus_timer_lock, flags); - } +/* To handle the TDLS event in the dhd_common.c + */ +int dhd_tdls_event_handler(dhd_pub_t *dhd_pub, wl_event_msg_t *event) +{ + int ret = BCME_OK; +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif // endif + ret = dhd_tdls_update_peer_info(dhd_pub, event); +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) +#pragma GCC diagnostic pop +#endif // endif + return ret; } -int -dhd_start_bus_timer(dhd_pub_t *pub) +int dhd_free_tdls_peer_list(dhd_pub_t *dhd_pub) { - int ret = BCME_OK; - unsigned long flags = 0; - uint32 bus_to_ms; + tdls_peer_node_t *cur = NULL, *prev = NULL; + if (!dhd_pub) + return BCME_ERROR; + cur = dhd_pub->peer_tbl.node; - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit_null; - } - DHD_TIMER_LOCK(pub->timeout_info->bus_timer_lock, flags); - bus_to_ms = pub->timeout_info->bus_timeout_val; + if ((dhd_pub->peer_tbl.node == NULL) && !dhd_pub->peer_tbl.tdls_peer_count) + return BCME_ERROR; - if (pub->timeout_info->bus_timeout_val == 0) { - /* Disable Bus timer timeout */ - DHD_INFO(("DHD: Bus Timeout Disabled\n")); - goto exit; - } - if (pub->timeout_info->bus_timer_active) { - DHD_ERROR(("%s:Timer already active\n", __FUNCTION__)); - ret = BCME_ERROR; - ASSERT(0); - } else { - pub->timeout_info->bus_timer = osl_timer_init(pub->osh, - "bus_timer", dhd_bus_timeout, pub); - pub->timeout_info->bus_timer_active = TRUE; - osl_timer_update(pub->osh, pub->timeout_info->bus_timer, bus_to_ms, 0); - } - if (ret == BCME_OK) { - DHD_INFO(("%s: BUS Timer started\n", __FUNCTION__)); + while (cur != NULL) { + prev = cur; + cur = cur->next; + MFREE(dhd_pub->osh, prev, sizeof(tdls_peer_node_t)); } -exit: - DHD_TIMER_UNLOCK(pub->timeout_info->bus_timer_lock, flags); -exit_null: - return ret; + dhd_pub->peer_tbl.tdls_peer_count = 0; + dhd_pub->peer_tbl.node = NULL; + return BCME_OK; } +#endif /* #if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ -int -dhd_stop_bus_timer(dhd_pub_t *pub) +/* pretty hex print a contiguous buffer +* based on the debug level specified +*/ +void +dhd_prhex(const char *msg, volatile uchar *buf, uint nbytes, uint8 dbg_level) { - int ret = BCME_OK; - unsigned long flags = 0; + char line[128], *p; + int len = sizeof(line); + int nchar; + uint i; - if (!pub->timeout_info) { - DHD_ERROR(("DHD: timeout_info NULL\n")); - ret = BCME_ERROR; - ASSERT(0); - goto exit; + if (msg && (msg[0] != '\0')) { + if (dbg_level == DHD_ERROR_VAL) + DHD_ERROR(("%s:\n", msg)); + else if (dbg_level == DHD_INFO_VAL) + DHD_INFO(("%s:\n", msg)); + else if (dbg_level == DHD_TRACE_VAL) + DHD_TRACE(("%s:\n", msg)); } - DHD_TIMER_LOCK(pub->timeout_info->bus_timer_lock, flags); - if (pub->timeout_info->bus_timer_active) { - osl_timer_del(pub->osh, pub->timeout_info->bus_timer); - pub->timeout_info->bus_timer_active = FALSE; - } - else { - DHD_INFO(("DHD: BUS timer is not active\n")); - } - if (ret == BCME_OK) { - DHD_INFO(("%s: Bus Timer Stopped\n", __FUNCTION__)); - } - DHD_TIMER_UNLOCK(pub->timeout_info->bus_timer_lock, flags); -exit: - return ret; -} + p = line; + for (i = 0; i < nbytes; i++) { + if (i % 16 == 0) { + nchar = snprintf(p, len, " %04x: ", i); /* line prefix */ + p += nchar; + len -= nchar; + } + if (len > 0) { + nchar = snprintf(p, len, "%02x ", buf[i]); + p += nchar; + len -= nchar; + } -int -dhd_set_request_id(dhd_pub_t *pub, uint16 id, uint32 cmd) -{ - DHD_INFO(("%s: id:%d\n", __FUNCTION__, id)); - if (pub->timeout_info) { - pub->timeout_info->cmd_request_id = id; - pub->timeout_info->cmd = cmd; - return BCME_OK; - } else { - return BCME_ERROR; + if (i % 16 == 15) { + /* flush line */ + if (dbg_level == DHD_ERROR_VAL) + DHD_ERROR(("%s:\n", line)); + else if (dbg_level == DHD_INFO_VAL) + DHD_INFO(("%s:\n", line)); + else if (dbg_level == DHD_TRACE_VAL) + DHD_TRACE(("%s:\n", line)); + p = line; + len = sizeof(line); + } } -} -uint16 -dhd_get_request_id(dhd_pub_t *pub) -{ - if (pub->timeout_info) { - return (pub->timeout_info->cmd_request_id); - } else { - return 0; + /* flush last partial line */ + if (p != line) { + if (dbg_level == DHD_ERROR_VAL) + DHD_ERROR(("%s:\n", line)); + else if (dbg_level == DHD_INFO_VAL) + DHD_INFO(("%s:\n", line)); + else if (dbg_level == DHD_TRACE_VAL) + DHD_TRACE(("%s:\n", line)); } } +#ifdef DUMP_IOCTL_IOV_LIST void -dhd_set_join_error(dhd_pub_t *pub, uint32 mask) +dhd_iov_li_append(dhd_pub_t *dhd, dll_t *list_head, dll_t *node) { - DHD_INFO(("Setting join Error %d\n", mask)); - if (pub->timeout_info) { - pub->timeout_info->cmd_join_error |= mask; + dll_t *item; + dhd_iov_li_t *iov_li; + dhd->dump_iovlist_len++; + + if (dhd->dump_iovlist_len == IOV_LIST_MAX_LEN+1) { + item = dll_head_p(list_head); + iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); + dll_delete(item); + MFREE(dhd->osh, iov_li, sizeof(*iov_li)); + dhd->dump_iovlist_len--; } + dll_append(list_head, node); } void -dhd_clear_join_error(dhd_pub_t *pub, uint32 mask) +dhd_iov_li_print(dll_t *list_head) { - DHD_INFO(("clear join Error %d\n", mask)); - if (pub->timeout_info) { - pub->timeout_info->cmd_join_error &= ~mask; + dhd_iov_li_t *iov_li; + dll_t *item, *next; + uint8 index = 0; + for (item = dll_head_p(list_head); !dll_end(list_head, item); item = next) { + next = dll_next_p(item); + iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); + DHD_ERROR(("%d:cmd_name = %s, cmd = %d.\n", ++index, iov_li->buff, iov_li->cmd)); } } void -dhd_get_scan_to_val(dhd_pub_t *pub, uint32 *to_val) +dhd_iov_li_delete(dhd_pub_t *dhd, dll_t *list_head) { - if (pub->timeout_info) { - *to_val = pub->timeout_info->scan_timeout_val; - } else { - *to_val = 0; + dll_t *item; + dhd_iov_li_t *iov_li; + while (!(dll_empty(list_head))) { + item = dll_head_p(list_head); + iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); + dll_delete(item); + MFREE(dhd->osh, iov_li, sizeof(*iov_li)); } } +#endif /* DUMP_IOCTL_IOV_LIST */ -void -dhd_set_scan_to_val(dhd_pub_t *pub, uint32 to_val) -{ - if (pub->timeout_info) { - DHD_INFO(("Setting TO val:%d\n", to_val)); - pub->timeout_info->scan_timeout_val = to_val; - } -} +/* configuations of ecounters to be enabled by default in FW */ +static ecounters_cfg_t ecounters_cfg_tbl[] = { + /* Global ecounters */ + {ECOUNTERS_STATS_TYPES_FLAG_GLOBAL, 0x0, WL_IFSTATS_XTLV_BUS_PCIE}, + // {ECOUNTERS_STATS_TYPES_FLAG_GLOBAL, 0x0, WL_IFSTATS_XTLV_TX_AMPDU_STATS}, + // {ECOUNTERS_STATS_TYPES_FLAG_GLOBAL, 0x0, WL_IFSTATS_XTLV_RX_AMPDU_STATS}, + + /* Slice specific ecounters */ + {ECOUNTERS_STATS_TYPES_FLAG_SLICE, 0x0, WL_SLICESTATS_XTLV_PERIODIC_STATE}, + {ECOUNTERS_STATS_TYPES_FLAG_SLICE, 0x1, WL_SLICESTATS_XTLV_PERIODIC_STATE}, + {ECOUNTERS_STATS_TYPES_FLAG_SLICE, 0x1, WL_IFSTATS_XTLV_WL_SLICE_BTCOEX}, + + /* Interface specific ecounters */ + {ECOUNTERS_STATS_TYPES_FLAG_IFACE, 0x0, WL_IFSTATS_XTLV_IF_PERIODIC_STATE}, + {ECOUNTERS_STATS_TYPES_FLAG_IFACE, 0x0, WL_IFSTATS_XTLV_GENERIC}, + {ECOUNTERS_STATS_TYPES_FLAG_IFACE, 0x0, WL_IFSTATS_XTLV_INFRA_SPECIFIC}, + {ECOUNTERS_STATS_TYPES_FLAG_IFACE, 0x0, WL_IFSTATS_XTLV_MGT_CNT}, + + /* secondary interface */ +}; -void -dhd_get_join_to_val(dhd_pub_t *pub, uint32 *to_val) +static event_ecounters_cfg_t event_ecounters_cfg_tbl[] = { + /* Interface specific event ecounters */ + {WLC_E_LINK, ECOUNTERS_STATS_TYPES_FLAG_IFACE, 0x0, WL_IFSTATS_XTLV_IF_EVENT_STATS}, +}; + +/* Accepts an argument to -s, -g or -f and creates an XTLV */ +int +dhd_create_ecounters_params(dhd_pub_t *dhd, uint16 type, uint16 if_slice_idx, + uint16 stats_rep, uint8 **xtlv) { - if (pub->timeout_info) { - *to_val = pub->timeout_info->join_timeout_val; - } else { - *to_val = 0; + uint8 *req_xtlv = NULL; + ecounters_stats_types_report_req_t *req; + bcm_xtlvbuf_t xtlvbuf, container_xtlvbuf; + ecountersv2_xtlv_list_elt_t temp; + uint16 xtlv_len = 0, total_len = 0; + int rc = BCME_OK; + + /* fill in the stat type XTLV. For now there is no explicit TLV for the stat type. */ + temp.id = stats_rep; + temp.len = 0; + + /* Hence len/data = 0/NULL */ + xtlv_len += temp.len + BCM_XTLV_HDR_SIZE; + + /* Total length of the container */ + total_len = BCM_XTLV_HDR_SIZE + + OFFSETOF(ecounters_stats_types_report_req_t, stats_types_req) + xtlv_len; + + /* Now allocate a structure for the entire request */ + if ((req_xtlv = (uint8 *)MALLOCZ(dhd->osh, total_len)) == NULL) { + rc = BCME_NOMEM; + goto fail; } -} -void -dhd_set_join_to_val(dhd_pub_t *pub, uint32 to_val) -{ - if (pub->timeout_info) { - DHD_INFO(("Setting TO val:%d\n", to_val)); - pub->timeout_info->join_timeout_val = to_val; + /* container XTLV context */ + bcm_xtlv_buf_init(&container_xtlvbuf, (uint8 *)req_xtlv, total_len, + BCM_XTLV_OPTION_ALIGN32); + + /* Fill other XTLVs in the container. Leave space for XTLV headers */ + req = (ecounters_stats_types_report_req_t *)(req_xtlv + BCM_XTLV_HDR_SIZE); + req->flags = type; + if (type == ECOUNTERS_STATS_TYPES_FLAG_SLICE) { + req->slice_mask = 0x1 << if_slice_idx; + } else if (type == ECOUNTERS_STATS_TYPES_FLAG_IFACE) { + req->if_index = if_slice_idx; } -} -void -dhd_get_cmd_to_val(dhd_pub_t *pub, uint32 *to_val) -{ - if (pub->timeout_info) { - *to_val = pub->timeout_info->cmd_timeout_val; - } else { - *to_val = 0; + /* Fill remaining XTLVs */ + bcm_xtlv_buf_init(&xtlvbuf, (uint8*) req->stats_types_req, xtlv_len, + BCM_XTLV_OPTION_ALIGN32); + if (bcm_xtlv_put_data(&xtlvbuf, temp.id, NULL, temp.len)) { + DHD_ERROR(("Error creating XTLV for requested stats type = %d\n", temp.id)); + rc = BCME_ERROR; + goto fail; } -} -void -dhd_set_cmd_to_val(dhd_pub_t *pub, uint32 to_val) -{ - if (pub->timeout_info) { - DHD_INFO(("Setting TO val:%d\n", to_val)); - pub->timeout_info->cmd_timeout_val = to_val; + /* fill the top level container and get done with the XTLV container */ + rc = bcm_xtlv_put_data(&container_xtlvbuf, WL_ECOUNTERS_XTLV_REPORT_REQ, NULL, + bcm_xtlv_buf_len(&xtlvbuf) + OFFSETOF(ecounters_stats_types_report_req_t, + stats_types_req)); + + if (rc) { + DHD_ERROR(("Error creating parent XTLV for type = %d\n", req->flags)); + goto fail; } -} -void -dhd_get_bus_to_val(dhd_pub_t *pub, uint32 *to_val) -{ - if (pub->timeout_info) { - *to_val = pub->timeout_info->bus_timeout_val; - } else { - *to_val = 0; +fail: + if (rc && req_xtlv) { + MFREE(dhd->osh, req_xtlv, total_len); + req_xtlv = NULL; } + + /* update the xtlv pointer */ + *xtlv = req_xtlv; + return rc; } -void -dhd_set_bus_to_val(dhd_pub_t *pub, uint32 to_val) +int +dhd_get_preserve_log_numbers(dhd_pub_t *dhd, uint32 *logset_mask) { - if (pub->timeout_info) { - DHD_INFO(("Setting TO val:%d\n", to_val)); - pub->timeout_info->bus_timeout_val = to_val; + wl_el_set_type_t logset_type, logset_op; + int ret = BCME_ERROR; + int i = 0, err = 0; + + if (!dhd || !logset_mask) + return BCME_BADARG; + + *logset_mask = 0; + memset(&logset_type, 0, sizeof(logset_type)); + memset(&logset_op, 0, sizeof(logset_op)); + logset_type.version = htod16(EVENT_LOG_SET_TYPE_CURRENT_VERSION); + logset_type.len = htod16(sizeof(wl_el_set_type_t)); + for (i = 0; i < WL_MAX_PRESERVE_BUFFER; i++) { + logset_type.set = i; + err = dhd_iovar(dhd, 0, "event_log_set_type", (char *)&logset_type, + sizeof(logset_type), (char *)&logset_op, sizeof(logset_op), FALSE); + /* the iovar may return 'unsupported' error if a log set number is not present + * in the fw, so we should not return on error ! + */ + if (err == BCME_OK && + logset_op.type == EVENT_LOG_SET_TYPE_PRSRV) { + *logset_mask |= 0x01u << i; + ret = BCME_OK; + } } + + return ret; } -#endif /* REPORT_FATAL_TIMEOUTS */ -#ifdef SHOW_LOGTRACE int -dhd_parse_logstrs_file(osl_t *osh, char *raw_fmts, int logstrs_size, - dhd_event_log_t *event_log) +dhd_start_ecounters(dhd_pub_t *dhd) { - logstr_header_t *hdr = NULL; - uint32 *lognums = NULL; - char *logstrs = NULL; - int ram_index = 0; - char **fmts; - int num_fmts = 0; - int32 i = 0; + uint8 i = 0; + uint8 *start_ptr; + int rc = BCME_OK; + bcm_xtlv_t *elt; + ecounters_config_request_v2_t *req = NULL; + ecountersv2_processed_xtlv_list_elt *list_elt, *tail = NULL; + ecountersv2_processed_xtlv_list_elt *processed_containers_list = NULL; + uint16 total_processed_containers_len = 0; + + for (i = 0; i < ARRAYSIZE(ecounters_cfg_tbl); i++) { + ecounters_cfg_t *ecounter_stat = &ecounters_cfg_tbl[i]; + + if ((list_elt = (ecountersv2_processed_xtlv_list_elt *) + MALLOCZ(dhd->osh, sizeof(*list_elt))) == NULL) { + DHD_ERROR(("Ecounters v2: No memory to process\n")); + goto fail; + } - /* Remember header from the logstrs.bin file */ - hdr = (logstr_header_t *) (raw_fmts + logstrs_size - - sizeof(logstr_header_t)); + rc = dhd_create_ecounters_params(dhd, ecounter_stat->type, + ecounter_stat->if_slice_idx, ecounter_stat->stats_rep, &list_elt->data); - if (hdr->log_magic == LOGSTRS_MAGIC) { - /* - * logstrs.bin start with header. - */ - num_fmts = hdr->rom_logstrs_offset / sizeof(uint32); - ram_index = (hdr->ram_lognums_offset - - hdr->rom_lognums_offset) / sizeof(uint32); - lognums = (uint32 *) &raw_fmts[hdr->rom_lognums_offset]; - logstrs = (char *) &raw_fmts[hdr->rom_logstrs_offset]; - - if (logstrs_size != hdr->logstrs_size) { - DHD_ERROR(("%s: bad logstrs_size %d\n", __FUNCTION__, hdr->logstrs_size)); - return BCME_ERROR; + if (rc) { + DHD_ERROR(("Ecounters v2: Could not process: stat: %d return code: %d\n", + ecounter_stat->stats_rep, rc)); + + /* Free allocated memory and go to fail to release any memories allocated + * in previous iterations. Note that list_elt->data gets populated in + * dhd_create_ecounters_params() and gets freed there itself. + */ + MFREE(dhd->osh, list_elt, sizeof(*list_elt)); + list_elt = NULL; + goto fail; } - } else { - /* - * Legacy logstrs.bin format without header. - */ - num_fmts = *((uint32 *) (raw_fmts)) / sizeof(uint32); - if (num_fmts == 0) { - /* Legacy ROM/RAM logstrs.bin format: - * - ROM 'lognums' section - * - RAM 'lognums' section - * - ROM 'logstrs' section. - * - RAM 'logstrs' section. - * - * 'lognums' is an array of indexes for the strings in the - * 'logstrs' section. The first uint32 is 0 (index of first - * string in ROM 'logstrs' section). - * - * The 4324b5 is the only ROM that uses this legacy format. Use the - * fixed number of ROM fmtnums to find the start of the RAM - * 'lognums' section. Use the fixed first ROM string ("Con\n") to - * find the ROM 'logstrs' section. - */ - #define NUM_4324B5_ROM_FMTS 186 - #define FIRST_4324B5_ROM_LOGSTR "Con\n" - ram_index = NUM_4324B5_ROM_FMTS; - lognums = (uint32 *) raw_fmts; - num_fmts = ram_index; - logstrs = (char *) &raw_fmts[num_fmts << 2]; - while (strncmp(FIRST_4324B5_ROM_LOGSTR, logstrs, 4)) { - num_fmts++; - logstrs = (char *) &raw_fmts[num_fmts << 2]; - } + elt = (bcm_xtlv_t *) list_elt->data; + + /* Put the elements in the order they are processed */ + if (processed_containers_list == NULL) { + processed_containers_list = list_elt; } else { - /* Legacy RAM-only logstrs.bin format: - * - RAM 'lognums' section - * - RAM 'logstrs' section. - * - * 'lognums' is an array of indexes for the strings in the - * 'logstrs' section. The first uint32 is an index to the - * start of 'logstrs'. Therefore, if this index is divided - * by 'sizeof(uint32)' it provides the number of logstr - * entries. - */ - ram_index = 0; - lognums = (uint32 *) raw_fmts; - logstrs = (char *) &raw_fmts[num_fmts << 2]; - } + tail->next = list_elt; + } + tail = list_elt; + /* Size of the XTLV returned */ + total_processed_containers_len += BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE; } - fmts = MALLOC(osh, num_fmts * sizeof(char *)); - if (fmts == NULL) { - DHD_ERROR(("%s: Failed to allocate fmts memory\n", __FUNCTION__)); - return BCME_ERROR; + + /* Now create ecounters config request with totallength */ + req = (ecounters_config_request_v2_t *)MALLOCZ(dhd->osh, sizeof(*req) + + total_processed_containers_len); + + if (req == NULL) { + rc = BCME_NOMEM; + goto fail; } - event_log->fmts_size = num_fmts * sizeof(char *); - for (i = 0; i < num_fmts; i++) { - /* ROM lognums index into logstrs using 'rom_logstrs_offset' as a base - * (they are 0-indexed relative to 'rom_logstrs_offset'). - * - * RAM lognums are already indexed to point to the correct RAM logstrs (they - * are 0-indexed relative to the start of the logstrs.bin file). - */ - if (i == ram_index) { - logstrs = raw_fmts; - } - fmts[i] = &logstrs[lognums[i]]; + req->version = ECOUNTERS_VERSION_2; + req->logset = EVENT_LOG_SET_ECOUNTERS; + req->reporting_period = ECOUNTERS_DEFAULT_PERIOD; + req->num_reports = ECOUNTERS_NUM_REPORTS; + req->len = total_processed_containers_len + + OFFSETOF(ecounters_config_request_v2_t, ecounters_xtlvs); + + /* Copy config */ + start_ptr = req->ecounters_xtlvs; + + /* Now go element by element in the list */ + while (processed_containers_list) { + list_elt = processed_containers_list; + + elt = (bcm_xtlv_t *)list_elt->data; + + memcpy(start_ptr, list_elt->data, BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE); + start_ptr += (size_t)(BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE); + processed_containers_list = processed_containers_list->next; + + /* Free allocated memories */ + MFREE(dhd->osh, elt, elt->len + BCM_XTLV_HDR_SIZE); + MFREE(dhd->osh, list_elt, sizeof(*list_elt)); } - event_log->fmts = fmts; - event_log->raw_fmts_size = logstrs_size; - event_log->raw_fmts = raw_fmts; - event_log->num_fmts = num_fmts; - return BCME_OK; + if ((rc = dhd_iovar(dhd, 0, "ecounters", (char *)req, req->len, NULL, 0, TRUE)) < 0) { + DHD_ERROR(("failed to start ecounters\n")); + } + +fail: + if (req) { + MFREE(dhd->osh, req, sizeof(*req) + total_processed_containers_len); + } + + /* Now go element by element in the list */ + while (processed_containers_list) { + list_elt = processed_containers_list; + elt = (bcm_xtlv_t *)list_elt->data; + processed_containers_list = processed_containers_list->next; + + /* Free allocated memories */ + MFREE(dhd->osh, elt, elt->len + BCM_XTLV_HDR_SIZE); + MFREE(dhd->osh, list_elt, sizeof(*list_elt)); + } + return rc; } -int dhd_parse_map_file(osl_t *osh, void *file, uint32 *ramstart, uint32 *rodata_start, - uint32 *rodata_end) +int +dhd_stop_ecounters(dhd_pub_t *dhd) { - char *raw_fmts = NULL; - uint32 read_size = READ_NUM_BYTES; - int error = 0; - char * cptr = NULL; - char c; - uint8 count = 0; + int rc = BCME_OK; + ecounters_config_request_v2_t *req; - *ramstart = 0; - *rodata_start = 0; - *rodata_end = 0; + /* Now create ecounters config request with totallength */ + req = (ecounters_config_request_v2_t *)MALLOCZ(dhd->osh, sizeof(*req)); - /* Allocate 1 byte more than read_size to terminate it with NULL */ - raw_fmts = MALLOC(osh, read_size + 1); - if (raw_fmts == NULL) { - DHD_ERROR(("%s: Failed to allocate raw_fmts memory \n", __FUNCTION__)); + if (req == NULL) { + rc = BCME_NOMEM; goto fail; } - /* read ram start, rodata_start and rodata_end values from map file */ - while (count != ALL_MAP_VAL) - { - error = dhd_os_read_file(file, raw_fmts, read_size); - if (error < 0) { - DHD_ERROR(("%s: map file read failed err:%d \n", __FUNCTION__, - error)); - goto fail; - } + req->version = ECOUNTERS_VERSION_2; + req->len = OFFSETOF(ecounters_config_request_v2_t, ecounters_xtlvs); - /* End raw_fmts with NULL as strstr expects NULL terminated strings */ - raw_fmts[read_size] = '\0'; + if ((rc = dhd_iovar(dhd, 0, "ecounters", (char *)req, req->len, NULL, 0, TRUE)) < 0) { + DHD_ERROR(("failed to stop ecounters\n")); + } - /* Get ramstart address */ - if ((cptr = strstr(raw_fmts, ramstart_str))) { - cptr = cptr - BYTES_AHEAD_NUM; - sscanf(cptr, "%x %c text_start", ramstart, &c); - count |= RAMSTART_BIT; - } +fail: + if (req) { + MFREE(dhd->osh, req, sizeof(*req)); + } + return rc; +} - /* Get ram rodata start address */ - if ((cptr = strstr(raw_fmts, rodata_start_str))) { - cptr = cptr - BYTES_AHEAD_NUM; - sscanf(cptr, "%x %c rodata_start", rodata_start, &c); - count |= RDSTART_BIT; +/* configured event_id_array for event ecounters */ +typedef struct event_id_array { + uint8 event_id; + uint8 str_idx; +} event_id_array_t; + +/* get event id array only from event_ecounters_cfg_tbl[] */ +static inline int __dhd_event_ecounters_get_event_id_array(event_id_array_t *event_array) +{ + uint8 i; + uint8 idx = 0; + int32 prev_evt_id = -1; + + for (i = 0; i < (uint8)ARRAYSIZE(event_ecounters_cfg_tbl); i++) { + if (prev_evt_id != event_ecounters_cfg_tbl[i].event_id) { + if (prev_evt_id >= 0) + idx++; + event_array[idx].event_id = event_ecounters_cfg_tbl[i].event_id; + event_array[idx].str_idx = i; } + prev_evt_id = event_ecounters_cfg_tbl[i].event_id; + } + return idx; +} - /* Get ram rodata end address */ - if ((cptr = strstr(raw_fmts, rodata_end_str))) { - cptr = cptr - BYTES_AHEAD_NUM; - sscanf(cptr, "%x %c rodata_end", rodata_end, &c); - count |= RDEND_BIT; +/* One event id has limit xtlv num to request based on wl_ifstats_xtlv_id * 2 interface */ +#define ECNTRS_MAX_XTLV_NUM (31 * 2) + +int +dhd_start_event_ecounters(dhd_pub_t *dhd) +{ + uint8 i, j = 0; + uint8 event_id_cnt = 0; + uint16 processed_containers_len = 0; + uint16 max_xtlv_len = 0; + int rc = BCME_OK; + uint8 *ptr; + uint8 *data; + event_id_array_t *id_array; + bcm_xtlv_t *elt = NULL; + event_ecounters_config_request_v2_t *req = NULL; + + id_array = (event_id_array_t *)MALLOCZ(dhd->osh, sizeof(event_id_array_t) * + ARRAYSIZE(event_ecounters_cfg_tbl)); + + if (id_array == NULL) { + rc = BCME_NOMEM; + goto fail; + } + event_id_cnt = __dhd_event_ecounters_get_event_id_array(id_array); + + max_xtlv_len = ((BCM_XTLV_HDR_SIZE + + OFFSETOF(event_ecounters_config_request_v2_t, ecounters_xtlvs)) * + ECNTRS_MAX_XTLV_NUM); + + /* Now create ecounters config request with max allowed length */ + req = (event_ecounters_config_request_v2_t *)MALLOCZ(dhd->osh, + sizeof(event_ecounters_config_request_v2_t *) + max_xtlv_len); + + if (req == NULL) { + rc = BCME_NOMEM; + goto fail; + } + + for (i = 0; i <= event_id_cnt; i++) { + /* req initialization by event id */ + req->version = ECOUNTERS_VERSION_2; + req->logset = EVENT_LOG_SET_ECOUNTERS; + req->event_id = id_array[i].event_id; + req->flags = EVENT_ECOUNTERS_FLAGS_ADD; + req->len = 0; + processed_containers_len = 0; + + /* Copy config */ + ptr = req->ecounters_xtlvs; + + for (j = id_array[i].str_idx; j < (uint8)ARRAYSIZE(event_ecounters_cfg_tbl); j++) { + event_ecounters_cfg_t *event_ecounter_stat = &event_ecounters_cfg_tbl[j]; + if (id_array[i].event_id != event_ecounter_stat->event_id) + break; + + rc = dhd_create_ecounters_params(dhd, event_ecounter_stat->type, + event_ecounter_stat->if_slice_idx, event_ecounter_stat->stats_rep, + &data); + + if (rc) { + DHD_ERROR(("%s: Could not process: stat: %d return code: %d\n", + __FUNCTION__, event_ecounter_stat->stats_rep, rc)); + goto fail; + } + + elt = (bcm_xtlv_t *)data; + + memcpy(ptr, elt, BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE); + ptr += (size_t)(BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE); + processed_containers_len += BCM_XTLV_LEN(elt) + BCM_XTLV_HDR_SIZE; + + /* Free allocated memories alloced by dhd_create_ecounters_params */ + MFREE(dhd->osh, elt, elt->len + BCM_XTLV_HDR_SIZE); + + if (processed_containers_len > max_xtlv_len) { + DHD_ERROR(("%s XTLV NUM IS OVERFLOWED THAN ALLOWED!!\n", + __FUNCTION__)); + rc = BCME_BADLEN; + goto fail; + } } - if (error < (int)read_size) { - /* - * since we reset file pos back to earlier pos by - * GO_BACK_FILE_POS_NUM_BYTES bytes we won't reach EOF. - * The reason for this is if string is spreaded across - * bytes, the read function should not miss it. - * So if ret value is less than read_size, reached EOF don't read further - */ - break; + req->len = processed_containers_len + + OFFSETOF(event_ecounters_config_request_v2_t, ecounters_xtlvs); + + DHD_INFO(("%s req version %d logset %d event_id %d flags %d len %d\n", + __FUNCTION__, req->version, req->logset, req->event_id, + req->flags, req->len)); + + rc = dhd_iovar(dhd, 0, "event_ecounters", (char *)req, req->len, NULL, 0, TRUE); + + if (rc < 0) { + DHD_ERROR(("failed to start event_ecounters(event id %d) with rc %d\n", + req->event_id, rc)); + goto fail; } - memset(raw_fmts, 0, read_size); - /* - * go back to predefined NUM of bytes so that we won't miss - * the string and addr even if it comes as splited in next read. - */ - dhd_os_seek_file(file, -GO_BACK_FILE_POS_NUM_BYTES); } - fail: - if (raw_fmts) { - MFREE(osh, raw_fmts, read_size + 1); - raw_fmts = NULL; + /* Free allocated memories */ + if (req) { + MFREE(dhd->osh, req, sizeof(event_ecounters_config_request_v2_t *) + max_xtlv_len); } - if (count == ALL_MAP_VAL) - return BCME_OK; - else { - DHD_ERROR(("%s: readmap error 0X%x \n", __FUNCTION__, - count)); - return BCME_ERROR; + if (id_array) { + MFREE(dhd->osh, id_array, sizeof(event_id_array_t) * + ARRAYSIZE(event_ecounters_cfg_tbl)); } + return rc; } -#ifdef PCIE_FULL_DONGLE + int -dhd_event_logtrace_infobuf_pkt_process(dhd_pub_t *dhdp, void *pktbuf, - dhd_event_log_t *event_data) +dhd_stop_event_ecounters(dhd_pub_t *dhd) { - uint32 infobuf_version; - info_buf_payload_hdr_t *payload_hdr_ptr; - uint16 payload_hdr_type; - uint16 payload_hdr_length; + int rc = BCME_OK; + event_ecounters_config_request_v2_t *req; - DHD_TRACE(("%s:Enter\n", __FUNCTION__)); + /* Now create ecounters config request with totallength */ + req = (event_ecounters_config_request_v2_t *)MALLOCZ(dhd->osh, sizeof(*req)); - if (PKTLEN(dhdp->osh, pktbuf) < sizeof(uint32)) { - DHD_ERROR(("%s: infobuf too small for version field\n", - __FUNCTION__)); - goto exit; - } - infobuf_version = *((uint32 *)PKTDATA(dhdp->osh, pktbuf)); - PKTPULL(dhdp->osh, pktbuf, sizeof(uint32)); - if (infobuf_version != PCIE_INFOBUF_V1) { - DHD_ERROR(("%s: infobuf version %d is not PCIE_INFOBUF_V1\n", - __FUNCTION__, infobuf_version)); - goto exit; + if (req == NULL) { + rc = BCME_NOMEM; + goto fail; } - /* Version 1 infobuf has a single type/length (and then value) field */ - if (PKTLEN(dhdp->osh, pktbuf) < sizeof(info_buf_payload_hdr_t)) { - DHD_ERROR(("%s: infobuf too small for v1 type/length fields\n", - __FUNCTION__)); - goto exit; + req->version = ECOUNTERS_VERSION_2; + req->flags = EVENT_ECOUNTERS_FLAGS_DEL_ALL; + req->len = OFFSETOF(event_ecounters_config_request_v2_t, ecounters_xtlvs); + + if ((rc = dhd_iovar(dhd, 0, "event_ecounters", (char *)req, req->len, NULL, 0, TRUE)) < 0) { + DHD_ERROR(("failed to stop event_ecounters\n")); } - /* Process/parse the common info payload header (type/length) */ - payload_hdr_ptr = (info_buf_payload_hdr_t *)PKTDATA(dhdp->osh, pktbuf); - payload_hdr_type = ltoh16(payload_hdr_ptr->type); - payload_hdr_length = ltoh16(payload_hdr_ptr->length); - if (payload_hdr_type != PCIE_INFOBUF_V1_TYPE_LOGTRACE) { - DHD_ERROR(("%s: payload_hdr_type %d is not V1_TYPE_LOGTRACE\n", - __FUNCTION__, payload_hdr_type)); - goto exit; + +fail: + if (req) { + MFREE(dhd->osh, req, sizeof(*req)); } - PKTPULL(dhdp->osh, pktbuf, sizeof(info_buf_payload_hdr_t)); + return rc; +} - /* Validate that the specified length isn't bigger than the - * provided data. +#ifdef DHD_LOG_DUMP +int +dhd_log_dump_ring_to_file(dhd_pub_t *dhdp, void *ring_ptr, void *file, + unsigned long *file_posn, log_dump_section_hdr_t *sec_hdr) +{ + uint32 rlen = 0; + uint32 data_len = 0, total_len = 0; + void *data = NULL; + unsigned long fpos_sechdr = 0; + unsigned long flags = 0; + int ret = 0; + dhd_dbg_ring_t *ring = (dhd_dbg_ring_t *)ring_ptr; + + if (!dhdp || !ring || !file || !sec_hdr || !file_posn) + return BCME_BADARG; + + /* do not allow further writes to the ring + * till we flush it */ - if (payload_hdr_length > PKTLEN(dhdp->osh, pktbuf)) { - DHD_ERROR(("%s: infobuf logtrace length is bigger" - " than actual buffer data\n", __FUNCTION__)); - goto exit; + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->state = RING_SUSPEND; + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + if (dhdp->concise_dbg_buf) { + /* re-use concise debug buffer temporarily + * to pull ring data, to write + * record by record to file + */ + data_len = CONCISE_DUMP_BUFLEN; + data = dhdp->concise_dbg_buf; + dhd_os_write_file_posn(file, file_posn, ECNTRS_LOG_HDR, + strlen(ECNTRS_LOG_HDR)); + /* write the section header now with zero length, + * once the correct length is found out, update + * it later + */ + fpos_sechdr = *file_posn; + sec_hdr->type = LOG_DUMP_SECTION_ECNTRS; + sec_hdr->length = 0; + dhd_os_write_file_posn(file, file_posn, (char *)sec_hdr, + sizeof(*sec_hdr)); + do { + rlen = dhd_dbg_ring_pull_single(ring, data, data_len, TRUE); + if (rlen > 0) { + /* write the log */ + ret = dhd_os_write_file_posn(file, file_posn, data, rlen); + if (ret < 0) { + DHD_ERROR(("%s: write file error !\n", __FUNCTION__)); + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->state = RING_ACTIVE; + DHD_DBG_RING_UNLOCK(ring->lock, flags); + return BCME_ERROR; + } + } + total_len += rlen; + } while (rlen > 0); + /* now update the section header length in the file */ + sec_hdr->length = total_len; + dhd_os_write_file_posn(file, &fpos_sechdr, (char *)sec_hdr, sizeof(*sec_hdr)); + } else { + DHD_ERROR(("%s: No concise buffer available !\n", __FUNCTION__)); } - dhd_dbg_trace_evnt_handler(dhdp, PKTDATA(dhdp->osh, pktbuf), - event_data, payload_hdr_length); - return BCME_OK; + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->state = RING_ACTIVE; + DHD_DBG_RING_UNLOCK(ring->lock, flags); -exit: - return BCME_ERROR; + return BCME_OK; } -#endif /* PCIE_FULL_DONGLE */ -#endif /* SHOW_LOGTRACE */ -#if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) - -/* To handle the TDLS event in the dhd_common.c - */ -int dhd_tdls_event_handler(dhd_pub_t *dhd_pub, wl_event_msg_t *event) +/* logdump cookie */ +#define MAX_LOGUDMP_COOKIE_CNT 10u +#define LOGDUMP_COOKIE_STR_LEN 50u +int +dhd_logdump_cookie_init(dhd_pub_t *dhdp, uint8 *buf, uint32 buf_size) { - int ret = BCME_OK; -#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-qual" -#endif - ret = dhd_tdls_update_peer_info(dhd_pub, event); -#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) -#pragma GCC diagnostic pop -#endif - return ret; -} + uint32 ring_size; -int dhd_free_tdls_peer_list(dhd_pub_t *dhd_pub) -{ - tdls_peer_node_t *cur = NULL, *prev = NULL; - if (!dhd_pub) + if (!dhdp || !buf) { + DHD_ERROR(("INVALID PTR: dhdp:%p buf:%p\n", dhdp, buf)); return BCME_ERROR; - cur = dhd_pub->peer_tbl.node; + } - if ((dhd_pub->peer_tbl.node == NULL) && !dhd_pub->peer_tbl.tdls_peer_count) + ring_size = dhd_ring_get_hdr_size() + LOGDUMP_COOKIE_STR_LEN * MAX_LOGUDMP_COOKIE_CNT; + if (buf_size < ring_size) { + DHD_ERROR(("BUF SIZE IS TO SHORT: req:%d buf_size:%d\n", + ring_size, buf_size)); return BCME_ERROR; + } - while (cur != NULL) { - prev = cur; - cur = cur->next; - MFREE(dhd_pub->osh, prev, sizeof(tdls_peer_node_t)); + dhdp->logdump_cookie = dhd_ring_init(buf, buf_size, + LOGDUMP_COOKIE_STR_LEN, MAX_LOGUDMP_COOKIE_CNT); + if (!dhdp->logdump_cookie) { + DHD_ERROR(("FAIL TO INIT COOKIE RING\n")); + return BCME_ERROR; } - dhd_pub->peer_tbl.tdls_peer_count = 0; - dhd_pub->peer_tbl.node = NULL; + return BCME_OK; } -#endif /* #if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) */ -/* pretty hex print a contiguous buffer - * based on the debug level specified - */ void -dhd_prhex(const char *msg, volatile uchar *buf, uint nbytes, uint8 dbg_level) +dhd_logdump_cookie_deinit(dhd_pub_t *dhdp) { - char line[128], *p; - int len = sizeof(line); - int nchar; - uint i; + if (!dhdp) { + return; + } + if (dhdp->logdump_cookie) { + dhd_ring_deinit(dhdp->logdump_cookie); + } - if (msg && (msg[0] != '\0')) { - if (dbg_level == DHD_ERROR_VAL) - DHD_ERROR(("%s:\n", msg)); - else if (dbg_level == DHD_INFO_VAL) - DHD_INFO(("%s:\n", msg)); - else if (dbg_level == DHD_TRACE_VAL) - DHD_TRACE(("%s:\n", msg)); + return; +} + +void +dhd_logdump_cookie_save(dhd_pub_t *dhdp, char *cookie, char *type) +{ + char *ptr; + + if (!dhdp || !cookie || !type || !dhdp->logdump_cookie) { + DHD_ERROR(("%s: At least one buffer ptr is NULL dhdp=%p cookie=%p" + " type = %p, cookie_cfg:%p\n", __FUNCTION__, + dhdp, cookie, type, dhdp?dhdp->logdump_cookie: NULL)); + return; } + ptr = (char *)dhd_ring_get_empty(dhdp->logdump_cookie); + if (ptr == NULL) { + DHD_ERROR(("%s : Skip to save due to locking\n", __FUNCTION__)); + return; + } + scnprintf(ptr, LOGDUMP_COOKIE_STR_LEN, "%s: %s\n", type, cookie); + return; +} - p = line; - for (i = 0; i < nbytes; i++) { - if (i % 16 == 0) { - nchar = snprintf(p, len, " %04x: ", i); /* line prefix */ - p += nchar; - len -= nchar; - } - if (len > 0) { - nchar = snprintf(p, len, "%02x ", buf[i]); - p += nchar; - len -= nchar; - } +int +dhd_logdump_cookie_get(dhd_pub_t *dhdp, char *ret_cookie, uint32 buf_size) +{ + char *ptr; - if (i % 16 == 15) { - /* flush line */ - if (dbg_level == DHD_ERROR_VAL) - DHD_ERROR(("%s:\n", line)); - else if (dbg_level == DHD_INFO_VAL) - DHD_INFO(("%s:\n", line)); - else if (dbg_level == DHD_TRACE_VAL) - DHD_TRACE(("%s:\n", line)); - p = line; - len = sizeof(line); - } + if (!dhdp || !ret_cookie || !dhdp->logdump_cookie) { + DHD_ERROR(("%s: At least one buffer ptr is NULL dhdp=%p" + "cookie=%p cookie_cfg:%p\n", __FUNCTION__, + dhdp, ret_cookie, dhdp?dhdp->logdump_cookie: NULL)); + return BCME_ERROR; + } + ptr = (char *)dhd_ring_get_first(dhdp->logdump_cookie); + if (ptr == NULL) { + DHD_ERROR(("%s : Skip to save due to locking\n", __FUNCTION__)); + return BCME_ERROR; } + memcpy(ret_cookie, ptr, MIN(buf_size, strlen(ptr))); + dhd_ring_free_first(dhdp->logdump_cookie); + return BCME_OK; +} - /* flush last partial line */ - if (p != line) { - if (dbg_level == DHD_ERROR_VAL) - DHD_ERROR(("%s:\n", line)); - else if (dbg_level == DHD_INFO_VAL) - DHD_INFO(("%s:\n", line)); - else if (dbg_level == DHD_TRACE_VAL) - DHD_TRACE(("%s:\n", line)); +int +dhd_logdump_cookie_count(dhd_pub_t *dhdp) +{ + if (!dhdp || !dhdp->logdump_cookie) { + DHD_ERROR(("%s: At least one buffer ptr is NULL dhdp=%p cookie=%p\n", + __FUNCTION__, dhdp, dhdp?dhdp->logdump_cookie: NULL)); + return 0; } + return dhd_ring_get_cur_size(dhdp->logdump_cookie); } -#ifdef DUMP_IOCTL_IOV_LIST -void -dhd_iov_li_append(dhd_pub_t *dhd, dll_t *list_head, dll_t *node) +static inline int +__dhd_log_dump_cookie_to_file( + dhd_pub_t *dhdp, void *fp, unsigned long *f_pos, char *buf, uint32 buf_size) { - dll_t *item; - dhd_iov_li_t *iov_li; - dhd->dump_iovlist_len++; - if (dhd->dump_iovlist_len == IOV_LIST_MAX_LEN+1) { - item = dll_head_p(list_head); - iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); - dll_delete(item); - MFREE(dhd->osh, iov_li, sizeof(*iov_li)); - dhd->dump_iovlist_len--; + uint32 remain = buf_size; + int ret = BCME_ERROR; + char tmp_buf[LOGDUMP_COOKIE_STR_LEN]; + log_dump_section_hdr_t sec_hdr; + while (dhd_logdump_cookie_count(dhdp) > 0) { + memset(tmp_buf, 0, sizeof(tmp_buf)); + ret = dhd_logdump_cookie_get(dhdp, tmp_buf, LOGDUMP_COOKIE_STR_LEN); + if (ret != BCME_OK) { + return ret; + } + remain -= scnprintf(&buf[buf_size - remain], remain, "%s", tmp_buf); } - dll_append(list_head, node); + ret = dhd_os_write_file_posn(fp, f_pos, COOKIE_LOG_HDR, strlen(COOKIE_LOG_HDR)); + if (ret < 0) { + DHD_ERROR(("%s : Write file Error for cookie hdr\n", __FUNCTION__)); + return ret; + } + sec_hdr.magic = LOG_DUMP_MAGIC; + sec_hdr.timestamp = local_clock(); + sec_hdr.type = LOG_DUMP_SECTION_COOKIE; + sec_hdr.length = buf_size - remain; + ret = dhd_os_write_file_posn(fp, f_pos, (char *)&sec_hdr, sizeof(sec_hdr)); + if (ret < 0) { + DHD_ERROR(("%s : Write file Error for section hdr\n", __FUNCTION__)); + return ret; + } + + ret = dhd_os_write_file_posn(fp, f_pos, buf, sec_hdr.length); + if (ret < 0) { + DHD_ERROR(("%s : Write file Error for cookie data\n", __FUNCTION__)); + } + + return ret; } -void -dhd_iov_li_print(dll_t *list_head) +int +dhd_log_dump_cookie_to_file(dhd_pub_t *dhdp, void *fp, unsigned long *f_pos) { - dhd_iov_li_t *iov_li; - dll_t *item, *next; - uint8 index = 0; - for (item = dll_head_p(list_head); !dll_end(list_head, item); item = next) { - next = dll_next_p(item); - iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); - index++; - DHD_ERROR(("%d:cmd_name = %s, cmd = %d.\n", index, iov_li->buff, iov_li->cmd)); + char *buf; + int ret = BCME_ERROR; + uint32 buf_size = MAX_LOGUDMP_COOKIE_CNT * LOGDUMP_COOKIE_STR_LEN; + + if (!dhdp || !dhdp->logdump_cookie ||!fp || !f_pos) { + DHD_ERROR(("%s At least one ptr is NULL " + "dhdp = %p cookie %p fp = %p f_pos = %p\n", + __FUNCTION__, dhdp, dhdp?dhdp->logdump_cookie:NULL, fp, f_pos)); + return ret; } + + buf = (char *)MALLOCZ(dhdp->osh, buf_size); + if (!buf) { + DHD_ERROR(("%s Fail to malloc buffer\n", __FUNCTION__)); + return ret; + } + ret = __dhd_log_dump_cookie_to_file(dhdp, fp, f_pos, buf, buf_size); + MFREE(dhdp->osh, buf, buf_size); + + return ret; } -void -dhd_iov_li_delete(dhd_pub_t *dhd, dll_t *list_head) +#endif /* DHD_LOG_DUMP */ + +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT +static void +copy_hang_info_ioctl_timeout(dhd_pub_t *dhd, int ifidx, wl_ioctl_t *ioc) { - dll_t *item; - dhd_iov_li_t *iov_li; - while (!(dll_empty(list_head))) { - item = dll_head_p(list_head); - iov_li = (dhd_iov_li_t *)CONTAINEROF(item, dhd_iov_li_t, list); - dll_delete(item); - MFREE(dhd->osh, iov_li, sizeof(*iov_li)); + int remain_len; + int i; + int *cnt; + char *dest; + int bytes_written; + const uint32 *ioc_buf; + + if (!dhd || !dhd->hang_info) { + DHD_ERROR(("%s dhd=%p hang_info=%p\n", + __FUNCTION__, dhd, (dhd ? dhd->hang_info : NULL))); + return; } + + cnt = &dhd->hang_info_cnt; + dest = dhd->hang_info; + + memset(dest, 0, VENDOR_SEND_HANG_EXT_INFO_LEN); + (*cnt) = 0; + + bytes_written = 0; + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written; + + get_debug_dump_time(dhd->debug_dump_time_hang_str); + copy_debug_dump_time(dhd->debug_dump_time_str, dhd->debug_dump_time_hang_str); + + bytes_written += scnprintf(&dest[bytes_written], remain_len, "%d %d %s %d %d %d %d %d %d ", + HANG_REASON_IOCTL_RESP_TIMEOUT, VENDOR_SEND_HANG_EXT_INFO_VER, + dhd->debug_dump_time_hang_str, + ifidx, ioc->cmd, ioc->len, ioc->set, ioc->used, ioc->needed); + (*cnt) = HANG_FIELD_IOCTL_RESP_TIMEOUT_CNT; + + clear_debug_dump_time(dhd->debug_dump_time_hang_str); + + ioc_buf = (const uint32 *)ioc->buf; + + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written; + bytes_written += scnprintf(&dest[bytes_written], remain_len, + "%08x", *(uint32 *)(ioc_buf++)); + (*cnt)++; + if ((*cnt) >= HANG_FIELD_CNT_MAX) { + return; + } + + for (i = 1; i < (uint32)(ioc->len / sizeof(uint32)) && *cnt <= HANG_FIELD_CNT_MAX; + i++, (*cnt)++) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - bytes_written; + bytes_written += scnprintf(&dest[bytes_written], remain_len, "%c%08x", + HANG_RAW_DEL, *(uint32 *)(ioc_buf++)); + } + + DHD_INFO(("%s hang info len: %d data: %s\n", + __FUNCTION__, (int)strlen(dhd->hang_info), dhd->hang_info)); } -#endif /* DUMP_IOCTL_IOV_LIST */ +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_cis.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_cis.c index 8b3d54f210bce4eb4847caaab0bd56d0aa754901..dc8f6d520358867a4a9961574f8d4e417f373d7b 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_cis.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_cis.c @@ -2,14 +2,14 @@ * Process CIS information from OTP for customer platform * (Handle the MAC address and module information) * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dhd_custom_cis.c 699163 2017-05-12 05:18:23Z $ + * $Id: dhd_custom_cis.c 734083 2017-12-01 05:44:24Z $ */ #include @@ -47,14 +47,11 @@ #ifdef DHD_USE_CISINFO /* File Location to keep each information */ -#define MACINFO PLATFORM_PATH".mac.info" -#define CIDINFO PLATFORM_PATH".cid.info" -#define REVINFO PLATFORM_PATH".rev" -#ifdef PLATFORM_SLP -#define MACINFO_EFS "/csa/.mac.info" -#else +#define MACINFO "/data/.mac.info" #define MACINFO_EFS "/efs/wifi/.mac.info" -#endif /* PLATFORM_SLP */ +#define CIDINFO "/data/misc/conn/.cid.info" +#define CIDINFO_DATA "/data/.cid.info" +#define REVINFO "/data/.rev" /* Definitions for MAC address */ #define MAC_BUF_SIZE 20 @@ -62,17 +59,13 @@ #define MAC_OUTPUT_FORMAT "%02X:%02X:%02X:%02X:%02X:%02X\n" /* Definitions for CIS information */ -#ifdef BCM4330_CHIP -#define CIS_BUF_SIZE 128 -#elif defined(BCM4334_CHIP) -#define CIS_BUF_SIZE 256 -#elif defined(BCM4359_CHIP) +#if defined(BCM4359_CHIP) #define CIS_BUF_SIZE 1280 #elif defined(BCM4361_CHIP) #define CIS_BUF_SIZE 1280 #else #define CIS_BUF_SIZE 512 -#endif /* BCM4330_CHIP */ +#endif /* BCM4359_CHIP */ #define CIS_TUPLE_TAG_START 0x80 #define CIS_TUPLE_TAG_VENDOR 0x81 @@ -309,10 +302,6 @@ dhd_set_macaddr_from_file(dhd_pub_t *dhdp) return BCME_ERROR; } - if (!filepath_efs) { - filepath_efs = MACINFO; - } - memset(mac_buf, 0, sizeof(mac_buf)); /* Read MAC address from the specified file */ @@ -436,10 +425,6 @@ dhd_check_module_mac(dhd_pub_t *dhdp) mac = &dhdp->mac; memset(otp_mac_buf, 0, sizeof(otp_mac_buf)); - if (!filepath_efs) { - filepath_efs = MACINFO; - } - if (!g_have_cis_dump) { DHD_INFO(("%s: Couldn't read CIS information\n", __FUNCTION__)); @@ -621,20 +606,7 @@ typedef struct { char cid_info[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[] = { - { 6, { 0x00, 0x00, 0x00, 0x33, 0x33, }, { "semco" } }, - { 6, { 0x00, 0x00, 0x00, 0xfb, 0x50, }, { "semcosh" } }, - { 6, { 0x00, 0x20, 0xc7, 0x00, 0x00, }, { "murata" } }, - { 0, { 0x00, }, { "murata" } } -}; -#elif defined(BCM4335_CHIP) +#if defined(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 */ @@ -728,6 +700,8 @@ vid_info_t vid_info[] = { { 3, { 0x71, 0x33, }, { "semco_sky_r01h_e32_b0" } }, { 3, { 0x81, 0x33, }, { "semco_sem_r01i_e32_b0" } }, { 3, { 0x82, 0x33, }, { "semco_sem_r02j_e32_b0" } }, + { 3, { 0x91, 0x33, }, { "semco_sem_r02a_e32a_b2" } }, + { 3, { 0xa1, 0x33, }, { "semco_sem_r02b_e32a_b2" } }, { 3, { 0x12, 0x22, }, { "murata_nxp_r012_1kl_a1" } }, { 3, { 0x13, 0x22, }, { "murata_mur_r013_1kl_b0" } }, { 3, { 0x14, 0x22, }, { "murata_mur_r014_1kl_b0" } }, @@ -742,6 +716,12 @@ vid_info_t vid_info[] = { { 3, { 0x32, 0x22, }, { "murata_mur_r032_1kl_b0" } }, { 3, { 0x33, 0x22, }, { "murata_mur_r033_1kl_b0" } }, { 3, { 0x34, 0x22, }, { "murata_mur_r034_1kl_b0" } }, + { 3, { 0x50, 0x22, }, { "murata_mur_r020_1qw_b2" } }, + { 3, { 0x51, 0x22, }, { "murata_mur_r021_1qw_b2" } }, + { 3, { 0x52, 0x22, }, { "murata_mur_r022_1qw_b2" } }, + { 3, { 0x61, 0x22, }, { "murata_mur_r031_1qw_b2" } }, + { 3, { 0x62, 0x22, }, { "murata_mur_r032_1qw_b2" } }, + { 3, { 0x71, 0x22, }, { "murata_mur_r041_1qw_b2" } }, { 0, { 0x00, }, { "samsung" } } /* Default: Not specified yet */ #endif /* SUPPORT_BCM4359_MIXED_MODULES */ }; @@ -812,16 +792,10 @@ dhd_check_module_cid(dhd_pub_t *dhdp) unsigned char *btype_start; unsigned char boardtype_len = 0; #endif /* SUPPORT_MULTIPLE_BOARDTYPE */ -#if defined(BCM4334_CHIP) || defined(BCM4335_CHIP) +#if defined(BCM4335_CHIP) const char *revfilepath = REVINFO; -#ifdef BCM4334_CHIP - unsigned char otp_buf[CIS_BUF_SIZE]; - cis_rw_t *cish; - int flag_b3; -#else char rev_str[10] = {0}; -#endif /* BCM4334_CHIP */ -#endif /* BCM4334_CHIP || BCM4335_CHIP */ +#endif /* BCM4335_CHIP */ /* Try reading out from CIS */ if (!g_have_cis_dump) { @@ -927,33 +901,6 @@ write_cid: DHD_INFO(("%s: CIS MATCH FOUND : %s\n", __FUNCTION__, cid_info)); dhd_write_file(cidfilepath, cid_info, strlen(cid_info) + 1); -#ifdef BCM4334_CHIP - /* Try reading out from OTP to distinguish B2 or B3 */ - memset(otp_buf, 0, sizeof(otp_buf)); - cish = (cis_rw_t *)&otp_buf[8]; - - cish->source = 0; - cish->byteoff = 0; - cish->nbytes = sizeof(otp_buf); - - strcpy(otp_buf, "otpdump"); - ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, otp_buf, - sizeof(otp_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 */ - otp_buf[34] = '\0'; - flag_b3 = bcm_atoi(&otp_buf[33]); - if (flag_b3 & 0x1) { - DHD_ERROR(("%s: REV MATCH FOUND : 4334B3, %c\n", - __FUNCTION__, otp_buf[33])); - dhd_write_cid_file(revfilepath, "4334B3", 6); - } -#endif /* BCM4334_CHIP */ #ifdef BCM4335_CHIP DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); if (concate_revision(dhdp->bus, rev_str, rev_str) < 0) { diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_exynos.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_exynos.c index f8c63e43f3fd792e15f0e83056d8fe00b0f3877e..674731daa7708c24df7d5de57cc0405a27ca272b 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_exynos.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_exynos.c @@ -1,14 +1,14 @@ /* * Platform Dependent file for Samsung Exynos * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,14 +16,14 @@ * 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_custom_exynos.c 731653 2017-11-14 03:29:19Z $ + * $Id: dhd_custom_exynos.c 729025 2017-10-30 03:31:19Z $ */ #include #include @@ -47,9 +47,9 @@ #include #include #include -#if defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) #include -#endif /* CONFIG_SOC_EXYNOS8895 */ +#endif /* CONFIG_SOC_EXYNOS8895 || defined(CONFIG_SOC_EXYNOS9810) */ #if defined(CONFIG_64BIT) #include @@ -63,7 +63,6 @@ defined(CONFIG_MACH_UNIVERSAL5422) #include #endif /* CONFIG_MACH_UNIVERSAL7580 || CONFIG_MACH_UNIVERSAL5430 || CONFIG_MACH_UNIVERSAL5422 */ - #include #ifdef CONFIG_MACH_A7LTE @@ -92,31 +91,26 @@ extern struct device *mmc_dev_for_wlan; #ifdef EXYNOS_PCIE_RC_ONOFF #ifdef CONFIG_MACH_UNIVERSAL5433 #define SAMSUNG_PCIE_CH_NUM -#elif defined(CONFIG_MACH_UNIVERSAL7420) -#define SAMSUNG_PCIE_CH_NUM 1 -#elif defined(CONFIG_MACH_EXSOM7420) +#elif defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_MACH_EXSOM7420) #define SAMSUNG_PCIE_CH_NUM 1 -#elif defined(CONFIG_SOC_EXYNOS8890) -#define SAMSUNG_PCIE_CH_NUM 0 -#elif defined(CONFIG_SOC_EXYNOS8895) +#elif defined(CONFIG_SOC_EXYNOS8890)|| defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) #define SAMSUNG_PCIE_CH_NUM 0 -#endif +#endif // endif #ifdef CONFIG_MACH_UNIVERSAL5433 -extern void exynos_pcie_poweron(void); -extern void exynos_pcie_poweroff(void); +extern void exynos_pcie_pm_resume(void); +extern void exynos_pcie_pm_suspend(void); #else -extern void exynos_pcie_poweron(int); -extern void exynos_pcie_poweroff(int); +extern void exynos_pcie_pm_resume(int); +extern void exynos_pcie_pm_suspend(int); #endif /* CONFIG_MACH_UNIVERSAL5433 */ #endif /* EXYNOS_PCIE_RC_ONOFF */ #if (defined(CONFIG_MACH_UNIVERSAL3475) || defined(CONFIG_SOC_EXYNOS7870) || \ - defined(CONFIG_MACH_UNIVERSAL7580) || defined(CONFIG_SOC_EXYNOS7885)) + defined(CONFIG_MACH_UNIVERSAL7580)) extern struct mmc_host *wlan_mmc; extern void mmc_ctrl_power(struct mmc_host *host, bool onoff); -#endif /* MACH_UNIVERSAL3475 || SOC_EXYNOS7870 || - * MACH_UNIVERSAL7580 || SOC_EXYNOS7885 - */ +#endif /* MACH_UNIVERSAL3475 || SOC_EXYNOS7870 || MACH_UNIVERSAL7580 */ static int dhd_wlan_power(int onoff) @@ -131,7 +125,7 @@ dhd_wlan_power(int onoff) #ifdef EXYNOS_PCIE_RC_ONOFF if (!onoff) { - exynos_pcie_poweroff(SAMSUNG_PCIE_CH_NUM); + exynos_pcie_pm_suspend(SAMSUNG_PCIE_CH_NUM); } if (gpio_direction_output(wlan_pwr_on, onoff)) { @@ -141,11 +135,11 @@ dhd_wlan_power(int onoff) } if (onoff) { -#if defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) printk(KERN_ERR "%s Disable L1ss EP side\n", __FUNCTION__); exynos_pcie_l1ss_ctrl(0, PCIE_L1SS_CTRL_WIFI); -#endif /* CONFIG_SOC_EXYNOS8895 */ - exynos_pcie_poweron(SAMSUNG_PCIE_CH_NUM); +#endif /* CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ + exynos_pcie_pm_resume(SAMSUNG_PCIE_CH_NUM); } #else #ifdef CONFIG_MACH_A7LTE @@ -171,12 +165,10 @@ dhd_wlan_power(int onoff) } #endif /* CONFIG_MACH_A7LTE */ #if (defined(CONFIG_MACH_UNIVERSAL3475) || defined(CONFIG_SOC_EXYNOS7870) || \ - defined(CONFIG_MACH_UNIVERSAL7580) || defined(CONFIG_SOC_EXYNOS7885)) + defined(CONFIG_MACH_UNIVERSAL7580)) if (wlan_mmc) mmc_ctrl_power(wlan_mmc, onoff); -#endif /* MACH_UNIVERSAL3475 || SOC_EXYNOS7870 || - * MACH_UNIVERSAL7580 || SOC_EXYNOS7885 - */ +#endif /* MACH_UNIVERSAL3475 || SOC_EXYNOS7870 || MACH_UNIVERSAL7580 */ #endif /* EXYNOS_PCIE_RC_ONOFF */ return 0; } @@ -207,32 +199,6 @@ dhd_wlan_set_carddetect(int val) } #endif /* !CONFIG_BCMDHD_PCIE */ -#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT -int -dhd_get_system_rev(void) -{ - const char *wlan_node = "samsung,brcm-wlan"; - struct device_node *root_node = NULL; - unsigned int base_system_rev_for_nv = 0; - int ret; - - root_node = of_find_compatible_node(NULL, NULL, wlan_node); - if (!root_node) { - printk(KERN_ERR "couldn't get root node\n"); - return -ENODEV; - } - - ret = of_property_read_u32(root_node, "base_system_rev_for_nv", - &base_system_rev_for_nv); - if (ret) { - printk(KERN_INFO "couldn't get base_system_rev_for_nv\n"); - return -ENODEV; - } - - return base_system_rev_for_nv; -} -#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ - int __init dhd_wlan_init_gpio(void) { @@ -273,7 +239,7 @@ dhd_wlan_init_gpio(void) gpio_export_link(wlan_dev, "WLAN_REG_ON", wlan_pwr_on); #ifdef EXYNOS_PCIE_RC_ONOFF - exynos_pcie_poweron(SAMSUNG_PCIE_CH_NUM); + exynos_pcie_pm_resume(SAMSUNG_PCIE_CH_NUM); #endif /* EXYNOS_PCIE_RC_ONOFF */ #ifdef CONFIG_BCMDHD_OOB_HOST_WAKE @@ -386,7 +352,7 @@ fail: } #if defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_SOC_EXYNOS8890) || \ - defined(CONFIG_SOC_EXYNOS8895) + defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) #if defined(CONFIG_DEFERRED_INITCALLS) deferred_module_init(dhd_wlan_init); #else @@ -395,5 +361,5 @@ late_initcall(dhd_wlan_init); #else device_initcall(dhd_wlan_init); #endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 || \ - CONFIG_SOC_EXYNOS8895 + CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_gpio.c index 87366842c96175403c3cc219224956a5d29652e9..09eb3a65645abe4dd711d42776ff325d7fa40fb0 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_gpio.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_gpio.c @@ -1,14 +1,14 @@ /* * Customer code to add GPIO control during WLAN start/stop * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_custom_gpio.c 664997 2016-10-14 11:56:35Z $ + * $Id: dhd_custom_gpio.c 717227 2017-08-23 13:51:13Z $ */ #include @@ -36,6 +36,9 @@ #include #include +#if defined(WL_WIRELESS_EXT) +#include +#endif // endif #define WL_ERROR(x) printf x #define WL_TRACE(x) @@ -86,7 +89,7 @@ int dhd_customer_oob_irq_map(void *adapter, unsigned long *irq_flags_ptr) WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", __FUNCTION__, dhd_oob_gpio_num)); -#endif +#endif // endif return (host_oob_irq); } @@ -176,7 +179,6 @@ const struct cntry_locales_custom translate_custom_table[] = { #endif /* EXMAPLE_TABLE */ }; - /* Customized Locale convertor * input : ISO 3166-1 country abbreviation * output: customized cspec @@ -212,5 +214,7 @@ void get_customized_country_code(void *adapter, char *country_iso_code, wl_count cspec->rev = translate_custom_table[0].custom_locale_rev; #endif /* EXMAPLE_TABLE */ return; + * (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) + */ } #endif /* !CUSTOMER_HW4 */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_memprealloc.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_memprealloc.c index 18ae4b4d7074b5553e4510c0a2d512458c283c7a..9348b7ebc039eaf4c1eb542619f64296e79bd0c9 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_memprealloc.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_memprealloc.c @@ -1,14 +1,14 @@ /* * Platform Dependent file for usage of Preallocted Memory * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,14 +16,14 @@ * 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_custom_memprealloc.c 730257 2017-11-06 12:52:32Z $ + * $Id: dhd_custom_memprealloc.c 734328 2017-12-04 06:33:47Z $ */ #include @@ -54,13 +54,18 @@ #define WLAN_STATIC_DHD_LOG_DUMP_BUF 15 #define WLAN_STATIC_DHD_LOG_DUMP_BUF_EX 16 #define WLAN_STATIC_DHD_PKTLOG_DUMP_BUF 17 -#define WLAN_STATIC_STAT_REPORT_BUF 18 #define WLAN_SCAN_BUF_SIZE (64 * 1024) +#if defined(CONFIG_64BIT) #define WLAN_DHD_INFO_BUF_SIZE (32 * 1024) #define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024) #define WLAN_DHD_IF_FLOW_LKUP_SIZE (64 * 1024) +#else +#define WLAN_DHD_INFO_BUF_SIZE (32 * 1024) +#define WLAN_DHD_WLFC_BUF_SIZE (16 * 1024) +#define WLAN_DHD_IF_FLOW_LKUP_SIZE (20 * 1024) +#endif /* CONFIG_64BIT */ #define WLAN_DHD_MEMDUMP_SIZE (1536 * 1024) #define PREALLOC_WLAN_SEC_NUM 4 @@ -114,13 +119,11 @@ #define WLAN_DHD_PKTID_IOCTL_MAP_SIZE ((WLAN_DHD_PKTID_IOCTL_MAP_HDR_SIZE) + \ ((WLAN_MAX_PKTID_IOCTL_ITEMS+1) * WLAN_DHD_PKTID_IOCTL_MAP_ITEM_SIZE)) -#define DHD_LOG_DUMP_BUF_SIZE (1024 * 1024) -#define DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024) +#define DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * 4) +#define DHD_LOG_DUMP_BUF_EX_SIZE (1024 * 1024 * 4) #define DHD_PKTLOG_DUMP_BUF_SIZE (64 * 1024) -#define DHD_STAT_REPORT_BUF_SIZE (128 * 1024) - #define WLAN_DHD_WLFC_HANGER_MAXITEMS 3072 #define WLAN_DHD_WLFC_HANGER_ITEM_SIZE 32 #define WLAN_DHD_WLFC_HANGER_SIZE ((WLAN_DHD_WLFC_HANGER_ITEM_SIZE) + \ @@ -152,18 +155,6 @@ static void *wlan_static_dhd_pktid_ioctl_map = NULL; static void *wlan_static_dhd_log_dump_buf = NULL; static void *wlan_static_dhd_log_dump_buf_ex = NULL; static void *wlan_static_dhd_pktlog_dump_buf = NULL; -static void *wlan_static_stat_report_buf = NULL; - -#define GET_STATIC_BUF(section, config_size, req_size, buf) ({\ - void *__ret; \ - if (req_size > config_size) {\ - pr_err("request " #section " size(%lu) is bigger than" \ - " static size(%d)\n", \ - req_size, config_size); \ - __ret = NULL; \ - } else { __ret = buf;} \ - __ret; \ -}) void *dhd_wlan_mem_prealloc(int section, unsigned long size) @@ -240,7 +231,6 @@ void return wlan_static_dhd_pktid_map; } - if (section == WLAN_STATIC_DHD_PKTID_IOCTL_MAP) { if (size > WLAN_DHD_PKTID_IOCTL_MAP_SIZE) { pr_err("request DHD_PKTID_IOCTL_MAP size(%lu) is bigger than" @@ -281,11 +271,6 @@ void return wlan_static_dhd_pktlog_dump_buf; } - if (section == WLAN_STATIC_STAT_REPORT_BUF) { - return GET_STATIC_BUF(WLAN_STATIC_STAT_REPORT_BUF, - DHD_STAT_REPORT_BUF_SIZE, size, wlan_static_stat_report_buf); - } - if ((section < 0) || (section >= PREALLOC_WLAN_SEC_NUM)) { return NULL; } @@ -419,12 +404,6 @@ dhd_init_wlan_mem(void) goto err_mem_alloc; } - wlan_static_stat_report_buf = kmalloc(DHD_STAT_REPORT_BUF_SIZE, GFP_KERNEL); - if (!wlan_static_stat_report_buf) { - pr_err("Failed to alloc wlan_static_stat_report_buf\n"); - goto err_mem_alloc; - } - pr_err("%s: WIFI MEM Allocated\n", __FUNCTION__); return 0; @@ -483,10 +462,6 @@ err_mem_alloc: kfree(wlan_static_dhd_pktlog_dump_buf); } - if (wlan_static_stat_report_buf) { - kfree(wlan_static_stat_report_buf); - } - pr_err("Failed to mem_alloc for WLAN\n"); for (j = 0; j < i; j++) { @@ -504,4 +479,80 @@ err_skb_alloc: return -ENOMEM; } EXPORT_SYMBOL(dhd_init_wlan_mem); + +void +dhd_exit_wlan_mem(void) +{ + int i = 0; + +#ifdef CONFIG_BCMDHD_PREALLOC_MEMDUMP + if (wlan_static_dhd_memdump_ram) { + kfree(wlan_static_dhd_memdump_ram); + } + +#endif /* CONFIG_BCMDHD_PREALLOC_MEMDUMP */ + +#ifdef CONFIG_BCMDHD_PCIE + if (wlan_static_if_flow_lkup) { + kfree(wlan_static_if_flow_lkup); + } + +#ifdef CONFIG_BCMDHD_PREALLOC_PKTIDMAP + if (wlan_static_dhd_pktid_map) { + kfree(wlan_static_dhd_pktid_map); + } + + if (wlan_static_dhd_pktid_ioctl_map) { + kfree(wlan_static_dhd_pktid_ioctl_map); + } +#endif /* CONFIG_BCMDHD_PREALLOC_PKTIDMAP */ +#else + if (wlan_static_dhd_wlfc_buf) { + kfree(wlan_static_dhd_wlfc_buf); + } + + if (wlan_static_dhd_wlfc_hanger) { + kfree(wlan_static_dhd_wlfc_hanger); + } +#endif /* CONFIG_BCMDHD_PCIE */ + if (wlan_static_dhd_info_buf) { + kfree(wlan_static_dhd_info_buf); + } + + if (wlan_static_dhd_log_dump_buf) { + kfree(wlan_static_dhd_log_dump_buf); + } + + if (wlan_static_dhd_log_dump_buf_ex) { + kfree(wlan_static_dhd_log_dump_buf_ex); + } + + if (wlan_static_scan_buf1) { + kfree(wlan_static_scan_buf1); + } + + if (wlan_static_scan_buf0) { + kfree(wlan_static_scan_buf0); + } + + if (wlan_static_dhd_pktlog_dump_buf) { + kfree(wlan_static_dhd_pktlog_dump_buf); + } + + pr_err("Failed to mem_alloc for WLAN\n"); + + for (i = 0; i < PREALLOC_WLAN_SEC_NUM; i++) { + if (wlan_mem_array[i].mem_ptr) { + kfree(wlan_mem_array[i].mem_ptr); + } + } + + pr_err("Failed to skb_alloc for WLAN\n"); + for (i = 0; i < WLAN_SKB_BUF_NUM; i++) { + dev_kfree_skb(wlan_static_skb[i]); + } + + return; +} +EXPORT_SYMBOL(dhd_exit_wlan_mem); #endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_msm.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_msm.c index 25a7d4e63fb73940c6ee5a0799db0bf0d2046052..c04c873d71bab10eea66748869dc455f035a162b 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_msm.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_msm.c @@ -1,14 +1,14 @@ /* * Platform Dependent file for Qualcomm MSM/APQ * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,14 +16,14 @@ * 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_custom_msm.c 714138 2017-08-03 08:55:55Z $ + * $Id: dhd_custom_msm.c 717191 2017-08-23 12:04:52Z $ * */ @@ -40,9 +40,10 @@ #include #include #include -#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) +#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \ + defined(CONFIG_ARCH_SDM845) #include -#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 */ +#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 || CONFIG_ARCH_SDM845 */ #ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM extern int dhd_init_wlan_mem(void); @@ -54,11 +55,12 @@ static int wlan_reg_on = -1; #define DHD_DT_COMPAT_ENTRY "android,bcmdhd_wlan" #define WIFI_WL_REG_ON_PROPNAME "wlan-en-gpio" -#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) +#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \ + defined(CONFIG_ARCH_SDM845) #define MSM_PCIE_CH_NUM 0 #else #define MSM_PCIE_CH_NUM 1 -#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 */ +#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 || CONFIG_ARCH_SDM845 */ #ifdef CONFIG_BCMDHD_OOB_HOST_WAKE static int wlan_host_wake_up = -1; @@ -110,7 +112,7 @@ dhd_wifi_init_gpio(void) printk(KERN_INFO "%s: gpio_wlan_host_wake : %d\n", __FUNCTION__, wlan_host_wake_up); if (gpio_request_one(wlan_host_wake_up, GPIOF_IN, "WLAN_HOST_WAKE")) { - printk(KERN_ERR "%s: Failed to request gpio %d for WLAN_HOST_WAKE\n", + printk(KERN_ERR "%s: Faiiled to request gpio %d for WLAN_HOST_WAKE\n", __FUNCTION__, wlan_host_wake_up); return -ENODEV; } else { @@ -232,7 +234,8 @@ fail: printk(KERN_INFO"%s: FINISH.......\n", __FUNCTION__); return ret; } -#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) +#if defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \ + defined(CONFIG_ARCH_SDM845) #if defined(CONFIG_DEFERRED_INITCALLS) deferred_module_init(dhd_wlan_init); #else @@ -240,4 +243,4 @@ late_initcall(dhd_wlan_init); #endif /* CONFIG_DEFERRED_INITCALLS */ #else device_initcall(dhd_wlan_init); -#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 */ +#endif /* CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 || CONFIG_ARCH_SDM845 */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd_oo/dhd_custom_sec.c index 61d8afe9b7e2fd025f2abfa46af64dafc6aab086..0180185a34ec4b7211ee1e487c006c3f263671c6 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_custom_sec.c @@ -1,14 +1,14 @@ /* * Customer HW 4 dependant file * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,123 +49,6 @@ extern int argos_irq_affinity_setup_label(unsigned int irq, const char *label, #endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ const struct cntry_locales_custom translate_custom_table[] = { -#if defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP) - /* 4330/4334/43241 */ - {"AR", "AR", 1}, - {"AT", "AT", 1}, - {"AU", "AU", 2}, - {"BE", "BE", 1}, - {"BG", "BG", 1}, - {"BN", "BN", 1}, - {"CA", "CA", 2}, - {"CH", "CH", 1}, - {"CY", "CY", 1}, - {"CZ", "CZ", 1}, - {"DE", "DE", 3}, - {"DK", "DK", 1}, - {"EE", "EE", 1}, - {"ES", "ES", 1}, - {"FI", "FI", 1}, - {"FR", "FR", 1}, - {"GB", "GB", 1}, - {"GR", "GR", 1}, - {"HR", "HR", 1}, - {"HU", "HU", 1}, - {"IE", "IE", 1}, - {"IS", "IS", 1}, - {"IT", "IT", 1}, - {"JP", "JP", 5}, - {"KR", "KR", 24}, - {"KW", "KW", 1}, - {"LI", "LI", 1}, - {"LT", "LT", 1}, - {"LU", "LU", 1}, - {"LV", "LV", 1}, - {"MT", "MT", 1}, - {"NL", "NL", 1}, - {"NO", "NO", 1}, - {"PL", "PL", 1}, - {"PT", "PT", 1}, - {"PY", "PY", 1}, - {"RO", "RO", 1}, - {"RU", "RU", 13}, - {"SE", "SE", 1}, - {"SI", "SI", 1}, - {"SK", "SK", 1}, - {"TW", "TW", 2}, -#ifdef BCM4330_CHIP - {"", "XZ", 1}, /* Universal if Country code is unknown or empty */ - {"IR", "XZ", 1}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ - {"SD", "XZ", 1}, /* Universal if Country code is SUDAN */ - {"GL", "XZ", 1}, /* Universal if Country code is GREENLAND */ - {"PS", "XZ", 1}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */ - {"TL", "XZ", 1}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */ - {"MH", "XZ", 1}, /* Universal if Country code is MARSHALL ISLANDS */ - {"JO", "XZ", 1}, /* Universal if Country code is Jordan */ - {"PG", "XZ", 1}, /* Universal if Country code is Papua New Guinea */ - {"SA", "XZ", 1}, /* Universal if Country code is Saudi Arabia */ - {"AF", "XZ", 1}, /* Universal if Country code is Afghanistan */ - {"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", "GB", 1}, - {"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}, - {"AE", "AZ", 0}, - {"IQ", "GB", 1}, - {"CN", "CL", 0}, - {"MX", "MX", 1}, -#else - /* 4334/43241 */ - {"", "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 */ - {"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 */ - {"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(BCM4330_CHIP) */ -#ifdef BCM4334_CHIP - {"AE", "AE", 1}, - {"MX", "MX", 1}, -#endif /* defined(BCM4334_CHIP) */ -#ifdef BCM43241_CHIP - {"AE", "AE", 6}, - {"BD", "BD", 2}, - {"CN", "CN", 38}, - {"MX", "MX", 20}, -#endif /* defined(BCM43241_CHIP) */ -#else /* defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP) */ /* default ccode/regrev */ {"", "XZ", 11}, /* Universal if Country code is unknown or empty */ {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ @@ -298,7 +181,7 @@ const struct cntry_locales_custom translate_custom_table[] = { {"KR", "KR", 70}, #else {"KR", "KR", 48}, -#endif +#endif // endif {"RU", "RU", 13}, {"UA", "UA", 8}, {"GT", "GT", 1}, @@ -319,7 +202,6 @@ const struct cntry_locales_custom translate_custom_table[] = { {"US", "US", 988}, {"CU", "US", 988}, {"CA", "Q2", 993}, -#endif /* default ccode/regrev */ }; /* Customized Locale convertor @@ -349,14 +231,14 @@ void get_customized_country_code(void *adapter, char *country_iso_code, wl_count return; } -#define PSMINFO PLATFORM_PATH".psm.info" -#define REVINFO PLATFORM_PATH".rev" +#define PSMINFO PLATFORM_PATH".psm.info" +#define REVINFO PLATFORM_PATH".rev" #define ANTINFO PLATFORM_PATH".ant.info" -#define WIFIVERINFO PLATFORM_PATH".wifiver.info" -#define RSDBINFO PLATFORM_PATH".rsdb.info" -#define LOGTRACEINFO PLATFORM_PATH".logtrace.info" -#define ADPSINFO PLATFORM_PATH".adps.info" -#define SOFTAPINFO PLATFORM_PATH".softap.info" +#define WIFIVERINFO PLATFORM_PATH".wifiver.info" +#define RSDBINFO PLATFORM_PATH".rsdb.info" +#define LOGTRACEINFO PLATFORM_PATH".logtrace.info" +#define ADPSINFO PLATFORM_PATH".adps.info" +#define SOFTAPINFO PLATFORM_PATH".softap.info" #ifdef DHD_PM_CONTROL_FROM_FILE extern bool g_pm_control; @@ -387,7 +269,7 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) if (power_val == '0') { #ifdef ROAM_ENABLE uint roamvar = 1; -#endif +#endif // endif uint32 wl_updown = 1; *power_mode = PM_OFF; @@ -396,15 +278,15 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) sizeof(uint), TRUE, 0); #ifndef CUSTOM_SET_ANTNPM /* Turn off MPC in AP mode */ - dhd_iovar(dhd, 0, "mpc", (char *)power_mode, sizeof(*power_mode), NULL, 0, - TRUE); + ret = dhd_iovar(dhd, 0, "mpc", (char *)power_mode, sizeof(*power_mode), + NULL, 0, TRUE); #endif /* !CUSTOM_SET_ANTNPM */ g_pm_control = TRUE; #ifdef ROAM_ENABLE /* Roaming off of dongle */ - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, 0, - TRUE); -#endif + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, + 0, TRUE); +#endif // endif #ifdef DHD_ENABLE_LPC /* Set lpc 0 */ ret = dhd_iovar(dhd, 0, "lpc", (char *)&lpc, sizeof(lpc), NULL, 0, TRUE); @@ -445,9 +327,6 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) DHD_ERROR(("[WIFI_SEC] %s: dhd_enable_adps failed %d\n", __FUNCTION__, ret)); } -#ifdef WLADPS_SEAK_AP_WAR - dhd->disabled_adps = TRUE; -#endif /* WLADPS_SEAK_AP_WAR */ #endif /* WLADPS */ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, (char *)&wl_updown, @@ -473,15 +352,16 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) int ret = -1; uint32 ant_val = 0; uint32 btc_mode = 0; -#ifndef CUSTOM_SET_ANTNPM - uint32 rsdb_mode = 0; -#endif /* !CUSTOM_SET_ANTNPM */ char *filepath = ANTINFO; uint chip_id = dhd_bus_chip_id(dhd); +#ifndef CUSTOM_SET_ANTNPM + wl_config_t rsdb_mode; + + memset(&rsdb_mode, 0, sizeof(rsdb_mode)); +#endif /* !CUSTOM_SET_ANTNPM */ /* Check if this chip can support MIMO */ - if (chip_id != BCM4324_CHIP_ID && - chip_id != BCM4350_CHIP_ID && + if (chip_id != BCM4350_CHIP_ID && chip_id != BCM4354_CHIP_ID && chip_id != BCM43569_CHIP_ID && chip_id != BCM4358_CHIP_ID && @@ -500,7 +380,7 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); #ifdef CUSTOM_SET_ANTNPM dhd->mimo_ant_set = 0; -#endif /* !CUSTOM_SET_ANTNPM */ +#endif /* CUSTOM_SET_ANTNPM */ return ret; } else { ret = kernel_read(fp, 0, (char *)&ant_val, 4); @@ -538,7 +418,7 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) #ifndef CUSTOM_SET_ANTNPM /* rsdb mode off */ DHD_ERROR(("[WIFI_SEC] %s: %s the RSDB mode!\n", - __FUNCTION__, rsdb_mode ? "Enable" : "Disable")); + __FUNCTION__, rsdb_mode.config ? "Enable" : "Disable")); ret = dhd_iovar(dhd, 0, "rsdb_mode", (char *)&rsdb_mode, sizeof(rsdb_mode), NULL, 0, TRUE); if (ret) { DHD_ERROR(("[WIFI_SEC] %s: Fail to execute dhd_wl_ioctl_cmd(): " @@ -579,36 +459,40 @@ int dhd_rsdb_mode_from_file(dhd_pub_t *dhd) { struct file *fp = NULL; int ret = -1; - uint32 rsdb_mode = 0; + wl_config_t rsdb_mode; + uint32 rsdb_configuration = 0; char *filepath = RSDBINFO; + memset(&rsdb_mode, 0, sizeof(rsdb_mode)); + /* Read RSDB on/off request from the file */ fp = filp_open(filepath, O_RDONLY, 0); if (IS_ERR(fp)) { DHD_ERROR(("[WIFI_SEC] %s: File [%s] doesn't exist\n", __FUNCTION__, filepath)); return ret; } else { - ret = kernel_read(fp, 0, (char *)&rsdb_mode, 4); + ret = kernel_read(fp, 0, (char *)&rsdb_configuration, 4); if (ret < 0) { DHD_ERROR(("[WIFI_SEC] %s: File read error, ret=%d\n", __FUNCTION__, ret)); filp_close(fp, NULL); return ret; } - rsdb_mode = bcm_atoi((char *)&rsdb_mode); + rsdb_mode.config = bcm_atoi((char *)&rsdb_configuration); - DHD_ERROR(("[WIFI_SEC] %s: RSDB mode from file = %d\n", __FUNCTION__, rsdb_mode)); + DHD_ERROR(("[WIFI_SEC] %s: RSDB mode from file = %d\n", + __FUNCTION__, rsdb_mode.config)); filp_close(fp, NULL); /* Check value from the file */ - if (rsdb_mode > 2) { + if (rsdb_mode.config > 2) { DHD_ERROR(("[WIFI_SEC] %s: Invalid value %d read from the file %s\n", - __FUNCTION__, rsdb_mode, filepath)); + __FUNCTION__, rsdb_mode.config, filepath)); return -1; } } - if (rsdb_mode == 0) { + if (rsdb_mode.config == 0) { ret = dhd_iovar(dhd, 0, "rsdb_mode", (char *)&rsdb_mode, sizeof(rsdb_mode), NULL, 0, TRUE); if (ret < 0) { @@ -852,17 +736,17 @@ uint32 sec_save_wlinfo(char *firm_ver, char *dhd_ver, char *nvram_p, char *clm_v } if (strlen(clm_ver)) { - min_len = min(strlen(clm_ver), max_len(temp_buf, CLM_PREFIX)); - min_len += strlen(CLM_PREFIX) + 3; - DHD_INFO(("[WIFI_SEC] clm ver length : %d\n", min_len)); - snprintf(version_info+str_len, min_len, CLM_PREFIX " %s\n", clm_ver); - str_len = strlen(version_info); - - DHD_INFO(("[WIFI_SEC] CLM version_info len : %d\n", str_len)); - DHD_INFO(("[WIFI_SEC] CLM version_info : %s\n", version_info)); - } else { - DHD_ERROR(("[WIFI_SEC] CLM version is missing.\n")); - } + min_len = min(strlen(clm_ver), max_len(temp_buf, CLM_PREFIX)); + min_len += strlen(CLM_PREFIX) + 3; + DHD_INFO(("[WIFI_SEC] clm ver length : %d\n", min_len)); + snprintf(version_info+str_len, min_len, CLM_PREFIX " %s\n", clm_ver); + str_len = strlen(version_info); + + DHD_INFO(("[WIFI_SEC] CLM version_info len : %d\n", str_len)); + DHD_INFO(("[WIFI_SEC] CLM version_info : %s\n", version_info)); + } else { + DHD_ERROR(("[WIFI_SEC] CLM version is missing.\n")); + } DHD_INFO(("[WIFI_SEC] version_info : %s, strlen : %zu\n", version_info, strlen(version_info))); @@ -907,87 +791,6 @@ __init get_hw_rev(char *arg) early_param("androidboot.hw_rev", get_hw_rev); #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */ -#endif /* CUSTOMER_HW4 || CUSTOMER_HW40 */ - -#if defined(FORCE_DISABLE_SINGLECORE_SCAN) -void -dhd_force_disable_singlcore_scan(dhd_pub_t *dhd) -{ - int ret = 0; - struct file *fp = NULL; - char *filepath = PLATFORM_PATH".cid.info"; - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - char vender[10] = {0, }; - uint32 pm_bcnrx = 0; - uint32 scan_ps = 0; - - if (BCM4354_CHIP_ID != dhd_bus_chip_id(dhd)) - return; - - fp = filp_open(filepath, O_RDONLY, 0); - if (IS_ERR(fp)) { - DHD_ERROR(("%s file open error\n", filepath)); - } else { - ret = kernel_read(fp, 0, (char *)vender, 5); - - if (ret > 0 && NULL != strstr(vender, "wisol")) { - DHD_ERROR(("wisol module : set pm_bcnrx=0, set scan_ps=0\n")); - - bcm_mkiovar("pm_bcnrx", (char *)&pm_bcnrx, 4, iovbuf, sizeof(iovbuf)); - ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - if (ret < 0) - DHD_ERROR(("Set pm_bcnrx error (%d)\n", ret)); - - bcm_mkiovar("scan_ps", (char *)&scan_ps, 4, iovbuf, sizeof(iovbuf)); - ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - if (ret < 0) - DHD_ERROR(("Set scan_ps error (%d)\n", ret)); - } - filp_close(fp, NULL); - } -} -#endif /* FORCE_DISABLE_SINGLECORE_SCAN */ - -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) -void -set_irq_cpucore(unsigned int irq, cpumask_var_t default_cpu_mask, - cpumask_var_t affinity_cpu_mask) -{ - argos_irq_affinity_setup_label(irq, - ARGOS_IRQ_WIFI_TABLE_LABEL, - affinity_cpu_mask, default_cpu_mask); - - argos_irq_affinity_setup_label(irq, - ARGOS_P2P_TABLE_LABEL, - affinity_cpu_mask, default_cpu_mask); -} -#elif defined(SET_PCIE_IRQ_CPU_CORE) -void -set_irq_cpucore(unsigned int irq, int set) -{ - if (set < 0 || set > 1) { - DHD_ERROR(("%s, PCIe CPU core set error\n", __FUNCTION__)); - return; - } - - if (set) { - DHD_ERROR(("%s, PCIe IRQ:%u set Core %d\n", - __FUNCTION__, irq, PCIE_IRQ_BIG_CORE)); - irq_set_affinity(irq, cpumask_of(PCIE_IRQ_BIG_CORE)); - } else { - DHD_ERROR(("%s, PCIe IRQ:%u set Core %d\n", - __FUNCTION__, irq, PCIE_IRQ_LITTLE_CORE)); - irq_set_affinity(irq, cpumask_of(PCIE_IRQ_LITTLE_CORE)); - } -} -#else -void -set_irq_cpucore(void) -{ - DHD_ERROR(("Unsupported IRQ affinity\n")); -} -#endif /* SET_PCIE_IRQ_CPU_CORE */ #ifdef ADPS_MODE_FROM_FILE /* @@ -1050,10 +853,11 @@ void dhd_adps_mode_from_file(dhd_pub_t *dhd) return; } #endif /* ADPS_MODE_FROM_FILE */ +#endif /* CUSTOMER_HW4 || CUSTOMER_HW40 */ #ifdef GEN_SOFTAP_INFO_FILE -#define SOFTAP_INFO_FILE_FIRST_LINE "#.softap.info" -#define SOFTAP_INFO_BUF_SZ 512 +#define SOFTAP_INFO_FILE_FIRST_LINE "#.softap.info" +#define SOFTAP_INFO_BUF_SZ 512 /* * # Whether both wifi and hotspot can be turned on at the same time? * DualBandConcurrency @@ -1076,7 +880,7 @@ const char *softap_info_items[] = { const char *softap_info_values[] = { "yes", "yes", "10", "yes", "yes", "yes", NULL }; -#elif defined(BCM43455_CHIP) || defined(BCM43456_CHIP) +#elif defined(BCM43455_CHIP) const char *softap_info_values[] = { "no", "yes", "10", "no", "yes", "yes", NULL }; @@ -1109,7 +913,7 @@ uint32 sec_save_softap_info(void) SOFTAP_INFO_FILE_FIRST_LINE); do { int len = strlen(softap_info_items[idx]) + - strlen(softap_info_values[idx]) + 2; + strlen(softap_info_values[idx]) + 2; pos += written; rem -= written; if (len > rem) { @@ -1132,3 +936,80 @@ uint32 sec_save_softap_info(void) return ret; } #endif /* GEN_SOFTAP_INFO_FILE */ + +#if defined(FORCE_DISABLE_SINGLECORE_SCAN) +void +dhd_force_disable_singlcore_scan(dhd_pub_t *dhd) +{ + int ret = 0; + struct file *fp = NULL; + char *filepath = PLATFORM_PATH".cid.info"; + char vender[10] = {0, }; + uint32 pm_bcnrx = 0; + uint32 scan_ps = 0; + + if (BCM4354_CHIP_ID != dhd_bus_chip_id(dhd)) + return; + + fp = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(fp)) { + DHD_ERROR(("%s file open error\n", filepath)); + } else { + ret = kernel_read(fp, 0, (char *)vender, 5); + + if (ret > 0 && NULL != strstr(vender, "wisol")) { + DHD_ERROR(("wisol module : set pm_bcnrx=0, set scan_ps=0\n")); + + ret = dhd_iovar(dhd, 0, "pm_bcnrx", (char *)&pm_bcnrx, sizeof(pm_bcnrx), + NULL, 0, TRUE); + if (ret < 0) + DHD_ERROR(("Set pm_bcnrx error (%d)\n", ret)); + + ret = dhd_iovar(dhd, 0, "scan_ps", (char *)&scan_ps, sizeof(scan_ps), NULL, + 0, TRUE); + if (ret < 0) + DHD_ERROR(("Set scan_ps error (%d)\n", ret)); + } + filp_close(fp, NULL); + } +} +#endif /* FORCE_DISABLE_SINGLECORE_SCAN */ +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) +void +set_irq_cpucore(unsigned int irq, cpumask_var_t default_cpu_mask, + cpumask_var_t affinity_cpu_mask) +{ + argos_irq_affinity_setup_label(irq, + ARGOS_IRQ_WIFI_TABLE_LABEL, + affinity_cpu_mask, default_cpu_mask); + + argos_irq_affinity_setup_label(irq, + ARGOS_P2P_TABLE_LABEL, + affinity_cpu_mask, default_cpu_mask); +} +#elif defined(SET_PCIE_IRQ_CPU_CORE) +void +set_irq_cpucore(unsigned int irq, int set) +{ + if (set < 0 || set > 1) { + DHD_ERROR(("%s, PCIe CPU core set error\n", __FUNCTION__)); + return; + } + + if (set) { + DHD_ERROR(("%s, PCIe IRQ:%u set Core %d\n", + __FUNCTION__, irq, PCIE_IRQ_BIG_CORE)); + irq_set_affinity(irq, cpumask_of(PCIE_IRQ_BIG_CORE)); + } else { + DHD_ERROR(("%s, PCIe IRQ:%u set Core %d\n", + __FUNCTION__, irq, PCIE_IRQ_LITTLE_CORE)); + irq_set_affinity(irq, cpumask_of(PCIE_IRQ_LITTLE_CORE)); + } +} +#else +void +set_irq_cpucore(void) +{ + DHD_ERROR(("Unsupported IRQ affinity\n")); +} +#endif /* SET_PCIE_IRQ_CPU_CORE && !DHD_LB_IRQSET */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_dbg.h b/drivers/net/wireless/bcmdhd_oo/dhd_dbg.h index 3f90c522936f2a5ba557aa753acf6643351fe921..1c437fb82529b64f13e8de66f0723d4f66733ee2 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_dbg.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_dbg.h @@ -1,14 +1,14 @@ /* * Debug/trace/assert driver definitions for Dongle Host Driver. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,49 +24,51 @@ * * <> * - * $Id: dhd_dbg.h 667145 2016-10-26 04:27:53Z $ + * $Id: dhd_dbg.h 737458 2017-12-21 05:17:03Z $ */ #ifndef _dhd_dbg_ #define _dhd_dbg_ - -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) -extern void dhd_log_dump_print(const char *fmt, ...); -extern void dhd_log_dump_print_drv(const char *fmt, ...); -#endif - -#if defined(DHD_DEBUG) +#define PRINT_RATE_LIMIT_PERIOD 5000000000u /* 5s in units of ns */ #ifdef DHD_LOG_DUMP -extern void dhd_log_dump_write(int type, const char *fmt, ...); extern char *dhd_log_dump_get_timestamp(void); +extern void dhd_log_dump_write(int type, char *binary_data, + int binary_len, const char *fmt, ...); #ifndef _DHD_LOG_DUMP_DEFINITIONS_ #define _DHD_LOG_DUMP_DEFINITIONS_ -#define DLD_BUF_TYPE_GENERAL 0 -#define DLD_BUF_TYPE_SPECIAL 1 -#define DHD_LOG_DUMP_WRITE(fmt, ...) dhd_log_dump_write(DLD_BUF_TYPE_GENERAL, fmt, ##__VA_ARGS__) -#define DHD_LOG_DUMP_WRITE_EX(fmt, ...) dhd_log_dump_write(DLD_BUF_TYPE_SPECIAL, fmt, ##__VA_ARGS__) +typedef enum { + DLD_BUF_TYPE_GENERAL = 0, + DLD_BUF_TYPE_PRESERVE, + DLD_BUF_TYPE_SPECIAL, + DLD_BUF_TYPE_ECNTRS, + DLD_BUF_TYPE_FILTER, + DLD_BUF_TYPE_ALL +} log_dump_type_t; +#define GENERAL_LOG_HDR "\n-------------------- General log ---------------------------\n" +#define PRESERVE_LOG_HDR "\n-------------------- Preserve log ---------------------------\n" +#define SPECIAL_LOG_HDR "\n-------------------- Special log ---------------------------\n" +#define DHD_DUMP_LOG_HDR "\n-------------------- 'dhd dump' log -----------------------\n" +#define EXT_TRAP_LOG_HDR "\n-------------------- Extended trap data -------------------\n" +#define HEALTH_CHK_LOG_HDR "\n-------------------- Health check data --------------------\n" +#define DHD_LOG_DUMP_WRITE(fmt, ...) \ + dhd_log_dump_write(DLD_BUF_TYPE_GENERAL, NULL, 0, fmt, ##__VA_ARGS__) +#define DHD_LOG_DUMP_WRITE_EX(fmt, ...) \ + dhd_log_dump_write(DLD_BUF_TYPE_SPECIAL, NULL, 0, fmt, ##__VA_ARGS__) +#define DHD_LOG_DUMP_WRITE_PRSRV(fmt, ...) \ + dhd_log_dump_write(DLD_BUF_TYPE_PRESERVE, NULL, 0, fmt, ##__VA_ARGS__) #endif /* !_DHD_LOG_DUMP_DEFINITIONS_ */ +#define CONCISE_DUMP_BUFLEN 16 * 1024 +#define ECNTRS_LOG_HDR "\n-------------------- Ecounters log --------------------------\n" +#define COOKIE_LOG_HDR "\n-------------------- Cookie List ----------------------------\n" +#endif /* DHD_LOG_DUMP */ -#ifdef DHD_EFI -#define DHD_ERROR(args) \ -do { \ - if (dhd_msg_level & DHD_ERROR_VAL) { \ - printf args; \ - dhd_log_dump_print_drv("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print_drv args; \ - } \ -} while (0) -#define DHD_INFO(args) \ -do { \ - if (dhd_msg_level & DHD_INFO_VAL) { \ - printf args; \ - dhd_log_dump_print_drv("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print_drv args; \ - } \ -} while (0) -#else /* DHD_EFI */ +#if defined(DHD_DEBUG) + +/* NON-NDIS cases */ +#ifdef DHD_LOG_DUMP +/* Common case for EFI and non EFI */ #define DHD_ERROR(args) \ do { \ if (dhd_msg_level & DHD_ERROR_VAL) { \ @@ -75,121 +77,143 @@ do { \ DHD_LOG_DUMP_WRITE args; \ } \ } while (0) + +/* !defined(DHD_EFI) and defined(DHD_LOG_DUMP) */ #define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0) -#endif /* DHD_EFI */ #else /* DHD_LOG_DUMP */ +/* !defined(DHD_LOG_DUMP cases) */ #define DHD_ERROR(args) do {if (dhd_msg_level & DHD_ERROR_VAL) printf args;} while (0) #define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0) #endif /* DHD_LOG_DUMP */ + #define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0) -#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0) -#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) printf args;} while (0) -#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) printf args;} while (0) -#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) printf args;} while (0) -#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) printf args;} while (0) -#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) printf args;} while (0) -#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0) #ifdef DHD_LOG_DUMP -#ifndef DHD_EFI -#define DHD_EVENT(args) \ +/* LOG_DUMP defines common to EFI and NON-EFI */ +#define DHD_ERROR_MEM(args) \ do { \ - if (dhd_msg_level & DHD_EVENT_VAL) { \ - printf args; \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + if (dhd_msg_level & DHD_ERROR_VAL) { \ + if (dhd_msg_level & DHD_ERROR_MEM_VAL) { \ + printf args; \ + } \ + DHD_LOG_DUMP_WRITE("[%s]: ", dhd_log_dump_get_timestamp()); \ DHD_LOG_DUMP_WRITE args; \ } \ } while (0) -#else -#define DHD_EVENT(args) \ +#define DHD_IOVAR_MEM(args) \ do { \ - if (dhd_msg_level & DHD_EVENT_VAL) { \ - dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print args; \ + if (dhd_msg_level & DHD_ERROR_VAL) { \ + if (dhd_msg_level & DHD_IOVAR_MEM_VAL) { \ + printf args; \ + } \ + DHD_LOG_DUMP_WRITE("[%s]: ", dhd_log_dump_get_timestamp()); \ + DHD_LOG_DUMP_WRITE args; \ } \ } while (0) -#endif /* !DHD_EFI */ -#else -#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0) -#endif /* DHD_LOG_DUMP */ -#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0) -#define DHD_ARPOE(args) do {if (dhd_msg_level & DHD_ARPOE_VAL) printf args;} while (0) -#define DHD_REORDER(args) do {if (dhd_msg_level & DHD_REORDER_VAL) printf args;} while (0) -#define DHD_PNO(args) do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0) -#define DHD_RTT(args) do {if (dhd_msg_level & DHD_RTT_VAL) printf args;} while (0) -#define DHD_PKT_MON(args) do {if (dhd_msg_level & DHD_PKT_MON_VAL) printf args;} while (0) -#ifdef DHD_LOG_DUMP -#ifndef DHD_EFI -#define DHD_MSGTRACE_LOG(args) \ +/* NON-EFI builds with LOG DUMP enabled */ +#define DHD_EVENT(args) \ do { \ - if (dhd_msg_level & DHD_MSGTRACE_VAL) { \ - printf args; \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__); \ + if (dhd_msg_level & DHD_EVENT_VAL) { \ + printf args; \ + DHD_LOG_DUMP_WRITE("[%s]: ", dhd_log_dump_get_timestamp()); \ DHD_LOG_DUMP_WRITE args; \ - } \ + } \ } while (0) -#else -#define DHD_MSGTRACE_LOG(args) \ +#define DHD_EVENT_MEM(args) \ do { \ - if (dhd_msg_level & DHD_MSGTRACE_VAL) { \ - dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print args; \ - } \ -} while (0) -#endif /* !DHD_EFI */ -#else -#define DHD_MSGTRACE_LOG(args) do {if (dhd_msg_level & DHD_MSGTRACE_VAL) printf args;} while (0) -#endif /* DHD_LOG_DUMP */ - -#if defined(DHD_LOG_DUMP) && defined(DHD_EFI) -#define DHD_FWLOG(args) DHD_MSGTRACE_LOG(args) -#else - -#define DHD_FWLOG(args) do {if (dhd_msg_level & DHD_FWLOG_VAL) printf args;} while (0) -#endif /* DHD_LOG_DUMP & DHD_EFI */ -#define DHD_DBGIF(args) do {if (dhd_msg_level & DHD_DBGIF_VAL) printf args;} while (0) - -#ifdef DHD_LOG_DUMP -#ifdef DHD_EFI -#define DHD_ERROR_MEM(args) \ -do { \ - if (dhd_msg_level & DHD_ERROR_VAL) { \ - dhd_log_dump_print_drv("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print_drv args; \ + if (dhd_msg_level & DHD_EVENT_VAL) { \ + if (dhd_msg_level & DHD_EVENT_MEM_VAL) \ + printf args; \ + DHD_LOG_DUMP_WRITE_PRSRV("[%s]: ", dhd_log_dump_get_timestamp()); \ + DHD_LOG_DUMP_WRITE_PRSRV args; \ } \ } while (0) -#define DHD_ERROR_EX(args) DHD_ERROR(args) -#else -#define DHD_ERROR_MEM(args) \ -do { \ - if (dhd_msg_level & DHD_ERROR_VAL) { \ - if (dhd_msg_level & DHD_ERROR_MEM_VAL) { \ - printf args; \ - } \ - DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - DHD_LOG_DUMP_WRITE args; \ + +/* Re-using 'DHD_MSGTRACE_VAL' for controlling printing of ecounter binary event +* logs to console and debug dump -- need to cleanup in the future to use separate +* 'DHD_ECNTR_VAL' bitmap flag. 'DHD_MSGTRACE_VAL' will be defined only +* for non-android builds. +*/ +#define DHD_ECNTR_LOG(args) \ +do { \ + if (dhd_msg_level & DHD_EVENT_VAL) { \ + if (dhd_msg_level & DHD_MSGTRACE_VAL) { \ + printf args; \ + DHD_LOG_DUMP_WRITE("[%s]: ", dhd_log_dump_get_timestamp()); \ + DHD_LOG_DUMP_WRITE args; \ + } \ } \ } while (0) + #define DHD_ERROR_EX(args) \ -do { \ +do { \ if (dhd_msg_level & DHD_ERROR_VAL) { \ printf args; \ - DHD_LOG_DUMP_WRITE_EX("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ + DHD_LOG_DUMP_WRITE_EX("[%s]: ", dhd_log_dump_get_timestamp()); \ DHD_LOG_DUMP_WRITE_EX args; \ } \ } while (0) -#endif /* DHD_EFI */ -#else + +#define DHD_MSGTRACE_LOG(args) \ +do { \ + if (dhd_msg_level & DHD_MSGTRACE_VAL) { \ + printf args; \ + } \ + DHD_LOG_DUMP_WRITE("[%s]: ", dhd_log_dump_get_timestamp()); \ + DHD_LOG_DUMP_WRITE args; \ +} while (0) +#else /* DHD_LOG_DUMP */ +/* !DHD_LOG_DUMP */ +#define DHD_MSGTRACE_LOG(args) do {if (dhd_msg_level & DHD_MSGTRACE_VAL) printf args;} while (0) #define DHD_ERROR_MEM(args) DHD_ERROR(args) +#define DHD_IOVAR_MEM(args) DHD_ERROR(args) +#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0) +#define DHD_ECNTR_LOG(args) DHD_EVENT(args) +#define DHD_EVENT_MEM(args) DHD_EVENT(args) #define DHD_ERROR_EX(args) DHD_ERROR(args) #endif /* DHD_LOG_DUMP */ +#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0) +#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) printf args;} while (0) +#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) printf args;} while (0) +#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) printf args;} while (0) +#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) printf args;} while (0) +#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) printf args;} while (0) +#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0) +#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0) +#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0) +#define DHD_ARPOE(args) do {if (dhd_msg_level & DHD_ARPOE_VAL) printf args;} while (0) +#define DHD_REORDER(args) do {if (dhd_msg_level & DHD_REORDER_VAL) printf args;} while (0) +#define DHD_PNO(args) do {if (dhd_msg_level & DHD_PNO_VAL) printf args;} while (0) +#define DHD_RTT(args) do {if (dhd_msg_level & DHD_RTT_VAL) printf args;} while (0) +#define DHD_PKT_MON(args) do {if (dhd_msg_level & DHD_PKT_MON_VAL) printf args;} while (0) + +#if defined(DHD_LOG_DUMP) +#define DHD_FWLOG(args) \ + do { \ + if (dhd_msg_level & DHD_FWLOG_VAL) { \ + printf args; \ + DHD_LOG_DUMP_WRITE args; \ + } \ + } while (0) +#else /* DHD_LOG_DUMP */ +#define DHD_FWLOG(args) do {if (dhd_msg_level & DHD_FWLOG_VAL) printf args;} while (0) +#endif /* DHD_LOG_DUMP */ + +#define DHD_DBGIF(args) do {if (dhd_msg_level & DHD_DBGIF_VAL) printf args;} while (0) + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#define DHD_RPM(args) do {if (dhd_msg_level & DHD_RPM_VAL) printf args;} while (0) +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef CUSTOMER_HW4_DEBUG #define DHD_TRACE_HW4 DHD_ERROR #define DHD_INFO_HW4 DHD_ERROR +#define DHD_ERROR_NO_HW4 DHD_INFO #else #define DHD_TRACE_HW4 DHD_TRACE #define DHD_INFO_HW4 DHD_INFO +#define DHD_ERROR_NO_HW4 DHD_ERROR #endif /* CUSTOMER_HW4_DEBUG */ #define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL) @@ -203,6 +227,7 @@ do { \ #define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL) #define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL) #define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL) +#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL) #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) @@ -214,36 +239,16 @@ do { \ #define DHD_DBGIF_ON() (dhd_msg_level & DHD_DBGIF_VAL) #define DHD_PKT_MON_ON() (dhd_msg_level & DHD_PKT_MON_VAL) #define DHD_PKT_MON_DUMP_ON() (dhd_msg_level & DHD_PKT_MON_DUMP_VAL) +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#define DHD_RPM_ON() (dhd_msg_level & DHD_RPM_VAL) +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #else /* defined(BCMDBG) || defined(DHD_DEBUG) */ -#if defined(DHD_EFI) -extern void dhd_log_dump_print_drv(const char *fmt, ...); -extern char *dhd_log_dump_get_timestamp(void); -#define DHD_ERROR(args) \ -do { \ - if (dhd_msg_level & DHD_ERROR_VAL) { \ - printf args; \ - dhd_log_dump_print_drv("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print_drv args; \ - } \ -} while (0) -#define DHD_INFO(args) \ -do { \ - if (dhd_msg_level & DHD_INFO_VAL) { \ - printf args; \ - dhd_log_dump_print_drv("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print_drv args; \ - } \ -} while (0) -#define DHD_TRACE(args) -#else /* DHD_EFI */ - #define DHD_ERROR(args) do {if (dhd_msg_level & DHD_ERROR_VAL) \ printf args;} while (0) #define DHD_TRACE(args) #define DHD_INFO(args) -#endif #define DHD_DATA(args) #define DHD_CTL(args) @@ -253,18 +258,12 @@ do { \ #define DHD_INTR(args) #define DHD_GLOM(args) -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) -#define DHD_EVENT(args) \ -do { \ - if (dhd_msg_level & DHD_EVENT_VAL) { \ - dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print args; \ - } \ -} while (0) -#else #define DHD_EVENT(args) -#endif /* DHD_EFI && DHD_LOG_DUMP */ +#define DHD_ECNTR_LOG(args) DHD_EVENT(args) +#define DHD_EVENT_MEM(args) DHD_EVENT(args) + +#define DHD_BTA(args) #define DHD_ISCAN(args) #define DHD_ARPOE(args) #define DHD_REORDER(args) @@ -272,42 +271,23 @@ do { \ #define DHD_RTT(args) #define DHD_PKT_MON(args) -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) -#define DHD_MSGTRACE_LOG(args) \ -do { \ - if (dhd_msg_level & DHD_MSGTRACE_VAL) { \ - dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print args; \ - } \ -} while (0) -#define DHD_FWLOG(args) DHD_MSGTRACE_LOG(args) -#else #define DHD_MSGTRACE_LOG(args) #define DHD_FWLOG(args) -#endif /* DHD_EFI && DHD_LOG_DUMP */ #define DHD_DBGIF(args) -#if defined(DHD_EFI) && defined(DHD_LOG_DUMP) -#define DHD_ERROR_MEM(args) \ -do { \ - if (dhd_msg_level & DHD_ERROR_VAL) { \ - dhd_log_dump_print("[%s] %s: ", dhd_log_dump_get_timestamp(), __FUNCTION__); \ - dhd_log_dump_print args; \ - } \ -} while (0) -#define DHD_ERROR_EX(args) DHD_ERROR(args) -#else -#define DHD_ERROR_MEM(args) DHD_ERROR(args) +#define DHD_ERROR_MEM(args) DHD_ERROR(args) +#define DHD_IOVAR_MEM(args) DHD_ERROR(args) #define DHD_ERROR_EX(args) DHD_ERROR(args) -#endif /* DHD_EFI && DHD_LOG_DUMP */ #ifdef CUSTOMER_HW4_DEBUG #define DHD_TRACE_HW4 DHD_ERROR #define DHD_INFO_HW4 DHD_ERROR +#define DHD_ERROR_NO_HW4 DHD_INFO #else #define DHD_TRACE_HW4 DHD_TRACE #define DHD_INFO_HW4 DHD_INFO +#define DHD_ERROR_NO_HW4 DHD_ERROR #endif /* CUSTOMER_HW4_DEBUG */ #define DHD_ERROR_ON() 0 @@ -321,6 +301,7 @@ do { \ #define DHD_INTR_ON() 0 #define DHD_GLOM_ON() 0 #define DHD_EVENT_ON() 0 +#define DHD_BTA_ON() 0 #define DHD_ISCAN_ON() 0 #define DHD_ARPOE_ON() 0 #define DHD_REORDER_ON() 0 @@ -332,7 +313,33 @@ do { \ #define DHD_MSGTRACE_ON() 0 #define DHD_FWLOG_ON() 0 #define DHD_DBGIF_ON() 0 -#endif +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#define DHD_RPM_ON() 0 +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ +#endif // endif + +#define DHD_ERROR_RLMT(args) \ +do { \ + if (dhd_msg_level & DHD_ERROR_VAL) { \ + static uint64 __err_ts = 0; \ + static uint32 __err_cnt = 0; \ + uint64 __cur_ts = 0; \ + __cur_ts = local_clock(); \ + if (__err_ts == 0 || (__cur_ts > __err_ts && \ + (__cur_ts - __err_ts > PRINT_RATE_LIMIT_PERIOD))) { \ + __err_ts = __cur_ts; \ + DHD_ERROR(args); \ + DHD_ERROR(("[Repeats %u times]\n", __err_cnt)); \ + __err_cnt = 0; \ + } else { \ + ++__err_cnt; \ + } \ + } \ +} while (0) + +/* even in non-BCMDBG builds, logging of dongle iovars should be available */ +#define DHD_DNGL_IOVAR_SET(args) \ + do {if (dhd_msg_level & DHD_DNGL_IOVAR_SET_VAL) printf args;} while (0) #define DHD_LOG(args) diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.c b/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.c new file mode 100644 index 0000000000000000000000000000000000000000..feab9e539fd830f68a726c4833cfd2acf45e5850 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.c @@ -0,0 +1,401 @@ +/* + * DHD debug ring API and structures + * + * <> + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: dhd_dbg_ring.c 737951 2017-12-25 13:35:49Z $ + */ +#include +#include +#include +#include +#include +#include +#include +#include + +int +dhd_dbg_ring_init(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring, uint16 id, uint8 *name, + uint32 ring_sz, void *allocd_buf) +{ + void *buf; + unsigned long flags = 0; + + if (allocd_buf == NULL) { + return BCME_NOMEM; + } else { + buf = allocd_buf; + } + + ring->lock = DHD_DBG_RING_LOCK_INIT(dhdp->osh); + if (!ring->lock) + return BCME_NOMEM; + + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->id = id; + strncpy(ring->name, name, DBGRING_NAME_MAX); + ring->name[DBGRING_NAME_MAX - 1] = 0; + ring->ring_size = ring_sz; + ring->wp = ring->rp = 0; + ring->ring_buf = buf; + ring->threshold = DBGRING_FLUSH_THRESHOLD(ring); + ring->state = RING_SUSPEND; + ring->rem_len = 0; + ring->sched_pull = TRUE; + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + return BCME_OK; +} + +void +dhd_dbg_ring_deinit(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring) +{ + unsigned long flags = 0; + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->id = 0; + ring->name[0] = 0; + ring->wp = ring->rp = 0; + memset(&ring->stat, 0, sizeof(ring->stat)); + ring->threshold = 0; + ring->state = RING_STOP; + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + DHD_DBG_RING_LOCK_DEINIT(dhdp->osh, ring->lock); +} + +void +dhd_dbg_ring_sched_pull(dhd_dbg_ring_t *ring, uint32 pending_len, + os_pullreq_t pull_fn, void *os_pvt, const int id) +{ + unsigned long flags = 0; + DHD_DBG_RING_LOCK(ring->lock, flags); + /* if the current pending size is bigger than threshold and + * threshold is set + */ + if (ring->threshold > 0 && + (pending_len >= ring->threshold) && ring->sched_pull) { + pull_fn(os_pvt, id); + ring->sched_pull = FALSE; + } + DHD_DBG_RING_UNLOCK(ring->lock, flags); +} + +uint32 +dhd_dbg_ring_get_pending_len(dhd_dbg_ring_t *ring) +{ + uint32 pending_len = 0; + unsigned long flags = 0; + DHD_DBG_RING_LOCK(ring->lock, flags); + if (ring->stat.written_bytes > ring->stat.read_bytes) { + pending_len = ring->stat.written_bytes - ring->stat.read_bytes; + } else if (ring->stat.written_bytes < ring->stat.read_bytes) { + pending_len = PENDING_LEN_MAX - ring->stat.read_bytes + ring->stat.written_bytes; + } else { + pending_len = 0; + } + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + return pending_len; +} + +int +dhd_dbg_ring_push(dhd_dbg_ring_t *ring, dhd_dbg_ring_entry_t *hdr, void *data) +{ + unsigned long flags; + uint32 w_len; + uint32 avail_size; + dhd_dbg_ring_entry_t *w_entry, *r_entry; + + if (!ring || !hdr || !data) { + return BCME_BADARG; + } + + DHD_DBG_RING_LOCK(ring->lock, flags); + + if (ring->state != RING_ACTIVE) { + DHD_DBG_RING_UNLOCK(ring->lock, flags); + return BCME_OK; + } + + w_len = ENTRY_LENGTH(hdr); + + DHD_DBGIF(("%s: RING%d[%s] hdr->len=%u, w_len=%u, wp=%d, rp=%d, ring_start=0x%p;" + " ring_size=%u\n", + __FUNCTION__, ring->id, ring->name, hdr->len, w_len, ring->wp, ring->rp, + ring->ring_buf, ring->ring_size)); + + if (w_len > ring->ring_size) { + DHD_DBG_RING_UNLOCK(ring->lock, flags); + DHD_ERROR(("%s: RING%d[%s] w_len=%u, ring_size=%u," + " write size exceeds ring size !\n", + __FUNCTION__, ring->id, ring->name, w_len, ring->ring_size)); + return BCME_BUFTOOLONG; + } + /* Claim the space */ + do { + avail_size = DBG_RING_CHECK_WRITE_SPACE(ring->rp, ring->wp, ring->ring_size); + if (avail_size <= w_len) { + /* Prepare the space */ + if (ring->rp <= ring->wp) { + ring->tail_padded = TRUE; + ring->rem_len = ring->ring_size - ring->wp; + DHD_DBGIF(("%s: RING%d[%s] Insuffient tail space," + " rp=%d, wp=%d, rem_len=%d, ring_size=%d," + " avail_size=%d, w_len=%d\n", __FUNCTION__, + ring->id, ring->name, ring->rp, ring->wp, + ring->rem_len, ring->ring_size, avail_size, + w_len)); + + /* 0 pad insufficient tail space */ + memset((uint8 *)ring->ring_buf + ring->wp, 0, ring->rem_len); + /* If read pointer is still at the beginning, make some room */ + if (ring->rp == 0) { + r_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + + ring->rp); + ring->rp += ENTRY_LENGTH(r_entry); + ring->stat.read_bytes += ENTRY_LENGTH(r_entry); + DHD_DBGIF(("%s: rp at 0, move by one entry length" + " (%u bytes)\n", + __FUNCTION__, (uint32)ENTRY_LENGTH(r_entry))); + } + if (ring->rp == ring->wp) { + ring->rp = 0; + } + ring->wp = 0; + DHD_DBGIF(("%s: new rp=%u, wp=%u\n", + __FUNCTION__, ring->rp, ring->wp)); + } else { + /* Not enough space for new entry, free some up */ + r_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + + ring->rp); + /* check bounds before incrementing read ptr */ + if (ring->rp + ENTRY_LENGTH(r_entry) >= ring->ring_size) { + DHD_ERROR(("%s: RING%d[%s] rp points out of boundary," + "ring->wp=%u, ring->rp=%u, ring->ring_size=%d\n", + __FUNCTION__, ring->id, ring->name, ring->wp, + ring->rp, ring->ring_size)); + ASSERT(0); + DHD_DBG_RING_UNLOCK(ring->lock, flags); + return BCME_BUFTOOSHORT; + } + ring->rp += ENTRY_LENGTH(r_entry); + /* skip padding if there is one */ + if (ring->tail_padded && + ((ring->rp + ring->rem_len) == ring->ring_size)) { + DHD_DBGIF(("%s: RING%d[%s] Found padding," + " avail_size=%d, w_len=%d, set rp=0\n", + __FUNCTION__, ring->id, ring->name, + avail_size, w_len)); + ring->rp = 0; + ring->tail_padded = FALSE; + ring->rem_len = 0; + } + ring->stat.read_bytes += ENTRY_LENGTH(r_entry); + DHD_DBGIF(("%s: RING%d[%s] read_bytes=%d, wp=%d, rp=%d\n", + __FUNCTION__, ring->id, ring->name, ring->stat.read_bytes, + ring->wp, ring->rp)); + } + } else { + break; + } + } while (TRUE); + + /* check before writing to the ring */ + if (ring->wp + w_len >= ring->ring_size) { + DHD_ERROR(("%s: RING%d[%s] wp pointed out of ring boundary, " + "wp=%d, ring_size=%d, w_len=%u\n", __FUNCTION__, ring->id, + ring->name, ring->wp, ring->ring_size, w_len)); + ASSERT(0); + DHD_DBG_RING_UNLOCK(ring->lock, flags); + return BCME_BUFTOOLONG; + } + + w_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->wp); + /* header */ + memcpy(w_entry, hdr, DBG_RING_ENTRY_SIZE); + w_entry->len = hdr->len; + /* payload */ + memcpy((char *)w_entry + DBG_RING_ENTRY_SIZE, data, w_entry->len); + /* update write pointer */ + ring->wp += w_len; + + /* update statistics */ + ring->stat.written_records++; + ring->stat.written_bytes += w_len; + DHD_DBGIF(("%s : RING%d[%s] written_records %d, written_bytes %d, read_bytes=%d," + " ring->threshold=%d, wp=%d, rp=%d\n", __FUNCTION__, ring->id, ring->name, + ring->stat.written_records, ring->stat.written_bytes, ring->stat.read_bytes, + ring->threshold, ring->wp, ring->rp)); + + DHD_DBG_RING_UNLOCK(ring->lock, flags); + return BCME_OK; +} + +int +dhd_dbg_ring_pull_single(dhd_dbg_ring_t *ring, void *data, uint32 buf_len, + bool strip_header) +{ + dhd_dbg_ring_entry_t *r_entry = NULL; + uint32 rlen = 0; + char *buf = NULL; + + if (!ring || !data || buf_len <= 0) { + return 0; + } + + /* pull from ring is allowed for inactive (suspended) ring + * in case of ecounters only, this is because, for ecounters + * when a trap occurs the ring is suspended and data is then + * pulled to dump it to a file. For other rings if ring is + * not in active state return without processing (as before) + */ +#ifndef DEBUGABILITY_ECNTRS_LOGGING + if (ring->state != RING_ACTIVE) { + return 0; + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + + if (ring->rp == ring->wp) { + return 0; + } + + DHD_DBGIF(("%s: RING%d[%s] buf_len=%u, wp=%d, rp=%d, ring_start=0x%p; ring_size=%u\n", + __FUNCTION__, ring->id, ring->name, buf_len, ring->wp, ring->rp, + ring->ring_buf, ring->ring_size)); + + r_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->rp); + + /* Boundary Check */ + rlen = ENTRY_LENGTH(r_entry); + if ((ring->rp + rlen) > ring->ring_size) { + DHD_ERROR(("%s: entry len %d is out of boundary of ring size %d," + " current ring %d[%s] - rp=%d\n", __FUNCTION__, rlen, + ring->ring_size, ring->id, ring->name, ring->rp)); + return 0; + } + + if (strip_header) { + rlen = r_entry->len; + buf = (char *)r_entry + DBG_RING_ENTRY_SIZE; + } else { + rlen = ENTRY_LENGTH(r_entry); + buf = (char *)r_entry; + } + if (rlen > buf_len) { + DHD_ERROR(("%s: buf len %d is too small for entry len %d\n", + __FUNCTION__, buf_len, rlen)); + DHD_ERROR(("%s: ring %d[%s] - ring size=%d, wp=%d, rp=%d\n", + __FUNCTION__, ring->id, ring->name, ring->ring_size, + ring->wp, ring->rp)); + ASSERT(0); + return 0; + } + + memcpy(data, buf, rlen); + /* update ring context */ + ring->rp += ENTRY_LENGTH(r_entry); + /* don't pass wp but skip padding if there is one */ + if (ring->rp != ring->wp && + ring->tail_padded && ((ring->rp + ring->rem_len) == ring->ring_size)) { + DHD_DBGIF(("%s: RING%d[%s] Found padding, rp=%d, wp=%d\n", + __FUNCTION__, ring->id, ring->name, ring->rp, ring->wp)); + ring->rp = 0; + ring->tail_padded = FALSE; + ring->rem_len = 0; + } + if (ring->rp >= ring->ring_size) { + DHD_ERROR(("%s: RING%d[%s] rp pointed out of ring boundary," + " rp=%d, ring_size=%d\n", __FUNCTION__, ring->id, + ring->name, ring->rp, ring->ring_size)); + ASSERT(0); + return 0; + } + ring->stat.read_bytes += ENTRY_LENGTH(r_entry); + DHD_DBGIF(("%s RING%d[%s]read_bytes %d, wp=%d, rp=%d\n", __FUNCTION__, + ring->id, ring->name, ring->stat.read_bytes, ring->wp, ring->rp)); + + return rlen; +} + +int +dhd_dbg_ring_pull(dhd_dbg_ring_t *ring, void *data, uint32 buf_len, bool strip_hdr) +{ + int32 r_len, total_r_len = 0; + + if (!ring || !data) + return 0; + + if (ring->state != RING_ACTIVE) + return 0; + + while (buf_len > 0) { + r_len = dhd_dbg_ring_pull_single(ring, data, buf_len, strip_hdr); + if (r_len == 0) + break; + data = (uint8 *)data + r_len; + buf_len -= r_len; + total_r_len += r_len; + } + + return total_r_len; +} + +int +dhd_dbg_ring_config(dhd_dbg_ring_t *ring, int log_level, uint32 threshold) +{ + unsigned long flags = 0; + if (!ring) + return BCME_BADADDR; + + if (ring->state == RING_STOP) + return BCME_UNSUPPORTED; + + DHD_DBG_RING_LOCK(ring->lock, flags); + + if (log_level == 0) + ring->state = RING_SUSPEND; + else + ring->state = RING_ACTIVE; + + ring->log_level = log_level; + ring->threshold = MIN(threshold, DBGRING_FLUSH_THRESHOLD(ring)); + + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + return BCME_OK; +} + +void +dhd_dbg_ring_start(dhd_dbg_ring_t *ring) +{ + if (!ring) + return; + + /* Initialize the information for the ring */ + ring->state = RING_SUSPEND; + ring->log_level = 0; + ring->rp = ring->wp = 0; + ring->threshold = 0; + memset(&ring->stat, 0, sizeof(struct ring_statistics)); + memset(ring->ring_buf, 0, ring->ring_size); +} diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.h b/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.h new file mode 100644 index 0000000000000000000000000000000000000000..9b5d83572e5b87b9b9ab92efb77e0c7fa789c217 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/dhd_dbg_ring.h @@ -0,0 +1,137 @@ +/* + * DHD debug ring header file + * + * <> + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: dhd_dbg_ring.h 737951 2017-12-25 13:35:49Z $ + */ + +#ifndef __DHD_DBG_RING_H__ +#define __DHD_DBG_RING_H__ + +#include + +#define PACKED_STRUCT __attribute__ ((packed)) + +#define DBGRING_NAME_MAX 32 + +enum dbg_ring_state { + RING_STOP = 0, /* ring is not initialized */ + RING_ACTIVE, /* ring is live and logging */ + RING_SUSPEND /* ring is initialized but not logging */ +}; + +/* each entry in dbg ring has below header, to handle + * variable length records in ring + */ +typedef struct dhd_dbg_ring_entry { + uint16 len; /* payload length excluding the header */ + uint8 flags; + uint8 type; /* Per ring specific */ + uint64 timestamp; /* present if has_timestamp bit is set. */ +} PACKED_STRUCT dhd_dbg_ring_entry_t; + +struct ring_statistics { + /* number of bytes that was written to the buffer by driver */ + uint32 written_bytes; + /* number of bytes that was read from the buffer by user land */ + uint32 read_bytes; + /* number of records that was written to the buffer by driver */ + uint32 written_records; +}; + +typedef struct dhd_dbg_ring_status { + uint8 name[DBGRING_NAME_MAX]; + uint32 flags; + int ring_id; /* unique integer representing the ring */ + /* total memory size allocated for the buffer */ + uint32 ring_buffer_byte_size; + uint32 verbose_level; + /* number of bytes that was written to the buffer by driver */ + uint32 written_bytes; + /* number of bytes that was read from the buffer by user land */ + uint32 read_bytes; + /* number of records that was read from the buffer by user land */ + uint32 written_records; +} dhd_dbg_ring_status_t; + +typedef struct dhd_dbg_ring { + int id; /* ring id */ + uint8 name[DBGRING_NAME_MAX]; /* name string */ + uint32 ring_size; /* numbers of item in ring */ + uint32 wp; /* write pointer */ + uint32 rp; /* read pointer */ + uint32 log_level; /* log_level */ + uint32 threshold; /* threshold bytes */ + void * ring_buf; /* pointer of actually ring buffer */ + void * lock; /* lock for ring access */ + struct ring_statistics stat; /* statistics */ + enum dbg_ring_state state; /* ring state enum */ + bool tail_padded; /* writer does not have enough space */ + uint32 rem_len; /* number of bytes from wp_pad to end */ + bool sched_pull; /* schedule reader immediately */ +} dhd_dbg_ring_t; + +#define DBGRING_FLUSH_THRESHOLD(ring) (ring->ring_size / 3) +#define RING_STAT_TO_STATUS(ring, status) \ + do { \ + strncpy(status.name, ring->name, \ + sizeof(status.name) - 1); \ + status.ring_id = ring->id; \ + status.ring_buffer_byte_size = ring->ring_size; \ + status.written_bytes = ring->stat.written_bytes; \ + status.written_records = ring->stat.written_records; \ + status.read_bytes = ring->stat.read_bytes; \ + status.verbose_level = ring->log_level; \ + } while (0) + +#define DBG_RING_ENTRY_SIZE (sizeof(dhd_dbg_ring_entry_t)) +#define ENTRY_LENGTH(hdr) ((hdr)->len + DBG_RING_ENTRY_SIZE) +#define PAYLOAD_MAX_LEN 65535 +#define PAYLOAD_ECNTR_MAX_LEN 1404 +#define PENDING_LEN_MAX 0xFFFFFFFF +#define DBG_RING_STATUS_SIZE (sizeof(dhd_dbg_ring_status_t)) + +#define TXACTIVESZ(r, w, d) (((r) <= (w)) ? ((w) - (r)) : ((d) - (r) + (w))) +#define DBG_RING_READ_AVAIL_SPACE(w, r, d) (((w) >= (r)) ? ((w) - (r)) : ((d) - (r))) +#define DBG_RING_WRITE_SPACE_AVAIL_CONT(r, w, d) (((w) >= (r)) ? ((d) - (w)) : ((r) - (w))) +#define DBG_RING_WRITE_SPACE_AVAIL(r, w, d) (d - (TXACTIVESZ(r, w, d))) +#define DBG_RING_CHECK_WRITE_SPACE(r, w, d) \ + MIN(DBG_RING_WRITE_SPACE_AVAIL(r, w, d), DBG_RING_WRITE_SPACE_AVAIL_CONT(r, w, d)) + +typedef void (*os_pullreq_t)(void *os_priv, const int ring_id); + +int dhd_dbg_ring_init(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring, uint16 id, uint8 *name, + uint32 ring_sz, void *allocd_buf); +void dhd_dbg_ring_deinit(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring); +int dhd_dbg_ring_push(dhd_dbg_ring_t *ring, dhd_dbg_ring_entry_t *hdr, void *data); +int dhd_dbg_ring_pull(dhd_dbg_ring_t *ring, void *data, uint32 buf_len, + bool strip_hdr); +int dhd_dbg_ring_pull_single(dhd_dbg_ring_t *ring, void *data, uint32 buf_len, + bool strip_header); +uint32 dhd_dbg_ring_get_pending_len(dhd_dbg_ring_t *ring); +void dhd_dbg_ring_sched_pull(dhd_dbg_ring_t *ring, uint32 pending_len, + os_pullreq_t pull_fn, void *os_pvt, const int id); +int dhd_dbg_ring_config(dhd_dbg_ring_t *ring, int log_level, uint32 threshold); +void dhd_dbg_ring_start(dhd_dbg_ring_t *ring); +#endif /* __DHD_DBG_RING_H__ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_debug.c b/drivers/net/wireless/bcmdhd_oo/dhd_debug.c index 88eccc4d4871aad71951b4dbc412f918a402eacf..cea9b18835b7dd1fcda2d4b55c503d1f5af3cc1a 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_debug.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_debug.c @@ -3,14 +3,14 @@ * * <> * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,12 +18,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: dhd_debug.c 711908 2017-07-20 10:37:34Z $ + * $Id: dhd_debug.c 737983 2017-12-26 07:10:52Z $ */ #include @@ -33,31 +33,18 @@ #include #include #include +#include #include #include +#include #include #include #include -#if defined(DHD_EFI) -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#define container_of(ptr, type, member) \ - ((type *)((char *)(ptr) - offsetof(type, member))) -#endif - -#define DBGRING_FLUSH_THRESHOLD(ring) (ring->ring_size / 3) -#define RING_STAT_TO_STATUS(ring, status) \ - do { \ - strncpy(status.name, ring->name, \ - sizeof(status.name) - 1); \ - status.ring_id = ring->id; \ - status.ring_buffer_byte_size = ring->ring_size; \ - status.written_bytes = ring->stat.written_bytes; \ - status.written_records = ring->stat.written_records; \ - status.read_bytes = ring->stat.read_bytes; \ - status.verbose_level = ring->log_level; \ - } while (0) +#if defined(DHD_EVENT_LOG_FILTER) +#include +#endif /* DHD_EVENT_LOG_FILTER */ #define DHD_PKT_INFO DHD_ERROR struct map_table { @@ -121,32 +108,32 @@ struct map_table event_tag_map[] = { /* define log level per ring type */ struct log_level_table fw_verbose_level_map[] = { - {1, EVENT_LOG_TAG_PCI_ERROR, EVENT_LOG_SET_BUS, "PCI_ERROR"}, - {1, EVENT_LOG_TAG_PCI_WARN, EVENT_LOG_SET_BUS, "PCI_WARN"}, - {2, EVENT_LOG_TAG_PCI_INFO, EVENT_LOG_SET_BUS, "PCI_INFO"}, - {3, EVENT_LOG_TAG_PCI_DBG, EVENT_LOG_SET_BUS, "PCI_DEBUG"}, - {3, EVENT_LOG_TAG_BEACON_LOG, EVENT_LOG_SET_WL, "BEACON_LOG"}, - {2, EVENT_LOG_TAG_WL_ASSOC_LOG, EVENT_LOG_SET_WL, "ASSOC_LOG"}, - {2, EVENT_LOG_TAG_WL_ROAM_LOG, EVENT_LOG_SET_WL, "ROAM_LOG"}, - {1, EVENT_LOG_TAG_TRACE_WL_INFO, EVENT_LOG_SET_WL, "WL_INFO"}, - {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, EVENT_LOG_SET_WL, "BTCOEX_INFO"}, + {1, EVENT_LOG_TAG_PCI_ERROR, "PCI_ERROR"}, + {1, EVENT_LOG_TAG_PCI_WARN, "PCI_WARN"}, + {2, EVENT_LOG_TAG_PCI_INFO, "PCI_INFO"}, + {3, EVENT_LOG_TAG_PCI_DBG, "PCI_DEBUG"}, + {3, EVENT_LOG_TAG_BEACON_LOG, "BEACON_LOG"}, + {2, EVENT_LOG_TAG_WL_ASSOC_LOG, "ASSOC_LOG"}, + {2, EVENT_LOG_TAG_WL_ROAM_LOG, "ROAM_LOG"}, + {1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL INFO"}, + {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX INFO"}, #ifdef CUSTOMER_HW4_DEBUG - {3, EVENT_LOG_TAG_SCAN_WARN, EVENT_LOG_SET_WL, "SCAN_WARN"}, + {3, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"}, #else - {1, EVENT_LOG_TAG_SCAN_WARN, EVENT_LOG_SET_WL, "SCAN_WARN"}, + {1, EVENT_LOG_TAG_SCAN_WARN, "SCAN_WARN"}, #endif /* CUSTOMER_HW4_DEBUG */ - {1, EVENT_LOG_TAG_SCAN_ERROR, EVENT_LOG_SET_WL, "SCAN_ERROR"}, - {2, EVENT_LOG_TAG_SCAN_TRACE_LOW, EVENT_LOG_SET_WL, "SCAN_TRACE_LOW"}, - {2, EVENT_LOG_TAG_SCAN_TRACE_HIGH, EVENT_LOG_SET_WL, "SCAN_TRACE_HIGH"} + {1, EVENT_LOG_TAG_SCAN_ERROR, "SCAN_ERROR"}, + {2, EVENT_LOG_TAG_SCAN_TRACE_LOW, "SCAN_TRACE_LOW"}, + {2, EVENT_LOG_TAG_SCAN_TRACE_HIGH, "SCAN_TRACE_HIGH"} }; struct log_level_table fw_event_level_map[] = { - {1, EVENT_LOG_TAG_TRACE_WL_INFO, EVENT_LOG_SET_WL, "WL_INFO"}, - {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, EVENT_LOG_SET_WL, "BTCOEX_INFO"}, + {1, EVENT_LOG_TAG_TRACE_WL_INFO, "WL_INFO"}, + {1, EVENT_LOG_TAG_TRACE_BTCOEX_INFO, "BTCOEX_INFO"}, #ifdef CUSTOMER_HW4_DEBUG - {3, EVENT_LOG_TAG_BEACON_LOG, EVENT_LOG_SET_WL, "BEACON LOG"}, + {3, EVENT_LOG_TAG_BEACON_LOG, "BEACON LOG"}, #else - {2, EVENT_LOG_TAG_BEACON_LOG, EVENT_LOG_SET_WL, "BEACON LOG"}, + {2, EVENT_LOG_TAG_BEACON_LOG, "BEACON LOG"}, #endif /* CUSTOMER_HW4_DEBUG */ }; @@ -160,9 +147,9 @@ struct map_table nan_event_map[] = { }; struct log_level_table nan_event_level_map[] = { - {1, EVENT_LOG_TAG_NAN_ERROR, 0, "NAN_ERROR"}, - {2, EVENT_LOG_TAG_NAN_INFO, 0, "NAN_INFO"}, - {3, EVENT_LOG_TAG_NAN_DBG, 0, "NAN_DEBUG"}, + {1, EVENT_LOG_TAG_NAN_ERROR, "NAN_ERROR"}, + {2, EVENT_LOG_TAG_NAN_INFO, "NAN_INFO"}, + {3, EVENT_LOG_TAG_NAN_DBG, "NAN_DEBUG"}, }; struct map_table nan_evt_tag_map[] = { @@ -193,225 +180,67 @@ struct tracelog_header { #define TRACE_LOG_MAGIC_NUMBER 0xEAE47C06 int -dhd_dbg_ring_pull_single(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len, - bool strip_header) +dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data) { dhd_dbg_ring_t *ring; - dhd_dbg_ring_entry_t *r_entry; - uint32 rlen; - char *buf; + int ret = 0; + uint32 pending_len = 0; if (!dhdp || !dhdp->dbg) { - return 0; - } - - ring = &dhdp->dbg->dbg_rings[ring_id]; - - if (ring->state != RING_ACTIVE) { - return 0; + return BCME_BADADDR; } - if (ring->rp == ring->wp) { - return 0; + if (!VALID_RING(ring_id)) { + DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id)); + return BCME_RANGE; } - r_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->rp); + ring = &dhdp->dbg->dbg_rings[ring_id]; - /* Boundary Check */ - rlen = ENTRY_LENGTH(r_entry); - if ((ring->rp + rlen) > ring->ring_size) { - DHD_ERROR(("%s: entry len %d is out of boundary of ring size %d," - " current ring %d[%s] - rp=%d\n", __FUNCTION__, rlen, - ring->ring_size, ring->id, ring->name, ring->rp)); - return 0; - } + ret = dhd_dbg_ring_push(ring, hdr, data); + if (ret != BCME_OK) + return ret; - if (strip_header) { - rlen = r_entry->len; - buf = (char *)r_entry + DBG_RING_ENTRY_SIZE; - } else { - rlen = ENTRY_LENGTH(r_entry); - buf = (char *)r_entry; - } - if (rlen > buf_len) { - DHD_ERROR(("%s: buf len %d is too small for entry len %d\n", - __FUNCTION__, buf_len, rlen)); - DHD_ERROR(("%s: ring %d[%s] - ring size=%d, wp=%d, rp=%d\n", - __FUNCTION__, ring->id, ring->name, ring->ring_size, - ring->wp, ring->rp)); - ASSERT(0); - return 0; - } + pending_len = dhd_dbg_ring_get_pending_len(ring); + dhd_dbg_ring_sched_pull(ring, pending_len, dhdp->dbg->pullreq, + dhdp->dbg->private, ring->id); - memcpy(data, buf, rlen); - /* update ring context */ - ring->rp += ENTRY_LENGTH(r_entry); - /* skip padding if there is one */ - if (ring->tail_padded && ((ring->rp + ring->rem_len) == ring->ring_size)) { - DHD_DBGIF(("%s: RING%d[%s] Found padding, rp=%d, wp=%d\n", - __FUNCTION__, ring->id, ring->name, ring->rp, ring->wp)); - ring->rp = 0; - ring->tail_padded = FALSE; - ring->rem_len = 0; - } - if (ring->rp >= ring->ring_size) { - DHD_ERROR(("%s: RING%d[%s] rp pointed out of ring boundary," - " rp=%d, ring_size=%d\n", __FUNCTION__, ring->id, - ring->name, ring->rp, ring->ring_size)); - ASSERT(0); - } - ring->stat.read_bytes += ENTRY_LENGTH(r_entry); - DHD_DBGIF(("%s RING%d[%s]read_bytes %d, wp=%d, rp=%d\n", __FUNCTION__, - ring->id, ring->name, ring->stat.read_bytes, ring->wp, ring->rp)); - - return rlen; + return ret; } int -dhd_dbg_ring_pull(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len) +dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len, + bool strip_header) { - int32 r_len, total_r_len = 0; dhd_dbg_ring_t *ring; - if (!dhdp || !dhdp->dbg) - return 0; - ring = &dhdp->dbg->dbg_rings[ring_id]; - if (ring->state != RING_ACTIVE) + if (!dhdp || !dhdp->dbg) { return 0; + } - while (buf_len > 0) { - r_len = dhd_dbg_ring_pull_single(dhdp, ring_id, data, buf_len, FALSE); - if (r_len == 0) - break; - data = (uint8 *)data + r_len; - buf_len -= r_len; - total_r_len += r_len; + if (!VALID_RING(ring_id)) { + DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id)); + return BCME_RANGE; } - return total_r_len; + ring = &dhdp->dbg->dbg_rings[ring_id]; + + return dhd_dbg_ring_pull_single(ring, data, buf_len, strip_header); } int -dhd_dbg_ring_push(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data) +dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len) { - unsigned long flags; - uint32 pending_len; - uint32 w_len; - uint32 avail_size; dhd_dbg_ring_t *ring; - dhd_dbg_ring_entry_t *w_entry, *r_entry; - if (!dhdp || !dhdp->dbg) { - return BCME_BADADDR; + if (!dhdp || !dhdp->dbg) + return 0; + if (!VALID_RING(ring_id)) { + DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id)); + return BCME_RANGE; } - ring = &dhdp->dbg->dbg_rings[ring_id]; - - if (ring->state != RING_ACTIVE) { - return BCME_OK; - } - - flags = dhd_os_spin_lock(ring->lock); - - w_len = ENTRY_LENGTH(hdr); - - if (w_len > ring->ring_size) { - dhd_os_spin_unlock(ring->lock, flags); - return BCME_ERROR; - } - - /* Claim the space */ - do { - avail_size = DBG_RING_CHECK_WRITE_SPACE(ring->rp, ring->wp, ring->ring_size); - if (avail_size <= w_len) { - /* Prepare the space */ - if (ring->rp <= ring->wp) { - ring->tail_padded = TRUE; - ring->rem_len = ring->ring_size - ring->wp; - DHD_DBGIF(("%s: RING%d[%s] Insuffient tail space," - " rp=%d, wp=%d, rem_len=%d, ring_size=%d," - " avail_size=%d, w_len=%d\n", __FUNCTION__, - ring->id, ring->name, ring->rp, ring->wp, - ring->rem_len, ring->ring_size, avail_size, - w_len)); - - /* 0 pad insufficient tail space */ - memset((uint8 *)ring->ring_buf + ring->wp, 0, ring->rem_len); - if (ring->rp == ring->wp) { - ring->rp = 0; - } - ring->wp = 0; - } else { - /* Not enough space for new entry, free some up */ - r_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + - ring->rp); - ring->rp += ENTRY_LENGTH(r_entry); - /* skip padding if there is one */ - if (ring->tail_padded && - ((ring->rp + ring->rem_len) == ring->ring_size)) { - DHD_DBGIF(("%s: RING%d[%s] Found padding," - " avail_size=%d, w_len=%d\n", __FUNCTION__, - ring->id, ring->name, avail_size, w_len)); - ring->rp = 0; - ring->tail_padded = FALSE; - ring->rem_len = 0; - } - if (ring->rp >= ring->ring_size) { - DHD_ERROR(("%s: RING%d[%s] rp points out of boundary," - " ring->rp = %d, ring->ring_size=%d\n", - __FUNCTION__, ring->id, ring->name, ring->rp, - ring->ring_size)); - ASSERT(0); - } - ring->stat.read_bytes += ENTRY_LENGTH(r_entry); - DHD_DBGIF(("%s: RING%d[%s] read_bytes %d, wp=%d, rp=%d\n", - __FUNCTION__, ring->id, ring->name, ring->stat.read_bytes, - ring->wp, ring->rp)); - } - } else { - break; - } - } while (TRUE); - - w_entry = (dhd_dbg_ring_entry_t *)((uint8 *)ring->ring_buf + ring->wp); - /* header */ - memcpy(w_entry, hdr, DBG_RING_ENTRY_SIZE); - w_entry->len = hdr->len; - /* payload */ - memcpy((char *)w_entry + DBG_RING_ENTRY_SIZE, data, w_entry->len); - /* update write pointer */ - ring->wp += w_len; - if (ring->wp >= ring->ring_size) { - DHD_ERROR(("%s: RING%d[%s] wp pointed out of ring boundary, " - "wp=%d, ring_size=%d\n", __FUNCTION__, ring->id, - ring->name, ring->wp, ring->ring_size)); - ASSERT(0); - } - /* update statistics */ - ring->stat.written_records++; - ring->stat.written_bytes += w_len; - DHD_DBGIF(("%s : RING%d[%s] written_records %d, written_bytes %d, read_bytes=%d," - " ring->threshold=%d, wp=%d, rp=%d\n", __FUNCTION__, ring->id, ring->name, - ring->stat.written_records, ring->stat.written_bytes, ring->stat.read_bytes, - ring->threshold, ring->wp, ring->rp)); - - /* Calculate current pending size */ - if (ring->stat.written_bytes > ring->stat.read_bytes) { - pending_len = ring->stat.written_bytes - ring->stat.read_bytes; - } else if (ring->stat.written_bytes < ring->stat.read_bytes) { - pending_len = 0xFFFFFFFF - ring->stat.read_bytes + ring->stat.written_bytes; - } else { - pending_len = 0; - } - - /* if the current pending size is bigger than threshold */ - if (ring->threshold > 0 && - (pending_len >= ring->threshold) && ring->sched_pull) { - dhdp->dbg->pullreq(dhdp->dbg->private, ring->id); - ring->sched_pull = FALSE; - } - dhd_os_spin_unlock(ring->lock, flags); - return BCME_OK; + return dhd_dbg_ring_pull(ring, data, buf_len, FALSE); } static int @@ -442,6 +271,11 @@ dhd_dbg_msgtrace_msg_parser(void *event_data) char *data, *s; static uint32 seqnum_prev = 0; + if (!event_data) { + DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__)); + return; + } + hdr = (msgtrace_hdr_t *)event_data; data = (char *)event_data + MSGTRACE_HDRLEN; @@ -500,9 +334,9 @@ event_get_tlv(uint16 id, const char* tlvs, uint tlvs_len) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif static int -dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) +dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *log_ptr, uint32 *data) { int ret = BCME_OK; wl_event_log_id_ver_t nan_hdr; @@ -520,7 +354,12 @@ dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) BCM_REFERENCE(eaddr_buf); - nan_hdr.t = *data; + if (log_ptr < data) { + DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data)); + return BCME_BADADDR; + } + + nan_hdr.t = *log_ptr; DHD_DBGIF(("%s: version %u event %x\n", __FUNCTION__, nan_hdr.version, nan_hdr.event)); @@ -533,16 +372,20 @@ dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) /* nan event log should at least contain a wl_event_log_id_ver_t * header and a arm cycle count */ - if (hdr->count < NAN_EVENT_LOG_MIN_LENGTH) { + if (hdr->count < 2) { return BCME_BADLEN; } memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t)); - ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t)); - if (ts_hdr->tag == EVENT_LOG_TAG_TS) { - ts_data = (uint32 *)ts_hdr - ts_hdr->count; - msg_hdr.timestamp = (uint64)ts_data[0]; - msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP; + if (log_ptr > data) { + ts_hdr = (event_log_hdr_t *)((uint8 *)log_ptr - sizeof(event_log_hdr_t)); + if (ts_hdr->tag == EVENT_LOG_TAG_TS) { + ts_data = (uint32 *)ts_hdr - ts_hdr->count; + if (ts_data >= data) { + msg_hdr.timestamp = (uint64)ts_data[0]; + msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP; + } + } } msg_hdr.type = DBG_RING_ENTRY_NAN_EVENT_TYPE; for (i = 0; i < ARRAYSIZE(nan_event_map); i++) { @@ -566,7 +409,7 @@ dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) evt_payload->event = nan_event_map[evt_idx].host_id; dest_tlvs = (char *)evt_payload->tlvs; tot_payload_len = sizeof(log_nan_event_t); - tlvs = (char *)(&data[1]); + tlvs = (char *)(&log_ptr[1]); tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT; for (i = 0; i < ARRAYSIZE(nan_evt_tag_map); i++) { tlv_data = (tlv_log *)event_get_tlv(nan_evt_tag_map[i].fw_id, @@ -596,14 +439,14 @@ dhd_dbg_nan_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) } msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_BINARY; msg_hdr.len = tot_payload_len; - dhd_dbg_ring_push(dhdp, NAN_EVENT_RING_ID, &msg_hdr, evt_payload); + dhd_dbg_push_to_ring(dhdp, NAN_EVENT_RING_ID, &msg_hdr, evt_payload); MFREE(dhdp->osh, evt_payload, evt_payload_len); } return ret; } static int -dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) +dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *log_ptr, uint32 *data) { int i = 0, match_idx = 0; int payload_len, tlv_len; @@ -624,33 +467,43 @@ dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) BCM_REFERENCE(eabuf); BCM_REFERENCE(chanbuf); + + if (log_ptr < data) { + DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data)); + return BCME_BADADDR; + } + /* get a event type and version */ - wl_log_id.t = *data; + wl_log_id.t = *log_ptr; if (wl_log_id.version != DIAG_VERSION) return BCME_VERSION; /* custom event log should at least contain a wl_event_log_id_ver_t * header and a arm cycle count */ - if (hdr->count < NAN_EVENT_LOG_MIN_LENGTH) { + if (hdr->count < 2) { return BCME_BADLEN; } - ts_hdr = (event_log_hdr_t *)((uint8 *)data - sizeof(event_log_hdr_t)); - if (ts_hdr->tag == EVENT_LOG_TAG_TS) { - ts_data = (uint32 *)ts_hdr - ts_hdr->count; - ts_saved = (uint64)ts_data[0]; + if (log_ptr > data) { + ts_hdr = (event_log_hdr_t *)((uint8 *)log_ptr - sizeof(event_log_hdr_t)); + if (ts_hdr->tag == EVENT_LOG_TAG_TS) { + ts_data = (uint32 *)ts_hdr - ts_hdr->count; + if (ts_data >= data) { + ts_saved = (uint64)ts_data[0]; + } + } } memset(&msg_hdr, 0, sizeof(dhd_dbg_ring_entry_t)); msg_hdr.timestamp = ts_saved; DHD_DBGIF(("Android Event ver %d, payload %d words, ts %llu\n", - (*data >> 16), hdr->count - 1, ts_saved)); + (*log_ptr >> 16), hdr->count - 1, ts_saved)); /* Perform endian convertion */ for (i = 0; i < hdr->count; i++) { /* *(data + i) = ntoh32(*(data + i)); */ - DHD_DATA(("%08x ", *(data + i))); + DHD_DATA(("%08x ", *(log_ptr + i))); } DHD_DATA(("\n")); msg_hdr.flags |= DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP; @@ -677,16 +530,19 @@ dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) DHD_DBGIF(("%s : event (%s)\n", __FUNCTION__, event_map[match_idx].desc)); /* get the payload length for event data (skip : log header + timestamp) */ payload_len = sizeof(log_conn_event_t) + DATA_UNIT_FOR_LOG_CNT * (hdr->count - 2); - event_data = MALLOC(dhdp->osh, payload_len); + event_data = (log_conn_event_t *)MALLOC(dhdp->osh, payload_len); if (!event_data) { DHD_ERROR(("failed to allocate the log_conn_event_t with length(%d)\n", payload_len)); return BCME_NOMEM; } + memset(event_data, 0, payload_len); event_data->event = event_map[match_idx].host_id; - dest_tlvs = (char *)event_data->tlvs; + event_data->tlvs = + (tlv_log *)((char *)event_data + offsetof(log_conn_event_t, tlvs)); + dest_tlvs = (char *)(event_data->tlvs); tot_payload_len = sizeof(log_conn_event_t); - tlvs = (char *)(&data[1]); + tlvs = (char *)(&log_ptr[1]); tlv_len = (hdr->count - 2) * DATA_UNIT_FOR_LOG_CNT; for (i = 0; i < ARRAYSIZE(event_tag_map); i++) { tlv_data = (tlv_log *)event_get_tlv(event_tag_map[i].fw_id, @@ -734,14 +590,70 @@ dhd_dbg_custom_evnt_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, uint32 *data) } } msg_hdr.len = tot_payload_len; - dhd_dbg_ring_push(dhdp, FW_EVENT_RING_ID, &msg_hdr, event_data); + dhd_dbg_push_to_ring(dhdp, FW_EVENT_RING_ID, &msg_hdr, event_data); MFREE(dhdp->osh, event_data, payload_len); } return ret; } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif + +int +replace_percent_p_to_x(char *fmt) +{ + int p_to_x_done = FALSE; + + while (*fmt != '\0') + { + /* Skip characters will we see a % */ + if (*fmt++ != '%') + { + continue; + } + + /* + * Skip any flags, field width and precision: + *Flags: Followed by % + * #, 0, -, ' ', + + */ + if (*fmt == '#') + fmt++; + + if (*fmt == '0' || *fmt == '-' || *fmt == '+') + fmt++; + + /* + * Field width: + * An optional decimal digit string (with non-zero first digit) + * specifying a minimum field width + */ + while (*fmt && bcm_isdigit(*fmt)) + fmt++; + + /* + * Precision: + * An optional precision, in the form of a period ('.') followed by an + * optional decimal digit string. + */ + if (*fmt == '.') + { + fmt++; + while (*fmt && bcm_isdigit(*fmt)) fmt++; + } + + /* If %p is seen, change it to %x */ + if (*fmt == 'p') + { + *fmt = 'x'; + p_to_x_done = TRUE; + } + if (*fmt) + fmt++; + } + + return p_to_x_done; +} /* To identify format of types %Ns where N >= 0 is a number */ bool @@ -772,10 +684,12 @@ check_valid_string_format(char *curr_ptr) #define FMTSTR_SIZE 132 #define ROMSTR_SIZE 200 #define SIZE_LOC_STR 50 -static uint64 verboselog_ts_saved = 0; +#define LOG_PRINT_CNT_MAX 16u +#define EL_PARSE_VER "V02" +#define EL_MSEC_PER_SEC 1000 static void dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, - void *raw_event_ptr) + void *raw_event_ptr, uint32 logset, uint16 block, uint32* data) { event_log_hdr_t *ts_hdr; uint32 *log_ptr = (uint32 *)hdr - hdr->count; @@ -787,13 +701,23 @@ dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, return; } - /* Get time stamp if it's updated */ - ts_hdr = (event_log_hdr_t *)((char *)log_ptr - sizeof(event_log_hdr_t)); - if (ts_hdr->tag == EVENT_LOG_TAG_TS) { - ts_data = (uint32 *)ts_hdr - ts_hdr->count; - verboselog_ts_saved = (uint64)ts_data[0]; - DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n", - ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1])); + if (log_ptr < data) { + DHD_ERROR(("Invalid log pointer, logptr : %p data : %p \n", log_ptr, data)); + return; + } + + BCM_REFERENCE(ts_hdr); + BCM_REFERENCE(ts_data); + if (log_ptr > data) { + /* Get time stamp if it's updated */ + ts_hdr = (event_log_hdr_t *)((char *)log_ptr - sizeof(event_log_hdr_t)); + if (ts_hdr->tag == EVENT_LOG_TAG_TS) { + ts_data = (uint32 *)ts_hdr - ts_hdr->count; + if (ts_data >= data) { + DHD_MSGTRACE_LOG(("EVENT_LOG_TS[0x%08x]: SYS:%08x CPU:%08x\n", + ts_data[ts_hdr->count - 1], ts_data[0], ts_data[1])); + } + } } if (hdr->tag == EVENT_LOG_TAG_ROM_PRINTF) { @@ -817,17 +741,17 @@ dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, event_log_hdr_t *hdr, } if (hdr->tag == EVENT_LOG_TAG_MSCHPROFILE || hdr->tag == EVENT_LOG_TAG_MSCHPROFILE_TLV) { - wl_mschdbg_verboselog_handler(dhdp, raw_event_ptr, hdr->tag, log_ptr); + wl_mschdbg_verboselog_handler(dhdp, raw_event_ptr, hdr, log_ptr); return; } /* print the message out in a logprint */ - dhd_dbg_verboselog_printf(dhdp, hdr, raw_event_ptr, log_ptr); + dhd_dbg_verboselog_printf(dhdp, hdr, raw_event_ptr, log_ptr, logset, block); } void dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, - void *raw_event_ptr, uint32 *log_ptr) + void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block) { dhd_event_log_t *raw_event = (dhd_event_log_t *)raw_event_ptr; uint16 count; @@ -842,15 +766,12 @@ dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, } u_arg; u_arg arg[MAX_NO_OF_ARG] = {{0}}; char *c_ptr = NULL; + struct bcmstrbuf b; BCM_REFERENCE(arg); - if (!raw_event) { - return; - } - /* print the message out in a logprint */ - if (!(raw_event->fmts) || hdr->fmt_num == 0xffff) { + if (!(raw_event->fmts)) { if (dhdp->dbg) { log_level = dhdp->dbg->dbg_rings[FW_VERBOSE_RING_ID].log_level; for (id = 0; id < ARRAYSIZE(fw_verbose_level_map); id++) { @@ -859,22 +780,44 @@ dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, return; } } - - DHD_EVENT(("%d.%d EL:tag=%d len=%d fmt=0x%x", - (uint32)verboselog_ts_saved / 1000, - (uint32)verboselog_ts_saved % 1000, - hdr->tag, - hdr->count, - hdr->fmt_num)); - - for (count = 0; count < (hdr->count-1); count++) { - if (count % 8 == 0) - DHD_EVENT(("\n\t%08x", log_ptr[count])); - else - DHD_EVENT((" %08x", log_ptr[count])); + if (hdr->fmt_num == 0xffff) { + DHD_ECNTR_LOG(("%06d.%03d EL:tag=%d len=%d fmt=0x%x", + (uint32)(log_ptr[hdr->count - 1] / EL_MSEC_PER_SEC), + (uint32)(log_ptr[hdr->count - 1] % EL_MSEC_PER_SEC), + hdr->tag, + hdr->count, + hdr->fmt_num)); + + for (count = 0; count < (hdr->count - 1); count++) { + if (count && (count % LOG_PRINT_CNT_MAX == 0)) { + DHD_ECNTR_LOG(("\n\t%08x", log_ptr[count])); + } else { + DHD_ECNTR_LOG((" %08x", log_ptr[count])); + } + } + DHD_ECNTR_LOG(("\n")); } - DHD_EVENT(("\n")); + else { + bcm_binit(&b, fmtstr_loc_buf, FMTSTR_SIZE); + bcm_bprintf(&b, "%06d.%03d EL:%s:%u:%u %d %d 0x%x", + (uint32)(log_ptr[hdr->count - 1] / EL_MSEC_PER_SEC), + (uint32)(log_ptr[hdr->count - 1] % EL_MSEC_PER_SEC), + EL_PARSE_VER, logset, block, + hdr->tag, + hdr->count, + hdr->fmt_num); + for (count = 0; count < (hdr->count - 1); count++) { + bcm_bprintf(&b, " %x", log_ptr[count]); + } + /* ensure preserve fw logs go to debug_dump only in case of customer4 */ + if (logset < WL_MAX_PRESERVE_BUFFER && + ((0x01u << logset) & dhdp->logset_prsrv_mask)) { + DHD_EVENT_MEM(("%s\n", b.origbuf)); + } else { + DHD_EVENT(("%s\n", b.origbuf)); + } + } return; } @@ -890,16 +833,29 @@ dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, raw_event->fmts[hdr->fmt_num >> 2]); hdr->count++; } else { - snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E: %6d.%3d %s", + snprintf(fmtstr_loc_buf, FMTSTR_SIZE, "CONSOLE_E:%u:%u %6d.%3d %s", + logset, block, log_ptr[hdr->count-1]/1000, (log_ptr[hdr->count - 1] % 1000), raw_event->fmts[hdr->fmt_num >> 2]); } c_ptr = fmtstr_loc_buf; } else { - DHD_ERROR(("%s: fmt number out of range \n", __FUNCTION__)); + /* for ecounters, don't print the error as it will flood */ + if (hdr->fmt_num != 0xffff) + DHD_ERROR(("%s: fmt number out of range\n", __FUNCTION__)); + else + DHD_INFO(("%s: fmt number out of range\n", __FUNCTION__)); + goto exit; + } + + if (hdr->count > MAX_NO_OF_ARG) { + DHD_ERROR(("%s: hdr->count(%d) out of range \n", __FUNCTION__, hdr->count)); goto exit; } + /* Replace all %p to %x to handle 32 bit %p */ + replace_percent_p_to_x(fmtstr_loc_buf); + for (count = 0; count < (hdr->count - 1); count++) { if (c_ptr != NULL) if ((c_ptr = bcmstrstr(c_ptr, "%")) != NULL) @@ -946,23 +902,31 @@ dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, } } - /* Print FW logs */ - DHD_FWLOG((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3], - arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10], - arg[11], arg[12], arg[13], arg[14], arg[15])); + /* ensure preserve fw logs go to debug_dump only in case of customer4 */ + if (logset < WL_MAX_PRESERVE_BUFFER && + ((0x01u << logset) & dhdp->logset_prsrv_mask)) { + DHD_EVENT_MEM((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3], + arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10], + arg[11], arg[12], arg[13], arg[14], arg[15])); + } else { + DHD_EVENT((fmtstr_loc_buf, arg[0], arg[1], arg[2], arg[3], + arg[4], arg[5], arg[6], arg[7], arg[8], arg[9], arg[10], + arg[11], arg[12], arg[13], arg[14], arg[15])); + } exit: MFREE(dhdp->osh, str_buf, (MAX_NO_OF_ARG * SIZE_LOC_STR)); } -static void +void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, - void *raw_event_ptr, uint datalen) + void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present, + uint32 msgtrace_seqnum) { msgtrace_hdr_t *hdr; - char *data; + char *data, *tmpdata; int id; - uint32 log_hdr_len = sizeof(event_log_hdr_t); + const uint32 log_hdr_len = sizeof(event_log_hdr_t); uint32 log_pyld_len; static uint32 seqnum_prev = 0; event_log_hdr_t *log_hdr; @@ -974,20 +938,52 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, dhd_dbg_ring_entry_t msg_hdr; char *logbuf; struct tracelog_header *logentry_header; + uint ring_data_len = 0; + bool ecntr_pushed = FALSE; + uint32 logset = 0; + uint16 block = 0; + uint min_expected_len = 0; + + BCM_REFERENCE(ecntr_pushed); + + if (msgtrace_hdr_present) + min_expected_len = (MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_LEN); + else + min_expected_len = EVENT_LOG_BLOCK_LEN; /* log trace event consists of: * msgtrace header * event log block header * event log payload */ - if (datalen <= MSGTRACE_HDRLEN + EVENT_LOG_BLOCK_HDRLEN) { + if (!event_data || (datalen <= min_expected_len)) { + DHD_ERROR(("%s: Not processing due to invalid event_data : %p or length : %d\n", + __FUNCTION__, event_data, datalen)); + if (event_data && msgtrace_hdr_present) { + prhex("event_data dump", event_data, datalen); + tmpdata = (char *)event_data + MSGTRACE_HDRLEN; + if (tmpdata) { + DHD_ERROR(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n", + ltoh16(*((uint16 *)(tmpdata+2))), + ltoh32(*((uint32 *)(tmpdata + 4))), + ltoh16(*((uint16 *)(tmpdata))))); + } + } else if (!event_data) { + DHD_ERROR(("%s: event_data is NULL, cannot dump prhex\n", __FUNCTION__)); + } return; } - hdr = (msgtrace_hdr_t *)event_data; - data = (char *)event_data + MSGTRACE_HDRLEN; - datalen -= MSGTRACE_HDRLEN; - if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, ntoh32(hdr->seqnum))) + if (msgtrace_hdr_present) { + hdr = (msgtrace_hdr_t *)event_data; + data = (char *)event_data + MSGTRACE_HDRLEN; + datalen -= MSGTRACE_HDRLEN; + msgtrace_seqnum = hdr->seqnum; + } else { + data = (char *)event_data; + } + + if (dhd_dbg_msgtrace_seqchk(&seqnum_prev, ntoh32(msgtrace_seqnum))) return; /* Save the whole message to event log ring */ @@ -998,20 +994,21 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, logentry_header = (struct tracelog_header *)logbuf; logentry_header->magic_num = TRACE_LOG_MAGIC_NUMBER; logentry_header->buf_size = datalen; - logentry_header->seq_num = hdr->seqnum; + logentry_header->seq_num = msgtrace_seqnum; msg_hdr.type = DBG_RING_ENTRY_DATA_TYPE; + ring_data_len = datalen + sizeof(*logentry_header); + if ((sizeof(*logentry_header) + datalen) > PAYLOAD_MAX_LEN) { DHD_ERROR(("%s:Payload len=%u exceeds max len\n", __FUNCTION__, ((uint)sizeof(*logentry_header) + datalen))); - VMFREE(dhdp->osh, logbuf, sizeof(*logentry_header) + datalen); - return; + goto exit; } msg_hdr.len = sizeof(*logentry_header) + datalen; memcpy(logbuf + sizeof(*logentry_header), data, datalen); - dhd_dbg_ring_push(dhdp, FW_VERBOSE_RING_ID, &msg_hdr, logbuf); - VMFREE(dhdp->osh, logbuf, sizeof(*logentry_header) + datalen); + DHD_DBGIF(("%s: datalen %d %d\n", __FUNCTION__, msg_hdr.len, datalen)); + dhd_dbg_push_to_ring(dhdp, FW_VERBOSE_RING_ID, &msg_hdr, logbuf); /* Print sequence number, originating set and length of received * event log buffer. Refer to event log buffer structure in @@ -1020,6 +1017,10 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, DHD_MSGTRACE_LOG(("EVENT_LOG_HDR[0x%x]: Set: 0x%08x length = %d\n", ltoh16(*((uint16 *)(data+2))), ltoh32(*((uint32 *)(data + 4))), ltoh16(*((uint16 *)(data))))); + + logset = ltoh32(*((uint32 *)(data + 4))); + block = ltoh16(*((uint16 *)(data+2))); + data += EVENT_LOG_BLOCK_HDRLEN; datalen -= EVENT_LOG_BLOCK_HDRLEN; @@ -1042,21 +1043,24 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, datalen -= log_hdr_len; continue; } - /* Check argument count, any event log should contain at least + /* Check argument count (for non-ecounter events only), + * any event log should contain at least * one argument (4 bytes) for arm cycle count and up to 16 - * arguments when the format is valid + * arguments except EVENT_LOG_TAG_STATS which could use the + * whole payload of 256 words */ if (log_hdr->count == 0) { break; } - if ((log_hdr->count > MAX_NO_OF_ARG) && (log_hdr->fmt_num != 0xffff)) { + if ((log_hdr->tag != EVENT_LOG_TAG_STATS) && (log_hdr->count > MAX_NO_OF_ARG)) { break; } log_pyld_len = log_hdr->count * DATA_UNIT_FOR_LOG_CNT; /* log data should not cross the event data boundary */ - if ((char *)log_hdr - data < log_pyld_len) + if ((uint32)((char *)log_hdr - data) < log_pyld_len) { break; + } /* skip 4 bytes time stamp packet */ if (log_hdr->tag == EVENT_LOG_TAG_TS) { datalen -= log_pyld_len + log_hdr_len; @@ -1078,16 +1082,42 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif log_item = (loglist_item_t *)container_of(cur, loglist_item_t, list); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif log_hdr = log_item->hdr; log_ptr = (uint32 *)log_hdr - log_hdr->count; dll_delete(cur); MFREE(dhdp->osh, log_item, sizeof(*log_item)); +#if defined(DEBUGABILITY_ECNTRS_LOGGING) && defined(DHD_LOG_DUMP) + if ((log_hdr->tag == EVENT_LOG_TAG_ECOUNTERS_TIME_DATA) || + ((log_hdr->tag == EVENT_LOG_TAG_STATS) && + (log_hdr->fmt_num == 0xffff))) { + if (!ecntr_pushed && dhd_log_dump_ecntr_enabled()) { + /* check msg hdr len before pushing */ + if (msg_hdr.len > (sizeof(*logentry_header) + + PAYLOAD_ECNTR_MAX_LEN)) { + DHD_ERROR(("%s: EVENT_LOG_VALIDATION_FAILS: " + "msg_hdr.len=%u, max allowed for ecntrs=%u", + __FUNCTION__, msg_hdr.len, + (uint32)(sizeof(*logentry_header) + + PAYLOAD_ECNTR_MAX_LEN))); + goto exit; + } + dhd_dbg_ring_push(dhdp->ecntr_dbg_ring, &msg_hdr, logbuf); + ecntr_pushed = TRUE; + } + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING && DHD_LOG_DUMP */ +#if defined(DHD_EVENT_LOG_FILTER) + if (log_hdr->tag == EVENT_LOG_TAG_STATS) { + dhd_event_log_filter_event_handler(dhdp, log_hdr, log_ptr); + } +#endif /* DHD_EVENT_LOG_FILTER */ + /* Before DHD debugability is implemented WLC_E_TRACE had been * used to carry verbose logging from firmware. We need to * be able to handle those messages even without a initialized @@ -1112,7 +1142,8 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, * this is not NAN event type data */ if (dhd_dbg_nan_event_handler(dhdp, - log_hdr, log_ptr) != BCME_VERSION) { + log_hdr, log_ptr, (uint32 *)data) + != BCME_VERSION) { msg_processed = TRUE; } break; @@ -1127,7 +1158,8 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, * this is not event type data */ if (dhd_dbg_custom_evnt_handler(dhdp, - log_hdr, log_ptr) != BCME_VERSION) { + log_hdr, log_ptr, (uint32 *)data) + != BCME_VERSION) { msg_processed = TRUE; } break; @@ -1136,15 +1168,21 @@ dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, } } if (!msg_processed) - dhd_dbg_verboselog_handler(dhdp, log_hdr, raw_event_ptr); + dhd_dbg_verboselog_handler(dhdp, log_hdr, raw_event_ptr, + logset, block, (uint32 *)data); } + +exit: + VMFREE(dhdp->osh, logbuf, ring_data_len); } #else /* !SHOW_LOGTRACE */ static INLINE void dhd_dbg_verboselog_handler(dhd_pub_t *dhdp, - event_log_hdr_t *hdr, void *raw_event_ptr) {}; -static INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, - void *event_data, void *raw_event_ptr, uint datalen) {}; + event_log_hdr_t *hdr, void *raw_event_ptr, uint32 logset, uint16 block, + uint32 *data) {}; +INLINE void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, + void *event_data, void *raw_event_ptr, uint datalen, + bool msgtrace_hdr_present, uint32 msgtrace_seqnum) {}; #endif /* SHOW_LOGTRACE */ #ifndef MACOSX_DHD void @@ -1164,86 +1202,11 @@ dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data, if (hdr->trace_type == MSGTRACE_HDR_TYPE_MSG) dhd_dbg_msgtrace_msg_parser(event_data); else if (hdr->trace_type == MSGTRACE_HDR_TYPE_LOG) - dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen); + dhd_dbg_msgtrace_log_parser(dhdp, event_data, raw_event_ptr, datalen, + TRUE, 0); } -#endif /* MACOSX_DHD */ -static int -dhd_dbg_ring_init(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring, uint16 id, uint8 *name, - uint32 ring_sz) -{ - void *buf; - unsigned long flags; - - buf = MALLOCZ(dhdp->osh, ring_sz); - if (!buf) - return BCME_NOMEM; - - ring->lock = dhd_os_spin_lock_init(dhdp->osh); - - flags = dhd_os_spin_lock(ring->lock); - ring->id = id; - strncpy(ring->name, name, DBGRING_NAME_MAX); - ring->name[DBGRING_NAME_MAX - 1] = 0; - ring->ring_size = ring_sz; - ring->wp = ring->rp = 0; - ring->ring_buf = buf; - ring->threshold = DBGRING_FLUSH_THRESHOLD(ring); - ring->state = RING_SUSPEND; - ring->sched_pull = TRUE; - ring->rem_len = 0; - dhd_os_spin_unlock(ring->lock, flags); - - return BCME_OK; -} - -static void -dhd_dbg_ring_deinit(dhd_pub_t *dhdp, dhd_dbg_ring_t *ring) -{ - void *buf; - uint32 ring_sz; - unsigned long flags; - if (!ring->ring_buf) - return; - - flags = dhd_os_spin_lock(ring->lock); - ring->id = 0; - ring->name[0] = 0; - ring_sz = ring->ring_size; - ring->ring_size = 0; - ring->wp = ring->rp = 0; - buf = ring->ring_buf; - ring->ring_buf = NULL; - memset(&ring->stat, 0, sizeof(ring->stat)); - ring->threshold = 0; - ring->state = RING_STOP; - dhd_os_spin_unlock(ring->lock, flags); - - dhd_os_spin_lock_deinit(dhdp->osh, ring->lock); - - MFREE(dhdp->osh, buf, ring_sz); -} - -uint8 -dhd_dbg_find_sets_by_tag(uint16 tag) -{ - uint i; - uint8 sets = 0; - - for (i = 0; i < ARRAYSIZE(fw_verbose_level_map); i++) { - if (fw_verbose_level_map[i].tag == tag) { - sets |= fw_verbose_level_map[i].sets; - } - } - - for (i = 0; i < ARRAYSIZE(fw_event_level_map); i++) { - if (fw_event_level_map[i].tag == tag) { - sets |= fw_event_level_map[i].sets; - } - } - - return sets; -} +#endif /* MACOSX_DHD */ /* * dhd_dbg_set_event_log_tag : modify the state of an event log tag @@ -1258,8 +1221,8 @@ dhd_dbg_set_event_log_tag(dhd_pub_t *dhdp, uint16 tag, uint8 set) memset(&pars, 0, sizeof(pars)); pars.tag = tag; - pars.set = dhd_dbg_find_sets_by_tag(tag); - pars.flags = set ? EVENT_LOG_TAG_FLAG_LOG : EVENT_LOG_TAG_FLAG_NONE; + pars.set = set; + pars.flags = EVENT_LOG_TAG_FLAG_LOG; if (!bcm_mkiovar(cmd, (char *)&pars, sizeof(pars), iovbuf, sizeof(iovbuf))) { DHD_ERROR(("%s mkiovar failed\n", __FUNCTION__)); @@ -1277,26 +1240,20 @@ dhd_dbg_set_configuration(dhd_pub_t *dhdp, int ring_id, int log_level, int flags { dhd_dbg_ring_t *ring; uint8 set = 1; - unsigned long lock_flags; int i, array_len = 0; struct log_level_table *log_level_tbl = NULL; + if (!dhdp || !dhdp->dbg) return BCME_BADADDR; - ring = &dhdp->dbg->dbg_rings[ring_id]; - - if (ring->state == RING_STOP) - return BCME_UNSUPPORTED; + if (!VALID_RING(ring_id)) { + DHD_ERROR(("%s : invalid ring_id : %d\n", __FUNCTION__, ring_id)); + return BCME_RANGE; + } - lock_flags = dhd_os_spin_lock(ring->lock); - if (log_level == 0) - ring->state = RING_SUSPEND; - else - ring->state = RING_ACTIVE; - ring->log_level = log_level; + ring = &dhdp->dbg->dbg_rings[ring_id]; + dhd_dbg_ring_config(ring, log_level, threshold); - ring->threshold = MIN(threshold, DBGRING_FLUSH_THRESHOLD(ring)); - dhd_os_spin_unlock(ring->lock, lock_flags); if (log_level > 0) set = TRUE; @@ -1415,13 +1372,7 @@ dhd_dbg_start(dhd_pub_t *dhdp, bool start) dbg_ring = &dbg->dbg_rings[ring_id]; if (!start) { if (VALID_RING(dbg_ring->id)) { - /* Initialize the information for the ring */ - dbg_ring->state = RING_SUSPEND; - dbg_ring->log_level = 0; - dbg_ring->rp = dbg_ring->wp = 0; - dbg_ring->threshold = 0; - memset(&dbg_ring->stat, 0, sizeof(struct ring_statistics)); - memset(dbg_ring->ring_buf, 0, dbg_ring->ring_size); + dhd_dbg_ring_start(dbg_ring); } } } @@ -1495,6 +1446,12 @@ __dhd_dbg_map_tx_status_to_pkt_fate(uint16 status) case WLFC_CTL_PKTFLAG_DISCARD_NOACK: pkt_fate = TX_PKT_FATE_SENT; break; + case WLFC_CTL_PKTFLAG_EXPIRED: + pkt_fate = TX_PKT_FATE_FW_DROP_EXPTIME; + break; + case WLFC_CTL_PKTFLAG_MKTFREE: + pkt_fate = TX_PKT_FATE_FW_PKT_FREE; + break; default: pkt_fate = TX_PKT_FATE_FW_DROP_OTHER; break; @@ -1514,8 +1471,9 @@ __dhd_dbg_free_tx_pkts(dhd_pub_t *dhdp, dhd_dbg_tx_info_t *tx_pkts, DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__)); count = 0; while ((count < pkt_count) && tx_pkts) { - if (tx_pkts->info.pkt) + if (tx_pkts->info.pkt) { PKTFREE(dhdp->osh, tx_pkts->info.pkt, TRUE); + } tx_pkts++; count++; } @@ -1532,8 +1490,9 @@ __dhd_dbg_free_rx_pkts(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkts, DHD_PKT_INFO(("%s, %d\n", __FUNCTION__, __LINE__)); count = 0; while ((count < pkt_count) && rx_pkts) { - if (rx_pkts->info.pkt) + if (rx_pkts->info.pkt) { PKTFREE(dhdp->osh, rx_pkts->info.pkt, TRUE); + } rx_pkts++; count++; } @@ -1582,9 +1541,9 @@ __dhd_dbg_dump_rx_pkt_info(dhd_pub_t *dhdp, dhd_dbg_rx_info_t *rx_pkt, int dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, - dbg_mon_tx_pkts_t tx_pkt_mon, - dbg_mon_tx_status_t tx_status_mon, - dbg_mon_rx_pkts_t rx_pkt_mon) + dbg_mon_tx_pkts_t tx_pkt_mon, + dbg_mon_tx_status_t tx_status_mon, + dbg_mon_rx_pkts_t rx_pkt_mon) { dhd_dbg_tx_report_t *tx_report = NULL; @@ -1594,7 +1553,6 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, dhd_dbg_pkt_mon_state_t tx_pkt_state; dhd_dbg_pkt_mon_state_t tx_status_state; dhd_dbg_pkt_mon_state_t rx_pkt_state; - gfp_t kflags; uint32 alloc_len; int ret = BCME_OK; unsigned long flags; @@ -1621,11 +1579,9 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, return BCME_OK; } - kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; - /* allocate and initialize tx packet monitoring */ alloc_len = sizeof(*tx_report); - tx_report = (dhd_dbg_tx_report_t *)kzalloc(alloc_len, kflags); + tx_report = (dhd_dbg_tx_report_t *)MALLOCZ(dhdp->osh, alloc_len); if (unlikely(!tx_report)) { DHD_ERROR(("%s(): could not allocate memory for - " "dhd_dbg_tx_report_t\n", __FUNCTION__)); @@ -1634,7 +1590,7 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, } alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN); - tx_pkts = (dhd_dbg_tx_info_t *)kzalloc(alloc_len, kflags); + tx_pkts = (dhd_dbg_tx_info_t *)MALLOCZ(dhdp->osh, alloc_len); if (unlikely(!tx_pkts)) { DHD_ERROR(("%s(): could not allocate memory for - " "dhd_dbg_tx_info_t\n", __FUNCTION__)); @@ -1650,7 +1606,7 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, /* allocate and initialze rx packet monitoring */ alloc_len = sizeof(*rx_report); - rx_report = (dhd_dbg_rx_report_t *)kzalloc(alloc_len, kflags); + rx_report = (dhd_dbg_rx_report_t *)MALLOCZ(dhdp->osh, alloc_len); if (unlikely(!rx_report)) { DHD_ERROR(("%s(): could not allocate memory for - " "dhd_dbg_rx_report_t\n", __FUNCTION__)); @@ -1659,7 +1615,7 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, } alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN); - rx_pkts = (dhd_dbg_rx_info_t *)kzalloc(alloc_len, kflags); + rx_pkts = (dhd_dbg_rx_info_t *)MALLOCZ(dhdp->osh, alloc_len); if (unlikely(!rx_pkts)) { DHD_ERROR(("%s(): could not allocate memory for - " "dhd_dbg_rx_info_t\n", __FUNCTION__)); @@ -1678,10 +1634,12 @@ dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, fail: /* tx packet monitoring */ if (tx_pkts) { - kfree(tx_pkts); + alloc_len = (sizeof(*tx_pkts) * MAX_FATE_LOG_LEN); + MFREE(dhdp->osh, tx_pkts, alloc_len); } if (tx_report) { - kfree(tx_report); + alloc_len = sizeof(*tx_report); + MFREE(dhdp->osh, tx_report, alloc_len); } dhdp->dbg->pkt_mon.tx_report = NULL; dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL; @@ -1692,10 +1650,12 @@ fail: /* rx packet monitoring */ if (rx_pkts) { - kfree(rx_pkts); + alloc_len = (sizeof(*rx_pkts) * MAX_FATE_LOG_LEN); + MFREE(dhdp->osh, rx_pkts, alloc_len); } if (rx_report) { - kfree(rx_report); + alloc_len = sizeof(*rx_report); + MFREE(dhdp->osh, rx_report, alloc_len); } dhdp->dbg->pkt_mon.rx_report = NULL; dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL; @@ -1751,7 +1711,6 @@ dhd_dbg_start_pkt_monitor(dhd_pub_t *dhdp) return -EINVAL; } - tx_pkt_state = dhdp->dbg->pkt_mon.tx_pkt_state; tx_status_state = dhdp->dbg->pkt_mon.tx_status_state; rx_pkt_state = dhdp->dbg->pkt_mon.rx_pkt_state; @@ -2063,7 +2022,6 @@ dhd_dbg_monitor_get_tx_pkts(dhd_pub_t *dhdp, void __user *user_buf, } } else #endif /* CONFIG_COMPAT */ - { ptr = (wifi_tx_report_t *)user_buf; while ((count < pkt_count) && tx_pkt && ptr) { @@ -2219,10 +2177,11 @@ dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp) if (tx_report->tx_pkts) { __dhd_dbg_free_tx_pkts(dhdp, tx_report->tx_pkts, tx_report->pkt_pos); - kfree(tx_report->tx_pkts); + MFREE(dhdp->osh, tx_report->tx_pkts, + (sizeof(*tx_report->tx_pkts) * MAX_FATE_LOG_LEN)); dhdp->dbg->pkt_mon.tx_report->tx_pkts = NULL; } - kfree(tx_report); + MFREE(dhdp->osh, tx_report, sizeof(*tx_report)); dhdp->dbg->pkt_mon.tx_report = NULL; } dhdp->dbg->pkt_mon.tx_pkt_mon = NULL; @@ -2234,10 +2193,11 @@ dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp) if (rx_report->rx_pkts) { __dhd_dbg_free_rx_pkts(dhdp, rx_report->rx_pkts, rx_report->pkt_pos); - kfree(rx_report->rx_pkts); + MFREE(dhdp->osh, rx_report->rx_pkts, + (sizeof(*rx_report->rx_pkts) * MAX_FATE_LOG_LEN)); dhdp->dbg->pkt_mon.rx_report->rx_pkts = NULL; } - kfree(rx_report); + MFREE(dhdp->osh, rx_report, sizeof(*rx_report)); dhdp->dbg->pkt_mon.rx_report = NULL; } dhdp->dbg->pkt_mon.rx_pkt_mon = NULL; @@ -2246,6 +2206,27 @@ dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp) DHD_PKT_MON(("%s(): packet monitor detach succeeded\n", __FUNCTION__)); return BCME_OK; } +bool +dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid, + uint16 status) +{ + bool pkt_fate = TRUE; + if (dhdp->d11_tx_status) { + pkt_fate = (status == WLFC_CTL_PKTFLAG_DISCARD) ? TRUE : FALSE; + DHD_DBG_PKT_MON_TX_STATUS(dhdp, pkt, pktid, status); + } + return pkt_fate; +} + +#else /* DBG_PKT_MON */ + +bool +dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, + uint32 pktid, uint16 status) +{ + return TRUE; +} + #endif /* DBG_PKT_MON */ /* @@ -2257,30 +2238,44 @@ int dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq, dbg_urgent_noti_t os_urgent_notifier, void *os_priv) { - dhd_dbg_t *dbg; - int ret, ring_id; + dhd_dbg_t *dbg = NULL; + dhd_dbg_ring_t *ring = NULL; + int ret = BCME_ERROR, ring_id = 0; + void *buf = NULL; dbg = MALLOCZ(dhdp->osh, sizeof(dhd_dbg_t)); if (!dbg) return BCME_NOMEM; + buf = MALLOCZ(dhdp->osh, FW_VERBOSE_RING_SIZE); + if (!buf) + goto error; ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_VERBOSE_RING_ID], FW_VERBOSE_RING_ID, - (uint8 *)FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE); + (uint8 *)FW_VERBOSE_RING_NAME, FW_VERBOSE_RING_SIZE, buf); if (ret) goto error; + buf = MALLOCZ(dhdp->osh, FW_EVENT_RING_SIZE); + if (!buf) + goto error; ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[FW_EVENT_RING_ID], FW_EVENT_RING_ID, - (uint8 *)FW_EVENT_RING_NAME, FW_EVENT_RING_SIZE); + (uint8 *)FW_EVENT_RING_NAME, FW_EVENT_RING_SIZE, buf); if (ret) goto error; + buf = MALLOCZ(dhdp->osh, DHD_EVENT_RING_SIZE); + if (!buf) + goto error; ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[DHD_EVENT_RING_ID], DHD_EVENT_RING_ID, - (uint8 *)DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE); + (uint8 *)DHD_EVENT_RING_NAME, DHD_EVENT_RING_SIZE, buf); if (ret) goto error; + buf = MALLOCZ(dhdp->osh, NAN_EVENT_RING_SIZE); + if (!buf) + goto error; ret = dhd_dbg_ring_init(dhdp, &dbg->dbg_rings[NAN_EVENT_RING_ID], NAN_EVENT_RING_ID, - (uint8 *)NAN_EVENT_RING_NAME, NAN_EVENT_RING_SIZE); + (uint8 *)NAN_EVENT_RING_NAME, NAN_EVENT_RING_SIZE, buf); if (ret) goto error; @@ -2294,7 +2289,13 @@ dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq, error: for (ring_id = DEBUG_RING_ID_INVALID + 1; ring_id < DEBUG_RING_ID_MAX; ring_id++) { if (VALID_RING(dbg->dbg_rings[ring_id].id)) { - dhd_dbg_ring_deinit(dhdp, &dbg->dbg_rings[ring_id]); + ring = &dbg->dbg_rings[ring_id]; + dhd_dbg_ring_deinit(dhdp, ring); + if (ring->ring_buf) { + MFREE(dhdp->osh, ring->ring_buf, ring->ring_size); + ring->ring_buf = NULL; + } + ring->ring_size = 0; } } MFREE(dhdp->osh, dhdp->dbg, sizeof(dhd_dbg_t)); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_debug.h b/drivers/net/wireless/bcmdhd_oo/dhd_debug.h index 93371137101e17a8f8f18127a59d084289a03c44..9dd722e1876e0189d0d63dbc6eaed4c5769b48ae 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_debug.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_debug.h @@ -3,14 +3,14 @@ * * <> * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,18 +18,19 @@ * 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_debug.h 705824 2017-06-19 13:58:39Z $ + * $Id: dhd_debug.h 736436 2017-12-15 05:22:20Z $ */ #ifndef _dhd_debug_h_ #define _dhd_debug_h_ #include #include +#include enum { DEBUG_RING_ID_INVALID = 0, @@ -62,17 +63,15 @@ enum { DBG_RING_ENTRY_FLAGS_HAS_TIMESTAMP = (1 << (1)) }; -#define DBGRING_NAME_MAX 32 /* firmware verbose ring, ring id 1 */ #define FW_VERBOSE_RING_NAME "fw_verbose" -#define FW_VERBOSE_RING_SIZE (64 * 1024) +#define FW_VERBOSE_RING_SIZE (256 * 1024) /* firmware event ring, ring id 2 */ #define FW_EVENT_RING_NAME "fw_event" #define FW_EVENT_RING_SIZE (64 * 1024) /* DHD connection event ring, ring id 3 */ #define DHD_EVENT_RING_NAME "dhd_event" #define DHD_EVENT_RING_SIZE (64 * 1024) - /* NAN event ring, ring id 4 */ #define NAN_EVENT_RING_NAME "nan_event" #define NAN_EVENT_RING_SIZE (64 * 1024) @@ -82,8 +81,6 @@ enum { #define TLV_LOG_NEXT(tlv) \ ((tlv) ? ((tlv_log *)((uint8 *)tlv + TLV_LOG_SIZE(tlv))) : 0) -#define DBG_RING_STATUS_SIZE (sizeof(dhd_dbg_ring_status_t)) - #define VALID_RING(id) \ ((id > DEBUG_RING_ID_INVALID) && (id < DEBUG_RING_ID_MAX)) @@ -94,13 +91,6 @@ enum { #define DBG_RING_ACTIVE(dhdp, ring_id) 0 #endif /* DEBUGABILITY */ -#define TXACTIVESZ(r, w, d) (((r) <= (w)) ? ((w) - (r)) : ((d) - (r) + (w))) -#define DBG_RING_READ_AVAIL_SPACE(w, r, d) (((w) >= (r)) ? ((w) - (r)) : ((d) - (r))) -#define DBG_RING_WRITE_SPACE_AVAIL_CONT(r, w, d) (((w) >= (r)) ? ((d) - (w)) : ((r) - (w))) -#define DBG_RING_WRITE_SPACE_AVAIL(r, w, d) (d - (TXACTIVESZ(r, w, d))) -#define DBG_RING_CHECK_WRITE_SPACE(r, w, d) \ - MIN(DBG_RING_WRITE_SPACE_AVAIL(r, w, d), DBG_RING_WRITE_SPACE_AVAIL_CONT(r, w, d)) - enum { /* driver receive association command from kernel */ WIFI_EVENT_ASSOCIATION_REQUESTED = 0, @@ -297,6 +287,7 @@ typedef struct per_packet_status_entry { } per_packet_status_entry_t; #define PACKED_STRUCT __attribute__ ((packed)) + typedef struct log_conn_event { uint16 event; tlv_log *tlvs; @@ -343,42 +334,12 @@ enum { DBG_RING_ENTRY_NAN_EVENT_TYPE }; -typedef struct dhd_dbg_ring_entry { - uint16 len; /* payload length excluding the header */ - uint8 flags; - uint8 type; /* Per ring specific */ - uint64 timestamp; /* present if has_timestamp bit is set. */ -} PACKED_STRUCT dhd_dbg_ring_entry_t; - -#define DBG_RING_ENTRY_SIZE (sizeof(dhd_dbg_ring_entry_t)) - -#define ENTRY_LENGTH(hdr) ((hdr)->len + DBG_RING_ENTRY_SIZE) - -#define PAYLOAD_MAX_LEN 65535 - -typedef struct dhd_dbg_ring_status { - uint8 name[DBGRING_NAME_MAX]; - uint32 flags; - int ring_id; /* unique integer representing the ring */ - /* total memory size allocated for the buffer */ - uint32 ring_buffer_byte_size; - uint32 verbose_level; - /* number of bytes that was written to the buffer by driver */ - uint32 written_bytes; - /* number of bytes that was read from the buffer by user land */ - uint32 read_bytes; - /* number of records that was read from the buffer by user land */ - uint32 written_records; -} dhd_dbg_ring_status_t; - struct log_level_table { int log_level; uint16 tag; - uint8 sets; char *desc; }; -#ifdef DEBUGABILITY #define DBG_EVENT_LOG(dhdp, connect_state) \ { \ do { \ @@ -388,14 +349,9 @@ struct log_level_table { &state, sizeof(state)); \ } while (0); \ } -#else -#define DBG_EVENT_LOG(dhdp, connect_state) -#endif /* DEBUGABILITY */ - #define MD5_PREFIX_LEN 4 #define MAX_FATE_LOG_LEN 32 - #define MAX_FRAME_LEN_ETHERNET 1518 #define MAX_FRAME_LEN_80211_MGMT 2352 /* 802.11-2012 Fig. 8-34 */ @@ -415,8 +371,8 @@ typedef enum { */ TX_PKT_FATE_FW_DROP_INVALID, - /* Dropped by firmware due to lack of buffer space. */ - TX_PKT_FATE_FW_DROP_NOBUFS, + /* Dropped by firmware due to lifetime expiration. */ + TX_PKT_FATE_FW_DROP_EXPTIME, /* * Dropped by firmware for any other reason. Includes @@ -440,6 +396,9 @@ typedef enum { /* Dropped by driver for any other reason. */ TX_PKT_FATE_DRV_DROP_OTHER, + /* Packet free by firmware. */ + TX_PKT_FATE_FW_PKT_FREE, + } wifi_tx_packet_fate; typedef enum { @@ -581,7 +540,6 @@ typedef struct compat_wifi_frame_info { } frame_content; } compat_wifi_frame_info_t; - typedef struct compat_wifi_tx_report { char md5_prefix[MD5_PREFIX_LEN]; wifi_tx_packet_fate fate; @@ -594,7 +552,6 @@ typedef struct compat_wifi_rx_report { compat_wifi_frame_info_t frame_inf; } compat_wifi_rx_report_t; - /* * Packet logging - internal data */ @@ -673,38 +630,6 @@ typedef struct dhd_dbg_pkt_mon dbg_mon_rx_pkts_t rx_pkt_mon; } dhd_dbg_pkt_mon_t; -enum dbg_ring_state { - RING_STOP = 0, /* ring is not initialized */ - RING_ACTIVE, /* ring is live and logging */ - RING_SUSPEND /* ring is initialized but not logging */ -}; - -struct ring_statistics { - /* number of bytes that was written to the buffer by driver */ - uint32 written_bytes; - /* number of bytes that was read from the buffer by user land */ - uint32 read_bytes; - /* number of records that was written to the buffer by driver */ - uint32 written_records; -}; - -typedef struct dhd_dbg_ring { - int id; /* ring id */ - uint8 name[DBGRING_NAME_MAX]; /* name string */ - uint32 ring_size; /* numbers of item in ring */ - uint32 wp; /* write pointer */ - uint32 rp; /* read pointer */ - uint32 log_level; /* log_level */ - uint32 threshold; /* threshold bytes */ - void * ring_buf; /* pointer of actually ring buffer */ - void * lock; /* spin lock for ring access */ - struct ring_statistics stat; /* statistics */ - enum dbg_ring_state state; /* ring state enum */ - bool tail_padded; /* writer does not have enough space */ - uint32 rem_len; /* number of bytes from wp_pad to end */ - bool sched_pull; /* schedule reader immediately */ -} dhd_dbg_ring_t; - typedef struct dhd_dbg { dhd_dbg_ring_t dbg_rings[DEBUG_RING_ID_MAX]; void *private; /* os private_data */ @@ -765,12 +690,12 @@ typedef struct dhd_dbg { #ifdef DUMP_IOCTL_IOV_LIST typedef struct dhd_iov_li { dll_t list; - uint32 cmd; - char buff[100]; + uint32 cmd; /* command number */ + char buff[100]; /* command name */ } dhd_iov_li_t; +#endif /* DUMP_IOCTL_IOV_LIST */ #define IOV_LIST_MAX_LEN 5 -#endif /* DUMP_IOCTL_IOV_LIST */ #ifdef DHD_DEBUG typedef struct { @@ -784,23 +709,28 @@ typedef struct { /* dhd_dbg functions */ extern void dhd_dbg_trace_evnt_handler(dhd_pub_t *dhdp, void *event_data, void *raw_event_ptr, uint datalen); +void dhd_dbg_msgtrace_log_parser(dhd_pub_t *dhdp, void *event_data, + void *raw_event_ptr, uint datalen, bool msgtrace_hdr_present, + uint32 msgtrace_seqnum); + extern int dhd_dbg_attach(dhd_pub_t *dhdp, dbg_pullreq_t os_pullreq, dbg_urgent_noti_t os_urgent_notifier, void *os_priv); extern void dhd_dbg_detach(dhd_pub_t *dhdp); extern int dhd_dbg_start(dhd_pub_t *dhdp, bool start); extern int dhd_dbg_set_configuration(dhd_pub_t *dhdp, int ring_id, int log_level, int flags, uint32 threshold); -extern int dhd_dbg_get_ring_status(dhd_pub_t *dhdp, int ring_id, - dhd_dbg_ring_status_t *dbg_ring_status); -extern int dhd_dbg_ring_push(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, void *data); -extern int dhd_dbg_ring_pull(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len); -extern int dhd_dbg_ring_pull_single(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len, - bool strip_header); extern int dhd_dbg_find_ring_id(dhd_pub_t *dhdp, char *ring_name); extern void *dhd_dbg_get_priv(dhd_pub_t *dhdp); extern int dhd_dbg_send_urgent_evt(dhd_pub_t *dhdp, const void *data, const uint32 len); extern void dhd_dbg_verboselog_printf(dhd_pub_t *dhdp, event_log_hdr_t *hdr, - void *raw_event_ptr, uint32 *log_ptr); + void *raw_event_ptr, uint32 *log_ptr, uint32 logset, uint16 block); +int dhd_dbg_pull_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len); +int dhd_dbg_pull_single_from_ring(dhd_pub_t *dhdp, int ring_id, void *data, uint32 buf_len, + bool strip_header); +int dhd_dbg_push_to_ring(dhd_pub_t *dhdp, int ring_id, dhd_dbg_ring_entry_t *hdr, + void *data); +int dhd_dbg_get_ring_status(dhd_pub_t *dhdp, int ring_id, + dhd_dbg_ring_status_t *dbg_ring_status); #ifdef DBG_PKT_MON extern int dhd_dbg_attach_pkt_monitor(dhd_pub_t *dhdp, @@ -820,6 +750,9 @@ extern int dhd_dbg_monitor_get_rx_pkts(dhd_pub_t *dhdp, void __user *user_buf, extern int dhd_dbg_detach_pkt_monitor(dhd_pub_t *dhdp); #endif /* DBG_PKT_MON */ +extern bool dhd_dbg_process_tx_status(dhd_pub_t *dhdp, void *pkt, + uint32 pktid, uint16 status); + /* os wrapper function */ extern int dhd_os_dbg_attach(dhd_pub_t *dhdp); extern void dhd_os_dbg_detach(dhd_pub_t *dhdp); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_debug_linux.c b/drivers/net/wireless/bcmdhd_oo/dhd_debug_linux.c index 7137529ce4631eb1529a1a7137ba9fe403a9fb02..14fa04f0c903f7fddcab6decf93c6dc1a5dd4026 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_debug_linux.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_debug_linux.c @@ -3,14 +3,14 @@ * * <> * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,12 +18,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: dhd_debug_linux.c 710862 2017-07-14 07:43:59Z $ + * $Id: dhd_debug_linux.c 730050 2017-11-03 13:06:14Z $ */ #include @@ -55,17 +55,17 @@ typedef struct dhd_dbg_os_ring_info { } linux_dbgring_info_t; struct log_level_table dhd_event_map[] = { - {1, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED, 0, "DRIVER EAPOL TX REQ"}, - {1, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED, 0, "DRIVER EAPOL RX"}, - {2, WIFI_EVENT_DRIVER_SCAN_REQUESTED, 0, "SCAN_REQUESTED"}, - {2, WIFI_EVENT_DRIVER_SCAN_COMPLETE, 0, "SCAN COMPELETE"}, - {3, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND, 0, "SCAN RESULT FOUND"}, - {2, WIFI_EVENT_DRIVER_PNO_ADD, 0, "PNO ADD"}, - {2, WIFI_EVENT_DRIVER_PNO_REMOVE, 0, "PNO REMOVE"}, - {2, WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND, 0, "PNO NETWORK FOUND"}, - {2, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED, 0, "PNO SCAN_REQUESTED"}, - {1, WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND, 0, "PNO SCAN RESULT FOUND"}, - {1, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE, 0, "PNO SCAN COMPELETE"} + {1, WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED, "DRIVER EAPOL TX REQ"}, + {1, WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED, "DRIVER EAPOL RX"}, + {2, WIFI_EVENT_DRIVER_SCAN_REQUESTED, "SCAN_REQUESTED"}, + {2, WIFI_EVENT_DRIVER_SCAN_COMPLETE, "SCAN COMPELETE"}, + {3, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND, "SCAN RESULT FOUND"}, + {2, WIFI_EVENT_DRIVER_PNO_ADD, "PNO ADD"}, + {2, WIFI_EVENT_DRIVER_PNO_REMOVE, "PNO REMOVE"}, + {2, WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND, "PNO NETWORK FOUND"}, + {2, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED, "PNO SCAN_REQUESTED"}, + {1, WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND, "PNO SCAN RESULT FOUND"}, + {1, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE, "PNO SCAN COMPELETE"} }; static void @@ -77,6 +77,8 @@ debug_data_send(dhd_pub_t *dhdp, int ring_id, const void *data, const uint32 len ndev = dhd_linux_get_primary_netdev(dhdp); if (!ndev) return; + if (!VALID_RING(ring_id)) + return; if (ring_send_sub_cb[ring_id]) { ring_sub_send = ring_send_sub_cb[ring_id]; ring_sub_send(ndev, ring_id, data, len, ring_status); @@ -104,12 +106,12 @@ dbg_ring_poll_worker(struct work_struct *work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif linux_dbgring_info_t *ring_info = container_of(d_work, linux_dbgring_info_t, work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif dhd_pub_t *dhdp = ring_info->dhdp; int ringid = ring_info->ring_id; dhd_dbg_ring_status_t ring_status; @@ -141,7 +143,8 @@ dbg_ring_poll_worker(struct work_struct *work) goto exit; } - rlen = dhd_dbg_ring_pull(dhdp, ringid, buf, buflen); + rlen = dhd_dbg_pull_from_ring(dhdp, ringid, buf, buflen); + if (!ring->sched_pull) { ring->sched_pull = TRUE; } @@ -362,7 +365,7 @@ dhd_os_push_push_ring_data(dhd_pub_t *dhdp, int ring_id, void *data, int32 data_ } } } - ret = dhd_dbg_ring_push(dhdp, ring_id, &msg_hdr, event_data); + ret = dhd_dbg_push_to_ring(dhdp, ring_id, &msg_hdr, event_data); if (ret) { DHD_ERROR(("%s : failed to push data into the ring (%d) with ret(%d)\n", __FUNCTION__, ring_id, ret)); @@ -436,6 +439,7 @@ dhd_os_dbg_get_feature(dhd_pub_t *dhdp, int32 *features) { int ret = BCME_OK; *features = 0; +#ifdef DEBUGABILITY *features |= DBG_MEMORY_DUMP_SUPPORTED; if (FW_SUPPORTED(dhdp, logtrace)) { *features |= DBG_CONNECT_EVENT_SUPPORTED; @@ -449,6 +453,7 @@ dhd_os_dbg_get_feature(dhd_pub_t *dhdp, int32 *features) *features |= DBG_PACKET_FATE_SUPPORTED; } #endif /* DBG_PKT_MON */ +#endif /* DEBUGABILITY */ return ret; } diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.c b/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.c new file mode 100644 index 0000000000000000000000000000000000000000..b1e5cd678f2a161882c3ea0ef955f3fb616e848e --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.c @@ -0,0 +1,1325 @@ +/* + * Wifi dongle status Filter and Report + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: dhd_event_log_filter.c 734369 2017-12-04 11:22:30Z $ + */ + +/* + * Filter MODULE and Report MODULE + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define htod32(i) (i) +#define htod16(i) (i) +#define dtoh32(i) (i) +#define dtoh16(i) (i) +#define htodchanspec(i) (i) +#define dtohchanspec(i) (i) + +#define DHD_FILTER_ERR_INTERNAL(fmt, ...) DHD_ERROR(("EWPF-" fmt, ##__VA_ARGS__)) +#define DHD_FILTER_TRACE_INTERNAL(fmt, ...) DHD_INFO(("EWPF-" fmt, ##__VA_ARGS__)) + +#define DHD_FILTER_ERR(x) DHD_FILTER_ERR_INTERNAL x +#define DHD_FILTER_TRACE(x) DHD_FILTER_TRACE_INTERNAL x + +/* ========= EWP Filter functions ============= */ +//#define EWPF_DEBUG +#define EWPF_DEBUG_BUF_LEN 512 +#define EWPF_VAL_CNT_PLINE 16 + +#define EWPF_REPORT_MAX_DATA 32 /* MAX record per slice */ + +#define EWPF_INVALID (-1) +#define EWPF_XTLV_INVALID 0 + +#define EWPF_MAX_IDX_TYPE 2 +#define EWPF_IDX_TYPE_SLICE 1 +#define EWPF_IDX_TYPE_IFACE 2 + +#define EWPF_MAX_SLICE 2 /* MAX slice in dongle */ +#define EWPF_SLICE_MAIN 0 /* SLICE ID for 5GHZ */ +#define EWPF_SLICE_AUX 1 /* SLICE ID for 2GHZ */ + +#define EWPF_MAX_IFACE 2 /* MAX IFACE supported, 0: STA */ + +#define EWPF_ARM_TO_MSEC 1 +#define EWPF_MSEC_TO_SEC 1000 +#define EWPF_EPOCH 1000 +#define EWPF_NONSEC_TO_SEC 1000000000 +#define EWPF_REPORT_YEAR_MUL 10000 +#define EWPF_REPORT_MON_MUL 100 +#define EWPF_REPORT_HOUR_MUL 10000 +#define EWPF_REPORT_MIN_MUL 100 +#define EWPF_REPORT_MINUTES 60 +#define EWPF_REPORT_YEAR_BASE 1900 + +/* EWPF element of slice type */ +typedef struct { + uint32 armcycle; /* dongle arm cycle for this record */ + wl_periodic_compact_cntrs_v1_t compact_cntr; +} EWPF_slc_elem_t; + +/* EWPF element for interface type */ +typedef struct { + uint32 armcycle; /* dongle arm cycle for this record */ + wl_if_stats_t if_stat; + wl_lqm_t lqm; + wl_if_infra_stats_t infra; + wl_if_mgt_stats_t mgmt_stat; + wl_if_state_compact_t if_comp_stat; +} EWPF_ifc_elem_t; + +typedef struct { + int enabled; /* enabled/disabled */ + dhd_pub_t *dhdp; + uint32 tmp_armcycle; /* global ARM CYCLE for TAG */ + int idx_type; /* 0 : SLICE, 1: IFACE */ + int xtlv_idx; /* Slice/Interface index : global for TAG */ + void *s_ring[EWPF_MAX_SLICE]; + void *i_ring[EWPF_MAX_IFACE]; + + /* used by Report module */ + uint8 last_bssid[ETHER_ADDR_LEN]; /* BSSID of last conencted/request */ + int last_channel; + uint32 last_armcycle; /* ARM CYCLE prior last connection */ +} EWP_filter_t; + +/* status gathering functions : XTLV callback functions */ +typedef int (*EWPF_filter_cb)(void *ctx, const uint8 *data, uint16 type, uint16 len); +static int evt_xtlv_print_cb(void *ctx, const uint8 *data, uint16 type, uint16 len); +static int evt_xtlv_copy_cb(void *ctx, const uint8 *data, uint16 type, uint16 len); +static int evt_xtlv_idx_cb(void *ctx, const uint8 *data, uint16 type, uint16 len); +static int evt_xtlv_type_cb(void *ctx, const uint8 *data, uint16 type, uint16 len); +static int filter_main_cb(void *ctx, const uint8 *data, uint16 type, uint16 len); + +/* ========= Module functions : exposed to others ============= */ +int +dhd_event_log_filter_init(dhd_pub_t *dhdp, uint8 *buf, uint32 buf_size) +{ + + EWP_filter_t *filter; + int idx; + uint32 req_size; + uint32 s_ring_size; /* slice ring */ + uint32 i_ring_size; /* interface ring */ + uint8 *buf_ptr = buf; + DHD_FILTER_ERR(("STARTED\n")); + + if (!dhdp || !buf) { + DHD_FILTER_ERR(("INVALID PTR: dhdp:%p buf:%p\n", dhdp, buf)); + return BCME_ERROR; + } + + i_ring_size = s_ring_size = dhd_ring_get_hdr_size(); + s_ring_size += ((uint32)sizeof(EWPF_slc_elem_t)) * EWPF_REPORT_MAX_DATA; + i_ring_size += ((uint32)sizeof(EWPF_ifc_elem_t)) * EWPF_REPORT_MAX_DATA; + + req_size = s_ring_size * EWPF_MAX_SLICE + i_ring_size * EWPF_MAX_IFACE; + req_size += (uint32)sizeof(EWP_filter_t); + + if (buf_size < req_size) { + DHD_FILTER_ERR(("BUF SIZE IS TO SHORT: req:%d buf_size:%d\n", + req_size, buf_size)); + return BCME_ERROR; + } + + BCM_REFERENCE(dhdp); + filter = (EWP_filter_t *)buf; + buf_ptr += sizeof(EWP_filter_t); + + /* initialize control block */ + memset(filter, 0, sizeof(EWP_filter_t)); + + filter->idx_type = EWPF_INVALID; + filter->xtlv_idx = EWPF_INVALID; + filter->tmp_armcycle = 0; + + for (idx = 0; idx < EWPF_MAX_SLICE; idx++) { + filter->s_ring[idx] = dhd_ring_init(buf_ptr, s_ring_size, + sizeof(EWPF_slc_elem_t), EWPF_REPORT_MAX_DATA); + if (!filter->s_ring[idx]) { + DHD_FILTER_ERR(("FAIL TO INIT SLICE RING: %d\n", idx)); + return BCME_ERROR; + } + buf_ptr += s_ring_size; + } + + for (idx = 0; idx < EWPF_MAX_IFACE; idx++) { + filter->i_ring[idx] = dhd_ring_init(buf_ptr, i_ring_size, + sizeof(EWPF_ifc_elem_t), EWPF_REPORT_MAX_DATA); + if (!filter->i_ring[idx]) { + DHD_FILTER_ERR(("FAIL TO INIT INTERFACE RING: %d\n", idx)); + return BCME_ERROR; + } + buf_ptr += i_ring_size; + } + + dhdp->event_log_filter = filter; + filter->dhdp = dhdp; + filter->enabled = TRUE; + return BCME_OK; +} + +void +dhd_event_log_filter_deinit(dhd_pub_t *dhdp) +{ + EWP_filter_t *filter; + int idx; + + if (!dhdp) { + return; + } + + if (dhdp->event_log_filter) { + filter = (EWP_filter_t *)dhdp->event_log_filter; + for (idx = 0; idx < EWPF_MAX_SLICE; idx ++) { + dhd_ring_deinit(filter->s_ring[idx]); + } + for (idx = 0; idx < EWPF_MAX_IFACE; idx ++) { + dhd_ring_deinit(filter->i_ring[idx]); + } + dhdp->event_log_filter = NULL; + } +} + +void +dhd_event_log_filter_notify_connect_request(dhd_pub_t *dhdp, uint8 *bssid, int channel) +{ + EWP_filter_t *filter; + void *last_elem; + + if (!dhdp || !dhdp->event_log_filter) { + return; + } + + filter = (EWP_filter_t *)dhdp->event_log_filter; + if (filter->enabled != TRUE) { + DHD_FILTER_ERR(("EWP Filter is not enabled\n")); + return; + } + + memcpy(filter->last_bssid, bssid, ETHER_ADDR_LEN); + filter->last_channel = channel; + + /* Refer STA interface */ + last_elem = dhd_ring_get_last(filter->i_ring[0]); + if (last_elem == NULL) { + filter->last_armcycle = 0; + } else { + /* EXCLUDE before connect start */ + filter->last_armcycle = *(uint32 *)last_elem + EWPF_EPOCH + 1; + } +} + +void +dhd_event_log_filter_notify_connect_done(dhd_pub_t *dhdp, uint8 *bssid, int roam) +{ + EWP_filter_t *filter; + void *last_elem; + int channel; + char buf[EWPF_DEBUG_BUF_LEN]; + int ret; + uint32 armcycle; + struct channel_info *ci; + + if (!dhdp || !dhdp->event_log_filter) { + return; + } + + filter = (EWP_filter_t *)dhdp->event_log_filter; + if (filter->enabled != TRUE) { + DHD_FILTER_ERR(("EWP Filter is not enabled\n")); + return; + } + + /* GET CHANNEL */ + *(uint32 *)buf = htod32(EWPF_DEBUG_BUF_LEN); + ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_CHANNEL, buf, EWPF_DEBUG_BUF_LEN, FALSE, 0); + if (ret != BCME_OK) { + DHD_FILTER_ERR(("FAIL TO GET BSS INFO: %d\n", ret)); + return; + } + + ci = (struct channel_info *)(buf + sizeof(uint32)); + channel = dtoh32(ci->hw_channel); + DHD_FILTER_TRACE(("CHANNEL:prev %d new:%d\n", filter->last_channel, channel)); + + memcpy(filter->last_bssid, bssid, ETHER_ADDR_LEN); + filter->last_channel = channel; + if (roam == FALSE) { + return; + } + + /* update connect time for roam */ + /* Refer STA interface */ + last_elem = dhd_ring_get_last(filter->i_ring[0]); + if (last_elem == NULL) { + armcycle = 0; + } else { + /* EXCLUDE before roam done */ + armcycle = *(uint32 *)last_elem + EWPF_EPOCH + 1; + } + + filter->last_armcycle = armcycle; +} + +/* ========= Event Handler functions and its callbacks: ============= */ +typedef struct _EWPF_tbl { + uint16 xtlv_id; /* XTLV ID, to handle */ + EWPF_filter_cb cb_func; /* specific call back function, usually for structre */ + int idx_type; /* structure specific info: belonged type */ + int max_idx; /* structure specific info: ALLOWED MAX IDX */ + uint32 offset; /* offset of structure in EWPF_elem-t, valid if cb is not null */ + struct _EWPF_tbl *tbl; /* sub table if XTLV map to XLTV */ +} EWPF_tbl_t; + +/* Context structre for XTLV callback */ +typedef struct { + dhd_pub_t *dhdp; + EWPF_tbl_t *tbl; +} EWPF_ctx_t; + +#define SLICE_INFO(a) EWPF_IDX_TYPE_SLICE, EWPF_MAX_SLICE, OFFSETOF(EWPF_slc_elem_t, a) +#define IFACE_INFO(a) EWPF_IDX_TYPE_IFACE, EWPF_MAX_IFACE, OFFSETOF(EWPF_ifc_elem_t, a) +#define NONE_INFO(a) 0, 0, a +/* XTLV TBL for WL_SLICESTATS_XTLV_PERIODIC_STATE */ +static EWPF_tbl_t EWPF_periodic[] = +{ + { + WL_STATE_COMPACT_COUNTERS, + evt_xtlv_copy_cb, + SLICE_INFO(compact_cntr), + NULL + }, + {EWPF_XTLV_INVALID, NULL, NONE_INFO(0), NULL} +}; + +static EWPF_tbl_t EWPF_if_periodic[] = +{ + { + WL_STATE_IF_COMPACT_STATE, + evt_xtlv_copy_cb, + IFACE_INFO(if_comp_stat), + NULL + }, + {EWPF_XTLV_INVALID, NULL, NONE_INFO(0), NULL} +}; + +/* XTLV TBL for EVENT_LOG_TAG_STATS */ +static EWPF_tbl_t EWPF_main[] = +{ + /* MAIN XTLV */ + { + WL_IFSTATS_XTLV_WL_SLICE, + evt_xtlv_type_cb, + NONE_INFO(0), + EWPF_main + }, + { + WL_IFSTATS_XTLV_IF, + evt_xtlv_type_cb, + NONE_INFO(0), + EWPF_main + }, + /* ID XTLVs */ + { + WL_IFSTATS_XTLV_SLICE_INDEX, + evt_xtlv_idx_cb, + NONE_INFO(0), + NULL + }, + { + WL_IFSTATS_XTLV_IF_INDEX, + evt_xtlv_idx_cb, + NONE_INFO(0), + NULL + }, + /* NORMAL XTLVS */ + { + WL_SLICESTATS_XTLV_PERIODIC_STATE, + NULL, + NONE_INFO(0), + EWPF_periodic + }, + { + WL_IFSTATS_XTLV_IF_LQM, + evt_xtlv_copy_cb, + IFACE_INFO(lqm), + NULL + }, + { + WL_IFSTATS_XTLV_GENERIC, + evt_xtlv_copy_cb, + IFACE_INFO(if_stat), + NULL + }, + { + WL_IFSTATS_XTLV_MGT_CNT, + evt_xtlv_copy_cb, + IFACE_INFO(mgmt_stat), + NULL + }, + { + WL_IFSTATS_XTLV_IF_PERIODIC_STATE, + NULL, + NONE_INFO(0), + EWPF_if_periodic + }, + { + WL_IFSTATS_XTLV_INFRA_SPECIFIC, + evt_xtlv_copy_cb, + IFACE_INFO(infra), + NULL + }, + { + WL_IFSTATS_XTLV_IF_EVENT_STATS, + evt_xtlv_print_cb, + NONE_INFO(0), + NULL + }, + + {EWPF_XTLV_INVALID, NULL, NONE_INFO(0), NULL} +}; + +static int +evt_xtlv_print_cb(void *ctx, const uint8 *data, uint16 type, uint16 len) +{ + uint8 bssid[ETHER_ADDR_LEN]; + wl_event_based_statistics_v1_t *elem; + + DHD_FILTER_TRACE(("%s type:%d %x len:%d %x\n", __FUNCTION__, type, type, len, len)); + + if (type == WL_IFSTATS_XTLV_IF_EVENT_STATS) { + elem = (wl_event_based_statistics_v1_t *)(uintptr_t)data; + if (elem->txdeauthivalclass > 0) { + memcpy(bssid, &elem->BSSID, ETHER_ADDR_LEN); + DHD_ERROR(("DHD STA sent DEAUTH frame with invalid class : %d times" + ", BSSID("MACDBG")\n", elem->txdeauthivalclass, MAC2STRDBG(bssid))); + } + } else { + DHD_FILTER_ERR(("%s TYPE(%d) IS NOT SUPPORTED TO PRINT\n", + __FUNCTION__, type)); + return BCME_ERROR; + } + + return BCME_OK; +} + +static int +evt_xtlv_copy_cb(void *ctx, const uint8 *data, uint16 type, uint16 len) +{ + EWPF_ctx_t *cur_ctx = (EWPF_ctx_t *)ctx; + EWP_filter_t *filter = (EWP_filter_t *)cur_ctx->dhdp->event_log_filter; + uint32 *armcycle; + EWPF_tbl_t *tbl; + void *ring; + void *target; + uint8 *ptr; + int tbl_idx; + uint32 elem_size; + + DHD_FILTER_TRACE(("%s type:%d %x len:%d %x\n", __FUNCTION__, type, type, len, len)); + + for (tbl_idx = 0; ; tbl_idx++) { + if (cur_ctx->tbl[tbl_idx].xtlv_id == EWPF_XTLV_INVALID) { + DHD_FILTER_ERR(("%s NOT SUPPORTED TYPE(%d)\n", __FUNCTION__, type)); + return BCME_OK; + } + if (cur_ctx->tbl[tbl_idx].xtlv_id == type) { + tbl = &cur_ctx->tbl[tbl_idx]; + break; + } + } + + /* Check Validation */ + if (filter->idx_type == EWPF_INVALID || + filter->xtlv_idx == EWPF_INVALID || + filter->idx_type != tbl->idx_type || + filter->xtlv_idx >= tbl->max_idx) { + DHD_FILTER_ERR(("XTLV VALIDATION FAILED: type:%x xtlv:%x idx:%d\n", + filter->idx_type, tbl->xtlv_id, filter->xtlv_idx)); + return BCME_OK; + } + + /* SET RING INFO */ + if (filter->idx_type == EWPF_IDX_TYPE_SLICE) { + ring = filter->s_ring[filter->xtlv_idx]; + elem_size = sizeof(EWPF_slc_elem_t); + } else { + ring = filter->i_ring[filter->xtlv_idx]; + elem_size = sizeof(EWPF_ifc_elem_t); + } + + /* Check armcycle epoch is changed */ + target = dhd_ring_get_last(ring); + if (target != NULL) { + armcycle = (uint32 *)target; + if (*armcycle + EWPF_EPOCH <= filter->tmp_armcycle) { + /* EPOCH is changed (longer than 1sec) */ + target = NULL; + } else if (*armcycle - EWPF_EPOCH >= filter->tmp_armcycle) { + /* dongle is rebooted */ + target = NULL; + } + } + + if (target == NULL) { + /* Get new idx */ + target = dhd_ring_get_empty(ring); + if (target == NULL) { + /* no available slot due to oldest slot is locked */ + DHD_FILTER_ERR(("SKIP to logging xltv(%x) due to locking\n", type)); + return BCME_OK; + } + + /* clean up target */ + armcycle = (uint32 *)target; + memset(target, 0, elem_size); + memcpy(armcycle, &filter->tmp_armcycle, sizeof(*armcycle)); + } + +#ifdef EWPF_DEBUG + DHD_FILTER_ERR(("idx:%d write_:%p %d %d\n", + filter->xtlv_idx, target, *armcycle, filter->tmp_armcycle)); +#endif // endif + + ptr = (uint8 *)target; + memcpy(ptr + cur_ctx->tbl[tbl_idx].offset, data, len); + return BCME_OK; +} + +static int +evt_xtlv_idx_cb(void *ctx, const uint8 *data, uint16 type, uint16 len) +{ + EWPF_ctx_t *cur_ctx = (EWPF_ctx_t *)ctx; + EWP_filter_t *filter = (EWP_filter_t *)cur_ctx->dhdp->event_log_filter; + + filter->xtlv_idx = data[0]; + + if (filter->idx_type == EWPF_IDX_TYPE_SLICE) { + if (type != WL_IFSTATS_XTLV_SLICE_INDEX || + filter->xtlv_idx >= EWPF_MAX_SLICE) { + goto idx_fail; + } + } else if (filter->idx_type == EWPF_IDX_TYPE_IFACE) { + if (type != WL_IFSTATS_XTLV_IF_INDEX || + filter->xtlv_idx >= EWPF_MAX_IFACE) { + DHD_FILTER_ERR(("CHANGE IFACE TO 0 in FORCE\n")); + return BCME_OK; + } + } else { + goto idx_fail; + } + return BCME_OK; + +idx_fail: + DHD_FILTER_ERR(("UNEXPECTED IDX XTLV: filter_type:%d input_type%x idx:%d\n", + filter->idx_type, type, filter->xtlv_idx)); + filter->idx_type = EWPF_INVALID; + filter->xtlv_idx = EWPF_INVALID; + return BCME_OK; +} + +static int +evt_xtlv_type_cb(void *ctx, const uint8 *data, uint16 type, uint16 len) +{ + EWPF_ctx_t *cur_ctx = (EWPF_ctx_t *)ctx; + EWP_filter_t *filter = (EWP_filter_t *)cur_ctx->dhdp->event_log_filter; + + if (type == WL_IFSTATS_XTLV_WL_SLICE) { + filter->idx_type = EWPF_IDX_TYPE_SLICE; + DHD_FILTER_TRACE(("SLICE XTLV\n")); + } else if (type == WL_IFSTATS_XTLV_IF) { + filter->idx_type = EWPF_IDX_TYPE_IFACE; + DHD_FILTER_TRACE(("IFACE XTLV\n")); + } + bcm_unpack_xtlv_buf(ctx, data, len, + BCM_XTLV_OPTION_ALIGN32, filter_main_cb); + return BCME_OK; +} + +static int +filter_main_cb(void *ctx, const uint8 *data, uint16 type, uint16 len) +{ + EWPF_ctx_t *cur_ctx = (EWPF_ctx_t *)ctx; + EWPF_ctx_t sub_ctx; + int idx; + int err; + + DHD_FILTER_TRACE(("%s type:%x len:%d\n", __FUNCTION__, type, len)); + + sub_ctx.dhdp = cur_ctx->dhdp; + for (idx = 0; ; idx++) { + if (cur_ctx->tbl[idx].xtlv_id == EWPF_XTLV_INVALID) { + DHD_FILTER_TRACE(("%s NOT SUPPORTED TYPE(%d)\n", __FUNCTION__, type)); + return BCME_OK; + } + if (cur_ctx->tbl[idx].xtlv_id == type) { + break; + } + } + + /* parse sub xtlv */ + if (cur_ctx->tbl[idx].cb_func == NULL) { + sub_ctx.tbl = cur_ctx->tbl[idx].tbl; + err = bcm_unpack_xtlv_buf(&sub_ctx, data, len, + BCM_XTLV_OPTION_ALIGN32, filter_main_cb); + return err; + } + + /* handle for structure/variable */ + return cur_ctx->tbl[idx].cb_func(ctx, data, type, len); +} + +void +dhd_event_log_filter_event_handler(dhd_pub_t *dhdp, event_log_hdr_t *log_hdr, uint32 *data) +{ + int err; + EWP_filter_t *filter; + EWPF_ctx_t ctx; + + if (!dhdp->event_log_filter) { + DHD_FILTER_ERR(("NO FILTER MODULE\n")); + return; + } + + if (!log_hdr || !data) { + DHD_FILTER_ERR(("INVALID PARAMETER\n")); + return; + } + + filter = (EWP_filter_t *)dhdp->event_log_filter; + if (filter->enabled != TRUE) { + DHD_FILTER_ERR(("FITLER IS NOT STARTED\n")); + return; + } + + /* get ARMCYCLE */ + filter->tmp_armcycle = data[log_hdr->count - 1]; + filter->idx_type = EWPF_INVALID; + filter->xtlv_idx = EWPF_INVALID; + +#ifdef EWPF_DEBUG + { + char buf[EWPF_DEBUG_BUF_LEN]; + int idx; + + memset(buf, 0, sizeof(buf)); + DHD_FILTER_ERR(("tag %d(%x) count %d(%x)\n", + log_hdr->tag, log_hdr->tag, log_hdr->count, log_hdr->count)); + for (idx = 0; idx < log_hdr->count; idx++) { + sprintf(&buf[strlen(buf)], "%08x ", data[idx]); + if ((idx + 1) % EWPF_VAL_CNT_PLINE == 0) { + DHD_FILTER_ERR(("%s\n", buf)); + memset(buf, 0, sizeof(buf)); + } + } + if (strlen(buf) > 0) { + DHD_FILTER_ERR(("%s\n", buf)); + } + } +#endif /* EWPF_DEBUG */ + + ctx.dhdp = dhdp; + ctx.tbl = EWPF_main; + if ((err = bcm_unpack_xtlv_buf( + &ctx, + (const uint8 *)data, + (log_hdr->count - 1) * sizeof(uint32), + BCM_XTLV_OPTION_ALIGN32, + filter_main_cb))) { + DHD_FILTER_ERR(("FAIL TO UNPACK XTLV: err(%d)\n", err)); + } +} +/* ========= Private Command(Serialize) ============= */ +//#define EWPR_DEBUG +#ifdef EWPR_DEBUG +#undef DHD_FILTER_TRACE +#define DHD_FILTER_TRACE DHD_FILTER_ERR +#endif /* EWPR_DEBUG */ +#define EWPR_DEBUG_BUF_LEN 512 + +#define EWP_REPORT_VERSION 0x20170905 +#define EWP_REPORT_ELEM_PRINT_BUF 256 +#define EWP_REPORT_NAME_MAX 64 + +#define EWPR_CSDCLIENT_DIFF 4 +#define EWPR_DELTA3_POS 3 +#define EWPR_DELTA2_POS 2 +#define EWPR_DELTA1_POS 1 +#define EWPR_NOW_POS 0 + +#define EWPR_INTERVAL 3 +#define EWPR_DELTA1_CNT 2 /* 6 seconds before */ +#define EWPR_DELTA2_CNT 5 /* 15 seconds before */ +#define EWPR_DELTA3_CNT 9 /* 27 seconds before */ +#define EWPR_ARRAY_CNT 10 /* INTERVAL * ARRAY total 30 seconds to lock */ + +#define EWPR_CNT_PER_LINE 5 + +/* EWP Reporter display format */ +#define EWP_DEC 1 +#define EWP_HEX 2 + +/* EWP Filter Data type */ +/* BASIC : signed + length */ +#define EWP_UINT8 2 +#define EWP_UINT16 4 +#define EWP_UINT32 8 +#define EWP_UINT64 16 +#define EWP_INT8 102 +#define EWP_INT16 104 +#define EWP_INT32 108 + +/* NON BAISC : need special handling */ +#define EWP_NON_BASIC 200 +#define EWP_DATE 201 +#define EWP_TIME 202 +#define EWP_BSSID 203 +#define EWP_OUI 204 + +/* Delimiter between values */ +#define KEY_DEL ' ' +#define RAW_DEL '_' + +/* IOVAR BUF SIZE */ +#define EWPR_IOV_BUF_LEN 64 + +typedef struct { + void *ring; /* INPUT ring to lock */ + void **elem_list; /* OUTPUT elem ptr list for each delta */ + uint32 max_armcycle; /* IN/OUT arm cycle should be less than this */ + uint32 min_armcycle; /* IN/OUT arm cycle should be bigger than this */ + uint32 max_period; /* IN allowed time diff between first and last */ + uint32 delta_cnt; /* IN finding delta count */ + uint32 *delta_list; /* IN delta values to find */ +} ewpr_lock_param_t; + +typedef struct { + char name[EWP_REPORT_NAME_MAX]; + int ring_type; /* Ring Type : EWPF_IDX_TYPE_SLICE, EWPF_IDX_TYPE_IFACE */ + uint32 offset; /* Offset from start of element structure */ + int data_type; /* Data type : one of EWP Filter Data Type */ + int display_format; /* Display format : one of EWP Reporter display */ + int display_type; /* MAX display BYTE: valid for HEX FORM */ +} ewpr_serial_info_t; + +/* offset defines */ +#define EWPR_CNT_OFFSET(a) \ + (OFFSETOF(EWPF_slc_elem_t, compact_cntr) + OFFSETOF(wl_periodic_compact_cntrs_v1_t, a)) +#define EWPR_STAT_OFFSET(a) \ + (OFFSETOF(EWPF_ifc_elem_t, if_stat) + OFFSETOF(wl_if_stats_t, a)) +#define EWPR_INFRA_OFFSET(a) \ + (OFFSETOF(EWPF_ifc_elem_t, infra) + OFFSETOF(wl_if_infra_stats_t, a)) +#define EWPR_MGMT_OFFSET(a) \ + (OFFSETOF(EWPF_ifc_elem_t, mgmt_stat) + OFFSETOF(wl_if_mgt_stats_t, a)) +#define EWPR_LQM_OFFSET(a) \ + (OFFSETOF(EWPF_ifc_elem_t, lqm) + OFFSETOF(wl_lqm_t, a)) +#define EWPR_SIGNAL_OFFSET(a) \ + (EWPR_LQM_OFFSET(current_bss) + OFFSETOF(wl_rx_signal_metric_t, a)) +#define EWPR_IF_COMP_OFFSET(a) \ + (OFFSETOF(EWPF_ifc_elem_t, if_comp_stat) + OFFSETOF(wl_if_state_compact_t, a)) + +/* serail info type define */ +#define EWPR_SERIAL_CNT(a) {\ + #a, EWPF_IDX_TYPE_SLICE, EWPR_CNT_OFFSET(a), \ + EWP_UINT32, EWP_HEX, EWP_UINT32} +#define EWPR_SERIAL_CNT_16(a) {\ + #a, EWPF_IDX_TYPE_SLICE, EWPR_CNT_OFFSET(a), \ + EWP_UINT32, EWP_HEX, EWP_UINT16} +#define EWPR_SERIAL_STAT(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_STAT_OFFSET(a), \ + EWP_UINT64, EWP_HEX, EWP_UINT32} +#define EWPR_SERIAL_INFRA(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_INFRA_OFFSET(a), \ + EWP_UINT32, EWP_HEX, EWP_UINT16} +#define EWPR_SERIAL_MGMT(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_MGMT_OFFSET(a), \ + EWP_UINT32, EWP_HEX, EWP_UINT16} +#define EWPR_SERIAL_LQM(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_LQM_OFFSET(a), \ + EWP_INT32, EWP_DEC, EWP_INT8} +#define EWPR_SERIAL_SIGNAL(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_SIGNAL_OFFSET(a), \ + EWP_INT32, EWP_DEC, EWP_INT8} +#define EWPR_SERIAL_IFCOMP_8(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_IF_COMP_OFFSET(a), \ + EWP_INT8, EWP_DEC, EWP_INT8} +#define EWPR_SERIAL_IFCOMP_16(a) {\ + #a, EWPF_IDX_TYPE_IFACE, EWPR_IF_COMP_OFFSET(a), \ + EWP_UINT16, EWP_DEC, EWP_UINT16} +#define EWPR_SERIAL_ARM(a) {\ + "armcycle:" #a, EWPF_IDX_TYPE_##a, 0, \ + EWP_UINT32, EWP_DEC, EWP_UINT32} +#define EWPR_SERIAL_NONE {"", EWPF_INVALID, 0, 0, 0, 0} + +ewpr_serial_info_t +ewpr_serial_CSDCLIENT_key_tbl[] = { + EWPR_SERIAL_STAT(txframe), + EWPR_SERIAL_STAT(txerror), + EWPR_SERIAL_STAT(rxframe), + EWPR_SERIAL_STAT(rxerror), + EWPR_SERIAL_STAT(txretrans), + EWPR_SERIAL_INFRA(rxbeaconmbss), + EWPR_SERIAL_CNT(txallfrm), + EWPR_SERIAL_CNT(rxrsptmout), + EWPR_SERIAL_CNT(rxbadplcp), + EWPR_SERIAL_CNT(rxcrsglitch), + EWPR_SERIAL_CNT(rxbadfcs), + EWPR_SERIAL_CNT_16(rxbeaconmbss), + EWPR_SERIAL_CNT_16(rxbeaconobss), + EWPR_SERIAL_NONE +}; + +ewpr_serial_info_t +ewpr_serial_CSDCLIENT_diff_tbl[] = { + EWPR_SERIAL_STAT(txframe), + EWPR_SERIAL_STAT(txerror), + EWPR_SERIAL_STAT(rxframe), + EWPR_SERIAL_STAT(rxerror), + EWPR_SERIAL_STAT(txretrans), + EWPR_SERIAL_INFRA(rxbeaconmbss), + EWPR_SERIAL_MGMT(txassocreq), + EWPR_SERIAL_MGMT(txreassocreq), + EWPR_SERIAL_MGMT(txdisassoc), + EWPR_SERIAL_MGMT(rxdisassoc), + EWPR_SERIAL_MGMT(rxassocrsp), + EWPR_SERIAL_MGMT(rxreassocrsp), + EWPR_SERIAL_MGMT(txauth), + EWPR_SERIAL_MGMT(rxauth), + EWPR_SERIAL_MGMT(txdeauth), + EWPR_SERIAL_MGMT(rxdeauth), + EWPR_SERIAL_MGMT(txaction), + EWPR_SERIAL_MGMT(rxaction), + EWPR_SERIAL_CNT(txallfrm), + EWPR_SERIAL_CNT(rxrsptmout), + EWPR_SERIAL_CNT(rxbadplcp), + EWPR_SERIAL_CNT(rxcrsglitch), + EWPR_SERIAL_CNT(rxbadfcs), + EWPR_SERIAL_CNT_16(rxbeaconmbss), + EWPR_SERIAL_CNT_16(rxbeaconobss), + EWPR_SERIAL_NONE +}; + +ewpr_serial_info_t +ewpr_serial_CSDCLIENT_array_tbl[] = { + EWPR_SERIAL_IFCOMP_8(rssi_sum), + EWPR_SERIAL_IFCOMP_8(snr), + EWPR_SERIAL_IFCOMP_8(noise_level), + EWPR_SERIAL_NONE +}; + +#ifdef EWPR_DEBUG +ewpr_serial_info_t +ewpr_serial_dbg_tbl[] = { + EWPR_SERIAL_ARM(IFACE), + EWPR_SERIAL_ARM(SLICE), + EWPR_SERIAL_NONE +}; +#endif /* EWPR_DEBUG */ + +int ewpr_set_period_lock(ewpr_lock_param_t *param); +int ewpr_diff_serial(ewpr_serial_info_t *info, char *buf, + int buf_len, void *_f_op, void *_s_op, char del); +int ewpr_single_serial(ewpr_serial_info_t *info, char *buf, int buf_len, void *ptr, char del); + +int +ewpr_serial_basic(char *buf, int buf_len, uint32 data, int format, int display_type, char del) +{ + if (format == EWP_HEX) { + switch (display_type) { + case EWP_INT8: + case EWP_UINT8: + return scnprintf(buf, buf_len, "%c%02x", del, data & 0xff); + case EWP_INT16: + case EWP_UINT16: + return scnprintf(buf, buf_len, "%c%04x", del, data & 0xffff); + case EWP_INT32: + case EWP_UINT32: + return scnprintf(buf, buf_len, "%c%08x", del, data & 0xffffffff); + default: + DHD_FILTER_ERR(("INVALID TYPE for Serial:%d", display_type)); + return 0; + } + } + + if (format == EWP_DEC) { + int32 sdata = (int32) data; + switch (display_type) { + case EWP_INT8: + case EWP_UINT8: + return scnprintf(buf, buf_len, "%c%04d", del, sdata); + case EWP_INT16: + case EWP_UINT16: + return scnprintf(buf, buf_len, "%c%06d", del, sdata); + case EWP_INT32: + case EWP_UINT32: + return scnprintf(buf, buf_len, "%c%011d", del, sdata); + default: + DHD_FILTER_ERR(("INVALID TYPE for Serial:%d", display_type)); + return 0; + } + } + + DHD_FILTER_ERR(("INVALID FORMAT for Serial:%d", format)); + return 0; +} + +int +ewpr_single_serial(ewpr_serial_info_t *info, char *buf, int buf_len, void *_ptr, char del) +{ + uint32 sval = 0; + + char *ptr = (char *)_ptr + info->offset; + + switch (info->data_type) { + case EWP_INT8: + sval = *(int8 *)ptr; + break; + case EWP_UINT8: + sval = *(uint8 *)ptr; + break; + case EWP_INT16: + sval = *(int16 *)ptr; + break; + case EWP_UINT16: + sval = *(uint16 *)ptr; + break; + case EWP_INT32: + sval = *(int32 *)ptr; + break; + case EWP_UINT32: + sval = *(uint32 *)ptr; + break; +#ifdef EWPR_DEBUG + case EWP_UINT64: + sval = (uint32)(*(uint64 *)ptr); + break; +#endif /* EWPR_DEBUG */ + default: + DHD_FILTER_ERR(("INVALID TYPE for Single Serial:%d", info->data_type)); + return 0; + } + + return ewpr_serial_basic(buf, buf_len, sval, info->display_format, info->display_type, del); +} + +int +ewpr_diff_serial(ewpr_serial_info_t *info, + char *buf, int buf_len, void *_f_op, void *_s_op, char del) +{ + char *f_op = (char *)_f_op; + char *s_op = (char *)_s_op; + uint32 diff; + + f_op = f_op + info->offset; + s_op = s_op + info->offset; + + switch (info->data_type) { + case EWP_INT8: + case EWP_UINT8: + diff = *(uint8 *)f_op - *(uint8 *)s_op; + break; + case EWP_INT16: + case EWP_UINT16: + diff = *(uint16 *)f_op - *(uint16 *)s_op; + break; + case EWP_INT32: + case EWP_UINT32: + diff = *(uint32 *)f_op - *(uint32 *)s_op; + break; + case EWP_UINT64: + diff = (uint32)(*(uint64 *)f_op - *(uint64 *)s_op); + break; + default: + DHD_FILTER_ERR(("INVALID TYPE to DIFF:%d", info->data_type)); + return 0; + } + + return ewpr_serial_basic(buf, buf_len, diff, info->display_format, info->display_type, del); +} + +#ifdef EWPR_DEBUG +void +ewpr_debug_dump(ewpr_serial_info_t *tbl, void **ring) +{ + void *elem; + int idx, idx2; + ewpr_serial_info_t *info; + char buf[EWPR_DEBUG_BUF_LEN]; + uint32 bytes_written; + int lock_cnt; + + for (idx = 0; strlen(tbl[idx].name) != 0; idx++) { + info = &tbl[idx]; + memset(buf, 0, sizeof(buf)); + lock_cnt = dhd_ring_lock_get_count(ring[info->ring_type - 1]); + elem = dhd_ring_lock_get_first(ring[info->ring_type - 1]); + bytes_written = scnprintf(buf, EWPR_DEBUG_BUF_LEN, "%s:", info->name); + for (idx2 = 0; elem && (idx2 < lock_cnt); idx2++) { + bytes_written += ewpr_single_serial(info, &buf[bytes_written], + EWPR_DEBUG_BUF_LEN - bytes_written, elem, KEY_DEL); + elem = dhd_ring_get_next(ring[info->ring_type - 1], elem); + } + DHD_FILTER_ERR(("%s\n", buf)); + } +} +#endif /* EWPR_DEBUG */ + +uint32 +dhd_event_log_filter_serialize(dhd_pub_t *dhdp, char *in_buf, uint32 tot_len, int type) +{ + EWP_filter_t *filter = (EWP_filter_t *)dhdp->event_log_filter; + void *ring[EWPF_MAX_IDX_TYPE]; + char *ret_buf = in_buf; + int slice_id; + int iface_id; + int idx, idx2; + uint32 bytes_written = 0; + void *elem[EWPF_MAX_IDX_TYPE][EWPR_CSDCLIENT_DIFF]; + void **elem_list; + int lock_cnt, lock_cnt2; + char *last_print; + void *arr_elem; + uint32 delta_list[EWPR_CSDCLIENT_DIFF]; + ewpr_lock_param_t lock_param; + int print_name = FALSE; + char cookie_str[DEBUG_DUMP_TIME_BUF_LEN]; + char iov_buf[EWPR_IOV_BUF_LEN]; + + if (type != 0) { + DHD_FILTER_ERR(("NOT SUPPORTED TYPE: %d\n", type)); + return 0; + } + + iface_id = 0; /* STA INTERFACE ONLY */ + if (filter->last_channel <= CH_MAX_2G_CHANNEL) { + slice_id = EWPF_SLICE_AUX; + } else { + slice_id = EWPF_SLICE_MAIN; + } + ring[EWPF_IDX_TYPE_SLICE - 1] = filter->s_ring[slice_id]; + ring[EWPF_IDX_TYPE_IFACE - 1] = filter->i_ring[iface_id]; + + /* Configure common LOCK parameter */ + lock_param.max_armcycle = (uint32)EWPF_INVALID; + lock_param.min_armcycle = filter->last_armcycle; + lock_param.max_period = (EWPR_ARRAY_CNT - 1)* EWPR_INTERVAL; + lock_param.max_period *= EWPF_MSEC_TO_SEC * EWPF_ARM_TO_MSEC; + lock_param.delta_cnt = ARRAYSIZE(delta_list); + lock_param.delta_list = delta_list; + + delta_list[EWPR_DELTA3_POS] = EWPR_DELTA3_CNT; + delta_list[EWPR_DELTA2_POS] = EWPR_DELTA2_CNT; + delta_list[EWPR_DELTA1_POS] = EWPR_DELTA1_CNT; + delta_list[EWPR_NOW_POS] = 0; + lock_param.ring = ring[EWPF_IDX_TYPE_IFACE -1]; + lock_param.elem_list = elem[EWPF_IDX_TYPE_IFACE -1]; + lock_cnt = ewpr_set_period_lock(&lock_param); + if (lock_cnt <= 0) { + DHD_FILTER_ERR(("FAIL TO GET IFACE LOCK: %d\n", iface_id)); + bytes_written = 0; + goto finished; + } + + delta_list[EWPR_DELTA3_POS] = EWPR_DELTA3_CNT; + delta_list[EWPR_DELTA2_POS] = EWPR_DELTA2_CNT; + delta_list[EWPR_DELTA1_POS] = EWPR_DELTA1_CNT; + delta_list[EWPR_NOW_POS] = 0; + lock_param.ring = ring[EWPF_IDX_TYPE_SLICE -1]; + lock_param.elem_list = elem[EWPF_IDX_TYPE_SLICE -1]; + lock_cnt2 = ewpr_set_period_lock(&lock_param); + if (lock_cnt2 <= 0) { + DHD_FILTER_ERR(("FAIL TO GET SLICE LOCK: %d\n", slice_id)); + goto finished; + } + + if (lock_cnt != lock_cnt2) { + DHD_FILTER_ERR(("Lock Count is Diff: iface:%d slice:%d\n", lock_cnt, lock_cnt2)); + lock_cnt = MIN(lock_cnt, lock_cnt2); + } + +#ifdef EWPR_DEBUG + print_name = TRUE; + ewpr_debug_dump(ewpr_serial_dbg_tbl, ring); + ewpr_debug_dump(ewpr_serial_CSDCLIENT_diff_tbl, ring); + ewpr_debug_dump(ewpr_serial_CSDCLIENT_array_tbl, ring); +#endif /* EWPR_DEBUG */ + + memset(ret_buf, 0, tot_len); + memset(cookie_str, 0, DEBUG_DUMP_TIME_BUF_LEN); + bytes_written = 0; + last_print = ret_buf; + + get_debug_dump_time(cookie_str); +#ifdef DHD_LOG_DUMP + dhd_logdump_cookie_save(dhdp, cookie_str, "ECNT"); +#endif // endif + + /* KEY DATA */ + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%08x", EWP_REPORT_VERSION); + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%s", KEY_DEL, cookie_str); + DHD_FILTER_ERR(("%d: %s\n", bytes_written, last_print)); + last_print = &ret_buf[bytes_written]; + + for (idx = 0; strlen(ewpr_serial_CSDCLIENT_key_tbl[idx].name) != 0; idx++) { + ewpr_serial_info_t *info = &ewpr_serial_CSDCLIENT_key_tbl[idx]; + elem_list = elem[info->ring_type - 1]; + if (print_name) { + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, " %s:", info->name); + } + bytes_written += ewpr_diff_serial(info, &ret_buf[bytes_written], + tot_len - bytes_written, + elem_list[EWPR_NOW_POS], + elem_list[EWPR_DELTA1_POS], + KEY_DEL); + if ((idx + 1) % EWPR_CNT_PER_LINE == 0) { + DHD_FILTER_ERR(("%d:%s\n", bytes_written, last_print)); + last_print = &ret_buf[bytes_written]; + } + } + + /* RAW DATA */ + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%08x", KEY_DEL, EWP_REPORT_VERSION); + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%s", RAW_DEL, cookie_str); + + for (idx = 0; strlen(ewpr_serial_CSDCLIENT_diff_tbl[idx].name) != 0; idx++) { + ewpr_serial_info_t *info = &ewpr_serial_CSDCLIENT_diff_tbl[idx]; + elem_list = elem[info->ring_type - 1]; + if (print_name) { + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, " %s:", info->name); + } + bytes_written += ewpr_diff_serial(info, &ret_buf[bytes_written], + tot_len - bytes_written, + elem_list[EWPR_NOW_POS], + elem_list[EWPR_DELTA1_POS], + RAW_DEL); + bytes_written += ewpr_diff_serial(info, &ret_buf[bytes_written], + tot_len - bytes_written, + elem_list[EWPR_DELTA1_POS], + elem_list[EWPR_DELTA2_POS], + RAW_DEL); + if ((idx + 1) % EWPR_CNT_PER_LINE == 0) { + DHD_FILTER_ERR(("%d:%s\n", bytes_written, last_print)); + last_print = &ret_buf[bytes_written]; + } + } + + /* FILL BSS SPECIFIC DATA LATER */ + if (dhd_iovar(dhdp, 0, "auth", NULL, 0, iov_buf, ARRAYSIZE(iov_buf), FALSE) < 0) { + DHD_FILTER_ERR(("fail to get auth\n")); + *(uint32 *)iov_buf = EWPF_INVALID; + + } + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%08x", RAW_DEL, *(uint32 *)iov_buf); + + if (dhd_iovar(dhdp, 0, "wsec", NULL, 0, iov_buf, ARRAYSIZE(iov_buf), FALSE) < 0) { + DHD_FILTER_ERR(("fail to get wsec\n")); + *(uint32 *)iov_buf = EWPF_INVALID; + + } + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%08x", RAW_DEL, *(uint32 *)iov_buf); + + if (dhd_iovar(dhdp, 0, "mfp", NULL, 0, iov_buf, ARRAYSIZE(iov_buf), FALSE) < 0) { + DHD_FILTER_ERR(("fail to get mfp\n")); + *(uint8 *)iov_buf = EWPF_INVALID; + + } + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%02x", RAW_DEL, *(uint8 *)iov_buf); + + if (dhd_iovar(dhdp, 0, "bip", NULL, 0, iov_buf, ARRAYSIZE(iov_buf), FALSE) < 0) { + DHD_FILTER_ERR(("fail to get bip\n")); + *(uint8 *)iov_buf = EWPF_INVALID; + } + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, "%c%02x", RAW_DEL, *(uint8 *)iov_buf); + + for (idx = 0; strlen(ewpr_serial_CSDCLIENT_array_tbl[idx].name) != 0; idx++) { + ewpr_serial_info_t *info = &ewpr_serial_CSDCLIENT_array_tbl[idx]; + if (print_name) { + bytes_written += scnprintf(&ret_buf[bytes_written], + tot_len - bytes_written, " %s:", info->name); + } + for (idx2 = 0; idx2 < EWPR_ARRAY_CNT - lock_cnt; idx2++) { + bytes_written += ewpr_serial_basic(&ret_buf[bytes_written], + tot_len - bytes_written, 0, + info->display_format, info->display_type, RAW_DEL); + } + arr_elem = elem[info->ring_type - 1][EWPR_DELTA3_POS]; + for (; idx2 < EWPR_ARRAY_CNT; idx2++) { + if (arr_elem == NULL) { + DHD_FILTER_ERR(("ARR IS NULL : %d %p \n", + idx2, elem[info->ring_type - 1][EWPR_DELTA3_POS])); + break; + } + bytes_written += ewpr_single_serial(info, &ret_buf[bytes_written], + tot_len - bytes_written, arr_elem, RAW_DEL); + arr_elem = dhd_ring_get_next(ring[info->ring_type - 1], arr_elem); + } + DHD_FILTER_ERR(("%d:%s\n", bytes_written, last_print)); + last_print = &ret_buf[bytes_written]; + } + +finished: + DHD_FILTER_ERR(("RET LEN:%d\n", (int)strlen(ret_buf))); + dhd_ring_lock_free(ring[EWPF_IDX_TYPE_SLICE - 1]); + dhd_ring_lock_free(ring[EWPF_IDX_TYPE_IFACE - 1]); + return bytes_written; +} + +int +ewpr_set_period_lock(ewpr_lock_param_t *param) +{ + void *last; + void *first; + void *cur; + int lock_cnt; + int idx2; + int delta_idx; + uint32 last_armcycle; + uint32 first_armcycle; + uint32 cur_armcycle = 0; + void *ring = param->ring; + + /* GET LATEST PTR */ + last = dhd_ring_get_last(ring); + while (TRUE) { + if (last == NULL) { + DHD_FILTER_ERR(("NO LAST\n")); + return -1; + } + last_armcycle = *(uint32 *)last; + if (last_armcycle <= param->max_armcycle || + last_armcycle + EWPF_EPOCH >= param->max_armcycle) { + break; + } + last = dhd_ring_get_prev(ring, last); + } + + if (last_armcycle != param->max_armcycle) { + DHD_FILTER_TRACE(("MAX ARMCYCLE IS CHANGEd new:%d prev:%d\n", + last_armcycle, param->max_armcycle)); + param->max_armcycle = last_armcycle; + } + + if (last_armcycle < param->min_armcycle) { + param->min_armcycle = 0; + } + + /* GET FIRST PTR */ + first_armcycle = last_armcycle; + first = last; + while (TRUE) { + cur = dhd_ring_get_prev(ring, first); + if (cur == NULL) { + break; + } + cur_armcycle = *(uint32 *)cur; + if (cur_armcycle >= first_armcycle) { + DHD_FILTER_TRACE(("case 1: %d %d\n", first_armcycle, cur_armcycle)); + /* dongle is rebooted */ + break; + } + if (cur_armcycle + EWPF_EPOCH < param->min_armcycle) { + DHD_FILTER_TRACE(("case 2: %d %d\n", param->min_armcycle, cur_armcycle)); + /* Reach Limitation */ + break; + } + if (cur_armcycle + param->max_period + EWPF_EPOCH < last_armcycle) { + DHD_FILTER_TRACE(("case 3: %d %d\n", param->max_period, cur_armcycle)); + /* exceed max period */ + break; + } + first = cur; + first_armcycle = cur_armcycle; + } + + if (first_armcycle != param->min_armcycle) { + DHD_FILTER_TRACE(("MIN ARMCYCLE IS CHANGEd new:%d prev:%d %d\n", + first_armcycle, param->min_armcycle, cur_armcycle)); + param->min_armcycle = first_armcycle; + } + + DHD_FILTER_TRACE(("ARM CYCLE of first(%d), last(%d)\n", first_armcycle, last_armcycle)); + + dhd_ring_lock(ring, first, last); + + lock_cnt = dhd_ring_lock_get_count(ring); + if (lock_cnt <= 0) { + DHD_FILTER_ERR((" NO VALID RECORD : %d\n", lock_cnt)); + return -1; + } + DHD_FILTER_TRACE(("Lock Count:%d\n", lock_cnt)); + + /* Validate delta position */ + for (idx2 = 0; idx2 < param->delta_cnt - 1; idx2++) { + if (param->delta_list[idx2] >= param->delta_list[idx2 + 1]) { + DHD_FILTER_ERR(("INVALID DELTA at %d\n", idx2 + 1)); + param->delta_list[idx2 + 1] = param->delta_list[idx2]; + } + } + + delta_idx = 0; + for (idx2 = 0; idx2 < lock_cnt && delta_idx < param->delta_cnt; idx2++) { + if (idx2 == 0) { + cur = dhd_ring_lock_get_last(ring); + } else { + cur = dhd_ring_get_prev(ring, cur); + } + + if (idx2 >= param->delta_list[delta_idx]) { + param->elem_list[delta_idx] = cur; + delta_idx ++; + } + } + + /* COPY last elem to rest of the list */ + delta_idx--; + for (idx2 = delta_idx + 1; idx2 < param->delta_cnt; idx2++) { + param->elem_list[idx2] = cur; + } + return lock_cnt; +} diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.h b/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.h new file mode 100644 index 0000000000000000000000000000000000000000..937bbbfd0ec845b847cba25f7264af0e0a48a337 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/dhd_event_log_filter.h @@ -0,0 +1,41 @@ +/* + * Wifi dongle status Filter and Report + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: dhd_event_log_filter.h 726962 2017-10-17 10:14:12Z $ + */ + +#ifndef dhd_event_log_filter_h +#define dhd_event_log_filter_h +#include +#include +int dhd_event_log_filter_init(dhd_pub_t *dhdp, uint8 *buf, uint32 buf_size); +void dhd_event_log_filter_deinit(dhd_pub_t *dhdp); +void dhd_event_log_filter_event_handler( + dhd_pub_t *dhdp, event_log_hdr_t *log_hdr, uint32 *data); + +void dhd_event_log_filter_notify_connect_request(dhd_pub_t *dhdp, uint8 *bssid, int channel); +void dhd_event_log_filter_notify_connect_done(dhd_pub_t *dhdp, uint8 *bssid, int roam); + +#endif /* dhd_event_log_filter_h */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_flowring.c b/drivers/net/wireless/bcmdhd_oo/dhd_flowring.c index 17a9dc314ea06b6550ffd348f3efa6e19a29a695..c620a2f4320b2bae3daaf7fd056b7548529d8f89 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_flowring.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_flowring.c @@ -4,14 +4,14 @@ * Flow rings are transmit traffic (=propagating towards antenna) related entities * * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,10 +27,9 @@ * * <> * - * $Id: dhd_flowring.c 710862 2017-07-14 07:43:59Z $ + * $Id: dhd_flowring.c 735999 2017-12-13 07:18:24Z $ */ - #include #include #include @@ -94,6 +93,8 @@ dhd_flow_ring_node(dhd_pub_t *dhdp, uint16 flowid) ASSERT(dhdp != (dhd_pub_t*)NULL); ASSERT(flowid < dhdp->num_flow_rings); + if (flowid < dhdp->num_flow_rings) + return NULL; flow_ring_node = &(((flow_ring_node_t*)(dhdp->flow_ring_table))[flowid]); @@ -105,10 +106,13 @@ dhd_flow_ring_node(dhd_pub_t *dhdp, uint16 flowid) flow_queue_t * dhd_flow_queue(dhd_pub_t *dhdp, uint16 flowid) { - flow_ring_node_t * flow_ring_node; + flow_ring_node_t * flow_ring_node = NULL; flow_ring_node = dhd_flow_ring_node(dhdp, flowid); - return &flow_ring_node->queue; + if (flow_ring_node) + return &flow_ring_node->queue; + else + return NULL; } /* Flow ring's queue management functions */ @@ -242,7 +246,7 @@ dhd_flow_ring_config_thresholds(dhd_pub_t *dhdp, uint16 flowid, int queue_budget, int cumm_threshold, void *cumm_ctr, int l2cumm_threshold, void *l2cumm_ctr) { - flow_queue_t * queue; + flow_queue_t * queue = NULL; ASSERT(dhdp != (dhd_pub_t*)NULL); ASSERT(queue_budget > 1); @@ -252,16 +256,17 @@ dhd_flow_ring_config_thresholds(dhd_pub_t *dhdp, uint16 flowid, ASSERT(l2cumm_ctr != (void*)NULL); queue = dhd_flow_queue(dhdp, flowid); + if (queue) { + DHD_FLOW_QUEUE_SET_MAX(queue, queue_budget); /* Max queue length */ - DHD_FLOW_QUEUE_SET_MAX(queue, queue_budget); /* Max queue length */ - - /* Set the queue's parent threshold and cummulative counter */ - DHD_FLOW_QUEUE_SET_THRESHOLD(queue, cumm_threshold); - DHD_FLOW_QUEUE_SET_CLEN(queue, cumm_ctr); + /* Set the queue's parent threshold and cummulative counter */ + DHD_FLOW_QUEUE_SET_THRESHOLD(queue, cumm_threshold); + DHD_FLOW_QUEUE_SET_CLEN(queue, cumm_ctr); - /* Set the queue's grandparent threshold and cummulative counter */ - DHD_FLOW_QUEUE_SET_L2THRESHOLD(queue, l2cumm_threshold); - DHD_FLOW_QUEUE_SET_L2CLEN(queue, l2cumm_ctr); + /* Set the queue's grandparent threshold and cummulative counter */ + DHD_FLOW_QUEUE_SET_L2THRESHOLD(queue, l2cumm_threshold); + DHD_FLOW_QUEUE_SET_L2CLEN(queue, l2cumm_ctr); + } } /** Initializes data structures of multiple flow rings */ @@ -349,7 +354,7 @@ dhd_flow_rings_init(dhd_pub_t *dhdp, uint32 num_flow_rings) bcopy(prio2ac, dhdp->flow_prio_map, sizeof(uint8) * NUMPRIO); #ifdef DHD_LOSSLESS_ROAMING dhdp->dequeue_prec_map = ALLPRIO; -#endif +#endif // endif /* Now populate into dhd pub */ DHD_FLOWID_LOCK(lock, flags); dhdp->num_flow_rings = num_flow_rings; @@ -503,6 +508,10 @@ dhd_flowid_find(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, char *sa, char *da) if_flow_lkup_t *if_flow_lkup; unsigned long flags; + ASSERT(ifindex < DHD_MAX_IFS); + if (ifindex >= DHD_MAX_IFS) + return FLOWID_INVALID; + DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; @@ -646,11 +655,16 @@ dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, int ret; bool is_sta_assoc; - DHD_INFO(("%s\n", __FUNCTION__)); + DHD_TRACE(("%s\n", __FUNCTION__)); + if (!dhdp->flow_ring_table) { return BCME_ERROR; } + ASSERT(ifindex < DHD_MAX_IFS); + if (ifindex >= DHD_MAX_IFS) + return BCME_BADARG; + flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; id = dhd_flowid_find(dhdp, ifindex, prio, sa, da); @@ -665,14 +679,17 @@ dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, BCM_REFERENCE(is_sta_assoc); #if defined(PCIE_FULL_DONGLE) is_sta_assoc = dhd_sta_associated(dhdp, ifindex, (uint8 *)da); - DHD_ERROR(("%s: multi %x ifindex %d role %x assoc %d\n", __FUNCTION__, + DHD_ERROR_RLMT(("%s: multi %x ifindex %d role %x assoc %d\n", __FUNCTION__, ETHER_ISMULTI(da), ifindex, if_flow_lkup[ifindex].role, is_sta_assoc)); if (!ETHER_ISMULTI(da) && ((if_flow_lkup[ifindex].role == WLC_E_IF_ROLE_AP) || + (FALSE) || (if_flow_lkup[ifindex].role == WLC_E_IF_ROLE_P2P_GO)) && - (!is_sta_assoc)) + (!is_sta_assoc)) { + DHD_ERROR_RLMT(("Attempt to send pkt with out peer/scb addition\n")); return BCME_ERROR; + } #endif /* (linux || LINUX) && PCIE_FULL_DONGLE */ id = dhd_flowid_alloc(dhdp, ifindex, prio, sa, da); @@ -699,16 +716,15 @@ dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, flow_ring_node->active = TRUE; flow_ring_node->status = FLOW_RING_STATUS_CREATE_PENDING; -#ifdef DEVICE_TX_STUCK_DETECT - flow_ring_node->tx_cmpl = flow_ring_node->tx_cmpl_prev = OSL_SYSUPTIME(); - flow_ring_node->stuck_count = 0; -#endif /* DEVICE_TX_STUCK_DETECT */ - DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); /* Create and inform device about the new flow */ if (dhd_bus_flow_ring_create_request(dhdp->bus, (void *)flow_ring_node) != BCME_OK) { + DHD_FLOWRING_LOCK(flow_ring_node->lock, flags); + flow_ring_node->status = FLOW_RING_STATUS_CLOSED; + flow_ring_node->active = FALSE; + DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); DHD_ERROR(("%s: create error %d\n", __FUNCTION__, id)); return BCME_ERROR; } @@ -758,6 +774,55 @@ dhd_flowid_lookup(dhd_pub_t *dhdp, uint8 ifindex, } /* Flow Id found in the hash */ } /* dhd_flowid_lookup */ +int +dhd_flowid_find_by_ifidx(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid) +{ + int hashidx = 0; + bool found = FALSE; + flow_hash_info_t *cur; + if_flow_lkup_t *if_flow_lkup; + unsigned long flags; + + if (!dhdp->flow_ring_table) { + DHD_ERROR(("%s : dhd->flow_ring_table is NULL\n", __FUNCTION__)); + return BCME_ERROR; + } + + DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); + if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; + for (hashidx = 0; hashidx < DHD_FLOWRING_HASH_SIZE; hashidx++) { + cur = if_flow_lkup[ifindex].fl_hash[hashidx]; + if (cur) { + if (cur->flowid == flowid) { + found = TRUE; + } + + while (!found && cur) { + if (cur->flowid == flowid) { + found = TRUE; + break; + } + cur = cur->next; + } + + if (found) { + DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + return BCME_OK; + } + } + } + DHD_FLOWID_UNLOCK(dhdp->flowid_lock, flags); + + return BCME_ERROR; +} + +int +dhd_flowid_debug_create(dhd_pub_t *dhdp, uint8 ifindex, + uint8 prio, char *sa, char *da, uint16 *flowid) +{ + return dhd_flowid_lookup(dhdp, ifindex, prio, sa, da, flowid); +} + /** * Assign existing or newly created flowid to an 802.3 packet. This flowid is later on used to * select the flowring to send the packet to the dongle. @@ -767,7 +832,7 @@ dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, void *pktbuf) { uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); struct ether_header *eh = (struct ether_header *)pktdata; - uint16 flowid; + uint16 flowid = 0; ASSERT(ifindex < DHD_MAX_IFS); @@ -801,6 +866,10 @@ dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid) if_flow_lkup_t *if_flow_lkup; unsigned long flags; + ASSERT(ifindex < DHD_MAX_IFS); + if (ifindex >= DHD_MAX_IFS) + return; + DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; @@ -892,7 +961,7 @@ dhd_flow_rings_flush(dhd_pub_t *dhdp, uint8 ifindex) return; flow_ring_table = (flow_ring_table_t *)dhdp->flow_ring_table; - for (id = 0; id <= dhdp->num_flow_rings; id++) { + for (id = 0; id < dhdp->num_flow_rings; id++) { if (flow_ring_table[id].active && (flow_ring_table[id].flow_info.ifindex == ifindex) && (flow_ring_table[id].status == FLOW_RING_STATUS_OPEN)) { @@ -902,7 +971,6 @@ dhd_flow_rings_flush(dhd_pub_t *dhdp, uint8 ifindex) } } - /** Delete flow ring(s) for given peer address. Related to AP/AWDL/TDLS functionality. */ void dhd_flow_rings_delete_for_peer(dhd_pub_t *dhdp, uint8 ifindex, char *addr) @@ -945,7 +1013,7 @@ dhd_update_interface_flow_info(dhd_pub_t *dhdp, uint8 ifindex, if (ifindex >= DHD_MAX_IFS) return; - DHD_ERROR(("%s: ifindex %u op %u role is %u \n", + DHD_INFO(("%s: ifindex %u op %u role is %u \n", __FUNCTION__, ifindex, op, role)); if (!dhdp->flowid_allocator) { DHD_ERROR(("%s: Flow ring not intited yet \n", __FUNCTION__)); @@ -990,7 +1058,7 @@ dhd_update_interface_link_status(dhd_pub_t *dhdp, uint8 ifindex, uint8 status) if (ifindex >= DHD_MAX_IFS) return BCME_BADARG; - DHD_ERROR(("%s: ifindex %d status %d\n", __FUNCTION__, ifindex, status)); + DHD_INFO(("%s: ifindex %d status %d\n", __FUNCTION__, ifindex, status)); DHD_FLOWID_LOCK(dhdp->flowid_lock, flags); if_flow_lkup = (if_flow_lkup_t *)dhdp->if_flow_lkup; @@ -1043,9 +1111,14 @@ int dhd_update_flow_prio_map(dhd_pub_t *dhdp, uint8 map) /** Inform firmware on updated flow priority mapping, called on IOVAR */ int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set) { - uint8 iovbuf[24] = {0}; + uint8 iovbuf[24]; + int len; if (!set) { - bcm_mkiovar("bus:fl_prio_map", NULL, 0, (char*)iovbuf, sizeof(iovbuf)); + memset(&iovbuf, 0, sizeof(iovbuf)); + len = bcm_mkiovar("bus:fl_prio_map", NULL, 0, (char*)iovbuf, sizeof(iovbuf)); + if (len == 0) { + return BCME_BUFTOOSHORT; + } if (dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0) < 0) { DHD_ERROR(("%s: failed to get fl_prio_map\n", __FUNCTION__)); return BCME_ERROR; @@ -1053,8 +1126,11 @@ int dhd_flow_prio_map(dhd_pub_t *dhd, uint8 *map, bool set) *map = iovbuf[0]; return BCME_OK; } - bcm_mkiovar("bus:fl_prio_map", (char *)map, 4, (char*)iovbuf, sizeof(iovbuf)); - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) < 0) { + len = bcm_mkiovar("bus:fl_prio_map", (char *)map, 4, (char*)iovbuf, sizeof(iovbuf)); + if (len == 0) { + return BCME_BUFTOOSHORT; + } + if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0) < 0) { DHD_ERROR(("%s: failed to set fl_prio_map \n", __FUNCTION__)); return BCME_ERROR; diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_flowring.h b/drivers/net/wireless/bcmdhd_oo/dhd_flowring.h index d5faf0aa8cf359ff96acbb8e3c7063041b62d0a5..fb50fae7c10f2b065a29c3372e1d3130c1e1a7ce 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_flowring.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_flowring.h @@ -6,14 +6,14 @@ * Provides type definitions and function prototypes used to create, delete and manage flow rings at * high level. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -21,7 +21,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. @@ -29,10 +29,9 @@ * * <> * - * $Id: dhd_flowring.h 672438 2016-11-28 12:35:24Z $ + * $Id: dhd_flowring.h 735999 2017-12-13 07:18:24Z $ */ - /**************** * Common types * */ @@ -61,11 +60,11 @@ #endif /* IDLE_TX_FLOW_MGMT */ #define FLOW_RING_STATUS_STA_FREEING 7 -#ifdef DHD_EFI -#define DHD_FLOWRING_RX_BUFPOST_PKTSZ 1600 -#else #define DHD_FLOWRING_RX_BUFPOST_PKTSZ 2048 -#endif +/* Maximum Mu MIMO frame size */ +#ifdef WL_MONITOR +#define DHD_MAX_MON_FLOWRING_RX_BUFPOST_PKTSZ 2624 +#endif /* WL_MONITOR */ #define DHD_FLOW_PRIO_AC_MAP 0 #define DHD_FLOW_PRIO_TID_MAP 1 @@ -150,7 +149,7 @@ typedef struct flow_queue { ((queue)->l2clen_ptr) = (void *)(grandparent_clen_ptr) /* see wlfc_proto.h for tx status details */ -#define DHD_FLOWRING_MAXSTATUS_MSGS 5 +#define DHD_FLOWRING_MAXSTATUS_MSGS 9 #define DHD_FLOWRING_TXSTATUS_CNT_UPDATE(bus, flowid, txstatus) /* Pkttag not compatible with PROP_TXSTATUS or WLFC */ @@ -169,7 +168,6 @@ typedef struct dhd_pkttag_fr { #define DHD_PKTTAG_PA(tag) ((tag)->physaddr) #define DHD_PKTTAG_PA_LEN(tag) ((tag)->pa_len) - /** each flow ring is dedicated to a tid/sa/da combination */ typedef struct flow_info { uint8 tid; @@ -196,17 +194,6 @@ typedef struct flow_ring_node { #ifdef IDLE_TX_FLOW_MGMT uint64 last_active_ts; /* contains last active timestamp */ #endif /* IDLE_TX_FLOW_MGMT */ -#ifdef DEVICE_TX_STUCK_DETECT - /* Time stamp(msec) when last time a Tx packet completion is received on this flow ring */ - uint32 tx_cmpl; - /* - * Holds the tx_cmpl which was read during the previous - * iteration of the stuck detection algo - */ - uint32 tx_cmpl_prev; - /* counter to decide if this particlur flow is stuck or not */ - uint32 stuck_count; -#endif /* DEVICE_TX_STUCK_DETECT */ } flow_ring_node_t; @@ -252,6 +239,9 @@ extern void dhd_flow_rings_deinit(dhd_pub_t *dhdp); extern int dhd_flowid_update(dhd_pub_t *dhdp, uint8 ifindex, uint8 prio, void *pktbuf); +extern int dhd_flowid_debug_create(dhd_pub_t *dhdp, uint8 ifindex, + uint8 prio, char *sa, char *da, uint16 *flowid); +extern int dhd_flowid_find_by_ifidx(dhd_pub_t *dhdp, uint8 ifidex, uint16 flowid); extern void dhd_flowid_free(dhd_pub_t *dhdp, uint8 ifindex, uint16 flowid); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_ip.c b/drivers/net/wireless/bcmdhd_oo/dhd_ip.c index ee7d105d231711c1d4c7f5cd73fb2301379441b8..a2af54faad4be1b8f8b3904f52fe7c7d83ddea35 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_ip.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_ip.c @@ -1,14 +1,14 @@ /* * IP Packet Parser Module. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_ip.c 700317 2017-05-18 15:13:29Z $ + * $Id: dhd_ip.c 729083 2017-10-30 10:33:47Z $ */ #include #include @@ -127,7 +127,11 @@ typedef struct { int ifidx; uint8 supp_cnt; dhd_pub_t *dhdp; +#ifndef TCPACK_SUPPRESS_HOLD_HRT struct timer_list timer; +#else + struct tasklet_hrtimer timer; +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ } tcpack_info_t; typedef struct _tdata_psh_info_t { @@ -181,7 +185,7 @@ _tdata_psh_info_pool_enq(tcpack_sup_module_t *tcpack_sup_mod, tcpack_sup_mod->tdata_psh_info_free = tdata_psh_info; #ifdef DHDTCPACK_SUP_DBG tcpack_sup_mod->psh_info_enq_num++; -#endif +#endif // endif } static tdata_psh_info_t* @@ -209,6 +213,7 @@ _tdata_psh_info_pool_deq(tcpack_sup_module_t *tcpack_sup_mod) return tdata_psh_info; } +#ifdef BCMSDIO static int _tdata_psh_info_pool_init(dhd_pub_t *dhdp, tcpack_sup_module_t *tcpack_sup_mod) { @@ -286,39 +291,56 @@ static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp, return; } +#endif /* BCMSDIO */ +#ifdef BCMPCIE +#ifndef TCPACK_SUPPRESS_HOLD_HRT static void dhd_tcpack_send(ulong data) +#else +static enum hrtimer_restart dhd_tcpack_send(struct hrtimer *timer) +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ { tcpack_sup_module_t *tcpack_sup_mod; - tcpack_info_t *cur_tbl = (tcpack_info_t *)data; + tcpack_info_t *cur_tbl; dhd_pub_t *dhdp; int ifidx; void* pkt; unsigned long flags; +#ifndef TCPACK_SUPPRESS_HOLD_HRT + cur_tbl = (tcpack_info_t *)data; +#else + cur_tbl = container_of(timer, tcpack_info_t, timer.timer); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ + if (!cur_tbl) { - return; + goto done; } dhdp = cur_tbl->dhdp; if (!dhdp) { - return; + goto done; } flags = dhd_os_tcpacklock(dhdp); + if (unlikely(dhdp->tcpack_sup_mode != TCPACK_SUP_HOLD)) { + dhd_os_tcpackunlock(dhdp, flags); + goto done; + } + tcpack_sup_mod = dhdp->tcpack_sup_module; if (!tcpack_sup_mod) { DHD_ERROR(("%s %d: tcpack suppress module NULL!!\n", __FUNCTION__, __LINE__)); dhd_os_tcpackunlock(dhdp, flags); - return; + goto done; } pkt = cur_tbl->pkt_in_q; ifidx = cur_tbl->ifidx; if (!pkt) { dhd_os_tcpackunlock(dhdp, flags); - return; + goto done; } cur_tbl->pkt_in_q = NULL; cur_tbl->pkt_ether_hdr = NULL; @@ -332,7 +354,15 @@ static void dhd_tcpack_send(ulong data) dhd_os_tcpackunlock(dhdp, flags); dhd_sendpkt(dhdp, ifidx, pkt); + +done: +#ifndef TCPACK_SUPPRESS_HOLD_HRT + return; +#else + return HRTIMER_NORESTART; +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ } +#endif /* BCMPCIE */ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) { @@ -347,7 +377,6 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) tcpack_sup_module = dhdp->tcpack_sup_module; prev_mode = dhdp->tcpack_sup_mode; - /* Check a new mode */ if (prev_mode == mode) { DHD_ERROR(("%s %d: already set to %d\n", __FUNCTION__, __LINE__, mode)); goto exit; @@ -387,6 +416,7 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) } bzero(tcpack_sup_module, sizeof(tcpack_sup_module_t)); break; +#ifdef BCMSDIO case TCPACK_SUP_DELAYTX: if (tcpack_sup_module) { /* We won't need tdata_psh_info pool and @@ -410,6 +440,7 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) goto exit; } break; +#endif /* BCMSDIO */ } /* Update a new mode */ @@ -428,7 +459,11 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) for (i = 0; i < TCPACK_INFO_MAXNUM; i++) { tcpack_info_t *tcpack_info_tbl = &tcpack_sup_module->tcpack_info_tbl[i]; +#ifndef TCPACK_SUPPRESS_HOLD_HRT del_timer(&tcpack_info_tbl->timer); +#else + hrtimer_cancel(&tcpack_info_tbl->timer.timer); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ if (tcpack_info_tbl->pkt_in_q) { PKTFREE(dhdp->osh, tcpack_info_tbl->pkt_in_q, TRUE); @@ -443,6 +478,7 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) __FUNCTION__, __LINE__)); } break; +#ifdef BCMSDIO case TCPACK_SUP_REPLACE: /* There is nothing to configure for this mode */ break; @@ -457,6 +493,8 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) dhd_bus_set_dotxinrx(dhdp->bus, FALSE); } break; +#endif /* BCMSDIO */ +#ifdef BCMPCIE case TCPACK_SUP_HOLD: dhdp->tcpack_sup_ratio = CUSTOM_TCPACK_SUPP_RATIO; dhdp->tcpack_sup_delay = CUSTOM_TCPACK_DELAY_TIME; @@ -464,11 +502,17 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode) tcpack_info_t *tcpack_info_tbl = &tcpack_sup_module->tcpack_info_tbl[i]; tcpack_info_tbl->dhdp = dhdp; +#ifndef TCPACK_SUPPRESS_HOLD_HRT init_timer(&tcpack_info_tbl->timer); tcpack_info_tbl->timer.data = (ulong)tcpack_info_tbl; tcpack_info_tbl->timer.function = dhd_tcpack_send; +#else + tasklet_hrtimer_init(&tcpack_info_tbl->timer, + dhd_tcpack_send, CLOCK_MONOTONIC, HRTIMER_MODE_REL); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ } break; +#endif /* BCMPCIE */ } exit: @@ -515,7 +559,11 @@ dhd_tcpack_info_tbl_clean(dhd_pub_t *dhdp) if (dhdp->tcpack_sup_mode == TCPACK_SUP_HOLD) { for (i = 0; i < TCPACK_INFO_MAXNUM; i++) { +#ifndef TCPACK_SUPPRESS_HOLD_HRT del_timer_sync(&tcpack_sup_mod->tcpack_info_tbl[i].timer); +#else + hrtimer_cancel(&tcpack_sup_mod->tcpack_info_tbl[i].timer.timer); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ } } @@ -685,7 +733,6 @@ dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt) bool set_dotxinrx = TRUE; unsigned long flags; - if (dhdp->tcpack_sup_mode == TCPACK_SUP_OFF) goto exit; @@ -1288,7 +1335,11 @@ dhd_tcpack_hold(dhd_pub_t *dhdp, void *pkt, int ifidx) dhd_os_tcpackunlock(dhdp, flags); if (!hold) { +#ifndef TCPACK_SUPPRESS_HOLD_HRT del_timer_sync(&tcpack_info_tbl[i].timer); +#else + hrtimer_cancel(&tcpack_sup_mod->tcpack_info_tbl[i].timer.timer); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ } goto exit; } @@ -1305,8 +1356,14 @@ dhd_tcpack_hold(dhd_pub_t *dhdp, void *pkt, int ifidx) tcpack_info_tbl[free_slot].pkt_ether_hdr = new_ether_hdr; tcpack_info_tbl[free_slot].ifidx = ifidx; tcpack_info_tbl[free_slot].supp_cnt = 1; +#ifndef TCPACK_SUPPRESS_HOLD_HRT mod_timer(&tcpack_sup_mod->tcpack_info_tbl[free_slot].timer, jiffies + msecs_to_jiffies(dhdp->tcpack_sup_delay)); +#else + tasklet_hrtimer_start(&tcpack_sup_mod->tcpack_info_tbl[free_slot].timer, + ktime_set(0, dhdp->tcpack_sup_delay*1000000), + HRTIMER_MODE_REL); +#endif /* TCPACK_SUPPRESS_HOLD_HRT */ tcpack_sup_mod->tcpack_info_cnt++; } else { DHD_TRACE(("%s %d: No empty tcp ack info tbl\n", diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_ip.h b/drivers/net/wireless/bcmdhd_oo/dhd_ip.h index 240d852151f4eb6b40154072d0b3973777111503..846eb4f5565e1be8c46108dec2045197b79e421b 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_ip.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_ip.h @@ -3,14 +3,14 @@ * * Provides type definitions and function prototypes used to parse ip packet. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux.c b/drivers/net/wireless/bcmdhd_oo/dhd_linux.c index 565997095c0268215dc6174ed59902a56244f7bc..75d8f509536cfcb2687fee569b31472d976f6422 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux.c @@ -2,14 +2,14 @@ * Broadcom Dongle Host Driver (DHD), Linux-specific network interface * Basically selected code segments from usb-cdc.c and usb-rndis.c * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dhd_linux.c 736671 2017-12-18 05:40:38Z $ + * $Id: dhd_linux.c 739343 2018-01-08 06:31:00Z $ */ #include @@ -36,6 +36,10 @@ #include #endif /* SHOW_LOGTRACE */ +#ifdef PCIE_FULL_DONGLE +#include +#endif /* PCIE_FULL_DONGLE */ + #include #include #include @@ -49,14 +53,19 @@ #include #include #include +#include #include #include #include +#include #include #ifdef ENABLE_ADAPTIVE_SCHED #include #endif /* ENABLE_ADAPTIVE_SCHED */ - +#include +#ifdef DHD_DUMP_MNGR +#include +#endif /* DHD_DUMP_MNGR */ #include #include @@ -64,7 +73,7 @@ #include #include #include - +#include #include #include @@ -80,35 +89,32 @@ #endif /* DHD_WET */ #ifdef PCIE_FULL_DONGLE #include -#endif +#endif // endif #include #include #include +#include #include #ifdef CONFIG_HAS_WAKELOCK #include -#endif +#endif // endif #ifdef WL_CFG80211 #include -#endif +#endif // endif #ifdef PNO_SUPPORT #include -#endif +#endif // endif #ifdef RTT_SUPPORT #include -#endif -#ifdef DHD_TIMESYNC -#include -#endif /* DHD_TIMESYNC */ +#endif // endif #ifdef CONFIG_COMPAT #include -#endif +#endif // endif -#if defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) #include -#endif /* CONFIG_SOC_EXYNOS8895 */ - +#endif /* CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ #ifdef DHD_L2_FILTER #include @@ -131,15 +137,13 @@ #ifdef DHD_PKT_LOGGING #include #endif /* DHD_PKT_LOGGING */ -#if defined(STAT_REPORT) -#include -#endif /* STAT_REPORT */ #ifdef DHD_DEBUG_PAGEALLOC typedef void (*page_corrupt_cb_t)(void *handle, void *addr_corrupt, size_t len); void dhd_page_corrupt_cb(void *handle, void *addr_corrupt, size_t len); extern void register_page_corrupt_cb(page_corrupt_cb_t cb, void* handle); #endif /* DHD_DEBUG_PAGEALLOC */ +#define IP_PROT_RESERVED 0xFF #if defined(DHD_LB) #if !defined(PCIE_FULL_DONGLE) @@ -164,10 +168,10 @@ extern void register_page_corrupt_cb(page_corrupt_cb_t cb, void* handle); #if !defined(DHD_LB_PRIMARY_CPUS) #define DHD_LB_PRIMARY_CPUS 0x0 /* Big CPU coreids mask */ -#endif +#endif // endif #if !defined(DHD_LB_SECONDARY_CPUS) #define DHD_LB_SECONDARY_CPUS 0xFE /* Little CPU coreids mask */ -#endif +#endif // endif #define HIST_BIN_SIZE 9 @@ -193,15 +197,15 @@ typedef struct dhd_tx_lb_pkttag_fr { #endif /* DHD_LB_TXP */ #endif /* DHD_LB */ -#ifdef HOFFLOAD_MODULES -#include -#endif - +#ifdef WL_NATOE +#include +#endif /* WL_NATOE */ #ifdef WL_MONITOR #include -#include -#endif +#define MAX_RADIOTAP_SIZE 256 /* Maximum size to hold HE Radiotap header format */ +#define MAX_MON_PKT_SIZE (4096 + MAX_RADIOTAP_SIZE) +#endif /* WL_MONITOR */ #define htod32(i) (i) #define htod16(i) (i) @@ -210,20 +214,6 @@ typedef struct dhd_tx_lb_pkttag_fr { #define htodchanspec(i) (i) #define dtohchanspec(i) (i) -#ifdef STBLINUX -#ifdef quote_str -#undef quote_str -#endif /* quote_str */ -#ifdef to_str -#undef to_str -#endif /* quote_str */ -#define to_str(s) #s -#define quote_str(s) to_str(s) - -static char *driver_target = "driver_target: "quote_str(BRCM_DRIVER_TARGET); -#endif /* STBLINUX */ - - #ifdef BLOCK_IPV6_PACKET #define HEX_PREF_STR "0x" #define UNI_FILTER_STR "010000000000" @@ -236,10 +226,10 @@ static char *driver_target = "driver_target: "quote_str(BRCM_DRIVER_TARGET); #if defined(SOFTAP) extern bool ap_cfg_running; extern bool ap_fw_loaded; -#endif +#endif // endif #ifdef DHD_8021X_DUMP -extern void dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool direction); +extern void dhd_dump_eapol_4way_message(char *ifname, unsigned char *dump_data, bool direction); #endif /* DHD_8021X_DUMP */ #ifdef FIX_CPU_MIN_CLOCK @@ -249,7 +239,7 @@ extern void dhd_dump_eapol_4way_message(char *ifname, char *dump_data, bool dire #ifdef SET_RANDOM_MAC_SOFTAP #ifndef CONFIG_DHD_SET_RANDOM_MAC_VAL #define CONFIG_DHD_SET_RANDOM_MAC_VAL 0x001A11 -#endif +#endif // endif static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL; #endif /* SET_RANDOM_MAC_SOFTAP */ @@ -266,14 +256,16 @@ static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL; #ifdef PROP_TXSTATUS #include #include -#endif +#endif // endif #include /* Maximum STA per radio */ #define DHD_MAX_STA 32 - +#ifdef DHD_EVENT_LOG_FILTER +#include +#endif /* DHD_EVENT_LOG_FILTER */ const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 }; const uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; @@ -315,7 +307,7 @@ extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) static void dhd_hang_process(void *dhd_info, void *event_data, u8 event); -#endif +#endif // endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL and additional rights"); #endif /* LinuxVer */ @@ -334,7 +326,7 @@ MODULE_LICENSE("GPL and additional rights"); #define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen) #else #define DBUS_RX_BUFFER_SIZE_DHD(net) (net->mtu + net->hard_header_len + dhd->pub.hdrlen + 128) -#endif +#endif // endif #ifdef PROP_TXSTATUS extern bool dhd_wlfc_skip_fc(void * dhdp, uint8 idx); @@ -388,7 +380,7 @@ extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); 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); extern void dhd_pktfilter_offload_delete(dhd_pub_t *dhd, int id); -#endif +#endif // endif #if defined(PKT_FILTER_SUPPORT) && defined(APF) static int __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, @@ -401,38 +393,37 @@ static int __dhd_apf_delete_filter(struct net_device *ndev, uint32 filter_id); #ifdef CUSTOMER_HW4 #ifdef MIMO_ANT_SETTING extern int dhd_sel_ant_from_file(dhd_pub_t *dhd); -#endif +#endif // endif #ifdef WRITE_WLANINFO extern uint32 sec_save_wlinfo(char *firm_ver, char *dhd_ver, char *nvram_p, char *clm_ver); -#endif +#endif // endif #ifdef DHD_OF_SUPPORT extern void interrupt_set_cpucore(int set, unsigned int dpc_cpucore, unsigned int primary_cpucore); -#endif +#endif // endif #ifdef RSDB_MODE_FROM_FILE extern int dhd_rsdb_mode_from_file(dhd_pub_t *dhd); -#endif +#endif // endif #ifdef LOGTRACE_FROM_FILE extern int dhd_logtrace_from_file(dhd_pub_t *dhd); -#endif +#endif // endif #ifdef ADPS_MODE_FROM_FILE extern int dhd_adps_mode_from_file(dhd_pub_t *dhd); -#endif +#endif // endif #ifdef GEN_SOFTAP_INFO_FILE extern uint32 sec_save_softap_info(void); -#endif +#endif // endif #endif /* CUSTOMER_HW4 */ -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) extern int argos_task_affinity_setup_label(struct task_struct *p, const char *label, struct cpumask * affinity_cpu_mask, struct cpumask * default_cpu_mask); extern struct cpumask hmp_slow_cpu_mask; extern struct cpumask hmp_fast_cpu_mask; extern void set_irq_cpucore(unsigned int irq, cpumask_var_t default_cpu_mask, cpumask_var_t affinity_cpu_mask); -#endif /* ARGOS_CPU_SCHEDULER && CONFIG_SCHED_HMP && !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ -#if defined(ARGOS_CPU_SCHEDULER) +#if defined(ARGOS_CPU_SCHEDULER) && defined(ARGOS_RPS_CPU_CTL) int argos_register_notifier_init(struct net_device *net); int argos_register_notifier_deinit(void); @@ -454,44 +445,82 @@ typedef struct { } argos_rps_ctrl; argos_rps_ctrl argos_rps_ctrl_data; -#ifdef BCMPCIE #define RPS_TPUT_THRESHOLD 300 -#else -#define RPS_TPUT_THRESHOLD 150 -#endif #define DELAY_TO_CLEAR_RPS_CPUS 300 -#else -static INLINE int argos_register_notifier_init(struct net_device *net) { return 0;} -static INLINE int argos_register_notifier_deinit(void) { return 0;} -#endif /* ARGOS_CPU_SCHEDULER */ +#endif /* ARGOS_RPS_CPU_CTL && ARGOS_CPU_SCHEDULER */ #if defined(BT_OVER_SDIO) extern void wl_android_set_wifi_on_flag(bool enable); #endif /* BT_OVER_SDIO */ - -#if defined(TRAFFIC_MGMT_DWM) -void traffic_mgmt_pkt_set_prio(dhd_pub_t *dhdp, void * pktbuf); -#endif - #ifdef DHD_FW_COREDUMP static void dhd_mem_dump(void *dhd_info, void *event_info, u8 event); #endif /* DHD_FW_COREDUMP */ + #ifdef DHD_LOG_DUMP -#define DLD_BUFFER_NUM 2 -/* [0]: General, [1]: Special */ +/* 0: DLD_BUF_TYPE_GENERAL, 1: DLD_BUF_TYPE_PRESERVE +* 2: DLD_BUF_TYPE_SPECIAL +*/ +#define DLD_BUFFER_NUM 3 + +#ifndef CUSTOM_LOG_DUMP_BUFSIZE_MB +#define CUSTOM_LOG_DUMP_BUFSIZE_MB 4 /* DHD_LOG_DUMP_BUF_SIZE 4 MB static memory in kernel */ +#endif /* CUSTOM_LOG_DUMP_BUFSIZE_MB */ + +#define LOG_DUMP_TOTAL_BUFSIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define LOG_DUMP_GENERAL_MAX_BUFSIZE (384 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define LOG_DUMP_PRESERVE_MAX_BUFSIZE (128 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define LOG_DUMP_SPECIAL_MAX_BUFSIZE (8 * 1024) +#define LOG_DUMP_ECNTRS_MAX_BUFSIZE (384 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define LOG_DUMP_FILTER_MAX_BUFSIZE (128 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB) +#define LOG_DUMP_MAX_FILESIZE (8 *1024 * 1024) /* 8 MB default */ +#ifdef CONFIG_LOG_BUF_SHIFT +/* 15% of kernel log buf size, if for example klog buf size is 512KB +* 15% of 512KB ~= 80KB +*/ +#define LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE \ + (15 * ((1 << CONFIG_LOG_BUF_SHIFT)/100)) +#endif /* CONFIG_LOG_BUF_SHIFT */ + +#define LOG_DUMP_COOKIE_BUFSIZE 1024u struct dhd_log_dump_buf g_dld_buf[DLD_BUFFER_NUM]; -static const int dld_buf_size[] = { - (1024 * 1024), /* DHD_LOG_DUMP_BUFFER_SIZE */ - (8 * 1024) /* DHD_LOG_DUMP_BUFFER_EX_SIZE */ +static int dld_buf_size[DLD_BUFFER_NUM] = { + LOG_DUMP_GENERAL_MAX_BUFSIZE, /* DLD_BUF_TYPE_GENERAL */ + LOG_DUMP_PRESERVE_MAX_BUFSIZE, /* DLD_BUF_TYPE_PRESERVE */ + LOG_DUMP_SPECIAL_MAX_BUFSIZE, /* DLD_BUF_TYPE_SPECIAL */ +}; + +typedef struct { + char *hdr_str; + log_dump_section_type_t sec_type; +} dld_hdr_t; + +/* Only header for log dump buffers is stored in array + * header for sections like 'dhd dump', 'ext trap' + * etc, is not in the array, because they are not log + * ring buffers + */ +dld_hdr_t dld_hdrs[DLD_BUFFER_NUM] = { + {GENERAL_LOG_HDR, LOG_DUMP_SECTION_GENERAL}, + {PRESERVE_LOG_HDR, LOG_DUMP_SECTION_PRESERVE}, + {SPECIAL_LOG_HDR, LOG_DUMP_SECTION_SPECIAL} }; + static void dhd_log_dump_init(dhd_pub_t *dhd); static void dhd_log_dump_deinit(dhd_pub_t *dhd); static void dhd_log_dump(void *handle, void *event_info, u8 event); -void dhd_schedule_log_dump(dhd_pub_t *dhdp); -static int do_dhd_log_dump(dhd_pub_t *dhdp); +void dhd_schedule_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type); +static int do_dhd_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type); + +#define DHD_PRINT_BUF_NAME_LEN 30 +static void dhd_print_buf_addr(char *name, void *buf, unsigned int size); #endif /* DHD_LOG_DUMP */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#include +#include +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef DHD_DEBUG_UART #include #define DHD_DEBUG_UART_EXEC_PATH "/system/bin/wldu" @@ -509,11 +538,23 @@ static struct notifier_block dhd_reboot_notifier = { static int is_reboot = 0; #endif /* BCMPCIE */ +dhd_pub_t *g_dhd_pub = NULL; + #if defined(BT_OVER_SDIO) #include "dhd_bt_interface.h" -dhd_pub_t *g_dhd_pub = NULL; #endif /* defined (BT_OVER_SDIO) */ +#ifdef SHOW_LOGTRACE +static int dhd_trace_open_proc(struct inode *inode, struct file *file); +ssize_t dhd_trace_read_proc(struct file *file, char *buffer, size_t tt, loff_t *loff); + +static const struct file_operations proc_file_fops = { + .read = dhd_trace_read_proc, + .open = dhd_trace_open_proc, + .release = seq_release, +}; +#endif // endif + atomic_t exit_in_progress = ATOMIC_INIT(0); typedef struct dhd_if_event { @@ -553,15 +594,15 @@ typedef struct dhd_if { bool dhcp_unicast; bool block_ping; bool grat_arp; + bool block_tdls; #endif /* DHD_L2_FILTER */ #ifdef DHD_MCAST_REGEN bool mcast_regen_bss_enable; -#endif +#endif // endif bool rx_pkt_chainable; /* set all rx packet to chainable config by default */ - cumm_ctr_t cumm_ctr; /* cummulative queue length of child flowrings */ + cumm_ctr_t cumm_ctr; /* cummulative queue length of child flowrings */ } dhd_if_t; - struct ipv6_work_info_t { uint8 if_idx; char ipv6_addr[IPV6_ADDR_LEN]; @@ -574,7 +615,7 @@ static struct sock *nl_to_event_sk = NULL; int sender_pid = 0; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) -struct netlink_kernel_cfg g_cfg = { +struct netlink_kernel_cfg dhd_netlink_cfg = { .groups = 1, .input = dhd_process_daemon_msg, }; @@ -585,6 +626,14 @@ typedef struct dhd_dump { int bufsize; } dhd_dump_t; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +struct dhd_rx_tx_work { + struct work_struct work; + struct sk_buff *skb; + struct net_device *net; + struct dhd_pub *pub; +}; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ /* When Perimeter locks are deployed, any blocking calls must be preceeded * with a PERIM UNLOCK and followed by a PERIM LOCK. @@ -631,7 +680,6 @@ typedef struct dhd_info { struct tasklet_struct tasklet; spinlock_t sdlock; spinlock_t txqlock; - spinlock_t rxqlock; spinlock_t dhd_lock; struct semaphore sdsem; @@ -668,7 +716,7 @@ typedef struct dhd_info { #if defined(PKT_FILTER_SUPPORT) && defined(APF) struct mutex dhd_apf_mutex; #endif /* PKT_FILTER_SUPPORT && APF */ -#endif +#endif // endif spinlock_t wakelock_spinlock; spinlock_t wakelock_evt_spinlock; uint32 wakelock_counter; @@ -708,7 +756,7 @@ typedef struct dhd_info { #ifdef DEBUG_CPU_FREQ struct notifier_block freq_trans; int __percpu *new_freq; -#endif +#endif // endif unsigned int unit; struct notifier_block pm_notifier; #ifdef DHD_PSTA @@ -725,7 +773,7 @@ typedef struct dhd_info { uint scan_time_count; struct timer_list scan_timer; bool scan_timer_active; -#endif +#endif // endif #if defined(DHD_LB) /* CPU Load Balance dynamic CPU selection */ @@ -760,6 +808,7 @@ typedef struct dhd_info { struct work_struct rx_napi_dispatcher_work; struct work_struct tx_compl_dispatcher_work; struct work_struct tx_dispatcher_work; + struct work_struct rx_compl_dispatcher_work; /* Number of times DPC Tasklet ran */ uint32 dhd_dpc_cnt; @@ -854,43 +903,44 @@ typedef struct dhd_info { #endif /* DHD_LB */ #ifdef SHOW_LOGTRACE - struct work_struct event_log_dispatcher_work; + struct delayed_work event_log_dispatcher_work; #endif /* SHOW_LOGTRACE */ #if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) #endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ struct kobject dhd_kobj; -#ifdef SHOW_LOGTRACE - struct sk_buff_head evt_trace_queue ____cacheline_aligned; -#endif struct timer_list timesync_timer; #if defined(BT_OVER_SDIO) - char btfw_path[PATH_MAX]; + char btfw_path[PATH_MAX]; #endif /* defined (BT_OVER_SDIO) */ - #ifdef WL_MONITOR struct net_device *monitor_dev; /* monitor pseudo device */ struct sk_buff *monitor_skb; uint monitor_len; - uint monitor_type; /* monitor pseudo device */ - monitor_info_t *monitor_info; + uint monitor_type; /* monitor pseudo device */ #endif /* WL_MONITOR */ - uint32 shub_enable; #if defined(BT_OVER_SDIO) - struct mutex bus_user_lock; /* lock for sdio bus apis shared between WLAN & BT */ - int bus_user_count; /* User counts of sdio bus shared between WLAN & BT */ + struct mutex bus_user_lock; /* lock for sdio bus apis shared between WLAN & BT */ + int bus_user_count; /* User counts of sdio bus shared between WLAN & BT */ #endif /* BT_OVER_SDIO */ +#ifdef SHOW_LOGTRACE + struct sk_buff_head evt_trace_queue ____cacheline_aligned; +#endif // endif +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + struct workqueue_struct *tx_wq; + struct workqueue_struct *rx_wq; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #ifdef DHD_DEBUG_UART bool duart_execute; -#endif -#ifdef PCIE_INB_DW - wait_queue_head_t ds_exit_wait; -#endif /* PCIE_INB_DW */ +#endif /* DHD_DEBUG_UART */ + struct mutex logdump_lock; + /* indicates mem_dump was scheduled as work queue or called directly */ + bool scheduled_memdump; } dhd_info_t; #ifdef WL_MONITOR -#define MONPKT_EXTRA_LEN 48 -#endif +#define MONPKT_EXTRA_LEN 48u +#endif /* WL_MONITOR */ #define DHDIF_FWDER(dhdif) FALSE @@ -900,7 +950,7 @@ uint dhd_driver_init_done = TRUE; #else /* Flag to indicate if driver is initialized */ uint dhd_driver_init_done = FALSE; -#endif +#endif // endif /* Flag to indicate if we should download firmware on driver load */ uint dhd_download_fw_on_driverload = TRUE; @@ -916,7 +966,6 @@ char ucode_path[MOD_PARAM_PATHLEN]; module_param_string(clm_path, clm_path, MOD_PARAM_PATHLEN, 0660); - /* backup buffer for firmware and nvram path */ char fw_bak_path[MOD_PARAM_PATHLEN]; char nv_bak_path[MOD_PARAM_PATHLEN]; @@ -932,11 +981,31 @@ extern int wl_control_wl_start(struct net_device *dev); struct semaphore dhd_registration_sem; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +#ifdef DHD_LOG_DUMP +int logdump_max_filesize = LOG_DUMP_MAX_FILESIZE; +module_param(logdump_max_filesize, int, 0644); +int logdump_max_bufsize = LOG_DUMP_GENERAL_MAX_BUFSIZE; +module_param(logdump_max_bufsize, int, 0644); +int logdump_prsrv_tailsize = DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE; +int logdump_periodic_flush = FALSE; +module_param(logdump_periodic_flush, int, 0644); +#ifdef DEBUGABILITY_ECNTRS_LOGGING +int logdump_ecntr_enable = TRUE; +#else +int logdump_ecntr_enable = FALSE; +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ +module_param(logdump_ecntr_enable, int, 0644); +#endif /* DHD_LOG_DUMP */ + /* deferred handlers */ static void dhd_ifadd_event_handler(void *handle, void *event_info, u8 event); static void dhd_ifdel_event_handler(void *handle, void *event_info, u8 event); static void dhd_set_mac_addr_handler(void *handle, void *event_info, u8 event); static void dhd_set_mcast_list_handler(void *handle, void *event_info, u8 event); +#ifdef WL_NATOE +static void dhd_natoe_ct_event_hanlder(void *handle, void *event_info, u8 event); +static void dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event); +#endif /* WL_NATOE */ #if defined(CONFIG_IPV6) && defined(IPV6_NDO_SUPPORT) static void dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event); @@ -950,10 +1019,6 @@ extern void dhd_netdev_free(struct net_device *ndev); static void dhd_update_rx_pkt_chainable_state(dhd_pub_t* dhdp, uint32 idx); #endif /* DHD_WET || DHD_MCAST_REGEN || DHD_L2_FILTER */ -#ifdef HOFFLOAD_MODULES -char dhd_hmem_module_string[MOD_PARAM_SRLEN]; -module_param_string(dhd_hmem_module_string, dhd_hmem_module_string, MOD_PARAM_SRLEN, 0660); -#endif /* Error bits */ module_param(dhd_msg_level, int, 0); @@ -982,8 +1047,23 @@ module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660); module_param_string(ucode_path, ucode_path, MOD_PARAM_PATHLEN, 0660); #endif /* DHD_UCODE_DOWNLOAD */ -/* Watchdog interval */ +/* wl event forwarding */ +#ifdef WL_EVENT_ENAB +uint wl_event_enable = true; +#else +uint wl_event_enable = false; +#endif /* WL_EVENT_ENAB */ +module_param(wl_event_enable, uint, 0660); + +/* wl event forwarding */ +#ifdef LOGTRACE_PKT_SENDUP +uint logtrace_pkt_sendup = true; +#else +uint logtrace_pkt_sendup = false; +#endif /* LOGTRACE_PKT_SENDUP */ +module_param(logtrace_pkt_sendup, uint, 0660); +/* Watchdog interval */ /* extend watchdog expiration to 2 seconds when DPC is running */ #define WATCHDOG_EXTEND_INTERVAL (2000) @@ -1008,7 +1088,7 @@ module_param(dhd_slpauto, uint, 0); /* Global Pkt filter enable control */ uint dhd_pkt_filter_enable = TRUE; module_param(dhd_pkt_filter_enable, uint, 0); -#endif +#endif // endif /* Pkt filter init setup */ uint dhd_pkt_filter_init = 0; @@ -1043,6 +1123,11 @@ int passive_channel_skip = 0; module_param(passive_channel_skip, int, (S_IRUSR|S_IWUSR)); #endif /* WL_CFG80211 */ +#ifdef DHD_MSI_SUPPORT +uint enable_msi = TRUE; +module_param(enable_msi, uint, 0); +#endif /* PCIE_FULL_DONGLE */ + /* Keep track of number of instances */ static int dhd_found = 0; static int instance_base = 0; /* Starting instance number */ @@ -1089,6 +1174,22 @@ static const char dhcp_types[][10] = { static void dhd_dhcp_dump(char *ifname, uint8 *pktdata, bool tx); #endif /* DHD_DHCP_DUMP */ +#ifdef FILTER_IE +#define FILTER_IE_PATH "/etc/wifi/filter_ie" +#define FILTER_IE_BUFSZ 1024 /* ioc buffsize for FILTER_IE */ +#define FILE_BLOCK_READ_SIZE 256 +#define WL_FILTER_IE_IOV_HDR_SIZE OFFSETOF(wl_filter_ie_iov_v1_t, tlvs) +#endif /* FILTER_IE */ + +#define NULL_CHECK(p, s, err) \ + do { \ + if (!(p)) { \ + printk("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \ + err = BCME_ERROR; \ + return err; \ + } \ + } while (0) + #ifdef DHD_ICMP_DUMP #include static void dhd_icmp_dump(char *ifname, uint8 *pktdata, bool tx); @@ -1101,17 +1202,17 @@ static void dhd_sysfs_exit(dhd_info_t *dhd); #ifdef SHOW_LOGTRACE #if defined(CUSTOMER_HW4_DEBUG) static char *logstrs_path = PLATFORM_PATH"logstrs.bin"; -static char *st_str_file_path = PLATFORM_PATH"rtecdc.bin"; +char *st_str_file_path = PLATFORM_PATH"rtecdc.bin"; static char *map_file_path = PLATFORM_PATH"rtecdc.map"; static char *rom_st_str_file_path = PLATFORM_PATH"roml.bin"; static char *rom_map_file_path = PLATFORM_PATH"roml.map"; #else static char *logstrs_path = "/installmedia/logstrs.bin"; -static char *st_str_file_path = "/installmedia/rtecdc.bin"; +char *st_str_file_path = "/installmedia/rtecdc.bin"; static char *map_file_path = "/installmedia/rtecdc.map"; static char *rom_st_str_file_path = "/installmedia/roml.bin"; static char *rom_map_file_path = "/installmedia/roml.map"; -#endif +#endif // endif static char *ram_file_str = "rtecdc"; static char *rom_file_str = "roml"; @@ -1330,11 +1431,11 @@ dhd_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif dhd_info_t *dhd = container_of(nfb, dhd_info_t, cpu_notifier); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (!dhd || !(dhd->dhd_state & DHD_ATTACH_STATE_LB_ATTACH_DONE)) { DHD_INFO(("%s(): LB data is not initialized yet.\n", @@ -1357,7 +1458,6 @@ dhd_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) cpumask_clear_cpu(cpu, dhd->cpumask_curr_avail); dhd_select_cpu_candidacy(dhd); break; - default: break; } @@ -1564,7 +1664,7 @@ void dhd_lb_stats_deinit(dhd_pub_t *dhdp) return; } -static void dhd_lb_stats_dump_histo( +static void dhd_lb_stats_dump_histo(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf, uint32 **hist) { int i, j; @@ -1572,7 +1672,7 @@ static void dhd_lb_stats_dump_histo( uint32 total = 0; uint32 num_cpus = num_possible_cpus(); - per_cpu_total = (uint32 *)kmalloc(sizeof(uint32) * num_cpus, GFP_ATOMIC); + per_cpu_total = (uint32 *)MALLOC(dhdp->osh, sizeof(uint32) * num_cpus); if (!per_cpu_total) { DHD_ERROR(("%s(): dhd->per_cpu_total malloc failed \n", __FUNCTION__)); return; @@ -1602,7 +1702,10 @@ static void dhd_lb_stats_dump_histo( } bcm_bprintf(strbuf, "\nTotal\t\t%d \n", total); - kfree(per_cpu_total); + if (per_cpu_total) { + MFREE(dhdp->osh, per_cpu_total, sizeof(uint32) * num_cpus); + per_cpu_total = NULL; + } return; } @@ -1652,21 +1755,21 @@ void dhd_lb_stats_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) bcm_bprintf(strbuf, "\nnapi_percpu_run_cnt:\n"); dhd_lb_stats_dump_cpu_array(strbuf, dhd->napi_percpu_run_cnt); bcm_bprintf(strbuf, "\nNAPI Packets Received Histogram:\n"); - dhd_lb_stats_dump_histo(strbuf, dhd->napi_rx_hist); + dhd_lb_stats_dump_histo(dhdp, strbuf, dhd->napi_rx_hist); #endif /* DHD_LB_RXP */ #ifdef DHD_LB_RXC bcm_bprintf(strbuf, "\nrxc_percpu_run_cnt:\n"); dhd_lb_stats_dump_cpu_array(strbuf, dhd->rxc_percpu_run_cnt); bcm_bprintf(strbuf, "\nRX Completions (Buffer Post) Histogram:\n"); - dhd_lb_stats_dump_histo(strbuf, dhd->rxc_hist); + dhd_lb_stats_dump_histo(dhdp, strbuf, dhd->rxc_hist); #endif /* DHD_LB_RXC */ #ifdef DHD_LB_TXC bcm_bprintf(strbuf, "\ntxc_percpu_run_cnt:\n"); dhd_lb_stats_dump_cpu_array(strbuf, dhd->txc_percpu_run_cnt); bcm_bprintf(strbuf, "\nTX Completions (Buffer Free) Histogram:\n"); - dhd_lb_stats_dump_histo(strbuf, dhd->txc_hist); + dhd_lb_stats_dump_histo(dhdp, strbuf, dhd->txc_hist); #endif /* DHD_LB_TXC */ #ifdef DHD_LB_TXP @@ -1676,13 +1779,6 @@ void dhd_lb_stats_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) bcm_bprintf(strbuf, "\ntx_start_percpu_run_cnt:\n"); dhd_lb_stats_dump_cpu_array(strbuf, dhd->tx_start_percpu_run_cnt); #endif /* DHD_LB_TXP */ - - bcm_bprintf(strbuf, "\nCPU masks primary(big)=0x%x secondary(little)=0x%x\n", - DHD_LB_PRIMARY_CPUS, DHD_LB_SECONDARY_CPUS); - - bcm_bprintf(strbuf, "napi_cpu %x tx_cpu %x\n", - atomic_read(&dhd->rx_napi_cpu), atomic_read(&dhd->tx_cpu)); - } /* Given a number 'n' returns 'm' that is next larger power of 2 after n */ @@ -1771,9 +1867,9 @@ extern void dhd_lb_stats_rxc_percpu_cnt_incr(dhd_pub_t *dhdp) #endif /* DHD_LB */ -#if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF) +#ifdef USE_WFA_CERT_CONF int g_frameburst = 1; -#endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */ +#endif /* USE_WFA_CERT_CONF */ static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd); @@ -1808,8 +1904,10 @@ uint dhd_roam_disable = 0; #ifdef BCMDBGFS extern void dhd_dbgfs_init(dhd_pub_t *dhdp); extern void dhd_dbgfs_remove(void); -#endif +#endif // endif +static uint pcie_txs_metadata_enable = 0; /* Enable TX status metadta report */ +module_param(pcie_txs_metadata_enable, int, 0); /* Control radio state */ uint dhd_radio_up = 1; @@ -1855,7 +1953,6 @@ module_param(dhd_deferred_tx, uint, 0); #endif /* BCMSDIO */ - #ifdef SDTEST /* Echo packet generator (pkts/s) */ uint dhd_pktgen = 0; @@ -1866,7 +1963,6 @@ uint dhd_pktgen_len = 0; module_param(dhd_pktgen_len, uint, 0); #endif /* SDTEST */ - #if defined(BCMSUP_4WAY_HANDSHAKE) /* Use in dongle supplicant for 4-way handshake */ #if defined(WLFBT) || defined(WL_ENABLE_IDSUP) @@ -1882,6 +1978,13 @@ module_param(dhd_use_idsup, uint, 0); int allow_delay_fwdl = FALSE; module_param(allow_delay_fwdl, int, 0); +#ifdef ECOUNTER_PERIODIC_DISABLE +uint enable_ecounter = FALSE; +#else +uint enable_ecounter = TRUE; +#endif // endif +module_param(enable_ecounter, uint, 0); + extern char dhd_version[]; extern char fw_version[]; extern char clm_version[]; @@ -1892,7 +1995,6 @@ static void dhd_net_if_unlock_local(dhd_info_t *dhd); static void dhd_suspend_lock(dhd_pub_t *dhdp); static void dhd_suspend_unlock(dhd_pub_t *dhdp); - /* Monitor interface */ int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); @@ -1931,11 +2033,11 @@ static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, voi #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif dhd_info_t *dhdinfo = (dhd_info_t*)container_of(nfb, struct dhd_info, pm_notifier); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif BCM_REFERENCE(dhdinfo); BCM_REFERENCE(suspend); @@ -1966,7 +2068,7 @@ static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, voi KERNEL_VERSION(2, 6, 39)) dhd_mmc_suspend = suspend; smp_mb(); -#endif +#endif // endif return ret; } @@ -2045,9 +2147,6 @@ dhd_info_t dhd_info_null = { #ifdef DHDTCPACK_SUPPRESS .tcpack_sup_mode = TCPACK_SUP_REPLACE, #endif /* DHDTCPACK_SUPPRESS */ -#if defined(TRAFFIC_MGMT_DWM) - .dhd_tm_dwm_tbl = { .dhd_dwm_enabled = TRUE }, -#endif .up = FALSE, .busstate = DHD_BUS_DOWN } @@ -2065,7 +2164,7 @@ struct net_device dhd_net_dev_null = { dhd_if_t dhd_if_null = { #ifdef WMF .wmf = { .wmf_enable = TRUE }, -#endif +#endif // endif .info = DHD_INFO_NULL, .net = DHD_NET_DEV_NULL, .idx = DHD_BAD_IF @@ -2093,7 +2192,6 @@ static void dhd_sta_pool_fini(dhd_pub_t *dhdp, int max_sta); /* Clear the pool of dhd_sta_t objects for built-in type driver */ static void dhd_sta_pool_clear(dhd_pub_t *dhdp, int max_sta); - /* Return interface pointer */ static inline dhd_if_t *dhd_get_ifp(dhd_pub_t *dhdp, uint32 ifidx) { @@ -2201,14 +2299,14 @@ dhd_if_del_sta_list(dhd_if_t *ifp) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { list_del(&sta->list); dhd_sta_free(&ifp->info->pub, sta); } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif DHD_IF_STA_LIST_UNLOCK(ifp, flags); return; @@ -2258,6 +2356,7 @@ dhd_sta_pool_init(dhd_pub_t *dhdp, int max_sta) sta->idx = id16_map_alloc(staid_allocator); ASSERT(sta->idx <= max_sta); } + /* Now place them into the pre-allocated free pool. */ for (idx = 1; idx <= max_sta; idx++) { sta = &sta_pool[idx]; @@ -2360,10 +2459,10 @@ dhd_find_sta(void *pub, int ifidx, void *ea) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry(sta, &ifp->sta_list, list) { if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) { - DHD_INFO(("%s: found STA " MACDBG "\n", + DHD_INFO(("%s: Found STA " MACDBG "\n", __FUNCTION__, MAC2STRDBG((char *)ea))); DHD_IF_STA_LIST_UNLOCK(ifp, flags); return sta; @@ -2371,7 +2470,7 @@ dhd_find_sta(void *pub, int ifidx, void *ea) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif DHD_IF_STA_LIST_UNLOCK(ifp, flags); return DHD_STA_NULL; @@ -2390,6 +2489,11 @@ dhd_add_sta(void *pub, int ifidx, void *ea) if (ifp == NULL) return DHD_STA_NULL; + if (!memcmp(ifp->net->dev_addr, ea, ETHER_ADDR_LEN)) { + DHD_ERROR(("%s: Serious FAILURE, receive own MAC %pM !!\n", __FUNCTION__, ea)); + return DHD_STA_NULL; + } + sta = dhd_sta_alloc((dhd_pub_t *)pub); if (sta == DHD_STA_NULL) { DHD_ERROR(("%s: Alloc failed\n", __FUNCTION__)); @@ -2407,6 +2511,8 @@ dhd_add_sta(void *pub, int ifidx, void *ea) list_add_tail(&sta->list, &ifp->sta_list); + DHD_ERROR(("%s: Adding STA " MACDBG "\n", + __FUNCTION__, MAC2STRDBG((char *)ea))); DHD_IF_STA_LIST_UNLOCK(ifp, flags); @@ -2429,7 +2535,7 @@ dhd_del_all_sta(void *pub, int ifidx) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { list_del(&sta->list); @@ -2445,7 +2551,7 @@ dhd_del_all_sta(void *pub, int ifidx) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif DHD_IF_STA_LIST_UNLOCK(ifp, flags); return; @@ -2468,7 +2574,7 @@ dhd_del_sta(void *pub, int ifidx, void *ea) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(sta, next, &ifp->sta_list, list) { if (!memcmp(sta->ea.octet, ea, ETHER_ADDR_LEN)) { DHD_ERROR(("%s: Deleting STA " MACDBG "\n", @@ -2479,7 +2585,7 @@ dhd_del_sta(void *pub, int ifidx, void *ea) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif DHD_IF_STA_LIST_UNLOCK(ifp, flags); #ifdef DHD_L2_FILTER if (ifp->parp_enable) { @@ -2560,11 +2666,10 @@ dhd_sta_t *dhd_find_sta(void *pub, int ifidx, void *ea) { return NULL; } void dhd_del_sta(void *pub, int ifidx, void *ea) {} #endif /* PCIE_FULL_DONGLE */ - - #if defined(DHD_LB) -#if defined(DHD_LB_TXC) || defined(DHD_LB_RXC) || defined(DHD_LB_TXP) +#if defined(DHD_LB_TXC) || defined(DHD_LB_RXC) || defined(DHD_LB_TXP) || \ + defined(DHD_LB_RXP) /** * dhd_tasklet_schedule - Function that runs in IPI context of the destination * CPU and schedules a tasklet. @@ -2607,7 +2712,7 @@ dhd_work_schedule_on(struct work_struct *work, int on_cpu) { schedule_work_on(on_cpu, work); } -#endif /* DHD_LB_TXC || DHD_LB_RXC || DHD_LB_TXP */ +#endif /* DHD_LB_TXC || DHD_LB_RXC || DHD_LB_TXP || DHD_LB_RXP */ #if defined(DHD_LB_TXC) /** @@ -2691,23 +2796,24 @@ dhd_lb_rx_compl_dispatch(dhd_pub_t *dhdp) if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) { dhd_tasklet_schedule(&dhd->rx_compl_tasklet); } else { - dhd_rx_compl_dispatcher_fn(dhdp); + schedule_work(&dhd->rx_compl_dispatcher_work); } } -static void dhd_rx_compl_dispatcher_fn(dhd_pub_t *dhdp) +static void dhd_rx_compl_dispatcher_fn(struct work_struct * work) { - struct dhd_info *dhd = dhdp->info; + struct dhd_info *dhd = + container_of(work, struct dhd_info, rx_compl_dispatcher_work); int cpu; - preempt_disable(); + get_online_cpus(); cpu = atomic_read(&dhd->rx_compl_cpu); if (!cpu_online(cpu)) dhd_tasklet_schedule(&dhd->rx_compl_tasklet); else { dhd_tasklet_schedule_on(&dhd->rx_compl_tasklet, cpu); } - preempt_enable(); + put_online_cpus(); } #endif /* DHD_LB_RXC */ @@ -2717,12 +2823,12 @@ static void dhd_tx_dispatcher_work(struct work_struct * work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif struct dhd_info *dhd = container_of(work, struct dhd_info, tx_dispatcher_work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif dhd_tasklet_schedule(&dhd->tx_tasklet); } @@ -2781,7 +2887,6 @@ dhd_lb_tx_dispatch(dhd_pub_t *dhdp) /* Schedule the work to dispatch ... */ dhd_tx_dispatcher_fn(dhdp); - } #endif /* DHD_LB_TXP */ @@ -2809,16 +2914,15 @@ dhd_napi_poll(struct napi_struct *napi, int budget) struct dhd_info *dhd; int processed = 0; struct sk_buff_head rx_process_queue; - int cnt = 0; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif dhd = container_of(napi, struct dhd_info, rx_napi_struct); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif DHD_INFO(("%s napi_queue<%d> budget<%d>\n", __FUNCTION__, skb_queue_len(&dhd->rx_napi_queue), budget)); @@ -2829,7 +2933,6 @@ dhd_napi_poll(struct napi_struct *napi, int budget) skb_queue_splice_tail_init(&dhd->rx_napi_queue, &rx_process_queue); spin_unlock_irqrestore(&dhd->rx_napi_queue.lock, flags); - cnt = (int)skb_queue_len(&rx_process_queue); while ((skb = __skb_dequeue(&rx_process_queue)) != NULL) { OSL_PREFETCH(skb->data); @@ -2840,18 +2943,6 @@ dhd_napi_poll(struct napi_struct *napi, int budget) dhd_rx_frame(&dhd->pub, ifid, skb, pkt_count, chan); processed++; - - if (cnt-- < 0) { - DHD_ERROR(("%s list:%p, list->prev:%p, list->next=%p\n", - __FUNCTION__, - &rx_process_queue, - rx_process_queue.prev, - rx_process_queue.next)); - DHD_ERROR(("%s skb:%p, skb->prev:%p, skb->next=%p\n", - __FUNCTION__, skb, skb->prev, skb->next)); - - DHD_ERROR(("%s processed %d\n", __FUNCTION__, processed)); - } } DHD_LB_STATS_UPDATE_NAPI_HISTO(&dhd->pub, processed); @@ -2949,23 +3040,14 @@ static void dhd_rx_napi_dispatcher_fn(struct work_struct * work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif struct dhd_info *dhd = container_of(work, struct dhd_info, rx_napi_dispatcher_work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif - int cpu; - - get_online_cpus(); - cpu = atomic_read(&dhd->rx_napi_cpu); - - if (!cpu_online(cpu)) - dhd_napi_schedule(dhd); - else - dhd_napi_schedule_on(dhd, cpu); +#endif // endif - put_online_cpus(); + dhd_napi_schedule(dhd); } /** @@ -3006,28 +3088,23 @@ dhd_lb_rx_napi_dispatch(dhd_pub_t *dhdp) curr_cpu = get_cpu(); put_cpu(); + preempt_disable(); on_cpu = atomic_read(&dhd->rx_napi_cpu); - DHD_INFO(("%s : curr_cpu : %d, cpumask : 0x%lx\n", __FUNCTION__, - curr_cpu, *cpumask_bits(dhd->cpumask_primary))); - - if (0 || #ifdef DHD_LB_IRQSET - /* XXX : SWWLAN-163963 - * Migration CPU from little to big has Tput degradation in NAS download - * scenario, and changing IRQ affinity from little to big shows - * the best performance without migration, - * so, if curr_cpu (from IRQ) is set from big core, - * it won't schedule to dedicated cpu. - */ - cpumask_and(&cpus, cpumask_of(curr_cpu), dhd->cpumask_primary) || + if (cpumask_and(&cpus, cpumask_of(curr_cpu), dhd->cpumask_primary) || + (!cpu_online(on_cpu))) { #else - (on_cpu == curr_cpu) || + if ((on_cpu == curr_cpu) || (!cpu_online(on_cpu))) { #endif /* DHD_LB_IRQSET */ - (!cpu_online(on_cpu))) { + DHD_INFO(("%s : curr_cpu : %d, cpumask : 0x%lx\n", __FUNCTION__, + curr_cpu, *cpumask_bits(dhd->cpumask_primary))); dhd_napi_schedule(dhd); } else { - schedule_work(&dhd->rx_napi_dispatcher_work); + DHD_INFO(("%s : schedule to curr_cpu : %d, cpumask : 0x%lx\n", + __FUNCTION__, curr_cpu, *cpumask_bits(dhd->cpumask_primary))); + dhd_work_schedule_on(&dhd->rx_napi_dispatcher_work, on_cpu); } + preempt_enable(); } /** @@ -3049,30 +3126,28 @@ dhd_lb_rx_pkt_enqueue(dhd_pub_t *dhdp, void *pkt, int ifidx) void dhd_irq_set_affinity(dhd_pub_t *dhdp) { - unsigned int irq = (unsigned int)-1; - int err = BCME_OK; + unsigned int irq = (unsigned int)-1; + int err = BCME_OK; - if (!dhdp) { - DHD_ERROR(("%s : dhdp is NULL\n", __FUNCTION__)); - return; - } + if (!dhdp) { + DHD_ERROR(("%s : dhdp is NULL\n", __FUNCTION__)); + return; + } - if (!dhdp->bus) { - DHD_ERROR(("%s : bus is NULL\n", __FUNCTION__)); - return; - } + if (!dhdp->bus) { + DHD_ERROR(("%s : bus is NULL\n", __FUNCTION__)); + return; + } - dhdpcie_get_pcieirq(dhdp->bus, &irq); - err = irq_set_affinity(irq, dhdp->info->cpumask_primary); - if (err) { - DHD_ERROR(("%s : irq set affinity is failed cpu:0x%lx\n", - __FUNCTION__, *cpumask_bits(dhdp->info->cpumask_primary))); - } + dhdpcie_get_pcieirq(dhdp->bus, &irq); + err = irq_set_affinity(irq, dhdp->info->cpumask_primary); + if (err) + DHD_ERROR(("%s : irq set affinity is failed cpu:0x%lx\n", + __FUNCTION__, *cpumask_bits(dhdp->info->cpumask_primary))); } #endif /* DHD_LB_IRQSET */ #endif /* DHD_LB */ - /** Returns dhd iflist index corresponding the the bssidx provided by apps */ int dhd_bssidx2idx(dhd_pub_t *dhdp, uint32 bssidx) { @@ -3117,7 +3192,7 @@ static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb) */ #if defined(WAIT_DEQUEUE) OSL_SLEEP(1); -#endif +#endif // endif return BCME_ERROR; } DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n", @@ -3318,9 +3393,6 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #ifndef SUPPORT_PM2_ONLY int power_mode = PM_MAX; #endif /* SUPPORT_PM2_ONLY */ -#ifdef SUPPORT_SENSORHUB - shub_control_t shub_ctl; -#endif /* SUPPORT_SENSORHUB */ /* wl_pkt_filter_enable_t enable_parm; */ int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ int ret = 0; @@ -3338,15 +3410,15 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) int bcn_li_bcn; #endif /* ENABLE_BCN_LI_BCN_WAKEUP */ uint nd_ra_filter = 0; +#ifdef ENABLE_IPMCAST_FILTER + int ipmcast_l2filter; +#endif /* ENABLE_IPMCAST_FILTER */ #endif /* DHD_USE_EARLYSUSPEND */ #ifdef PASS_ALL_MCAST_PKTS struct dhd_info *dhdinfo; uint32 allmulti; uint i; #endif /* PASS_ALL_MCAST_PKTS */ -#ifdef ENABLE_IPMCAST_FILTER - int ipmcast_l2filter; -#endif /* ENABLE_IPMCAST_FILTER */ #ifdef DYNAMIC_SWOOB_DURATION #ifndef CUSTOM_INTR_WIDTH #define CUSTOM_INTR_WIDTH 100 @@ -3359,11 +3431,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) int dtim_period = 0; int bcn_interval = 0; int bcn_to_dly = 0; -#ifndef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND - int bcn_timeout = CUSTOM_BCN_TIMEOUT_SETTING; -#else +#if defined(CUSTOM_BCN_TIMEOUT_IN_SUSPEND) && defined(DHD_USE_EARLYSUSPEND) bcn_timeout = CUSTOM_BCN_TIMEOUT_SETTING; -#endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ +#else + int bcn_timeout = CUSTOM_BCN_TIMEOUT_SETTING; +#endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND && DHD_USE_EARLYSUSPEND */ #endif /* OEM_ANDROID && BCMPCIE */ if (!dhd) @@ -3387,9 +3459,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) if (value && dhd->in_suspend) { #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 1; -#endif +#endif // 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, @@ -3406,29 +3478,18 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #endif /* APF */ #endif /* PKT_FILTER_SUPPORT */ -#ifdef SUPPORT_SENSORHUB - shub_ctl.enable = 1; - shub_ctl.cmd = 0x000; - shub_ctl.op_mode = 1; - shub_ctl.interval = 0; - if (dhd->info->shub_enable == 1) { - ret = dhd_iovar(dhd, 0, "shub_msreq", - (char *)&shub_ctl, sizeof(shub_ctl), NULL, 0, TRUE); - if (ret < 0) { - DHD_ERROR(("%s SensorHub MS start: failed %d\n", - __FUNCTION__, ret)); - } - } -#endif /* SUPPORT_SENSORHUB */ - - #ifdef PASS_ALL_MCAST_PKTS allmulti = 0; for (i = 0; i < DHD_MAX_IFS; i++) { if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) - dhd_iovar(dhd, i, "allmulti", (char *)&allmulti, - sizeof(allmulti), NULL, 0, TRUE); - + ret = dhd_iovar(dhd, i, "allmulti", + (char *)&allmulti, + sizeof(allmulti), + NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s allmulti failed %d\n", + __FUNCTION__, ret)); + } } #endif /* PASS_ALL_MCAST_PKTS */ @@ -3444,10 +3505,13 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #endif /* WLTDLS */ #if defined(BCMPCIE) bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd, &dtim_period, - &bcn_interval); - dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, + &bcn_interval); + ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, sizeof(bcn_li_dtim), NULL, 0, TRUE); - + if (ret < 0) { + DHD_ERROR(("%s bcn_li_dtim failed %d\n", + __FUNCTION__, ret)); + } if ((bcn_li_dtim * dtim_period * bcn_interval) >= MIN_DTIM_FOR_ROAM_THRES_EXTEND) { /* @@ -3456,9 +3520,12 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) * bcn_timeout/2) */ lpas = 1; - dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), NULL, - 0, TRUE); - + ret = dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), + NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s lpas failed %d\n", __FUNCTION__, + ret)); + } bcn_to_dly = 1; /* * if bcn_to_dly is 1, the real roam threshold is @@ -3466,12 +3533,20 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) * notify link down event after roaming procedure complete * if we hit bcn_timeout while we are in roaming progress. */ - dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, + ret = dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, sizeof(bcn_to_dly), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s bcn_to_dly failed %d\n", + __FUNCTION__, ret)); + } /* Increase beacon timeout to 6 secs or use bigger one */ bcn_timeout = max(bcn_timeout, BCN_TIMEOUT_IN_SUSPEND); - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s bcn_timeout failed %d\n", + __FUNCTION__, ret)); + } } #else bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd); @@ -3483,29 +3558,45 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #ifdef DHD_USE_EARLYSUSPEND #ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND bcn_timeout = CUSTOM_BCN_TIMEOUT_IN_SUSPEND; - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s bcn_timeout failed %d\n", __FUNCTION__, + ret)); + } #endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */ #ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND roam_time_thresh = CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND; - dhd_iovar(dhd, 0, "roam_time_thresh", (char *)&roam_time_thresh, + ret = dhd_iovar(dhd, 0, "roam_time_thresh", + (char *)&roam_time_thresh, sizeof(roam_time_thresh), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s roam_time_thresh failed %d\n", + __FUNCTION__, ret)); + } #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ #ifndef ENABLE_FW_ROAM_SUSPEND /* Disable firmware roaming during suspend */ - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), - NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, + sizeof(roamvar), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s roam_off failed %d\n", + __FUNCTION__, ret)); + } #endif /* ENABLE_FW_ROAM_SUSPEND */ #ifdef ENABLE_BCN_LI_BCN_WAKEUP bcn_li_bcn = 0; - dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, sizeof(bcn_li_bcn), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s bcn_li_bcn failed %d\n", __FUNCTION__, ret)); + } #endif /* ENABLE_BCN_LI_BCN_WAKEUP */ #ifdef NDO_CONFIG_SUPPORT if (dhd->ndo_enable) { if (!dhd->ndo_host_ip_overflow) { /* enable ND offload on suspend */ - ret = dhd_ndo_enable(dhd, 1); + ret = dhd_ndo_enable(dhd, TRUE); if (ret < 0) { DHD_ERROR(("%s: failed to enable NDO\n", __FUNCTION__)); @@ -3536,6 +3627,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) ret = dhd_iovar(dhd, 0, "ipmcast_l2filter", (char *)&ipmcast_l2filter, sizeof(ipmcast_l2filter), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("failed to set ipmcast_l2filter (%d)\n", ret)); + } #endif /* ENABLE_IPMCAST_FILTER */ #ifdef DYNAMIC_SWOOB_DURATION intr_width = CUSTOM_INTR_WIDTH; @@ -3549,26 +3643,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) } else { #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 0; -#endif +#endif // endif /* Kernel resumed */ DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__)); - -#ifdef SUPPORT_SENSORHUB - shub_ctl.enable = 1; - shub_ctl.cmd = 0x000; - shub_ctl.op_mode = 0; - shub_ctl.interval = 0; - if (dhd->info->shub_enable == 1) { - ret = dhd_iovar(dhd, 0, "shub_msreq", - (char *)&shub_ctl, sizeof(shub_ctl), - NULL, 0, TRUE); - if (ret < 0) { - DHD_ERROR(("%s SensorHub MS stop: failed %d\n", - __FUNCTION__, ret)); - } - } -#endif /* SUPPORT_SENSORHUB */ - #ifdef DYNAMIC_SWOOB_DURATION intr_width = 0; ret = dhd_iovar(dhd, 0, "bus:intr_width", (char *)&intr_width, @@ -3593,23 +3670,40 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) allmulti = 1; for (i = 0; i < DHD_MAX_IFS; i++) { if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) - dhd_iovar(dhd, i, "allmulti", (char *)&allmulti, - sizeof(allmulti), NULL, 0, TRUE); + ret = dhd_iovar(dhd, i, "allmulti", + (char *)&allmulti, + sizeof(allmulti), NULL, + 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s: allmulti failed:%d\n", + __FUNCTION__, ret)); + } } #endif /* PASS_ALL_MCAST_PKTS */ #if defined(BCMPCIE) /* restore pre-suspend setting */ - dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, + ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, sizeof(bcn_li_dtim), NULL, 0, TRUE); - - dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), NULL, 0, - TRUE); - - dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, + if (ret < 0) { + DHD_ERROR(("%s:bcn_li_ditm failed:%d\n", + __FUNCTION__, ret)); + } + ret = dhd_iovar(dhd, 0, "lpas", (char *)&lpas, sizeof(lpas), NULL, + 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s:lpas failed:%d\n", __FUNCTION__, ret)); + } + ret = dhd_iovar(dhd, 0, "bcn_to_dly", (char *)&bcn_to_dly, sizeof(bcn_to_dly), NULL, 0, TRUE); - - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, + if (ret < 0) { + DHD_ERROR(("%s:bcn_to_dly failed:%d\n", __FUNCTION__, ret)); + } + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s:bcn_timeout failed:%d\n", + __FUNCTION__, ret)); + } #else /* restore pre-suspend setting for dtim_skip */ ret = dhd_iovar(dhd, 0, "bcn_li_dtim", (char *)&bcn_li_dtim, @@ -3621,29 +3715,45 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) #ifdef DHD_USE_EARLYSUSPEND #ifdef CUSTOM_BCN_TIMEOUT_IN_SUSPEND bcn_timeout = CUSTOM_BCN_TIMEOUT; - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s:bcn_timeout failed:%d\n", + __FUNCTION__, ret)); + } #endif /* CUSTOM_BCN_TIMEOUT_IN_SUSPEND */ #ifdef CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND roam_time_thresh = 2000; - dhd_iovar(dhd, 0, "roam_time_thresh", (char *)&roam_time_thresh, + ret = dhd_iovar(dhd, 0, "roam_time_thresh", + (char *)&roam_time_thresh, sizeof(roam_time_thresh), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s:roam_time_thresh failed:%d\n", + __FUNCTION__, ret)); + } #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */ #ifndef ENABLE_FW_ROAM_SUSPEND roamvar = dhd_roam_disable; - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), - NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, + sizeof(roamvar), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s: roam_off fail:%d\n", __FUNCTION__, ret)); + } #endif /* ENABLE_FW_ROAM_SUSPEND */ #ifdef ENABLE_BCN_LI_BCN_WAKEUP bcn_li_bcn = 1; - dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, sizeof(bcn_li_bcn), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s: bcn_li_bcn failed:%d\n", + __FUNCTION__, ret)); + } #endif /* ENABLE_BCN_LI_BCN_WAKEUP */ #ifdef NDO_CONFIG_SUPPORT if (dhd->ndo_enable) { /* Disable ND offload on resume */ - ret = dhd_ndo_enable(dhd, 0); + ret = dhd_ndo_enable(dhd, FALSE); if (ret < 0) { DHD_ERROR(("%s: failed to disable NDO\n", __FUNCTION__)); @@ -3671,6 +3781,9 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) ret = dhd_iovar(dhd, 0, "ipmcast_l2filter", (char *)&ipmcast_l2filter, sizeof(ipmcast_l2filter), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("failed to clear ipmcast_l2filter ret:%d", ret)); + } #endif /* ENABLE_IPMCAST_FILTER */ #endif /* DHD_USE_EARLYSUSPEND */ #ifdef DHD_LB_IRQSET @@ -3867,7 +3980,6 @@ dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx) return NULL; } - static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) { @@ -3876,7 +3988,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) struct netdev_hw_addr *ha; #else struct dev_mc_list *mclist; -#endif +#endif // endif uint32 allmulti, cnt; wl_ioctl_t ioc; @@ -3945,7 +4057,6 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) /* Send down the multicast list first. */ - buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN); if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) { DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n", @@ -3974,11 +4085,11 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif netdev_for_each_mc_addr(ha, dev) { #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (!cnt_iface[i]) break; memcpy(bufp, ha->addr, ETHER_ADDR_LEN); @@ -4008,7 +4119,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif netdev_for_each_mc_addr(ha, dev) { if (!cnt) break; @@ -4018,7 +4129,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif #else /* LINUX < 2.6.35 */ for (mclist = dev->mc_list; (mclist && (cnt > 0)); cnt--, mclist = mclist->next) { @@ -4109,8 +4220,7 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, uint8 *addr) #ifdef SOFTAP extern struct net_device *ap_net_dev; extern tsk_ctl_t ap_eth_ctl; /* ap netdev heper thread ctl */ -#endif - +#endif // endif #ifdef DHD_PSTA /* Get psta/psr configuration configuration */ @@ -4142,13 +4252,13 @@ dhd_update_rx_pkt_chainable_state(dhd_pub_t* dhdp, uint32 idx) if ( #ifdef DHD_L2_FILTER (ifp->block_ping) || -#endif +#endif // endif #ifdef DHD_WET (dhd->wet_mode) || -#endif +#endif // endif #ifdef DHD_MCAST_REGEN (ifp->mcast_regen_bss_enable) || -#endif +#endif // endif FALSE) { ifp->rx_pkt_chainable = FALSE; } @@ -4201,13 +4311,15 @@ dhd_ifadd_event_handler(void *handle, void *event_info, u8 event) { dhd_info_t *dhd = handle; dhd_if_event_t *if_event = event_info; - struct net_device *ndev; int ifidx, bssidx; int ret; #if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) struct wl_if_event_info info; +#else + struct net_device *ndev; #endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ + BCM_REFERENCE(ret); if (event != DHD_WQ_WORK_IF_ADD) { DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); return; @@ -4231,23 +4343,28 @@ dhd_ifadd_event_handler(void *handle, void *event_info, u8 event) bssidx = if_event->event.bssidx; DHD_TRACE(("%s: registering if with ifidx %d\n", __FUNCTION__, ifidx)); - #if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) if (if_event->event.ifidx > 0) { + u8 *mac_addr; bzero(&info, sizeof(info)); - info.ifidx = if_event->event.ifidx; - info.bssidx = if_event->event.bssidx; + info.ifidx = ifidx; + info.bssidx = bssidx; info.role = if_event->event.role; strncpy(info.name, if_event->name, IFNAMSIZ); + if (is_valid_ether_addr(if_event->mac)) { + mac_addr = if_event->mac; + } else { + mac_addr = NULL; + } + if (wl_cfg80211_post_ifcreate(dhd->pub.info->iflist[0]->net, - &info, if_event->mac, NULL, true) != NULL) { + &info, mac_addr, NULL, true) == NULL) { /* Do the post interface create ops */ - DHD_ERROR(("Post ifcreate ops done. Returning \n")); + DHD_ERROR(("Post ifcreate ops failed. Returning \n")); goto done; } } -#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ - +#else /* This path is for non-android case */ /* The interface name in host and in event msg are same */ /* if name in event msg is used to create dongle if list on host */ @@ -4266,6 +4383,8 @@ dhd_ifadd_event_handler(void *handle, void *event_info, u8 event) dhd_remove_if(&dhd->pub, ifidx, TRUE); goto done; } +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ + #ifndef PCIE_FULL_DONGLE /* Turn on AP isolation in the firmware for interfaces operating in AP mode */ if (FW_SUPPORTED((&dhd->pub), ap) && (if_event->event.role != WLC_E_IF_ROLE_STA)) { @@ -4294,7 +4413,6 @@ dhd_ifdel_event_handler(void *handle, void *event_info, u8 event) int ifidx; dhd_if_event_t *if_event = event_info; - if (event != DHD_WQ_WORK_IF_DEL) { DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); return; @@ -4318,25 +4436,28 @@ dhd_ifdel_event_handler(void *handle, void *event_info, u8 event) DHD_TRACE(("Removing interface with idx %d\n", ifidx)); DHD_PERIM_UNLOCK(&dhd->pub); + if (!dhd->pub.info->iflist[ifidx]) { + /* No matching netdev found */ + DHD_ERROR(("Netdev not found! Do nothing.\n")); + goto done; + } #if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) if (if_event->event.ifidx > 0) { /* Do the post interface del ops */ - if (wl_cfg80211_post_ifdel(dhd->pub.info->iflist[ifidx]->net, true) == 0) { - DHD_TRACE(("Post ifdel ops done. Returning \n")); - DHD_PERIM_LOCK(&dhd->pub); + if (wl_cfg80211_post_ifdel(dhd->pub.info->iflist[ifidx]->net, + true, if_event->event.ifidx) != 0) { + DHD_TRACE(("Post ifdel ops failed. Returning \n")); goto done; } } -#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ - +#else + /* For non-cfg80211 drivers */ dhd_remove_if(&dhd->pub, ifidx, TRUE); - DHD_PERIM_LOCK(&dhd->pub); +#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ -#if defined(WL_CFG80211) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) done: -#endif /* WL_CFG80211 && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ + DHD_PERIM_LOCK(&dhd->pub); MFREE(dhd->pub.osh, if_event, sizeof(dhd_if_event_t)); - DHD_PERIM_UNLOCK(&dhd->pub); DHD_OS_WAKE_UNLOCK(&dhd->pub); dhd_net_if_unlock_local(dhd); @@ -4591,7 +4712,7 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) struct ether_header *eh = NULL; #if defined(DHD_L2_FILTER) dhd_if_t *ifp = dhd_get_ifp(dhdp, ifidx); -#endif +#endif // endif /* Reject if down */ if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { @@ -4696,14 +4817,17 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) pktsetprio(pktbuf, FALSE); #endif /* QOS_MAP_SET */ } +#ifndef PKTPRIO_OVERRIDE + else { + /* Some protocols like OZMO use priority values from 256..263. + * these are magic values to indicate a specific 802.1d priority. + * make sure that priority field is in range of 0..7 + */ + PKTSETPRIO(pktbuf, PKTPRIO(pktbuf) & 0x7); + } +#endif /* !PKTPRIO_OVERRIDE */ } - -#if defined(TRAFFIC_MGMT_DWM) - traffic_mgmt_pkt_set_prio(dhdp, pktbuf); - -#endif - #ifdef PCIE_FULL_DONGLE /* * Lkup the per interface hash table, for a matching flowring. If one is not @@ -4715,7 +4839,7 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) PKTCFREE(dhd->pub.osh, pktbuf, TRUE); return ret; } -#endif +#endif // endif #ifdef PROP_TXSTATUS if (dhd_wlfc_is_supported(dhdp)) { @@ -4804,7 +4928,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #ifdef DHD_PCIE_RUNTIMEPM exit: -#endif +#endif // endif DHD_GENERAL_LOCK(dhdp, flags); DHD_BUS_BUSY_CLEAR_IN_SEND_PKT(dhdp); dhd_os_busbusy_wake(dhdp); @@ -4879,7 +5003,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) return -ENODEV; #else return NETDEV_TX_BUSY; -#endif +#endif // endif } #endif /* DHD_PCIE_RUNTIMEPM */ @@ -4900,13 +5024,12 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) return -ENODEV; #else return NETDEV_TX_BUSY; -#endif +#endif // endif } DHD_OS_WAKE_LOCK(&dhd->pub); DHD_PERIM_LOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken); - #if defined(DHD_HANG_SEND_UP_TEST) if (dhd->pub.req_hang_type == HANG_REASON_BUS_DOWN) { dhd->pub.busstate = DHD_BUS_DOWN; @@ -4933,7 +5056,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) return -ENODEV; #else return NETDEV_TX_BUSY; -#endif +#endif // endif } ifp = DHD_DEV_IFP(net); @@ -4950,7 +5073,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) return -ENODEV; #else return NETDEV_TX_BUSY; -#endif +#endif // endif } DHD_GENERAL_UNLOCK(&dhd->pub, flags); @@ -5020,8 +5143,9 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) /* PSR related packet proto manipulation should be done in DHD * since dongle doesn't have complete payload */ - if (PSR_ENABLED(&dhd->pub) && (dhd_psta_proc(&dhd->pub, - ifidx, &pktbuf, TRUE) < 0)) { + if (PSR_ENABLED(&dhd->pub) && + (dhd_psta_proc(&dhd->pub, ifidx, &pktbuf, TRUE) < 0)) { + DHD_ERROR(("%s:%s: psta send proc failed\n", __FUNCTION__, dhd_ifname(&dhd->pub, ifidx))); } @@ -5051,7 +5175,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) ret = dhd_lb_sendpkt(dhd, net, ifidx, pktbuf); #else ret = __dhd_sendpkt(&dhd->pub, ifidx, pktbuf); -#endif +#endif // endif done: if (ret) { @@ -5061,7 +5185,7 @@ done: #ifdef PROP_TXSTATUS /* tx_packets counter can counted only when wlfc is disabled */ if (!dhd_wlfc_is_supported(&dhd->pub)) -#endif +#endif // endif { dhd->pub.tx_packets++; ifp->stats.tx_packets++; @@ -5069,7 +5193,6 @@ done: } } - DHD_GENERAL_LOCK(&dhd->pub, flags); DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub); dhd_os_busbusy_wake(&dhd->pub); @@ -5081,30 +5204,145 @@ done: return 0; #else return NETDEV_TX_OK; -#endif +#endif // endif } - -void -dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state) +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +void dhd_rx_wq_wakeup(struct work_struct *ptr) { - struct net_device *net; - dhd_info_t *dhd = dhdp->info; - int i; + struct dhd_rx_tx_work *work; + struct dhd_pub * pub; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + work = container_of(ptr, struct dhd_rx_tx_work, work); - ASSERT(dhd); + pub = work->pub; -#ifdef DHD_LOSSLESS_ROAMING - /* block flowcontrol during roaming */ - if ((dhdp->dequeue_prec_map == 1 << PRIO_8021D_NC) && state == ON) { + DHD_RPM(("%s: ENTER. \n", __FUNCTION__)); + + if (atomic_read(&pub->block_bus) || pub->busstate == DHD_BUS_DOWN) { return; } -#endif - if (ifidx == ALL_INTERFACES) { - /* Flow control on all active interfaces */ + DHD_OS_WAKE_LOCK(pub); + if (pm_runtime_get_sync(dhd_bus_to_dev(pub->bus)) >= 0) { + + // do nothing but wakeup the bus. + pm_runtime_mark_last_busy(dhd_bus_to_dev(pub->bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(pub->bus)); + } + DHD_OS_WAKE_UNLOCK(pub); + kfree(work); +} + +void dhd_start_xmit_wq_adapter(struct work_struct *ptr) +{ + struct dhd_rx_tx_work *work; + int ret; + dhd_info_t *dhd; + struct dhd_bus * bus; + + work = container_of(ptr, struct dhd_rx_tx_work, work); + + dhd = DHD_DEV_INFO(work->net); + + bus = dhd->pub.bus; + + if (atomic_read(&dhd->pub.block_bus)) { + kfree_skb(work->skb); + kfree(work); + dhd_netif_start_queue(bus); + return; + } + + if (pm_runtime_get_sync(dhd_bus_to_dev(bus)) >= 0) { + ret = dhd_start_xmit(work->skb, work->net); + pm_runtime_mark_last_busy(dhd_bus_to_dev(bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(bus)); + } + kfree(work); + dhd_netif_start_queue(bus); + + if (ret) + netdev_err(work->net, + "error: dhd_start_xmit():%d\n", ret); +} + +int BCMFASTPATH +dhd_start_xmit_wrapper(struct sk_buff *skb, struct net_device *net) +{ + struct dhd_rx_tx_work *start_xmit_work; + int ret; + dhd_info_t *dhd = DHD_DEV_INFO(net); + + if (dhd->pub.busstate == DHD_BUS_SUSPEND) { + DHD_RPM(("%s: wakeup the bus using workqueue.\n", __FUNCTION__)); + + dhd_netif_stop_queue(dhd->pub.bus); + + start_xmit_work = (struct dhd_rx_tx_work*) + kmalloc(sizeof(*start_xmit_work), GFP_ATOMIC); + + if (!start_xmit_work) { + netdev_err(net, + "error: failed to alloc start_xmit_work\n"); + ret = -ENOMEM; + goto exit; + } + + INIT_WORK(&start_xmit_work->work, dhd_start_xmit_wq_adapter); + start_xmit_work->skb = skb; + start_xmit_work->net = net; + queue_work(dhd->tx_wq, &start_xmit_work->work); + ret = NET_XMIT_SUCCESS; + + } else if (dhd->pub.busstate == DHD_BUS_DATA) { + ret = dhd_start_xmit(skb, net); + } else { + /* when bus is down */ + ret = -ENODEV; + } + +exit: + return ret; +} +void +dhd_bus_wakeup_work(dhd_pub_t *dhdp) +{ + struct dhd_rx_tx_work *rx_work; + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + + rx_work = kmalloc(sizeof(*rx_work), GFP_ATOMIC); + if (!rx_work) { + DHD_ERROR(("%s: start_rx_work alloc error. \n", __FUNCTION__)); + return; + } + + INIT_WORK(&rx_work->work, dhd_rx_wq_wakeup); + rx_work->pub = dhdp; + queue_work(dhd->rx_wq, &rx_work->work); + +} +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ +void +dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state) +{ + struct net_device *net; + dhd_info_t *dhd = dhdp->info; + int i; + + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + + ASSERT(dhd); + +#ifdef DHD_LOSSLESS_ROAMING + /* block flowcontrol during roaming */ + if ((dhdp->dequeue_prec_map == 1 << PRIO_8021D_NC) && state == ON) { + return; + } +#endif // endif + + if (ifidx == ALL_INTERFACES) { + /* Flow control on all active interfaces */ dhdp->txoff = state; for (i = 0; i < DHD_MAX_IFS; i++) { if (dhd->iflist[i]) { @@ -5158,8 +5396,6 @@ static const char *_get_packet_type_str(uint16 type) } #endif /* DHD_RX_DUMP */ - - #ifdef DHD_MCAST_REGEN /* * Description: This function is called to do the reverse translation @@ -5197,6 +5433,26 @@ dhd_mcast_reverse_translation(struct ether_header *eh) #endif /* MCAST_REGEN */ #ifdef SHOW_LOGTRACE +static void +dhd_netif_rx_ni(struct sk_buff * skb) +{ + /* Do not call netif_recieve_skb as this workqueue scheduler is + * not from NAPI Also as we are not in INTR context, do not call + * netif_rx, instead call netif_rx_ni (for kerenl >= 2.6) which + * does netif_rx, disables irq, raise NET_IF_RX softirq and + * enables interrupts back + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + netif_rx_ni(skb); +#else + ulong flags; + netif_rx(skb); + local_irq_save(flags); + RAISE_RX_SOFTIRQ(); + local_irq_restore(flags); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ +} + static int dhd_event_logtrace_pkt_process(dhd_pub_t *dhdp, struct sk_buff * skb) { @@ -5241,6 +5497,9 @@ exit: return ret; } +#define DHD_EVENT_LOGTRACE_BOUND 12 +#define DHD_EVENT_LOGTRACE_RESCHEDULE_DELAY_MS 1 + static void dhd_event_logtrace_process(struct work_struct * work) { @@ -5248,15 +5507,18 @@ dhd_event_logtrace_process(struct work_struct * work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif + struct delayed_work *dw = to_delayed_work(work); struct dhd_info *dhd = - container_of(work, struct dhd_info, event_log_dispatcher_work); + container_of(dw, struct dhd_info, event_log_dispatcher_work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif dhd_pub_t *dhdp; struct sk_buff *skb; + uint32 qlen; + uint32 process_len; if (!dhd) { DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); @@ -5270,65 +5532,76 @@ dhd_event_logtrace_process(struct work_struct * work) return; } - DHD_TRACE(("%s:Enter\n", __FUNCTION__)); + qlen = skb_queue_len(&dhd->evt_trace_queue); + process_len = MIN(qlen, DHD_EVENT_LOGTRACE_BOUND); - /* Run while(1) loop till all skbs are dequeued */ - while ((skb = skb_dequeue(&dhd->evt_trace_queue)) != NULL) { + /* Run while loop till bound is reached or skb queue is empty */ + while (process_len--) { + int ifid = 0; + skb = skb_dequeue(&dhd->evt_trace_queue); + if (skb == NULL) { + DHD_ERROR(("%s: skb is NULL, which is not valid case\n", + __FUNCTION__)); + break; + } + BCM_REFERENCE(ifid); #ifdef PCIE_FULL_DONGLE - int ifid; + /* Check if pkt is from INFO ring or WLC_E_TRACE */ ifid = DHD_PKTTAG_IFID((dhd_pkttag_fr_t *)PKTTAG(skb)); - if (ifid == DHD_EVENT_IF) { + if (ifid == DHD_DUMMY_INFO_IF) { + /* Process logtrace from info rings */ dhd_event_logtrace_infobuf_pkt_process(dhdp, skb, &dhd->event_data); - /* For sending skb to network layer, convert it to Native PKT - * after that assign skb->dev with Primary interface n/w device - * as for infobuf events, we are sending special DHD_EVENT_IF - */ -#ifdef NOT_YET - skb = PKTTONATIVE(dhdp->osh, skb); - skb->dev = dhd->iflist[0]->net; -#endif + } else +#endif /* PCIE_FULL_DONGLE */ + { + /* Processing WLC_E_TRACE case OR non PCIE PCIE_FULL_DONGLE case */ + dhd_event_logtrace_pkt_process(dhdp, skb); + } + + /* Send packet up if logtrace_pkt_sendup is TRUE */ + if (dhdp->logtrace_pkt_sendup) { #ifdef DHD_USE_STATIC_CTRLBUF + /* If bufs are allocated via static buf pool + * and logtrace_pkt_sendup enabled, make a copy, + * free the local one and send the copy up. + */ + void *npkt = PKTDUP(dhdp->osh, skb); + /* Clone event and send it up */ PKTFREE_STATIC(dhdp->osh, skb, FALSE); -#else - PKTFREE(dhdp->osh, skb, FALSE); + if (npkt) { + skb = npkt; + } else { + DHD_ERROR(("skb clone failed. dropping logtrace pkt.\n")); + /* Packet is already freed, go to next packet */ + continue; + } #endif /* DHD_USE_STATIC_CTRLBUF */ - continue; - } - else { - dhd_event_logtrace_pkt_process(dhdp, skb); - } -#else - dhd_event_logtrace_pkt_process(dhdp, skb); +#ifdef PCIE_FULL_DONGLE + /* For infobuf packets as if is DHD_DUMMY_INFO_IF, + * to send skb to network layer, assign skb->dev with + * Primary interface n/w device + */ + if (ifid == DHD_DUMMY_INFO_IF) { + skb = PKTTONATIVE(dhdp->osh, skb); + skb->dev = dhd->iflist[0]->net; + } #endif /* PCIE_FULL_DONGLE */ - - /* Free skb buffer here if DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT - * macro is defined the Info Ring event and WLC_E_TRACE event is freed in DHD - * else it is always sent up to network layers. - */ -#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT + /* Send pkt UP */ + dhd_netif_rx_ni(skb); + } else { + /* Don't send up. Free up the packet. */ #ifdef DHD_USE_STATIC_CTRLBUF - PKTFREE_STATIC(dhdp->osh, skb, FALSE); + PKTFREE_STATIC(dhdp->osh, skb, FALSE); #else - PKTFREE(dhdp->osh, skb, FALSE); + PKTFREE(dhdp->osh, skb, FALSE); #endif /* DHD_USE_STATIC_CTRLBUF */ -#else /* !DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */ - /* Do not call netif_recieve_skb as this workqueue scheduler is not from NAPI - * Also as we are not in INTR context, do not call netif_rx, instead call - * netif_rx_ni (for kerenl >= 2.6) which does netif_rx, disables irq, raise - * NET_IF_RX softirq and enables interrupts back - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - netif_rx_ni(skb); -#else - { - ulong flags; - netif_rx(skb); - local_irq_save(flags); - RAISE_RX_SOFTIRQ(); - local_irq_restore(flags); } -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ -#endif /* DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */ + } + + /* Reschedule the workqueue if more packets to be processed */ + if (qlen >= DHD_EVENT_LOGTRACE_BOUND) { + schedule_delayed_work(&dhd->event_log_dispatcher_work, + msecs_to_jiffies(DHD_EVENT_LOGTRACE_RESCHEDULE_DELAY_MS)); } } @@ -5343,7 +5616,7 @@ dhd_event_logtrace_enqueue(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #endif /* PCIE_FULL_DONGLE */ skb_queue_tail(&dhd->evt_trace_queue, pktbuf); - schedule_work(&dhd->event_log_dispatcher_work); + schedule_delayed_work(&dhd->event_log_dispatcher_work, 0); } void @@ -5387,7 +5660,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) uint8 interface_role; if_flow_lkup_t *if_flow_lkup; unsigned long flags; -#endif +#endif // endif #ifdef DHD_WAKE_STATUS int pkt_wake = 0; wake_counts_t *wcp = NULL; @@ -5402,10 +5675,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTSETNEXT(dhdp->osh, pktbuf, NULL); /* info ring "debug" data, which is not a 802.3 frame, is sent/hacked with a - * special ifidx of DHD_EVENT_IF. This is just internal to dhd to get the data from - * dhd_msgbuf.c:dhd_prot_infobuf_cmplt_process() to here (dhd_rx_frame). + * special ifidx of DHD_DUMMY_INFO_IF. This is just internal to dhd to get the data + * from dhd_msgbuf.c:dhd_prot_infobuf_cmplt_process() to here (dhd_rx_frame). */ - if (ifidx == DHD_EVENT_IF) { + if (ifidx == DHD_DUMMY_INFO_IF) { /* Event msg printing is called from dhd_rx_frame which is in Tasklet * context in case of PCIe FD, in case of other bus this will be from * DPC context. If we get bunch of events from Dongle then printing all @@ -5414,12 +5687,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) * events with type WLC_E_TRACE. * We'll print this console logs from the WorkQueue context by enqueing SKB * here and Dequeuing will be done in WorkQueue and will be freed only if - * DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT is defined + * logtrace_pkt_sendup is TRUE */ #ifdef SHOW_LOGTRACE dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf); #else /* !SHOW_LOGTRACE */ - /* If SHOW_LOGTRACE not defined and ifidx is DHD_EVENT_IF, + /* If SHOW_LOGTRACE not defined and ifidx is DHD_DUMMY_INFO_IF, * free the PKT here itself */ #ifdef DHD_USE_STATIC_CTRLBUF @@ -5434,7 +5707,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) pkt_wake = dhd_bus_get_bus_wake(dhdp); wcp = dhd_bus_get_wakecount(dhdp); if (wcp == NULL) { - /* If wakeinfo count buffer is null do not update wake count values */ + /* If wakeinfo count buffer is null do not update wake count values */ pkt_wake = 0; } #endif /* DHD_WAKE_STATUS */ @@ -5472,7 +5745,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTCFREE(dhdp->osh, pktbuf, FALSE); continue; } -#endif +#endif // endif #ifdef DHD_L2_FILTER /* If block_ping is enabled drop the ping packet */ if (ifp->block_ping) { @@ -5498,6 +5771,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) continue; } } + if (ifp->block_tdls) { + if (bcm_l2_filter_block_tdls(dhdp->osh, pktbuf) == BCME_OK) { + PKTCFREE(dhdp->osh, pktbuf, FALSE); + continue; + } + } #endif /* DHD_L2_FILTER */ #ifdef DHD_MCAST_REGEN @@ -5529,10 +5808,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } #endif /* MCAST_REGEN */ - #ifdef DHDTCPACK_SUPPRESS dhd_tcpdata_info_get(dhdp, pktbuf); -#endif +#endif // endif skb = PKTTONATIVE(dhdp->osh, pktbuf); ASSERT(ifp); @@ -5549,9 +5827,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_WET */ #ifdef DHD_PSTA - if (PSR_ENABLED(dhdp) && (dhd_psta_proc(dhdp, ifidx, &pktbuf, FALSE) < 0)) { - DHD_ERROR(("%s:%s: psta recv proc failed\n", __FUNCTION__, - dhd_ifname(dhdp, ifidx))); + if (PSR_ENABLED(dhdp) && + (dhd_psta_proc(dhdp, ifidx, &pktbuf, FALSE) < 0)) { + DHD_ERROR(("%s:%s: psta recv proc failed\n", __FUNCTION__, + dhd_ifname(dhdp, ifidx))); } #endif /* DHD_PSTA */ @@ -5565,9 +5844,11 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) continue; } } else { - void *npktbuf = PKTDUP(dhdp->osh, pktbuf); - if (npktbuf) + void *npktbuf = NULL; + if ((ntoh16(eh->ether_type) != ETHER_TYPE_IAPP_L2_UPDATE) && + (npktbuf = PKTDUP(dhdp->osh, pktbuf)) != NULL) { dhd_sendpkt(dhdp, ifidx, npktbuf); + } } } #endif /* PCIE_FULL_DONGLE */ @@ -5634,6 +5915,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_RX_FULL_DUMP */ } #endif /* DHD_RX_DUMP */ + #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKEPKT_DUMP) if (pkt_wake) { prhex("[wakepkt_dump]", (char*)dump_data, MIN(len, 32)); @@ -5650,9 +5932,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) skb->data = eth; skb->len = len; -#ifdef DBG_PKT_MON DHD_DBG_PKT_MON_RX(dhdp, skb); -#endif /* DBG_PKT_MON */ #ifdef DHD_PKT_LOGGING DHD_PKTLOG_RX(dhdp, skb); #endif /* DHD_PKT_LOGGING */ @@ -5682,7 +5962,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); #else PKTFREE(dhdp->osh, pktbuf, FALSE); -#endif +#endif // endif continue; } @@ -5697,7 +5977,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) * events with type WLC_E_TRACE. * We'll print this console logs from the WorkQueue context by enqueing SKB * here and Dequeuing will be done in WorkQueue and will be freed only if - * DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT is defined + * logtrace_pkt_sendup is true */ if (event_type == WLC_E_TRACE) { DHD_TRACE(("%s: WLC_E_TRACE\n", __FUNCTION__)); @@ -5751,18 +6031,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); #else PKTFREE(dhdp->osh, pktbuf, FALSE); -#endif +#endif // endif continue; } -#ifdef DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -#ifdef DHD_USE_STATIC_CTRLBUF - PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); -#else - PKTFREE(dhdp->osh, pktbuf, FALSE); -#endif /* DHD_USE_STATIC_CTRLBUF */ - continue; -#else /* * For the event packets, there is a possibility * of ifidx getting modifed.Thus update the ifp @@ -5782,10 +6054,35 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); #else PKTFREE(dhdp->osh, pktbuf, FALSE); -#endif +#endif // endif + continue; + } + + if (dhdp->wl_event_enabled) { +#ifdef DHD_USE_STATIC_CTRLBUF + /* If event bufs are allocated via static buf pool + * and wl events are enabled, make a copy, free the + * local one and send the copy up. + */ + void *npkt = PKTDUP(dhdp->osh, skb); + /* Clone event and send it up */ + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); + if (npkt) { + skb = npkt; + } else { + DHD_ERROR(("skb clone failed. dropping event.\n")); + continue; + } +#endif /* DHD_USE_STATIC_CTRLBUF */ + } else { + /* If event enabled not explictly set, drop events */ +#ifdef DHD_USE_STATIC_CTRLBUF + PKTFREE_STATIC(dhdp->osh, pktbuf, FALSE); +#else + PKTFREE(dhdp->osh, pktbuf, FALSE); +#endif /* DHD_USE_STATIC_CTRLBUF */ continue; } -#endif /* DHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT */ } else { tout_rx = DHD_PACKET_TIMEOUT_MS; @@ -5845,8 +6142,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* DHD_WAKE_STATUS */ } - if (ifp->net) - ifp->net->last_rx = jiffies; +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) + ifp->net->last_rx = jiffies; +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 11, 0) */ if (ntoh16(skb->protocol) != ETHER_TYPE_BRCM) { dhdp->dstats.rx_bytes += skb->len; @@ -5883,6 +6181,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, __FUNCTION__, __LINE__); +#if defined(ARGOS_RPS_CPU_CTL) && defined(ARGOS_CPU_SCHEDULER) + argos_register_notifier_deinit(); +#endif /* ARGOS_RPS_CPU_CTL && ARGOS_CPU_SCHEDULER */ +#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); +#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ #if defined(DHD_LB_RXP) DHD_PERIM_UNLOCK_ALL((dhd->fwder_unit % FWDER_MAX_UNIT)); netif_receive_skb(skb); @@ -5929,11 +6233,10 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL); - eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); type = ntoh16(eh->ether_type); - if ((type == ETHER_TYPE_802_1X) && (dhd_get_pend_8021x_cnt(dhd) > 0)) { + if (type == ETHER_TYPE_802_1X) { atomic_dec(&dhd->pend_8021x_cnt); } @@ -5951,7 +6254,7 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) } } } -#endif +#endif // endif } static struct net_device_stats * @@ -6029,11 +6332,6 @@ dhd_watchdog_thread(void *data) DHD_TIMER(("%s:\n", __FUNCTION__)); dhd_bus_watchdog(&dhd->pub); -#ifdef DHD_TIMESYNC - /* Call the timesync module watchdog */ - dhd_timesync_watchdog(&dhd->pub); -#endif /* DHD_TIMESYNC */ - DHD_GENERAL_LOCK(&dhd->pub, flags); /* Count the tick for reference */ dhd->pub.tickcnt++; @@ -6082,11 +6380,6 @@ static void dhd_watchdog(ulong data) /* Call the bus module watchdog */ dhd_bus_watchdog(&dhd->pub); -#ifdef DHD_TIMESYNC - /* Call the timesync module watchdog */ - dhd_timesync_watchdog(&dhd->pub); -#endif /* DHD_TIMESYNC */ - DHD_GENERAL_LOCK(&dhd->pub, flags); /* Count the tick for reference */ dhd->pub.tickcnt++; @@ -6179,7 +6472,6 @@ void dhd_runtime_pm_enable(dhd_pub_t *dhdp) #endif /* DHD_PCIE_RUNTIMEPM */ - #ifdef ENABLE_ADAPTIVE_SCHED static void dhd_sched_policy(int prio) @@ -6217,11 +6509,10 @@ exit: static int dhd_dpc_thread(void *data) { -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) int ret = 0; unsigned long flags; -#endif /* ARGOS_CPU_SCHEDULER && CONFIG_SCHED_HMP && !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ tsk_ctl_t *tsk = (tsk_ctl_t *)data; dhd_info_t *dhd = (dhd_info_t *)tsk->parent; @@ -6235,8 +6526,7 @@ dhd_dpc_thread(void *data) setScheduler(current, SCHED_FIFO, ¶m); } -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) if (!zalloc_cpumask_var(&dhd->pub.default_cpu_mask, GFP_KERNEL)) { DHD_ERROR(("dpc_thread, zalloc_cpumask_var error\n")); dhd->pub.affinity_isdpc = FALSE; @@ -6282,11 +6572,11 @@ dhd_dpc_thread(void *data) #else /* ARGOS_CPU_SCHEDULER */ #ifdef CUSTOM_DPC_CPUCORE set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE)); -#endif +#endif // endif #ifdef CUSTOM_SET_CPUCORE dhd->pub.current_dpc = current; #endif /* CUSTOM_SET_CPUCORE */ -#endif /* ARGOS_CPU_SCHEDULER && CONFIG_SCHED_HMP && !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ /* Run until signal received */ while (1) { if (!binary_sema_down(tsk)) { @@ -6344,15 +6634,14 @@ dhd_rxf_thread(void *data) { tsk_ctl_t *tsk = (tsk_ctl_t *)data; dhd_info_t *dhd = (dhd_info_t *)tsk->parent; -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) int ret = 0; unsigned long flags; -#endif /* ARGOS_CPU_SCHEDULER && CONFIG_SCHED_HMP !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ #if defined(WAIT_DEQUEUE) #define RXF_WATCHDOG_TIME 250 /* BARK_TIME(1000) / */ ulong watchdogTime = OSL_SYSUPTIME(); /* msec */ -#endif +#endif // endif dhd_pub_t *pub = &dhd->pub; /* This thread doesn't need any user-level access, @@ -6365,8 +6654,7 @@ dhd_rxf_thread(void *data) setScheduler(current, SCHED_FIFO, ¶m); } -#if defined(ARGOS_CPU_SCHEDULER) && defined(CONFIG_SCHED_HMP) && \ - !defined(DHD_LB_IRQSET) +#if defined(ARGOS_CPU_SCHEDULER) && !defined(DHD_LB_IRQSET) if (!zalloc_cpumask_var(&dhd->pub.rxf_affinity_cpu_mask, GFP_KERNEL)) { DHD_ERROR(("rxthread zalloc_cpumask_var error\n")); dhd->pub.affinity_isrxf = FALSE; @@ -6390,14 +6678,14 @@ dhd_rxf_thread(void *data) #ifdef CUSTOM_SET_CPUCORE dhd->pub.current_rxf = current; #endif /* CUSTOM_SET_CPUCORE */ -#endif /* ARGOS_CPU_SCHEDULER && CONFIG_SCHED_HMP && !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && !DHD_LB_IRQSET */ /* 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 +#endif // endif #ifdef ENABLE_ADAPTIVE_SCHED dhd_sched_policy(dhd_rxf_prio); #endif /* ENABLE_ADAPTIVE_SCHED */ @@ -6425,7 +6713,7 @@ dhd_rxf_thread(void *data) RAISE_RX_SOFTIRQ(); local_irq_restore(flags); -#endif +#endif // endif skb = skbnext; } #if defined(WAIT_DEQUEUE) @@ -6433,7 +6721,7 @@ dhd_rxf_thread(void *data) OSL_SLEEP(1); watchdogTime = OSL_SYSUPTIME(); } -#endif +#endif // endif DHD_OS_WAKE_UNLOCK(pub); } else { @@ -6654,22 +6942,24 @@ dhd_toe_set(dhd_info_t *dhd, int ifidx, uint32 toe_ol) void dhd_set_scb_probe(dhd_pub_t *dhd) { wl_scb_probe_t scb_probe; + char iovbuf[WL_EVENTING_MASK_LEN + sizeof(wl_scb_probe_t)]; int ret; if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { return; } - ret = dhd_iovar(dhd, 0, "scb_probe", NULL, 0, - (char *)&scb_probe, sizeof(scb_probe), FALSE); + ret = dhd_iovar(dhd, 0, "scb_probe", NULL, 0, iovbuf, sizeof(iovbuf), FALSE); if (ret < 0) { DHD_ERROR(("%s: GET max_scb_probe failed\n", __FUNCTION__)); } + memcpy(&scb_probe, iovbuf, sizeof(wl_scb_probe_t)); + scb_probe.scb_max_probe = NUM_SCB_MAX_PROBE; - ret = dhd_iovar(dhd, 0, "scb_probe", (char *)&scb_probe, sizeof(scb_probe), - NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "scb_probe", (char *)&scb_probe, sizeof(wl_scb_probe_t), NULL, 0, + TRUE); if (ret < 0) { DHD_ERROR(("%s: max_scb_probe setting failed\n", __FUNCTION__)); return; @@ -6692,7 +6982,6 @@ struct ethtool_ops dhd_ethtool_ops = { }; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ - #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) static int dhd_ethtool(dhd_info_t *dhd, void *uaddr) @@ -6704,7 +6993,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) struct ethtool_value edata; uint32 toe_cmpnt, csum_dir; int ret; -#endif +#endif // endif DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -6820,7 +7109,7 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) DHD_ERROR(("%s : skipped due to negative pid - unloading?\n", __FUNCTION__)); return FALSE; } -#endif +#endif // endif if ((error == -ETIMEDOUT) || (error == -EREMOTEIO) || ((dhdp->busstate == DHD_BUS_DOWN) && (!dhdp->dongle_reset))) { @@ -6860,101 +7149,69 @@ void dhd_rx_mon_pkt(dhd_pub_t *dhdp, host_rxbuf_cmpl_t* msg, void *pkt, int ifidx) { dhd_info_t *dhd = (dhd_info_t *)dhdp->info; -#ifdef HOST_RADIOTAP_CONV - uint16 len = 0, offset = 0; - monitor_pkt_info_t pkt_info; - memcpy(&pkt_info.marker, &msg->marker, sizeof(msg->marker)); - memcpy(&pkt_info.ts, &msg->ts, sizeof(monitor_pkt_ts_t)); - - if (!dhd->monitor_skb) { - if ((dhd->monitor_skb = dev_alloc_skb(MAX_MON_PKT_SIZE)) == NULL) - return; - } - - len = bcmwifi_monitor(dhd->monitor_info, &pkt_info, PKTDATA(dhdp->osh, pkt), - PKTLEN(dhdp->osh, pkt), PKTDATA(dhdp->osh, dhd->monitor_skb), &offset); - - if (dhd->monitor_type && dhd->monitor_dev) - dhd->monitor_skb->dev = dhd->monitor_dev; - else { - PKTFREE(dhdp->osh, pkt, FALSE); - dev_kfree_skb(dhd->monitor_skb); - return; - } - - PKTFREE(dhdp->osh, pkt, FALSE); - - if (!len) { - return; - } - - skb_put(dhd->monitor_skb, len); - skb_pull(dhd->monitor_skb, offset); - - dhd->monitor_skb->protocol = eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); -#else - uint8 amsdu_flag = (msg->flags & BCMPCIE_PKT_FLAGS_MONITOR_MASK) >> - BCMPCIE_PKT_FLAGS_MONITOR_SHIFT; - switch (amsdu_flag) { - case BCMPCIE_PKT_FLAGS_MONITOR_NO_AMSDU: - default: - if (!dhd->monitor_skb) { - if ((dhd->monitor_skb = PKTTONATIVE(dhdp->osh, pkt)) == NULL) + { + uint8 amsdu_flag = (msg->flags & BCMPCIE_PKT_FLAGS_MONITOR_MASK) >> + BCMPCIE_PKT_FLAGS_MONITOR_SHIFT; + switch (amsdu_flag) { + case BCMPCIE_PKT_FLAGS_MONITOR_NO_AMSDU: + default: + if (!dhd->monitor_skb) { + if ((dhd->monitor_skb = PKTTONATIVE(dhdp->osh, pkt)) + == NULL) + return; + } + if (dhd->monitor_type && dhd->monitor_dev) + dhd->monitor_skb->dev = dhd->monitor_dev; + else { + PKTFREE(dhdp->osh, pkt, FALSE); + dhd->monitor_skb = NULL; return; - } - - if (dhd->monitor_type && dhd->monitor_dev) - dhd->monitor_skb->dev = dhd->monitor_dev; - else { - PKTFREE(dhdp->osh, pkt, FALSE); - dhd->monitor_skb = NULL; - return; - } + } + dhd->monitor_skb->protocol = + eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); + dhd->monitor_len = 0; + break; - dhd->monitor_skb->protocol = - eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); - dhd->monitor_len = 0; - break; - case BCMPCIE_PKT_FLAGS_MONITOR_FIRST_PKT: - if (!dhd->monitor_skb) { - if ((dhd->monitor_skb = dev_alloc_skb(MAX_MON_PKT_SIZE)) == NULL) + case BCMPCIE_PKT_FLAGS_MONITOR_FIRST_PKT: + if (!dhd->monitor_skb) { + if ((dhd->monitor_skb = dev_alloc_skb(MAX_MON_PKT_SIZE)) + == NULL) + return; + dhd->monitor_len = 0; + } + if (dhd->monitor_type && dhd->monitor_dev) + dhd->monitor_skb->dev = dhd->monitor_dev; + else { + PKTFREE(dhdp->osh, pkt, FALSE); + dev_kfree_skb(dhd->monitor_skb); return; - dhd->monitor_len = 0; - } - if (dhd->monitor_type && dhd->monitor_dev) - dhd->monitor_skb->dev = dhd->monitor_dev; - else { + } + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb), + PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); + dhd->monitor_len = PKTLEN(dhdp->osh, pkt); PKTFREE(dhdp->osh, pkt, FALSE); - dev_kfree_skb(dhd->monitor_skb); return; - } - memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb), - PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); - dhd->monitor_len = PKTLEN(dhdp->osh, pkt); - PKTFREE(dhdp->osh, pkt, FALSE); - return; - case BCMPCIE_PKT_FLAGS_MONITOR_INTER_PKT: - memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, + case BCMPCIE_PKT_FLAGS_MONITOR_INTER_PKT: + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); - dhd->monitor_len += PKTLEN(dhdp->osh, pkt); + dhd->monitor_len += PKTLEN(dhdp->osh, pkt); + PKTFREE(dhdp->osh, pkt, FALSE); + return; - PKTFREE(dhdp->osh, pkt, FALSE); - return; - case BCMPCIE_PKT_FLAGS_MONITOR_LAST_PKT: - memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, + case BCMPCIE_PKT_FLAGS_MONITOR_LAST_PKT: + memcpy(PKTDATA(dhdp->osh, dhd->monitor_skb) + dhd->monitor_len, PKTDATA(dhdp->osh, pkt), PKTLEN(dhdp->osh, pkt)); - dhd->monitor_len += PKTLEN(dhdp->osh, pkt); - - PKTFREE(dhdp->osh, pkt, FALSE); - skb_put(dhd->monitor_skb, dhd->monitor_len); - dhd->monitor_skb->protocol = - eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); - dhd->monitor_len = 0; - break; + dhd->monitor_len += PKTLEN(dhdp->osh, pkt); + PKTFREE(dhdp->osh, pkt, FALSE); + skb_put(dhd->monitor_skb, dhd->monitor_len); + dhd->monitor_skb->protocol = + eth_type_trans(dhd->monitor_skb, dhd->monitor_skb->dev); + dhd->monitor_len = 0; + break; + } } -#endif /* HOST_RADIOTAP_CONV */ if (in_interrupt()) { bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, __FUNCTION__, __LINE__); @@ -7004,38 +7261,266 @@ dhd_monitor_start(struct sk_buff *skb, struct net_device *dev) return 0; } -static int -dhd_monitor_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - return 0; -} +#if defined(BT_OVER_SDIO) -static struct net_device_stats* -dhd_monitor_get_stats(struct net_device *dev) +void +dhdsdio_bus_usr_cnt_inc(dhd_pub_t *dhdp) { - return &DHD_MON_DEV_STATS(dev); + dhdp->info->bus_user_count++; } -static const struct net_device_ops netdev_monitor_ops = +void +dhdsdio_bus_usr_cnt_dec(dhd_pub_t *dhdp) { - .ndo_start_xmit = dhd_monitor_start, - .ndo_get_stats = dhd_monitor_get_stats, - .ndo_do_ioctl = dhd_monitor_ioctl -}; + dhdp->info->bus_user_count--; +} -static void -dhd_add_monitor_if(void *handle, void *event_info, u8 event) +/* Return values: + * Success: Returns 0 + * Failure: Returns -1 or errono code + */ +int +dhd_bus_get(wlan_bt_handle_t handle, bus_owner_t owner) { - dhd_info_t *dhd = handle; - struct net_device *dev; - char *devname; + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + int ret = 0; - if (event != DHD_WQ_WORK_IF_ADD) { - DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); - return; + mutex_lock(&dhd->bus_user_lock); + ++dhd->bus_user_count; + if (dhd->bus_user_count < 0) { + DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); + ret = -1; + goto exit; } - if (!dhd) { + if (dhd->bus_user_count == 1) { + + dhd->pub.hang_was_sent = 0; + + /* First user, turn on WL_REG, start the bus */ + DHD_ERROR(("%s(): First user Turn On WL_REG & start the bus", __FUNCTION__)); + + if (!wifi_platform_set_power(dhd->adapter, TRUE, WIFI_TURNON_DELAY)) { + /* Enable F1 */ + ret = dhd_bus_resume(dhdp, 0); + if (ret) { + DHD_ERROR(("%s(): Failed to enable F1, err=%d\n", + __FUNCTION__, ret)); + goto exit; + } + } + + dhd_update_fw_nv_path(dhd); + /* update firmware and nvram path to sdio bus */ + dhd_bus_update_fw_nv_path(dhd->pub.bus, + dhd->fw_path, dhd->nv_path); + /* download the firmware, Enable F2 */ + /* TODO: Should be done only in case of FW switch */ + ret = dhd_bus_devreset(dhdp, FALSE); + dhd_bus_resume(dhdp, 1); + if (!ret) { + if (dhd_sync_with_dongle(&dhd->pub) < 0) { + DHD_ERROR(("%s(): Sync with dongle failed!!\n", __FUNCTION__)); + ret = -EFAULT; + } + } else { + DHD_ERROR(("%s(): Failed to download, err=%d\n", __FUNCTION__, ret)); + } + } else { + DHD_ERROR(("%s(): BUS is already acquired, just increase the count %d \r\n", + __FUNCTION__, dhd->bus_user_count)); + } +exit: + mutex_unlock(&dhd->bus_user_lock); + return ret; +} +EXPORT_SYMBOL(dhd_bus_get); + +/* Return values: + * Success: Returns 0 + * Failure: Returns -1 or errono code + */ +int +dhd_bus_put(wlan_bt_handle_t handle, bus_owner_t owner) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + int ret = 0; + BCM_REFERENCE(owner); + + mutex_lock(&dhd->bus_user_lock); + --dhd->bus_user_count; + if (dhd->bus_user_count < 0) { + DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); + dhd->bus_user_count = 0; + ret = -1; + goto exit; + } + + if (dhd->bus_user_count == 0) { + /* Last user, stop the bus and turn Off WL_REG */ + DHD_ERROR(("%s(): There are no owners left Trunf Off WL_REG & stop the bus \r\n", + __FUNCTION__)); +#ifdef PROP_TXSTATUS + if (dhd->pub.wlfc_enabled) { + dhd_wlfc_deinit(&dhd->pub); + } +#endif /* PROP_TXSTATUS */ +#ifdef PNO_SUPPORT + if (dhd->pub.pno_state) { + dhd_pno_deinit(&dhd->pub); + } +#endif /* PNO_SUPPORT */ +#ifdef RTT_SUPPORT + if (dhd->pub.rtt_state) { + dhd_rtt_deinit(&dhd->pub); + } +#endif /* RTT_SUPPORT */ + ret = dhd_bus_devreset(dhdp, TRUE); + if (!ret) { + dhd_bus_suspend(dhdp); + wifi_platform_set_power(dhd->adapter, FALSE, WIFI_TURNOFF_DELAY); + } + } else { + DHD_ERROR(("%s(): Other owners using bus, decrease the count %d \r\n", + __FUNCTION__, dhd->bus_user_count)); + } +exit: + mutex_unlock(&dhd->bus_user_lock); + return ret; +} +EXPORT_SYMBOL(dhd_bus_put); + +int +dhd_net_bus_get(struct net_device *dev) +{ + dhd_info_t *dhd = DHD_DEV_INFO(dev); + return dhd_bus_get(&dhd->pub, WLAN_MODULE); +} + +int +dhd_net_bus_put(struct net_device *dev) +{ + dhd_info_t *dhd = DHD_DEV_INFO(dev); + return dhd_bus_put(&dhd->pub, WLAN_MODULE); +} + +/* + * Function to enable the Bus Clock + * Returns BCME_OK on success and BCME_xxx on failure + * + * This function is not callable from non-sleepable context + */ +int dhd_bus_clk_enable(wlan_bt_handle_t handle, bus_owner_t owner) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + + int ret; + + dhd_os_sdlock(dhdp); + /* + * The second argument is TRUE, that means, we expect + * the function to "wait" until the clocks are really + * available + */ + ret = __dhdsdio_clk_enable(dhdp->bus, owner, TRUE); + dhd_os_sdunlock(dhdp); + + return ret; +} +EXPORT_SYMBOL(dhd_bus_clk_enable); + +/* + * Function to disable the Bus Clock + * Returns BCME_OK on success and BCME_xxx on failure + * + * This function is not callable from non-sleepable context + */ +int dhd_bus_clk_disable(wlan_bt_handle_t handle, bus_owner_t owner) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + + int ret; + + dhd_os_sdlock(dhdp); + /* + * The second argument is TRUE, that means, we expect + * the function to "wait" until the clocks are really + * disabled + */ + ret = __dhdsdio_clk_disable(dhdp->bus, owner, TRUE); + dhd_os_sdunlock(dhdp); + + return ret; +} +EXPORT_SYMBOL(dhd_bus_clk_disable); + +/* + * Function to reset bt_use_count counter to zero. + * + * This function is not callable from non-sleepable context + */ +void dhd_bus_reset_bt_use_count(wlan_bt_handle_t handle) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + + /* take the lock and reset bt use count */ + dhd_os_sdlock(dhdp); + dhdsdio_reset_bt_use_count(dhdp->bus); + dhd_os_sdunlock(dhdp); +} +EXPORT_SYMBOL(dhd_bus_reset_bt_use_count); + +void dhd_bus_retry_hang_recovery(wlan_bt_handle_t handle) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)handle; + dhd_info_t *dhd = (dhd_info_t*)dhdp->info; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + dhdp->hang_was_sent = 0; + + dhd_os_send_hang_message(&dhd->pub); +#else + DHD_ERROR(("%s: unsupported\n", __FUNCTION__)); +#endif // endif +} +EXPORT_SYMBOL(dhd_bus_retry_hang_recovery); + +#endif /* BT_OVER_SDIO */ + +static int +dhd_monitor_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) +{ + return 0; +} + +static struct net_device_stats* +dhd_monitor_get_stats(struct net_device *dev) +{ + return &DHD_MON_DEV_STATS(dev); +} + +static const struct net_device_ops netdev_monitor_ops = +{ + .ndo_start_xmit = dhd_monitor_start, + .ndo_get_stats = dhd_monitor_get_stats, + .ndo_do_ioctl = dhd_monitor_ioctl +}; + +static void +dhd_add_monitor_if(void *handle, void *event_info, u8 event) +{ + dhd_info_t *dhd = handle; + struct net_device *dev; + char *devname; + + if (event != DHD_WQ_WORK_IF_ADD) { + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); + return; + } + + if (!dhd) { DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); return; } @@ -7052,7 +7537,7 @@ dhd_add_monitor_if(void *handle, void *event_info, u8 event) #ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ #define ARPHRD_IEEE80211_PRISM 802 -#endif +#endif // endif #ifndef ARPHRD_IEEE80211_RADIOTAP #define ARPHRD_IEEE80211_RADIOTAP 803 /* IEEE 802.11 + radiotap header */ @@ -7066,15 +7551,13 @@ dhd_add_monitor_if(void *handle, void *event_info, u8 event) dev->get_stats = dhd_monitor_get_stats; #else dev->netdev_ops = &netdev_monitor_ops; -#endif +#endif // endif if (register_netdev(dev)) { DHD_ERROR(("%s, register_netdev failed for %s\n", __FUNCTION__, dev->name)); free_netdev(dev); } - - bcmwifi_monitor_create(&dhd->monitor_info); dhd->monitor_dev = dev; } @@ -7105,11 +7588,6 @@ dhd_del_monitor_if(void *handle, void *event_info, u8 event) dhd->monitor_dev = NULL; } - - if (dhd->monitor_info) { - bcmwifi_monitor_delete(dhd->monitor_info); - dhd->monitor_info = NULL; - } } static void @@ -7144,39 +7622,14 @@ int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_bu int buflen = 0; struct net_device *net; -#ifdef REPORT_FATAL_TIMEOUTS - if (ioc->cmd == WLC_SET_WPA_AUTH) { - int wpa_auth; - - wpa_auth = *((int *)ioc->buf); - DHD_INFO(("wpa_auth:%d\n", wpa_auth)); - if (wpa_auth != WPA_AUTH_DISABLED) { - /* If AP is with security then enable WLC_E_PSK_SUP event checking */ - dhd_set_join_error(pub, WLC_WPA_MASK); - } else { - /* If AP is with open then disable WLC_E_PSK_SUP event checking */ - dhd_clear_join_error(pub, WLC_WPA_MASK); - } - } - - if (ioc->cmd == WLC_SET_AUTH) { - int auth; - auth = *((int *)ioc->buf); - DHD_INFO(("Auth:%d\n", auth)); - - if (auth != WL_AUTH_OPEN_SYSTEM) { - /* If AP is with security then enable WLC_E_PSK_SUP event checking */ - dhd_set_join_error(pub, WLC_WPA_MASK); - } else { - /* If AP is with open then disable WLC_E_PSK_SUP event checking */ - dhd_clear_join_error(pub, WLC_WPA_MASK); - } - } -#endif /* REPORT_FATAL_TIMEOUTS */ net = dhd_idx2net(pub, ifidx); if (!net) { bcmerror = BCME_BADARG; - goto done; + /* + * The netdev pointer is bad means the DHD can't communicate + * to higher layers, so just return from here + */ + return bcmerror; } /* check for local dhd ioctl and handle it */ @@ -7235,7 +7688,6 @@ int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_bu ioc->cmd == WLC_DISASSOC) dhd_wait_pend8021x(net); - if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) && data_buf != NULL && strncmp("rpc_", data_buf, 4) == 0) { bcmerror = BCME_UNSUPPORTED; @@ -7248,16 +7700,7 @@ int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc, void *data_bu if (bcmerror == BCME_OK && ioc->cmd == WLC_SET_MONITOR) { dhd_set_monitor(pub, ifidx, *(int32*)data_buf); } -#endif - -#ifdef REPORT_FATAL_TIMEOUTS - if (ioc->cmd == WLC_SCAN && bcmerror == 0) { - dhd_start_scan_timer(pub); - } - if (ioc->cmd == WLC_SET_SSID && bcmerror == 0) { - dhd_start_join_timer(pub); - } -#endif /* REPORT_FATAL_TIMEOUTS */ +#endif /* WL_MONITOR */ done: dhd_check_hang(net, pub, bcmerror); @@ -7265,6 +7708,12 @@ done: return bcmerror; } +/** + * Called by the OS (optionally via a wrapper function). + * @param net Linux per dongle instance + * @param ifr Linux request structure + * @param cmd e.g. SIOCETHTOOL + */ static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) { @@ -7273,8 +7722,8 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) int bcmerror = 0; int ifidx; int ret; - void *local_buf = NULL; - void __user *ioc_buf_user = NULL; + void *local_buf = NULL; /**< buffer in kernel space */ + void __user *ioc_buf_user = NULL; /**< buffer in user space */ u16 buflen = 0; if (atomic_read(&exit_in_progress)) { @@ -7325,7 +7774,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ if (cmd == SIOCDEVPRIVATE+1) { - ret = wl_android_priv_cmd(net, ifr, cmd); + ret = wl_android_priv_cmd(net, ifr); dhd_check_hang(net, &dhd->pub, ret); DHD_PERIM_UNLOCK(&dhd->pub); DHD_OS_WAKE_UNLOCK(&dhd->pub); @@ -7341,7 +7790,11 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) memset(&ioc, 0, sizeof(ioc)); #ifdef CONFIG_COMPAT +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)) + if (in_compat_syscall()) { +#else if (is_compat_task()) { +#endif /* LINUX_VER >= 4.6 */ compat_wl_ioctl_t compat_ioc; if (copy_from_user(&compat_ioc, ifr->ifr_data, sizeof(compat_wl_ioctl_t))) { bcmerror = BCME_BADADDR; @@ -7451,7 +7904,7 @@ static int dhd_init_cpufreq_fix(dhd_info_t *dhd) if (dhd) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->cpufreq_fix); -#endif +#endif // endif dhd->cpufreq_fix_status = FALSE; } return 0; @@ -7461,7 +7914,7 @@ static void dhd_fix_cpu_freq(dhd_info_t *dhd) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_lock(&dhd->cpufreq_fix); -#endif +#endif // endif if (dhd && !dhd->cpufreq_fix_status) { pm_qos_add_request(&dhd->dhd_cpu_qos, PM_QOS_CPU_FREQ_MIN, 300000); #ifdef FIX_BUS_MIN_CLOCK @@ -7473,18 +7926,18 @@ static void dhd_fix_cpu_freq(dhd_info_t *dhd) } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_unlock(&dhd->cpufreq_fix); -#endif +#endif // endif } static void dhd_rollback_cpu_freq(dhd_info_t *dhd) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_lock(&dhd ->cpufreq_fix); -#endif +#endif // endif if (dhd && dhd->cpufreq_fix_status != TRUE) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_unlock(&dhd->cpufreq_fix); -#endif +#endif // endif return; } @@ -7497,222 +7950,31 @@ static void dhd_rollback_cpu_freq(dhd_info_t *dhd) dhd->cpufreq_fix_status = FALSE; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_unlock(&dhd->cpufreq_fix); -#endif +#endif // endif } #endif /* FIX_CPU_MIN_CLOCK */ -#if defined(BT_OVER_SDIO) - -void -dhdsdio_bus_usr_cnt_inc(dhd_pub_t *dhdp) +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int +dhd_ioctl_entry_wrapper(struct net_device *net, struct ifreq *ifr, int cmd) { - dhdp->info->bus_user_count++; -} + int error; + dhd_info_t *dhd = DHD_DEV_INFO(net); -void -dhdsdio_bus_usr_cnt_dec(dhd_pub_t *dhdp) -{ - dhdp->info->bus_user_count--; -} - -/* Return values: - * Success: Returns 0 - * Failure: Returns -1 or errono code - */ -int -dhd_bus_get(wlan_bt_handle_t handle, bus_owner_t owner) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)handle; - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - int ret = 0; - - mutex_lock(&dhd->bus_user_lock); - ++dhd->bus_user_count; - if (dhd->bus_user_count < 0) { - DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); - ret = -1; - goto exit; - } - - if (dhd->bus_user_count == 1) { - - dhd->pub.hang_was_sent = 0; - - /* First user, turn on WL_REG, start the bus */ - DHD_ERROR(("%s(): First user Turn On WL_REG & start the bus", __FUNCTION__)); - - if (!wifi_platform_set_power(dhd->adapter, TRUE, WIFI_TURNON_DELAY)) { - /* Enable F1 */ - ret = dhd_bus_resume(dhdp, 0); - if (ret) { - DHD_ERROR(("%s(): Failed to enable F1, err=%d\n", - __FUNCTION__, ret)); - goto exit; - } - } - - dhd_update_fw_nv_path(dhd); - /* update firmware and nvram path to sdio bus */ - dhd_bus_update_fw_nv_path(dhd->pub.bus, - dhd->fw_path, dhd->nv_path); - /* download the firmware, Enable F2 */ - /* TODO: Should be done only in case of FW switch */ - ret = dhd_bus_devreset(dhdp, FALSE); - dhd_bus_resume(dhdp, 1); - if (!ret) { - if (dhd_sync_with_dongle(&dhd->pub) < 0) { - DHD_ERROR(("%s(): Sync with dongle failed!!\n", __FUNCTION__)); - ret = -EFAULT; - } - } else { - DHD_ERROR(("%s(): Failed to download, err=%d\n", __FUNCTION__, ret)); - } - } else { - DHD_ERROR(("%s(): BUS is already acquired, just increase the count %d \r\n", - __FUNCTION__, dhd->bus_user_count)); - } -exit: - mutex_unlock(&dhd->bus_user_lock); - return ret; -} -EXPORT_SYMBOL(dhd_bus_get); - -/* Return values: - * Success: Returns 0 - * Failure: Returns -1 or errono code - */ -int -dhd_bus_put(wlan_bt_handle_t handle, bus_owner_t owner) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)handle; - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - int ret = 0; - BCM_REFERENCE(owner); - - mutex_lock(&dhd->bus_user_lock); - --dhd->bus_user_count; - if (dhd->bus_user_count < 0) { - DHD_ERROR(("%s(): bus_user_count is negative, which is invalid\n", __FUNCTION__)); - dhd->bus_user_count = 0; - ret = -1; - goto exit; - } - - if (dhd->bus_user_count == 0) { - /* Last user, stop the bus and turn Off WL_REG */ - DHD_ERROR(("%s(): There are no owners left Trunf Off WL_REG & stop the bus \r\n", - __FUNCTION__)); -#ifdef PROP_TXSTATUS - if (dhd->pub.wlfc_enabled) { - dhd_wlfc_deinit(&dhd->pub); - } -#endif /* PROP_TXSTATUS */ -#ifdef PNO_SUPPORT - if (dhd->pub.pno_state) { - dhd_pno_deinit(&dhd->pub); - } -#endif /* PNO_SUPPORT */ -#ifdef RTT_SUPPORT - if (dhd->pub.rtt_state) { - dhd_rtt_deinit(&dhd->pub); - } -#endif /* RTT_SUPPORT */ - ret = dhd_bus_devreset(dhdp, TRUE); - if (!ret) { - dhd_bus_suspend(dhdp); - wifi_platform_set_power(dhd->adapter, FALSE, WIFI_TURNOFF_DELAY); - } - } else { - DHD_ERROR(("%s(): Other owners using bus, decrease the count %d \r\n", - __FUNCTION__, dhd->bus_user_count)); - } -exit: - mutex_unlock(&dhd->bus_user_lock); - return ret; -} -EXPORT_SYMBOL(dhd_bus_put); - -int -dhd_net_bus_get(struct net_device *dev) -{ - dhd_info_t *dhd = DHD_DEV_INFO(dev); - return dhd_bus_get(&dhd->pub, WLAN_MODULE); -} - -int -dhd_net_bus_put(struct net_device *dev) -{ - dhd_info_t *dhd = DHD_DEV_INFO(dev); - return dhd_bus_put(&dhd->pub, WLAN_MODULE); -} - -/* - * Function to enable the Bus Clock - * Returns BCME_OK on success and BCME_xxx on failure - * - * This function is not callable from non-sleepable context - */ -int dhd_bus_clk_enable(wlan_bt_handle_t handle, bus_owner_t owner) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)handle; - - int ret; - - dhd_os_sdlock(dhdp); - /* - * The second argument is TRUE, that means, we expect - * the function to "wait" until the clocks are really - * available - */ - ret = __dhdsdio_clk_enable(dhdp->bus, owner, TRUE); - dhd_os_sdunlock(dhdp); - - return ret; -} -EXPORT_SYMBOL(dhd_bus_clk_enable); - -/* - * Function to disable the Bus Clock - * Returns BCME_OK on success and BCME_xxx on failure - * - * This function is not callable from non-sleepable context - */ -int dhd_bus_clk_disable(wlan_bt_handle_t handle, bus_owner_t owner) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)handle; - - int ret; + if (atomic_read(&dhd->pub.block_bus)) + return -EHOSTDOWN; - dhd_os_sdlock(dhdp); - /* - * The second argument is TRUE, that means, we expect - * the function to "wait" until the clocks are really - * disabled - */ - ret = __dhdsdio_clk_disable(dhdp->bus, owner, TRUE); - dhd_os_sdunlock(dhdp); + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) < 0) + return BCME_ERROR; - return ret; -} -EXPORT_SYMBOL(dhd_bus_clk_disable); + error = dhd_ioctl_entry(net, ifr, cmd); -/* - * Function to reset bt_use_count counter to zero. - * - * This function is not callable from non-sleepable context - */ -void dhd_bus_reset_bt_use_count(wlan_bt_handle_t handle) -{ - dhd_pub_t *dhdp = (dhd_pub_t *)handle; + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); - /* take the lock and reset bt use count */ - dhd_os_sdlock(dhdp); - dhdsdio_reset_bt_use_count(dhdp->bus); - dhd_os_sdunlock(dhdp); + return error; } -EXPORT_SYMBOL(dhd_bus_reset_bt_use_count); - -#endif /* BT_OVER_SDIO */ +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ static int dhd_stop(struct net_device *net) @@ -7772,7 +8034,6 @@ dhd_stop(struct net_device *net) wl_cfg80211_down(net); ifp = dhd->iflist[0]; - ASSERT(ifp && ifp->net); /* * For CFG80211: Clean up all the left over virtual interfaces * when the primary Interface is brought down. [ifconfig wlan0 down] @@ -7810,7 +8071,7 @@ dhd_stop(struct net_device *net) #ifdef SHOW_LOGTRACE /* Wait till event_log_dispatcher_work finishes */ - cancel_work_sync(&dhd->event_log_dispatcher_work); + cancel_delayed_work_sync(&dhd->event_log_dispatcher_work); #endif /* SHOW_LOGTRACE */ #if defined(DHD_LB_RXP) @@ -7822,12 +8083,14 @@ dhd_stop(struct net_device *net) #endif /* DHD_LB_TXP */ } +#if defined(ARGOS_RPS_CPU_CTL) && defined(ARGOS_CPU_SCHEDULER) argos_register_notifier_deinit(); +#endif /* ARGOS_RPS_CPU_CTL && ARGOS_CPU_SCHEDULER */ #ifdef DHDTCPACK_SUPPRESS dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); #endif /* DHDTCPACK_SUPPRESS */ #if defined(DHD_LB_RXP) - if (ifp->net == dhd->rx_napi_netdev) { + if (ifp && ifp->net == dhd->rx_napi_netdev) { DHD_INFO(("%s napi<%p> disabled ifp->net<%p,%s>\n", __FUNCTION__, &dhd->rx_napi_struct, net, net->name)); skb_queue_purge(&dhd->rx_napi_queue); @@ -7843,7 +8106,7 @@ dhd_stop(struct net_device *net) #ifdef PROP_TXSTATUS dhd_wlfc_cleanup(&dhd->pub, NULL, 0); -#endif +#endif // endif #ifdef SHOW_LOGTRACE if (!dhd_download_fw_on_driverload) { /* Release the skbs from queue for WLC_E_TRACE event */ @@ -7903,7 +8166,7 @@ exit: } } #endif /* SUPPORT_DEEP_SLEEP */ -#endif +#endif // endif dhd->pub.hang_was_sent = 0; /* Clear country spec for for built-in type driver */ @@ -7915,7 +8178,7 @@ exit: #ifdef BCMDBGFS dhd_dbgfs_remove(); -#endif +#endif // endif DHD_PERIM_UNLOCK(&dhd->pub); DHD_OS_WAKE_UNLOCK(&dhd->pub); @@ -7956,7 +8219,7 @@ dhd_open(struct net_device *net) dhd_info_t *dhd = DHD_DEV_INFO(net); #ifdef TOE uint32 toe_ol; -#endif +#endif // endif int ifidx; int32 ret = 0; @@ -8009,7 +8272,7 @@ dhd_open(struct net_device *net) DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__)); } mutex_lock(&_dhd_sdio_mutex_lock_); -#endif +#endif // endif #endif /* MULTIPLE_SUPPLICANT */ DHD_OS_WAKE_LOCK(&dhd->pub); @@ -8024,7 +8287,7 @@ dhd_open(struct net_device *net) #ifdef DHD_LOSSLESS_ROAMING dhd->pub.dequeue_prec_map = ALLPRIO; -#endif +#endif // endif #if !defined(WL_CFG80211) /* * Force start if ifconfig_up gets called before START command @@ -8038,7 +8301,7 @@ dhd_open(struct net_device *net) goto exit; } -#endif +#endif // endif ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); @@ -8097,13 +8360,23 @@ dhd_open(struct net_device *net) dhd_fix_cpu_freq(dhd); } #endif /* FIX_CPU_MIN_CLOCK */ -#endif +#endif // endif if (dhd->pub.busstate != DHD_BUS_DATA) { /* try to bring up bus */ DHD_PERIM_UNLOCK(&dhd->pub); + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) >= 0) { + ret = dhd_bus_start(&dhd->pub); + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); + } +#else ret = dhd_bus_start(&dhd->pub); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + DHD_PERIM_LOCK(&dhd->pub); if (ret) { DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); @@ -8113,14 +8386,13 @@ dhd_open(struct net_device *net) } - #ifdef BT_OVER_SDIO if (dhd->pub.is_bt_recovery_required) { DHD_ERROR(("%s: Send Hang Notification 2 to BT\n", __FUNCTION__)); bcmsdh_btsdio_process_dhd_hang_notification(TRUE); } dhd->pub.is_bt_recovery_required = FALSE; -#endif +#endif // endif /* dhd_sync_with_dongle has been called in dhd_bus_start or wl_android_wifi_on */ memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); @@ -8179,10 +8451,16 @@ dhd_open(struct net_device *net) #endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */ } +#if defined(ARGOS_CPU_SCHEDULER) && defined(ARGOS_RPS_CPU_CTL) argos_register_notifier_init(net); -#if defined(DHDTCPACK_SUPPRESS) - dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DEFAULT); -#endif /* DHDTCPACK_SUPPRESS */ +#endif /* ARGOS_CPU_SCHEDULER && ARGOS_RPS_CPU_CTL */ +#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) +#if defined(SET_RPS_CPUS) || defined(ARGOS_RPS_CPU_CTL) + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); +#else + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); +#endif /* ARGOS_CPU_SCHEDULER && ARGOS_RPS_CPU_CTL */ +#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ #if defined(NUM_SCB_MAX_PROBE) dhd_set_scb_probe(&dhd->pub); #endif /* NUM_SCB_MAX_PROBE */ @@ -8193,11 +8471,25 @@ dhd_open(struct net_device *net) netif_start_queue(net); dhd->pub.up = 1; + if (wl_event_enable) { + /* For wl utility to receive events */ + dhd->pub.wl_event_enabled = true; + } else { + dhd->pub.wl_event_enabled = false; + } + + if (logtrace_pkt_sendup) { + /* For any deamon to recieve logtrace */ + dhd->pub.logtrace_pkt_sendup = true; + } else { + dhd->pub.logtrace_pkt_sendup = false; + } + OLD_MOD_INC_USE_COUNT; #ifdef BCMDBGFS dhd_dbgfs_init(&dhd->pub); -#endif +#endif // endif exit: if (ret) { @@ -8210,7 +8502,7 @@ exit: #if defined(MULTIPLE_SUPPLICANT) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && defined(BCMSDIO) mutex_unlock(&_dhd_sdio_mutex_lock_); -#endif +#endif // endif #endif /* MULTIPLE_SUPPLICANT */ return ret; } @@ -8257,9 +8549,9 @@ dhd_event_ifadd(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, ui #ifdef WL_CFG80211 if (wl_cfg80211_notify_ifadd(dhd_linux_get_primary_netdev(&dhdinfo->pub), - ifevent->ifidx, name, mac, ifevent->bssidx) == BCME_OK) + ifevent->ifidx, name, mac, ifevent->bssidx, ifevent->role) == BCME_OK) return BCME_OK; -#endif +#endif // endif /* handle IF event caused by wl commands, SoftAP, WEXT and * anything else. This has to be done asynchronously otherwise @@ -8325,33 +8617,128 @@ dhd_event_ifchange(dhd_info_t *dhdinfo, wl_event_data_if_t *ifevent, char *name, return BCME_OK; } -/* unregister and free the existing net_device interface (if any) in iflist and - * allocate a new one. the slot is reused. this function does NOT register the - * new interface to linux kernel. dhd_register_if does the job - */ -struct net_device* -dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, - uint8 *mac, uint8 bssidx, bool need_rtnl_lock, const char *dngl_name) +#ifdef WL_NATOE +/* Handler to update natoe info and bind with new subscriptions if there is change in config */ +static void +dhd_natoe_ct_event_hanlder(void *handle, void *event_info, u8 event) { - dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info; - dhd_if_t *ifp; + dhd_info_t *dhd = handle; + wl_event_data_natoe_t *natoe = event_info; + dhd_nfct_info_t *nfct = dhd->pub.nfct; - ASSERT(dhdinfo && (ifidx < DHD_MAX_IFS)); - ifp = dhdinfo->iflist[ifidx]; + if (event != DHD_WQ_WORK_NATOE_EVENT) { + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); + return; + } - if (ifp != NULL) { - if (ifp->net != NULL) { - DHD_ERROR(("%s: free existing IF %s ifidx:%d \n", - __FUNCTION__, ifp->net->name, ifidx)); + if (!dhd) { + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); + return; + } + if (natoe->natoe_active && natoe->sta_ip && natoe->start_port && natoe->end_port && + (natoe->start_port < natoe->end_port)) { + /* Rebind subscriptions to start receiving notifications from groups */ + if (dhd_ct_nl_bind(nfct, nfct->subscriptions) < 0) { + dhd_ct_close(nfct); + } + dhd_ct_send_dump_req(nfct); + } else if (!natoe->natoe_active) { + /* Rebind subscriptions to stop receiving notifications from groups */ + if (dhd_ct_nl_bind(nfct, CT_NULL_SUBSCRIPTION) < 0) { + dhd_ct_close(nfct); + } + } +} - if (ifidx == 0) { - /* For primary ifidx (0), there shouldn't be - * any netdev present already. - */ - DHD_ERROR(("Primary ifidx populated already\n")); - ASSERT(0); - return NULL; - } +/* As NATOE enable/disbale event is received, we have to bind with new NL subscriptions. + * Scheduling workq to switch from tasklet context as bind call may sleep in handler + */ +int +dhd_natoe_ct_event(dhd_pub_t *dhd, char *data) +{ + wl_event_data_natoe_t *event_data = (wl_event_data_natoe_t *)data; + + if (dhd->nfct) { + wl_event_data_natoe_t *natoe = dhd->nfct->natoe_info; + uint8 prev_enable = natoe->natoe_active; + + spin_lock_bh(&dhd->nfct_lock); + memcpy(natoe, event_data, sizeof(*event_data)); + spin_unlock_bh(&dhd->nfct_lock); + + if (prev_enable != event_data->natoe_active) { + dhd_deferred_schedule_work(dhd->info->dhd_deferred_wq, + (void *)natoe, DHD_WQ_WORK_NATOE_EVENT, + dhd_natoe_ct_event_hanlder, DHD_WQ_WORK_PRIORITY_LOW); + } + return BCME_OK; + } + DHD_ERROR(("%s ERROR NFCT is not enabled \n", __FUNCTION__)); + return BCME_ERROR; +} + +/* Handler to send natoe ioctl to dongle */ +static void +dhd_natoe_ct_ioctl_handler(void *handle, void *event_info, uint8 event) +{ + dhd_info_t *dhd = handle; + dhd_ct_ioc_t *ct_ioc = event_info; + + if (event != DHD_WQ_WORK_NATOE_IOCTL) { + DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); + return; + } + + if (!dhd) { + DHD_ERROR(("%s: dhd info not available \n", __FUNCTION__)); + return; + } + + if (dhd_natoe_prep_send_exception_port_ioctl(&dhd->pub, ct_ioc) < 0) { + DHD_ERROR(("%s: Error in sending NATOE IOCTL \n", __FUNCTION__)); + } +} + +/* When Netlink message contains port collision info, the info must be sent to dongle FW + * For that we have to switch context from softirq/tasklet by scheduling workq for natoe_ct ioctl + */ +void +dhd_natoe_ct_ioctl_schedule_work(dhd_pub_t *dhd, dhd_ct_ioc_t *ioc) +{ + + dhd_deferred_schedule_work(dhd->info->dhd_deferred_wq, (void *)ioc, + DHD_WQ_WORK_NATOE_IOCTL, dhd_natoe_ct_ioctl_handler, + DHD_WQ_WORK_PRIORITY_HIGH); +} +#endif /* WL_NATOE */ + +/* unregister and free the existing net_device interface (if any) in iflist and + * allocate a new one. the slot is reused. this function does NOT register the + * new interface to linux kernel. dhd_register_if does the job + */ +struct net_device* +dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, + uint8 *mac, uint8 bssidx, bool need_rtnl_lock, const char *dngl_name) +{ + dhd_info_t *dhdinfo = (dhd_info_t *)dhdpub->info; + dhd_if_t *ifp; + + ASSERT(dhdinfo && (ifidx < DHD_MAX_IFS)); + ifp = dhdinfo->iflist[ifidx]; + + if (ifp != NULL) { + if (ifp->net != NULL) { + DHD_ERROR(("%s: free existing IF %s ifidx:%d \n", + __FUNCTION__, ifp->net->name, ifidx)); + + if (ifidx == 0) { + /* For primary ifidx (0), there shouldn't be + * any netdev present already. + */ + DHD_ERROR(("Primary ifidx populated already\n")); + ASSERT(0); + return NULL; + } dhd_dev_priv_clear(ifp->net); /* clear net_device private */ @@ -8383,7 +8770,7 @@ dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, ifp->bssidx = bssidx; #ifdef DHD_MCAST_REGEN ifp->mcast_regen_bss_enable = FALSE; -#endif +#endif // endif /* set to TRUE rx_pkt_chainable at alloc time */ ifp->rx_pkt_chainable = TRUE; @@ -8418,10 +8805,11 @@ dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, dhdinfo->iflist[ifidx] = ifp; /* initialize the dongle provided if name */ - if (dngl_name) + if (dngl_name) { strncpy(ifp->dngl_name, dngl_name, IFNAMSIZ); - else if (name) + } else if (name) { strncpy(ifp->dngl_name, name, IFNAMSIZ); + } #ifdef PCIE_FULL_DONGLE /* Initialize STA info list */ @@ -8434,7 +8822,6 @@ dhd_allocate_if(dhd_pub_t *dhdpub, int ifidx, const char *name, ifp->parp_allnode = TRUE; #endif /* DHD_L2_FILTER */ - DHD_CUMM_CTR_INIT(&ifp->cumm_ctr); return ifp->net; @@ -8488,14 +8875,14 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) } else { netif_tx_disable(ifp->net); - - #if defined(SET_RPS_CPUS) custom_rps_map_clear(ifp->net->_rx); #endif /* SET_RPS_CPUS */ -#if defined(ARGOS_CPU_SCHEDULER) && defined(DHDTCPACK_SUPPRESS) +#if (defined(SET_RPS_CPUS) || defined(ARGOS_RPS_CPU_CTL)) +#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) dhd_tcpack_suppress_set(dhdpub, TCPACK_SUP_OFF); -#endif /* ARGOS_CPU_SCHEDULER && DHDTCPACK_SUPPRESS */ +#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ +#endif /* SET_RPS_CPUS || ARGOS_RPS_CPU_CTL */ if (need_rtnl_lock) unregister_netdev(ifp->net); else @@ -8510,14 +8897,14 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) ifp->phnd_arp_table = NULL; #endif /* DHD_L2_FILTER */ - dhd_if_del_sta_list(ifp); #ifdef PCIE_FULL_DONGLE - /* Delete flowrings of WDS interface */ - if (if_flow_lkup[ifidx].role == WLC_E_IF_ROLE_WDS) { + /* Delete flowrings of virtual interface */ + if ((ifidx != 0) && (if_flow_lkup[ifidx].role != WLC_E_IF_ROLE_AP)) { dhd_flow_rings_delete(dhdpub, ifidx); } #endif /* PCIE_FULL_DONGLE */ + DHD_CUMM_CTR_INIT(&ifp->cumm_ctr); MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp)); @@ -8527,39 +8914,59 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock) return BCME_OK; } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) static struct net_device_ops dhd_ops_pri = { .ndo_open = dhd_open, .ndo_stop = dhd_stop, .ndo_get_stats = dhd_get_stats, +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + .ndo_do_ioctl = dhd_ioctl_entry_wrapper, + .ndo_start_xmit = dhd_start_xmit_wrapper, +#else .ndo_do_ioctl = dhd_ioctl_entry, .ndo_start_xmit = dhd_start_xmit, +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ .ndo_set_mac_address = dhd_set_mac_address, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) .ndo_set_rx_mode = dhd_set_multicast_list, #else .ndo_set_multicast_list = dhd_set_multicast_list, -#endif +#endif // endif }; static struct net_device_ops dhd_ops_virt = { .ndo_get_stats = dhd_get_stats, +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + .ndo_do_ioctl = dhd_ioctl_entry_wrapper, + .ndo_start_xmit = dhd_start_xmit_wrapper, +#else .ndo_do_ioctl = dhd_ioctl_entry, .ndo_start_xmit = dhd_start_xmit, +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ .ndo_set_mac_address = dhd_set_mac_address, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) .ndo_set_rx_mode = dhd_set_multicast_list, #else .ndo_set_multicast_list = dhd_set_multicast_list, -#endif +#endif // endif }; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ -#ifdef DEBUGGER -extern void debugger_init(void *bus_handle); -#endif +int +dhd_os_write_file_posn(void *fp, unsigned long *posn, void *buf, + unsigned long buflen) +{ + loff_t wr_posn = *posn; + + if (!fp || !buf || buflen == 0) + return -1; + + if (vfs_write((struct file *)fp, buf, buflen, &wr_posn) < 0) + return -1; + *posn = wr_posn; + return 0; +} #ifdef SHOW_LOGTRACE int @@ -8602,12 +9009,12 @@ dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp) filep = filp_open(logstrs_path, O_RDONLY, 0); if (IS_ERR(filep)) { - DHD_INFO(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path)); + DHD_ERROR_NO_HW4(("%s: Failed to open the file %s \n", __FUNCTION__, logstrs_path)); goto fail; } error = vfs_stat(logstrs_path, &stat); if (error) { - DHD_INFO(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path)); + DHD_ERROR_NO_HW4(("%s: Failed to stat file %s \n", __FUNCTION__, logstrs_path)); goto fail; } logstrs_size = (int) stat.size; @@ -8622,8 +9029,9 @@ dhd_init_logstrs_array(osl_t *osh, dhd_event_log_t *temp) DHD_ERROR(("%s: Failed to allocate memory \n", __FUNCTION__)); goto fail; } + if (vfs_read(filep, raw_fmts, logstrs_size, &filep->f_pos) != logstrs_size) { - DHD_INFO(("%s: Failed to read file %s", __FUNCTION__, logstrs_path)); + DHD_ERROR_NO_HW4(("%s: Failed to read file %s\n", __FUNCTION__, logstrs_path)); goto fail; } @@ -8667,7 +9075,7 @@ dhd_read_map(osl_t *osh, char *fname, uint32 *ramstart, uint32 *rodata_start, filep = filp_open(fname, O_RDONLY, 0); if (IS_ERR(filep)) { - DHD_INFO(("%s: Failed to open %s \n", __FUNCTION__, fname)); + DHD_ERROR_NO_HW4(("%s: Failed to open %s \n", __FUNCTION__, fname)); goto fail; } @@ -8691,7 +9099,6 @@ dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, ch mm_segment_t fs; char *raw_fmts = NULL; uint32 logstrs_size = 0; - int error = 0; uint32 ramstart = 0; uint32 rodata_start = 0; @@ -8721,8 +9128,11 @@ dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, ch goto fail; } - /* Full file size is huge. Just read required part */ - logstrs_size = rodata_end - rodata_start; + if (TRUE) { + /* Full file size is huge. Just read required part */ + logstrs_size = rodata_end - rodata_start; + logfilebase = rodata_start - ramstart; + } if (logstrs_size == 0) { DHD_ERROR(("%s: return as logstrs_size is 0\n", __FUNCTION__)); @@ -8735,12 +9145,12 @@ dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, ch goto fail; } - logfilebase = rodata_start - ramstart; - - error = generic_file_llseek(filep, logfilebase, SEEK_SET); - if (error < 0) { - DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error)); - goto fail; + if (TRUE) { + error = generic_file_llseek(filep, logfilebase, SEEK_SET); + if (error < 0) { + DHD_ERROR(("%s: %s llseek failed %d \n", __FUNCTION__, str_file, error)); + goto fail; + } } error = vfs_read(filep, raw_fmts, logstrs_size, (&filep->f_pos)); @@ -8752,13 +9162,11 @@ dhd_init_static_strs_array(osl_t *osh, dhd_event_log_t *temp, char *str_file, ch if (strstr(str_file, ram_file_str) != NULL) { temp->raw_sstr = raw_fmts; temp->raw_sstr_size = logstrs_size; - temp->ramstart = ramstart; temp->rodata_start = rodata_start; temp->rodata_end = rodata_end; } else if (strstr(str_file, rom_file_str) != NULL) { temp->rom_raw_sstr = raw_fmts; temp->rom_raw_sstr_size = logstrs_size; - temp->rom_ramstart = ramstart; temp->rom_rodata_start = rodata_start; temp->rom_rodata_end = rodata_end; } @@ -8787,11 +9195,42 @@ fail1: } return error; +} /* dhd_init_static_strs_array */ + +static int +dhd_trace_open_proc(struct inode *inode, struct file *file) +{ + return single_open(file, 0, NULL); } -#endif /* SHOW_LOGTRACE */ +ssize_t +dhd_trace_read_proc(struct file *file, char __user *buffer, size_t tt, loff_t *loff) +{ + trace_buf_info_t *trace_buf_info; + int ret = BCME_ERROR; + ASSERT(g_dhd_pub); + mutex_lock(&g_dhd_pub->dhd_trace_lock); + trace_buf_info = (trace_buf_info_t *)MALLOC(g_dhd_pub->osh, + sizeof(trace_buf_info_t)); + if (trace_buf_info != NULL) { + dhd_get_read_buf_ptr(g_dhd_pub, trace_buf_info); + if (copy_to_user(buffer, (void*)trace_buf_info->buf, MIN(trace_buf_info->size, tt))) + return -EFAULT; + if (trace_buf_info->availability == BUF_NOT_AVAILABLE) + ret = BUF_NOT_AVAILABLE; + else + ret = trace_buf_info->size; + MFREE(g_dhd_pub->osh, trace_buf_info, sizeof(trace_buf_info_t)); + } else + DHD_ERROR(("Memory allocation Failed\n")); + + mutex_unlock(&g_dhd_pub->dhd_trace_lock); + return ret; +} +#endif /* SHOW_LOGTRACE */ +/** Called once for each hardware (dongle) instance that this DHD manages */ dhd_pub_t * dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) { @@ -8809,13 +9248,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); -#ifdef STBLINUX - DHD_ERROR(("%s\n", driver_target)); -#endif /* STBLINUX */ /* will implement get_ids for DBUS later */ #if defined(BCMSDIO) dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num); -#endif +#endif // endif adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num); /* Allocate primary dhd_info */ @@ -8837,14 +9273,15 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dll_init(&(dhd->pub.dump_iovlist_head)); #endif /* DUMP_IOCTL_IOV_LIST */ dhd->adapter = adapter; -#ifdef DHD_DEBUG - dll_init(&(dhd->pub.mw_list_head)); -#endif /* DHD_DEBUG */ #ifdef BT_OVER_SDIO dhd->pub.is_bt_recovery_required = FALSE; mutex_init(&dhd->bus_user_lock); #endif /* BT_OVER_SDIO */ +#ifdef DHD_DEBUG + dll_init(&(dhd->pub.mw_list_head)); +#endif /* DHD_DEBUG */ + #ifdef GET_CUSTOM_MAC_ENABLE wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet); #endif /* GET_CUSTOM_MAC_ENABLE */ @@ -8870,11 +9307,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) * solution */ dhd_update_fw_nv_path(dhd); + dhd->pub.pcie_txs_metadata_enable = pcie_txs_metadata_enable; /* Link to info module */ dhd->pub.info = dhd; - /* Link to bus module */ dhd->pub.bus = bus; dhd->pub.hdrlen = bus_hdrlen; @@ -8907,12 +9344,12 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #ifdef DHD_L2_FILTER /* initialize the l2_filter_cnt */ dhd->pub.l2_filter_cnt = 0; -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) net->open = NULL; #else net->netdev_ops = NULL; -#endif +#endif // endif mutex_init(&dhd->dhd_iovar_mutex); sema_init(&dhd->proto_sem, 1); @@ -8947,9 +9384,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* Initialize other structure content */ init_waitqueue_head(&dhd->ioctl_resp_wait); init_waitqueue_head(&dhd->d3ack_wait); -#ifdef PCIE_INB_DW - init_waitqueue_head(&dhd->ds_exit_wait); -#endif /* PCIE_INB_DW */ init_waitqueue_head(&dhd->ctrl_wait); init_waitqueue_head(&dhd->dhd_bus_busy_state_wait); init_waitqueue_head(&dhd->dmaxfer_wait); @@ -8958,7 +9392,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* Initialize the spinlocks */ spin_lock_init(&dhd->sdlock); spin_lock_init(&dhd->txqlock); - spin_lock_init(&dhd->rxqlock); spin_lock_init(&dhd->dhd_lock); spin_lock_init(&dhd->rxf_lock); #ifdef WLTDLS @@ -8977,6 +9410,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) spin_lock_init(&dhd->wakelock_evt_spinlock); DHD_OS_WAKE_LOCK_INIT(dhd); dhd->wakelock_counter = 0; + /* wakelocks prevent a system from going into a low power state */ #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); #endif /* CONFIG_HAS_WAKELOCK */ @@ -8987,7 +9421,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #if defined(PKT_FILTER_SUPPORT) && defined(APF) mutex_init(&dhd->dhd_apf_mutex); #endif /* PKT_FILTER_SUPPORT && APF */ -#endif +#endif // endif dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; /* Attach and link in the protocol */ @@ -8997,15 +9431,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) } dhd_state |= DHD_ATTACH_STATE_PROT_ATTACH; -#ifdef DHD_TIMESYNC - /* attach the timesync module */ - if (dhd_timesync_attach(&dhd->pub) != 0) { - DHD_ERROR(("dhd_timesync_attach failed\n")); - goto fail; - } - dhd_state |= DHD_ATTACH_TIMESYNC_ATTACH_DONE; -#endif /* DHD_TIMESYNC */ - #ifdef WL_CFG80211 spin_lock_init(&dhd->pub.up_lock); /* Attach and link in the cfg80211 */ @@ -9016,10 +9441,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_monitor_init(&dhd->pub); dhd_state |= DHD_ATTACH_STATE_CFG80211; -#endif -#ifdef DHD_LOG_DUMP - dhd_log_dump_init(&dhd->pub); -#endif /* DHD_LOG_DUMP */ +#endif // endif + #if defined(WL_WIRELESS_EXT) /* Attach and link in the iw */ if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { @@ -9048,6 +9471,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) goto fail; } +#if defined(SHOW_LOGTRACE) && defined(DBG_RING_LOG_INIT_DEFAULT) + /* enable verbose ring to support dump_trace_buf */ + dhd_os_start_logging(&dhd->pub, FW_VERBOSE_RING_NAME, 3, 0, 0, 0); +#endif /* SHOW_LOGTRACE */ + #ifdef DBG_PKT_MON dhd->pub.dbg->pkt_mon_lock = dhd_os_spin_lock_init(dhd->pub.osh); #ifdef DBG_PKT_MON_INIT_DEFAULT @@ -9055,16 +9483,39 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #endif /* DBG_PKT_MON_INIT_DEFAULT */ #endif /* DBG_PKT_MON */ #endif /* DEBUGABILITY */ + +#ifdef DHD_LOG_DUMP + dhd_log_dump_init(&dhd->pub); +#endif /* DHD_LOG_DUMP */ + #ifdef DHD_PKT_LOGGING dhd_os_attach_pktlog(&dhd->pub); #endif /* DHD_PKT_LOGGING */ - +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT + dhd->pub.hang_info = MALLOCZ(osh, VENDOR_SEND_HANG_EXT_INFO_LEN); + if (dhd->pub.hang_info == NULL) { + DHD_ERROR(("%s: alloc hang_info failed\n", __FUNCTION__)); + } +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ if (dhd_sta_pool_init(&dhd->pub, DHD_MAX_STA) != BCME_OK) { DHD_ERROR(("%s: Initializing %u sta\n", __FUNCTION__, DHD_MAX_STA)); goto fail; } - +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + dhd->tx_wq = alloc_workqueue("bcmdhd-tx-wq", WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + if (!dhd->tx_wq) { + DHD_ERROR(("%s: alloc_workqueue(bcmdhd-tx-wq) failed\n", __FUNCTION__)); + goto fail; + } + dhd->rx_wq = alloc_workqueue("bcmdhd-rx-wq", WQ_HIGHPRI | WQ_UNBOUND | WQ_MEM_RECLAIM, 1); + if (!dhd->rx_wq) { + DHD_ERROR(("%s: alloc_workqueue(bcmdhd-rx-wq) failed\n", __FUNCTION__)); + destroy_workqueue(dhd->tx_wq); + dhd->tx_wq = NULL; + goto fail; + } +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ /* Set up the watchdog timer */ init_timer(&dhd->timer); @@ -9097,11 +9548,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) } #endif /* DHD_PCIE_RUNTIMEPM */ -#ifdef DEBUGGER - debugger_init((void *) bus); -#endif #ifdef SHOW_LOGTRACE skb_queue_head_init(&dhd->evt_trace_queue); + if (proc_create("dhd_trace", S_IRUSR, NULL, &proc_file_fops) == NULL) + DHD_ERROR(("Failed to create /proc/dhd_trace procfs interface\n")); + mutex_init(&dhd->pub.dhd_trace_lock); #endif /* SHOW_LOGTRACE */ /* Set up the bottom half handler */ @@ -9113,7 +9564,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) } } else { #if defined(ARGOS_CPU_SCHEDULER) && defined(ARGOS_DPC_TASKLET_CTL) && \ - defined(CONFIG_SCHED_HMP) && !defined(DHD_LB_IRQSET) + !defined(DHD_LB_IRQSET) if (!zalloc_cpumask_var(&dhd->pub.default_cpu_mask, GFP_KERNEL)) { DHD_ERROR(("dpc tasklet, zalloc_cpumask_var error\n")); dhd->pub.affinity_isdpc = FALSE; @@ -9145,7 +9596,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->pub.affinity_isdpc = TRUE; } } -#endif /* ARGOS_CPU_SCHEDULER && ARGOS_DPC_TASKLET_CTL && CONFIG_SCHED_HMP && !DHD_LB_IRQSET */ +#endif /* ARGOS_CPU_SCHEDULER && ARGOS_DPC_TASKLET_CTL && !DHD_LB_IRQSET */ /* use tasklet for dpc */ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); dhd->thr_dpc_ctl.thr_pid = -1; @@ -9199,15 +9650,20 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->new_freq = alloc_percpu(int); dhd->freq_trans.notifier_call = dhd_cpufreq_notifier; cpufreq_register_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER); -#endif +#endif // endif #ifdef DHDTCPACK_SUPPRESS - dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DEFAULT); +#ifdef BCMSDIO + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_DELAYTX); +#elif defined(BCMPCIE) + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_HOLD); +#else + dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); +#endif /* BCMSDIO */ #endif /* DHDTCPACK_SUPPRESS */ #if defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) #endif /* defined(BCM_DNGL_EMBEDIMAGE) || defined(BCM_REQUEST_FW) */ - #ifdef DHD_DEBUG_PAGEALLOC register_page_corrupt_cb(dhd_page_corrupt_cb, &dhd->pub); #endif /* DHD_DEBUG_PAGEALLOC */ @@ -9261,6 +9717,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #if defined(DHD_LB_RXC) tasklet_init(&dhd->rx_compl_tasklet, dhd_lb_rx_compl_handler, (ulong)(&dhd->pub)); + INIT_WORK(&dhd->rx_compl_dispatcher_work, dhd_rx_compl_dispatcher_fn); DHD_INFO(("%s load balance init rx_compl_tasklet\n", __FUNCTION__)); #endif /* DHD_LB_RXC */ @@ -9284,29 +9741,44 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_state |= DHD_ATTACH_STATE_LB_ATTACH_DONE; #endif /* DHD_LB */ -#ifdef SHOW_LOGTRACE - INIT_WORK(&dhd->event_log_dispatcher_work, dhd_event_logtrace_process); -#endif /* SHOW_LOGTRACE */ - - DHD_SSSR_MEMPOOL_INIT(&dhd->pub); - -#ifdef REPORT_FATAL_TIMEOUTS - init_dhd_timeouts(&dhd->pub); -#endif /* REPORT_FATAL_TIMEOUTS */ -#ifdef BCMPCIE +#if defined(BCMPCIE) dhd->pub.extended_trap_data = MALLOCZ(osh, BCMPCIE_EXT_TRAP_DATA_MAXLEN); if (dhd->pub.extended_trap_data == NULL) { DHD_ERROR(("%s: Failed to alloc extended_trap_data\n", __FUNCTION__)); } -#endif /* BCMPCIE */ +#endif /* BCMPCIE && ETD */ + +#ifdef SHOW_LOGTRACE + INIT_DELAYED_WORK(&dhd->event_log_dispatcher_work, dhd_event_logtrace_process); +#endif /* SHOW_LOGTRACE */ + + DHD_SSSR_MEMPOOL_INIT(&dhd->pub); (void)dhd_sysfs_init(dhd); +#ifdef WL_NATOE + /* Open Netlink socket for NF_CONNTRACK notifications */ + dhd->pub.nfct = dhd_ct_open(&dhd->pub, NFNL_SUBSYS_CTNETLINK | NFNL_SUBSYS_CTNETLINK_EXP, + CT_ALL); +#endif /* WL_NATOE */ + dhd_state |= DHD_ATTACH_STATE_DONE; dhd->dhd_state = dhd_state; dhd_found++; + g_dhd_pub = &dhd->pub; + DHD_ERROR(("%s: g_dhd_pub %p\n", __FUNCTION__, g_dhd_pub)); + +#ifdef DHD_DUMP_MNGR + dhd->pub.dump_file_manage = + (dhd_dump_file_manage_t *)MALLOCZ(dhd->pub.osh, sizeof(dhd_dump_file_manage_t)); + if (unlikely(!dhd->pub.dump_file_manage)) { + DHD_ERROR(("%s(): could not allocate memory for - " + "dhd_dump_file_manage_t\n", __FUNCTION__)); + } +#endif /* DHD_DUMP_MNGR */ + return &dhd->pub; fail: @@ -9317,6 +9789,7 @@ fail: dhd_detach(&dhd->pub); dhd_free(&dhd->pub); } + dhd_null_flag: return NULL; } @@ -9340,6 +9813,7 @@ int dhd_bus_get_fw_mode(dhd_pub_t *dhdp) return dhd_get_fw_mode(dhdp->info); } +extern char * nvram_get(const char *name); bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) { int fw_len; @@ -9418,6 +9892,7 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) } memset(dhdinfo->nv_path, 0, nv_path_len); strncpy(dhdinfo->nv_path, nv, nv_path_len); + dhdinfo->nv_path[nv_len] = '\0'; #ifdef DHD_USE_SINGLE_NVRAM_FILE /* Remove "_net" or "_mfg" tag from current nvram path */ { @@ -9471,7 +9946,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) DHD_ERROR(("ucode path: %s\n", dhdinfo->uc_path)); #endif /* DHD_UCODE_DOWNLOAD */ -#ifndef BCMEMBEDIMAGE /* fw_path and nv_path are not mandatory for BCMEMBEDIMAGE */ if (dhdinfo->fw_path[0] == '\0') { DHD_ERROR(("firmware path not found\n")); @@ -9481,7 +9955,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo) DHD_ERROR(("nvram path not found\n")); return FALSE; } -#endif /* BCMEMBEDIMAGE */ return TRUE; } @@ -9493,7 +9966,6 @@ extern bool dhd_update_btfw_path(dhd_info_t *dhdinfo, char* btfw_path) const char *fw = NULL; wifi_adapter_info_t *adapter = dhdinfo->adapter; - /* Update bt firmware path. The path may be from adapter info or module parameter * The path from adapter info is used for initialization only (as it won't change). * @@ -9545,7 +10017,6 @@ extern bool dhd_update_btfw_path(dhd_info_t *dhdinfo, char* btfw_path) } #endif /* defined (BT_OVER_SDIO) */ - #ifdef CUSTOMER_HW4_DEBUG bool dhd_validate_chipid(dhd_pub_t *dhdp) { @@ -9562,24 +10033,14 @@ bool dhd_validate_chipid(dhd_pub_t *dhdp) config_chipid = BCM4354_CHIP_ID; #elif defined(BCM4339_CHIP) config_chipid = BCM4339_CHIP_ID; -#elif defined(BCM43349_CHIP) - config_chipid = BCM43349_CHIP_ID; #elif defined(BCM4335_CHIP) config_chipid = BCM4335_CHIP_ID; -#elif defined(BCM43241_CHIP) - config_chipid = BCM4324_CHIP_ID; -#elif defined(BCM4334_CHIP) - config_chipid = BCM4334_CHIP_ID; -#elif defined(BCM4330_CHIP) - config_chipid = BCM4330_CHIP_ID; #elif defined(BCM43430_CHIP) config_chipid = BCM43430_CHIP_ID; #elif defined(BCM43018_CHIP) config_chipid = BCM43018_CHIP_ID; -#elif defined(BCM43455_CHIP) || defined(BCM43456_CHIP) +#elif defined(BCM43455_CHIP) config_chipid = BCM4345_CHIP_ID; -#elif defined(BCM4334W_CHIP) - config_chipid = BCM43342_CHIP_ID; #elif defined(BCM43454_CHIP) config_chipid = BCM43454_CHIP_ID; #elif defined(BCM43012_CHIP_) @@ -9594,11 +10055,6 @@ bool dhd_validate_chipid(dhd_pub_t *dhdp) return FALSE; #endif /* BCM4354_CHIP */ -#ifdef SUPPORT_MULTIPLE_CHIP_4345X - if (config_chipid == BCM43454_CHIP_ID || config_chipid == BCM4345_CHIP_ID) { - return TRUE; - } -#endif /* SUPPORT_MULTIPLE_CHIP_4345X */ #if defined(BCM4354_CHIP) && defined(SUPPORT_MULTIPLE_REVISION) if (chipid == BCM4350_CHIP_ID && config_chipid == BCM4354_CHIP_ID) { return TRUE; @@ -9638,7 +10094,6 @@ int dhd_download_btfw(wlan_bt_handle_t handle, char* btfw_path) dhd_pub_t *dhdp = (dhd_pub_t *)handle; dhd_info_t *dhd = (dhd_info_t*)dhdp->info; - /* Download BT firmware image to the dongle */ if (dhd->pub.busstate == DHD_BUS_DATA && dhd_update_btfw_path(dhd, btfw_path)) { DHD_INFO(("%s: download btfw from: %s\n", __FUNCTION__, dhd->btfw_path)); @@ -9666,11 +10121,13 @@ dhd_bus_start(dhd_pub_t *dhdp) ASSERT(dhd); DHD_TRACE(("Enter %s:\n", __FUNCTION__)); + dhdp->dongle_trap_occured = 0; + dhdp->iovar_timeout_occured = 0; +#ifdef PCIE_FULL_DONGLE + dhdp->d3ack_timeout_occured = 0; +#endif /* PCIE_FULL_DONGLE */ DHD_PERIM_LOCK(dhdp); -#ifdef HOFFLOAD_MODULES - dhd_linux_get_modfw_address(dhdp); -#endif /* try to download image and nvram to the dongle */ if (dhd->pub.busstate == DHD_BUS_DOWN && dhd_update_fw_nv_path(dhd)) { /* Indicate FW Download has not yet done */ @@ -9806,10 +10263,10 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_PERIM_UNLOCK(dhdp); return ret; } -#if defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) DHD_ERROR(("%s: Enable L1ss EP side\n", __FUNCTION__)); exynos_pcie_l1ss_ctrl(1, PCIE_L1SS_CTRL_WIFI); -#endif /* CONFIG_SOC_EXYNOS8895 */ +#endif /* CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ #if defined(DHD_DEBUG) && defined(BCMSDIO) f2_sync_end = OSL_SYSUPTIME(); @@ -9826,9 +10283,6 @@ dhd_bus_start(dhd_pub_t *dhdp) } #endif /* ARP_OFFLOAD_SUPPORT */ -#if defined(TRAFFIC_MGMT_DWM) - bzero(&dhd->pub.dhd_tm_dwm_tbl, sizeof(dhd_trf_mgmt_dwm_tbl_t)); -#endif DHD_PERIM_UNLOCK(dhdp); return 0; } @@ -9841,6 +10295,9 @@ int _dhd_tdls_enable(dhd_pub_t *dhd, bool tdls_on, bool auto_on, struct ether_ad uint32 tdls_idle_time = CUSTOM_TDLS_IDLE_MODE_SETTING; int32 tdls_rssi_high = CUSTOM_TDLS_RSSI_THRESHOLD_HIGH; int32 tdls_rssi_low = CUSTOM_TDLS_RSSI_THRESHOLD_LOW; + uint32 tdls_pktcnt_high = CUSTOM_TDLS_PCKTCNT_THRESHOLD_HIGH; + uint32 tdls_pktcnt_low = CUSTOM_TDLS_PCKTCNT_THRESHOLD_LOW; + BCM_REFERENCE(mac); if (!FW_SUPPORTED(dhd, tdls)) return BCME_ERROR; @@ -9882,6 +10339,18 @@ auto_mode: DHD_ERROR(("%s: tdls_rssi_low failed %d\n", __FUNCTION__, ret)); goto exit; } + ret = dhd_iovar(dhd, 0, "tdls_trigger_pktcnt_high", (char *)&tdls_pktcnt_high, + sizeof(tdls_pktcnt_high), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s: tdls_trigger_pktcnt_high failed %d\n", __FUNCTION__, ret)); + goto exit; + } + ret = dhd_iovar(dhd, 0, "tdls_trigger_pktcnt_low", (char *)&tdls_pktcnt_low, + sizeof(tdls_pktcnt_low), NULL, 0, TRUE); + if (ret < 0) { + DHD_ERROR(("%s: tdls_trigger_pktcnt_low failed %d\n", __FUNCTION__, ret)); + goto exit; + } } exit: @@ -10002,7 +10471,7 @@ int dhd_tdls_update_peer_info(dhd_pub_t *dhdp, wl_event_msg_t *event) return BCME_OK; } #endif /* PCIE_FULL_DONGLE */ -#endif +#endif // endif bool dhd_is_concurrent_mode(dhd_pub_t *dhd) { @@ -10074,10 +10543,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) } return 0; } -#endif - - - +#endif // endif #ifdef WLAIBSS int @@ -10164,10 +10630,9 @@ dhd_enable_adps(dhd_pub_t *dhd, uint8 on) bcm_iov_buf_t *iov_buf = NULL; wl_adps_params_v1_t *data = NULL; - char buf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(*data); - iov_buf = kmalloc(len, GFP_KERNEL); + iov_buf = MALLOC(dhd->osh, len); if (iov_buf == NULL) { DHD_ERROR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__, len)); ret = BCME_NOMEM; @@ -10185,8 +10650,8 @@ dhd_enable_adps(dhd_pub_t *dhd, uint8 on) for (i = 1; i <= MAX_BANDS; i++) { data->band = i; - bcm_mkiovar("adps", (char *)iov_buf, len, buf, sizeof(buf)); - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0)) < 0) { + ret = dhd_iovar(dhd, 0, "adps", (char *)iov_buf, len, NULL, 0, TRUE); + if (ret < 0) { if (ret == BCME_UNSUPPORTED) { DHD_ERROR(("%s adps is not supported\n", __FUNCTION__)); ret = BCME_OK; @@ -10202,7 +10667,8 @@ dhd_enable_adps(dhd_pub_t *dhd, uint8 on) exit: if (iov_buf) { - kfree(iov_buf); + MFREE(dhd->osh, iov_buf, len); + iov_buf = NULL; } return ret; } @@ -10229,14 +10695,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* CUSTOM_AMPDU_BA_WSIZE ||(WLAIBSS && CUSTOM_IBSS_AMPDU_BA_WSIZE) */ #if defined(CUSTOM_AMPDU_MPDU) int32 ampdu_mpdu = 0; -#endif +#endif // endif #if defined(CUSTOM_AMPDU_RELEASE) int32 ampdu_release = 0; -#endif +#endif // endif #if defined(CUSTOM_AMSDU_AGGSF) int32 amsdu_aggsf = 0; -#endif - shub_control_t shub_ctl; +#endif // endif #if defined(BCMSDIO) #ifdef PROP_TXSTATUS @@ -10245,7 +10710,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint32 hostreorder = 1; #endif /* DISABLE_11N */ #endif /* PROP_TXSTATUS */ -#endif +#endif // endif #ifndef PCIE_FULL_DONGLE uint32 wl_ap_isolate; #endif /* PCIE_FULL_DONGLE */ @@ -10275,7 +10740,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint retry_max = CUSTOM_ASSOC_RETRY_MAX; #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; -#endif +#endif // endif int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; int scan_passive_time = DHD_SCAN_PASSIVE_TIME; @@ -10309,13 +10774,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(SOFTAP) uint dtim = 1; -#endif +#endif // endif #if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) struct ether_addr p2p_ea; -#endif +#endif // endif #ifdef BCMCCX uint32 ccx = 1; -#endif +#endif // endif #ifdef SOFTAP_UAPSD_OFF uint32 wme_apsd = 0; #endif /* SOFTAP_UAPSD_OFF */ @@ -10330,7 +10795,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef OKC_SUPPORT uint32 okc = 1; -#endif +#endif // endif #ifdef DISABLE_11N uint32 nmode = 0; @@ -10344,7 +10809,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DISABLE_TXBFR */ #ifdef AMPDU_VO_ENABLE struct ampdu_tid_control tid; -#endif +#endif // endif #if defined(PROP_TXSTATUS) #ifdef USE_WFA_CERT_CONF uint32 proptx = 0; @@ -10362,20 +10827,17 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DISABLE_11N_PROPRIETARY_RATES */ #ifdef CUSTOM_PSPRETEND_THR uint32 pspretend_thr = CUSTOM_PSPRETEND_THR; -#endif +#endif // endif #ifdef CUSTOM_EVENT_PM_WAKE uint32 pm_awake_thresh = CUSTOM_EVENT_PM_WAKE; #endif /* CUSTOM_EVENT_PM_WAKE */ - uint32 rsdb_mode = 0; -#ifdef ENABLE_TEMP_THROTTLING - wl_temp_control_t temp_control; -#endif /* ENABLE_TEMP_THROTTLING */ #ifdef DISABLE_PRUNED_SCAN uint32 scan_features = 0; #endif /* DISABLE_PRUNED_SCAN */ -#ifdef DHD_2G_ONLY_SUPPORT - uint band = WLC_BAND_2G; -#endif /* DHD_2G_ONLY_SUPPORT */ +#if defined(WBTEXT) && defined(WBTEXT_BTMDELTA) + uint32 btmdelta = WBTEXT_BTMDELTA; +#endif /* WBTEXT && WBTEXT_BTMDELTA */ + #ifdef PKT_FILTER_SUPPORT dhd_pkt_filter_enable = TRUE; #ifdef APF @@ -10398,7 +10860,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; - #ifdef CUSTOMER_HW4_DEBUG if (!dhd_validate_chipid(dhd)) { DHD_ERROR(("%s: CONFIG_BCMXXX and CHIP ID(%x) is mismatched\n", @@ -10412,6 +10873,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_MFG_MODE) || (op_mode == DHD_FLAG_MFG_MODE)) { dhd->op_mode = DHD_FLAG_MFG_MODE; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + /* disable runtimePM by default in MFG mode. */ + pm_runtime_disable(dhd_bus_to_dev(dhd->bus)); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #ifdef DHD_PCIE_RUNTIMEPM /* Disable RuntimePM in mfg mode */ DHD_DISABLE_RUNTIME_PM(dhd); @@ -10475,6 +10940,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd->fw_capabilities[cap_buf_size - 1] = '\0'; } +#ifdef WL_MONITOR + if (FW_SUPPORTED(dhd, monitor)) { + dhd->monitor_enable = TRUE; + DHD_ERROR(("%s: Monitor mode is enabled in FW cap\n", __FUNCTION__)); + } else { + dhd->monitor_enable = FALSE; + DHD_ERROR(("%s: Monitor mode is not enabled in FW cap\n", __FUNCTION__)); + } +#endif /* WL_MONITOR */ + if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) || (op_mode == DHD_FLAG_HOSTAP_MODE)) { #ifdef SET_RANDOM_MAC_SOFTAP @@ -10483,10 +10958,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd->op_mode = DHD_FLAG_HOSTAP_MODE; #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; -#endif +#endif // endif #ifdef PKT_FILTER_SUPPORT dhd_pkt_filter_enable = FALSE; -#endif +#endif // endif #ifdef SET_RANDOM_MAC_SOFTAP SRANDOM32((uint)jiffies); rand_mac = RANDOM32(); @@ -10511,7 +10986,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) ret = dhd_iovar(dhd, 0, "wme_apsd", (char *)&wme_apsd, sizeof(wme_apsd), NULL, 0, TRUE); if (ret < 0) { - DHD_ERROR(("%s: set wme_apsd 0 fail (error=%d)\n", + DHD_ERROR(("%s: set wme_apsd 0 fail (error=%d)\n", __FUNCTION__, ret)); } #endif /* SOFTAP_UAPSD_OFF */ @@ -10527,25 +11002,28 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef USE_DYNAMIC_F2_BLKSIZE dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY); #endif /* USE_DYNAMIC_F2_BLKSIZE */ +#ifndef CUSTOM_SET_ANTNPM if (FW_SUPPORTED(dhd, rsdb)) { - rsdb_mode = 0; + wl_config_t rsdb_mode; + memset(&rsdb_mode, 0, sizeof(rsdb_mode)); ret = dhd_iovar(dhd, 0, "rsdb_mode", (char *)&rsdb_mode, sizeof(rsdb_mode), - NULL, 0, TRUE); + NULL, 0, TRUE); if (ret < 0) { DHD_ERROR(("%s Disable rsdb_mode is failed ret= %d\n", __FUNCTION__, ret)); } } +#endif /* !CUSTOM_SET_ANTNPM */ } else { uint32 concurrent_mode = 0; if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_P2P_MODE) || (op_mode == DHD_FLAG_P2P_MODE)) { #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; -#endif +#endif // endif #ifdef PKT_FILTER_SUPPORT dhd_pkt_filter_enable = FALSE; -#endif +#endif // endif dhd->op_mode = DHD_FLAG_P2P_MODE; } else if ((!op_mode && dhd_get_fw_mode(dhd->info) == DHD_FLAG_IBSS_MODE) || (op_mode == DHD_FLAG_IBSS_MODE)) { @@ -10557,7 +11035,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) (concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 1; -#endif +#endif // endif dhd->op_mode |= concurrent_mode; } @@ -10573,7 +11051,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) (char *)&ap_mode, sizeof(ap_mode), TRUE, 0)) < 0) { DHD_ERROR(("%s WLC_SET_AP failed %d\n", __FUNCTION__, ret)); } -#endif +#endif // endif memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN); ETHER_SET_LOCALADDR(&p2p_ea); ret = dhd_iovar(dhd, 0, "p2p_da_override", (char *)&p2p_ea, sizeof(p2p_ea), @@ -10585,12 +11063,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #else (void)concurrent_mode; -#endif +#endif // endif } -#if defined(RSDB_MODE_FROM_FILE) +#ifdef RSDB_MODE_FROM_FILE (void)dhd_rsdb_mode_from_file(dhd); -#endif +#endif /* RSDB_MODE_FROM_FILE */ #ifdef DISABLE_PRUNED_SCAN if (FW_SUPPORTED(dhd, rsdb)) { @@ -10620,7 +11098,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd->info->rxthread_enabled = FALSE; else dhd->info->rxthread_enabled = TRUE; -#endif +#endif // endif /* Set Country code */ if (dhd->dhd_cspec.ccode[0] != 0) { ret = dhd_iovar(dhd, 0, "country", (char *)&dhd->dhd_cspec, sizeof(wl_country_t), @@ -10629,15 +11107,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__)); } - -#ifdef DHD_2G_ONLY_SUPPORT - DHD_ERROR(("Enabled DHD 2G only support!!\n")); - ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)&band, sizeof(band), TRUE, 0); - if (ret < 0) { - DHD_ERROR(("%s Set Band B failed %d\n", __FUNCTION__, ret)); - } -#endif /* DHD_2G_ONLY_SUPPORT */ - /* Set Listen Interval */ ret = dhd_iovar(dhd, 0, "assoc_listen", (char *)&listen_interval, sizeof(listen_interval), NULL, 0, TRUE); @@ -10651,12 +11120,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* USE_WFA_CERT_CONF */ /* Disable built-in roaming to allowed ext supplicant to take care of roaming */ - dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "roam_off", (char *)&roamvar, sizeof(roamvar), NULL, 0, TRUE); #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ #if defined(ROAM_ENABLE) #ifdef DISABLE_BCNLOSS_ROAM - dhd_iovar(dhd, 0, "roam_bcnloss_off", (char *)&roam_bcnloss_off, sizeof(roam_bcnloss_off), - NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "roam_bcnloss_off", (char *)&roam_bcnloss_off, + sizeof(roam_bcnloss_off), NULL, 0, TRUE); #endif /* DISABLE_BCNLOSS_ROAM */ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), TRUE, 0)) < 0) @@ -10690,10 +11159,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* CUSTOM_EVENT_PM_WAKE */ #ifdef OKC_SUPPORT - dhd_iovar(dhd, 0, "okc_enable", (char *)&okc, sizeof(okc), NULL, 0, TRUE); -#endif + ret = dhd_iovar(dhd, 0, "okc_enable", (char *)&okc, sizeof(okc), NULL, 0, TRUE); +#endif // endif #ifdef BCMCCX - dhd_iovar(dhd, 0, "ccx_enable", (char *)&ccx, sizeof(ccx), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "ccx_enable", (char *)&ccx, sizeof(ccx), NULL, 0, TRUE); #endif /* BCMCCX */ #ifdef WLTDLS #ifdef ENABLE_TDLS_AUTO_MODE @@ -10724,9 +11193,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DHD_ENABLE_LPC */ #ifdef WLADPS -#ifdef WLADPS_SEAK_AP_WAR - dhd->disabled_adps = FALSE; -#endif /* WLADPS_SEAK_AP_WAR */ if (dhd->op_mode & DHD_FLAG_STA_MODE) { #ifdef ADPS_MODE_FROM_FILE dhd_adps_mode_from_file(dhd); @@ -10748,10 +11214,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(BCMSDIO) /* Match Host and Dongle rx alignment */ - dhd_iovar(dhd, 0, "bus:txglomalign", (char *)&dongle_align, sizeof(dongle_align), + ret = dhd_iovar(dhd, 0, "bus:txglomalign", (char *)&dongle_align, sizeof(dongle_align), NULL, 0, TRUE); - #ifdef USE_WFA_CERT_CONF if (sec_get_param_wfa_cert(dhd, SET_PARAM_BUS_TXGLOM_MODE, &glom) == BCME_OK) { DHD_ERROR(("%s, read txglom param =%d\n", __FUNCTION__, glom)); @@ -10759,18 +11224,20 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* USE_WFA_CERT_CONF */ if (glom != DEFAULT_GLOM_VALUE) { DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); - dhd_iovar(dhd, 0, "bus:txglom", (char *)&glom, sizeof(glom), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "bus:txglom", (char *)&glom, sizeof(glom), NULL, 0, TRUE); } #endif /* defined(BCMSDIO) */ /* Setup timeout if Beacons are lost and roam is off to report link down */ - dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "bcn_timeout", (char *)&bcn_timeout, sizeof(bcn_timeout), NULL, 0, + TRUE); /* Setup assoc_retry_max count to reconnect target AP in dongle */ - dhd_iovar(dhd, 0, "assoc_retry_max", (char *)&retry_max, sizeof(retry_max), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "assoc_retry_max", (char *)&retry_max, sizeof(retry_max), NULL, 0, + TRUE); #if defined(AP) && !defined(WLP2P) - dhd_iovar(dhd, 0, "apsta", (char *)&apsta, sizeof(apsta), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "apsta", (char *)&apsta, sizeof(apsta), NULL, 0, TRUE); #endif /* defined(AP) && !defined(WLP2P) */ @@ -10782,7 +11249,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if (ap_fw_loaded == TRUE) { dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0); } -#endif +#endif // endif #if defined(KEEP_ALIVE) { @@ -10791,7 +11258,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(SOFTAP) if (ap_fw_loaded == FALSE) -#endif +#endif // endif if (!(dhd->op_mode & (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) { if ((res = dhd_keep_alive_onoff(dhd)) < 0) @@ -10828,9 +11295,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s, read frameburst param=%d\n", __FUNCTION__, frameburst)); } #endif /* USE_WL_FRAMEBURST */ -#ifdef DISABLE_FRAMEBURST_VSDB g_frameburst = frameburst; -#endif /* DISABLE_FRAMEBURST_VSDB */ #endif /* USE_WFA_CERT_CONF */ #ifdef DISABLE_WL_FRAMEBURST_SOFTAP /* Disable Framebursting for SofAP */ @@ -10858,7 +11323,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* DHD_SET_FW_HIGHSPEED */ - iov_buf = (char*)kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + iov_buf = (char*)MALLOC(dhd->osh, WLC_IOCTL_SMLEN); if (iov_buf == NULL) { DHD_ERROR(("failed to allocate %d bytes for iov_buf\n", WLC_IOCTL_SMLEN)); ret = BCME_NOMEM; @@ -10879,7 +11344,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* Set ampdu ba wsize to 64 or 16 */ #ifdef CUSTOM_AMPDU_BA_WSIZE ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE; -#endif +#endif // endif #if defined(WLAIBSS) && defined(CUSTOM_IBSS_AMPDU_BA_WSIZE) if (dhd->op_mode == DHD_FLAG_IBSS_MODE) ampdu_ba_wsize = CUSTOM_IBSS_AMPDU_BA_WSIZE; @@ -10894,20 +11359,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* CUSTOM_AMPDU_BA_WSIZE || (WLAIBSS && CUSTOM_IBSS_AMPDU_BA_WSIZE) */ -#ifdef ENABLE_TEMP_THROTTLING - if (dhd->op_mode & DHD_FLAG_STA_MODE) { - memset(&temp_control, 0, sizeof(temp_control)); - temp_control.enable = 1; - temp_control.control_bit = TEMP_THROTTLE_CONTROL_BIT; - ret = dhd_iovar(dhd, 0, "temp_throttle_control", (char *)&temp_control, - sizeof(temp_control), NULL, 0, TRUE); - if (ret < 0) { - DHD_ERROR(("%s Set temp_throttle_control to %d failed \n", - __FUNCTION__, ret)); - } - } -#endif /* ENABLE_TEMP_THROTTLING */ - #if defined(CUSTOM_AMPDU_MPDU) ampdu_mpdu = CUSTOM_AMPDU_MPDU; if (ampdu_mpdu != 0 && (ampdu_mpdu <= ampdu_ba_wsize)) { @@ -10938,7 +11389,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) ret = dhd_iovar(dhd, 0, "amsdu_aggsf", (char *)&amsdu_aggsf, sizeof(amsdu_aggsf), NULL, 0, TRUE); if (ret < 0) { - DHD_ERROR(("%s Set amsdu_aggsf to %d failed %d\n", + DHD_ERROR(("%s Set amsdu_aggsf to %d failed %d\n", __FUNCTION__, CUSTOM_AMSDU_AGGSF, ret)); } } @@ -10962,7 +11413,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) vht_features = 0x3; /* 2G support */ #endif /* SUPPORT_2G_VHT */ #ifdef SUPPORT_5G_1024QAM_VHT - if (dhd_get_chipid(dhd) == BCM4361_CHIP_ID) { + if (BCM4347_CHIP(dhd_get_chipid(dhd))) { vht_features |= 0x6; /* 5G 1024 QAM support */ } #endif /* SUPPORT_5G_1024QAM_VHT */ @@ -10981,7 +11432,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) __FUNCTION__, ret, vht_features)); ret = dhd_iovar(dhd, 0, "vht_features", (char *)&vht_features, - sizeof(vht_features), NULL, 0, TRUE); + sizeof(vht_features), NULL, 0, TRUE); + DHD_ERROR(("%s vht_features set. ret --> %d\n", __FUNCTION__, ret)); } } @@ -10994,9 +11446,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s ht_features set failed %d\n", __FUNCTION__, ret)); } #endif /* DISABLE_11N_PROPRIETARY_RATES */ -#ifdef DHD_DISABLE_VHTMODE - dhd_disable_vhtmode(dhd); -#endif /* DHD_DISABLE_VHTMODE */ #ifdef CUSTOM_PSPRETEND_THR /* Turn off MPC in AP mode */ ret = dhd_iovar(dhd, 0, "pspretend_threshold", (char *)&pspretend_thr, @@ -11005,7 +11454,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s pspretend_threshold for HostAPD failed %d\n", __FUNCTION__, ret)); } -#endif +#endif // endif ret = dhd_iovar(dhd, 0, "buf_key_b4_m4", (char *)&buf_key_b4_m4, sizeof(buf_key_b4_m4), NULL, 0, TRUE); @@ -11013,8 +11462,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s buf_key_b4_m4 set failed %d\n", __FUNCTION__, ret)); } #ifdef SUPPORT_SET_CAC - bcm_mkiovar("cac", (char *)&cac, sizeof(cac), iovbuf, sizeof(iovbuf)); - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { + ret = dhd_iovar(dhd, 0, "cac", (char *)&cac, sizeof(cac), NULL, 0, TRUE); + if (ret < 0) { DHD_ERROR(("%s Failed to set cac to %d, %d\n", __FUNCTION__, cac, ret)); } #endif /* SUPPORT_SET_CAC */ @@ -11046,7 +11495,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_DISASSOC_IND); setbit(eventmask, WLC_E_DISASSOC); setbit(eventmask, WLC_E_JOIN); - setbit(eventmask, WLC_E_BSSID); setbit(eventmask, WLC_E_START); setbit(eventmask, WLC_E_ASSOC_IND); setbit(eventmask, WLC_E_PSK_SUP); @@ -11056,16 +11504,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_ASSOC_RESP_IE); #ifdef LIMIT_BORROW setbit(eventmask, WLC_E_ALLOW_CREDIT_BORROW); -#endif +#endif // endif #ifndef WL_CFG80211 setbit(eventmask, WLC_E_PMKID_CACHE); setbit(eventmask, WLC_E_TXFAIL); -#endif +#endif // endif setbit(eventmask, WLC_E_JOIN_START); setbit(eventmask, WLC_E_SCAN_COMPLETE); #ifdef DHD_DEBUG setbit(eventmask, WLC_E_SCAN_CONFIRM_IND); -#endif +#endif // endif #ifdef PNO_SUPPORT setbit(eventmask, WLC_E_PFN_NET_FOUND); setbit(eventmask, WLC_E_PFN_BEST_BATCHING); @@ -11073,7 +11521,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_PFN_BSSID_NET_LOST); #endif /* PNO_SUPPORT */ /* enable dongle roaming event */ +#ifdef WL_CFG80211 setbit(eventmask, WLC_E_ROAM); + setbit(eventmask, WLC_E_BSSID); +#endif /* WL_CFG80211 */ #ifdef BCMCCX setbit(eventmask, WLC_E_ADDTS_IND); setbit(eventmask, WLC_E_DELTS_IND); @@ -11114,7 +11565,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* CUSTOM_EVENT_PM_WAKE */ #ifdef DHD_LOSSLESS_ROAMING setbit(eventmask, WLC_E_ROAM_PREP); -#endif +#endif // endif + /* nan events */ + setbit(eventmask, WLC_E_NAN); #if defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) dhd_update_flow_prio_map(dhd, DHD_FLOW_PRIO_LLR_MAP); #endif /* defined(PCIE_FULL_DONGLE) && defined(DHD_LOSSLESS_ROAMING) */ @@ -11132,7 +11585,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* make up event mask ext message iovar for event larger than 128 */ msglen = ROUNDUP(WLC_E_LAST, NBBY)/NBBY + EVENTMSGS_EXT_STRUCT_SIZE; - eventmask_msg = (eventmsgs_ext_t*)kmalloc(msglen, GFP_KERNEL); + eventmask_msg = (eventmsgs_ext_t*)MALLOC(dhd->osh, msglen); if (eventmask_msg == NULL) { DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", msglen)); ret = BCME_NOMEM; @@ -11166,11 +11619,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DBG_PKT_MON */ #ifdef DHD_ULP setbit(eventmask_msg->mask, WLC_E_ULP); -#endif -#ifdef ENABLE_TEMP_THROTTLING - setbit(eventmask_msg->mask, WLC_E_TEMP_THROTTLE); -#endif /* ENABLE_TEMP_THROTTLING */ - +#endif // endif +#ifdef WL_NATOE + setbit(eventmask_msg->mask, WLC_E_NATOE_NFCT); +#endif /* WL_NATOE */ /* Write updated Event mask */ eventmask_msg->ver = EVENTMSGS_VER; eventmask_msg->command = EVENTMSGS_SET_MASK; @@ -11193,7 +11645,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(DHD_8021X_DUMP) && defined(SHOW_LOGTRACE) /* Enabling event log trace for EAP events */ - el_tag = (wl_el_tag_params_t *)kmalloc(sizeof(wl_el_tag_params_t), GFP_KERNEL); + el_tag = (wl_el_tag_params_t *)MALLOC(dhd->osh, sizeof(wl_el_tag_params_t)); if (el_tag == NULL) { DHD_ERROR(("failed to allocate %d bytes for event_msg_ext\n", (int)sizeof(wl_el_tag_params_t))); @@ -11203,17 +11655,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) el_tag->tag = EVENT_LOG_TAG_4WAYHANDSHAKE; el_tag->set = 1; el_tag->flags = EVENT_LOG_TAG_FLAG_LOG; - bcm_mkiovar("event_log_tag_control", (char *)el_tag, - sizeof(*el_tag), iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + ret = dhd_iovar(dhd, 0, "event_log_tag_control", (char *)el_tag, sizeof(*el_tag), NULL, 0, + TRUE); #endif /* DHD_8021X_DUMP */ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, - sizeof(scan_assoc_time), TRUE, 0); + sizeof(scan_assoc_time), TRUE, 0); dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, - sizeof(scan_unassoc_time), TRUE, 0); + sizeof(scan_unassoc_time), TRUE, 0); dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time, - sizeof(scan_passive_time), TRUE, 0); + sizeof(scan_passive_time), TRUE, 0); #ifdef ARP_OFFLOAD_SUPPORT /* Set and enable ARP offload feature for STA only */ @@ -11221,7 +11672,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if (arpoe && !ap_fw_loaded) { #else if (arpoe) { -#endif +#endif // endif dhd_arp_offload_enable(dhd, TRUE); dhd_arp_offload_set(dhd, dhd_arp_mode); } else { @@ -11263,18 +11714,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ dhd->pktfilter[DHD_MDNS_FILTER_NUM] = NULL; #endif /* PASS_IPV4_SUSPEND */ - - dhd->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM] = NULL; if (FW_SUPPORTED(dhd, pf6)) { /* Immediately pkt filter TYPE 6 Dicard Broadcast IP packet */ dhd->pktfilter[DHD_IP4BCAST_DROP_FILTER_NUM] = DISCARD_IPV4_BCAST; /* Immediately pkt filter TYPE 6 Dicard Cisco STP packet */ - dhd->pktfilter[DHD_CISCO_STP_DROP_FILTER_NUM] = - "108 1 6 ETH_H:14 0xFFFFFFFFFFFF 0xAAAA0300000C"; + dhd->pktfilter[DHD_LLC_STP_DROP_FILTER_NUM] = DISCARD_LLC_STP; /* Immediately pkt filter TYPE 6 Dicard Cisco XID protocol */ - dhd->pktfilter[DHD_CISCO_XID_DROP_FILTER_NUM] = - "109 1 6 ETH_H:14 0xFFFFFF 0x0001AF"; - + dhd->pktfilter[DHD_LLC_XID_DROP_FILTER_NUM] = DISCARD_LLC_XID; dhd->pktfilter_count = 10; } @@ -11304,17 +11750,18 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* DISABLE_11N */ #ifdef ENABLE_BCN_LI_BCN_WAKEUP - dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, sizeof(bcn_li_bcn), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "bcn_li_bcn", (char *)&bcn_li_bcn, sizeof(bcn_li_bcn), NULL, 0, + TRUE); #endif /* ENABLE_BCN_LI_BCN_WAKEUP */ #ifdef AMPDU_VO_ENABLE tid.tid = PRIO_8021D_VO; /* Enable TID(6) for voice */ tid.enable = TRUE; - dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); + ret = dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); tid.tid = PRIO_8021D_NC; /* Enable TID(7) for voice */ tid.enable = TRUE; - dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); -#endif + ret = dhd_iovar(dhd, 0, "ampdu_tid", (char *)&tid, sizeof(tid), NULL, 0, TRUE); +#endif // endif /* query for 'clmver' to get clm version info from firmware */ memset(buf, 0, sizeof(buf)); ret = dhd_iovar(dhd, 0, "clmver", NULL, 0, buf, sizeof(buf), FALSE); @@ -11412,7 +11859,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* DISABLE_11N */ - if (wlfc_enable) dhd_wlfc_init(dhd); #ifndef DISABLE_11N @@ -11436,7 +11882,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if (!dhd->pno_state) { dhd_pno_init(dhd); } -#endif +#endif // endif #ifdef RTT_SUPPORT if (!dhd->rtt_state) { ret = dhd_rtt_init(dhd); @@ -11444,39 +11890,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s failed to initialize RTT\n", __FUNCTION__)); } } -#endif +#endif // endif +#ifdef FILTER_IE + /* Failure to configure filter IE is not a fatal error, ignore it. */ + if (!(dhd->op_mode & (DHD_FLAG_HOSTAP_MODE | DHD_FLAG_MFG_MODE))) + dhd_read_from_file(dhd); +#endif /* FILTER_IE */ #ifdef WL11U dhd_interworking_enable(dhd); #endif /* WL11U */ -#ifdef SUPPORT_SENSORHUB - DHD_ERROR(("%s: SensorHub enabled %d\n", - __FUNCTION__, dhd->info->shub_enable)); - ret2 = dhd_iovar(dhd, 0, "shub", NULL, 0, - (char *)&shub_ctl, sizeof(shub_ctl), FALSE); - if (ret2 < 0) { - DHD_ERROR(("%s failed to get shub hub enable information %d\n", - __FUNCTION__, ret2)); - dhd->info->shub_enable = 0; - } else { - dhd->info->shub_enable = shub_ctl.enable; - DHD_ERROR(("%s: checking sensorhub enable %d\n", - __FUNCTION__, dhd->info->shub_enable)); - } -#else - DHD_ERROR(("%s: SensorHub diabled %d\n", - __FUNCTION__, dhd->info->shub_enable)); - dhd->info->shub_enable = FALSE; - shub_ctl.enable = FALSE; - ret2 = dhd_iovar(dhd, 0, "shub", (char *)&shub_ctl, sizeof(shub_ctl), - NULL, 0, TRUE); - if (ret2 < 0) { - DHD_ERROR(("%s failed to set ShubHub disable\n", - __FUNCTION__)); - } -#endif /* SUPPORT_SENSORHUB */ - - #ifdef NDO_CONFIG_SUPPORT dhd->ndo_enable = FALSE; dhd->ndo_host_ip_overflow = FALSE; @@ -11545,46 +11968,60 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* DHD_NON_DMA_M2M_CORRUPTION */ - /* WNM capabilities */ wnm_cap = 0 #ifdef WL11U | WL_WNM_BSSTRANS | WL_WNM_NOTIF -#endif +#endif // endif #ifdef WBTEXT | WL_WNM_BSSTRANS | WL_WNM_MAXIDLE -#endif +#endif // endif ; if (dhd_iovar(dhd, 0, "wnm", (char *)&wnm_cap, sizeof(wnm_cap), NULL, 0, TRUE) < 0) { DHD_ERROR(("failed to set WNM capabilities\n")); } -#ifdef CUSTOM_ASSOC_TIMEOUT - /* set recreate_bi_timeout to increase assoc timeout : - * 20 * 100TU * 1024 / 1000 = 2 secs - * (beacon wait time = recreate_bi_timeout * beacon_period * 1024 / 1000) - */ - if (dhd_wl_ioctl_set_intiovar(dhd, "recreate_bi_timeout", - CUSTOM_ASSOC_TIMEOUT, - WLC_SET_VAR, TRUE, 0) != BCME_OK) { - DHD_ERROR(("failed to set assoc timeout\n")); + if (FW_SUPPORTED(dhd, ecounters) && enable_ecounter) { + if (dhd_start_ecounters(dhd) != BCME_OK) { + DHD_ERROR(("%s Ecounters start failed\n", __FUNCTION__)); + } else if (dhd_start_event_ecounters(dhd) != BCME_OK) { + DHD_ERROR(("%s Event_Ecounters start failed\n", __FUNCTION__)); + } + + } + + /* store the preserve log set numbers */ + if (dhd_get_preserve_log_numbers(dhd, &dhd->logset_prsrv_mask) + != BCME_OK) { + DHD_ERROR(("%s: Failed to get preserve log # !\n", __FUNCTION__)); } -#endif /* CUSTOM_ASSOC_TIMEOUT */ + +#if defined(WBTEXT) && defined(WBTEXT_BTMDELTA) + if (dhd_iovar(dhd, 0, "wnm_btmdelta", (char *)&btmdelta, sizeof(btmdelta), + NULL, 0, TRUE) < 0) { + DHD_ERROR(("failed to set BTM delta\n")); + } +#endif /* WBTEXT && WBTEXT_BTMDELTA */ done: - if (eventmask_msg) - kfree(eventmask_msg); - if (iov_buf) - kfree(iov_buf); + if (eventmask_msg) { + MFREE(dhd->osh, eventmask_msg, msglen); + eventmask_msg = NULL; + } + if (iov_buf) { + MFREE(dhd->osh, iov_buf, WLC_IOCTL_SMLEN); + iov_buf = NULL; + } #if defined(DHD_8021X_DUMP) && defined(SHOW_LOGTRACE) - if (el_tag) - kfree(el_tag); + if (el_tag) { + MFREE(dhd->osh, el_tag, sizeof(wl_el_tag_params_t)); + el_tag = NULL; + } #endif /* DHD_8021X_DUMP */ return ret; } - int dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, uint param_len, char *res_buf, uint res_len, int set) @@ -11608,7 +12045,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, uint param_len ret = BCME_BADARG; goto exit; } - buf = kzalloc(input_len, GFP_KERNEL); + buf = MALLOCZ(pub->osh, input_len); if (!buf) { DHD_ERROR(("%s: mem alloc failed\n", __FUNCTION__)); ret = BCME_NOMEM; @@ -11636,7 +12073,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, uint param_len if (res_len < input_len) { DHD_INFO(("%s: res_len(%d) < input_len(%d)\n", __FUNCTION__, res_len, input_len)); - buf = kzalloc(input_len, GFP_KERNEL); + buf = MALLOCZ(pub->osh, input_len); if (!buf) { DHD_ERROR(("%s: mem alloc failed\n", __FUNCTION__)); ret = BCME_NOMEM; @@ -11675,7 +12112,10 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *param_buf, uint param_len } } exit: - kfree(buf); + if (buf) { + MFREE(pub->osh, buf, input_len); + buf = NULL; + } return ret; } @@ -11709,7 +12149,6 @@ dhd_getiovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, return ret; } - int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx) { struct dhd_info *dhd = dhdp->info; @@ -11752,7 +12191,7 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int 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 +#endif // endif /* now we saved hoste_ip table, clr it in the dongle AOE */ dhd_aoe_hostip_clr(dhd_pub, idx); @@ -11785,7 +12224,7 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx) 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 +#endif // endif } /* @@ -11932,7 +12371,7 @@ dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event) WL_ND_IPV6_ADDR_TYPE_UNICAST, ndo_work->if_idx); } else { ret = dhd_ndo_add_ip(dhdp, &ndo_work->ipv6_addr[0], - ndo_work->if_idx); + ndo_work->if_idx); } if (ret < 0) { DHD_ERROR(("%s: Adding a host ip for NDO failed %d\n", @@ -11978,13 +12417,14 @@ dhd_inet6_work_handler(void *dhd_info, void *event_data, u8 event) break; } done: + /* free ndo_work. alloced while scheduling the work */ if (ndo_work) { kfree(ndo_work); } return; -} +} /* dhd_init_logstrs_array */ /* * Neighbor Discovery Offload: Called when an interface @@ -12065,8 +12505,14 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) ASSERT(!net->open); net->get_stats = dhd_get_stats; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + net->do_ioctl = dhd_ioctl_entry_wrapper; + net->hard_start_xmit = dhd_start_xmit_wrapper; +#else net->do_ioctl = dhd_ioctl_entry; net->hard_start_xmit = dhd_start_xmit; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + net->set_mac_address = dhd_set_mac_address; net->set_multicast_list = dhd_set_multicast_list; net->open = net->stop = NULL; @@ -12137,8 +12583,6 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) goto fail; } - - printf("Register interface [%s] MAC: "MACDBG"\n\n", net->name, #if defined(CUSTOMER_HW4_DEBUG) MAC2STRDBG(dhd->pub.mac.octet)); @@ -12148,7 +12592,7 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) #if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) wl_iw_iscan_set_scan_broadcast_prep(net, 1); -#endif +#endif // endif #if (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \ KERNEL_VERSION(2, 6, 27)))) @@ -12173,9 +12617,9 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock) dhd_event_logtrace_flush_queue(dhdp); #endif /* SHOW_LOGTRACE */ -#ifdef DHDTCPACK_SUPPRESS +#if defined(BCMPCIE) && defined(DHDTCPACK_SUPPRESS) dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF); -#endif /* DHDTCPACK_SUPPRESS */ +#endif /* BCMPCIE && DHDTCPACK_SUPPRESS */ dhd_net_bus_devreset(net, TRUE); #ifdef BCMLXSDMMC dhd_net_bus_suspend(net); @@ -12194,7 +12638,7 @@ fail: net->open = NULL; #else net->netdev_ops = NULL; -#endif +#endif // endif return err; } @@ -12228,7 +12672,6 @@ dhd_bus_detach(dhd_pub_t *dhdp) } } - void dhd_detach(dhd_pub_t *dhdp) { dhd_info_t *dhd; @@ -12237,10 +12680,7 @@ void dhd_detach(dhd_pub_t *dhdp) struct net_device *dev; #ifdef WL_CFG80211 struct bcm_cfg80211 *cfg = NULL; -#endif -#ifdef HOFFLOAD_MODULES - struct module_metadata *hmem = NULL; -#endif +#endif // endif if (!dhdp) return; @@ -12290,15 +12730,9 @@ void dhd_detach(dhd_pub_t *dhdp) #endif /* DHD_WLFC_THREAD */ #endif /* PROP_TXSTATUS */ -#ifdef DHD_TIMESYNC - if (dhd->dhd_state & DHD_ATTACH_TIMESYNC_ATTACH_DONE) { - dhd_timesync_detach(dhdp); - } -#endif /* DHD_TIMESYNC */ #ifdef WL_CFG80211 - if (dev) { + if (dev) wl_cfg80211_down(dev); - } #endif /* WL_CFG80211 */ if (dhd->dhd_state & DHD_ATTACH_STATE_PROT_ATTACH) { @@ -12366,22 +12800,20 @@ void dhd_detach(dhd_pub_t *dhdp) /* delete primary interface 0 */ ifp = dhd->iflist[0]; - ASSERT(ifp); - ASSERT(ifp->net); if (ifp && ifp->net) { - - #ifdef WL_CFG80211 cfg = wl_get_cfg(ifp->net); -#endif +#endif // endif /* in unregister_netdev case, the interface gets freed by net->destructor * (which is set to free_netdev) */ if (ifp->net->reg_state == NETREG_UNINITIALIZED) { free_netdev(ifp->net); } else { +#if defined(ARGOS_CPU_SCHEDULER) && defined(ARGOS_RPS_CPU_CTL) argos_register_notifier_deinit(); +#endif /* ARGOS_CPU_SCHEDULER && ARGOS_RPS_CPU_CTL */ #ifdef SET_RPS_CPUS custom_rps_map_clear(ifp->net->_rx); #endif /* SET_RPS_CPUS */ @@ -12401,7 +12833,6 @@ void dhd_detach(dhd_pub_t *dhdp) ifp->phnd_arp_table = NULL; #endif /* DHD_L2_FILTER */ - dhd_if_del_sta_list(ifp); MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); @@ -12440,6 +12871,12 @@ void dhd_detach(dhd_pub_t *dhdp) } } +#ifdef WL_NATOE + if (dhd->pub.nfct) { + dhd_ct_close(dhd->pub.nfct); + } +#endif /* WL_NATOE */ + #ifdef DHD_LB if (dhd->dhd_state & DHD_ATTACH_STATE_LB_ATTACH_DONE) { /* Clear the flag first to avoid calling the cpu notifier */ @@ -12473,9 +12910,6 @@ void dhd_detach(dhd_pub_t *dhdp) DHD_SSSR_MEMPOOL_DEINIT(&dhd->pub); -#ifdef DHD_LOG_DUMP - dhd_log_dump_deinit(&dhd->pub); -#endif /* DHD_LOG_DUMP */ #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { if (!cfg) { @@ -12486,8 +12920,14 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_monitor_uninit(); } } -#endif +#endif // endif +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + destroy_workqueue(dhd->tx_wq); + dhd->tx_wq = NULL; + destroy_workqueue(dhd->rx_wq); + dhd->rx_wq = NULL; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #ifdef DEBUGABILITY if (dhdp->dbg) { #ifdef DBG_PKT_MON @@ -12497,10 +12937,15 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_os_dbg_detach(dhdp); } #endif /* DEBUGABILITY */ -#ifdef SHOW_LOGTRACE #ifdef DHD_PKT_LOGGING - dhd_os_detach_pktlog(dhdp); + dhd_os_detach_pktlog(dhdp); #endif /* DHD_PKT_LOGGING */ +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT + if (dhd->pub.hang_info) { + MFREE(dhd->pub.osh, dhd->pub.hang_info, VENDOR_SEND_HANG_EXT_INFO_LEN); + } +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ +#ifdef SHOW_LOGTRACE /* Release the skbs from queue for WLC_E_TRACE event */ dhd_event_logtrace_flush_queue(dhdp); @@ -12528,22 +12973,15 @@ void dhd_detach(dhd_pub_t *dhdp) dhd->dhd_state &= ~DHD_ATTACH_LOGTRACE_INIT; } #endif /* SHOW_LOGTRACE */ -#ifdef BCMPCIE - if (dhdp->extended_trap_data) - { - MFREE(dhdp->osh, dhdp->extended_trap_data, BCMPCIE_EXT_TRAP_DATA_MAXLEN); - dhdp->extended_trap_data = NULL; - } -#endif /* BCMPCIE */ #ifdef PNO_SUPPORT if (dhdp->pno_state) dhd_pno_deinit(dhdp); -#endif +#endif // endif #ifdef RTT_SUPPORT if (dhdp->rtt_state) { dhd_rtt_deinit(dhdp); } -#endif +#endif // endif #if defined(CONFIG_PM_SLEEP) if (dhd_pm_notifier_registered) { unregister_pm_notifier(&dhd->pm_notifier); @@ -12556,7 +12994,7 @@ void dhd_detach(dhd_pub_t *dhdp) free_percpu(dhd->new_freq); dhd->new_freq = NULL; cpufreq_unregister_notifier(&dhd->freq_trans, CPUFREQ_TRANSITION_NOTIFIER); -#endif +#endif // endif #ifdef CONFIG_HAS_WAKELOCK dhd->wakelock_wd_counter = 0; wake_lock_destroy(&dhd->wl_wdwake); @@ -12574,7 +13012,6 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif /* ARGOS_CPU_SCHEDULER */ - #ifdef DHDTCPACK_SUPPRESS /* This will free all MEM allocated for TCPACK SUPPRESS */ dhd_tcpack_suppress_set(&dhd->pub, TCPACK_SUP_OFF); @@ -12584,19 +13021,12 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_flow_rings_deinit(dhdp); if (dhdp->prot) dhd_prot_detach(dhdp); -#endif +#endif // endif #if defined(WLTDLS) && defined(PCIE_FULL_DONGLE) dhd_free_tdls_peer_list(dhdp); -#endif +#endif // endif -#ifdef HOFFLOAD_MODULES - hmem = &dhdp->hmem; - dhd_free_module_memory(dhdp->bus, hmem); -#endif /* HOFFLOAD_MODULES */ -#if defined(BT_OVER_SDIO) - mutex_destroy(&dhd->bus_user_lock); -#endif /* BT_OVER_SDIO */ #ifdef DUMP_IOCTL_IOV_LIST dhd_iov_li_delete(dhdp, &(dhdp->dump_iovlist_head)); #endif /* DUMP_IOCTL_IOV_LIST */ @@ -12614,15 +13044,40 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_deferred_work_deinit(dhd->dhd_deferred_wq); dhd->dhd_deferred_wq = NULL; + /* log dump related buffers should be freed after wq is purged */ +#ifdef DHD_LOG_DUMP + dhd_log_dump_deinit(&dhd->pub); +#endif /* DHD_LOG_DUMP */ +#if defined(BCMPCIE) + if (dhdp->extended_trap_data) + { + MFREE(dhdp->osh, dhdp->extended_trap_data, BCMPCIE_EXT_TRAP_DATA_MAXLEN); + dhdp->extended_trap_data = NULL; + } +#endif /* BCMPCIE */ + #ifdef SHOW_LOGTRACE /* Wait till event_log_dispatcher_work finishes */ - cancel_work_sync(&dhd->event_log_dispatcher_work); + cancel_delayed_work_sync(&dhd->event_log_dispatcher_work); + mutex_lock(&dhd->pub.dhd_trace_lock); + remove_proc_entry("dhd_trace", NULL); + mutex_unlock(&dhd->pub.dhd_trace_lock); #endif /* SHOW_LOGTRACE */ +#ifdef DHD_DUMP_MNGR + if (dhd->pub.dump_file_manage) { + MFREE(dhd->pub.osh, dhd->pub.dump_file_manage, + sizeof(dhd_dump_file_manage_t)); + } +#endif /* DHD_DUMP_MNGR */ dhd_sysfs_exit(dhd); dhd->pub.fw_download_done = FALSE; -} +#if defined(BT_OVER_SDIO) + mutex_destroy(&dhd->bus_user_lock); +#endif /* BT_OVER_SDIO */ + +} /* dhd_detach */ void dhd_free(dhd_pub_t *dhdp) @@ -12659,21 +13114,7 @@ dhd_free(dhd_pub_t *dhdp) #endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ dhdp->soc_ram = NULL; } -#ifdef CACHE_FW_IMAGES - if (dhdp->cached_fw) { - MFREE(dhdp->osh, dhdp->cached_fw, dhdp->bus->ramsize); - dhdp->cached_fw = NULL; - } - - if (dhdp->cached_nvram) { - MFREE(dhdp->osh, dhdp->cached_nvram, MAX_NVRAMBUF_SIZE); - dhdp->cached_nvram = NULL; - } -#endif - if (dhd) { -#ifdef REPORT_FATAL_TIMEOUTS - deinit_dhd_timeouts(&dhd->pub); -#endif /* REPORT_FATAL_TIMEOUTS */ + if (dhd != NULL) { /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */ if (dhd != (dhd_info_t *)dhd_os_prealloc(dhdp, @@ -12755,7 +13196,6 @@ dhd_module_init(void) DHD_PERIM_RADIO_INIT(); - if (firmware_path[0] != '\0') { strncpy(fw_bak_path, firmware_path, MOD_PARAM_PATHLEN); fw_bak_path[MOD_PARAM_PATHLEN-1] = '\0'; @@ -12808,17 +13248,18 @@ dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unuse return NOTIFY_DONE; } - #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) #if defined(CONFIG_DEFERRED_INITCALLS) && !defined(EXYNOS_PCIE_MODULE_PATCH) #if defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_SOC_EXYNOS8890) || \ - defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_SOC_EXYNOS8895) || \ - defined(CONFIG_ARCH_MSM8998) + defined(CONFIG_ARCH_MSM8996) || defined(CONFIG_ARCH_MSM8998) || \ + defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) || \ + defined(CONFIG_ARCH_SDM845) deferred_module_init_sync(dhd_module_init); #else deferred_module_init(dhd_module_init); #endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 || - * CONFIG_ARCH_MSM8996 || CONFIG_SOC_EXYNOS8895 || CONFIG_ARCH_MSM8998 + * CONFIG_ARCH_MSM8996 || CONFIG_ARCH_MSM8998 || CONFIG_SOC_EXYNOS8895 + * CONFIG_SOC_EXYNOS9810 || CONFIG_ARCH_SDM845 */ #elif defined(USE_LATE_INITCALL_SYNC) late_initcall_sync(dhd_module_init); @@ -12884,6 +13325,58 @@ dhd_os_dhdiovar_unlock(dhd_pub_t *pub) } } +void +dhd_os_logdump_lock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = NULL; + + if (!pub) + return; + + dhd = (dhd_info_t *)(pub->info); + + if (dhd) { + mutex_lock(&dhd->logdump_lock); + } +} + +void +dhd_os_logdump_unlock(dhd_pub_t *pub) +{ + dhd_info_t *dhd = NULL; + + if (!pub) + return; + + dhd = (dhd_info_t *)(pub->info); + + if (dhd) { + mutex_unlock(&dhd->logdump_lock); + } +} + +unsigned long +dhd_os_dbgring_lock(void *lock) +{ + if (!lock) + return 0; + + mutex_lock((struct mutex *)lock); + + return 0; +} + +void +dhd_os_dbgring_unlock(void *lock, unsigned long flags) +{ + BCM_REFERENCE(flags); + + if (!lock) + return; + + mutex_unlock((struct mutex *)lock); +} + unsigned int dhd_os_get_ioctl_resp_timeout(void) { @@ -12907,7 +13400,7 @@ dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition) timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); #else timeout = dhd_ioctl_timeout_msec * HZ / 1000; -#endif +#endif // endif DHD_PERIM_UNLOCK(pub); @@ -12935,10 +13428,10 @@ dhd_os_d3ack_wait(dhd_pub_t *pub, uint *condition) /* Convert timeout in millsecond to jiffies */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); + timeout = msecs_to_jiffies(D3_ACK_RESP_TIMEOUT); #else - timeout = dhd_ioctl_timeout_msec * HZ / 1000; -#endif + timeout = D3_ACK_RESP_TIMEOUT * HZ / 1000; +#endif // endif DHD_PERIM_UNLOCK(pub); @@ -12949,40 +13442,6 @@ dhd_os_d3ack_wait(dhd_pub_t *pub, uint *condition) return timeout; } -#ifdef PCIE_INB_DW -int -dhd_os_ds_exit_wait(dhd_pub_t *pub, uint *condition) -{ - dhd_info_t * dhd = (dhd_info_t *)(pub->info); - int timeout; - - /* Convert timeout in millsecond to jiffies */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - timeout = msecs_to_jiffies(ds_exit_timeout_msec); -#else - timeout = ds_exit_timeout_msec * HZ / 1000; -#endif - - DHD_PERIM_UNLOCK(pub); - - timeout = wait_event_timeout(dhd->ds_exit_wait, (*condition), timeout); - - DHD_PERIM_LOCK(pub); - - return timeout; -} - -int -dhd_os_ds_exit_wake(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - wake_up(&dhd->ds_exit_wait); - return 0; -} - -#endif /* PCIE_INB_DW */ - int dhd_os_d3ack_wake(dhd_pub_t *pub) { @@ -12991,6 +13450,7 @@ dhd_os_d3ack_wake(dhd_pub_t *pub) wake_up(&dhd->d3ack_wait); return 0; } + int dhd_os_busbusy_wait_negation(dhd_pub_t *pub, uint *condition) { @@ -13006,7 +13466,7 @@ dhd_os_busbusy_wait_negation(dhd_pub_t *pub, uint *condition) timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); #else timeout = DHD_BUS_BUSY_TIMEOUT * HZ / 1000; -#endif +#endif // endif timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, !(*condition), timeout); @@ -13029,13 +13489,38 @@ dhd_os_busbusy_wait_condition(dhd_pub_t *pub, uint *var, uint condition) timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); #else timeout = DHD_BUS_BUSY_TIMEOUT * HZ / 1000; -#endif +#endif // endif timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, (*var == condition), timeout); return timeout; } +/* + * Wait until the '(*var & bitmask) == condition' is met. + * Returns 0 if the @condition evaluated to false after the timeout elapsed + * Returns 1 if the @condition evaluated to true + */ +int +dhd_os_busbusy_wait_bitmask(dhd_pub_t *pub, uint *var, + uint bitmask, uint condition) +{ + dhd_info_t * dhd = (dhd_info_t *)(pub->info); + int timeout; + + /* Convert timeout in millsecond to jiffies */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + timeout = msecs_to_jiffies(DHD_BUS_BUSY_TIMEOUT); +#else + timeout = DHD_BUS_BUSY_TIMEOUT * HZ / 1000; +#endif // endif + + timeout = wait_event_timeout(dhd->dhd_bus_busy_state_wait, + ((*var & bitmask) == condition), timeout); + + return timeout; +} + int dhd_os_dmaxfer_wait(dhd_pub_t *pub, uint *condition) { @@ -13047,6 +13532,7 @@ dhd_os_dmaxfer_wait(dhd_pub_t *pub, uint *condition) DHD_PERIM_LOCK(pub); return ret; + } int @@ -13061,7 +13547,7 @@ dhd_os_dmaxfer_wake(dhd_pub_t *pub) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) /* Fix compilation error for FC11 */ INLINE -#endif +#endif // endif int dhd_os_busbusy_wake(dhd_pub_t *pub) { @@ -13084,7 +13570,6 @@ dhd_os_wd_timer_extend(void *bus, bool extend) dhd_os_wd_timer(bus, dhd->default_wd_interval); } - void dhd_os_wd_timer(void *bus, uint wdtick) { @@ -13123,11 +13608,11 @@ dhd_os_wd_timer(void *bus, uint wdtick) return; } - if (wdtick) { + if (wdtick) { #ifdef BCMSDIO DHD_OS_WD_WAKE_LOCK(pub); -#endif /* BCMSDIO */ dhd_watchdog_ms = (uint)wdtick; +#endif /* BCMSDIO */ /* Re arm the timer, at last watchdog period */ mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd->wd_timer_valid = TRUE; @@ -13186,7 +13671,7 @@ exit: #endif /* DHD_PCIE_RUNTIMEPM */ void * -dhd_os_open_image(char *filename) +dhd_os_open_image1(dhd_pub_t *pub, char *filename) { struct file *fp; int size; @@ -13216,6 +13701,8 @@ dhd_os_open_image(char *filename) goto err; } + DHD_ERROR(("%s: %s (%d bytes) open success\n", __FUNCTION__, filename, size)); + err: return fp; } @@ -13245,20 +13732,6 @@ dhd_os_get_image_block(char *buf, int len, void *image) return rdlen; } -int -dhd_os_get_image_size(void *image) -{ - struct file *fp = (struct file *)image; - int size; - if (!image) { - return 0; - } - - size = i_size_read(file_inode(fp)); - - return size; -} - #if defined(BT_OVER_SDIO) int dhd_os_gets_image(dhd_pub_t *pub, char *str, int len, void *image) @@ -13287,12 +13760,26 @@ err: } #endif /* defined (BT_OVER_SDIO) */ +int +dhd_os_get_image_size(void *image) +{ + struct file *fp = (struct file *)image; + int size; + if (!image) { + return 0; + } + + size = i_size_read(file_inode(fp)); + + return size; +} void -dhd_os_close_image(void *image) +dhd_os_close_image1(dhd_pub_t *pub, void *image) { - if (image) + if (image) { filp_close((struct file *)image, NULL); + } } void @@ -13342,19 +13829,11 @@ dhd_os_sdunlock_txq(dhd_pub_t *pub) void dhd_os_sdlock_rxq(dhd_pub_t *pub) { - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - spin_lock_bh(&dhd->rxqlock); } void dhd_os_sdunlock_rxq(dhd_pub_t *pub) { - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - spin_unlock_bh(&dhd->rxqlock); } static void @@ -13470,16 +13949,23 @@ dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, bcmerror = wl_process_host_event(&dhd->pub, &ifidx, pktdata, pktlen, event, data, NULL); #endif /* SHOW_LOGTRACE */ + if (unlikely(bcmerror != BCME_OK)) { + return bcmerror; + } - if (bcmerror != BCME_OK) - return (bcmerror); + if (ntoh32(event->event_type) == WLC_E_IF) { + /* WLC_E_IF event types are consumed by wl_process_host_event. + * For ifadd/del ops, the netdev ptr may not be valid at this + * point. so return before invoking cfg80211/wext handlers. + */ + return BCME_OK; + } #if defined(WL_WIRELESS_EXT) if (event->bsscfgidx == 0) { /* * Wireless ext is on primary interface only */ - ASSERT(dhd->iflist[ifidx] != NULL); ASSERT(dhd->iflist[ifidx]->net != NULL); @@ -13490,8 +13976,6 @@ dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, #endif /* defined(WL_WIRELESS_EXT) */ #ifdef WL_CFG80211 - ASSERT(dhd->iflist[ifidx] != NULL); - ASSERT(dhd->iflist[ifidx]->net != NULL); if (dhd->iflist[ifidx]->net) { spin_lock_irqsave(&dhd->pub.up_lock, flags); if (dhd->pub.up) { @@ -13508,8 +13992,11 @@ dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen, void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) { - /* Just return from here */ - return; + switch (ntoh32(event->event_type)) { + /* Handle error case or further events here */ + default: + break; + } } #ifdef LOG_INTO_TCPDUMP @@ -13587,7 +14074,7 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) dhd_os_sdlock(dhd); #endif /* defined(BCMSDIO) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) */ return; -} +} /* dhd_init_static_strs_array */ void dhd_wait_event_wakeup(dhd_pub_t *dhd) { @@ -13595,7 +14082,7 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd) struct dhd_info *dhdinfo = dhd->info; if (waitqueue_active(&dhdinfo->ctrl_wait)) wake_up(&dhdinfo->ctrl_wait); -#endif +#endif // endif return; } @@ -13607,6 +14094,11 @@ dhd_net_bus_devreset(struct net_device *dev, uint8 flag) dhd_info_t *dhd = DHD_DEV_INFO(dev); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + if (pm_runtime_get_sync(dhd_bus_to_dev(dhd->pub.bus)) < 0) + return BCME_ERROR; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + if (flag == TRUE) { /* Issue wl down command before resetting the chip */ if (dhd_wl_ioctl_cmd(&dhd->pub, WLC_DOWN, NULL, 0, TRUE, 0) < 0) { @@ -13621,7 +14113,7 @@ dhd_net_bus_devreset(struct net_device *dev, uint8 flag) if (dhd->pub.pno_state) { dhd_pno_deinit(&dhd->pub); } -#endif +#endif // endif #ifdef RTT_SUPPORT if (dhd->pub.rtt_state) { dhd_rtt_deinit(&dhd->pub); @@ -13644,6 +14136,11 @@ dhd_net_bus_devreset(struct net_device *dev, uint8 flag) ret = dhd_bus_devreset(&dhd->pub, flag); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_mark_last_busy(dhd_bus_to_dev(dhd->pub.bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(dhd->pub.bus)); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + if (flag) { /* Clear some flags for recovery logic */ dhd->pub.dongle_trap_occured = 0; @@ -13708,10 +14205,10 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) ret = dhd_set_suspend(val, &dhd->pub); #else ret = dhd_suspend_resume_helper(dhd, val, force); -#endif +#endif // endif #ifdef WL_CFG80211 wl_cfg80211_update_power_mode(dev); -#endif +#endif // endif } return ret; } @@ -13873,7 +14370,20 @@ dhd_dev_get_feature_set(struct net_device *dev) #ifdef KEEP_ALIVE feature_set |= WIFI_FEATURE_MKEEP_ALIVE; #endif /* KEEP_ALIVE */ - +#ifdef SUPPORT_RANDOM_MAC_SCAN + feature_set |= WIFI_FEATURE_SCAN_RAND; +#endif /* SUPPORT_RANDOM_MAC_SCAN */ +#ifdef FILTER_IE + if (FW_SUPPORTED(dhd, fie)) { + feature_set |= WIFI_FEATURE_FILTER_IE; + } +#endif /* FILTER_IE */ +#ifdef ROAMEXP_SUPPORT + /* Check if the Android O roam feature is supported by FW */ + if (!(BCME_UNSUPPORTED == dhd_dev_set_whitelist_ssid(dev, NULL, 0, true))) { + feature_set |= WIFI_FEATURE_CONTROL_ROAMING; + } +#endif /* ROAMEXP_SUPPORT */ return feature_set; } @@ -13942,7 +14452,6 @@ dhd_dev_set_nodfs(struct net_device *dev, u32 nodfs) return 0; } #endif /* CUSTOM_FORCE_NODFS_FLAG */ - #ifdef NDO_CONFIG_SUPPORT int dhd_dev_ndo_cfg(struct net_device *dev, u8 enable) @@ -13966,7 +14475,7 @@ dhd_dev_ndo_cfg(struct net_device *dev, u8 enable) dhdp->ndo_enable = FALSE; /* disable ND offload in FW */ - ret = dhd_ndo_enable(dhdp, 0); + ret = dhd_ndo_enable(dhdp, FALSE); if (ret < 0) { DHD_ERROR(("%s: failed to disable NDO: %d\n", __FUNCTION__, ret)); } @@ -14061,7 +14570,7 @@ dhd_dev_ndo_update_inet6addr(struct net_device *dev) dhdp->ndo_host_ip_overflow = TRUE; /* Disable ND offload in FW */ DHD_INFO(("%s: Host IP overflow, disable NDO\n", __FUNCTION__)); - ret = dhd_ndo_enable(dhdp, 0); + ret = dhd_ndo_enable(dhdp, FALSE); } return ret; @@ -14165,7 +14674,7 @@ dhd_dev_ndo_update_inet6addr(struct net_device *dev) if (dhdp->in_suspend) { /* drvier is in (early) suspend state, need to enable ND offload in FW */ DHD_INFO(("%s: enable NDO\n", __FUNCTION__)); - ret = dhd_ndo_enable(dhdp, 1); + ret = dhd_ndo_enable(dhdp, TRUE); } } @@ -14326,11 +14835,11 @@ dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time_flag) /* Linux wrapper to call common dhd_handle_hotlist_scan_evt */ void * dhd_dev_hotlist_scan_event(struct net_device *dev, - const void *data, int *send_evt_bytes, hotlist_type_t type) + const void *data, int *send_evt_bytes, hotlist_type_t type, u32 *buf_len) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - return (dhd_handle_hotlist_scan_evt(&dhd->pub, data, send_evt_bytes, type)); + return (dhd_handle_hotlist_scan_evt(&dhd->pub, data, send_evt_bytes, type, buf_len)); } /* Linux wrapper to call common dhd_process_full_gscan_result */ @@ -14390,12 +14899,12 @@ dhd_dev_set_lazy_roam_cfg(struct net_device *dev, return BCME_BADARG; } - DHD_ERROR(("a_band_boost_thr %d a_band_penalty_thr %d\n", + DHD_INFO(("a_band_boost_thr %d a_band_penalty_thr %d\n", roam_param->a_band_boost_threshold, roam_param->a_band_penalty_threshold)); - DHD_ERROR(("a_band_boost_factor %d a_band_penalty_factor %d cur_bssid_boost %d\n", + DHD_INFO(("a_band_boost_factor %d a_band_penalty_factor %d cur_bssid_boost %d\n", roam_param->a_band_boost_factor, roam_param->a_band_penalty_factor, roam_param->cur_bssid_boost)); - DHD_ERROR(("alert_roam_trigger_thr %d a_band_max_boost %d\n", + DHD_INFO(("alert_roam_trigger_thr %d a_band_max_boost %d\n", roam_param->alert_roam_trigger_threshold, roam_param->a_band_max_boost)); memcpy(&roam_exp_cfg.params, roam_param, sizeof(*roam_param)); @@ -14441,21 +14950,25 @@ dhd_dev_set_lazy_roam_bssid_pref(struct net_device *dev, wl_bssid_pref_cfg_t *bssid_pref, uint32 flush) { int err; - int len; + uint len; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); bssid_pref->version = BSSID_PREF_LIST_VERSION; /* By default programming bssid pref flushes out old values */ bssid_pref->flags = (flush && !bssid_pref->count) ? ROAM_EXP_CLEAR_BSSID_PREF: 0; len = sizeof(wl_bssid_pref_cfg_t); - len += (bssid_pref->count - 1) * sizeof(wl_bssid_pref_list_t); - err = dhd_iovar(&(dhd->pub), 0, "roam_exp_bssid_pref", (char *)bssid_pref, - len, NULL, 0, TRUE); + if (bssid_pref->count) { + len += (bssid_pref->count - 1) * sizeof(wl_bssid_pref_list_t); + } + err = dhd_iovar(&dhd->pub, 0, "roam_exp_bssid_pref", + (char *)bssid_pref, len, NULL, 0, TRUE); if (err != BCME_OK) { DHD_ERROR(("%s : Failed to execute roam_exp_bssid_pref %d\n", __FUNCTION__, err)); } return err; } +#endif /* GSCAN_SUPPORT */ +#if defined(GSCAN_SUPPORT) || defined(ROAMEXP_SUPPORT) int dhd_dev_set_blacklist_bssid(struct net_device *dev, maclist_t *blacklist, uint32 len, uint32 flush) @@ -14500,28 +15013,28 @@ dhd_dev_set_whitelist_ssid(struct net_device *dev, wl_ssid_whitelist_t *ssid_whi } ssid_whitelist->version = SSID_WHITELIST_VERSION; ssid_whitelist->flags = flush ? ROAM_EXP_CLEAR_SSID_WHITELIST : 0; - err = dhd_iovar(&(dhd->pub), 0, "roam_exp_ssid_whitelist", (char *)ssid_whitelist, - len, NULL, 0, TRUE); + err = dhd_iovar(&dhd->pub, 0, "roam_exp_ssid_whitelist", (char *)ssid_whitelist, len, NULL, + 0, TRUE); if (err != BCME_OK) { DHD_ERROR(("%s : Failed to execute roam_exp_bssid_pref %d\n", __FUNCTION__, err)); } return err; } -#endif /* GSCAN_SUPPORT */ +#endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */ #if defined(GSCAN_SUPPORT) || defined(DHD_GET_VALID_CHANNELS) /* Linux wrapper to call common dhd_pno_get_gscan */ void * dhd_dev_pno_get_gscan(struct net_device *dev, dhd_pno_gscan_cmd_cfg_t type, - void *info, uint32 *len) + void *info, uint32 *len) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); return (dhd_pno_get_gscan(&dhd->pub, type, info, len)); } #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */ -#endif +#endif // endif -#ifdef RSSI_MONITOR_SUPPORT +#ifdef RSSI_MONITOR_SUPPORT int dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, int8 max_rssi, int8 min_rssi) @@ -14534,8 +15047,8 @@ dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, rssi_monitor.max_rssi = max_rssi; rssi_monitor.min_rssi = min_rssi; rssi_monitor.flags = start ? 0: RSSI_MONITOR_STOP; - err = dhd_iovar(&(dhd->pub), 0, "rssi_monitor", (char *)&rssi_monitor, - sizeof(rssi_monitor), NULL, 0, TRUE); + err = dhd_iovar(&dhd->pub, 0, "rssi_monitor", (char *)&rssi_monitor, sizeof(rssi_monitor), + NULL, 0, TRUE); if (err < 0 && err != BCME_UNSUPPORTED) { DHD_ERROR(("%s : Failed to execute rssi_monitor %d\n", __FUNCTION__, err)); } @@ -14544,14 +15057,15 @@ dhd_dev_set_rssi_monitor_cfg(struct net_device *dev, int start, #endif /* RSSI_MONITOR_SUPPORT */ #ifdef DHDTCPACK_SUPPRESS -int dhd_dev_set_tcpack_sup_mode_cfg(struct net_device *dev, uint8 enable) +int +dhd_dev_set_tcpack_sup_mode_cfg(struct net_device *dev, uint8 enable) { int err; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - err = dhd_tcpack_suppress_set(&(dhd->pub), enable); + err = dhd_tcpack_suppress_set(&dhd->pub, enable); if (err != BCME_OK) { - DHD_ERROR(("%s : Failed to execute rssi_monitor %d\n", __FUNCTION__, err)); + DHD_ERROR(("%s : Failed to set tcpack_suppress mode: %d\n", __FUNCTION__, err)); } return err; } @@ -14607,7 +15121,6 @@ dhd_set_rand_mac_oui(dhd_pub_t *dhd) } #ifdef RTT_SUPPORT -#ifdef WL_CFG80211 /* Linux wrapper to call common dhd_pno_set_cfg_gscan */ int dhd_dev_rtt_set_cfg(struct net_device *dev, void *buf) @@ -14668,7 +15181,7 @@ int dhd_dev_rtt_cancel_responder(struct net_device *dev) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); return (dhd_rtt_cancel_responder(&dhd->pub)); } -#endif /* WL_CFG80211 */ + #endif /* RTT_SUPPORT */ #ifdef KEEP_ALIVE @@ -14703,13 +15216,13 @@ dhd_dev_start_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id, uint8 *ip_pk DHD_TRACE(("%s execution\n", __FUNCTION__)); - if ((pbuf = kzalloc(KA_TEMP_BUF_SIZE, GFP_KERNEL)) == NULL) { + if ((pbuf = MALLOCZ(dhd_pub->osh, KA_TEMP_BUF_SIZE)) == NULL) { DHD_ERROR(("failed to allocate buf with size %d\n", KA_TEMP_BUF_SIZE)); res = BCME_NOMEM; return res; } - if ((pmac_frame = kzalloc(KA_FRAME_SIZE, GFP_KERNEL)) == NULL) { + if ((pmac_frame = MALLOCZ(dhd_pub->osh, KA_FRAME_SIZE)) == NULL) { DHD_ERROR(("failed to allocate mac_frame with size %d\n", KA_FRAME_SIZE)); res = BCME_NOMEM; goto exit; @@ -14808,19 +15321,25 @@ dhd_dev_start_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id, uint8 *ip_pk res = dhd_wl_ioctl_cmd(dhd_pub, WLC_SET_VAR, pbuf, buf_len, TRUE, 0); exit: - kfree(pmac_frame_begin); - kfree(pbuf); + if (pmac_frame_begin) { + MFREE(dhd_pub->osh, pmac_frame_begin, KA_FRAME_SIZE); + pmac_frame_begin = NULL; + } + if (pbuf) { + MFREE(dhd_pub->osh, pbuf, KA_TEMP_BUF_SIZE); + pbuf = NULL; + } return res; } int dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id) { - char *pbuf; + char *pbuf = NULL; wl_mkeep_alive_pkt_t mkeep_alive_pkt; - wl_mkeep_alive_pkt_t *mkeep_alive_pktp; + wl_mkeep_alive_pkt_t *mkeep_alive_pktp = NULL; int res = BCME_ERROR; - int i; + int i = 0; /* * The mkeep_alive packet is for STA interface only; if the bss is configured as AP, @@ -14834,7 +15353,7 @@ dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id) /* * Get current mkeep-alive status. Skip ID 0 which is being used for NULL pkt. */ - if ((pbuf = kmalloc(KA_TEMP_BUF_SIZE, GFP_KERNEL)) == NULL) { + if ((pbuf = MALLOC(dhd_pub->osh, KA_TEMP_BUF_SIZE)) == NULL) { DHD_ERROR(("failed to allocate buf with size %d\n", KA_TEMP_BUF_SIZE)); return res; } @@ -14880,7 +15399,10 @@ dhd_dev_stop_mkeep_alive(dhd_pub_t *dhd_pub, uint8 mkeep_alive_id) res = BCME_NOTFOUND; } exit: - kfree(pbuf); + if (pbuf) { + MFREE(dhd_pub->osh, pbuf, KA_TEMP_BUF_SIZE); + pbuf = NULL; + } return res; } #endif /* KEEP_ALIVE */ @@ -14892,7 +15414,7 @@ static void _dhd_apf_lock_local(dhd_info_t *dhd) if (dhd) { mutex_lock(&dhd->dhd_apf_mutex); } -#endif +#endif // endif } static void _dhd_apf_unlock_local(dhd_info_t *dhd) @@ -14901,7 +15423,7 @@ static void _dhd_apf_unlock_local(dhd_info_t *dhd) if (dhd) { mutex_unlock(&dhd->dhd_apf_mutex); } -#endif +#endif // endif } static int @@ -14915,7 +15437,6 @@ __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, char *buf; u32 cmd_len, buf_len; int ifidx, ret; - gfp_t kflags; char cmd[] = "pkt_filter_add"; ifidx = dhd_net2idx(dhd, ndev); @@ -14937,8 +15458,7 @@ __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, buf_len = cmd_len + WL_PKT_FILTER_FIXED_LEN + WL_APF_PROGRAM_FIXED_LEN + program_len; - kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; - buf = kzalloc(buf_len, kflags); + buf = MALLOCZ(dhdp->osh, buf_len); if (unlikely(!buf)) { DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len)); return -ENOMEM; @@ -14963,7 +15483,7 @@ __dhd_apf_add_filter(struct net_device *ndev, uint32 filter_id, } if (buf) { - kfree(buf); + MFREE(dhdp->osh, buf, buf_len); } return ret; } @@ -14978,7 +15498,6 @@ __dhd_apf_config_filter(struct net_device *ndev, uint32 filter_id, char *buf; u32 cmd_len, buf_len; int ifidx, ret; - gfp_t kflags; char cmd[] = "pkt_filter_enable"; ifidx = dhd_net2idx(dhd, ndev); @@ -14990,8 +15509,7 @@ __dhd_apf_config_filter(struct net_device *ndev, uint32 filter_id, cmd_len = sizeof(cmd); buf_len = cmd_len + sizeof(*pkt_filterp); - kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; - buf = kzalloc(buf_len, kflags); + buf = MALLOCZ(dhdp->osh, buf_len); if (unlikely(!buf)) { DHD_ERROR(("%s: MALLOC failure, %d bytes\n", __FUNCTION__, buf_len)); return -ENOMEM; @@ -15019,7 +15537,7 @@ __dhd_apf_config_filter(struct net_device *ndev, uint32 filter_id, exit: if (buf) { - kfree(buf); + MFREE(dhdp->osh, buf, buf_len); } return ret; } @@ -15164,10 +15682,14 @@ dhd_dev_apf_enable_filter(struct net_device *ndev) dhd_info_t *dhd = DHD_DEV_INFO(ndev); dhd_pub_t *dhdp = &dhd->pub; int ret = 0; + bool nan_dp_active = false; DHD_APF_LOCK(ndev); - - if (dhdp->apf_set && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) { +#ifdef WL_NAN + nan_dp_active = wl_cfgnan_is_dp_active(ndev); +#endif /* WL_NAN */ + if (dhdp->apf_set && (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE) && + !nan_dp_active)) { ret = __dhd_apf_config_filter(ndev, PKT_FILTER_APF_ID, PKT_FILTER_MODE_FORWARD_ON_MATCH, TRUE); } @@ -15239,13 +15761,13 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event) rtnl_lock(); dev_close(dev); rtnl_unlock(); -#endif /* !CUSTOMER_HW4 & !CUSTOMER_HW2_INTERPOSER */ +#endif // endif #if defined(WL_WIRELESS_EXT) wl_iw_send_priv_event(dev, "HANG"); -#endif +#endif // endif #if defined(WL_CFG80211) wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); -#endif +#endif // endif } } @@ -15264,7 +15786,32 @@ EXPORT_SYMBOL(dhd_host_recover_link); int dhd_os_send_hang_message(dhd_pub_t *dhdp) { int ret = 0; + if (dhdp) { +#ifdef WL_CFG80211 + struct net_device *primary_ndev; + struct bcm_cfg80211 *cfg; + + primary_ndev = dhd_linux_get_primary_netdev(dhdp); + if (!primary_ndev) { + DHD_ERROR(("%s: Cannot find primary netdev\n", + __FUNCTION__)); + return -ENODEV; + } + + cfg = wl_get_cfg(primary_ndev); + if (!cfg) { + DHD_ERROR(("%s: Cannot find cfg\n", __FUNCTION__)); + return -EINVAL; + } + + /* Skip sending HANG event to framework if driver is not ready */ + if (!wl_get_drv_status(cfg, READY, primary_ndev)) { + DHD_ERROR(("%s: device is not ready\n", __FUNCTION__)); + return -ENODEV; + } +#endif /* WL_CFG80211 */ + #if defined(DHD_HANG_SEND_UP_TEST) if (dhdp->req_hang_type) { DHD_ERROR(("%s, Clear HANG test request 0x%x\n", @@ -15295,7 +15842,7 @@ int dhd_os_send_hang_message(dhd_pub_t *dhdp) dhdp->hang_was_sent = 1; #ifdef BT_OVER_SDIO dhdp->is_bt_recovery_required = TRUE; -#endif +#endif // endif dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dhdp, DHD_WQ_WORK_HANG_MSG, dhd_hang_process, DHD_WQ_WORK_PRIORITY_HIGH); } @@ -15318,7 +15865,7 @@ int net_os_send_hang_message(struct net_device *dev) ret = dhd_os_send_hang_message(&dhd->pub); #else ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); -#endif +#endif // endif #ifdef BT_OVER_SDIO } DHD_ERROR(("%s: HANG -> Reset BT\n", __FUNCTION__)); @@ -15360,7 +15907,6 @@ int net_os_send_hang_message_reason(struct net_device *dev, const char *string_n } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */ - int dhd_net_wifi_platform_set_power(struct net_device *dev, bool on, unsigned long delay_msec) { dhd_info_t *dhd = DHD_DEV_INFO(dev); @@ -15416,64 +15962,26 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec, bool notif dhd_info_t *dhd = DHD_DEV_INFO(dev); #ifdef WL_CFG80211 struct bcm_cfg80211 *cfg = wl_get_cfg(dev); -#endif +#endif // endif if (dhd && dhd->pub.up) { memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); -#ifdef DHD_DISABLE_VHTMODE - dhd_disable_vhtmode(&dhd->pub); -#endif /* DHD_DISABLE_VHTMODE */ - #ifdef WL_CFG80211 wl_update_wiphybands(cfg, notify); -#endif - } -} - -#ifdef DHD_DISABLE_VHTMODE -void -dhd_disable_vhtmode(dhd_pub_t *dhd) -{ - int ret = 0; - uint32 vhtmode = FALSE; - ret = dhd_iovar(dhd, 0, "vhtmode", (char *)&vhtmode, sizeof(vhtmode), NULL, 0, TRUE); - if (ret < 0) { - DHD_ERROR(("%s Set vhtmode 0 failed %d\n", __FUNCTION__, ret)); - - if (ret == BCME_NOTDOWN) { - uint wl_down = 1; - ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, - (char *)&wl_down, sizeof(wl_down), TRUE, 0); - if (ret) { - DHD_ERROR(("%s WL_DOWN Fail ret %d\n", __FUNCTION__, ret)); - return; - } - - ret = dhd_iovar(dhd, 0, "vhtmode", (char *)&vhtmode, - sizeof(vhtmode), NULL, 0, TRUE); - DHD_ERROR(("%s Set vhtmode %d, ret %d\n", __FUNCTION__, vhtmode, ret)); - - ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, - (char *)&wl_down, sizeof(wl_down), TRUE, 0); - if (ret) { - DHD_ERROR(("%s WL_UP Fail ret %d\n", __FUNCTION__, ret)); - } - } +#endif // endif } } -#endif /* DHD_DISABLE_VHTMODE */ - void dhd_bus_band_set(struct net_device *dev, uint band) { dhd_info_t *dhd = DHD_DEV_INFO(dev); #ifdef WL_CFG80211 struct bcm_cfg80211 *cfg = wl_get_cfg(dev); -#endif +#endif // endif if (dhd && dhd->pub.up) { #ifdef WL_CFG80211 wl_update_wiphybands(cfg, true); -#endif +#endif // endif } } @@ -15495,7 +16003,7 @@ int dhd_net_set_fw_path(struct net_device *dev, char *fw) DHD_INFO(("GOT STA FIRMWARE\n")); ap_fw_loaded = FALSE; } -#endif +#endif // endif return 0; } @@ -15516,7 +16024,7 @@ static void dhd_net_if_lock_local(dhd_info_t *dhd) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) if (dhd) mutex_lock(&dhd->dhd_net_if_mutex); -#endif +#endif // endif } static void dhd_net_if_unlock_local(dhd_info_t *dhd) @@ -15524,7 +16032,7 @@ static void dhd_net_if_unlock_local(dhd_info_t *dhd) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) if (dhd) mutex_unlock(&dhd->dhd_net_if_mutex); -#endif +#endif // endif } static void dhd_suspend_lock(dhd_pub_t *pub) @@ -15533,7 +16041,7 @@ static void dhd_suspend_lock(dhd_pub_t *pub) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (dhd) mutex_lock(&dhd->dhd_suspend_mutex); -#endif +#endif // endif } static void dhd_suspend_unlock(dhd_pub_t *pub) @@ -15542,7 +16050,7 @@ static void dhd_suspend_unlock(dhd_pub_t *pub) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (dhd) mutex_unlock(&dhd->dhd_suspend_mutex); -#endif +#endif // endif } unsigned long dhd_os_general_spin_lock(dhd_pub_t *pub) @@ -15599,6 +16107,27 @@ dhd_os_spin_unlock(void *lock, unsigned long flags) spin_unlock_irqrestore((spinlock_t *)lock, flags); } +void * +dhd_os_dbgring_lock_init(osl_t *osh) +{ + struct mutex *mtx = NULL; + + mtx = MALLOCZ(osh, sizeof(*mtx)); + if (mtx) + mutex_init(mtx); + + return mtx; +} + +void +dhd_os_dbgring_lock_deinit(osl_t *osh, void *mtx) +{ + if (mtx) { + mutex_destroy(mtx); + MFREE(osh, mtx, sizeof(struct mutex)); + } +} + static int dhd_get_pend_8021x_cnt(dhd_info_t *dhd) { @@ -15649,7 +16178,6 @@ int write_file(const char * file_name, uint32 flags, uint8 *buf, int size) fp = filp_open(file_name, flags, 0664); if (IS_ERR(fp)) { DHD_ERROR(("open file error, err = %ld\n", PTR_ERR(fp))); - ret = -1; goto exit; } @@ -15678,11 +16206,11 @@ exit: return ret; } -#endif +#endif // endif #ifdef DHD_DEBUG static void -dhd_convert_memdump_type_to_str(uint32 type, char *buf) +dhd_convert_memdump_type_to_str(uint32 type, char *buf, int substr_type) { char *type_str = NULL; @@ -15708,14 +16236,17 @@ dhd_convert_memdump_type_to_str(uint32 type, char *buf) case DUMP_TYPE_SCAN_TIMEOUT: type_str = "SCAN_timeout"; break; - case DUMP_TYPE_JOIN_TIMEOUT: - type_str = "JOIN_timeout"; - break; case DUMP_TYPE_SCAN_BUSY: type_str = "SCAN_Busy"; break; case DUMP_TYPE_BY_SYSDUMP: - type_str = "BY_SYSDUMP_USER"; + if (substr_type == CMD_UNWANTED) { + type_str = "BY_SYSDUMP_FORUSER_unwanted"; + } else if (substr_type == CMD_DISCONNECTED) { + type_str = "BY_SYSDUMP_FORUSER_disconnected"; + } else { + type_str = "BY_SYSDUMP_FORUSER"; + } break; case DUMP_TYPE_BY_LIVELOCK: type_str = "BY_LIVELOCK"; @@ -15726,29 +16257,26 @@ dhd_convert_memdump_type_to_str(uint32 type, char *buf) case DUMP_TYPE_AP_ABNORMAL_ACCESS: type_str = "INVALID_ACCESS"; break; - case DUMP_TYPE_CFG_VENDOR_TRIGGERED: - type_str = "CFG_VENDOR_TRIGGERED"; - break; case DUMP_TYPE_RESUMED_ON_TIMEOUT_RX: type_str = "ERROR_RX_TIMED_OUT"; break; case DUMP_TYPE_RESUMED_ON_TIMEOUT_TX: type_str = "ERROR_TX_TIMED_OUT"; break; - case DUMP_TYPE_RESUMED_ON_INVALID_RING_RDWR: + case DUMP_TYPE_CFG_VENDOR_TRIGGERED: + type_str = "CFG_VENDOR_TRIGGERED"; + break; + case DUMP_TYPE_RESUMED_ON_INVALID_RING_RDWR: type_str = "BY_INVALID_RING_RDWR"; break; - case DUMP_TYPE_DONGLE_HOST_EVENT: - type_str = "BY_DONGLE_HOST_EVENT"; + case DUMP_TYPE_IFACE_OP_FAILURE: + type_str = "BY_IFACE_OP_FAILURE"; break; case DUMP_TYPE_TRANS_ID_MISMATCH: type_str = "BY_TRANS_ID_MISMATCH"; break; - case DUMP_TYPE_HANG_ON_IFACE_OP_FAIL: - type_str = "HANG_IFACE_OP_FAIL"; - break; #ifdef DEBUG_DNGL_INIT_FAIL - case DUMP_TYPE_DONGLE_INIT_FAILURE; + case DUMP_TYPE_DONGLE_INIT_FAILURE: type_str = "DONGLE_INIT_FAIL"; break; #endif /* DEBUG_DNGL_INIT_FAIL */ @@ -15757,6 +16285,12 @@ dhd_convert_memdump_type_to_str(uint32 type, char *buf) type_str = "READ_SHM_FAIL"; break; #endif /* SUPPORT_LINKDOWN_RECOVERY */ + case DUMP_TYPE_DONGLE_HOST_EVENT: + type_str = "BY_DONGLE_HOST_EVENT"; + break; + case DUMP_TYPE_SMMU_FAULT: + type_str = "SMMU_FAULT"; + break; default: type_str = "Unknown_type"; break; @@ -15779,11 +16313,11 @@ write_dump_to_file(dhd_pub_t *dhd, uint8 *buf, int size, char *fname) memset(memdump_path, 0, sizeof(memdump_path)); memset(memdump_type, 0, sizeof(memdump_type)); do_gettimeofday(&curtime); - dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type); + dhd_convert_memdump_type_to_str(dhd->memdump_type, memdump_type, dhd->debug_dump_subcmd); #ifdef CUSTOMER_HW4_DEBUG - snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_%ld.%ld", - DHD_COMMON_DUMP_PATH, fname, memdump_type, - (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); + get_debug_dump_time(dhd->debug_dump_time_str); + snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_" "%s", + DHD_COMMON_DUMP_PATH, fname, memdump_type, dhd->debug_dump_time_str); file_mode = O_CREAT | O_WRONLY | O_SYNC; #elif (defined(BOARD_PANDA) || defined(__ARM_ARCH_7A__)) snprintf(memdump_path, sizeof(memdump_path), "%s%s_%s_%ld.%ld", @@ -15818,9 +16352,19 @@ write_dump_to_file(dhd_pub_t *dhd, uint8 *buf, int size, char *fname) /* print SOCRAM dump file path */ DHD_ERROR(("%s: file_path = %s\n", __FUNCTION__, memdump_path)); +#ifdef DHD_LOG_DUMP + dhd_print_buf_addr("write_dump_to_file", buf, size); +#endif /* DHD_LOG_DUMP */ + /* Write file */ ret = write_file(memdump_path, file_mode, buf, size); +#ifdef DHD_DUMP_MNGR + if (ret == BCME_OK) { + dhd_dump_file_manage_enqueue(dhd, memdump_path, fname); + } +#endif /* DHD_DUMP_MNGR */ + return ret; } #endif /* DHD_DEBUG */ @@ -15842,7 +16386,7 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub) if (dhd->wakelock_ctrl_timeout_enable) wake_lock_timeout(&dhd->wl_ctrlwake, msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)/2); -#endif +#endif // endif dhd->wakelock_rx_timeout_enable = 0; dhd->wakelock_ctrl_timeout_enable = 0; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); @@ -15899,7 +16443,7 @@ int dhd_os_wake_lock_ctrl_timeout_cancel(dhd_pub_t *pub) #ifdef CONFIG_HAS_WAKELOCK if (wake_lock_active(&dhd->wl_ctrlwake)) wake_unlock(&dhd->wl_ctrlwake); -#endif +#endif // endif spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return 0; @@ -15925,7 +16469,6 @@ int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) return ret; } - #if defined(DHD_TRACE_WAKE_LOCK) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) #include @@ -15933,7 +16476,6 @@ int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) #include #endif /* KERNEL_VER >= KERNEL_VERSION(3, 7, 0) */ - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) /* Define 2^5 = 32 bucket size hash table */ DEFINE_HASHTABLE(wklock_history, 5); @@ -15975,7 +16517,6 @@ static struct wk_trace_record *find_wklock_entry(unsigned long addr) return NULL; } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) #define HASH_ADD(hashtable, node, key) \ do { \ @@ -16128,7 +16669,7 @@ int dhd_os_wake_lock(dhd_pub_t *pub) wake_lock(&dhd->wl_wifi); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_stay_awake(pub); -#endif +#endif // endif } #ifdef DHD_TRACE_WAKE_LOCK if (trace_wklock_onoff) { @@ -16152,7 +16693,7 @@ void dhd_event_wake_lock(dhd_pub_t *pub) wake_lock(&dhd->wl_evtwake); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_stay_awake(pub); -#endif +#endif // endif } } @@ -16212,7 +16753,7 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) wake_unlock(&dhd->wl_wifi); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_relax(pub); -#endif +#endif // endif } ret = dhd->wakelock_counter; } @@ -16230,7 +16771,7 @@ void dhd_event_wake_unlock(dhd_pub_t *pub) wake_unlock(&dhd->wl_evtwake); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_relax(pub); -#endif +#endif // endif } } @@ -16281,7 +16822,7 @@ int dhd_os_check_wakelock(dhd_pub_t *pub) #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) if (dhd && (dhd->wakelock_counter > 0) && dhd_bus_dev_pm_enabled(pub)) return 1; -#endif +#endif // endif return 0; } @@ -16360,7 +16901,7 @@ int dhd_os_wd_wake_lock(dhd_pub_t *pub) #ifdef CONFIG_HAS_WAKELOCK /* if wakelock_wd_counter was never used : lock it at once */ wake_lock(&dhd->wl_wdwake); -#endif +#endif // endif } dhd->wakelock_wd_counter++; ret = dhd->wakelock_wd_counter; @@ -16382,7 +16923,7 @@ int dhd_os_wd_wake_unlock(dhd_pub_t *pub) if (!dhd->waive_wakelock) { #ifdef CONFIG_HAS_WAKELOCK wake_unlock(&dhd->wl_wdwake); -#endif +#endif // endif } } spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); @@ -16510,13 +17051,13 @@ int dhd_os_wake_lock_restore(dhd_pub_t *pub) wake_lock(&dhd->wl_wifi); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_stay_awake(&dhd->pub); -#endif +#endif // endif } else if (dhd->wakelock_before_waive > 0 && dhd->wakelock_counter == 0) { #ifdef CONFIG_HAS_WAKELOCK wake_unlock(&dhd->wl_wifi); #elif defined(BCMSDIO) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) dhd_bus_dev_pm_relax(&dhd->pub); -#endif +#endif // endif } dhd->wakelock_before_waive = 0; exit: @@ -16531,6 +17072,7 @@ void dhd_os_wake_lock_init(struct dhd_info *dhd) dhd->wakelock_counter = 0; dhd->wakelock_rx_timeout_enable = 0; dhd->wakelock_ctrl_timeout_enable = 0; + /* wakelocks prevent a system from going into a low power state */ #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"); @@ -16676,13 +17218,13 @@ int dhd_deepsleep(struct net_device *dev, int flag) #endif /* PKT_FILTER_SUPPORT */ /* Disable MPC */ powervar = 0; - dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, 0, - TRUE); + ret = dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, + 0, TRUE); /* Enable Deepsleep */ powervar = 1; - dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, sizeof(powervar), NULL, - 0, TRUE); + ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, sizeof(powervar), + NULL, 0, TRUE); break; case 0: /* Deepsleep Off */ @@ -16691,8 +17233,8 @@ int dhd_deepsleep(struct net_device *dev, int flag) /* Disable Deepsleep */ for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) { powervar = 0; - dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, sizeof(powervar), - NULL, 0, TRUE); + ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, + sizeof(powervar), NULL, 0, TRUE); ret = dhd_iovar(dhdp, 0, "deepsleep", (char *)&powervar, sizeof(powervar), iovbuf, sizeof(iovbuf), FALSE); @@ -16710,8 +17252,8 @@ int dhd_deepsleep(struct net_device *dev, int flag) /* Enable MPC */ powervar = 1; - dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, 0, - TRUE); + ret = dhd_iovar(dhdp, 0, "mpc", (char *)&powervar, sizeof(powervar), NULL, + 0, TRUE); break; } @@ -16809,7 +17351,6 @@ dhd_dbg_state_read(struct file *file, char __user *ubuf, return rval; } - static ssize_t dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { @@ -16834,7 +17375,6 @@ dhd_debugfs_write(struct file *file, const char __user *ubuf, size_t count, loff return count; } - loff_t dhd_debugfs_lseek(struct file *file, loff_t off, int whence) { @@ -16893,7 +17433,6 @@ void dhd_dbgfs_remove(void) } #endif /* BCMDBGFS */ - #ifdef CUSTOM_SET_CPUCORE void dhd_set_cpucore(dhd_pub_t *dhd, int set) { @@ -17082,7 +17621,11 @@ done: void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size) { + unsigned long flags = 0; dhd_dump_t *dump = NULL; + dhd_info_t *dhd_info = NULL; + + dhd_info = (dhd_info_t *)dhdp->info; dump = (dhd_dump_t *)MALLOC(dhdp->osh, sizeof(dhd_dump_t)); if (dump == NULL) { DHD_ERROR(("%s: dhd dump memory allocation failed\n", __FUNCTION__)); @@ -17101,18 +17644,22 @@ void dhd_schedule_memdump(dhd_pub_t *dhdp, uint8 *buf, uint32 size) if (dhdp->memdump_enabled == DUMP_MEMONLY) { BUG_ON(1); } - -#ifdef DHD_LOG_DUMP - if (dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) { - dhd_schedule_log_dump(dhdp); - } -#endif /* DHD_LOG_DUMP */ #ifdef DEBUG_DNGL_INIT_FAIL if (dhdp->memdump_type == DUMP_TYPE_DONGLE_INIT_FAILURE) { + dhd_info->scheduled_memdump = FALSE; dhd_mem_dump((void *)dhdp->info, (void *)dump, 0); return; } #endif /* DEBUG_DNGL_INIT_FAIL */ + + dhd_info->scheduled_memdump = TRUE; + /* bus busy bit for mem dump will be cleared in mem dump + * work item context, after mem dump file is written + */ + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_SET_IN_MEMDUMP(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + DHD_ERROR(("%s: scheduling mem dump.. \n", __FUNCTION__)); dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, (void *)dump, DHD_WQ_WORK_SOC_RAM_DUMP, dhd_mem_dump, DHD_WQ_WORK_PRIORITY_HIGH); } @@ -17120,21 +17667,82 @@ static void dhd_mem_dump(void *handle, void *event_info, u8 event) { dhd_info_t *dhd = handle; + dhd_pub_t *dhdp = NULL; dhd_dump_t *dump = event_info; + unsigned long flags = 0; + + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); if (!dhd) { DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); return; } + dhdp = &dhd->pub; + + DHD_GENERAL_LOCK(dhdp, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { + DHD_GENERAL_UNLOCK(dhdp, flags); + DHD_ERROR(("%s: bus is down! can't collect mem dump. \n", __FUNCTION__)); + goto exit; + } + DHD_GENERAL_UNLOCK(dhdp, flags); + if (!dump) { DHD_ERROR(("%s: dump is NULL\n", __FUNCTION__)); - return; + goto exit; } if (write_dump_to_file(&dhd->pub, dump->buf, dump->bufsize, "mem_dump")) { DHD_ERROR(("%s: writing SoC_RAM dump to the file failed\n", __FUNCTION__)); +#ifdef DHD_DEBUG_UART dhd->pub.memdump_success = FALSE; +#endif /* DHD_DEBUG_UART */ + } + + /* directly call dhd_log_dump for debug_dump collection from the mem_dump work queue + * context, no need to schedule another work queue for log dump. In case of + * user initiated DEBUG_DUMP wpa_cli command (DUMP_TYPE_BY_SYSDUMP), + * cfg layer is itself scheduling the log_dump work queue. + * that path is not disturbed. If 'dhd_mem_dump' is called directly then we will not + * collect debug_dump as it may be called from non-sleepable context. + */ +#ifdef DHD_LOG_DUMP + if (dhd->scheduled_memdump && + dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) { + log_dump_type_t *flush_type = MALLOCZ(dhdp->osh, + sizeof(log_dump_type_t)); + if (flush_type) { + *flush_type = DLD_BUF_TYPE_ALL; + DHD_ERROR(("%s: calling log dump.. \n", __FUNCTION__)); + dhd_log_dump(dhd, flush_type, 0); + } + } +#endif /* DHD_LOG_DUMP */ + +#ifdef DHD_PKT_LOGGING + copy_debug_dump_time(dhdp->debug_dump_time_pktlog_str, dhdp->debug_dump_time_str); +#endif /* DHD_PKT_LOGGING */ + clear_debug_dump_time(dhdp->debug_dump_time_str); + + /* before calling bug on, wait for other logs to be dumped. + * we cannot wait in case dhd_mem_dump is called directly + * as it may not be in a sleepable context + */ + if (dhd->scheduled_memdump) { + uint bitmask = 0; + int timeleft = 0; +#ifdef DHD_SSSR_DUMP + bitmask |= DHD_BUS_BUSY_IN_SSSRDUMP; +#endif // endif + if (bitmask != 0) { + timeleft = dhd_os_busbusy_wait_bitmask(dhdp, + &dhdp->dhd_bus_busy_state, bitmask, 0); + if ((timeleft == 0) || (timeleft == 1)) { + DHD_ERROR(("%s:Timed out on sssr dump,dhd_bus_busy_state=0x%x\n", + __FUNCTION__, dhdp->dhd_bus_busy_state)); + } + } } if (dhd->pub.memdump_enabled == DUMP_MEMFILE_BUGON && @@ -17144,16 +17752,27 @@ dhd_mem_dump(void *handle, void *event_info, u8 event) #ifdef DHD_DEBUG_UART dhd->pub.memdump_success == TRUE && #endif /* DHD_DEBUG_UART */ +#ifdef DNGL_EVENT_SUPPORT + dhd->pub.memdump_type != DUMP_TYPE_DONGLE_HOST_EVENT && +#endif /* DNGL_EVENT_SUPPORT */ dhd->pub.memdump_type != DUMP_TYPE_CFG_VENDOR_TRIGGERED) { #ifdef SHOW_LOGTRACE /* Wait till event_log_dispatcher_work finishes */ - cancel_work_sync(&dhd->event_log_dispatcher_work); + cancel_delayed_work_sync(&dhd->event_log_dispatcher_work); #endif /* SHOW_LOGTRACE */ BUG_ON(1); } - MFREE(dhd->pub.osh, dump, sizeof(dhd_dump_t)); + +exit: + if (dump) + MFREE(dhd->pub.osh, dump, sizeof(dhd_dump_t)); + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_CLEAR_IN_MEMDUMP(&dhd->pub); + dhd_os_busbusy_wake(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + dhd->scheduled_memdump = FALSE; } #endif /* DHD_FW_COREDUMP */ @@ -17167,6 +17786,9 @@ dhd_sssr_dump(void *handle, void *event_info, u8 event) int i; char before_sr_dump[128]; char after_sr_dump[128]; + unsigned long flags = 0; + + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); if (!dhd) { DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); @@ -17175,6 +17797,14 @@ dhd_sssr_dump(void *handle, void *event_info, u8 event) dhdp = &dhd->pub; + DHD_GENERAL_LOCK(dhdp, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { + DHD_GENERAL_UNLOCK(dhdp, flags); + DHD_ERROR(("%s: bus is down! can't collect sssr dump. \n", __FUNCTION__)); + goto exit; + } + DHD_GENERAL_UNLOCK(dhdp, flags); + for (i = 0; i < MAX_NUM_D11CORES; i++) { /* Init file name */ memset(before_sr_dump, 0, sizeof(before_sr_dump)); @@ -17201,27 +17831,41 @@ dhd_sssr_dump(void *handle, void *event_info, u8 event) } } - if (dhdp->sssr_vasip_buf_before) { - if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_vasip_buf_before, - dhdp->sssr_reg_info.vasip_regs.vasip_sr_size, "sssr_vasip_before_SR")) { - DHD_ERROR(("%s: writing SSSR VASIP dump before to the file failed\n", + if (dhdp->sssr_dig_buf_before) { + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_dig_buf_before, + dhdp->sssr_reg_info.vasip_regs.vasip_sr_size, "sssr_dig_before_SR")) { + DHD_ERROR(("%s: writing SSSR Dig dump before to the file failed\n", __FUNCTION__)); } } - if (dhdp->sssr_vasip_buf_after) { - if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_vasip_buf_after, - dhdp->sssr_reg_info.vasip_regs.vasip_sr_size, "sssr_vasip_after_SR")) { - DHD_ERROR(("%s: writing SSSR VASIP dump after to the file failed\n", + if (dhdp->sssr_dig_buf_after) { + if (write_dump_to_file(dhdp, (uint8 *)dhdp->sssr_dig_buf_after, + dhdp->sssr_reg_info.vasip_regs.vasip_sr_size, "sssr_dig_after_SR")) { + DHD_ERROR(("%s: writing SSSR Dig VASIP dump after to the file failed\n", __FUNCTION__)); } } +exit: + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_CLEAR_IN_SSSRDUMP(dhdp); + dhd_os_busbusy_wake(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); } void dhd_schedule_sssr_dump(dhd_pub_t *dhdp) { + unsigned long flags = 0; + /* bus busy bit for sssr dump will be cleared in sssr dump + * work item context, after sssr dump files are created + */ + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_SET_IN_SSSRDUMP(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + + DHD_ERROR(("%s: scheduling sssr dump.. \n", __FUNCTION__)); dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, NULL, DHD_WQ_WORK_SSSR_DUMP, dhd_sssr_dump, DHD_WQ_WORK_PRIORITY_HIGH); } @@ -17232,27 +17876,194 @@ static void dhd_log_dump(void *handle, void *event_info, u8 event) { dhd_info_t *dhd = handle; + log_dump_type_t *type = (log_dump_type_t *)event_info; - if (!dhd) { + if (!dhd || !type) { DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); return; } - if (do_dhd_log_dump(&dhd->pub)) { +#ifdef WL_CFG80211 + /* flush the fw side logs */ + wl_flush_fw_log_buffer(dhd_linux_get_primary_netdev(&dhd->pub), + FW_LOGSET_MASK_ALL); +#endif // endif + /* there are currently 3 possible contexts from which + * log dump can be scheduled - + * 1.TRAP 2.supplicant DEBUG_DUMP pvt driver command + * 3.HEALTH CHECK event + * The concise debug info buffer is a shared resource + * and in case a trap is one of the contexts then both the + * scheduled work queues need to run because trap data is + * essential for debugging. Hence a mutex lock is acquired + * before calling do_dhd_log_dump(). + */ + DHD_ERROR(("%s: calling log dump.. \n", __FUNCTION__)); + dhd_os_logdump_lock(&dhd->pub); + DHD_OS_WAKE_LOCK(&dhd->pub); + if (do_dhd_log_dump(&dhd->pub, type) != BCME_OK) { DHD_ERROR(("%s: writing debug dump to the file failed\n", __FUNCTION__)); - return; } + DHD_OS_WAKE_UNLOCK(&dhd->pub); + dhd_os_logdump_unlock(&dhd->pub); } -void dhd_schedule_log_dump(dhd_pub_t *dhdp) +void dhd_schedule_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type) { + DHD_ERROR(("%s: scheduling log dump.. \n", __FUNCTION__)); dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, - (void*)NULL, DHD_WQ_WORK_DHD_LOG_DUMP, + (void*)type, DHD_WQ_WORK_DHD_LOG_DUMP, dhd_log_dump, DHD_WQ_WORK_PRIORITY_HIGH); } +static void +dhd_print_buf_addr(char *name, void *buf, unsigned int size) +{ +#if defined(CONFIG_ARM64) + DHD_ERROR(("-------- %s: buf(va)=%llx, buf(pa)=%llx, bufsize=%d\n", + name, (uint64)buf, (uint64)__virt_to_phys((ulong)buf), size)); +#elif defined(__ARM_ARCH_7A__) + DHD_ERROR(("-------- %s: buf(va)=%x, buf(pa)=%x, bufsize=%d\n", + name, (uint32)buf, (uint32)__virt_to_phys((ulong)buf), size)); +#endif /* __ARM_ARCH_7A__ */ +} + +static void +dhd_log_dump_buf_addr(dhd_pub_t *dhdp, log_dump_type_t *type) +{ + int i; + unsigned long wr_size = 0; + struct dhd_log_dump_buf *dld_buf = &g_dld_buf[0]; + size_t log_size = 0; + char buf_name[DHD_PRINT_BUF_NAME_LEN]; + dhd_dbg_ring_t *ring = NULL; + + BCM_REFERENCE(ring); + + for (i = 0; i < DLD_BUFFER_NUM; i++) { + dld_buf = &g_dld_buf[i]; + log_size = (unsigned long)dld_buf->max - + (unsigned long)dld_buf->buffer; + if (dld_buf->wraparound) { + wr_size = log_size; + } else { + wr_size = (unsigned long)dld_buf->present - + (unsigned long)dld_buf->front; + } + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d]", i); + dhd_print_buf_addr(buf_name, dld_buf, dld_buf_size[i]); + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] buffer", i); + dhd_print_buf_addr(buf_name, dld_buf->buffer, wr_size); + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] present", i); + dhd_print_buf_addr(buf_name, dld_buf->present, wr_size); + scnprintf(buf_name, sizeof(buf_name), "dlb_buf[%d] front", i); + dhd_print_buf_addr(buf_name, dld_buf->front, wr_size); + } + +#ifdef DEBUGABILITY_ECNTRS_LOGGING + /* periodic flushing of ecounters is NOT supported */ + if (*type == DLD_BUF_TYPE_ALL && + logdump_ecntr_enable && + dhdp->ecntr_dbg_ring) { + + ring = (dhd_dbg_ring_t *)dhdp->ecntr_dbg_ring; + dhd_print_buf_addr("ecntr_dbg_ring", ring, LOG_DUMP_ECNTRS_MAX_BUFSIZE); + dhd_print_buf_addr("ecntr_dbg_ring ring_buf", ring->ring_buf, + LOG_DUMP_ECNTRS_MAX_BUFSIZE); + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + + if (dhdp->dongle_trap_occured && dhdp->extended_trap_data) { + dhd_print_buf_addr("extended_trap_data", dhdp->extended_trap_data, + BCMPCIE_EXT_TRAP_DATA_MAXLEN); + } + +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) + /* if health check event was received */ + if (dhdp->memdump_type == DUMP_TYPE_DONGLE_HOST_EVENT) { + dhd_print_buf_addr("health_chk_event_data", dhdp->health_chk_event_data, + HEALTH_CHK_BUF_SIZE); + } +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT */ + + /* append the concise debug information */ + if (dhdp->concise_dbg_buf) { + dhd_print_buf_addr("concise_dbg_buf", dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); + } +} + +#ifdef CUSTOMER_HW4_DEBUG +static void +dhd_log_dump_print_to_kmsg(char *bufptr, unsigned long len) +{ + char tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE + 1]; + char *end = NULL; + unsigned long plen = 0; + + if (!bufptr || !len) + return; + + memset(tmp_buf, 0, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE); + end = bufptr + len; + while (bufptr < end) { + if ((bufptr + DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE) < end) { + memcpy(tmp_buf, bufptr, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE); + tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE] = '\0'; + printf("%s", tmp_buf); + bufptr += DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE; + } else { + plen = (unsigned long)end - (unsigned long)bufptr; + memcpy(tmp_buf, bufptr, plen); + tmp_buf[plen] = '\0'; + printf("%s", tmp_buf); + bufptr += plen; + } + } +} + +static void +dhd_log_dump_print_tail(dhd_pub_t *dhdp, + struct dhd_log_dump_buf *dld_buf, + uint tail_len) +{ + char *flush_ptr1 = NULL, *flush_ptr2 = NULL; + unsigned long len_flush1 = 0, len_flush2 = 0; + unsigned long flags = 0; + + /* need to hold the lock before accessing 'present' and 'remain' ptrs */ + spin_lock_irqsave(&dld_buf->lock, flags); + flush_ptr1 = dld_buf->present - tail_len; + if (flush_ptr1 >= dld_buf->front) { + /* tail content is within the buffer */ + flush_ptr2 = NULL; + len_flush1 = tail_len; + } else if (dld_buf->wraparound) { + /* tail content spans the buffer length i.e, wrap around */ + flush_ptr1 = dld_buf->front; + len_flush1 = (unsigned long)dld_buf->present - (unsigned long)flush_ptr1; + len_flush2 = (unsigned long)tail_len - len_flush1; + flush_ptr2 = (char *)((unsigned long)dld_buf->max - + (unsigned long)len_flush2); + } else { + /* amt of logs in buffer is less than tail size */ + flush_ptr1 = dld_buf->front; + flush_ptr2 = NULL; + len_flush1 = (unsigned long)dld_buf->present - (unsigned long)dld_buf->front; + } + spin_unlock_irqrestore(&dld_buf->lock, flags); + + printf("\n================= LOG_DUMP tail =================\n"); + if (flush_ptr2) { + dhd_log_dump_print_to_kmsg(flush_ptr2, len_flush2); + } + dhd_log_dump_print_to_kmsg(flush_ptr1, len_flush1); + printf("\n===================================================\n"); +} +#endif /* CUSTOMER_HW4_DEBUG */ + +/* Must hold 'dhd_os_logdump_lock' before calling this function ! */ static int -do_dhd_log_dump(dhd_pub_t *dhdp) +do_dhd_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type) { int ret = 0, i = 0; struct file *fp = NULL; @@ -17260,23 +18071,70 @@ do_dhd_log_dump(dhd_pub_t *dhdp) loff_t pos = 0; unsigned int wr_size = 0; char dump_path[128]; - struct timeval curtime; uint32 file_mode; unsigned long flags = 0; struct dhd_log_dump_buf *dld_buf = &g_dld_buf[0]; + size_t log_size = 0; + size_t fspace_remain = 0; + struct kstat stat; + char time_str[128]; + char *ts = NULL; + uint32 remain_len = 0; + log_dump_section_hdr_t sec_hdr; + dhd_info_t *dhd_info = NULL; + + DHD_ERROR(("%s: ENTER \n", __FUNCTION__)); + + /* if dhdp is null, its extremely unlikely that log dump will be scheduled + * so not freeing 'type' here is ok, even if we want to free 'type' + * we cannot do so, since 'dhdp->osh' is unavailable + * as dhdp is null + */ + if (!dhdp || !type) { + if (dhdp) { + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp); + dhd_os_busbusy_wake(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + } + return BCME_ERROR; + } - const char *pre_strs = - "-------------------- General log ---------------------------\n"; - - const char *post_strs = - "-------------------- Specific log --------------------------\n"; + DHD_GENERAL_LOCK(dhdp, flags); + if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhdp)) { + DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp); + dhd_os_busbusy_wake(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + MFREE(dhdp->osh, type, sizeof(*type)); + DHD_ERROR(("%s: bus is down! can't collect log dump. \n", __FUNCTION__)); + return BCME_ERROR; + } + DHD_BUS_BUSY_SET_IN_LOGDUMP(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); - if (!dhdp) { - return -1; + dhd_info = (dhd_info_t *)dhdp->info; + /* in case of trap get preserve logs from ETD */ +#if defined(BCMPCIE) && defined(DEBUGABILITY_ETD_PRSRV_LOGS) + if (dhdp->dongle_trap_occured && + dhdp->extended_trap_data) { + dhdpcie_get_etd_preserve_logs(dhdp, (uint8 *)dhdp->extended_trap_data, + &dhd_info->event_data); } +#endif /* BCMPCIE */ - DHD_ERROR(("DHD version: %s\n", dhd_version)); - DHD_ERROR(("F/W version: %s\n", fw_version)); + /* flush the event work items to get any fw events/logs + * flush_work is a blocking call + */ + flush_delayed_work(&dhd_info->event_log_dispatcher_work); + +#ifdef CUSTOMER_HW4_DEBUG + /* print last 'x' KB of preserve buffer data to kmsg console + * this is to address cases where debug_dump is not + * available for debugging + */ + dhd_log_dump_print_tail(dhdp, + &g_dld_buf[DLD_BUF_TYPE_PRESERVE], logdump_prsrv_tailsize); +#endif /* CUSTOMER_HW4_DEBUG */ /* change to KERNEL_DS address limit */ old_fs = get_fs(); @@ -17284,13 +18142,47 @@ do_dhd_log_dump(dhd_pub_t *dhdp) /* Init file name */ memset(dump_path, 0, sizeof(dump_path)); - do_gettimeofday(&curtime); - snprintf(dump_path, sizeof(dump_path), "%s_%ld.%ld", - DHD_COMMON_DUMP_PATH "debug_dump_USER", - (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); - file_mode = O_CREAT | O_WRONLY | O_SYNC; + switch (dhdp->debug_dump_subcmd) { + case CMD_UNWANTED: + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE + DHD_DUMP_SUBSTR_UNWANTED); + break; + case CMD_DISCONNECTED: + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE + DHD_DUMP_SUBSTR_DISCONNECTED); + break; + default: + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_COMMON_DUMP_PATH DHD_DEBUG_DUMP_TYPE); + } + if (!dhdp->logdump_periodic_flush) { + get_debug_dump_time(dhdp->debug_dump_time_str); + snprintf(dump_path, sizeof(dump_path), "%s_" "%s", + dump_path, dhdp->debug_dump_time_str); + } + + memset(time_str, 0, sizeof(time_str)); + ts = dhd_log_dump_get_timestamp(); + snprintf(time_str, sizeof(time_str), + "\n\n ========== LOG DUMP TAKEN AT : %s =========\n", ts); + + DHD_ERROR(("DHD version: %s\n", dhd_version)); + DHD_ERROR(("F/W version: %s\n", fw_version)); DHD_ERROR(("debug_dump_path = %s\n", dump_path)); + + dhd_log_dump_buf_addr(dhdp, type); + + /* if this is the first time after dhd is loaded, + * or, if periodic flush is disabled, clear the log file + */ + if (!dhdp->logdump_periodic_flush || dhdp->last_file_posn == 0) + file_mode = O_CREAT | O_WRONLY | O_SYNC | O_TRUNC; + else + file_mode = O_CREAT | O_RDWR | O_SYNC; + fp = filp_open(dump_path, file_mode, 0664); if (IS_ERR(fp)) { ret = PTR_ERR(fp); @@ -17298,24 +18190,94 @@ do_dhd_log_dump(dhd_pub_t *dhdp) goto exit; } - ret = vfs_write(fp, pre_strs, strlen(pre_strs), &pos); + ret = vfs_stat(dump_path, &stat); + if (ret < 0) { + DHD_ERROR(("file stat error, err = %d\n", ret)); + goto exit; + } + + /* if some one else has changed the file */ + if (dhdp->last_file_posn != 0 && + stat.size < dhdp->last_file_posn) { + dhdp->last_file_posn = 0; + } + + if (dhdp->logdump_periodic_flush) { + log_size = strlen(time_str) + strlen(DHD_DUMP_LOG_HDR) + sizeof(sec_hdr); + /* calculate the amount of space required to dump all logs */ + for (i = 0; i < DLD_BUFFER_NUM; ++i) { + if (*type != DLD_BUF_TYPE_ALL && i != *type) + continue; + + if (g_dld_buf[i].wraparound) { + log_size += (unsigned long)g_dld_buf[i].max + - (unsigned long)g_dld_buf[i].buffer; + } else { + spin_lock_irqsave(&g_dld_buf[i].lock, flags); + log_size += (unsigned long)g_dld_buf[i].present - + (unsigned long)g_dld_buf[i].front; + spin_unlock_irqrestore(&g_dld_buf[i].lock, flags); + } + log_size += strlen(dld_hdrs[i].hdr_str) + sizeof(sec_hdr); + + if (*type != DLD_BUF_TYPE_ALL && i == *type) + break; + } + + ret = generic_file_llseek(fp, dhdp->last_file_posn, SEEK_CUR); + if (ret < 0) { + DHD_ERROR(("file seek last posn error ! err = %d \n", ret)); + goto exit; + } + pos = fp->f_pos; + + /* if the max file size is reached, wrap around to beginning of the file + * we're treating the file as a large ring buffer + */ + fspace_remain = logdump_max_filesize - pos; + if (log_size > fspace_remain) { + fp->f_pos -= pos; + pos = fp->f_pos; + } + } + /* write the timestamp hdr to the file first */ + ret = vfs_write(fp, time_str, strlen(time_str), &pos); if (ret < 0) { DHD_ERROR(("write file error, err = %d\n", ret)); goto exit; } - do { - unsigned int buf_size = (unsigned int)(dld_buf->max - - (unsigned long)dld_buf->buffer); + /* prep the section header */ + memset(&sec_hdr, 0, sizeof(sec_hdr)); + sec_hdr.magic = LOG_DUMP_MAGIC; + sec_hdr.timestamp = local_clock(); + + for (i = 0; i < DLD_BUFFER_NUM; ++i) { + unsigned int buf_size = 0; + + if (*type != DLD_BUF_TYPE_ALL && i != *type) + continue; + + /* calculate the length of the log */ + dld_buf = &g_dld_buf[i]; + buf_size = (unsigned long)dld_buf->max - + (unsigned long)dld_buf->buffer; if (dld_buf->wraparound) { wr_size = buf_size; } else { - if (!dld_buf->buffer[0]) { /* print log if buf is empty. */ - DHD_ERROR_EX(("Buffer is empty. No event/log.\n")); - } - wr_size = (unsigned int)(dld_buf->present - dld_buf->front); - } - + /* need to hold the lock before accessing 'present' and 'remain' ptrs */ + spin_lock_irqsave(&dld_buf->lock, flags); + wr_size = (unsigned long)dld_buf->present - + (unsigned long)dld_buf->front; + spin_unlock_irqrestore(&dld_buf->lock, flags); + } + + /* write the section header first */ + sec_hdr.type = dld_hdrs[i].sec_type; + sec_hdr.length = wr_size; + vfs_write(fp, dld_hdrs[i].hdr_str, strlen(dld_hdrs[i].hdr_str), &pos); + vfs_write(fp, (char *)&sec_hdr, sizeof(sec_hdr), &pos); + /* write the log */ ret = vfs_write(fp, dld_buf->buffer, wr_size, &pos); if (ret < 0) { DHD_ERROR(("write file error, err = %d\n", ret)); @@ -17329,38 +18291,121 @@ do_dhd_log_dump(dhd_pub_t *dhdp) dld_buf->remain = buf_size; bzero(dld_buf->buffer, buf_size); spin_unlock_irqrestore(&dld_buf->lock, flags); - ret = BCME_OK; - if (++i < DLD_BUFFER_NUM) { - dld_buf = &g_dld_buf[i]; - } else { + if (*type != DLD_BUF_TYPE_ALL) break; + } + +#ifdef DEBUGABILITY_ECNTRS_LOGGING + /* periodic flushing of ecounters is NOT supported */ + if (*type == DLD_BUF_TYPE_ALL && + logdump_ecntr_enable && + dhdp->ecntr_dbg_ring) { + dhd_log_dump_ring_to_file(dhdp, dhdp->ecntr_dbg_ring, + fp, (unsigned long *)&pos, &sec_hdr); + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + +#ifdef BCMPCIE + /* append extended trap data to the file in case of traps */ + if (dhdp->dongle_trap_occured && + dhdp->extended_trap_data) { + /* write the section header first */ + vfs_write(fp, EXT_TRAP_LOG_HDR, strlen(EXT_TRAP_LOG_HDR), &pos); + sec_hdr.type = LOG_DUMP_SECTION_EXT_TRAP; + sec_hdr.length = BCMPCIE_EXT_TRAP_DATA_MAXLEN; + vfs_write(fp, (char *)&sec_hdr, sizeof(sec_hdr), &pos); + /* write the log */ + ret = vfs_write(fp, (char *)dhdp->extended_trap_data, + BCMPCIE_EXT_TRAP_DATA_MAXLEN, &pos); + if (ret < 0) { + DHD_ERROR(("write file error of ext trap info," + " err = %d\n", ret)); + goto exit; } + } +#endif /* BCMPCIE */ - ret = vfs_write(fp, post_strs, strlen(post_strs), &pos); +#if defined(DHD_FW_COREDUMP) && defined(DNGL_EVENT_SUPPORT) + /* if health check event was received, dump to file */ + if (dhdp->memdump_type == DUMP_TYPE_DONGLE_HOST_EVENT) { + /* write the section header first */ + vfs_write(fp, HEALTH_CHK_LOG_HDR, strlen(HEALTH_CHK_LOG_HDR), &pos); + sec_hdr.type = LOG_DUMP_SECTION_HEALTH_CHK; + sec_hdr.length = HEALTH_CHK_BUF_SIZE; + vfs_write(fp, (char *)&sec_hdr, sizeof(sec_hdr), &pos); + /* write the log */ + ret = vfs_write(fp, (char *)dhdp->health_chk_event_data, + HEALTH_CHK_BUF_SIZE, &pos); if (ret < 0) { - DHD_ERROR(("write file error, err = %d\n", ret)); + DHD_ERROR(("write file error of health chk info," + " err = %d\n", ret)); goto exit; } - } while (1); + } +#endif /* DHD_FW_COREDUMP && DNGL_EVENT_SUPPORT */ -exit: -#if defined(STAT_REPORT) - if (!IS_ERR(fp) && ret >= 0) { - wl_stat_report_file_save(dhdp, fp); + /* append the concise debug information to the file. + * This is the information which is seen + * when a 'dhd dump' iovar is fired + */ + if (dhdp->concise_dbg_buf) { + remain_len = dhd_dump(dhdp, (char *)dhdp->concise_dbg_buf, CONCISE_DUMP_BUFLEN); + if (remain_len <= 0) { + DHD_ERROR(("%s: error getting concise debug info !\n", + __FUNCTION__)); + goto exit; + } else { + /* write the section header first */ + vfs_write(fp, DHD_DUMP_LOG_HDR, strlen(DHD_DUMP_LOG_HDR), &pos); + sec_hdr.type = LOG_DUMP_SECTION_DHD_DUMP; + sec_hdr.length = CONCISE_DUMP_BUFLEN - remain_len; + vfs_write(fp, (char *)&sec_hdr, sizeof(sec_hdr), &pos); + /* write the log */ + ret = vfs_write(fp, dhdp->concise_dbg_buf, + CONCISE_DUMP_BUFLEN - remain_len, &pos); + if (ret < 0) { + DHD_ERROR(("write file error of concise debug info," + " err = %d\n", ret)); + goto exit; + } + } } -#endif /* STAT_REPORT */ - if (!IS_ERR(fp)) { - filp_close(fp, NULL); + if (dhdp->logdump_cookie && dhd_logdump_cookie_count(dhdp) > 0) { + ret = dhd_log_dump_cookie_to_file(dhdp, fp, (unsigned long *)&pos); + if (ret < 0) { + DHD_ERROR(("write file error of cooke info, err = %d\n", ret)); + goto exit; + } } - set_fs(old_fs); - return ret; + if (dhdp->logdump_periodic_flush) { + /* store the last position written to in the file for future use */ + dhdp->last_file_posn = pos; + } + +exit: + MFREE(dhdp->osh, type, sizeof(*type)); + if (!IS_ERR(fp) && fp != NULL) { + filp_close(fp, NULL); + } + set_fs(old_fs); + DHD_GENERAL_LOCK(dhdp, flags); + DHD_BUS_BUSY_CLEAR_IN_LOGDUMP(dhdp); + dhd_os_busbusy_wake(dhdp); + DHD_GENERAL_UNLOCK(dhdp, flags); + +#ifdef DHD_DUMP_MNGR + if (ret >= 0) { + dhd_dump_file_manage_enqueue(dhdp, dump_path, DHD_DEBUG_DUMP_TYPE); + } +#endif /* DHD_DUMP_MNGR */ + + return (ret < 0) ? BCME_ERROR : BCME_OK; } #endif /* DHD_LOG_DUMP */ - #ifdef BCMASSERT_LOG #ifdef CUSTOMER_HW4_DEBUG #define ASSERTINFO PLATFORM_PATH".assert.info" @@ -17399,7 +18444,7 @@ void dhd_get_assert_info(dhd_pub_t *dhd) #else /* By default. set to 0, Kernel Panic */ g_assert_type = (mem_val >= 0) ? mem_val : 0; -#endif +#endif // endif } #endif /* BCMASSERT_LOG */ @@ -17485,46 +18530,6 @@ dhd_os_get_version(struct net_device *dev, bool dhd_ver, char **buf, uint32 size return BCME_OK; } - -#if defined(TRAFFIC_MGMT_DWM) -void traffic_mgmt_pkt_set_prio(dhd_pub_t *dhdp, void * pktbuf) -{ - struct ether_header *eh; - struct ethervlan_header *evh; - uint8 *pktdata, *ip_body; - uint8 dwm_filter; - uint8 tos_tc = 0; - uint8 dscp = 0; - pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); - eh = (struct ether_header *) pktdata; - ip_body = NULL; - - if (dhdp->dhd_tm_dwm_tbl.dhd_dwm_enabled) { - if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { - evh = (struct ethervlan_header *)eh; - if ((evh->ether_type == hton16(ETHER_TYPE_IP)) || - (evh->ether_type == hton16(ETHER_TYPE_IPV6))) { - ip_body = pktdata + sizeof(struct ethervlan_header); - } - } else if ((eh->ether_type == hton16(ETHER_TYPE_IP)) || - (eh->ether_type == hton16(ETHER_TYPE_IPV6))) { - ip_body = pktdata + sizeof(struct ether_header); - } - if (ip_body) { - tos_tc = IP_TOS46(ip_body); - dscp = tos_tc >> IPV4_TOS_DSCP_SHIFT; - } - - if (dscp < DHD_DWM_TBL_SIZE) { - dwm_filter = dhdp->dhd_tm_dwm_tbl.dhd_dwm_tbl[dscp]; - if (DHD_TRF_MGMT_DWM_IS_FILTER_SET(dwm_filter)) { - PKTSETPRIO(pktbuf, DHD_TRF_MGMT_DWM_PRIO(dwm_filter)); - } - } - } -} -#endif - bool dhd_sta_associated(dhd_pub_t *dhdp, uint32 bssidx, uint8 *mac) { return dhd_find_sta(dhdp, bssidx, mac) ? TRUE : FALSE; @@ -17697,8 +18702,35 @@ int dhd_set_grat_arp_status(dhd_pub_t *dhdp, uint32 idx, int val) return BCME_OK; } -#endif /* DHD_L2_FILTER */ +int dhd_get_block_tdls_status(dhd_pub_t *dhdp, uint32 idx) +{ + dhd_info_t *dhd = dhdp->info; + dhd_if_t *ifp; + + ASSERT(idx < DHD_MAX_IFS); + + ifp = dhd->iflist[idx]; + + ASSERT(ifp); + + return ifp->block_tdls; +} + +int dhd_set_block_tdls_status(dhd_pub_t *dhdp, uint32 idx, int val) +{ + dhd_info_t *dhd = dhdp->info; + dhd_if_t *ifp; + ASSERT(idx < DHD_MAX_IFS); + ifp = dhd->iflist[idx]; + + ASSERT(ifp); + + ifp->block_tdls = val; + + return BCME_OK; +} +#endif /* DHD_L2_FILTER */ #if defined(SET_RPS_CPUS) || defined(ARGOS_RPS_CPU_CTL) int dhd_rps_cpus_enable(struct net_device *net, int enable) @@ -17824,7 +18856,7 @@ void custom_rps_map_clear(struct netdev_rx_queue *queue) } #endif /* SET_RPS_CPUS || ARGOS_RPS_CPU_CTL */ -#if defined(ARGOS_CPU_SCHEDULER) +#if defined(ARGOS_CPU_SCHEDULER) && defined(ARGOS_RPS_CPU_CTL) int argos_register_notifier_init(struct net_device *net) { @@ -17876,9 +18908,9 @@ argos_register_notifier_deinit(void) DHD_ERROR(("DHD: primary_net_dev is null %s: \n", __FUNCTION__)); return -1; } -#if !defined(DHD_LB) && defined(ARGOS_RPS_CPU_CTL) +#ifndef DHD_LB custom_rps_map_clear(argos_rps_ctrl_data.wlan_primary_netdev->_rx); -#endif /* !DHD_LB && ARGOS_RPS_CPU_CTL */ +#endif /* !DHD_LB */ if (argos_p2p.notifier_call) { sec_argos_unregister_notifier(&argos_p2p, ARGOS_P2P_TABLE_LABEL); @@ -17925,7 +18957,7 @@ argos_status_notifier_wifi_cb(struct notifier_block *notifier, /* It does not need to configre rps_cpus * if Load Balance is enabled */ -#if !defined(DHD_LB) && defined(ARGOS_RPS_CPU_CTL) +#ifndef DHD_LB int err = 0; if (cpu_online(RPS_CPUS_WLAN_CORE_ID)) { @@ -17944,38 +18976,38 @@ argos_status_notifier_wifi_cb(struct notifier_block *notifier, "speed=%ld, error=%d\n", __FUNCTION__, speed, err)); } else { -#endif /* !DHD_LB && ARGOS_RPS_CPU_CTL */ -#ifdef DHDTCPACK_SUPPRESS - if (dhdp->tcpack_sup_mode != TCPACK_SUP_ON) { +#endif /* !DHD_LB */ +#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) + if (dhdp->tcpack_sup_mode != TCPACK_SUP_HOLD) { DHD_ERROR(("%s : set ack suppress. TCPACK_SUP_ON(%d)\n", - __FUNCTION__, TCPACK_SUP_ON)); - dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_ON); + __FUNCTION__, TCPACK_SUP_HOLD)); + dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_HOLD); } -#endif /* DHDTCPACK_SUPPRESS */ +#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ argos_rps_ctrl_data.argos_rps_cpus_enabled = 1; -#if !defined(DHD_LB) && defined(ARGOS_RPS_CPU_CTL) +#ifndef DHD_LB DHD_ERROR(("DHD: %s: Set RPS_CPUs, speed=%ld\n", __FUNCTION__, speed)); } -#endif /* !DHD_LB && ARGOS_RPS_CPU_CTL */ +#endif /* !DHD_LB */ } } else { if (argos_rps_ctrl_data.argos_rps_cpus_enabled == 1) { -#ifdef DHDTCPACK_SUPPRESS +#if (defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE)) if (dhdp->tcpack_sup_mode != TCPACK_SUP_OFF) { DHD_ERROR(("%s : set ack suppress. TCPACK_SUP_OFF\n", __FUNCTION__)); dhd_tcpack_suppress_set(dhdp, TCPACK_SUP_OFF); } -#endif /* DHDTCPACK_SUPPRESS */ -#if !defined(DHD_LB) && defined(ARGOS_RPS_CPU_CTL) +#endif /* DHDTCPACK_SUPPRESS && BCMPCIE */ +#ifndef DHD_LB /* It does not need to configre rps_cpus * if Load Balance is enabled */ custom_rps_map_clear(argos_rps_ctrl_data.wlan_primary_netdev->_rx); DHD_ERROR(("DHD: %s: Clear RPS_CPUs, speed=%ld\n", __FUNCTION__, speed)); OSL_SLEEP(DELAY_TO_CLEAR_RPS_CPUS); -#endif /* !DHD_LB && ARGOS_RPS_CPU_CTL */ +#endif /* !DHD_LB */ argos_rps_ctrl_data.argos_rps_cpus_enabled = 0; } } @@ -17991,8 +19023,7 @@ argos_status_notifier_p2p_cb(struct notifier_block *notifier, DHD_INFO(("DHD: %s: speed=%ld\n", __FUNCTION__, speed)); return argos_status_notifier_wifi_cb(notifier, speed, v); } -#endif /* ARGOS_CPU_SCHEDULER */ - +#endif /* ARGOS_CPU_SCHEDULER && ARGOS_RPS_CPU_CTL */ #ifdef DHD_DEBUG_PAGEALLOC @@ -18140,7 +19171,7 @@ dhd_get_read_buf_ptr(dhd_pub_t *dhd_pub, trace_buf_info_t *trace_buf_info) dhd_dbg_ring_status_t ring_status; uint32 rlen; - rlen = dhd_dbg_ring_pull_single(dhd_pub, FW_VERBOSE_RING_ID, trace_buf_info->buf, + rlen = dhd_dbg_pull_single_from_ring(dhd_pub, FW_VERBOSE_RING_ID, trace_buf_info->buf, TRACE_LOG_BUF_MAX_SIZE, TRUE); trace_buf_info->size = rlen; trace_buf_info->availability = NEXT_BUF_NOT_AVAIL; @@ -18167,13 +19198,14 @@ dhd_create_to_notifier_skt(void) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) /* Kernel 3.7 onwards this API accepts only 3 arguments. */ /* Kernel version 3.6 is a special case which accepts 4 arguments */ - nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, &g_cfg); + nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, &dhd_netlink_cfg); #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) /* Kernel version 3.5 and below use this old API format */ nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, 0, dhd_process_daemon_msg, NULL, THIS_MODULE); #else - nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, THIS_MODULE, &g_cfg); + nl_to_event_sk = netlink_kernel_create(&init_net, BCM_NL_USER, THIS_MODULE, + &dhd_netlink_cfg); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)) */ if (!nl_to_event_sk) { @@ -18231,6 +19263,64 @@ dhd_send_msg_to_daemon(struct sk_buff *skb, void *data, int size) return 0; } +static ssize_t +show_enable_ecounter(struct dhd_info *dev, char *buf) +{ + ssize_t ret = 0; + unsigned long onoff; + + onoff = enable_ecounter; + ret = scnprintf(buf, PAGE_SIZE - 1, "%lu \n", + onoff); + return ret; +} + +static ssize_t +ecounter_onoff(struct dhd_info *dev, const char *buf, size_t count) +{ + unsigned long onoff; + dhd_info_t *dhd = (dhd_info_t *)dev; + dhd_pub_t *dhdp; + + if (!dhd) { + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); + return count; + } + dhdp = &dhd->pub; + if (!FW_SUPPORTED(dhdp, ecounters)) { + DHD_ERROR(("%s: ecounters not supported by FW\n", __FUNCTION__)); + return count; + } + + onoff = bcm_strtoul(buf, NULL, 10); + + sscanf(buf, "%lu", &onoff); + if (onoff != 0 && onoff != 1) { + return -EINVAL; + } + + if (enable_ecounter == onoff) { + DHD_ERROR(("%s: ecounters already %d\n", __FUNCTION__, enable_ecounter)); + return count; + } + + enable_ecounter = onoff; + if (enable_ecounter) { + if (dhd_start_ecounters(dhdp) != BCME_OK) { + DHD_ERROR(("%s Ecounters start failed\n", __FUNCTION__)); + } else if (dhd_start_event_ecounters(dhdp) != BCME_OK) { + DHD_ERROR(("%s Event_Ecounters start failed\n", __FUNCTION__)); + } + } else { + if (dhd_stop_ecounters(dhdp) != BCME_OK) { + DHD_ERROR(("%s Ecounters stop failed\n", __FUNCTION__)); + } else if (dhd_stop_event_ecounters(dhdp) != BCME_OK) { + DHD_ERROR(("%s Event_Ecounters stop failed\n", __FUNCTION__)); + } + } + + return count; +} static void dhd_process_daemon_msg(struct sk_buff *skb) @@ -18245,142 +19335,314 @@ dhd_process_daemon_msg(struct sk_buff *skb) dhd_send_msg_to_daemon(skb, &to_info, sizeof(to_info)); } -#ifdef REPORT_FATAL_TIMEOUTS -static void -dhd_send_trap_to_fw(dhd_pub_t * pub, int reason, int trap) +#ifdef DHD_LOG_DUMP +bool +dhd_log_dump_ecntr_enabled(void) { - bcm_to_info_t to_info; - - to_info.magic = BCM_TO_MAGIC; - to_info.reason = reason; - to_info.trap = trap; - - DHD_ERROR(("Sending Event reason:%d trap:%d\n", reason, trap)); - dhd_send_msg_to_daemon(NULL, (void *)&to_info, sizeof(bcm_to_info_t)); + return (bool)logdump_ecntr_enable; } -void -dhd_send_trap_to_fw_for_timeout(dhd_pub_t * pub, timeout_reasons_t reason) -{ - int to_reason; - int trap = NO_TRAP; - switch (reason) { - case DHD_REASON_COMMAND_TO: - to_reason = REASON_COMMAND_TO; - trap = DO_TRAP; - break; - case DHD_REASON_JOIN_TO: - to_reason = REASON_JOIN_TO; - break; - case DHD_REASON_SCAN_TO: - to_reason = REASON_SCAN_TO; - break; - case DHD_REASON_OQS_TO: - to_reason = REASON_OQS_TO; - trap = DO_TRAP; - break; - default: - to_reason = REASON_UNKOWN; - } - dhd_send_trap_to_fw(pub, to_reason, trap); -} -#endif /* REPORT_FATAL_TIMEOUTS */ - -#ifdef DHD_LOG_DUMP void dhd_log_dump_init(dhd_pub_t *dhd) { - struct dhd_log_dump_buf *dld_buf; + struct dhd_log_dump_buf *dld_buf, *dld_buf_special; int i = 0; + uint8 *prealloc_buf = NULL, *bufptr = NULL; #if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) int prealloc_idx = DHD_PREALLOC_DHD_LOG_DUMP_BUF; #endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ + int ret; + dhd_dbg_ring_t *ring = NULL; + unsigned long flags = 0; + dhd_info_t *dhd_info = dhd->info; + void *cookie_buf = NULL; - for (i = 0; i < DLD_BUFFER_NUM; i++) { - dld_buf = &g_dld_buf[i]; - spin_lock_init(&dld_buf->lock); -#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) - dld_buf->buffer = DHD_OS_PREALLOC(dhd, prealloc_idx++, dld_buf_size[i]); + BCM_REFERENCE(ret); + BCM_REFERENCE(ring); + BCM_REFERENCE(flags); + + /* sanity check */ + if (logdump_prsrv_tailsize <= 0 || + logdump_prsrv_tailsize > DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE) { + logdump_prsrv_tailsize = DHD_LOG_DUMP_MAX_TAIL_FLUSH_SIZE; + } + /* now adjust the preserve log flush size based on the + * kernel printk log buffer size + */ +#ifdef CONFIG_LOG_BUF_SHIFT + DHD_ERROR(("%s: kernel log buf size = %uKB; logdump_prsrv_tailsize = %uKB;" + " limit prsrv tail size to = %uKB\n", + __FUNCTION__, (1 << CONFIG_LOG_BUF_SHIFT)/1024, + logdump_prsrv_tailsize/1024, LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE/1024)); + + if (logdump_prsrv_tailsize > LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE) { + logdump_prsrv_tailsize = LOG_DUMP_KERNEL_TAIL_FLUSH_SIZE; + } #else - dld_buf->buffer = kmalloc(dld_buf_size[i], GFP_KERNEL); -#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ + DHD_ERROR(("%s: logdump_prsrv_tailsize = %uKB \n", + __FUNCTION__, logdump_prsrv_tailsize/1024); +#endif /* CONFIG_LOG_BUF_SHIFT */ - if (!dld_buf->buffer) { - dld_buf->buffer = kmalloc(dld_buf_size[i], GFP_KERNEL); - DHD_ERROR(("Try to allocate memory using kmalloc().\n")); + mutex_init(&dhd_info->logdump_lock); - if (!dld_buf->buffer) { - DHD_ERROR(("Failed to allocate memory for dld_buf[%d].\n", i)); - goto fail; - } - } + /* initialize log dump buf structures */ + memset(g_dld_buf, 0, sizeof(struct dhd_log_dump_buf) * DLD_BUFFER_NUM); + + /* set the log dump buffer size based on the module_param */ + if (logdump_max_bufsize > LOG_DUMP_GENERAL_MAX_BUFSIZE || + logdump_max_bufsize <= 0) + dld_buf_size[DLD_BUF_TYPE_GENERAL] = LOG_DUMP_GENERAL_MAX_BUFSIZE; + else + dld_buf_size[DLD_BUF_TYPE_GENERAL] = logdump_max_bufsize; + + /* pre-alloc the memory for the log buffers & 'special' buffer */ + dld_buf_special = &g_dld_buf[DLD_BUF_TYPE_SPECIAL]; +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) + DHD_ERROR(("%s : Try to allocate memory total(%d) special(%d)\n", + __FUNCTION__, LOG_DUMP_TOTAL_BUFSIZE, LOG_DUMP_SPECIAL_MAX_BUFSIZE)); + prealloc_buf = DHD_OS_PREALLOC(dhd, prealloc_idx++, LOG_DUMP_TOTAL_BUFSIZE); + dld_buf_special->buffer = DHD_OS_PREALLOC(dhd, prealloc_idx++, + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); +#else + prealloc_buf = MALLOCZ(dhd->osh, LOG_DUMP_TOTAL_BUFSIZE); + dld_buf_special->buffer = MALLOCZ(dhd->osh, dld_buf_size[DLD_BUF_TYPE_SPECIAL]); +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ + if (!prealloc_buf) { + DHD_ERROR(("Failed to pre-allocate memory for log buffers !\n")); + goto fail; + } + if (!dld_buf_special->buffer) { + DHD_ERROR(("Failed to pre-allocate memory for special buffer !\n")); + goto fail; + } + bufptr = prealloc_buf; + for (i = 0; i < DLD_BUFFER_NUM; i++) { + dld_buf = &g_dld_buf[i]; + dld_buf->dhd_pub = dhd; + spin_lock_init(&dld_buf->lock); dld_buf->wraparound = 0; - dld_buf->max = (unsigned long)dld_buf->buffer + dld_buf_size[i]; + if (i != DLD_BUF_TYPE_SPECIAL) { + dld_buf->buffer = bufptr; + dld_buf->max = (unsigned long)dld_buf->buffer + dld_buf_size[i]; + bufptr = (uint8 *)dld_buf->max; + } else { + dld_buf->max = (unsigned long)dld_buf->buffer + dld_buf_size[i]; + } dld_buf->present = dld_buf->front = dld_buf->buffer; dld_buf->remain = dld_buf_size[i]; dld_buf->enable = 1; } + +#ifdef DEBUGABILITY_ECNTRS_LOGGING + /* now use the rest of the pre-alloc'd memory for filter and ecounter log */ + dhd->ecntr_dbg_ring = MALLOCZ(dhd->osh, sizeof(dhd_dbg_ring_t)); + if (!dhd->ecntr_dbg_ring) + goto fail; + + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; + ret = dhd_dbg_ring_init(dhd, ring, ECNTR_RING_ID, + ECNTR_RING_NAME, LOG_DUMP_ECNTRS_MAX_BUFSIZE, + bufptr); + if (ret != BCME_OK) { + DHD_ERROR(("%s: unable to init ecntr ring !\n", + __FUNCTION__)); + goto fail; + } + DHD_DBG_RING_LOCK(ring->lock, flags); + ring->state = RING_ACTIVE; + ring->threshold = 0; + DHD_DBG_RING_UNLOCK(ring->lock, flags); + + bufptr += LOG_DUMP_ECNTRS_MAX_BUFSIZE; +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + + /* Concise buffer is used as intermediate buffer for following purposes + * a) pull ecounters records temporarily before + * writing it to file + * b) to store dhd dump data before putting it to file + * It should have a size equal to + * MAX(largest possible ecntr record, 'dhd dump' data size) + */ + dhd->concise_dbg_buf = MALLOC(dhd->osh, CONCISE_DUMP_BUFLEN); + if (!dhd->concise_dbg_buf) { + DHD_ERROR(("%s: unable to alloc mem for concise debug info !\n", + __FUNCTION__)); + goto fail; + } + +#if defined(DHD_EVENT_LOG_FILTER) + ret = dhd_event_log_filter_init(dhd, + bufptr, + LOG_DUMP_FILTER_MAX_BUFSIZE); + if (ret != BCME_OK) { + goto fail; + } +#endif /* DHD_EVENT_LOG_FILTER */ + + cookie_buf = MALLOC(dhd->osh, LOG_DUMP_COOKIE_BUFSIZE); + if (!cookie_buf) { + DHD_ERROR(("%s: unable to alloc mem for logdump cookie buffer\n", + __FUNCTION__)); + goto fail; + } + ret = dhd_logdump_cookie_init(dhd, cookie_buf, LOG_DUMP_COOKIE_BUFSIZE); + if (ret != BCME_OK) { + MFREE(dhd->osh, cookie_buf, LOG_DUMP_COOKIE_BUFSIZE); + goto fail; + } return; fail: + + if (dhd->logdump_cookie) { + dhd_logdump_cookie_deinit(dhd); + MFREE(dhd->osh, dhd->logdump_cookie, LOG_DUMP_COOKIE_BUFSIZE); + dhd->logdump_cookie = NULL; + } +#if defined(DHD_EVENT_LOG_FILTER) + if (dhd->event_log_filter) { + dhd_event_log_filter_deinit(dhd); + } +#endif /* DHD_EVENT_LOG_FILTER */ + + if (dhd->concise_dbg_buf) { + MFREE(dhd->osh, dhd->concise_dbg_buf, CONCISE_DUMP_BUFLEN); + } + +#ifdef DEBUGABILITY_ECNTRS_LOGGING + if (dhd->ecntr_dbg_ring) { + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; + dhd_dbg_ring_deinit(dhd, ring); + ring->ring_buf = NULL; + ring->ring_size = 0; + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); + dhd->ecntr_dbg_ring = NULL; + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) + if (prealloc_buf) { + DHD_OS_PREFREE(dhd, prealloc_buf, LOG_DUMP_TOTAL_BUFSIZE); + } + if (dld_buf_special->buffer) { + DHD_OS_PREFREE(dhd, dld_buf_special->buffer, + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); + } +#else + if (prealloc_buf) { + MFREE(dhd->osh, prealloc_buf, LOG_DUMP_TOTAL_BUFSIZE); + } + if (dld_buf_special->buffer) { + MFREE(dhd->osh, dld_buf_special->buffer, + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); + } +#endif /* CONFIG_DHD_USE_STATIC_BUF */ for (i = 0; i < DLD_BUFFER_NUM; i++) { - if (dld_buf[i].buffer) { - kfree(dld_buf[i].buffer); - } + dld_buf = &g_dld_buf[i]; + dld_buf->enable = 0; + dld_buf->buffer = NULL; } + + mutex_destroy(&dhd_info->logdump_lock); } void dhd_log_dump_deinit(dhd_pub_t *dhd) { - struct dhd_log_dump_buf *dld_buf; + struct dhd_log_dump_buf *dld_buf = NULL, *dld_buf_special = NULL; int i = 0; + dhd_info_t *dhd_info = dhd->info; + dhd_dbg_ring_t *ring = NULL; + + BCM_REFERENCE(ring); + + if (dhd->concise_dbg_buf) { + MFREE(dhd->osh, dhd->concise_dbg_buf, CONCISE_DUMP_BUFLEN); + dhd->concise_dbg_buf = NULL; + } + + if (dhd->logdump_cookie) { + dhd_logdump_cookie_deinit(dhd); + MFREE(dhd->osh, dhd->logdump_cookie, LOG_DUMP_COOKIE_BUFSIZE); + dhd->logdump_cookie = NULL; + } + +#if defined(DHD_EVENT_LOG_FILTER) + if (dhd->event_log_filter) { + dhd_event_log_filter_deinit(dhd); + } +#endif /* DHD_EVENT_LOG_FILTER */ + +#ifdef DEBUGABILITY_ECNTRS_LOGGING + if (dhd->ecntr_dbg_ring) { + ring = (dhd_dbg_ring_t *)dhd->ecntr_dbg_ring; + dhd_dbg_ring_deinit(dhd, ring); + ring->ring_buf = NULL; + ring->ring_size = 0; + MFREE(dhd->osh, ring, sizeof(dhd_dbg_ring_t)); + dhd->ecntr_dbg_ring = NULL; + } +#endif /* DEBUGABILITY_ECNTRS_LOGGING */ + /* 'general' buffer points to start of the pre-alloc'd memory */ + dld_buf = &g_dld_buf[DLD_BUF_TYPE_GENERAL]; + dld_buf_special = &g_dld_buf[DLD_BUF_TYPE_SPECIAL]; +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) + if (dld_buf->buffer) { + DHD_OS_PREFREE(dhd, dld_buf->buffer, LOG_DUMP_TOTAL_BUFSIZE); + } + if (dld_buf_special->buffer) { + DHD_OS_PREFREE(dhd, dld_buf_special->buffer, + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); + } +#else + if (dld_buf->buffer) { + MFREE(dhd->osh, dld_buf->buffer, LOG_DUMP_TOTAL_BUFSIZE); + } + if (dld_buf_special->buffer) { + MFREE(dhd->osh, dld_buf_special->buffer, + dld_buf_size[DLD_BUF_TYPE_SPECIAL]); + } +#endif /* CONFIG_DHD_USE_STATIC_BUF */ for (i = 0; i < DLD_BUFFER_NUM; i++) { dld_buf = &g_dld_buf[i]; dld_buf->enable = 0; -#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_MEMDUMP) - DHD_OS_PREFREE(dhd, dld_buf->buffer, dld_buf_size[i]); -#else - kfree(dld_buf->buffer); -#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_MEMDUMP */ + dld_buf->buffer = NULL; } + + mutex_destroy(&dhd_info->logdump_lock); } void -dhd_log_dump_write(int type, const char *fmt, ...) +dhd_log_dump_write(int type, char *binary_data, + int binary_len, const char *fmt, ...) { int len = 0; char tmp_buf[DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE] = {0, }; va_list args; unsigned long flags = 0; struct dhd_log_dump_buf *dld_buf = NULL; + bool flush_log = FALSE; - switch (type) - { - case DLD_BUF_TYPE_GENERAL: - dld_buf = &g_dld_buf[type]; - break; - case DLD_BUF_TYPE_SPECIAL: - dld_buf = &g_dld_buf[type]; - break; - default: - DHD_ERROR(("%s: Unknown DHD_LOG_DUMP_BUF_TYPE(%d).\n", - __FUNCTION__, type)); - return; + if (type < 0 || type >= DLD_BUFFER_NUM) { + DHD_INFO(("%s: Unknown DHD_LOG_DUMP_BUF_TYPE(%d).\n", + __FUNCTION__, type)); + return; } + dld_buf = &g_dld_buf[type]; + if (dld_buf->enable != 1) { return; } va_start(args, fmt); - len = vsnprintf(tmp_buf, DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE, fmt, args); /* Non ANSI C99 compliant returns -1, * ANSI compliant return len >= DHD_LOG_DUMP_MAX_TEMP_BUFFER_SIZE */ + va_end(args); if (len < 0) { return; } @@ -18396,16 +19658,31 @@ dhd_log_dump_write(int type, const char *fmt, ...) dld_buf->wraparound = 1; dld_buf->present = dld_buf->front; dld_buf->remain = dld_buf_size[type]; + /* if wrap around happens, flush the ring buffer to the file */ + flush_log = TRUE; } - strncpy(dld_buf->present, tmp_buf, len); + memcpy(dld_buf->present, tmp_buf, len); dld_buf->remain -= len; dld_buf->present += len; spin_unlock_irqrestore(&dld_buf->lock, flags); /* double check invalid memory operation */ ASSERT((unsigned long)dld_buf->present <= dld_buf->max); - va_end(args); + + if (dld_buf->dhd_pub) { + dhd_pub_t *dhdp = (dhd_pub_t *)dld_buf->dhd_pub; + dhdp->logdump_periodic_flush = + logdump_periodic_flush; + if (logdump_periodic_flush && flush_log) { + log_dump_type_t *flush_type = MALLOCZ(dhdp->osh, + sizeof(log_dump_type_t)); + if (flush_type) { + *flush_type = type; + dhd_schedule_log_dump(dld_buf->dhd_pub, flush_type); + } + } + } } char* @@ -18424,96 +19701,23 @@ dhd_log_dump_get_timestamp(void) } #endif /* DHD_LOG_DUMP */ -int -dhd_write_file(const char *filepath, char *buf, int buf_len) +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +void +dhd_flush_rx_tx_wq(dhd_pub_t *dhdp) { - struct file *fp = NULL; - mm_segment_t old_fs; - int ret = 0; - - /* change to KERNEL_DS address limit */ - old_fs = get_fs(); - set_fs(KERNEL_DS); + dhd_info_t * dhd; - /* File is always created. */ - fp = filp_open(filepath, O_RDWR | O_CREAT, 0664); - if (IS_ERR(fp)) { - DHD_ERROR(("%s: Couldn't open file '%s' err %ld\n", - __FUNCTION__, filepath, PTR_ERR(fp))); - ret = BCME_ERROR; - } else { - if (fp->f_mode & FMODE_WRITE) { - ret = vfs_write(fp, buf, buf_len, &fp->f_pos); - if (ret < 0) { - DHD_ERROR(("%s: Couldn't write file '%s'\n", - __FUNCTION__, filepath)); - ret = BCME_ERROR; - } else { - ret = BCME_OK; - } + if (dhdp) { + dhd = dhdp->info; + if (dhd) { + flush_workqueue(dhd->tx_wq); + flush_workqueue(dhd->rx_wq); } - filp_close(fp, NULL); } - /* restore previous address limit */ - set_fs(old_fs); - - return ret; -} - -int -dhd_read_file(const char *filepath, char *buf, int buf_len) -{ - struct file *fp = NULL; - mm_segment_t old_fs; - int ret; - - /* change to KERNEL_DS address limit */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - - fp = filp_open(filepath, O_RDONLY, 0); - if (IS_ERR(fp)) { - set_fs(old_fs); - DHD_ERROR(("%s: File %s doesn't exist\n", __FUNCTION__, filepath)); - return BCME_ERROR; - } - - ret = kernel_read(fp, 0, buf, buf_len); - filp_close(fp, NULL); - - /* restore previous address limit */ - set_fs(old_fs); - - /* Return the number of bytes read */ - if (ret > 0) { - /* Success to read */ - ret = 0; - } else { - DHD_ERROR(("%s: Couldn't read the file %s, ret=%d\n", - __FUNCTION__, filepath, ret)); - ret = BCME_ERROR; - } - - return ret; -} - -int -dhd_write_file_and_check(const char *filepath, char *buf, int buf_len) -{ - int ret; - - ret = dhd_write_file(filepath, buf, buf_len); - if (ret < 0) { - return ret; - } - - /* Read the file again and check if the file size is not zero */ - memset(buf, 0, buf_len); - ret = dhd_read_file(filepath, buf, buf_len); - - return ret; + return; } +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #ifdef DHD_LB_TXP #define DHD_LB_TXBOUND 64 @@ -18535,6 +19739,8 @@ dhd_lb_tx_process(dhd_info_t *dhd) return resched; } + BCM_REFERENCE(net); + DHD_LB_STATS_PERCPU_ARR_INCR(dhd->txp_percpu_run_cnt); /* Base Loop to perform the actual Tx */ @@ -18549,7 +19755,6 @@ dhd_lb_tx_process(dhd_info_t *dhd) net = DHD_LB_TX_PKTTAG_NETDEV((dhd_tx_lb_pkttag_fr_t *)PKTTAG(skb)); ifidx = DHD_LB_TX_PKTTAG_IFIDX((dhd_tx_lb_pkttag_fr_t *)PKTTAG(skb)); - BCM_REFERENCE(net); DHD_TRACE(("Processing skb %p for net %p index %d \r\n", skb, net, ifidx)); @@ -18677,6 +19882,60 @@ lbtxp_onoff(struct dhd_info *dev, const char *buf, size_t count) } #endif /* DHD_LB_TXP */ + +#ifdef DHD_LOG_DUMP +static ssize_t +show_logdump_periodic_flush(struct dhd_info *dev, char *buf) +{ + ssize_t ret = 0; + unsigned long val; + + val = logdump_periodic_flush; + ret = scnprintf(buf, PAGE_SIZE - 1, "%lu \n", val); + return ret; +} + +static ssize_t +logdump_periodic_flush_onoff(struct dhd_info *dev, const char *buf, size_t count) +{ + unsigned long val; + + val = bcm_strtoul(buf, NULL, 10); + + sscanf(buf, "%lu", &val); + if (val != 0 && val != 1) { + return -EINVAL; + } + logdump_periodic_flush = val; + return count; +} +static ssize_t +show_logdump_ecntr(struct dhd_info *dev, char *buf) +{ + ssize_t ret = 0; + unsigned long val; + + val = logdump_ecntr_enable; + ret = scnprintf(buf, PAGE_SIZE - 1, "%lu \n", val); + return ret; +} + +static ssize_t +logdump_ecntr_onoff(struct dhd_info *dev, const char *buf, size_t count) +{ + unsigned long val; + + val = bcm_strtoul(buf, NULL, 10); + + sscanf(buf, "%lu", &val); + if (val != 0 && val != 1) { + return -EINVAL; + } + logdump_ecntr_enable = val; + return count; +} + +#endif /* DHD_LOG_DUMP */ /* * Generic Attribute Structure for DHD. * If we have to add a new sysfs entry under /sys/bcm-dhd/, we have @@ -18701,15 +19960,31 @@ static struct dhd_attr dhd_attr_wklock = static struct dhd_attr dhd_attr_lbtxp = __ATTR(lbtxp, 0660, show_lbtxp, lbtxp_onoff); #endif /* DHD_LB_TXP */ +#ifdef DHD_LOG_DUMP +static struct dhd_attr dhd_attr_logdump_periodic_flush = + __ATTR(logdump_periodic_flush, 0660, show_logdump_periodic_flush, + logdump_periodic_flush_onoff); +static struct dhd_attr dhd_attr_logdump_ecntr = + __ATTR(logdump_ecntr_enable, 0660, show_logdump_ecntr, + logdump_ecntr_onoff); +#endif /* DHD_LOG_DUMP */ + +static struct dhd_attr dhd_attr_ecounters = + __ATTR(ecounters, 0660, show_enable_ecounter, ecounter_onoff); /* Attribute object that gets registered with "bcm-dhd" kobject tree */ static struct attribute *default_attrs[] = { #if defined(DHD_TRACE_WAKE_LOCK) &dhd_attr_wklock.attr, -#endif /* DHD_TRACE_WAKE_LOCK */ +#endif // endif #if defined(DHD_LB_TXP) &dhd_attr_lbtxp.attr, #endif /* DHD_LB_TXP */ +#ifdef DHD_LOG_DUMP + &dhd_attr_logdump_periodic_flush.attr, + &dhd_attr_logdump_ecntr.attr, +#endif // endif + &dhd_attr_ecounters.attr, NULL }; @@ -18725,12 +20000,12 @@ static ssize_t dhd_show(struct kobject *kobj, struct attribute *attr, char *buf) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif dhd_info_t *dhd = to_dhd(kobj); struct dhd_attr *d_attr = to_attr(attr); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif int ret; if (d_attr->show) @@ -18751,12 +20026,12 @@ static ssize_t dhd_store(struct kobject *kobj, struct attribute *attr, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif dhd_info_t *dhd = to_dhd(kobj); struct dhd_attr *d_attr = to_attr(attr); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif int ret; if (d_attr->store) @@ -18847,12 +20122,12 @@ dhd_debug_uart_exec(dhd_pub_t *dhdp, char *cmd) #ifdef DHD_FW_COREDUMP if (dhdp->memdump_enabled == DUMP_MEMFILE_BUGON) -#endif +#endif // endif { if (dhdp->hang_reason == HANG_REASON_PCIE_LINK_DOWN || #ifdef DHD_FW_COREDUMP dhdp->memdump_success == FALSE || -#endif +#endif // endif FALSE) { dhdp->info->duart_execute = TRUE; DHD_ERROR(("DHD: %s - execute %s %s\n", @@ -18864,7 +20139,7 @@ dhd_debug_uart_exec(dhd_pub_t *dhdp, char *cmd) #ifdef DHD_LOG_DUMP if (dhdp->memdump_type != DUMP_TYPE_BY_SYSDUMP) -#endif +#endif // endif { BUG_ON(1); } @@ -18904,26 +20179,22 @@ dmaxfer_free_dmaaddr_handler(void *handle, void *event_info, u8 event) { dmaxref_mem_map_t *dmmap = (dmaxref_mem_map_t *)event_info; dhd_info_t *dhd_info = (dhd_info_t *)handle; - dhd_pub_t *dhdp = &dhd_info->pub; if (event != DHD_WQ_WORK_DMA_LB_MEM_REL) { - DHD_ERROR(("%s: unexpected event \n", __FUNCTION__)); + DHD_ERROR(("%s: Unexpected event \n", __FUNCTION__)); return; } - - if ((dhd_info == NULL) || (dhdp == NULL)) { - DHD_ERROR(("%s: invalid dhd_info\n", __FUNCTION__)); + if (dhd_info == NULL) { + DHD_ERROR(("%s: Invalid dhd_info\n", __FUNCTION__)); return; } - if (dmmap == NULL) { DHD_ERROR(("%s: dmmap is null\n", __FUNCTION__)); return; } - dmaxfer_free_prev_dmaaddr(dhdp, dmmap); + dmaxfer_free_prev_dmaaddr(&dhd_info->pub, dmmap); } - void dhd_schedule_dmaxfer_free(dhd_pub_t *dhdp, dmaxref_mem_map_t *dmmap) { @@ -18934,33 +20205,6 @@ dhd_schedule_dmaxfer_free(dhd_pub_t *dhdp, dmaxref_mem_map_t *dmmap) } #endif /* PCIE_FULL_DONGLE */ /* ---------------------------- End of sysfs implementation ------------------------------------- */ -#ifdef HOFFLOAD_MODULES -void -dhd_linux_get_modfw_address(dhd_pub_t *dhd) -{ - const char* module_name = NULL; - const struct firmware *module_fw; - struct module_metadata *hmem = &dhd->hmem; - - if (dhd_hmem_module_string[0] != '\0') { - module_name = dhd_hmem_module_string; - } else { - DHD_ERROR(("%s No module image name specified\n", __FUNCTION__)); - return; - } - if (request_firmware(&module_fw, module_name, dhd_bus_to_dev(dhd->bus))) { - DHD_ERROR(("modules.img not available\n")); - return; - } - if (!dhd_alloc_module_memory(dhd->bus, module_fw->size, hmem)) { - release_firmware(module_fw); - return; - } - memcpy(hmem->data, module_fw->data, module_fw->size); - release_firmware(module_fw); -} -#endif /* HOFFLOAD_MODULES */ - #ifdef SET_PCIE_IRQ_CPU_CORE void dhd_set_irq_cpucore(dhd_pub_t *dhdp, int set) @@ -18984,131 +20228,476 @@ dhd_set_irq_cpucore(dhd_pub_t *dhdp, int set) } #endif /* SET_PCIE_IRQ_CPU_CORE */ -#if defined(DHD_HANG_SEND_UP_TEST) -void -dhd_make_hang_with_reason(struct net_device *dev, const char *string_num) +int +dhd_write_file(const char *filepath, char *buf, int buf_len) { - dhd_info_t *dhd = NULL; - dhd_pub_t *dhdp = NULL; - uint reason = HANG_REASON_MAX; - char buf[WLC_IOCTL_SMLEN] = {0, }; - uint32 fw_test_code = 0; - dhd = DHD_DEV_INFO(dev); - - if (dhd) { - dhdp = &dhd->pub; - } - - if (!dhd || !dhdp) { - return; - } + struct file *fp = NULL; + mm_segment_t old_fs; + int ret = 0; - reason = (uint) bcm_strtoul(string_num, NULL, 0); - DHD_ERROR(("Enter %s, reason=0x%x\n", __FUNCTION__, reason)); + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); - if (reason == 0) { - if (dhdp->req_hang_type) { - DHD_ERROR(("%s, Clear HANG test request 0x%x\n", - __FUNCTION__, dhdp->req_hang_type)); - dhdp->req_hang_type = 0; - return; - } else { - DHD_ERROR(("%s, No requested HANG test\n", __FUNCTION__)); - return; + /* File is always created. */ + fp = filp_open(filepath, O_RDWR | O_CREAT, 0664); + if (IS_ERR(fp)) { + DHD_ERROR(("%s: Couldn't open file '%s' err %ld\n", + __FUNCTION__, filepath, PTR_ERR(fp))); + ret = BCME_ERROR; + } else { + if (fp->f_mode & FMODE_WRITE) { + ret = vfs_write(fp, buf, buf_len, &fp->f_pos); + if (ret < 0) { + DHD_ERROR(("%s: Couldn't write file '%s'\n", + __FUNCTION__, filepath)); + ret = BCME_ERROR; + } else { + ret = BCME_OK; + } } - } else if ((reason <= HANG_REASON_MASK) || (reason >= HANG_REASON_MAX)) { - DHD_ERROR(("Invalid HANG request, reason 0x%x\n", reason)); - return; + filp_close(fp, NULL); } - if (dhdp->req_hang_type != 0) { - DHD_ERROR(("Already HANG requested for test\n")); - return; - } + /* restore previous address limit */ + set_fs(old_fs); - switch (reason) { - case HANG_REASON_IOCTL_RESP_TIMEOUT: - DHD_ERROR(("Make HANG!!!: IOCTL response timeout(0x%x)\n", reason)); - dhdp->req_hang_type = reason; - fw_test_code = 102; /* resumed on timeour */ - bcm_mkiovar("bus:disconnect", (void *)&fw_test_code, 4, buf, sizeof(buf)); - dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); - break; - case HANG_REASON_DONGLE_TRAP: - DHD_ERROR(("Make HANG!!!: Dongle trap (0x%x)\n", reason)); - dhdp->req_hang_type = reason; - fw_test_code = 99; /* dongle trap */ - bcm_mkiovar("bus:disconnect", (void *)&fw_test_code, 4, buf, sizeof(buf)); - dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); - break; - case HANG_REASON_D3_ACK_TIMEOUT: - DHD_ERROR(("Make HANG!!!: D3 ACK timeout (0x%x)\n", reason)); - dhdp->req_hang_type = reason; - break; - case HANG_REASON_BUS_DOWN: - DHD_ERROR(("Make HANG!!!: BUS down(0x%x)\n", reason)); - dhdp->req_hang_type = reason; - break; - case HANG_REASON_PCIE_LINK_DOWN: - case HANG_REASON_MSGBUF_LIVELOCK: - dhdp->req_hang_type = 0; - DHD_ERROR(("Does not support requested HANG(0x%x)\n", reason)); - break; - case HANG_REASON_IFACE_OP_FAILURE: - DHD_ERROR(("Make HANG!!!: P2P inrerface delete failure(0x%x)\n", reason)); - dhdp->req_hang_type = reason; - break; - case HANG_REASON_HT_AVAIL_ERROR: - dhdp->req_hang_type = 0; - DHD_ERROR(("PCIe does not support requested HANG(0x%x)\n", reason)); - break; - case HANG_REASON_PCIE_RC_LINK_UP_FAIL: - DHD_ERROR(("Make HANG!!!:Link Up(0x%x)\n", reason)); - dhdp->req_hang_type = reason; - break; - default: - dhdp->req_hang_type = 0; - DHD_ERROR(("Unknown HANG request (0x%x)\n", reason)); - break; - } -} -#endif /* DHD_HANG_SEND_UP_TEST */ -#ifdef DHD_WAKE_STATUS -wake_counts_t* -dhd_get_wakecount(dhd_pub_t *dhdp) -{ - return dhd_bus_get_wakecount(dhdp); + return ret; } -#endif /* DHD_WAKE_STATUS */ -#ifdef BCM_ASLR_HEAP -uint32 -dhd_get_random_number(void) +int +dhd_read_file(const char *filepath, char *buf, int buf_len) { - uint32 rand = 0; - get_random_bytes_arch(&rand, sizeof(rand)); - return rand; -} -#endif /* BCM_ASLR_HEAP */ + struct file *fp = NULL; + mm_segment_t old_fs; + int ret; -#ifdef DHD_PKT_LOGGING -void -dhd_pktlog_dump(void *handle, void *event_info, u8 event) -{ - dhd_info_t *dhd = handle; + /* change to KERNEL_DS address limit */ + old_fs = get_fs(); + set_fs(KERNEL_DS); - if (!dhd) { - DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); - return; + fp = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(fp)) { + set_fs(old_fs); + DHD_ERROR(("%s: File %s doesn't exist\n", __FUNCTION__, filepath)); + return BCME_ERROR; } - if (dhd_pktlog_write_file(&dhd->pub)) { - DHD_ERROR(("%s: writing pktlog dump to the file failed\n", __FUNCTION__)); - return; + ret = kernel_read(fp, 0, buf, buf_len); + filp_close(fp, NULL); + + /* restore previous address limit */ + set_fs(old_fs); + + /* Return the number of bytes read */ + if (ret > 0) { + /* Success to read */ + ret = 0; + } else { + DHD_ERROR(("%s: Couldn't read the file %s, ret=%d\n", + __FUNCTION__, filepath, ret)); + ret = BCME_ERROR; } + + return ret; } -void +int +dhd_write_file_and_check(const char *filepath, char *buf, int buf_len) +{ + int ret; + + ret = dhd_write_file(filepath, buf, buf_len); + if (ret < 0) { + return ret; + } + + /* Read the file again and check if the file size is not zero */ + memset(buf, 0, buf_len); + ret = dhd_read_file(filepath, buf, buf_len); + + return ret; +} + +#ifdef FILTER_IE +int dhd_read_from_file(dhd_pub_t *dhd) +{ + int ret = 0, nread = 0; + void *fd; + uint8 *buf; + NULL_CHECK(dhd, "dhd is NULL", ret); + + buf = MALLOCZ(dhd->osh, FILE_BLOCK_READ_SIZE); + if (!buf) { + DHD_ERROR(("error: failed to alllocate buf.\n")); + return BCME_NOMEM; + } + + /* open file to read */ + fd = dhd_os_open_image1(dhd, FILTER_IE_PATH); + if (!fd) { + DHD_ERROR(("error: failed to open %s\n", FILTER_IE_PATH)); + ret = BCME_EPERM; + goto exit; + } + nread = dhd_os_get_image_block(buf, (FILE_BLOCK_READ_SIZE - 1), fd); + if (nread > 0) { + buf[nread] = '\0'; + if ((ret = dhd_parse_filter_ie(dhd, buf)) < 0) { + DHD_ERROR(("error: failed to parse filter ie\n")); + } + } else { + DHD_ERROR(("error: zero length file.failed to read\n")); + ret = BCME_ERROR; + } + dhd_os_close_image1(dhd, fd); +exit: + if (buf) { + MFREE(dhd->osh, buf, FILE_BLOCK_READ_SIZE); + buf = NULL; + } + return ret; +} + +int dhd_get_filter_ie_count(dhd_pub_t *dhdp, uint8* buf) +{ + uint8* pstr = buf; + int element_count = 0; + + if (buf == NULL) { + return BCME_ERROR; + } + + while (*pstr != '\0') { + if (*pstr == '\n') { + element_count++; + } + pstr++; + } + /* + * New line character must not be present after last line. + * To count last line + */ + element_count++; + + return element_count; +} + +int dhd_parse_oui(dhd_pub_t *dhd, uint8 *inbuf, uint8 *oui, int len) +{ + uint8 i, j, msb, lsb, oui_len = 0; + /* + * OUI can vary from 3 bytes to 5 bytes. + * While reading from file as ascii input it can + * take maximum size of 14 bytes and minumum size of + * 8 bytes including ":" + * Example 5byte OUI + * Example 3byte OUI + */ + + if ((inbuf == NULL) || (len < 8) || (len > 14)) { + DHD_ERROR(("error: failed to parse OUI \n")); + return BCME_ERROR; + } + + for (j = 0, i = 0; i < len; i += 3, ++j) { + if (!bcm_isxdigit(inbuf[i]) || !bcm_isxdigit(inbuf[i + 1])) { + DHD_ERROR(("error: invalid OUI format \n")); + return BCME_ERROR; + } + msb = inbuf[i] > '9' ? bcm_toupper(inbuf[i]) - 'A' + 10 : inbuf[i] - '0'; + lsb = inbuf[i + 1] > '9' ? bcm_toupper(inbuf[i + 1]) - + 'A' + 10 : inbuf[i + 1] - '0'; + oui[j] = (msb << 4) | lsb; + } + /* Size of oui.It can vary from 3/4/5 */ + oui_len = j; + + return oui_len; +} + +int dhd_check_valid_ie(dhd_pub_t *dhdp, uint8* buf, int len) +{ + int i = 0; + + while (i < len) { + if (!bcm_isdigit(buf[i])) { + DHD_ERROR(("error: non digit value found in filter_ie \n")); + return BCME_ERROR; + } + i++; + } + if (bcm_atoi((char*)buf) > 255) { + DHD_ERROR(("error: element id cannot be greater than 255 \n")); + return BCME_ERROR; + } + + return BCME_OK; +} + +int dhd_parse_filter_ie(dhd_pub_t *dhd, uint8 *buf) +{ + int element_count = 0, i = 0, oui_size = 0, ret = 0; + uint16 bufsize, buf_space_left, id = 0, len = 0; + uint16 filter_iovsize, all_tlvsize; + wl_filter_ie_tlv_t *p_ie_tlv = NULL; + wl_filter_ie_iov_v1_t *p_filter_iov = (wl_filter_ie_iov_v1_t *) NULL; + char *token = NULL, *ele_token = NULL, *oui_token = NULL, *type = NULL; + uint8 data[20]; + + element_count = dhd_get_filter_ie_count(dhd, buf); + DHD_INFO(("total element count %d \n", element_count)); + /* Calculate the whole buffer size */ + filter_iovsize = sizeof(wl_filter_ie_iov_v1_t) + FILTER_IE_BUFSZ; + p_filter_iov = MALLOCZ(dhd->osh, filter_iovsize); + + if (p_filter_iov == NULL) { + DHD_ERROR(("error: failed to allocate %d bytes of memory\n", filter_iovsize)); + return BCME_ERROR; + } + + /* setup filter iovar header */ + p_filter_iov->version = WL_FILTER_IE_VERSION; + p_filter_iov->len = filter_iovsize; + p_filter_iov->fixed_length = p_filter_iov->len - FILTER_IE_BUFSZ; + p_filter_iov->pktflag = FC_PROBE_REQ; + p_filter_iov->option = WL_FILTER_IE_CHECK_SUB_OPTION; + /* setup TLVs */ + bufsize = filter_iovsize - WL_FILTER_IE_IOV_HDR_SIZE; /* adjust available size for TLVs */ + p_ie_tlv = (wl_filter_ie_tlv_t *)&p_filter_iov->tlvs[0]; + buf_space_left = bufsize; + + while ((i < element_count) && (buf != NULL)) { + len = 0; + /* token contains one line of input data */ + token = bcmstrtok((char**)&buf, "\n", NULL); + if (token == NULL) { + break; + } + if ((ele_token = bcmstrstr(token, ",")) == NULL) { + /* only element id is present */ + if (dhd_check_valid_ie(dhd, token, strlen(token)) == BCME_ERROR) { + DHD_ERROR(("error: Invalid element id \n")); + ret = BCME_ERROR; + goto exit; + } + id = bcm_atoi((char*)token); + data[len++] = WL_FILTER_IE_SET; + } else { + /* oui is present */ + ele_token = bcmstrtok(&token, ",", NULL); + if ((ele_token == NULL) || (dhd_check_valid_ie(dhd, ele_token, + strlen(ele_token)) == BCME_ERROR)) { + DHD_ERROR(("error: Invalid element id \n")); + ret = BCME_ERROR; + goto exit; + } + id = bcm_atoi((char*)ele_token); + data[len++] = WL_FILTER_IE_SET; + if ((oui_token = bcmstrstr(token, ",")) == NULL) { + oui_size = dhd_parse_oui(dhd, token, &(data[len]), strlen(token)); + if (oui_size == BCME_ERROR) { + DHD_ERROR(("error: Invalid OUI \n")); + ret = BCME_ERROR; + goto exit; + } + len += oui_size; + } else { + /* type is present */ + oui_token = bcmstrtok(&token, ",", NULL); + if ((oui_token == NULL) || ((oui_size = + dhd_parse_oui(dhd, oui_token, + &(data[len]), strlen(oui_token))) == BCME_ERROR)) { + DHD_ERROR(("error: Invalid OUI \n")); + ret = BCME_ERROR; + goto exit; + } + len += oui_size; + if ((type = bcmstrstr(token, ",")) == NULL) { + if (dhd_check_valid_ie(dhd, token, + strlen(token)) == BCME_ERROR) { + DHD_ERROR(("error: Invalid type \n")); + ret = BCME_ERROR; + goto exit; + } + data[len++] = bcm_atoi((char*)token); + } else { + /* subtype is present */ + type = bcmstrtok(&token, ",", NULL); + if ((type == NULL) || (dhd_check_valid_ie(dhd, type, + strlen(type)) == BCME_ERROR)) { + DHD_ERROR(("error: Invalid type \n")); + ret = BCME_ERROR; + goto exit; + } + data[len++] = bcm_atoi((char*)type); + /* subtype is last element */ + if ((token == NULL) || (*token == '\0') || + (dhd_check_valid_ie(dhd, token, + strlen(token)) == BCME_ERROR)) { + DHD_ERROR(("error: Invalid subtype \n")); + ret = BCME_ERROR; + goto exit; + } + data[len++] = bcm_atoi((char*)token); + } + } + } + ret = bcm_pack_xtlv_entry((uint8 **)&p_ie_tlv, + &buf_space_left, id, len, data, BCM_XTLV_OPTION_ALIGN32); + if (ret != BCME_OK) { + DHD_ERROR(("%s : bcm_pack_xtlv_entry() failed ," + "status=%d\n", __FUNCTION__, ret)); + goto exit; + } + i++; + } + if (i == 0) { + /* file is empty or first line is blank */ + DHD_ERROR(("error: filter_ie file is empty or first line is blank \n")); + ret = BCME_ERROR; + goto exit; + } + /* update the iov header, set len to include all TLVs + header */ + all_tlvsize = (bufsize - buf_space_left); + p_filter_iov->len = htol16(all_tlvsize + WL_FILTER_IE_IOV_HDR_SIZE); + ret = dhd_iovar(dhd, 0, "filter_ie", (void *)p_filter_iov, + p_filter_iov->len, NULL, 0, TRUE); + if (ret != BCME_OK) { + DHD_ERROR(("error: IOVAR failed, status=%d\n", ret)); + } +exit: + /* clean up */ + if (p_filter_iov) { + MFREE(dhd->osh, p_filter_iov, filter_iovsize); + p_filter_iov = NULL; + } + return ret; +} +#endif /* FILTER_IE */ +#ifdef DHD_WAKE_STATUS +wake_counts_t* +dhd_get_wakecount(dhd_pub_t *dhdp) +{ + return dhd_bus_get_wakecount(dhdp); +} +#endif /* DHD_WAKE_STATUS */ + +void +dhd_get_random_bytes(uint8 *buf, uint len) +{ +#ifdef BCMPCIE + get_random_bytes_arch(buf, len); +#endif /* BCMPCIE */ +} + +#if defined(DHD_HANG_SEND_UP_TEST) +void +dhd_make_hang_with_reason(struct net_device *dev, const char *string_num) +{ + dhd_info_t *dhd = NULL; + dhd_pub_t *dhdp = NULL; + uint reason = HANG_REASON_MAX; + uint32 fw_test_code = 0; + dhd = DHD_DEV_INFO(dev); + + if (dhd) { + dhdp = &dhd->pub; + } + + if (!dhd || !dhdp) { + return; + } + + reason = (uint) bcm_strtoul(string_num, NULL, 0); + DHD_ERROR(("Enter %s, reason=0x%x\n", __FUNCTION__, reason)); + + if (reason == 0) { + if (dhdp->req_hang_type) { + DHD_ERROR(("%s, Clear HANG test request 0x%x\n", + __FUNCTION__, dhdp->req_hang_type)); + dhdp->req_hang_type = 0; + return; + } else { + DHD_ERROR(("%s, No requested HANG test\n", __FUNCTION__)); + return; + } + } else if ((reason <= HANG_REASON_MASK) || (reason >= HANG_REASON_MAX)) { + DHD_ERROR(("Invalid HANG request, reason 0x%x\n", reason)); + return; + } + + if (dhdp->req_hang_type != 0) { + DHD_ERROR(("Already HANG requested for test\n")); + return; + } + + switch (reason) { + case HANG_REASON_IOCTL_RESP_TIMEOUT: + DHD_ERROR(("Make HANG!!!: IOCTL response timeout(0x%x)\n", reason)); + dhdp->req_hang_type = reason; + fw_test_code = 102; /* resumed on timeour */ + dhd_wl_ioctl_set_intiovar(dhdp, "bus:disconnect", fw_test_code, + WLC_SET_VAR, TRUE, 0); + break; + case HANG_REASON_DONGLE_TRAP: + DHD_ERROR(("Make HANG!!!: Dongle trap (0x%x)\n", reason)); + dhdp->req_hang_type = reason; + fw_test_code = 99; /* dongle trap */ + dhd_wl_ioctl_set_intiovar(dhdp, "bus:disconnect", fw_test_code, + WLC_SET_VAR, TRUE, 0); + break; + case HANG_REASON_D3_ACK_TIMEOUT: + DHD_ERROR(("Make HANG!!!: D3 ACK timeout (0x%x)\n", reason)); + dhdp->req_hang_type = reason; + break; + case HANG_REASON_BUS_DOWN: + DHD_ERROR(("Make HANG!!!: BUS down(0x%x)\n", reason)); + dhdp->req_hang_type = reason; + break; + case HANG_REASON_PCIE_LINK_DOWN: + case HANG_REASON_MSGBUF_LIVELOCK: + dhdp->req_hang_type = 0; + DHD_ERROR(("Does not support requested HANG(0x%x)\n", reason)); + break; + case HANG_REASON_IFACE_DEL_FAILURE: + dhdp->req_hang_type = 0; + DHD_ERROR(("Does not support requested HANG(0x%x)\n", reason)); + break; + case HANG_REASON_HT_AVAIL_ERROR: + dhdp->req_hang_type = 0; + DHD_ERROR(("PCIe does not support requested HANG(0x%x)\n", reason)); + break; + case HANG_REASON_PCIE_RC_LINK_UP_FAIL: + DHD_ERROR(("Make HANG!!!:Link Up(0x%x)\n", reason)); + dhdp->req_hang_type = reason; + break; + default: + dhdp->req_hang_type = 0; + DHD_ERROR(("Unknown HANG request (0x%x)\n", reason)); + break; + } +} +#endif /* DHD_HANG_SEND_UP_TEST */ + +#ifdef DHD_PKT_LOGGING +void +dhd_pktlog_dump(void *handle, void *event_info, u8 event) +{ + dhd_info_t *dhd = handle; + + if (!dhd) { + DHD_ERROR(("%s: dhd is NULL\n", __FUNCTION__)); + return; + } + + if (dhd_pktlog_write_file(&dhd->pub)) { + DHD_ERROR(("%s: writing pktlog dump to the file failed\n", __FUNCTION__)); + return; + } +} + +void dhd_schedule_pktlog_dump(dhd_pub_t *dhdp) { dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, @@ -19116,3 +20705,952 @@ dhd_schedule_pktlog_dump(dhd_pub_t *dhdp) dhd_pktlog_dump, DHD_WQ_WORK_PRIORITY_HIGH); } #endif /* DHD_PKT_LOGGING */ + +#ifdef BIGDATA_SOFTAP +void dhd_schedule_gather_ap_stadata(void *bcm_cfg, void *ndev, const wl_event_msg_t *e) +{ + struct bcm_cfg80211 *cfg; + dhd_pub_t *dhdp; + ap_sta_wq_data_t *p_wq_data; + + if (!bcm_cfg || !ndev || !e) { + WL_ERR(("bcm_cfg=%p ndev=%p e=%p\n", bcm_cfg, ndev, e)); + return; + } + + cfg = (struct bcm_cfg80211 *)bcm_cfg; + dhdp = (dhd_pub_t *)cfg->pub; + + if (!dhdp || !cfg->ap_sta_info) { + WL_ERR(("dhdp=%p ap_sta_info=%p\n", dhdp, cfg->ap_sta_info)); + return; + } + + p_wq_data = (ap_sta_wq_data_t *)MALLOCZ(dhdp->osh, sizeof(ap_sta_wq_data_t)); + if (unlikely(!p_wq_data)) { + DHD_ERROR(("%s(): could not allocate memory for - " + "ap_sta_wq_data_t\n", __FUNCTION__)); + return; + } + + mutex_lock(&cfg->ap_sta_info->wq_data_sync); + + memcpy(&p_wq_data->e, e, sizeof(wl_event_msg_t)); + p_wq_data->dhdp = dhdp; + p_wq_data->bcm_cfg = cfg; + p_wq_data->ndev = (struct net_device *)ndev; + + mutex_unlock(&cfg->ap_sta_info->wq_data_sync); + + dhd_deferred_schedule_work(dhdp->info->dhd_deferred_wq, + p_wq_data, DHD_WQ_WORK_GET_BIGDATA_AP, + wl_gather_ap_stadata, DHD_WQ_WORK_PRIORITY_HIGH); + +} +#endif /* BIGDATA_SOFTAP */ + +void +get_debug_dump_time(char *str) +{ + struct timeval curtime; + unsigned long local_time; + struct rtc_time tm; + + if (!strlen(str)) { + do_gettimeofday(&curtime); + local_time = (u32)(curtime.tv_sec - + (sys_tz.tz_minuteswest * DHD_LOG_DUMP_TS_MULTIPLIER_VALUE)); + rtc_time_to_tm(local_time, &tm); + + snprintf(str, DEBUG_DUMP_TIME_BUF_LEN, DHD_LOG_DUMP_TS_FMT_YYMMDDHHMMSSMSMS, + tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, + tm.tm_sec, (int)(curtime.tv_usec/NSEC_PER_USEC)); + } +} + +void +clear_debug_dump_time(char *str) +{ + memset(str, 0, DEBUG_DUMP_TIME_BUF_LEN); +} +#if defined(WL_CFGVENDOR_SEND_HANG_EVENT) || defined(DHD_PKT_LOGGING) +void +copy_debug_dump_time(char *dest, char *src) +{ + memcpy(dest, src, DEBUG_DUMP_TIME_BUF_LEN); +} +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT || DHD_PKT_LOGGING */ + +#define KIRQ_PRINT_BUF_LEN 256 + +void +dhd_print_kirqstats(dhd_pub_t *dhd, unsigned int irq_num) +{ + unsigned long flags = 0; + struct irq_desc *desc; + int i; /* cpu iterator */ + struct bcmstrbuf strbuf; + char tmp_buf[KIRQ_PRINT_BUF_LEN]; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) + desc = irq_to_desc(irq_num); + if (!desc) { + DHD_ERROR(("%s : irqdesc is not found \n", __FUNCTION__)); + return; + } + bcm_binit(&strbuf, tmp_buf, KIRQ_PRINT_BUF_LEN); + raw_spin_lock_irqsave(&desc->lock, flags); + bcm_bprintf(&strbuf, "dhd irq %u:", irq_num); + for_each_online_cpu(i) + bcm_bprintf(&strbuf, "%10u ", + desc->kstat_irqs ? *per_cpu_ptr(desc->kstat_irqs, i) : 0); + if (desc->irq_data.chip) { + if (desc->irq_data.chip->name) + bcm_bprintf(&strbuf, " %8s", desc->irq_data.chip->name); + else + bcm_bprintf(&strbuf, " %8s", "-"); + } else { + bcm_bprintf(&strbuf, " %8s", "None"); + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) + if (desc->irq_data.domain) + bcm_bprintf(&strbuf, " %d", (int)desc->irq_data.hwirq); +#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL + bcm_bprintf(&strbuf, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge"); +#endif // endif +#endif /* LINUX VERSION > 3.1.0 */ + + if (desc->name) + bcm_bprintf(&strbuf, "-%-8s", desc->name); + + DHD_ERROR(("%s\n", strbuf.origbuf)); + raw_spin_unlock_irqrestore(&desc->lock, flags); +#endif /* LINUX VERSION > 2.6.28 */ +} + +void +dhd_show_kirqstats(dhd_pub_t *dhd) +{ + unsigned int irq = -1; +#ifdef BCMPCIE + dhdpcie_get_pcieirq(dhd->bus, &irq); +#endif /* BCMPCIE */ +#ifdef BCMSDIO + irq = ((wifi_adapter_info_t *)dhd->info->adapter)->irq_num; +#endif /* BCMSDIO */ + if (irq != -1) { +#ifdef BCMPCIE + DHD_ERROR(("DUMP data kernel irq stats : \n")); +#endif /* BCMPCIE */ +#ifdef BCMSDIO + DHD_ERROR(("DUMP data/host wakeup kernel irq stats : \n")); +#endif /* BCMSDIO */ + dhd_print_kirqstats(dhd, irq); + } +#ifdef BCMPCIE_OOB_HOST_WAKE + irq = dhdpcie_get_oob_irq_num(dhd->bus); + if (irq) { + DHD_ERROR(("DUMP PCIE host wakeup kernel irq stats : \n")); + dhd_print_kirqstats(dhd, irq); + } +#endif /* BCMPCIE_OOB_HOST_WAKE */ +} + +void +dhd_print_tasklet_status(dhd_pub_t *dhd) +{ + dhd_info_t *dhdinfo; + + if (!dhd) { + DHD_ERROR(("%s : DHD is null\n", __FUNCTION__)); + return; + } + + dhdinfo = dhd->info; + + if (!dhdinfo) { + DHD_ERROR(("%s : DHD INFO is null \n", __FUNCTION__)); + return; + } + + DHD_ERROR(("DHD Tasklet status : 0x%lx\n", dhdinfo->tasklet.state)); +} + +/* + * DHD RING + */ +#define DHD_RING_ERR_INTERNAL(fmt, ...) DHD_ERROR(("EWPF-" fmt, ##__VA_ARGS__)) +#define DHD_RING_TRACE_INTERNAL(fmt, ...) DHD_INFO(("EWPF-" fmt, ##__VA_ARGS__)) + +#define DHD_RING_ERR(x) DHD_RING_ERR_INTERNAL x +#define DHD_RING_TRACE(x) DHD_RING_TRACE_INTERNAL x + +#define DHD_RING_MAGIC 0x20170910 +#define DHD_RING_IDX_INVALID 0xffffffff + +typedef struct { + uint32 elem_size; + uint32 elem_cnt; + uint32 write_idx; /* next write index, -1 : not started */ + uint32 read_idx; /* next read index, -1 : not start */ + + /* protected elements during serialization */ + int lock_idx; /* start index of locked, element will not be overried */ + int lock_count; /* number of locked, from lock idx */ + + /* saved data elements */ + void *elem; +} dhd_fixed_ring_info_t; + +typedef struct { + uint32 magic; + uint32 type; + struct mutex ring_sync; /* pointer to mutex */ + union { + dhd_fixed_ring_info_t fixed; + }; +} dhd_ring_info_t; + +uint32 +dhd_ring_get_hdr_size(void) +{ + return sizeof(dhd_ring_info_t); +} + +void * +dhd_ring_init(uint8 *buf, uint32 buf_size, uint32 elem_size, uint32 elem_cnt) +{ + dhd_ring_info_t *ret_ring; + + if (!buf) { + DHD_RING_ERR(("NO RING BUFFER\n")); + return NULL; + } + if (buf_size < dhd_ring_get_hdr_size() + elem_size * elem_cnt) { + DHD_RING_ERR(("RING SIZE IS TOO SMALL\n")); + return NULL; + } + + ret_ring = (dhd_ring_info_t *)buf; + ret_ring->type = DHD_RING_TYPE_FIXED; + mutex_init(&ret_ring->ring_sync); + ret_ring->fixed.read_idx = DHD_RING_IDX_INVALID; + ret_ring->fixed.write_idx = DHD_RING_IDX_INVALID; + ret_ring->fixed.lock_idx = DHD_RING_IDX_INVALID; + ret_ring->fixed.elem = buf + sizeof(dhd_ring_info_t); + ret_ring->fixed.elem_size = elem_size; + ret_ring->fixed.elem_cnt = elem_cnt; + ret_ring->magic = DHD_RING_MAGIC; + return ret_ring; +} + +void +dhd_ring_deinit(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + dhd_fixed_ring_info_t *fixed; + if (!ring) { + return; + } + + if (ring->magic != DHD_RING_MAGIC) { + return; + } + + mutex_destroy(&ring->ring_sync); + fixed = &ring->fixed; + memset(fixed->elem, 0, fixed->elem_size * fixed->elem_cnt); + fixed->elem_size = fixed->elem_cnt = 0; + ring->type = 0; + ring->magic = 0; + return; +} + +/* get counts between two indexes of ring buffer (internal only) */ +static inline int +__dhd_fixed_ring_get_count(dhd_fixed_ring_info_t *ring, int start, int end) +{ + if (start == DHD_RING_IDX_INVALID || end == DHD_RING_IDX_INVALID) { + return 0; + } + + return (ring->elem_cnt + end - start) % ring->elem_cnt + 1; +} + +static inline int +__dhd_fixed_ring_get_cur_size(dhd_fixed_ring_info_t *ring) +{ + return __dhd_fixed_ring_get_count(ring, ring->read_idx, ring->write_idx); +} + +static inline void * +__dhd_fixed_ring_get_first(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + return NULL; + } + return (uint8 *)ring->elem + (ring->elem_size * ring->read_idx); +} + +static inline void +__dhd_fixed_ring_free_first(dhd_fixed_ring_info_t *ring) +{ + uint32 next_idx; + + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return; + } + + next_idx = (ring->read_idx + 1) % ring->elem_cnt; + if (ring->read_idx == ring->write_idx) { + /* Become empty */ + ring->read_idx = ring->write_idx = DHD_RING_IDX_INVALID; + return; + } + + ring->read_idx = next_idx; + return; +} + +static inline void * +__dhd_fixed_ring_get_last(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + return NULL; + } + return (uint8 *)ring->elem + (ring->elem_size * ring->write_idx); +} + +static inline void * +__dhd_fixed_ring_get_empty(dhd_fixed_ring_info_t *ring) +{ + uint32 tmp_idx; + + if (ring->read_idx == DHD_RING_IDX_INVALID) { + ring->read_idx = ring->write_idx = 0; + return (uint8 *)ring->elem; + } + + /* check next index is not locked */ + tmp_idx = (ring->write_idx + 1) % ring->elem_cnt; + if (ring->lock_idx == tmp_idx) { + return NULL; + } + + ring->write_idx = tmp_idx; + if (ring->write_idx == ring->read_idx) { + /* record is full, drop oldest one */ + ring->read_idx = (ring->read_idx + 1) % ring->elem_cnt; + + } + return (uint8 *)ring->elem + (ring->elem_size * ring->write_idx); +} + +static inline uint32 +__dhd_fixed_ring_ptr2idx(dhd_fixed_ring_info_t *ring, void *ptr, char *sig) +{ + uint32 diff; + uint32 ret_idx = (uint32)DHD_RING_IDX_INVALID; + + if (ptr < ring->elem) { + DHD_RING_ERR(("INVALID POINTER %s:%p, ring->elem:%p\n", sig, ptr, ring->elem)); + return ret_idx; + } + diff = (uint32)((uint8 *)ptr - (uint8 *)ring->elem); + if (diff % ring->elem_size != 0) { + DHD_RING_ERR(("INVALID POINTER %s:%p, ring->elem:%p\n", sig, ptr, ring->elem)); + return ret_idx; + } + ret_idx = diff / ring->elem_size; + if (ret_idx >= ring->elem_cnt) { + DHD_RING_ERR(("INVALID POINTER max:%d cur:%d\n", ring->elem_cnt, ret_idx)); + } + return ret_idx; +} + +static inline void * +__dhd_fixed_ring_get_next(dhd_fixed_ring_info_t *ring, void *prev) +{ + uint32 cur_idx; + + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return NULL; + } + + cur_idx = __dhd_fixed_ring_ptr2idx(ring, prev, "NEXT"); + if (cur_idx >= ring->elem_cnt) { + return NULL; + } + + if (cur_idx == ring->write_idx) { + /* no more new record */ + return NULL; + } + + cur_idx = (cur_idx + 1) % ring->elem_cnt; + return (uint8 *)ring->elem + ring->elem_size * cur_idx; +} + +static inline void * +__dhd_fixed_ring_get_prev(dhd_fixed_ring_info_t *ring, void *prev) +{ + uint32 cur_idx; + + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return NULL; + } + cur_idx = __dhd_fixed_ring_ptr2idx(ring, prev, "PREV"); + if (cur_idx >= ring->elem_cnt) { + return NULL; + } + if (cur_idx == ring->read_idx) { + /* no more new record */ + return NULL; + } + + cur_idx = (cur_idx + ring->elem_cnt - 1) % ring->elem_cnt; + return (uint8 *)ring->elem + ring->elem_size * cur_idx; +} + +static inline void +__dhd_fixed_ring_lock(dhd_fixed_ring_info_t *ring, void *first_ptr, void *last_ptr) +{ + uint32 first_idx; + uint32 last_idx; + uint32 ring_filled_cnt; + uint32 tmp_cnt; + + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return; + } + + if (first_ptr) { + first_idx = __dhd_fixed_ring_ptr2idx(ring, first_ptr, "LCK FIRST"); + if (first_idx >= ring->elem_cnt) { + return; + } + } else { + first_idx = ring->read_idx; + } + + if (last_ptr) { + last_idx = __dhd_fixed_ring_ptr2idx(ring, last_ptr, "LCK LAST"); + if (last_idx >= ring->elem_cnt) { + return; + } + } else { + last_idx = ring->write_idx; + } + + ring_filled_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, ring->write_idx); + tmp_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, first_idx); + if (tmp_cnt > ring_filled_cnt) { + DHD_RING_ERR(("LOCK FIRST IS TO EMPTY ELEM: write: %d read: %d cur:%d\n", + ring->write_idx, ring->read_idx, first_idx)); + return; + } + + tmp_cnt = __dhd_fixed_ring_get_count(ring, ring->read_idx, last_idx); + if (tmp_cnt > ring_filled_cnt) { + DHD_RING_ERR(("LOCK LAST IS TO EMPTY ELEM: write: %d read: %d cur:%d\n", + ring->write_idx, ring->read_idx, last_idx)); + return; + } + + ring->lock_idx = first_idx; + ring->lock_count = __dhd_fixed_ring_get_count(ring, first_idx, last_idx); + return; +} + +static inline void +__dhd_fixed_ring_lock_free(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return; + } + + ring->lock_idx = DHD_RING_IDX_INVALID; + ring->lock_count = 0; + return; +} +static inline void * +__dhd_fixed_ring_lock_get_first(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return NULL; + } + if (ring->lock_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("NO LOCK POINT\n")); + return NULL; + } + return (uint8 *)ring->elem + ring->elem_size * ring->lock_idx; +} + +static inline void * +__dhd_fixed_ring_lock_get_last(dhd_fixed_ring_info_t *ring) +{ + int lock_last_idx; + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return NULL; + } + if (ring->lock_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("NO LOCK POINT\n")); + return NULL; + } + + lock_last_idx = (ring->lock_idx + ring->lock_count - 1) % ring->elem_cnt; + return (uint8 *)ring->elem + ring->elem_size * lock_last_idx; +} + +static inline int +__dhd_fixed_ring_lock_get_count(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return BCME_ERROR; + } + if (ring->lock_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("NO LOCK POINT\n")); + return BCME_ERROR; + } + return ring->lock_count; +} + +static inline void +__dhd_fixed_ring_lock_free_first(dhd_fixed_ring_info_t *ring) +{ + if (ring->read_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("EMPTY RING\n")); + return; + } + if (ring->lock_idx == DHD_RING_IDX_INVALID) { + DHD_RING_ERR(("NO LOCK POINT\n")); + return; + } + + ring->lock_count--; + if (ring->lock_count <= 0) { + ring->lock_idx = DHD_RING_IDX_INVALID; + } else { + ring->lock_idx = (ring->lock_idx + 1) % ring->elem_cnt; + } + return; +} + +/* Get first element : oldest element */ +void * +dhd_ring_get_first(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_get_first(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +/* Free first element : oldest element */ +void +dhd_ring_free_first(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + __dhd_fixed_ring_free_first(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return; +} + +/* Get latest element */ +void * +dhd_ring_get_last(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_get_last(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +/* Get next point can be written + * will overwrite which doesn't read + * will return NULL if next pointer is locked + */ +void * +dhd_ring_get_empty(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_get_empty(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +void * +dhd_ring_get_next(void *_ring, void *cur) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_get_next(&ring->fixed, cur); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +void * +dhd_ring_get_prev(void *_ring, void *cur) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_get_prev(&ring->fixed, cur); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +int +dhd_ring_get_cur_size(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + int cnt = 0; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return cnt; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + cnt = __dhd_fixed_ring_get_cur_size(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return cnt; +} + +/* protect element between lock_ptr and write_idx */ +void +dhd_ring_lock(void *_ring, void *first_ptr, void *last_ptr) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + __dhd_fixed_ring_lock(&ring->fixed, first_ptr, last_ptr); + } + mutex_unlock(&ring->ring_sync); + return; +} + +/* free all lock */ +void +dhd_ring_lock_free(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + __dhd_fixed_ring_lock_free(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return; +} + +void * +dhd_ring_lock_get_first(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_lock_get_first(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +void * +dhd_ring_lock_get_last(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + void *ret = NULL; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return NULL; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_lock_get_last(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +int +dhd_ring_lock_get_count(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + int ret = BCME_ERROR; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return ret; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + ret = __dhd_fixed_ring_lock_get_count(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return ret; +} + +/* free first locked element */ +void +dhd_ring_lock_free_first(void *_ring) +{ + dhd_ring_info_t *ring = (dhd_ring_info_t *)_ring; + + if (!ring || ring->magic != DHD_RING_MAGIC) { + DHD_RING_ERR(("%s :INVALID RING INFO\n", __FUNCTION__)); + return; + } + + mutex_lock(&ring->ring_sync); + if (ring->type == DHD_RING_TYPE_FIXED) { + __dhd_fixed_ring_lock_free_first(&ring->fixed); + } + mutex_unlock(&ring->ring_sync); + return; +} + +#ifdef DHD_DUMP_MNGR +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0)) +#define DHD_VFS_INODE(dir) (dir->d_inode) +#else +#define DHD_VFS_INODE(dir) d_inode(dir) +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 19, 0) */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0)) +#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b) +#else +#define DHD_VFS_UNLINK(dir, b, c) vfs_unlink(DHD_VFS_INODE(dir), b, c) +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */ + +static int +dhd_file_delete(char *path) +{ + struct path file_path; + int err; + struct dentry *dir; + + err = kern_path(path, 0, &file_path); + + if (err < 0) { + return err; + } + if (FALSE || +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)) + !d_is_file(file_path.dentry) || +#if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 0, 0)) + d_really_is_negative(file_path.dentry) +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(4, 0, 0) */ +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) */ +) + { + err = -EINVAL; + } else { + dir = dget_parent(file_path.dentry); + + if (!IS_ERR(dir)) { + err = DHD_VFS_UNLINK(dir, file_path.dentry, NULL); + dput(dir); + } else { + err = PTR_ERR(dir); + } + } + + path_put(&file_path); + + if (err < 0) { + DHD_ERROR(("Failed to delete file: %s error: %d\n", path, err)); + } + + return err; +} + +static int +dhd_dump_file_manage_idx(dhd_dump_file_manage_t *fm_ptr, char *fname) +{ + int i; + int fm_idx = -1; + + for (i = 0; i < DHD_DUMP_TYPE_COUNT_MAX; i++) { + if (strlen(fm_ptr->elems[i].type_name) == 0) { + fm_idx = i; + break; + } + if (!(strncmp(fname, fm_ptr->elems[i].type_name, strlen(fname)))) { + fm_idx = i; + break; + } + } + + if (fm_idx == -1) { + return fm_idx; + } + + if (strlen(fm_ptr->elems[fm_idx].type_name) == 0) { + strncpy(fm_ptr->elems[fm_idx].type_name, fname, DHD_DUMP_TYPE_NAME_SIZE); + fm_ptr->elems[fm_idx].file_idx = 0; + } + + return fm_idx; +} + +/* + * dhd_dump_file_manage_enqueue - enqueue dump file path + * and delete odest file if file count is max. +*/ +void +dhd_dump_file_manage_enqueue(dhd_pub_t *dhd, char *dump_path, char *fname) +{ + int fm_idx; + int fp_idx; + dhd_dump_file_manage_t *fm_ptr; + DFM_elem_t *elem; + + if (!dhd || !dhd->dump_file_manage) { + DHD_ERROR(("%s(): dhdp=%p dump_file_manage=%p\n", + __FUNCTION__, dhd, (dhd ? dhd->dump_file_manage : NULL))); + return; + } + + fm_ptr = dhd->dump_file_manage; + + /* find file_manage idx */ + DHD_INFO(("%s(): fname: %s dump_path: %s\n", __FUNCTION__, fname, dump_path)); + if ((fm_idx = dhd_dump_file_manage_idx(fm_ptr, fname)) < 0) { + DHD_ERROR(("%s(): Out of file manager entries, fname: %s\n", + __FUNCTION__, fname)); + return; + } + + elem = &fm_ptr->elems[fm_idx]; + fp_idx = elem->file_idx; + DHD_INFO(("%s(): fm_idx: %d fp_idx: %d path: %s\n", + __FUNCTION__, fm_idx, fp_idx, elem->file_path[fp_idx])); + + /* delete oldest file */ + if (strlen(elem->file_path[fp_idx]) != 0) { + if (dhd_file_delete(elem->file_path[fp_idx]) < 0) { + DHD_ERROR(("%s(): Failed to delete file: %s\n", + __FUNCTION__, elem->file_path[fp_idx])); + } else { + DHD_ERROR(("%s(): Successed to delete file: %s\n", + __FUNCTION__, elem->file_path[fp_idx])); + } + } + + /* save dump file path */ + strncpy(elem->file_path[fp_idx], dump_path, DHD_DUMP_FILE_PATH_SIZE); + + /* change file index to next file index */ + elem->file_idx = (elem->file_idx + 1) % DHD_DUMP_FILE_COUNT_MAX; +} +#endif /* DHD_DUMP_MNGR */ + +#ifdef DHD_MAP_LOGGING +/* Will be called from SMMU fault handler */ +void +dhd_debug_info_dump(void) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)g_dhd_pub; + DHD_ERROR(("%s: Trigger SMMU Fault\n", __FUNCTION__)); + + DHD_OS_WAKE_LOCK(dhdp); + dhd_prot_debug_info_print(dhdp); + osl_dma_map_dump(); +#ifdef DHD_FW_COREDUMP + /* Load the dongle side dump to host memory */ + dhdp->memdump_enabled = DUMP_MEMONLY; + dhdp->memdump_type = DUMP_TYPE_SMMU_FAULT; + dhd_bus_mem_dump(dhdp); +#endif /* DHD_FW_COREDUMP */ + DHD_OS_WAKE_UNLOCK(dhdp); +} +EXPORT_SYMBOL(dhd_debug_info_dump); +#endif /* DHD_MAP_LOGGING */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux.h b/drivers/net/wireless/bcmdhd_oo/dhd_linux.h index 534605f40f1ef4a4fa6bf0dd678afde8a69a84eb..654845093bfa3f5cb4880445aa6614ab2239b632 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux.h @@ -1,14 +1,14 @@ /* * DHD Linux header file (dhd_linux exports for cfg80211 and other components) * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_linux.h 733907 2017-11-30 12:20:38Z $ + * $Id: dhd_linux.h 701006 2017-05-23 08:25:04Z $ */ /* wifi platform functions for power, interrupt and pre-alloc, either @@ -49,7 +49,7 @@ #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ #if defined(CONFIG_WIFI_CONTROL_FUNC) #include -#endif +#endif // endif #if !defined(CONFIG_WIFI_CONTROL_FUNC) #define WLAN_PLAT_NODFS_FLAG 0x01 @@ -126,24 +126,10 @@ bool dhd_update_fw_nv_path(struct dhd_info *dhdinfo); int dhd_net_bus_get(struct net_device *dev); int dhd_net_bus_put(struct net_device *dev); #endif /* BT_OVER_SDIO */ -#ifdef HOFFLOAD_MODULES -extern void dhd_free_module_memory(struct dhd_bus *bus, struct module_metadata *hmem); -extern void* dhd_alloc_module_memory(struct dhd_bus *bus, uint32_t size, - struct module_metadata *hmem); -#endif /* HOFFLOAD_MODULES */ #if defined(WLADPS) || defined(WLADPS_PRIVATE_CMD) #define ADPS_ENABLE 1 #define ADPS_DISABLE 0 -typedef struct bcm_iov_buf { - uint16 version; - uint16 len; - uint16 id; - uint16 data[1]; -} bcm_iov_buf_t; int dhd_enable_adps(dhd_pub_t *dhd, uint8 on); #endif /* WLADPS || WLADPS_PRIVATE_CMD */ -#ifdef DHD_DISABLE_VHTMODE -void dhd_disable_vhtmode(dhd_pub_t *dhd); -#endif /* DHD_DISABLE_VHTMODE */ #endif /* __DHD_LINUX_H__ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux_platdev.c b/drivers/net/wireless/bcmdhd_oo/dhd_linux_platdev.c index f20bec0f56b8fc5d7242785adeb2ffe0c8899042..d9602d61609ec2d9d89c356f67c780ecf5a9882f 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux_platdev.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux_platdev.c @@ -1,14 +1,14 @@ /* * Linux platform device for DHD WLAN adapter * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_linux_platdev.c 662397 2016-09-29 10:15:08Z $ + * $Id: dhd_linux_platdev.c 732962 2017-11-22 14:04:49Z $ */ #include #include @@ -41,7 +41,7 @@ #include #if defined(CONFIG_WIFI_CONTROL_FUNC) #include -#endif +#endif // endif #ifdef CONFIG_DTS #include #include @@ -68,12 +68,12 @@ static bool dts_enabled = FALSE; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wmissing-field-initializers" -#endif +#endif // endif struct resource dhd_wlan_resources = {0}; struct wifi_platform_data dhd_wlan_control = {0}; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif #endif /* CONFIG_OF && !defined(CONFIG_ARCH_MSM) */ #endif /* !defind(CONFIG_DTS) */ @@ -150,14 +150,6 @@ int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *ir int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec) { int err = 0; -#ifndef CONFIG_DTS - struct wifi_platform_data *plat_data; -#endif -#ifdef BT_OVER_SDIO - if (is_power_on == on) { - return -EINVAL; - } -#endif /* BT_OVER_SDIO */ #ifdef CONFIG_DTS if (on) { err = regulator_enable(wifi_regulator); @@ -170,6 +162,8 @@ int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long if (err < 0) DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__)); #else + struct wifi_platform_data *plat_data; + if (!adapter || !adapter->wifi_plat_data) return -EINVAL; plat_data = adapter->wifi_plat_data; @@ -290,7 +284,7 @@ static int wifi_plat_dev_drv_probe(struct platform_device *pdev) adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK; #ifdef DHD_ISR_NO_SUSPEND adapter->intr_flags |= IRQF_NO_SUSPEND; -#endif +#endif // endif } #ifdef CONFIG_DTS @@ -405,11 +399,11 @@ static int wifi_platdev_match(struct device *dev, void *data) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif const struct platform_device *pdev = to_platform_device(dev); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (strcmp(pdev->name, name) == 0) { DHD_ERROR(("found wifi platform device %s\n", name)); @@ -472,7 +466,6 @@ static int wifi_ctrlfunc_register_drv(void) return err; } } - #if !defined(CONFIG_DTS) if (dts_enabled) { struct resource *resource; @@ -482,12 +475,11 @@ static int wifi_ctrlfunc_register_drv(void) adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK; #ifdef DHD_ISR_NO_SUSPEND adapter->intr_flags |= IRQF_NO_SUSPEND; -#endif +#endif // endif wifi_plat_dev_probe_ret = dhd_wifi_platform_load(); } #endif /* !defined(CONFIG_DTS) */ - #ifdef CONFIG_DTS wifi_plat_dev_probe_ret = platform_driver_register(&wifi_platform_dev_driver); #endif /* CONFIG_DTS */ @@ -511,6 +503,7 @@ void wifi_ctrlfunc_unregister_drv(void) return; DHD_ERROR(("unregister wifi platform drivers\n")); + if (dev1) platform_driver_unregister(&wifi_platform_dev_driver); if (dev2) @@ -683,7 +676,6 @@ static int dhd_wifi_platform_load_pcie(void) } #endif /* BCMPCIE */ - void dhd_wifi_platform_unregister_drv(void) { if (cfg_multichip) @@ -697,7 +689,7 @@ extern int dhd_dpc_prio; extern uint dhd_deferred_tx; #if defined(BCMLXSDMMC) extern struct semaphore dhd_registration_sem; -#endif +#endif // endif #ifdef BCMSDIO static int dhd_wifi_platform_load_sdio(void) @@ -718,7 +710,7 @@ static int dhd_wifi_platform_load_sdio(void) #if defined(BCMLXSDMMC) sema_init(&dhd_registration_sem, 0); -#endif +#endif // endif if (dhd_wifi_platdata == NULL) { DHD_ERROR(("DHD wifi platform data is required for Android build\n")); @@ -808,7 +800,7 @@ fail: wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY); wifi_platform_bus_enumerate(adapter, FALSE); } -#endif +#endif // endif return err; } diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux_sched.c b/drivers/net/wireless/bcmdhd_oo/dhd_linux_sched.c index 88c0cce635bd92d36b242524497733616dbc42df..d1268c77b70915f5ec1923a99e124b163391ca61 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux_sched.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux_sched.c @@ -1,14 +1,14 @@ /* * Expose some of the kernel scheduler routines * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.c b/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.c index 1cba8d1400c43739f840c05927eeca16d101e05f..54b13bdac0901361d5fa0c44cf8a1d3f38de013a 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.c @@ -2,14 +2,14 @@ * Broadcom Dongle Host Driver (DHD), Generic work queue framework * Generic interface to handle dhd deferred work events * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dhd_linux_wq.c 641330 2016-06-02 06:55:00Z $ + * $Id: dhd_linux_wq.c 675839 2016-12-19 03:07:26Z $ */ #include @@ -71,18 +71,19 @@ struct dhd_deferred_wq { struct work_struct deferred_work; /* should be the first member */ struct kfifo *prio_fifo; - struct kfifo *work_fifo; - u8 *prio_fifo_buf; - u8 *work_fifo_buf; - spinlock_t work_lock; - void *dhd_info; /* review: does it require */ + struct kfifo *work_fifo; + u8 *prio_fifo_buf; + u8 *work_fifo_buf; + spinlock_t work_lock; + void *dhd_info; /* review: does it require */ + u32 event_skip_mask; }; static inline struct kfifo* dhd_kfifo_init(u8 *buf, int size, spinlock_t *lock) { struct kfifo *fifo; - gfp_t flags = CAN_SLEEP() ? GFP_KERNEL : GFP_ATOMIC; + gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC; #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 33)) fifo = kfifo_init(buf, size, flags, lock); @@ -103,7 +104,7 @@ dhd_kfifo_free(struct kfifo *fifo) #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31)) /* FC11 releases the fifo memory */ kfree(fifo); -#endif +#endif // endif } /* deferred work functions */ @@ -112,10 +113,10 @@ static void dhd_deferred_work_handler(struct work_struct *data); void* dhd_deferred_work_init(void *dhd_info) { - struct dhd_deferred_wq *work = NULL; - u8* buf; - unsigned long fifo_size = 0; - gfp_t flags = CAN_SLEEP() ? GFP_KERNEL : GFP_ATOMIC; + struct dhd_deferred_wq *work = NULL; + u8* buf; + unsigned long fifo_size = 0; + gfp_t flags = CAN_SLEEP()? GFP_KERNEL : GFP_ATOMIC; if (!dhd_info) { DHD_ERROR(("%s: dhd info not initialized\n", __FUNCTION__)); @@ -170,6 +171,7 @@ dhd_deferred_work_init(void *dhd_info) } work->dhd_info = dhd_info; + work->event_skip_mask = 0; DHD_ERROR(("%s: work queue initialized\n", __FUNCTION__)); return work; @@ -186,7 +188,6 @@ dhd_deferred_work_deinit(void *work) { struct dhd_deferred_wq *deferred_work = work; - if (!deferred_work) { DHD_ERROR(("%s: deferred work has been freed already\n", __FUNCTION__)); @@ -256,6 +257,12 @@ dhd_deferred_schedule_work(void *workq, void *event_data, u8 event, return DHD_WQ_STS_UNKNOWN_PRIORITY; } + if ((deferred_wq->event_skip_mask & (1 << event))) { + DHD_ERROR(("%s: Skip event requested. Mask = 0x%x\n", + __FUNCTION__, deferred_wq->event_skip_mask)); + return DHD_WQ_STS_EVENT_SKIPPED; + } + /* * default element size is 1, which can be changed * using kfifo_esize(). Older kernel(FC11) doesn't support @@ -363,7 +370,6 @@ dhd_deferred_work_handler(struct work_struct *work) continue; } - if (work_event.event_handler) { work_event.event_handler(deferred_work->dhd_info, work_event.event_data, work_event.event); @@ -377,3 +383,22 @@ dhd_deferred_work_handler(struct work_struct *work) return; } + +void +dhd_deferred_work_set_skip(void *work, u8 event, bool set) +{ + struct dhd_deferred_wq *deferred_wq = (struct dhd_deferred_wq *)work; + + if (!deferred_wq || !event || (event >= DHD_MAX_WQ_EVENTS)) { + DHD_ERROR(("%s: Invalid!!\n", __FUNCTION__)); + return; + } + + if (set) { + /* Set */ + deferred_wq->event_skip_mask |= (1 << event); + } else { + /* Clear */ + deferred_wq->event_skip_mask &= ~(1 << event); + } +} diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.h b/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.h index 6dc41a5dc3a3c2932650211dcdd68fd4301f1696..327a433db820f61d63dad98fc355902e36d431b9 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_linux_wq.h @@ -2,14 +2,14 @@ * Broadcom Dongle Host Driver (DHD), Generic work queue framework * Generic interface to handle dhd deferred work events * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dhd_linux_wq.h 704361 2017-06-13 08:50:38Z $ + * $Id: dhd_linux_wq.h 733672 2017-11-29 11:08:27Z $ */ #ifndef _dhd_linux_wq_h_ #define _dhd_linux_wq_h_ @@ -39,14 +39,18 @@ enum _wq_event { DHD_WQ_WORK_SET_MCAST_LIST, DHD_WQ_WORK_IPV6_NDO, DHD_WQ_WORK_HANG_MSG, - DHD_WQ_WORK_SOC_RAM_DUMP, + DHD_WQ_WORK_SSSR_DUMP, DHD_WQ_WORK_DHD_LOG_DUMP, + DHD_WQ_WORK_PKTLOG_DUMP, DHD_WQ_WORK_INFORM_DHD_MON, DHD_WQ_WORK_EVENT_LOGTRACE, DHD_WQ_WORK_DMA_LB_MEM_REL, + DHD_WQ_WORK_NATOE_EVENT, + DHD_WQ_WORK_NATOE_IOCTL, + DHD_WQ_WORK_MACDBG, DHD_WQ_WORK_DEBUG_UART_DUMP, - DHD_WQ_WORK_SSSR_DUMP, - DHD_WQ_WORK_PKTLOG_DUMP, + DHD_WQ_WORK_GET_BIGDATA_AP, + DHD_WQ_WORK_SOC_RAM_DUMP, DHD_MAX_WQ_EVENTS }; @@ -68,6 +72,7 @@ enum wq_priority { #define DHD_WQ_STS_SCHED_FAILED -3 #define DHD_WQ_STS_UNKNOWN_EVENT -4 #define DHD_WQ_STS_UNKNOWN_PRIORITY -5 +#define DHD_WQ_STS_EVENT_SKIPPED -6 typedef void (*event_handler_t)(void *handle, void *event_data, u8 event); @@ -75,4 +80,5 @@ void *dhd_deferred_work_init(void *dhd); void dhd_deferred_work_deinit(void *workq); int dhd_deferred_schedule_work(void *workq, void *event_data, u8 event, event_handler_t evt_handler, u8 priority); +void dhd_deferred_work_set_skip(void *work, u8 event, bool set); #endif /* _dhd_linux_wq_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.c b/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.c index c1032f20376630548bdb9aea7db5a3e4162f56d0..39db486caa5c54cb312f85c5aa1d6fba39044e21 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.c @@ -3,14 +3,14 @@ * * <> * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -56,6 +56,7 @@ static uint32 solt_chanspec[4] = {0, }, req_start[4] = {0, }; static bool lastMessages = FALSE; #define US_PRE_SEC 1000000 +#define DATA_UNIT_FOR_LOG_CNT 4 static void dhd_mschdbg_us_to_sec(uint32 time_h, uint32 time_l, uint32 *sec, uint32 *remain) { @@ -647,18 +648,23 @@ static void dhd_mschdbg_dump_data(dhd_pub_t *dhdp, void *raw_event_ptr, int type case WL_MSCH_PROFILER_EVENT_LOG: { - while (len > 0) { + while (len >= (int)WL_MSCH_EVENT_LOG_HEAD_SIZE) { msch_event_log_profiler_event_data_t *p = (msch_event_log_profiler_event_data_t *)data; + event_log_hdr_t hdr; int size = WL_MSCH_EVENT_LOG_HEAD_SIZE + p->hdr.count * sizeof(uint32); + if (len < size || size > sizeof(msch_event_log_profiler_event_data_t)) { + break; + } data += size; len -= size; dhd_mschdbg_us_to_sec(p->time_hi, p->time_lo, &s, &ss); MSCH_EVENT_HEAD(0); MSCH_EVENT(("%06d.%06d [wl%d]: ", s, ss, p->hdr.tag)); - p->hdr.tag = EVENT_LOG_TAG_MSCHPROFILE; - p->hdr.fmt_num = ntoh16(p->hdr.fmt_num); - dhd_dbg_verboselog_printf(dhdp, &p->hdr, raw_event_ptr, p->data); + hdr.tag = EVENT_LOG_TAG_MSCHPROFILE; + hdr.count = p->hdr.count + 1; + hdr.fmt_num = ntoh16(p->hdr.fmt_num); + dhd_dbg_verboselog_printf(dhdp, &hdr, raw_event_ptr, p->data, 0, 0); } lastMessages = TRUE; break; @@ -724,23 +730,44 @@ wl_mschdbg_event_handler(dhd_pub_t *dhdp, void *raw_event_ptr, int type, void *d } void -wl_mschdbg_verboselog_handler(dhd_pub_t *dhdp, void *raw_event_ptr, int tag, uint32 *log_ptr) +wl_mschdbg_verboselog_handler(dhd_pub_t *dhdp, void *raw_event_ptr, event_log_hdr_t *log_hdr, + uint32 *log_ptr) { + uint32 log_pyld_len; head_log = "CONSOLE"; - if (tag == EVENT_LOG_TAG_MSCHPROFILE) { + + if (log_hdr->count == 0) { + return; + } + log_pyld_len = (log_hdr->count - 1) * DATA_UNIT_FOR_LOG_CNT; + + if (log_hdr->tag == EVENT_LOG_TAG_MSCHPROFILE) { msch_event_log_profiler_event_data_t *p = (msch_event_log_profiler_event_data_t *)log_ptr; + event_log_hdr_t hdr; uint32 s, ss; + + if (log_pyld_len < OFFSETOF(msch_event_log_profiler_event_data_t, data) || + log_pyld_len > sizeof(msch_event_log_profiler_event_data_t)) { + return; + } + dhd_mschdbg_us_to_sec(p->time_hi, p->time_lo, &s, &ss); MSCH_EVENT_HEAD(0); MSCH_EVENT(("%06d.%06d [wl%d]: ", s, ss, p->hdr.tag)); - p->hdr.tag = EVENT_LOG_TAG_MSCHPROFILE; - p->hdr.fmt_num = ntoh16(p->hdr.fmt_num); - dhd_dbg_verboselog_printf(dhdp, &p->hdr, raw_event_ptr, p->data); + hdr.tag = EVENT_LOG_TAG_MSCHPROFILE; + hdr.count = p->hdr.count + 1; + hdr.fmt_num = ntoh16(p->hdr.fmt_num); + dhd_dbg_verboselog_printf(dhdp, &hdr, raw_event_ptr, p->data, 0, 0); } else { msch_collect_tlv_t *p = (msch_collect_tlv_t *)log_ptr; int type = ntoh16(p->type); int len = ntoh16(p->size); + + if (log_pyld_len < OFFSETOF(msch_collect_tlv_t, value) + len) { + return; + } + dhd_mschdbg_dump_data(dhdp, raw_event_ptr, type, p->value, len); } } diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.h b/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.h index 749e1119f42175fdf9633f3485249d0104a43e14..b7107406ac4e76a37f47e6569cc915254326dbd9 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_mschdbg.h @@ -3,14 +3,14 @@ * * <> * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -32,8 +32,8 @@ #ifdef SHOW_LOGTRACE extern void wl_mschdbg_event_handler(dhd_pub_t *dhdp, void *raw_event_ptr, int type, void *data, int len); -extern void wl_mschdbg_verboselog_handler(dhd_pub_t *dhdp, void *raw_event_ptr, int tag, - uint32 *log_ptr); +extern void wl_mschdbg_verboselog_handler(dhd_pub_t *dhdp, void *raw_event_ptr, + event_log_hdr_t *log_hdr, uint32 *log_ptr); #endif /* SHOW_LOGTRACE */ #endif /* _dhd_mschdbg_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_msgbuf.c b/drivers/net/wireless/bcmdhd_oo/dhd_msgbuf.c index ca09965d72803c2924a71a7e14f19f44fcc68288..283df99bb8ddb8fb3bb4d2d554a579771061ad96 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_msgbuf.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_msgbuf.c @@ -3,14 +3,14 @@ * Provides type definitions and function prototypes used to link the * DHD OS, bus, and protocol modules. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,10 +26,9 @@ * * <> * - * $Id: dhd_msgbuf.c 733632 2017-11-29 08:46:58Z $ + * $Id: dhd_msgbuf.c 739566 2018-01-09 01:24:24Z $ */ - #include #include @@ -52,9 +51,6 @@ #include #include #include -#ifdef DHD_TIMESYNC -#include -#endif /* DHD_TIMESYNC */ #if defined(DHD_LB) #include @@ -64,8 +60,11 @@ #define DHD_LB_WORK_SCHED (DHD_LB_WORKQ_SYNC * 2) #endif /* DHD_LB */ +#include #include +#include #include +#include #ifdef DHD_PKT_LOGGING #include @@ -107,6 +106,9 @@ extern char fw_version[]; #define MSGBUF_IOCTL_ACK_PENDING (1<<0) #define MSGBUF_IOCTL_RESP_PENDING (1<<1) +#define DHD_IOCTL_REQ_PKTBUFSZ 2048 +#define MSGBUF_IOCTL_MAX_RQSTLEN (DHD_IOCTL_REQ_PKTBUFSZ - H2DRING_CTRL_SUB_ITEMSIZE) + #define DMA_ALIGN_LEN 4 #define DMA_D2H_SCRATCH_BUF_LEN 8 @@ -115,7 +117,7 @@ extern char fw_version[]; #ifdef BCM_HOST_BUF #ifndef DMA_HOST_BUFFER_LEN #define DMA_HOST_BUFFER_LEN 0x200000 -#endif +#endif // endif #endif /* BCM_HOST_BUF */ #define DHD_FLOWRING_IOCTL_BUFPOST_PKTSZ 8192 @@ -126,7 +128,7 @@ extern char fw_version[]; #define DHD_H2D_INFORING_MAX_BUF_POST 32 #define DHD_MAX_TSBUF_POST 8 -#define DHD_PROT_FUNCS 41 +#define DHD_PROT_FUNCS 43 /* Length of buffer in host for bus throughput measurement */ #define DHD_BUS_TPUT_BUF_LEN 2048 @@ -141,6 +143,9 @@ extern char fw_version[]; /* Giving room before ioctl_trans_id rollsover. */ #define BUFFER_BEFORE_ROLLOVER 300 +/* 512K memory + 32K registers */ +#define SNAPSHOT_UPLOAD_BUF_SIZE ((512 + 32) * 1024) + struct msgbuf_ring; /* ring context for common and flow rings */ /** @@ -269,7 +274,6 @@ typedef uint8 (* d2h_sync_cb_t)(dhd_pub_t *dhd, struct msgbuf_ring *ring, #define DHD_D2H_RINGID(offset) \ ((offset) + BCMPCIE_H2D_COMMON_MSGRINGS) - #define DHD_DMAH_NULL ((void*)NULL) /* @@ -283,7 +287,7 @@ typedef uint8 (* d2h_sync_cb_t)(dhd_pub_t *dhd, struct msgbuf_ring *ring, #define DHD_DMA_PAD (L1_CACHE_BYTES) #else #define DHD_DMA_PAD (128) -#endif +#endif // endif /* Used in loopback tests */ typedef struct dhd_dmaxfer { @@ -294,7 +298,7 @@ typedef struct dhd_dmaxfer { uint32 len; bool in_progress; uint64 start_usec; - uint32 d11_lpbk; + uint32 d11_lpbk; int status; } dhd_dmaxfer_t; @@ -334,6 +338,7 @@ typedef struct msgbuf_ring { uint16 compeltion_ring_ids[MAX_COMPLETION_RING_IDS_ASSOCIATED]; uchar name[RING_NAME_MAX_LENGTH]; uint32 ring_mem_allocated; + void *ring_lock; } msgbuf_ring_t; #define DHD_RING_BGN_VA(ring) ((ring)->dma_buf.va) @@ -341,8 +346,6 @@ typedef struct msgbuf_ring { ((uint8 *)(DHD_RING_BGN_VA((ring))) + \ (((ring)->max_items - 1) * (ring)->item_len)) - - /* This can be overwritten by module parameter defined in dhd_linux.c * or by dhd iovar h2d_max_txpost. */ @@ -421,7 +424,6 @@ typedef struct dhd_prot { void *pktid_ctrl_map; /* a pktid maps to a packet and its metadata */ void *pktid_rx_map; /* pktid map for rx path */ void *pktid_tx_map; /* pktid map for tx path */ - void *rx_lock; /* rx pktid map and rings access protection */ bool metadata_dbg; void *pktid_map_handle_ioctl; @@ -429,7 +431,6 @@ typedef struct dhd_prot { uint16 rx_metadata_offset; uint16 tx_metadata_offset; - #if defined(DHD_D2H_SOFT_DOORBELL_SUPPORT) /* Host's soft doorbell configuration */ bcmpcie_soft_doorbell_t soft_doorbell[BCMPCIE_D2H_COMMON_MSGRINGS]; @@ -449,17 +450,20 @@ typedef struct dhd_prot { dhd_dma_buf_t fw_trap_buf; /* firmware trap buffer */ - uint32 host_ipc_version; /* Host sypported IPC rev */ + uint32 host_ipc_version; /* Host sypported IPC rev */ uint32 device_ipc_version; /* FW supported IPC rev */ uint32 active_ipc_version; /* Host advertised IPC rev */ dhd_dma_buf_t hostts_req_buf; /* For holding host timestamp request buf */ bool hostts_req_buf_inuse; bool rx_ts_log_enabled; bool tx_ts_log_enabled; + bool no_retry; + bool no_aggr; + bool fixed_rate; } dhd_prot_t; +extern bool dhd_timesync_delay_post_bufs(dhd_pub_t *dhdp); extern void dhd_schedule_dmaxfer_free(dhd_pub_t* dhdp, dmaxref_mem_map_t *dmmap); - /* Convert a dmaaddr_t to a base_addr with htol operations */ static INLINE void dhd_base_addr_htolpa(sh_addr_t *base_addr, dmaaddr_t pa); @@ -535,7 +539,6 @@ static int dhd_msgbuf_rxbuf_post_ts_bufs(dhd_pub_t *pub); static void dhd_prot_return_rxbuf(dhd_pub_t *dhd, uint32 pktid, uint32 rxcnt); - /* D2H Message handling */ static int dhd_prot_process_msgtype(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint8 *buf, uint32 len); @@ -572,10 +575,11 @@ static void dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd_pub_t *dhd); static void dhd_prot_process_d2h_ring_config_complete(dhd_pub_t *dhd, void *msg); static void dhd_prot_process_d2h_ring_create_complete(dhd_pub_t *dhd, void *buf); static void dhd_prot_process_h2d_ring_create_complete(dhd_pub_t *dhd, void *buf); -static void dhd_prot_process_d2h_mb_data(dhd_pub_t *dhd, void* buf); static void dhd_prot_process_infobuf_complete(dhd_pub_t *dhd, void* buf); +static void dhd_prot_process_d2h_mb_data(dhd_pub_t *dhd, void* buf); static void dhd_prot_detach_info_rings(dhd_pub_t *dhd); static void dhd_prot_process_d2h_host_ts_complete(dhd_pub_t *dhd, void* buf); +static void dhd_prot_process_snapshot_complete(dhd_pub_t *dhd, void *buf); typedef void (*dhd_msgbuf_func_t)(dhd_pub_t *dhd, void *msg); @@ -624,9 +628,10 @@ static dhd_msgbuf_func_t table_lookup[DHD_PROT_FUNCS] = { NULL, /* MSG_TYPE_HOSTTIMSTAMP */ dhd_prot_process_d2h_host_ts_complete, /* MSG_TYPE_HOSTTIMSTAMP_CMPLT */ dhd_prot_process_fw_timestamp, /* MSG_TYPE_FIRMWARE_TIMESTAMP */ + NULL, /* MSG_TYPE_SNAPSHOT_UPLOAD */ + dhd_prot_process_snapshot_complete, /* MSG_TYPE_SNAPSHOT_CMPLT */ }; - #ifdef DHD_RX_CHAINING #define PKT_CTF_CHAINABLE(dhd, ifidx, evh, prio, h_sa, h_da, h_prio) \ @@ -652,27 +657,6 @@ static void BCMFASTPATH dhd_rxchain_commit(dhd_pub_t *dhd); static void dhd_prot_h2d_sync_init(dhd_pub_t *dhd); -/** - * D2H DMA to completion callback handlers. Based on the mode advertised by the - * dongle through the PCIE shared region, the appropriate callback will be - * registered in the proto layer to be invoked prior to precessing any message - * from a D2H DMA ring. If the dongle uses a read barrier or another mode that - * does not require host participation, then a noop callback handler will be - * bound that simply returns the msg_type. - */ -static void dhd_prot_d2h_sync_livelock(dhd_pub_t *dhd, uint32 msg_seqnum, msgbuf_ring_t *ring, - uint32 tries, volatile uchar *msg, int msglen); -static uint8 dhd_prot_d2h_sync_seqnum(dhd_pub_t *dhd, msgbuf_ring_t *ring, - volatile cmn_msg_hdr_t *msg, int msglen); -static uint8 dhd_prot_d2h_sync_xorcsum(dhd_pub_t *dhd, msgbuf_ring_t *ring, - volatile cmn_msg_hdr_t *msg, int msglen); -static uint8 dhd_prot_d2h_sync_none(dhd_pub_t *dhd, msgbuf_ring_t *ring, - volatile cmn_msg_hdr_t *msg, int msglen); -static void dhd_prot_d2h_sync_init(dhd_pub_t *dhd); -static int dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create); -static int dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create); -static uint16 dhd_get_max_flow_rings(dhd_pub_t *dhd); - bool dhd_prot_is_cmpl_ring_empty(dhd_pub_t *dhd, void *prot_info) { @@ -693,6 +677,15 @@ dhd_prot_is_cmpl_ring_empty(dhd_pub_t *dhd, void *prot_info) ret = (wr == rd) ? TRUE : FALSE; return ret; } + +void +dhd_prot_dump_ring_ptrs(void *prot_info) +{ + msgbuf_ring_t *ring = (msgbuf_ring_t *)prot_info; + DHD_ERROR(("%s curr_rd: %d rd: %d wr: %d \n", __FUNCTION__, + ring->curr_rd, ring->rd, ring->wr)); +} + uint16 dhd_prot_get_h2d_max_txpost(dhd_pub_t *dhd) { @@ -703,6 +696,29 @@ dhd_prot_set_h2d_max_txpost(dhd_pub_t *dhd, uint16 max_txpost) { h2d_max_txpost = max_txpost; } +/** + * D2H DMA to completion callback handlers. Based on the mode advertised by the + * dongle through the PCIE shared region, the appropriate callback will be + * registered in the proto layer to be invoked prior to precessing any message + * from a D2H DMA ring. If the dongle uses a read barrier or another mode that + * does not require host participation, then a noop callback handler will be + * bound that simply returns the msg_type. + */ +static void dhd_prot_d2h_sync_livelock(dhd_pub_t *dhd, uint32 msg_seqnum, msgbuf_ring_t *ring, + uint32 tries, volatile uchar *msg, int msglen); +static uint8 dhd_prot_d2h_sync_seqnum(dhd_pub_t *dhd, msgbuf_ring_t *ring, + volatile cmn_msg_hdr_t *msg, int msglen); +static uint8 dhd_prot_d2h_sync_xorcsum(dhd_pub_t *dhd, msgbuf_ring_t *ring, + volatile cmn_msg_hdr_t *msg, int msglen); +static uint8 dhd_prot_d2h_sync_none(dhd_pub_t *dhd, msgbuf_ring_t *ring, + volatile cmn_msg_hdr_t *msg, int msglen); +static void dhd_prot_d2h_sync_init(dhd_pub_t *dhd); +static int dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create, + uint16 ring_type, uint32 id); +static int dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create, + uint8 type, uint32 id); +static uint16 dhd_get_max_flow_rings(dhd_pub_t *dhd); + /** * dhd_prot_d2h_sync_livelock - when the host determines that a DMA transfer has * not completed, a livelock condition occurs. Host will avert this livelock by @@ -717,13 +733,15 @@ dhd_prot_d2h_sync_livelock(dhd_pub_t *dhd, uint32 msg_seqnum, msgbuf_ring_t *rin volatile uchar *msg, int msglen) { uint32 ring_seqnum = ring->seqnum; + DHD_ERROR(( "LIVELOCK DHD<%p> ring<%s> msg_seqnum<%u> ring_seqnum<%u:%u> tries<%u> max<%lu>" " tot<%lu> dma_buf va<%p> msg<%p> curr_rd<%d>\n", dhd, ring->name, msg_seqnum, ring_seqnum, ring_seqnum% D2H_EPOCH_MODULO, tries, dhd->prot->d2h_sync_wait_max, dhd->prot->d2h_sync_wait_tot, ring->dma_buf.va, msg, ring->curr_rd)); - prhex("D2H MsgBuf Failure", (volatile uchar *)msg, msglen); + + dhd_prhex("D2H MsgBuf Failure", msg, msglen, DHD_ERROR_VAL); dhd_bus_dump_console_buffer(dhd->bus); dhd_prot_debug_info_print(dhd); @@ -861,9 +879,15 @@ dhd_prot_d2h_sync_xorcsum(dhd_pub_t *dhd, msgbuf_ring_t *ring, */ for (step = 1; step <= PCIE_D2H_SYNC_NUM_OF_STEPS; step++) { for (tries = 0; tries < PCIE_D2H_SYNC_WAIT_TRIES; tries++) { - prot_checksum = bcm_compute_xor32((volatile uint32 *)msg, num_words); - if (prot_checksum == 0U) { /* checksum is OK */ - if (msg->epoch == ring_seqnum) { + /* First verify if the seqnumber has been update, + * if yes, then only check xorcsum. + * Once seqnum and xorcsum is proper that means + * complete message has arrived. + */ + if (msg->epoch == ring_seqnum) { + prot_checksum = bcm_compute_xor32((volatile uint32 *)msg, + num_words); + if (prot_checksum == 0U) { /* checksum is OK */ ring->seqnum++; /* next expected sequence number */ goto dma_completed; } @@ -965,7 +989,6 @@ dhd_prot_h2d_sync_init(dhd_pub_t *dhd) /* +----------------- End of PCIE DHD H2D DMA SYNC ------------------------+ */ - /* * +---------------------------------------------------------------------------+ * PCIE DMA-able buffer. Sets up a dhd_dma_buf_t object, which includes the @@ -981,7 +1004,6 @@ dhd_base_addr_htolpa(sh_addr_t *base_addr, dmaaddr_t pa) base_addr->high_addr = htol32(PHYSADDRHI(pa)); } - /** * dhd_dma_buf_audit - Any audits on a DHD DMA Buffer. */ @@ -1019,7 +1041,6 @@ dhd_dma_buf_alloc(dhd_pub_t *dhd, dhd_dma_buf_t *dma_buf, uint32 buf_len) osl_t *osh = dhd->osh; uint16 dma_align = DMA_ALIGN_LEN; - ASSERT(dma_buf != NULL); ASSERT(dma_buf->va == NULL); ASSERT(dma_buf->len == 0); @@ -1129,10 +1150,9 @@ dhd_dma_buf_init(dhd_pub_t *dhd, void *dhd_dma_buf, /* On Router, the pktptr serves as a pktid. */ - #if defined(PROP_TXSTATUS) && !defined(DHD_PCIE_PKTID) #error "PKTIDMAP must be supported with PROP_TXSTATUS/WLFC" -#endif +#endif // endif /* Enum for marking the buffer color based on usage */ typedef enum dhd_pkttype { @@ -1146,12 +1166,15 @@ typedef enum dhd_pkttype { PKTTYPE_TSBUF_RX } dhd_pkttype_t; -#define DHD_PKTID_INVALID (0U) -#define DHD_IOCTL_REQ_PKTID (0xFFFE) -#define DHD_FAKE_PKTID (0xFACE) -#define DHD_H2D_DBGRING_REQ_PKTID 0xFFFD -#define DHD_D2H_DBGRING_REQ_PKTID 0xFFFC -#define DHD_H2D_HOSTTS_REQ_PKTID 0xFFFB +#define DHD_PKTID_INVALID (0U) +#define DHD_IOCTL_REQ_PKTID (0xFFFE) +#define DHD_FAKE_PKTID (0xFACE) +#define DHD_H2D_DBGRING_REQ_PKTID 0xFFFD +#define DHD_D2H_DBGRING_REQ_PKTID 0xFFFC +#define DHD_H2D_HOSTTS_REQ_PKTID 0xFFFB +#define DHD_H2D_BTLOGRING_REQ_PKTID 0xFFFA +#define DHD_D2H_BTLOGRING_REQ_PKTID 0xFFF9 +#define DHD_H2D_SNAPSHOT_UPLOAD_REQ_PKTID 0xFFF8 #define IS_FLOWRING(ring) \ ((strncmp(ring->name, "h2dflr", sizeof("h2dflr"))) == (0)) @@ -1175,11 +1198,11 @@ static void dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map); #endif /* MACOSX_DHD */ #if defined(DHD_PCIE_PKTID) -#if defined(MACOSX_DHD) || defined(DHD_EFI) +#if defined(MACOSX_DHD) #define IOCTLRESP_USE_CONSTMEM static void free_ioctl_return_buffer(dhd_pub_t *dhd, dhd_dma_buf_t *retbuf); static int alloc_ioctl_return_buffer(dhd_pub_t *dhd, dhd_dma_buf_t *retbuf); -#endif +#endif // endif /* Determine number of pktids that are available */ static INLINE uint32 dhd_pktid_map_avail_cnt(dhd_pktid_map_handle_t *handle); @@ -1225,6 +1248,13 @@ static void *dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map, #define DHD_TEST_IS_ALLOC 3 #define DHD_TEST_IS_FREE 4 +typedef enum dhd_pktid_map_type { + DHD_PKTID_MAP_TYPE_CTRL = 1, + DHD_PKTID_MAP_TYPE_TX, + DHD_PKTID_MAP_TYPE_RX, + DHD_PKTID_MAP_TYPE_UNKNOWN +} dhd_pktid_map_type_t; + #ifdef USE_DHD_PKTID_AUDIT_LOCK #define DHD_PKTID_AUDIT_LOCK_INIT(osh) dhd_os_spin_lock_init(osh) #define DHD_PKTID_AUDIT_LOCK_DEINIT(osh, lock) dhd_os_spin_lock_deinit(osh, lock) @@ -1239,12 +1269,12 @@ static void *dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map, #endif /* DHD_PKTID_AUDIT_ENABLED */ -/* #define USE_DHD_PKTID_LOCK 1 */ +#define USE_DHD_PKTID_LOCK 1 #ifdef USE_DHD_PKTID_LOCK #define DHD_PKTID_LOCK_INIT(osh) dhd_os_spin_lock_init(osh) #define DHD_PKTID_LOCK_DEINIT(osh, lock) dhd_os_spin_lock_deinit(osh, lock) -#define DHD_PKTID_LOCK(lock) dhd_os_spin_lock(lock) +#define DHD_PKTID_LOCK(lock, flags) (flags) = dhd_os_spin_lock(lock) #define DHD_PKTID_UNLOCK(lock, flags) dhd_os_spin_unlock(lock, flags) #else #define DHD_PKTID_LOCK_INIT(osh) (void *)(1) @@ -1286,6 +1316,9 @@ typedef struct dhd_pktid_map { uint32 items; /* total items in map */ uint32 avail; /* total available items */ int failures; /* lockers unavailable count */ + /* Spinlock to protect dhd_pktid_map in process/tasklet context */ + void *pktid_lock; /* Used when USE_DHD_PKTID_LOCK is defined */ + #if defined(DHD_PKTID_AUDIT_ENABLED) void *pktid_audit_lock; struct bcm_mwbmap *pktid_audit; /* multi word bitmap based audit */ @@ -1343,17 +1376,38 @@ typedef struct dhd_pktid_map { #define DHD_PKTID_AVAIL(map) dhd_pktid_map_avail_cnt(map) #if defined(DHD_PKTID_AUDIT_ENABLED) + +static int +dhd_get_pktid_map_type(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map) +{ + dhd_prot_t *prot = dhd->prot; + int pktid_map_type; + + if (pktid_map == prot->pktid_ctrl_map) { + pktid_map_type = DHD_PKTID_MAP_TYPE_CTRL; + } else if (pktid_map == prot->pktid_tx_map) { + pktid_map_type = DHD_PKTID_MAP_TYPE_TX; + } else if (pktid_map == prot->pktid_rx_map) { + pktid_map_type = DHD_PKTID_MAP_TYPE_RX; + } else { + pktid_map_type = DHD_PKTID_MAP_TYPE_UNKNOWN; + } + + return pktid_map_type; +} + /** -* dhd_pktid_audit - Use the mwbmap to audit validity of a pktid. +* __dhd_pktid_audit - Use the mwbmap to audit validity of a pktid. */ static int -dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, +__dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, const int test_for, const char *errmsg) { #define DHD_PKT_AUDIT_STR "ERROR: %16s Host PktId Audit: " struct bcm_mwbmap *handle; uint32 flags; bool ignore_audit; + int error = BCME_OK; if (pktid_map == (dhd_pktid_map_t *)NULL) { DHD_ERROR((DHD_PKT_AUDIT_STR "Pkt id map NULL\n", errmsg)); @@ -1365,21 +1419,19 @@ dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, handle = pktid_map->pktid_audit; if (handle == (struct bcm_mwbmap *)NULL) { DHD_ERROR((DHD_PKT_AUDIT_STR "Handle NULL\n", errmsg)); - DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags); - return BCME_OK; + goto out; } /* Exclude special pktids from audit */ ignore_audit = (pktid == DHD_IOCTL_REQ_PKTID) | (pktid == DHD_FAKE_PKTID); if (ignore_audit) { - DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags); - return BCME_OK; + goto out; } if ((pktid == DHD_PKTID_INVALID) || (pktid > pktid_map->items)) { DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> invalid\n", errmsg, pktid)); - /* lock is released in "error" */ - goto error; + error = BCME_ERROR; + goto out; } /* Perform audit */ @@ -1388,25 +1440,27 @@ dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, if (!bcm_mwbmap_isfree(handle, pktid)) { DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> alloc duplicate\n", errmsg, pktid)); - goto error; + error = BCME_ERROR; + } else { + bcm_mwbmap_force(handle, pktid); } - bcm_mwbmap_force(handle, pktid); break; case DHD_DUPLICATE_FREE: if (bcm_mwbmap_isfree(handle, pktid)) { DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> free duplicate\n", errmsg, pktid)); - goto error; + error = BCME_ERROR; + } else { + bcm_mwbmap_free(handle, pktid); } - bcm_mwbmap_free(handle, pktid); break; case DHD_TEST_IS_ALLOC: if (bcm_mwbmap_isfree(handle, pktid)) { DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> is not allocated\n", errmsg, pktid)); - goto error; + error = BCME_ERROR; } break; @@ -1414,24 +1468,34 @@ dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, if (!bcm_mwbmap_isfree(handle, pktid)) { DHD_ERROR((DHD_PKT_AUDIT_STR "PktId<%d> is not free", errmsg, pktid)); - goto error; + error = BCME_ERROR; } break; default: - goto error; + DHD_ERROR(("%s: Invalid test case: %d\n", __FUNCTION__, test_for)); + error = BCME_ERROR; + break; } +out: DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags); - return BCME_OK; - -error: + return error; +} - DHD_PKTID_AUDIT_UNLOCK(pktid_map->pktid_audit_lock, flags); - /* May insert any trap mechanism here ! */ - dhd_pktid_error_handler(dhd); +static int +dhd_pktid_audit(dhd_pub_t *dhd, dhd_pktid_map_t *pktid_map, uint32 pktid, + const int test_for, const char *errmsg) +{ + int ret = BCME_OK; + ret = __dhd_pktid_audit(dhd, pktid_map, pktid, test_for, errmsg); + if (ret == BCME_ERROR) { + DHD_ERROR(("%s: Got Pkt Id Audit failure: PKTID<%d> PKTID MAP TYPE<%d>\n", + __FUNCTION__, pktid, dhd_get_pktid_map_type(dhd, pktid_map))); + dhd_pktid_error_handler(dhd); + } - return BCME_ERROR; + return ret; } #define DHD_PKTID_AUDIT(dhdp, map, pktid, test_for) \ @@ -1439,12 +1503,15 @@ error: static int dhd_pktid_audit_ring_debug(dhd_pub_t *dhdp, dhd_pktid_map_t *map, uint32 pktid, - const int test_for, void *msg, uint32 msg_len, const char * func) + const int test_for, void *msg, uint32 msg_len, const char *func) { - int ret = 0; - ret = DHD_PKTID_AUDIT(dhdp, map, pktid, test_for); + int ret = BCME_OK; + ret = __dhd_pktid_audit(dhdp, map, pktid, test_for, func); if (ret == BCME_ERROR) { + DHD_ERROR(("%s: Got Pkt Id Audit failure: PKTID<%d> PKTID MAP TYPE<%d>\n", + __FUNCTION__, pktid, dhd_get_pktid_map_type(dhdp, map))); prhex(func, (uchar *)msg, msg_len); + dhd_pktid_error_handler(dhdp); } return ret; } @@ -1454,7 +1521,6 @@ dhd_pktid_audit_ring_debug(dhd_pub_t *dhdp, dhd_pktid_map_t *map, uint32 pktid, #endif /* DHD_PKTID_AUDIT_ENABLED */ - /** * +---------------------------------------------------------------------------+ * Packet to Packet Id mapper using a paradigm. @@ -1497,13 +1563,20 @@ dhd_pktid_map_init(dhd_pub_t *dhd, uint32 num_items) return (dhd_pktid_map_handle_t *)NULL; } - /* Initialize the lock that protects this structure */ map->items = num_items; map->avail = num_items; map_items = DHD_PKIDMAP_ITEMS(map->items); map_keys_sz = DHD_PKTIDMAP_KEYS_SZ(map->items); + + /* Initialize the lock that protects this structure */ + map->pktid_lock = DHD_PKTID_LOCK_INIT(osh); + if (map->pktid_lock == NULL) { + DHD_ERROR(("%s:%d: Lock init failed \r\n", __FUNCTION__, __LINE__)); + goto error; + } + map->keys = (dhd_pktid_key_t *)MALLOC(osh, map_keys_sz); if (map->keys == NULL) { DHD_ERROR(("%s:%d: MALLOC failed for map->keys size %d\n", @@ -1553,9 +1626,15 @@ error: DHD_PKTID_AUDIT_LOCK_DEINIT(osh, map->pktid_audit_lock); } #endif /* DHD_PKTID_AUDIT_ENABLED */ + if (map->keys) { MFREE(osh, map->keys, map_keys_sz); } + + if (map->pktid_lock) { + DHD_PKTID_LOCK_DEINIT(osh, map->pktid_lock); + } + VMFREE(osh, map, dhd_pktid_map_sz); } return (dhd_pktid_map_handle_t *)NULL; @@ -1574,11 +1653,11 @@ dhd_pktid_map_reset(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) dhd_pktid_map_t *map; dhd_pktid_item_t *locker; uint32 map_items; - uint32 flags; + unsigned long flags; bool data_tx = FALSE; map = (dhd_pktid_map_t *)handle; - DHD_GENERAL_LOCK(dhd, flags); + DHD_PKTID_LOCK(map->pktid_lock, flags); osh = dhd->osh; map_items = DHD_PKIDMAP_ITEMS(map->items); @@ -1619,7 +1698,7 @@ dhd_pktid_map_reset(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) map->avail = map_items; memset(&map->lockers[1], 0, sizeof(dhd_pktid_item_t) * map_items); - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); } #ifdef IOCTLRESP_USE_CONSTMEM @@ -1631,10 +1710,10 @@ dhd_pktid_map_reset_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) dhd_pktid_map_t *map; dhd_pktid_item_t *locker; uint32 map_items; - uint32 flags; + unsigned long flags; map = (dhd_pktid_map_t *)handle; - DHD_GENERAL_LOCK(dhd, flags); + DHD_PKTID_LOCK(map->pktid_lock, flags); map_items = DHD_PKIDMAP_ITEMS(map->items); /* skip reserved KEY #0, and start from 1 */ @@ -1653,10 +1732,7 @@ dhd_pktid_map_reset_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) retbuf.dmah = locker->dmah; retbuf.secdma = locker->secdma; - /* This could be a callback registered with dhd_pktid_map */ - DHD_GENERAL_UNLOCK(dhd, flags); free_ioctl_return_buffer(dhd, &retbuf); - DHD_GENERAL_LOCK(dhd, flags); } else { #ifdef DHD_PKTID_AUDIT_RING @@ -1668,11 +1744,10 @@ dhd_pktid_map_reset_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) map->avail = map_items; memset(&map->lockers[1], 0, sizeof(dhd_pktid_item_t) * map_items); - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); } #endif /* IOCTLRESP_USE_CONSTMEM */ - /** * Free the pktid map. */ @@ -1683,6 +1758,9 @@ dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) uint32 dhd_pktid_map_sz; uint32 map_keys_sz; + if (handle == NULL) + return; + /* Free any pending packets */ dhd_pktid_map_reset(dhd, handle); @@ -1690,6 +1768,8 @@ dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) dhd_pktid_map_sz = DHD_PKTID_MAP_SZ(map->items); map_keys_sz = DHD_PKTIDMAP_KEYS_SZ(map->items); + DHD_PKTID_LOCK_DEINIT(dhd->osh, map->pktid_lock); + #if defined(DHD_PKTID_AUDIT_ENABLED) if (map->pktid_audit != (struct bcm_mwbmap *)NULL) { bcm_mwbmap_fini(dhd->osh, map->pktid_audit); /* Destruct pktid_audit */ @@ -1710,6 +1790,9 @@ dhd_pktid_map_fini_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) uint32 dhd_pktid_map_sz; uint32 map_keys_sz; + if (handle == NULL) + return; + /* Free any pending packets */ dhd_pktid_map_reset_ioctl(dhd, handle); @@ -1717,6 +1800,8 @@ dhd_pktid_map_fini_ioctl(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle) dhd_pktid_map_sz = DHD_PKTID_MAP_SZ(map->items); map_keys_sz = DHD_PKTIDMAP_KEYS_SZ(map->items); + DHD_PKTID_LOCK_DEINIT(dhd->osh, map->pktid_lock); + #if defined(DHD_PKTID_AUDIT_ENABLED) if (map->pktid_audit != (struct bcm_mwbmap *)NULL) { bcm_mwbmap_fini(dhd->osh, map->pktid_audit); /* Destruct pktid_audit */ @@ -1738,11 +1823,14 @@ dhd_pktid_map_avail_cnt(dhd_pktid_map_handle_t *handle) { dhd_pktid_map_t *map; uint32 avail; + unsigned long flags; ASSERT(handle != NULL); map = (dhd_pktid_map_t *)handle; + DHD_PKTID_LOCK(map->pktid_lock, flags); avail = map->avail; + DHD_PKTID_UNLOCK(map->pktid_lock, flags); return avail; } @@ -1761,13 +1849,17 @@ dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey; dhd_pktid_map_t *map; dhd_pktid_item_t *locker; + unsigned long flags; ASSERT(handle != NULL); map = (dhd_pktid_map_t *)handle; + DHD_PKTID_LOCK(map->pktid_lock, flags); + if ((int)(map->avail) <= 0) { /* no more pktids to allocate */ map->failures++; DHD_INFO(("%s:%d: failed, no free keys\n", __FUNCTION__, __LINE__)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); return DHD_PKTID_INVALID; /* failed alloc request */ } @@ -1780,6 +1872,7 @@ dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, " map->avail<%u>, nkey<%u>, pkttype<%u>\n", __FUNCTION__, __LINE__, map->avail, nkey, pkttype)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); return DHD_PKTID_INVALID; /* failed alloc request */ } @@ -1789,7 +1882,10 @@ dhd_pktid_map_reserve(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, locker->len = 0; locker->state = LOCKER_IS_BUSY; /* reserve this locker */ + DHD_PKTID_UNLOCK(map->pktid_lock, flags); + ASSERT(nkey != DHD_PKTID_INVALID); + return nkey; /* return locker's numbered key */ } @@ -1804,13 +1900,17 @@ dhd_pktid_map_save(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt, { dhd_pktid_map_t *map; dhd_pktid_item_t *locker; + unsigned long flags; ASSERT(handle != NULL); map = (dhd_pktid_map_t *)handle; + DHD_PKTID_LOCK(map->pktid_lock, flags); + if ((nkey == DHD_PKTID_INVALID) || (nkey > DHD_PKIDMAP_ITEMS(map->items))) { DHD_ERROR(("%s:%d: Error! saving invalid pktid<%u> pkttype<%u>\n", __FUNCTION__, __LINE__, nkey, pkttype)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); #ifdef DHD_FW_COREDUMP if (dhd->memdump_enabled) { /* collect core dump */ @@ -1837,6 +1937,7 @@ dhd_pktid_map_save(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, void *pkt, locker->pkttype = pkttype; locker->pkt = pkt; locker->state = LOCKER_IS_BUSY; /* make this locker busy */ + DHD_PKTID_UNLOCK(map->pktid_lock, flags); } /** @@ -1874,14 +1975,18 @@ dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey, dhd_pktid_item_t *locker; void * pkt; unsigned long long locker_addr; + unsigned long flags; ASSERT(handle != NULL); map = (dhd_pktid_map_t *)handle; + DHD_PKTID_LOCK(map->pktid_lock, flags); + if ((nkey == DHD_PKTID_INVALID) || (nkey > DHD_PKIDMAP_ITEMS(map->items))) { DHD_ERROR(("%s:%d: Error! Try to free invalid pktid<%u>, pkttype<%d>\n", __FUNCTION__, __LINE__, nkey, pkttype)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); #ifdef DHD_FW_COREDUMP if (dhd->memdump_enabled) { /* collect core dump */ @@ -1904,6 +2009,7 @@ dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey, if (locker->state == LOCKER_IS_FREE) { DHD_ERROR(("%s:%d: Error! freeing already freed invalid pktid<%u>\n", __FUNCTION__, __LINE__, nkey)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); #ifdef DHD_FW_COREDUMP if (dhd->memdump_enabled) { /* collect core dump */ @@ -1933,6 +2039,7 @@ dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey, "pkttype <%d> locker->pa <0x%llx> \n", __FUNCTION__, __LINE__, locker->state, locker->pkttype, pkttype, locker_addr)); + DHD_PKTID_UNLOCK(map->pktid_lock, flags); #ifdef DHD_FW_COREDUMP if (dhd->memdump_enabled) { /* collect core dump */ @@ -1967,12 +2074,13 @@ dhd_pktid_map_free(dhd_pub_t *dhd, dhd_pktid_map_handle_t *handle, uint32 nkey, locker->pkt = NULL; /* Clear pkt */ locker->len = 0; + DHD_PKTID_UNLOCK(map->pktid_lock, flags); + return pkt; } #else /* ! DHD_PCIE_PKTID */ - typedef struct pktlist { PKT_LIST *tx_pkt_list; /* list for tx packets */ PKT_LIST *rx_pkt_list; /* list for rx packets */ @@ -1991,7 +2099,6 @@ typedef struct pktlist { #define DHD_PKTID32(pktptr32) ((uint32)(pktptr32)) #define DHD_PKTPTR32(pktid32) ((void *)(pktid32)) - static INLINE uint32 dhd_native_to_pktid(dhd_pktid_map_handle_t *map, void *pktptr32, dmaaddr_t pa, uint32 dma_len, void *dmah, void *secdma, dhd_pkttype_t pkttype); @@ -2057,14 +2164,9 @@ error_done: } static void -dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map) +dhd_pktid_map_reset(dhd_pub_t *dhd, pktlists_t *handle) { osl_t *osh = dhd->osh; - pktlists_t *handle = (pktlists_t *) map; - - ASSERT(handle != NULL); - if (handle == (pktlists_t *)NULL) - return; if (handle->ctrl_pkt_list) { PKTLIST_FINI(handle->ctrl_pkt_list); @@ -2080,6 +2182,20 @@ dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map) PKTLIST_FINI(handle->tx_pkt_list); MFREE(osh, handle->tx_pkt_list, sizeof(PKT_LIST)); } +} + +static void +dhd_pktid_map_fini(dhd_pub_t *dhd, dhd_pktid_map_handle_t *map) +{ + osl_t *osh = dhd->osh; + pktlists_t *handle = (pktlists_t *) map; + + ASSERT(handle != NULL); + if (handle == (pktlists_t *)NULL) { + return; + } + + dhd_pktid_map_reset(dhd, handle); if (handle) { MFREE(osh, handle, sizeof(pktlists_t)); @@ -2164,7 +2280,6 @@ dhd_pktid_to_native(dhd_pktid_map_handle_t *map, uint32 pktid32, /* +------------------ End of PCIE DHD PKTID MAPPER -----------------------+ */ - /** * The PCIE FD protocol layer is constructed in two phases: * Phase 1. dhd_prot_attach() @@ -2192,6 +2307,11 @@ dhd_prot_attach(dhd_pub_t *dhd) osl_t *osh = dhd->osh; dhd_prot_t *prot; + /* FW going to DMA extended trap data, + * allocate buffer for the maximum extended trap data. + */ + uint32 trap_buf_len = BCMPCIE_EXT_TRAP_DATA_MAXLEN; + /* Allocate prot structure */ if (!(prot = (dhd_prot_t *)DHD_OS_PREALLOC(dhd, DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) { @@ -2210,6 +2330,7 @@ dhd_prot_attach(dhd_pub_t *dhd) dhd->idma_inited = 0; dhd->ifrm_inited = 0; + dhd->dar_inited = 0; /* Common Ring Allocations */ @@ -2289,6 +2410,7 @@ dhd_prot_attach(dhd_pub_t *dhd) if (dhd_dma_buf_alloc(dhd, &prot->d2h_dma_scratch_buf, DMA_D2H_SCRATCH_BUF_LEN)) { #endif /* BCM_HOST_BUF */ + goto fail; } @@ -2299,9 +2421,7 @@ dhd_prot_attach(dhd_pub_t *dhd) #ifdef DHD_RX_CHAINING dhd_rxchain_reset(&prot->rxchain); -#endif - - prot->rx_lock = dhd_os_spin_lock_init(dhd->osh); +#endif // endif prot->pktid_ctrl_map = DHD_NATIVE_TO_PKTID_INIT(dhd, MAX_CTRL_PKTID); if (prot->pktid_ctrl_map == NULL) { @@ -2313,7 +2433,7 @@ dhd_prot_attach(dhd_pub_t *dhd) goto fail; prot->pktid_tx_map = DHD_NATIVE_TO_PKTID_INIT(dhd, MAX_TX_PKTID); - if (prot->pktid_rx_map == NULL) + if (prot->pktid_tx_map == NULL) goto fail; #ifdef IOCTLRESP_USE_CONSTMEM @@ -2329,27 +2449,36 @@ dhd_prot_attach(dhd_pub_t *dhd) { void *buffer; buffer = MALLOC(dhd->osh, sizeof(void*) * DHD_LB_WORKQ_SZ); + if (buffer == NULL) { + DHD_ERROR(("%s: failed to allocate RXC work buffer\n", __FUNCTION__)); + goto fail; + } bcm_workq_init(&prot->tx_compl_prod, &prot->tx_compl_cons, buffer, DHD_LB_WORKQ_SZ); prot->tx_compl_prod_sync = 0; DHD_INFO(("%s: created tx_compl_workq <%p,%d>\n", __FUNCTION__, buffer, DHD_LB_WORKQ_SZ)); - } + } #endif /* DHD_LB_TXC */ #if defined(DHD_LB_RXC) - { + { void *buffer; buffer = MALLOC(dhd->osh, sizeof(void*) * DHD_LB_WORKQ_SZ); + if (buffer == NULL) { + DHD_ERROR(("%s: failed to allocate RXC work buffer\n", __FUNCTION__)); + goto fail; + } bcm_workq_init(&prot->rx_compl_prod, &prot->rx_compl_cons, buffer, DHD_LB_WORKQ_SZ); prot->rx_compl_prod_sync = 0; DHD_INFO(("%s: created rx_compl_workq <%p,%d>\n", __FUNCTION__, buffer, DHD_LB_WORKQ_SZ)); - } + } #endif /* DHD_LB_RXC */ + /* Initialize trap buffer */ - if (dhd_dma_buf_alloc(dhd, &dhd->prot->fw_trap_buf, BCMPCIE_EXT_TRAP_DATA_MAXLEN)) { + if (dhd_dma_buf_alloc(dhd, &dhd->prot->fw_trap_buf, trap_buf_len)) { DHD_ERROR(("%s: dhd_init_trap_buffer falied\n", __FUNCTION__)); goto fail; } @@ -2358,11 +2487,10 @@ dhd_prot_attach(dhd_pub_t *dhd) fail: -#ifndef CONFIG_DHD_USE_STATIC_BUF - if (prot != NULL) { + if (prot) { + /* Free up all allocated memories */ dhd_prot_detach(dhd); } -#endif /* CONFIG_DHD_USE_STATIC_BUF */ return BCME_NOMEM; } /* dhd_prot_attach */ @@ -2375,48 +2503,40 @@ dhd_set_host_cap(dhd_pub_t *dhd) if (dhd->bus->api.fw_rev >= PCIE_SHARED_VERSION_6) { if (dhd->h2d_phase_supported) { - data |= HOSTCAP_H2D_VALID_PHASE; - - if (dhd->force_dongletrap_on_bad_h2d_phase) { + if (dhd->force_dongletrap_on_bad_h2d_phase) data |= HOSTCAP_H2D_ENABLE_TRAP_ON_BADPHASE; - } } - if (prot->host_ipc_version > prot->device_ipc_version) { + if (prot->host_ipc_version > prot->device_ipc_version) prot->active_ipc_version = prot->device_ipc_version; - } else { + else prot->active_ipc_version = prot->host_ipc_version; - } data |= prot->active_ipc_version; if (dhdpcie_bus_get_pcie_hostready_supported(dhd->bus)) { - DHD_INFO(("Advertise Hostready Capability\n")); - data |= HOSTCAP_H2D_ENABLE_HOSTRDY; } -#ifdef PCIE_INB_DW - if (dhdpcie_bus_get_pcie_inband_dw_supported(dhd->bus)) { - DHD_INFO(("Advertise Inband-DW Capability\n")); - data |= HOSTCAP_DS_INBAND_DW; - data |= HOSTCAP_DS_NO_OOB_DW; - dhdpcie_bus_enab_pcie_dw(dhd->bus, DEVICE_WAKE_INB); - } else -#endif /* PCIE_INB_DW */ -#ifdef PCIE_OOB - if (dhdpcie_bus_get_pcie_oob_dw_supported(dhd->bus)) { - dhdpcie_bus_enab_pcie_dw(dhd->bus, DEVICE_WAKE_OOB); - } else -#endif /* PCIE_OOB */ { /* Disable DS altogether */ data |= HOSTCAP_DS_NO_OOB_DW; dhdpcie_bus_enab_pcie_dw(dhd->bus, DEVICE_WAKE_NONE); } - if (dhdpcie_bus_get_pcie_idma_supported(dhd->bus)) { + /* Indicate support for extended trap data */ + data |= HOSTCAP_EXTENDED_TRAP_DATA; + /* Indicate support for TX status metadata */ + if (dhd->pcie_txs_metadata_enable != 0) + data |= HOSTCAP_TXSTATUS_METADATA; + + /* Enable fast delete ring in firmware if supported */ + if (dhd->fast_delete_ring_support) { + data |= HOSTCAP_FAST_DELETE_RING; + } + + if (dhdpcie_bus_get_pcie_idma_supported(dhd->bus)) { DHD_ERROR(("IDMA inited\n")); data |= HOSTCAP_H2D_IDMA; dhd->idma_inited = TRUE; @@ -2430,11 +2550,11 @@ dhd_set_host_cap(dhd_pub_t *dhd) dhd_prot_dma_indx_free(dhd); } - /* Indicate support for TX status metadata */ - data |= HOSTCAP_TXSTATUS_METADATA; - - /* Indicate support for extended trap data */ - data |= HOSTCAP_EXTENDED_TRAP_DATA; + if (dhdpcie_bus_get_pcie_dar_supported(dhd->bus)) { + DHD_ERROR(("DAR doorbell Use\n")); + data |= HOSTCAP_H2D_DAR; + dhd->dar_inited = TRUE; + } DHD_INFO(("%s:Active Ver:%d, Host Ver:%d, FW Ver:%d\n", __FUNCTION__, @@ -2445,14 +2565,7 @@ dhd_set_host_cap(dhd_pub_t *dhd) dhd_bus_cmn_writeshared(dhd->bus, &prot->fw_trap_buf.pa, sizeof(prot->fw_trap_buf.pa), DNGL_TO_HOST_TRAP_ADDR, 0); } -#ifdef HOFFLOAD_MODULES - dhd_bus_cmn_writeshared(dhd->bus, &dhd->hmem.data_addr, - sizeof(dhd->hmem.data_addr), WRT_HOST_MODULE_ADDR, 0); -#endif -#ifdef DHD_TIMESYNC - dhd_timesync_notify_ipc_rev(dhd->ts, prot->active_ipc_version); -#endif /* DHD_TIMESYNC */ } /** @@ -2468,6 +2581,8 @@ dhd_prot_init(dhd_pub_t *dhd) sh_addr_t base_addr; dhd_prot_t *prot = dhd->prot; int ret = 0; + uint32 idmacontrol; + uint32 waitcount = 0; /** * A user defined value can be assigned to global variable h2d_max_txpost via @@ -2487,7 +2602,7 @@ dhd_prot_init(dhd_pub_t *dhd) /* using the latest shared structure template */ prot->max_rxbufpost = DEFAULT_RX_BUFFERS_TO_POST; } - DHD_INFO(("%s:%d: MAX_RXBUFPOST = %d\n", __FUNCTION__, __LINE__, prot->max_rxbufpost)); + DHD_ERROR(("%s:%d: MAX_RXBUFPOST = %d\n", __FUNCTION__, __LINE__, prot->max_rxbufpost)); /* Initialize. bzero() would blow away the dma pointers. */ prot->max_eventbufpost = DHD_FLOWRING_MAX_EVENTBUF_POST; @@ -2522,12 +2637,6 @@ dhd_prot_init(dhd_pub_t *dhd) prot->ioctl_resplen = 0; prot->ioctl_received = IOCTL_WAIT; - /* Register the interrupt function upfront */ - /* remove corerev checks in data path */ - prot->mb_ring_fn = dhd_bus_get_mbintr_fn(dhd->bus); - - prot->mb_2_ring_fn = dhd_bus_get_mbintr_2_fn(dhd->bus); - /* Initialize Common MsgBuf Rings */ prot->device_ipc_version = dhd->bus->api.fw_rev; @@ -2536,6 +2645,14 @@ dhd_prot_init(dhd_pub_t *dhd) /* Init the host API version */ dhd_set_host_cap(dhd); + /* Register the interrupt function upfront */ + /* remove corerev checks in data path */ + /* do this after host/fw negotiation for DAR */ + prot->mb_ring_fn = dhd_bus_get_mbintr_fn(dhd->bus); + prot->mb_2_ring_fn = dhd_bus_get_mbintr_2_fn(dhd->bus); + + dhd->bus->_dar_war = (dhd->bus->sih->buscorerev < 64) ? TRUE : FALSE; + dhd_prot_ring_init(dhd, &prot->h2dring_ctrl_subn); dhd_prot_ring_init(dhd, &prot->h2dring_rxp_subn); dhd_prot_ring_init(dhd, &prot->d2hring_ctrl_cpln); @@ -2554,14 +2671,6 @@ dhd_prot_init(dhd_pub_t *dhd) dhd_prot_h2d_sync_init(dhd); -#ifdef PCIE_INB_DW - /* Set the initial DS state */ - if (INBAND_DW_ENAB(dhd->bus)) { - dhdpcie_bus_set_pcie_inband_dw_state(dhd->bus, - DW_DEVICE_DS_ACTIVE); - } -#endif /* PCIE_INB_DW */ - /* init the scratch buffer */ dhd_base_addr_htolpa(&base_addr, prot->d2h_dma_scratch_buf.pa); dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr), @@ -2588,7 +2697,6 @@ dhd_prot_init(dhd_pub_t *dhd) dhd_base_addr_htolpa(&base_addr, prot->d2h_dma_indx_rd_buf.pa); dhd_bus_cmn_writeshared(dhd->bus, &base_addr, sizeof(base_addr), D2H_DMA_INDX_RD_BUF, 0); - } /* Signal to the dongle that common ring init is complete */ @@ -2613,6 +2721,35 @@ dhd_prot_init(dhd_pub_t *dhd) H2D_IFRM_INDX_WR_BUF, 0); } + /* If IDMA is enabled and initied, wait for FW to setup the IDMA descriptors + * Waiting just before configuring doorbell + */ +#define IDMA_ENABLE_WAIT 10 + if (IDMA_ACTIVE(dhd)) { + /* wait for idma_en bit in IDMAcontrol register to be set */ + /* Loop till idma_en is not set */ + uint buscorerev = dhd->bus->sih->buscorerev; + idmacontrol = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + IDMAControl(buscorerev), 0, 0); + while (!(idmacontrol & PCIE_IDMA_MODE_EN(buscorerev)) && + (waitcount++ < IDMA_ENABLE_WAIT)) { + + DHD_ERROR(("iDMA not enabled yet,waiting 1 ms c=%d IDMAControl = %08x\n", + waitcount, idmacontrol)); + OSL_DELAY(1000); /* 1ms as its onetime only */ + idmacontrol = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + IDMAControl(buscorerev), 0, 0); + } + + if (waitcount < IDMA_ENABLE_WAIT) { + DHD_ERROR(("iDMA enabled PCIEControl = %08x\n", idmacontrol)); + } else { + DHD_ERROR(("Error: wait for iDMA timed out wait=%d IDMAControl = %08x\n", + waitcount, idmacontrol)); + return BCME_ERROR; + } + } + /* See if info rings could be created */ if (dhd->bus->api.fw_rev >= PCIE_SHARED_VERSION_6) { if ((ret = dhd_prot_init_info_rings(dhd)) != BCME_OK) { @@ -2634,10 +2771,36 @@ dhd_prot_init(dhd_pub_t *dhd) dhd_msgbuf_rxbuf_post_ioctlresp_bufs(dhd); dhd_msgbuf_rxbuf_post_event_bufs(dhd); + /* + * Note that any communication with the Dongle should be added + * below this point. Any other host data structure initialiation that + * needs to be done prior to the DPC starts executing should be done + * befor this point. + * Because once we start sending H2D requests to Dongle, the Dongle + * respond immediately. So the DPC context to handle this + * D2H response could preempt the context in which dhd_prot_init is running. + * We want to ensure that all the Host part of dhd_prot_init is + * done before that. + */ + + /* See if info rings could be created */ + if (dhd->bus->api.fw_rev >= PCIE_SHARED_VERSION_6) { + if ((ret = dhd_prot_init_info_rings(dhd)) != BCME_OK) { + /* For now log and proceed, further clean up action maybe necessary + * when we have more clarity. + */ + DHD_ERROR(("%s Info rings couldn't be created: Err Code%d", + __FUNCTION__, ret)); + } + } + + prot->no_retry = FALSE; + prot->no_aggr = FALSE; + prot->fixed_rate = FALSE; + return BCME_OK; } /* dhd_prot_init */ - /** * dhd_prot_detach - PCIE FD protocol layer destructor. * Unlink, frees allocated protocol memory (including dhd_prot) @@ -2693,13 +2856,7 @@ void dhd_prot_detach(dhd_pub_t *dhd) DHD_NATIVE_TO_PKTID_FINI(dhd, prot->pktid_tx_map); #ifdef IOCTLRESP_USE_CONSTMEM DHD_NATIVE_TO_PKTID_FINI_IOCTL(dhd, prot->pktid_map_handle_ioctl); -#endif - - dhd_os_spin_lock_deinit(dhd->osh, prot->rx_lock); - -#ifndef CONFIG_DHD_USE_STATIC_BUF - MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); -#endif /* CONFIG_DHD_USE_STATIC_BUF */ +#endif // endif #if defined(DHD_LB_TXC) if (prot->tx_compl_prod.buffer) @@ -2712,11 +2869,12 @@ void dhd_prot_detach(dhd_pub_t *dhd) sizeof(void*) * DHD_LB_WORKQ_SZ); #endif /* DHD_LB_RXC */ + DHD_OS_PREFREE(dhd, dhd->prot, sizeof(dhd_prot_t)); + dhd->prot = NULL; } } /* dhd_prot_detach */ - /** * dhd_prot_reset - Reset the protocol layer without freeing any objects. * This may be invoked to soft reboot the dongle, without having to @@ -2764,13 +2922,12 @@ dhd_prot_reset(dhd_pub_t *dhd) dhd_dma_buf_reset(dhd, &prot->h2d_ifrm_indx_wr_buf); - /* Reset all DMA-able buffers for DMAing H2D/D2H WR/RD indices */ + /* Rest all DMA-able buffers for DMAing H2D/D2H WR/RD indices */ dhd_dma_buf_reset(dhd, &prot->h2d_dma_indx_rd_buf); dhd_dma_buf_reset(dhd, &prot->h2d_dma_indx_wr_buf); dhd_dma_buf_reset(dhd, &prot->d2h_dma_indx_rd_buf); dhd_dma_buf_reset(dhd, &prot->d2h_dma_indx_wr_buf); - prot->rx_metadata_offset = 0; prot->tx_metadata_offset = 0; @@ -2831,7 +2988,6 @@ dhd_prot_reset(dhd_pub_t *dhd) #define DHD_LB_DISPATCH_TX_COMPL(dhdp) do { /* noop */ } while (0) #endif /* !DHD_LB_TXC */ - #if defined(DHD_LB) /* DHD load balancing: deferral of work to another online CPU */ /* DHD_LB_TXC DHD_LB_RXC DHD_LB_RXP dispatchers, in dhd_linux.c */ @@ -2908,7 +3064,7 @@ dhd_lb_tx_compl_handler(unsigned long data) DMA_UNMAP(dhd->osh, pa, pa_len, DMA_RX, 0, 0); #if defined(BCMPCIE) dhd_txcomplete(dhd, pkt, true); -#endif +#endif // endif PKTFREE(dhd->osh, pkt, TRUE); count++; @@ -2964,7 +3120,16 @@ dhd_check_create_info_rings(dhd_pub_t *dhd) { dhd_prot_t *prot = dhd->prot; int ret = BCME_ERROR; - uint16 ringid = dhd->bus->max_tx_flowrings + BCMPCIE_COMMON_MSGRINGS; + uint16 ringid; + + { + /* dongle may increase max_submission_rings so keep + * ringid at end of dynamic rings + */ + ringid = dhd->bus->max_tx_flowrings + + (dhd->bus->max_submission_rings - dhd->bus->max_tx_flowrings) + + BCMPCIE_H2D_COMMON_MSGRINGS; + } if (prot->h2dring_info_subn && prot->d2hring_info_cpln) { return BCME_OK; /* dhd_prot_init rentry after a dhd_prot_reset */ @@ -3046,7 +3211,8 @@ dhd_prot_init_info_rings(dhd_pub_t *dhd) } DHD_TRACE(("trying to send create d2h info ring: id %d\n", prot->d2hring_info_cpln->idx)); - ret = dhd_send_d2h_ringcreate(dhd, prot->d2hring_info_cpln); + ret = dhd_send_d2h_ringcreate(dhd, prot->d2hring_info_cpln, + BCMPCIE_D2H_RING_TYPE_DBGBUF_CPL, DHD_D2H_DBGRING_REQ_PKTID); if (ret != BCME_OK) return ret; @@ -3056,7 +3222,8 @@ dhd_prot_init_info_rings(dhd_pub_t *dhd) prot->h2dring_info_subn->n_completion_ids = 1; prot->h2dring_info_subn->compeltion_ring_ids[0] = prot->d2hring_info_cpln->idx; - ret = dhd_send_h2d_ringcreate(dhd, prot->h2dring_info_subn); + ret = dhd_send_h2d_ringcreate(dhd, prot->h2dring_info_subn, + BCMPCIE_H2D_RING_TYPE_DBGBUF_SUBMIT, DHD_H2D_DBGRING_REQ_PKTID); /* Note that there is no way to delete d2h or h2d ring deletion incase either fails, * so can not cleanup if one ring was created while the other failed @@ -3088,7 +3255,6 @@ int dhd_sync_with_dongle(dhd_pub_t *dhd) int ret = 0; wlc_rev_info_t revinfo; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT); @@ -3096,7 +3262,6 @@ int dhd_sync_with_dongle(dhd_pub_t *dhd) /* Post ts buffer after shim layer is attached */ ret = dhd_msgbuf_rxbuf_post_ts_bufs(dhd); - #ifdef DHD_FW_COREDUMP /* Check the memdump capability */ dhd_get_memdump_info(dhd); @@ -3127,7 +3292,6 @@ done: return ret; } /* dhd_sync_with_dongle */ - #define DHD_DBG_SHOW_METADATA 0 #if DHD_DBG_SHOW_METADATA @@ -3240,7 +3404,11 @@ dhd_prot_packet_free(dhd_pub_t *dhd, void *pkt, uint8 pkttype, bool send) } } -/* dhd_prot_packet_get should be called only for items having pktid_ctrl_map handle */ +/** + * dhd_prot_packet_get should be called only for items having pktid_ctrl_map handle + * and all the bottom most functions like dhd_pktid_map_free hold separate DHD_PKTID_LOCK + * to ensure thread safety, so no need to hold any locks for this function + */ static INLINE void * BCMFASTPATH dhd_prot_packet_get(dhd_pub_t *dhd, uint32 pktid, uint8 pkttype, bool free_pktid) { @@ -3307,42 +3475,7 @@ dhd_prot_ioctl_ret_buffer_get(dhd_pub_t *dhd, uint32 pktid, dhd_dma_buf_t *retbu return; } -#endif - -#ifdef PCIE_INB_DW -static int -dhd_prot_inc_hostactive_devwake_assert(dhd_bus_t *bus) -{ - unsigned long flags = 0; - - if (INBAND_DW_ENAB(bus)) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - bus->host_active_cnt++; - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - if (dhd_bus_set_device_wake(bus, TRUE) != BCME_OK) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - bus->host_active_cnt--; - dhd_bus_inb_ack_pending_ds_req(bus); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - return BCME_ERROR; - } - } - - return BCME_OK; -} - -static void -dhd_prot_dec_hostactive_ack_pending_dsreq(dhd_bus_t *bus) -{ - unsigned long flags = 0; - if (INBAND_DW_ENAB(bus)) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - bus->host_active_cnt--; - dhd_bus_inb_ack_pending_ds_req(bus); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - } -} -#endif /* PCIE_INB_DW */ +#endif // endif static void BCMFASTPATH dhd_msgbuf_rxbuf_post(dhd_pub_t *dhd, bool use_rsv_pktid) @@ -3402,20 +3535,17 @@ dhd_prot_rxbuf_post(dhd_pub_t *dhd, uint16 count, bool use_rsv_pktid) void *lcl_buf; uint16 lcl_buf_size; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - +#ifdef WL_MONITOR + if (dhd->monitor_enable) { + pktsz = DHD_MAX_MON_FLOWRING_RX_BUFPOST_PKTSZ; + } +#endif /* WL_MONITOR */ /* allocate a local buffer to store pkt buffer va, pa and length */ lcl_buf_size = (sizeof(void *) + sizeof(dmaaddr_t) + sizeof(uint32)) * RX_BUF_BURST; lcl_buf = MALLOC(dhd->osh, lcl_buf_size); if (!lcl_buf) { DHD_ERROR(("%s: local scratch buffer allocation failed\n", __FUNCTION__)); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif return 0; } pktbuf = lcl_buf; @@ -3459,14 +3589,15 @@ dhd_prot_rxbuf_post(dhd_pub_t *dhd, uint16 count, bool use_rsv_pktid) /* only post what we have */ count = i; - /* grab the rx lock to allocate pktid and post on ring */ - DHD_SPIN_LOCK(prot->rx_lock, flags); + /* grab the ring lock to allocate pktid and post on ring */ + DHD_RING_LOCK(ring->ring_lock, flags); /* Claim space for exactly 'count' no of messages, for mitigation purpose */ msg_start = (void *) dhd_prot_alloc_ring_space(dhd, ring, count, &alloced, TRUE); if (msg_start == NULL) { DHD_INFO(("%s:%d: Rxbufpost Msgbuf Not available\n", __FUNCTION__, __LINE__)); + DHD_RING_UNLOCK(ring->ring_lock, flags); goto cleanup; } /* if msg_start != NULL, we should have alloced space for atleast 1 item */ @@ -3564,13 +3695,10 @@ alloc_pkt_id: /* update ring's WR index and ring doorbell to dongle */ if (alloced > 0) { - unsigned long flags1; - DHD_GENERAL_LOCK(dhd, flags1); dhd_prot_ring_write_complete(dhd, ring, msg_start, alloced); - DHD_GENERAL_UNLOCK(dhd, flags1); } - DHD_SPIN_UNLOCK(prot->rx_lock, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); cleanup: for (i = alloced; i < count; i++) { @@ -3586,21 +3714,18 @@ cleanup: } MFREE(dhd->osh, lcl_buf, lcl_buf_size); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + return alloced; } /* dhd_prot_rxbufpost */ static int -dhd_prot_infobufpost(dhd_pub_t *dhd) +dhd_prot_infobufpost(dhd_pub_t *dhd, msgbuf_ring_t *ring) { unsigned long flags; uint32 pktid; dhd_prot_t *prot = dhd->prot; - msgbuf_ring_t *ring = prot->h2dring_info_subn; uint16 alloced = 0; - uint16 pktsz = DHD_FLOWRING_RX_BUFPOST_PKTSZ; + uint16 pktsz = DHD_INFOBUF_RX_BUFPOST_PKTSZ; uint32 pktlen; info_buf_post_msg_t *infobuf_post; uint8 *infobuf_post_tmp; @@ -3608,17 +3733,23 @@ dhd_prot_infobufpost(dhd_pub_t *dhd) void* msg_start; uint8 i = 0; dmaaddr_t pa; - int16 count; + int16 count = 0; if (ring == NULL) return 0; if (ring->inited != TRUE) return 0; - if (prot->max_infobufpost == 0) - return 0; + if (ring == dhd->prot->h2dring_info_subn) { + if (prot->max_infobufpost == 0) + return 0; - count = prot->max_infobufpost - prot->infobufpost; + count = prot->max_infobufpost - prot->infobufpost; + } + else { + DHD_ERROR(("Unknown ring\n")); + return 0; + } if (count <= 0) { DHD_INFO(("%s: Cannot post more than max info resp buffers\n", @@ -3626,21 +3757,15 @@ dhd_prot_infobufpost(dhd_pub_t *dhd) return 0; } -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ + /* grab the ring lock to allocate pktid and post on ring */ + DHD_RING_LOCK(ring->ring_lock, flags); - DHD_GENERAL_LOCK(dhd, flags); /* Claim space for exactly 'count' no of messages, for mitigation purpose */ msg_start = (void *) dhd_prot_alloc_ring_space(dhd, ring, count, &alloced, FALSE); - DHD_GENERAL_UNLOCK(dhd, flags); if (msg_start == NULL) { DHD_INFO(("%s:%d: infobufpost Msgbuf Not available\n", __FUNCTION__, __LINE__)); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return -1; } @@ -3701,25 +3826,14 @@ dhd_prot_infobufpost(dhd_pub_t *dhd) infobuf_post->cmn_hdr.flags = ring->current_phase; ring->seqnum++; -#if defined(DHD_PCIE_PKTID) - /* get the lock before calling DHD_NATIVE_TO_PKTID */ - DHD_GENERAL_LOCK(dhd, flags); -#endif /* DHD_PCIE_PKTID */ - pktid = DHD_NATIVE_TO_PKTID(dhd, dhd->prot->pktid_ctrl_map, p, pa, pktlen, DMA_RX, NULL, ring->dma_buf.secdma, PKTTYPE_INFO_RX); - #if defined(DHD_PCIE_PKTID) - /* free lock */ - DHD_GENERAL_UNLOCK(dhd, flags); - if (pktid == DHD_PKTID_INVALID) { if (SECURE_DMA_ENAB(dhd->osh)) { - DHD_GENERAL_LOCK(dhd, flags); SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, 0, ring->dma_buf.secdma, 0); - DHD_GENERAL_UNLOCK(dhd, flags); } else DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, 0); @@ -3728,7 +3842,7 @@ dhd_prot_infobufpost(dhd_pub_t *dhd) #else PKTFREE(dhd->osh, p, FALSE); #endif /* DHD_USE_STATIC_CTRLBUF */ - DHD_ERROR(("%s: Pktid pool depleted.\n", __FUNCTION__)); + DHD_ERROR_RLMT(("%s: Pktid pool depleted.\n", __FUNCTION__)); break; } #endif /* DHD_PCIE_PKTID */ @@ -3766,15 +3880,14 @@ dhd_prot_infobufpost(dhd_pub_t *dhd) /* Update the write pointer in TCM & ring bell */ if (alloced > 0) { - prot->infobufpost += alloced; - DHD_INFO(("allocated %d buffers for info ring\n", alloced)); - DHD_GENERAL_LOCK(dhd, flags); + if (ring == dhd->prot->h2dring_info_subn) { + prot->infobufpost += alloced; + } dhd_prot_ring_write_complete(dhd, ring, msg_start, alloced); - DHD_GENERAL_UNLOCK(dhd, flags); } -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); + return alloced; } /* dhd_prot_infobufpost */ @@ -3846,7 +3959,6 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) return -1; } - if ((msg_type == MSG_TYPE_EVENT_BUF_POST) || (msg_type == MSG_TYPE_TIMSTAMP_BUFPOST)) non_ioctl_resp_buf = TRUE; else @@ -3890,10 +4002,8 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) pktlen = PKTLEN(dhd->osh, p); if (SECURE_DMA_ENAB(dhd->osh)) { - DHD_GENERAL_LOCK(dhd, flags); pa = SECURE_DMA_MAP(dhd->osh, PKTDATA(dhd->osh, p), pktlen, DMA_RX, p, 0, ring->dma_buf.secdma, 0); - DHD_GENERAL_UNLOCK(dhd, flags); } #ifndef BCM_SECURE_DMA else @@ -3928,18 +4038,15 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) #endif /* DMAMAP_STATS */ } -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhd, flags); + /* grab the ring lock to allocate pktid and post on ring */ + DHD_RING_LOCK(ring->ring_lock, flags); rxbuf_post = (ioctl_resp_evt_buf_post_msg_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (rxbuf_post == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DHD_ERROR(("%s:%d: Ctrl submit Msgbuf Not available to post buffer \n", __FUNCTION__, __LINE__)); @@ -3948,10 +4055,8 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) #endif /* IOCTLRESP_USE_CONSTMEM */ { if (SECURE_DMA_ENAB(dhd->osh)) { - DHD_GENERAL_LOCK(dhd, flags); SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL, ring->dma_buf.secdma, 0); - DHD_GENERAL_UNLOCK(dhd, flags); } else { DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL); } @@ -3986,9 +4091,9 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) BCMPCIE_CMNHDR_PHASE_BIT_INIT; } } - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL); - DHD_ERROR(("%s: Pktid pool depleted.\n", __FUNCTION__)); + DHD_ERROR_RLMT(("%s: Pktid pool depleted.\n", __FUNCTION__)); goto free_pkt_return; } @@ -4012,16 +4117,14 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) BCMPCIE_CMNHDR_PHASE_BIT_INIT; } } - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); #ifdef IOCTLRESP_USE_CONSTMEM if (non_ioctl_resp_buf) #endif /* IOCTLRESP_USE_CONSTMEM */ { if (SECURE_DMA_ENAB(dhd->osh)) { - DHD_GENERAL_LOCK(dhd, flags); SECURE_DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL, ring->dma_buf.secdma, 0); - DHD_GENERAL_UNLOCK(dhd, flags); } else DMA_UNMAP(dhd->osh, pa, pktlen, DMA_RX, 0, DHD_DMAH_NULL); } @@ -4039,28 +4142,22 @@ dhd_prot_rxbufpost_ctrl(dhd_pub_t *dhd, uint8 msg_type) /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, rxbuf_post, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return 1; free_pkt_return: -#ifdef IOCTLRESP_USE_CONSTMEM if (!non_ioctl_resp_buf) { +#ifdef IOCTLRESP_USE_CONSTMEM free_ioctl_return_buffer(dhd, &retbuf); - } else -#endif - { +#else + dhd_prot_packet_free(dhd, p, buf_type, FALSE); +#endif /* IOCTLRESP_USE_CONSTMEM */ + } else { dhd_prot_packet_free(dhd, p, buf_type, FALSE); } -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif - return -1; } /* dhd_prot_rxbufpost_ctrl */ @@ -4123,26 +4220,6 @@ dhd_msgbuf_rxbuf_post_event_bufs(dhd_pub_t *dhd) static int dhd_msgbuf_rxbuf_post_ts_bufs(dhd_pub_t *dhd) { -#ifdef DHD_TIMESYNC - dhd_prot_t *prot = dhd->prot; - int max_to_post; - - if (prot->active_ipc_version < 7) { - DHD_ERROR(("no ts buffers to device ipc rev is %d, needs to be atleast 7\n", - prot->active_ipc_version)); - return 0; - } - - max_to_post = prot->max_tsbufpost - prot->cur_ts_bufs_posted; - if (max_to_post <= 0) { - DHD_INFO(("%s: Cannot post more than max ts buffers\n", - __FUNCTION__)); - return 0; - } - - prot->cur_ts_bufs_posted += dhd_msgbuf_rxbuf_post_ctrlpath(dhd, - MSG_TYPE_TIMSTAMP_BUFPOST, max_to_post); -#endif /* DHD_TIMESYNC */ return 0; } @@ -4153,6 +4230,7 @@ dhd_prot_process_msgbuf_infocpl(dhd_pub_t *dhd, uint bound) bool more = TRUE; uint n = 0; msgbuf_ring_t *ring = prot->d2hring_info_cpln; + unsigned long flags; if (ring == NULL) return FALSE; @@ -4169,8 +4247,10 @@ dhd_prot_process_msgbuf_infocpl(dhd_pub_t *dhd, uint bound) break; } + DHD_RING_LOCK(ring->ring_lock, flags); /* Get the message from ring */ msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len); + DHD_RING_UNLOCK(ring->ring_lock, flags); if (msg_addr == NULL) { more = FALSE; break; @@ -4232,12 +4312,12 @@ dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound) pktqhead = pkt_newidx = NULL; pkt_cnt_newidx = 0; - DHD_SPIN_LOCK(prot->rx_lock, flags); + DHD_RING_LOCK(ring->ring_lock, flags); /* Get the address of the next message to be read from ring */ msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len); if (msg_addr == NULL) { - DHD_SPIN_UNLOCK(prot->rx_lock, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); break; } @@ -4329,7 +4409,7 @@ dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound) dhd_rx_mon_pkt(dhd, msg, pkt, ifidx); continue; } -#endif +#endif // endif if (!pktqhead) { pktqhead = prevpkt = pkt; @@ -4347,12 +4427,6 @@ dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound) } } -#ifdef DHD_TIMESYNC - if (dhd->prot->rx_ts_log_enabled) { - ts_timestamp_t *ts = (ts_timestamp_t *)&msg->ts; - dhd_timesync_log_rx_timestamp(dhd->ts, ifidx, ts->low, ts->high); - } -#endif /* DHD_TIMESYNC */ } /* roll back read pointer for unprocessed message */ @@ -4366,7 +4440,7 @@ dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound) /* Update read pointer */ dhd_prot_upd_read_idx(dhd, ring); - DHD_SPIN_UNLOCK(prot->rx_lock, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); pkt = pktqhead; for (i = 0; pkt && i < pkt_cnt; i++, pkt = nextpkt) { @@ -4396,6 +4470,10 @@ dhd_prot_process_msgbuf_rxcpl(dhd_pub_t *dhd, uint bound) /* Post another set of rxbufs to the device */ dhd_prot_return_rxbuf(dhd, 0, pkt_cnt); +#ifdef DHD_RX_CHAINING + dhd_rxchain_commit(dhd); +#endif // endif + /* After batch processing, check RX bound */ n += pkt_cnt; if (n >= bound) { @@ -4444,6 +4522,7 @@ dhd_prot_process_msgbuf_txcpl(dhd_pub_t *dhd, uint bound) bool more = TRUE; uint n = 0; msgbuf_ring_t *ring = &dhd->prot->d2hring_tx_cpln; + unsigned long flags; /* Process all the messages - DTOH direction */ while (!dhd_is_device_removed(dhd)) { @@ -4455,8 +4534,11 @@ dhd_prot_process_msgbuf_txcpl(dhd_pub_t *dhd, uint bound) break; } + DHD_RING_LOCK(ring->ring_lock, flags); /* Get the address of the next message to be read from ring */ msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len); + DHD_RING_UNLOCK(ring->ring_lock, flags); + if (msg_addr == NULL) { more = FALSE; break; @@ -4504,6 +4586,7 @@ dhd_prot_process_trapbuf(dhd_pub_t *dhd) if (data & D2H_DEV_FWHALT) { DHD_ERROR(("Firmware trapped and trap_data is 0x%04x\n", data)); + if (data & D2H_DEV_EXT_TRAP_DATA) { if (dhd->extended_trap_data) { @@ -4525,6 +4608,7 @@ dhd_prot_process_ctrlbuf(dhd_pub_t *dhd) { dhd_prot_t *prot = dhd->prot; msgbuf_ring_t *ring = &prot->d2hring_ctrl_cpln; + unsigned long flags; /* Process all the messages - DTOH direction */ while (!dhd_is_device_removed(dhd)) { @@ -4535,8 +4619,11 @@ dhd_prot_process_ctrlbuf(dhd_pub_t *dhd) break; } + DHD_RING_LOCK(ring->ring_lock, flags); /* Get the address of the next message to be read from ring */ msg_addr = dhd_prot_get_read_addr(dhd, ring, &msg_len); + DHD_RING_UNLOCK(ring->ring_lock, flags); + if (msg_addr == NULL) { break; } @@ -4619,6 +4706,18 @@ dhd_prot_process_msgtype(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint8 *buf, uint32 goto done; } + if (msg_type == MSG_TYPE_INFO_BUF_CMPLT) { + if (ring == dhd->prot->d2hring_info_cpln) { + if (!dhd->prot->infobufpost) { + DHD_ERROR(("infobuf posted are zero," + "but there is a completion\n")); + goto done; + } + dhd->prot->infobufpost--; + dhd_prot_infobufpost(dhd, dhd->prot->h2dring_info_subn); + dhd_prot_process_infobuf_complete(dhd, buf); + } + } else if (table_lookup[msg_type]) { table_lookup[msg_type](dhd, buf); } @@ -4635,7 +4734,7 @@ done: #ifdef DHD_RX_CHAINING dhd_rxchain_commit(dhd); -#endif +#endif // endif return ret; } /* dhd_prot_process_msgtype */ @@ -4720,9 +4819,11 @@ dhd_prot_ioctack_process(dhd_pub_t *dhd, void *msg) { ioctl_req_ack_msg_t *ioct_ack = (ioctl_req_ack_msg_t *)msg; unsigned long flags; -#ifdef DHD_PKTID_AUDIT_RING +#if defined(DHD_PKTID_AUDIT_RING) uint32 pktid = ltoh32(ioct_ack->cmn_hdr.request_id); +#endif // endif +#if defined(DHD_PKTID_AUDIT_RING) /* Skip audit for ADHD_IOCTL_REQ_PKTID = 0xFFFE */ if (pktid != DHD_IOCTL_REQ_PKTID) { #ifndef IOCTLRESP_USE_CONSTMEM @@ -4733,7 +4834,7 @@ dhd_prot_ioctack_process(dhd_pub_t *dhd, void *msg) DHD_TEST_IS_ALLOC, msg, D2HRING_CTRL_CMPLT_ITEMSIZE); #endif /* !IOCTLRESP_USE_CONSTMEM */ } -#endif /* DHD_PKTID_AUDIT_RING */ +#endif // endif DHD_GENERAL_LOCK(dhd, flags); if ((dhd->prot->ioctl_state & MSGBUF_IOCTL_ACK_PENDING) && @@ -4753,11 +4854,6 @@ dhd_prot_ioctack_process(dhd_pub_t *dhd, void *msg) if (ioct_ack->compl_hdr.status != 0) { DHD_ERROR(("got an error status for the ioctl request...need to handle that\n")); } -#ifdef REPORT_FATAL_TIMEOUTS - else { - dhd_stop_bus_timer(dhd); - } -#endif /* REPORT_FATAL_TIMEOUTS */ } /** called on MSG_TYPE_IOCTL_CMPLT message received from dongle */ @@ -4770,15 +4866,12 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) void *pkt; unsigned long flags; dhd_dma_buf_t retbuf; -#ifdef REPORT_FATAL_TIMEOUTS - uint16 dhd_xt_id; -#endif memset(&retbuf, 0, sizeof(dhd_dma_buf_t)); pkt_id = ltoh32(ioct_resp->cmn_hdr.request_id); -#ifdef DHD_PKTID_AUDIT_RING +#if defined(DHD_PKTID_AUDIT_RING) #ifndef IOCTLRESP_USE_CONSTMEM DHD_PKTID_AUDIT_RING_DEBUG(dhd, prot->pktid_ctrl_map, pkt_id, DHD_DUPLICATE_FREE, msg, D2HRING_CTRL_CMPLT_ITEMSIZE); @@ -4786,7 +4879,7 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) DHD_PKTID_AUDIT_RING_DEBUG(dhd, prot->pktid_map_handle_ioctl, pkt_id, DHD_DUPLICATE_FREE, msg, D2HRING_CTRL_CMPLT_ITEMSIZE); #endif /* !IOCTLRESP_USE_CONSTMEM */ -#endif /* DHD_PKTID_AUDIT_RING */ +#endif // endif DHD_GENERAL_LOCK(dhd, flags); if ((prot->ioctl_state & MSGBUF_IOCTL_ACK_PENDING) || @@ -4801,6 +4894,7 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) /* Clear Response pending bit */ prot->ioctl_state &= ~MSGBUF_IOCTL_RESP_PENDING; + DHD_GENERAL_UNLOCK(dhd, flags); #ifndef IOCTLRESP_USE_CONSTMEM pkt = dhd_prot_packet_get(dhd, pkt_id, PKTTYPE_IOCTL_RX, TRUE); @@ -4809,13 +4903,11 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) pkt = retbuf.va; #endif /* !IOCTLRESP_USE_CONSTMEM */ if (!pkt) { - DHD_GENERAL_UNLOCK(dhd, flags); DHD_ERROR(("%s: received ioctl response with NULL pkt\n", __FUNCTION__)); prhex("dhd_prot_ioctcmplt_process:", (uchar *)msg, D2HRING_CTRL_CMPLT_ITEMSIZE); return; } - DHD_GENERAL_UNLOCK(dhd, flags); prot->ioctl_resplen = ltoh16(ioct_resp->resp_len); prot->ioctl_status = ltoh16(ioct_resp->compl_hdr.status); @@ -4825,9 +4917,6 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) DHD_ERROR(("%s: transaction id(%d %d) or cmd(%d %d) mismatch\n", __FUNCTION__, xt_id, prot->ioctl_trans_id, prot->curr_ioctl_cmd, ioct_resp->cmd)); -#ifdef REPORT_FATAL_TIMEOUTS - dhd_stop_cmd_timer(dhd); -#endif /* REPORT_FATAL_TIMEOUTS */ dhd_wakeup_ioctl_event(dhd, IOCTL_RETURN_ON_ERROR); dhd_prot_debug_info_print(dhd); #ifdef DHD_FW_COREDUMP @@ -4842,15 +4931,6 @@ dhd_prot_ioctcmplt_process(dhd_pub_t *dhd, void *msg) dhd_schedule_reset(dhd); goto exit; } -#ifdef REPORT_FATAL_TIMEOUTS - dhd_xt_id = dhd_get_request_id(dhd); - if (xt_id == dhd_xt_id) { - dhd_stop_cmd_timer(dhd); - } else { - DHD_ERROR(("%s: Cmd timer not stopped received xt_id %d stored xt_id %d", - __FUNCTION__, xt_id, dhd_xt_id)); - } -#endif /* REPORT_FATAL_TIMEOUTS */ DHD_CTL(("IOCTL_COMPLETE: req_id %x transid %d status %x resplen %d\n", pkt_id, xt_id, prot->ioctl_status, prot->ioctl_resplen)); @@ -4895,32 +4975,19 @@ dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg) void *dmah; void *secdma; bool pkt_fate; -#ifdef DEVICE_TX_STUCK_DETECT - flow_ring_node_t *flow_ring_node; - uint16 flowid; -#endif /* DEVICE_TX_STUCK_DETECT */ - + msgbuf_ring_t *ring = &dhd->prot->d2hring_tx_cpln; txstatus = (host_txbuf_cmpl_t *)msg; -#ifdef DEVICE_TX_STUCK_DETECT - flowid = txstatus->compl_hdr.flow_ring_id; - flow_ring_node = DHD_FLOW_RING(dhd, flowid); - /** - * Since we got a completion message on this flowid, - * update tx_cmpl time stamp - */ - flow_ring_node->tx_cmpl = OSL_SYSUPTIME(); -#endif /* DEVICE_TX_STUCK_DETECT */ /* locks required to protect circular buffer accesses */ - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); pktid = ltoh32(txstatus->cmn_hdr.request_id); pkt_fate = TRUE; -#ifdef DHD_PKTID_AUDIT_RING +#if defined(DHD_PKTID_AUDIT_RING) DHD_PKTID_AUDIT_RING_DEBUG(dhd, dhd->prot->pktid_tx_map, pktid, DHD_DUPLICATE_FREE, msg, D2HRING_TXCMPLT_ITEMSIZE); -#endif /* DHD_PKTID_AUDIT_RING */ +#endif // endif DHD_INFO(("txstatus for pktid 0x%04x\n", pktid)); if (prot->active_tx_count) { @@ -4934,16 +5001,27 @@ dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg) } ASSERT(pktid != 0); + + pkt = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_tx_map, pktid, + pa, len, dmah, secdma, PKTTYPE_DATA_TX); + if (pkt) { + if (SECURE_DMA_ENAB(dhd->osh)) { + int offset = 0; + BCM_REFERENCE(offset); + + if (dhd->prot->tx_metadata_offset) + offset = dhd->prot->tx_metadata_offset + ETHER_HDR_LEN; + SECURE_DMA_UNMAP(dhd->osh, (uint) pa, + (uint) dhd->prot->tx_metadata_offset, DMA_RX, 0, dmah, + secdma, offset); + } else + DMA_UNMAP(dhd->osh, pa, (uint) len, DMA_RX, 0, dmah); + } #if defined(DHD_LB_TXC) && !defined(BCM_SECURE_DMA) { int elem_ix; void **elem; bcm_workq_t *workq; - dmaaddr_t pa; - uint32 pa_len; - - pkt = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_tx_map, - pktid, pa, pa_len, dmah, secdma, PKTTYPE_DATA_TX); workq = &prot->tx_compl_prod; /* @@ -4956,7 +5034,7 @@ dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg) elem_ix = bcm_ring_prod(WORKQ_RING(workq), DHD_LB_WORKQ_SZ); DHD_PKTTAG_SET_PA((dhd_pkttag_fr_t *)PKTTAG(pkt), pa); - DHD_PKTTAG_SET_PA_LEN((dhd_pkttag_fr_t *)PKTTAG(pkt), pa_len); + DHD_PKTTAG_SET_PA_LEN((dhd_pkttag_fr_t *)PKTTAG(pkt), len); if (elem_ix == BCM_RING_FULL) { DHD_ERROR(("tx_compl_prod BCM_RING_FULL\n")); @@ -4977,51 +5055,30 @@ dhd_prot_txstatus_process(dhd_pub_t *dhd, void *msg) DHD_INFO(("%s: tx_compl_prod pkt<%p> sync<%d>\n", __FUNCTION__, pkt, prot->tx_compl_prod_sync)); - DHD_GENERAL_UNLOCK(dhd, flags); - + DHD_RING_UNLOCK(ring->ring_lock, flags); return; } workq_ring_full: #endif /* !DHD_LB_TXC */ - - pkt = DHD_PKTID_TO_NATIVE(dhd, dhd->prot->pktid_tx_map, pktid, - pa, len, dmah, secdma, PKTTYPE_DATA_TX); - if (pkt) { - if (SECURE_DMA_ENAB(dhd->osh)) { - int offset = 0; - BCM_REFERENCE(offset); - if (dhd->prot->tx_metadata_offset) - offset = dhd->prot->tx_metadata_offset + ETHER_HDR_LEN; - SECURE_DMA_UNMAP(dhd->osh, (uint) pa, - (uint) dhd->prot->tx_metadata_offset, DMA_RX, 0, dmah, - secdma, offset); - } else - DMA_UNMAP(dhd->osh, pa, (uint) len, DMA_RX, 0, dmah); #ifdef DMAMAP_STATS dhd->dma_stats.txdata--; dhd->dma_stats.txdata_sz -= len; #endif /* DMAMAP_STATS */ -#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING) - if (dhd->d11_tx_status) { - uint16 tx_status; - - tx_status = ltoh16(txstatus->compl_hdr.status) & - WLFC_CTL_PKTFLAG_MASK; - pkt_fate = (tx_status == WLFC_CTL_PKTFLAG_DISCARD) ? TRUE : FALSE; - - DHD_DBG_PKT_MON_TX_STATUS(dhd, pkt, pktid, tx_status); + pkt_fate = dhd_dbg_process_tx_status(dhd, pkt, pktid, + ltoh16(txstatus->compl_hdr.status) & WLFC_CTL_PKTFLAG_MASK); #ifdef DHD_PKT_LOGGING - DHD_PKTLOG_TXS(dhd, pkt, pktid, tx_status); -#endif /* DHD_PKT_LOGGING */ + if (dhd->d11_tx_status) { + DHD_PKTLOG_TXS(dhd, pkt, pktid, + ltoh16(txstatus->compl_hdr.status) & WLFC_CTL_PKTFLAG_MASK); } -#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */ +#endif /* DHD_PKT_LOGGING */ #if defined(BCMPCIE) dhd_txcomplete(dhd, pkt, pkt_fate); -#endif +#endif // endif #if DHD_DBG_SHOW_METADATA if (dhd->prot->metadata_dbg && @@ -5036,24 +5093,16 @@ workq_ring_full: dhd_prot_print_metadata(dhd, ptr, txstatus->metadata_len); } #endif /* DHD_DBG_SHOW_METADATA */ - DHD_GENERAL_UNLOCK(dhd, flags); + + DHD_RING_UNLOCK(ring->ring_lock, flags); PKTFREE(dhd->osh, pkt, TRUE); - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); DHD_FLOWRING_TXSTATUS_CNT_UPDATE(dhd->bus, txstatus->compl_hdr.flow_ring_id, txstatus->tx_status); -#ifdef DHD_TIMESYNC - if (dhd->prot->tx_ts_log_enabled) { - ts_timestamp_t *ts = (ts_timestamp_t *)&(txstatus->ts); - dhd_timesync_log_tx_timestamp(dhd->ts, - txstatus->compl_hdr.flow_ring_id, - txstatus->cmn_hdr.if_id, - ts->low, ts->high); - } -#endif /* DHD_TIMESYNC */ } - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); return; } /* dhd_prot_txstatus_process */ @@ -5067,17 +5116,16 @@ dhd_prot_event_process(dhd_pub_t *dhd, void *msg) uint16 buflen; int ifidx = 0; void* pkt; - unsigned long flags; dhd_prot_t *prot = dhd->prot; /* Event complete header */ evnt = (wlevent_req_msg_t *)msg; bufid = ltoh32(evnt->cmn_hdr.request_id); -#ifdef DHD_PKTID_AUDIT_RING +#if defined(DHD_PKTID_AUDIT_RING) DHD_PKTID_AUDIT_RING_DEBUG(dhd, dhd->prot->pktid_ctrl_map, bufid, DHD_DUPLICATE_FREE, msg, D2HRING_CTRL_CMPLT_ITEMSIZE); -#endif /* DHD_PKTID_AUDIT_RING */ +#endif // endif buflen = ltoh16(evnt->event_data_len); @@ -5088,10 +5136,7 @@ dhd_prot_event_process(dhd_pub_t *dhd, void *msg) prot->cur_event_bufs_posted--; dhd_msgbuf_rxbuf_post_event_bufs(dhd); - /* locks required to protect pktid_map */ - DHD_GENERAL_LOCK(dhd, flags); pkt = dhd_prot_packet_get(dhd, bufid, PKTTYPE_EVENT_RX, TRUE); - DHD_GENERAL_UNLOCK(dhd, flags); if (!pkt) { DHD_ERROR(("%s: pkt is NULL for pktid %d\n", __FUNCTION__, bufid)); @@ -5115,7 +5160,6 @@ dhd_prot_process_infobuf_complete(dhd_pub_t *dhd, void* buf) uint32 pktid; uint16 buflen; void * pkt; - unsigned long flags; resp = (info_buf_resp_t *)buf; pktid = ltoh32(resp->cmn_hdr.request_id); @@ -5130,18 +5174,7 @@ dhd_prot_process_infobuf_complete(dhd_pub_t *dhd, void* buf) pktid, buflen, resp->cmn_hdr.flags, ltoh16(resp->seqnum), dhd->prot->rx_dataoffset)); - if (!dhd->prot->infobufpost) { - DHD_ERROR(("infobuf posted are zero, but there is a completion\n")); - return; - } - - dhd->prot->infobufpost--; - dhd_prot_infobufpost(dhd); - - DHD_GENERAL_LOCK(dhd, flags); pkt = dhd_prot_packet_get(dhd, pktid, PKTTYPE_INFO_RX, TRUE); - DHD_GENERAL_UNLOCK(dhd, flags); - if (!pkt) return; @@ -5155,7 +5188,13 @@ dhd_prot_process_infobuf_complete(dhd_pub_t *dhd, void* buf) * special ifidx of -1. This is just internal to dhd to get the data to * dhd_linux.c:dhd_rx_frame() from here (dhd_prot_infobuf_cmplt_process). */ - dhd_bus_rx_frame(dhd->bus, pkt, DHD_EVENT_IF /* ifidx HACK */, 1); + dhd_bus_rx_frame(dhd->bus, pkt, DHD_DUMMY_INFO_IF /* ifidx HACK */, 1); +} + +/** called on MSG_TYPE_SNAPSHOT_CMPLT message received from dongle */ +static void BCMFASTPATH +dhd_prot_process_snapshot_complete(dhd_pub_t *dhd, void *buf) +{ } /** Stop protocol: sync w/dongle state. */ @@ -5181,7 +5220,6 @@ dhd_prot_hdrlen(dhd_pub_t *dhd, void *PKTBUF) return 0; } - #define PKTBUF pktbuf /** @@ -5216,19 +5254,14 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) ring = (msgbuf_ring_t *)flow_ring_node->prot_info; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); /* Create a unique 32-bit packet id */ pktid = DHD_NATIVE_TO_PKTID_RSV(dhd, dhd->prot->pktid_tx_map, PKTBUF, PKTTYPE_DATA_TX); #if defined(DHD_PCIE_PKTID) if (pktid == DHD_PKTID_INVALID) { - DHD_ERROR(("%s: Pktid pool depleted.\n", __FUNCTION__)); + DHD_ERROR_RLMT(("%s: Pktid pool depleted.\n", __FUNCTION__)); /* * If we return error here, the caller would queue the packet * again. So we'll just free the skb allocated in DMA Zone. @@ -5248,14 +5281,11 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) goto err_free_pktid; } -#ifdef DBG_PKT_MON DHD_DBG_PKT_MON_TX(dhd, PKTBUF, pktid); -#endif /* DBG_PKT_MON */ #ifdef DHD_PKT_LOGGING DHD_PKTLOG_TX(dhd, PKTBUF, pktid); #endif /* DHD_PKT_LOGGING */ - /* Extract the data pointer and length information */ pktdata = PKTDATA(dhd->osh, PKTBUF); pktlen = PKTLEN(dhd->osh, PKTBUF); @@ -5302,7 +5332,7 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) if (ring->pend_items_count == 0) ring->start_addr = (void *)txdesc; ring->pend_items_count++; -#endif +#endif // endif /* Form the Tx descriptor message buffer */ @@ -5314,7 +5344,6 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) txdesc->flags = BCMPCIE_PKT_FLAGS_FRAME_802_3; prio = (uint8)PKTPRIO(PKTBUF); - txdesc->flags |= (prio & 0x7) << BCMPCIE_PKT_FLAGS_PRIO_SHIFT; txdesc->seg_cnt = 1; @@ -5351,7 +5380,6 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) if (PHYSADDRISZERO(meta_pa)) { /* Unmap the data pointer to a DMA-able address */ if (SECURE_DMA_ENAB(dhd->osh)) { - int offset = 0; BCM_REFERENCE(offset); @@ -5405,15 +5433,14 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) /* occupying the last slot in the flow_ring - before wrap around. */ if ((ring->pend_items_count == prot->txp_threshold) || ((uint8 *) txdesc == (uint8 *) DHD_RING_END_VA(ring))) { - dhd_prot_txdata_write_flush(dhd, flowid, TRUE); + dhd_prot_txdata_write_flush(dhd, flowid); } #else /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, txdesc, 1); -#endif +#endif // endif prot->active_tx_count++; - /* * Take a wake lock, do not sleep if we have atleast one packet * to finish. @@ -5421,11 +5448,7 @@ dhd_prot_txdata(dhd_pub_t *dhd, void *PKTBUF, uint8 ifidx) if (prot->active_tx_count >= 1) DHD_TXFL_WAKE_LOCK_TIMEOUT(dhd, MAX_TX_TIMEOUT); - DHD_GENERAL_UNLOCK(dhd, flags); - -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_OK; @@ -5455,22 +5478,17 @@ err_free_pktid: err_no_res_pktfree: #endif /* DHD_PCIE_PKTID */ + DHD_RING_UNLOCK(ring->ring_lock, flags); - - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif return BCME_NORESOURCE; } /* dhd_prot_txdata */ -/* called with a lock */ +/* called with a ring_lock */ /** optimization to write "n" tx items at a time to ring */ void BCMFASTPATH -dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flowid, bool in_lock) +dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flowid) { #ifdef TXP_FLUSH_NITEMS - unsigned long flags = 0; flow_ring_table_t *flow_ring_table; flow_ring_node_t *flow_ring_node; msgbuf_ring_t *ring; @@ -5479,10 +5497,6 @@ dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flowid, bool in_lock) return; } - if (!in_lock) { - DHD_GENERAL_LOCK(dhd, flags); - } - flow_ring_table = (flow_ring_table_t *)dhd->flow_ring_table; flow_ring_node = (flow_ring_node_t *)&flow_ring_table[flowid]; ring = (msgbuf_ring_t *)flow_ring_node->prot_info; @@ -5494,10 +5508,6 @@ dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flowid, bool in_lock) ring->pend_items_count = 0; ring->start_addr = NULL; } - - if (!in_lock) { - DHD_GENERAL_UNLOCK(dhd, flags); - } #endif /* TXP_FLUSH_NITEMS */ } @@ -5564,9 +5574,9 @@ static void dhd_prot_wlioctl_intercept(dhd_pub_t *dhd, wl_ioctl_t * ioc, void * buf) { dhd_prot_t *prot = dhd->prot; + int slen = 0; if (ioc->cmd == WLC_SET_VAR && buf != NULL && !strcmp(buf, "pcie_bus_tput")) { - int slen = 0; pcie_bus_tput_params_t *tput_params; slen = strlen("pcie_bus_tput") + 1; @@ -5575,6 +5585,28 @@ dhd_prot_wlioctl_intercept(dhd_pub_t *dhd, wl_ioctl_t * ioc, void * buf) sizeof(tput_params->host_buf_addr)); tput_params->host_buf_len = DHD_BUS_TPUT_BUF_LEN; } + +} + +/* called after an ioctl returns from dongle */ +static void +dhd_prot_wl_ioctl_ret_intercept(dhd_pub_t *dhd, wl_ioctl_t * ioc, void * buf, + int ifidx, int ret, int len) +{ + + if (!ret && ioc->cmd == WLC_SET_VAR && buf != NULL) { + /* Intercept the wme_dp ioctl here */ + if (!strcmp(buf, "wme_dp")) { + int slen, val = 0; + + slen = strlen("wme_dp") + 1; + if (len >= (int)(slen + sizeof(int))) + bcopy(((char *)buf + slen), &val, sizeof(int)); + dhd->wme_dp = (uint8) ltoh32(val); + } + + } + } #ifdef DHD_PM_CONTROL_FROM_FILE @@ -5587,9 +5619,15 @@ int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int int ret = -1; uint8 action; + if (dhd->bus->is_linkdown) { + DHD_ERROR(("%s : PCIe link is down. we have nothing to do\n", __FUNCTION__)); + goto done; + } + if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) { - DHD_ERROR(("%s : bus is down. we have nothing to do - bs: %d, has: %d\n", - __FUNCTION__, dhd->busstate, dhd->hang_was_sent)); + DHD_ERROR(("%s : bus is down. we have nothing to do -" + " bus state: %d, sent hang: %d\n", __FUNCTION__, + dhd->busstate, dhd->hang_was_sent)); goto done; } @@ -5635,18 +5673,7 @@ int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int dhd->dongle_error = ret; } - if (!ret && ioc->cmd == WLC_SET_VAR && buf != NULL) { - /* Intercept the wme_dp ioctl here */ - if (!strcmp(buf, "wme_dp")) { - int slen, val = 0; - - slen = strlen("wme_dp") + 1; - if (len >= (int)(slen + sizeof(int))) - bcopy(((char *)buf + slen), &val, sizeof(int)); - dhd->wme_dp = (uint8) ltoh32(val); - } - - } + dhd_prot_wl_ioctl_ret_intercept(dhd, ioc, buf, ifidx, ret, len); done: return ret; @@ -5671,21 +5698,13 @@ dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len) msglen = ALIGN_SIZE(msglen, DMA_ALIGN_LEN); msglen = LIMIT_TO_MAX(msglen, MSGBUF_MAX_MSG_SIZE); -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); ioct_rqst = (ioct_reqst_hdr_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (ioct_rqst == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return 0; } @@ -5711,10 +5730,8 @@ dhdmsgbuf_lpbk_req(dhd_pub_t *dhd, uint len) /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, ioct_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return 0; } @@ -5756,7 +5773,6 @@ mem_alloc_fail: return BCME_NOMEM; } /* dhd_prepare_schedule_dmaxfer_free */ - /** test / loopback */ void dmaxfer_free_prev_dmaaddr(dhd_pub_t *dhdp, dmaxref_mem_map_t *dmmap) @@ -5770,7 +5786,6 @@ dmaxfer_free_prev_dmaaddr(dhd_pub_t *dhdp, dmaxref_mem_map_t *dmmap) } /* dmaxfer_free_prev_dmaaddr */ - /** test / loopback */ int dmaxfer_prepare_dmaaddr(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay, dhd_dmaxfer_t *dmaxfer) @@ -5834,9 +5849,9 @@ dhd_msgbuf_dmaxfer_process(dhd_pub_t *dhd, void *msg) OSL_CACHE_INV(prot->dmaxfer.dstmem.va, prot->dmaxfer.len); if (prot->dmaxfer.srcmem.va && prot->dmaxfer.dstmem.va) { if (memcmp(prot->dmaxfer.srcmem.va, - prot->dmaxfer.dstmem.va, prot->dmaxfer.len) || - cmplt->compl_hdr.status != BCME_OK) { - DHD_ERROR(("DMA loopback failed\n")); + prot->dmaxfer.dstmem.va, prot->dmaxfer.len) || + cmplt->compl_hdr.status != BCME_OK) { + DHD_ERROR(("DMA loopback failed\n")); prhex("XFER SRC: ", prot->dmaxfer.srcmem.va, prot->dmaxfer.len); prhex("XFER DST: ", @@ -5874,9 +5889,9 @@ dhd_msgbuf_dmaxfer_process(dhd_pub_t *dhd, void *msg) prot->dmaxfer.len, DHD_INFO_VAL); dhd_prhex("XFER DST: ", prot->dmaxfer.dstmem.va, prot->dmaxfer.len, DHD_INFO_VAL); + } } } - } dhd_prepare_schedule_dmaxfer_free(dhd); end_usec -= prot->dmaxfer.start_usec; @@ -5918,13 +5933,13 @@ dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay, return BCME_ERROR; } - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); prot->dmaxfer.in_progress = TRUE; if ((ret = dmaxfer_prepare_dmaaddr(dhd, xferlen, srcdelay, destdelay, &prot->dmaxfer)) != BCME_OK) { prot->dmaxfer.in_progress = FALSE; - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); return ret; } @@ -5934,7 +5949,7 @@ dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay, if (dmap == NULL) { dmaxfer_free_dmaaddr(dhd, &prot->dmaxfer); prot->dmaxfer.in_progress = FALSE; - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_NOMEM; } @@ -5956,13 +5971,13 @@ dhdmsgbuf_dmaxfer_req(dhd_pub_t *dhd, uint len, uint srcdelay, uint destdelay, dmap->flags = (((core_num & PCIE_DMA_XFER_FLG_CORE_NUMBER_MASK) << PCIE_DMA_XFER_FLG_CORE_NUMBER_SHIFT) | ((prot->dmaxfer.d11_lpbk & PCIE_DMA_XFER_FLG_D11_LPBK_MASK) - << PCIE_DMA_XFER_FLG_D11_LPBK_SHIFT)); + << PCIE_DMA_XFER_FLG_D11_LPBK_SHIFT)); prot->dmaxfer.start_usec = OSL_SYSUPTIME_US(); /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, dmap, 1); - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DHD_ERROR(("DMA loopback Started...\n")); @@ -5991,6 +6006,24 @@ dhd_msgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (dhd->bus->is_linkdown) { + DHD_ERROR(("%s : PCIe link is down. we have nothing to do\n", + __FUNCTION__)); + return -EIO; + } + + if (dhd->busstate == DHD_BUS_DOWN) { + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); + return -EIO; + } + + /* don't talk to the dongle if fw is about to be reloaded */ + if (dhd->hang_was_sent) { + DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n", + __FUNCTION__)); + return -EIO; + } + if (cmd == WLC_GET_VAR && buf) { if (!len || !*(uint8 *)buf) { @@ -6004,58 +6037,25 @@ dhd_msgbuf_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, if ((len >= strlen("bcmerrorstr")) && (!strcmp((char *)buf, "bcmerrorstr"))) { - strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), copylen); *(uint8 *)((uint8 *)buf + (copylen - 1)) = '\0'; - goto done; } else if ((len >= strlen("bcmerror")) && !strcmp((char *)buf, "bcmerror")) { - *(uint32 *)(uint32 *)buf = dhd->dongle_error; - goto done; } } - DHD_CTL(("query_ioctl: ACTION %d ifdix %d cmd %d len %d \n", action, ifidx, cmd, len)); -#ifdef REPORT_FATAL_TIMEOUTS - /* - * These timers "should" be started before sending H2D interrupt. - * Think of the scenario where H2D interrupt is fired and the Dongle - * responds back immediately. From the DPC we would stop the cmd, bus - * timers. But the process context could have switched out leading to - * a situation where the timers are Not started yet, but are actually stopped. - * - * Disable preemption from the time we start the timer until we are done - * with seding H2D interrupts. - */ - OSL_DISABLE_PREEMPTION(dhd->osh); - dhd_set_request_id(dhd, dhd->prot->ioctl_trans_id+1, cmd); - dhd_start_cmd_timer(dhd); - dhd_start_bus_timer(dhd); -#endif /* REPORT_FATAL_TIMEOUTS */ ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx); -#ifdef REPORT_FATAL_TIMEOUTS - /* For some reason if we fail to ring door bell, stop the timers */ if (ret < 0) { DHD_ERROR(("%s(): dhd_fillup_ioct_reqst failed \r\n", __FUNCTION__)); - dhd_stop_cmd_timer(dhd); - dhd_stop_bus_timer(dhd); - OSL_ENABLE_PREEMPTION(dhd->osh); goto done; } - OSL_ENABLE_PREEMPTION(dhd->osh); -#else - if (ret < 0) { - DHD_ERROR(("%s(): dhd_fillup_ioct_reqst failed \r\n", __FUNCTION__)); - goto done; - } -#endif /* REPORT_FATAL_TIMEOUTS */ /* wait for IOCTL completion message from dongle and get first fragment */ ret = dhd_msgbuf_wait_ioctl_cmplt(dhd, len, buf); @@ -6064,9 +6064,58 @@ done: return ret; } -/** - * Waits for IOCTL completion message from the dongle, copies this into caller - * provided parameter 'buf'. +void +dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd) +{ + + uint32 intstatus; + dhd_prot_t *prot = dhd->prot; + + dhd->rxcnt_timeout++; + dhd->rx_ctlerrs++; + dhd->iovar_timeout_occured = TRUE; + DHD_ERROR(("%s: resumed on timeout rxcnt_timeout %d ioctl_cmd %d " + "trans_id %d state %d busstate=%d ioctl_received=%d\n", + __FUNCTION__, dhd->rxcnt_timeout, prot->curr_ioctl_cmd, + prot->ioctl_trans_id, prot->ioctl_state, + dhd->busstate, prot->ioctl_received)); + if (prot->curr_ioctl_cmd == WLC_SET_VAR || + prot->curr_ioctl_cmd == WLC_GET_VAR) { + char iovbuf[32]; + int i; + int dump_size = 128; + uint8 *ioctl_buf = (uint8 *)prot->ioctbuf.va; + memset(iovbuf, 0, sizeof(iovbuf)); + strncpy(iovbuf, ioctl_buf, sizeof(iovbuf) - 1); + iovbuf[sizeof(iovbuf) - 1] = '\0'; + DHD_ERROR(("Current IOVAR (%s): %s\n", + prot->curr_ioctl_cmd == WLC_SET_VAR ? + "WLC_SET_VAR" : "WLC_GET_VAR", iovbuf)); + DHD_ERROR(("========== START IOCTL REQBUF DUMP ==========\n")); + for (i = 0; i < dump_size; i++) { + DHD_ERROR(("%02X ", ioctl_buf[i])); + if ((i % 32) == 31) { + DHD_ERROR(("\n")); + } + } + DHD_ERROR(("\n========== END IOCTL REQBUF DUMP ==========\n")); + } + + /* Check the PCIe link status by reading intstatus register */ + intstatus = si_corereg(dhd->bus->sih, + dhd->bus->sih->buscoreidx, dhd->bus->pcie_mailbox_int, 0, 0); + if (intstatus == (uint32)-1) { + DHD_ERROR(("%s : PCIe link might be down\n", __FUNCTION__)); + dhd->bus->is_linkdown = TRUE; + } + + dhd_bus_dump_console_buffer(dhd->bus); + dhd_prot_debug_info_print(dhd); +} + +/** + * Waits for IOCTL completion message from the dongle, copies this into caller + * provided parameter 'buf'. */ static int dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) @@ -6087,77 +6136,27 @@ dhd_msgbuf_wait_ioctl_cmplt(dhd_pub_t *dhd, uint32 len, void *buf) #ifdef DHD_RECOVER_TIMEOUT if (prot->ioctl_received == 0) { - uint32 intstatus = 0; - uint32 intmask = 0; - intstatus = si_corereg(dhd->bus->sih, - dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); - intmask = si_corereg(dhd->bus->sih, - dhd->bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); - if ((intstatus) && (!intmask) && (timeleft == 0) && (!dhd_query_bus_erros(dhd))) - { - DHD_ERROR(("%s: iovar timeout trying again intstatus=%x intmask=%x\n", - __FUNCTION__, intstatus, intmask)); - DHD_ERROR(("\n ------- DUMPING INTR enable/disable counters\r\n")); - DHD_ERROR(("resume_intr_enable_count=%lu dpc_intr_enable_count=%lu\n" - "isr_intr_disable_count=%lu suspend_intr_disable_count=%lu\n" - "dpc_return_busdown_count=%lu\n", - dhd->bus->resume_intr_enable_count, dhd->bus->dpc_intr_enable_count, - dhd->bus->isr_intr_disable_count, - dhd->bus->suspend_intr_disable_count, - dhd->bus->dpc_return_busdown_count)); - + uint32 intstatus = si_corereg(dhd->bus->sih, + dhd->bus->sih->buscoreidx, dhd->bus->pcie_mailbox_int, 0, 0); + int host_irq_disbled = dhdpcie_irq_disabled(dhd->bus); + if ((intstatus) && (intstatus != (uint32)-1) && + (timeleft == 0) && (!dhd_query_bus_erros(dhd))) { + DHD_ERROR(("%s: iovar timeout trying again intstatus=%x" + " host_irq_disabled=%d\n", + __FUNCTION__, intstatus, host_irq_disbled)); + dhd_pcie_intr_count_dump(dhd); + dhd_print_tasklet_status(dhd); dhd_prot_process_ctrlbuf(dhd); - timeleft = dhd_os_ioctl_resp_wait(dhd, (uint *)&prot->ioctl_received); - /* Enable Back Interrupts using IntMask */ - dhdpcie_bus_intr_enable(dhd->bus); + /* Clear Interrupts */ + dhdpcie_bus_clear_intstatus(dhd->bus); } } #endif /* DHD_RECOVER_TIMEOUT */ if (timeleft == 0 && (!dhd_query_bus_erros(dhd))) { - uint32 intstatus; - - dhd->rxcnt_timeout++; - dhd->rx_ctlerrs++; - dhd->iovar_timeout_occured = TRUE; - DHD_ERROR(("%s: resumed on timeout rxcnt_timeout %d ioctl_cmd %d " - "trans_id %d state %d busstate=%d ioctl_received=%d\n", - __FUNCTION__, dhd->rxcnt_timeout, prot->curr_ioctl_cmd, - prot->ioctl_trans_id, prot->ioctl_state, - dhd->busstate, prot->ioctl_received)); - if (prot->curr_ioctl_cmd == WLC_SET_VAR || - prot->curr_ioctl_cmd == WLC_GET_VAR) { - char iovbuf[32]; - int i; - int dump_size = 128; - uint8 *ioctl_buf = (uint8 *)prot->ioctbuf.va; - memset(iovbuf, 0, sizeof(iovbuf)); - strncpy(iovbuf, ioctl_buf, sizeof(iovbuf) - 1); - iovbuf[sizeof(iovbuf) - 1] = '\0'; - DHD_ERROR(("Current IOVAR (%s): %s\n", - prot->curr_ioctl_cmd == WLC_SET_VAR ? - "WLC_SET_VAR" : "WLC_GET_VAR", iovbuf)); - DHD_ERROR(("========== START IOCTL REQBUF DUMP ==========\n")); - for (i = 0; i < dump_size; i++) { - DHD_ERROR(("%02X ", ioctl_buf[i])); - if ((i % 32) == 31) { - DHD_ERROR(("\n")); - } - } - DHD_ERROR(("\n========== END IOCTL REQBUF DUMP ==========\n")); - } - - /* Check the PCIe link status by reading intstatus register */ - intstatus = si_corereg(dhd->bus->sih, - dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); - if (intstatus == (uint32)-1) { - DHD_ERROR(("%s : PCIe link might be down\n", __FUNCTION__)); - dhd->bus->is_linkdown = TRUE; - } - dhd_bus_dump_console_buffer(dhd->bus); - dhd_prot_debug_info_print(dhd); + dhd_msgbuf_iovar_timeout_dump(dhd); #ifdef DHD_FW_COREDUMP /* Collect socram dump */ @@ -6212,6 +6211,12 @@ dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, u DHD_TRACE(("%s: Enter \n", __FUNCTION__)); + if (dhd->bus->is_linkdown) { + DHD_ERROR(("%s : PCIe link is down. we have nothing to do\n", + __FUNCTION__)); + return -EIO; + } + if (dhd->busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); return -EIO; @@ -6227,43 +6232,13 @@ dhd_msgbuf_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, u DHD_CTL(("ACTION %d ifdix %d cmd %d len %d \n", action, ifidx, cmd, len)); -#ifdef REPORT_FATAL_TIMEOUTS - /* - * These timers "should" be started before sending H2D interrupt. - * Think of the scenario where H2D interrupt is fired and the Dongle - * responds back immediately. From the DPC we would stop the cmd, bus - * timers. But the process context could have switched out leading to - * a situation where the timers are Not started yet, but are actually stopped. - * - * Disable preemption from the time we start the timer until we are done - * with seding H2D interrupts. - */ - OSL_DISABLE_PREEMPTION(dhd->osh); - dhd_set_request_id(dhd, dhd->prot->ioctl_trans_id+1, cmd); - dhd_start_cmd_timer(dhd); - dhd_start_bus_timer(dhd); -#endif /* REPORT_FATAL_TIMEOUTS */ - /* Fill up msgbuf for ioctl req */ ret = dhd_fillup_ioct_reqst(dhd, (uint16)len, cmd, buf, ifidx); -#ifdef REPORT_FATAL_TIMEOUTS - /* For some reason if we fail to ring door bell, stop the timers */ - if (ret < 0) { - DHD_ERROR(("%s(): dhd_fillup_ioct_reqst failed \r\n", __FUNCTION__)); - dhd_stop_cmd_timer(dhd); - dhd_stop_bus_timer(dhd); - OSL_ENABLE_PREEMPTION(dhd->osh); - goto done; - } - - OSL_ENABLE_PREEMPTION(dhd->osh); -#else if (ret < 0) { DHD_ERROR(("%s(): dhd_fillup_ioct_reqst failed \r\n", __FUNCTION__)); goto done; } -#endif /* REPORT_FATAL_TIMEOUTS */ ret = dhd_msgbuf_wait_ioctl_cmplt(dhd, len, buf); @@ -6329,21 +6304,13 @@ dhd_post_dummy_msg(dhd_pub_t *dhd) dhd_prot_t *prot = dhd->prot; msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); hevent = (hostevent_hdr_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (hevent == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return -1; } @@ -6361,10 +6328,8 @@ dhd_post_dummy_msg(dhd_pub_t *dhd) * from the msgbuf, we can directly call the write_complete */ dhd_prot_ring_write_complete(dhd, ring, hevent, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return 0; } @@ -6391,8 +6356,9 @@ dhd_prot_alloc_ring_space(dhd_pub_t *dhd, msgbuf_ring_t *ring, #ifdef SUPPORT_LINKDOWN_RECOVERY /* Check if ring->rd is valid */ if (ring->rd >= ring->max_items) { - dhd->bus->read_shm_fail = TRUE; DHD_ERROR(("%s: Invalid rd idx=%d\n", ring->name, ring->rd)); + dhd_prot_debug_info_print(dhd); + dhd->bus->read_shm_fail = TRUE; return NULL; } #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -6443,22 +6409,14 @@ dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx /* Limit ioct request to MSGBUF_MAX_MSG_SIZE bytes including hdrs */ /* 8K allocation of dongle buffer fails */ /* dhd doesnt give separate input & output buf lens */ - /* so making the assumption that input length can never be more than 1.5k */ - rqstlen = MIN(rqstlen, MSGBUF_MAX_MSG_SIZE); + /* so making the assumption that input length can never be more than 2k */ + rqstlen = MIN(rqstlen, MSGBUF_IOCTL_MAX_RQSTLEN); -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); if (prot->ioctl_state) { DHD_ERROR(("%s: pending ioctl %02x\n", __FUNCTION__, prot->ioctl_state)); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_BUSY; } else { prot->ioctl_state = MSGBUF_IOCTL_ACK_PENDING | MSGBUF_IOCTL_RESP_PENDING; @@ -6472,10 +6430,7 @@ dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx prot->ioctl_state = 0; prot->curr_ioctl_cmd = 0; prot->ioctl_received = IOCTL_WAIT; - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ring->ring_lock, flags); return -1; } @@ -6514,15 +6469,12 @@ dhd_fillup_ioct_reqst(dhd_pub_t *dhd, uint16 len, uint cmd, void* buf, int ifidx /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, ioct_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return 0; } /* dhd_fillup_ioct_reqst */ - /** * dhd_prot_ring_attach - Initialize the msgbuf_ring object and attach a * DMA-able buffer to it. The ring is NOT tagged as inited until all the ring @@ -6602,6 +6554,8 @@ dhd_prot_ring_attach(dhd_pub_t *dhd, msgbuf_ring_t *ring, const char *name, } #endif /* BCM_SECURE_DMA */ + ring->ring_lock = dhd_os_spin_lock_init(dhd->osh); + DHD_INFO(("RING_ATTACH : %s Max item %d len item %d total size %d " "ring start %p buf phys addr %x:%x \n", ring->name, ring->max_items, ring->item_len, @@ -6621,7 +6575,6 @@ free_dma_buf: } /* dhd_prot_ring_attach */ - /** * dhd_prot_ring_init - Post the common ring information to dongle. * @@ -6656,7 +6609,6 @@ dhd_prot_ring_init(dhd_pub_t *dhd, msgbuf_ring_t *ring) } /* dhd_prot_ring_init */ - /** * dhd_prot_ring_reset - bzero a ring's DMA-ble buffer and cache flush * Reset WR and RD indices to 0. @@ -6674,7 +6626,6 @@ dhd_prot_ring_reset(dhd_pub_t *dhd, msgbuf_ring_t *ring) ring->create_pending = FALSE; } - /** * dhd_prot_ring_detach - Detach the DMA-able buffer and any other objects * hanging off the msgbuf_ring. @@ -6709,8 +6660,9 @@ dhd_prot_ring_detach(dhd_pub_t *dhd, msgbuf_ring_t *ring) dhd_dma_buf_free(dhd, &ring->dma_buf); } -} /* dhd_prot_ring_detach */ + dhd_os_spin_lock_deinit(dhd->osh, ring->ring_lock); +} /* dhd_prot_ring_detach */ /* * +---------------------------------------------------------------------------- @@ -6856,7 +6808,6 @@ fail: } /* dhd_prot_flowrings_pool_attach */ - /** * dhd_prot_flowrings_pool_reset - Reset all msgbuf_ring_t objects in the pool. * Invokes dhd_prot_ring_reset to perform the actual reset. @@ -6893,7 +6844,6 @@ dhd_prot_flowrings_pool_reset(dhd_pub_t *dhd) /* Flowring pool state must be as-if dhd_prot_flowrings_pool_attach */ } - /** * dhd_prot_flowrings_pool_detach - Free pool of msgbuf_ring along with * DMA-able buffers for flowrings. @@ -6919,7 +6869,6 @@ dhd_prot_flowrings_pool_detach(dhd_pub_t *dhd) dhd_prot_ring_detach(dhd, ring); } - MFREE(prot->osh, prot->h2d_flowrings_pool, (h2d_flowrings_total * sizeof(msgbuf_ring_t))); @@ -6928,7 +6877,6 @@ dhd_prot_flowrings_pool_detach(dhd_pub_t *dhd) } /* dhd_prot_flowrings_pool_detach */ - /** * dhd_prot_flowrings_pool_fetch - Fetch a preallocated and initialized * msgbuf_ring from the flowring pool, and assign it. @@ -6965,7 +6913,6 @@ dhd_prot_flowrings_pool_fetch(dhd_pub_t *dhd, uint16 flowid) return ring; } - /** * dhd_prot_flowrings_pool_release - release a previously fetched flowring's * msgbuf_ring back to the flow_ring pool. @@ -6994,7 +6941,6 @@ dhd_prot_flowrings_pool_release(dhd_pub_t *dhd, uint16 flowid, void *flow_ring) ring->curr_rd = 0; } - /* Assumes only one index is updated at a time */ /* If exactly_nitems is true, this function will allocate space for nitems or fail */ /* Exception: when wrap around is encountered, to prevent hangup (last nitems of ring buffer) */ @@ -7036,7 +6982,6 @@ dhd_prot_get_ring_space(msgbuf_ring_t *ring, uint16 nitems, uint16 * alloced, return ret_ptr; } /* dhd_prot_get_ring_space */ - /** * dhd_prot_ring_write_complete - Host updates the new WR index on producing * new messages in a H2D ring. The messages are flushed from cache prior to @@ -7047,20 +6992,18 @@ dhd_prot_get_ring_space(msgbuf_ring_t *ring, uint16 nitems, uint16 * alloced, * always hold appropriate locks. */ static void BCMFASTPATH -dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t * ring, void* p, +__dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t * ring, void* p, uint16 nitems) { dhd_prot_t *prot = dhd->prot; - uint8 db_index; + uint32 db_index; uint16 max_flowrings = dhd->bus->max_tx_flowrings; + uint corerev; /* cache flush */ OSL_CACHE_FLUSH(p, ring->item_len * nitems); - if (IDMA_DS_ACTIVE(dhd) && IDMA_ACTIVE(dhd)) { - dhd_bus_cmn_writeshared(dhd->bus, &(ring->wr), - sizeof(uint16), RING_WR_UPD, ring->idx); - } else if (IDMA_ACTIVE(dhd) || dhd->dma_h2d_ring_upd_support) { + if (IDMA_ACTIVE(dhd) || dhd->dma_h2d_ring_upd_support) { dhd_prot_dma_indx_set(dhd, ring->wr, H2D_DMA_INDX_WR_UPD, ring->idx); } else if (IFRM_ACTIVE(dhd) && DHD_IS_FLOWRING(ring->idx, max_flowrings)) { @@ -7074,17 +7017,54 @@ dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t * ring, void* p, /* raise h2d interrupt */ if (IDMA_ACTIVE(dhd) || (IFRM_ACTIVE(dhd) && DHD_IS_FLOWRING(ring->idx, max_flowrings))) { - if (IDMA_DS_ACTIVE(dhd)) { - prot->mb_ring_fn(dhd->bus, ring->wr); - } else { - db_index = IDMA_IDX0; - prot->mb_2_ring_fn(dhd->bus, db_index, TRUE); + db_index = IDMA_IDX0; + /* this api is called in wl down path..in that case sih is freed already */ + if (dhd->bus->sih) { + corerev = dhd->bus->sih->buscorerev; + /* We need to explictly configure the type of DMA for core rev >= 24 */ + if (corerev >= 24) { + db_index |= (DMA_TYPE_IDMA << DMA_TYPE_SHIFT); + } } + prot->mb_2_ring_fn(dhd->bus, db_index, TRUE); } else { prot->mb_ring_fn(dhd->bus, ring->wr); } } +static void BCMFASTPATH +dhd_prot_ring_write_complete(dhd_pub_t *dhd, msgbuf_ring_t * ring, void* p, + uint16 nitems) +{ + unsigned long flags_bus; + DHD_BUS_LOCK(dhd->bus->bus_lock, flags_bus); + __dhd_prot_ring_write_complete(dhd, ring, p, nitems); + DHD_BUS_UNLOCK(dhd->bus->bus_lock, flags_bus); +} + +/** + * dhd_prot_ring_write_complete_mbdata - will be called from dhd_prot_h2d_mbdata_send_ctrlmsg, + * which will hold DHD_BUS_LOCK to update WR pointer, Ring DB and also update bus_low_power_state + * to indicate D3_INFORM sent in the same BUS_LOCK. + */ +static void BCMFASTPATH +dhd_prot_ring_write_complete_mbdata(dhd_pub_t *dhd, msgbuf_ring_t * ring, void *p, + uint16 nitems, uint32 mb_data) +{ + unsigned long flags_bus; + + DHD_BUS_LOCK(dhd->bus->bus_lock, flags_bus); + + __dhd_prot_ring_write_complete(dhd, ring, p, nitems); + + /* Mark D3_INFORM in the same context to skip ringing H2D DB after D3_INFORM */ + if (mb_data == H2D_HOST_D3_INFORM) { + dhd->bus->bus_low_power_state = DHD_BUS_D3_INFORM_SENT; + } + + DHD_BUS_UNLOCK(dhd->bus->bus_lock, flags_bus); +} + /** * dhd_prot_upd_read_idx - Host updates the new RD index on consuming messages * from a D2H ring. The new RD index will be updated in the DMA Index array or @@ -7094,7 +7074,8 @@ static void dhd_prot_upd_read_idx(dhd_pub_t *dhd, msgbuf_ring_t * ring) { dhd_prot_t *prot = dhd->prot; - uint8 db_index; + uint32 db_index; + uint corerev; /* update read index */ /* If dma'ing h2d indices supported @@ -7104,13 +7085,15 @@ dhd_prot_upd_read_idx(dhd_pub_t *dhd, msgbuf_ring_t * ring) if (IDMA_ACTIVE(dhd)) { dhd_prot_dma_indx_set(dhd, ring->rd, D2H_DMA_INDX_RD_UPD, ring->idx); - if (IDMA_DS_ACTIVE(dhd)) { - dhd_bus_cmn_writeshared(dhd->bus, &(ring->rd), - sizeof(uint16), RING_RD_UPD, ring->idx); - } else { - db_index = IDMA_IDX1; - prot->mb_2_ring_fn(dhd->bus, db_index, FALSE); + db_index = IDMA_IDX1; + if (dhd->bus->sih) { + corerev = dhd->bus->sih->buscorerev; + /* We need to explictly configure the type of DMA for core rev >= 24 */ + if (corerev >= 24) { + db_index |= (DMA_TYPE_IDMA << DMA_TYPE_SHIFT); + } } + prot->mb_2_ring_fn(dhd->bus, db_index, FALSE); } else if (dhd->dma_h2d_ring_upd_support) { dhd_prot_dma_indx_set(dhd, ring->rd, D2H_DMA_INDX_RD_UPD, ring->idx); @@ -7121,19 +7104,17 @@ dhd_prot_upd_read_idx(dhd_pub_t *dhd, msgbuf_ring_t * ring) } static int -dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) +dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create, + uint16 ring_type, uint32 req_id) { unsigned long flags; d2h_ring_create_req_t *d2h_ring; uint16 alloced = 0; int ret = BCME_OK; uint16 max_h2d_rings = dhd->bus->max_submission_rings; + msgbuf_ring_t *ctrl_ring = &dhd->prot->h2dring_ctrl_subn; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); DHD_TRACE(("%s trying to send D2H ring create Req\n", __FUNCTION__)); @@ -7145,7 +7126,7 @@ dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) /* Request for ring buffer space */ d2h_ring = (d2h_ring_create_req_t *) dhd_prot_alloc_ring_space(dhd, - &dhd->prot->h2dring_ctrl_subn, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, + ctrl_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, &alloced, FALSE); if (d2h_ring == NULL) { @@ -7154,16 +7135,16 @@ dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) ret = BCME_NOMEM; goto err; } - ring_to_create->create_req_id = DHD_D2H_DBGRING_REQ_PKTID; + ring_to_create->create_req_id = (uint16)req_id; ring_to_create->create_pending = TRUE; /* Common msg buf hdr */ d2h_ring->msg.msg_type = MSG_TYPE_D2H_RING_CREATE; d2h_ring->msg.if_id = 0; - d2h_ring->msg.flags = dhd->prot->h2dring_ctrl_subn.current_phase; + d2h_ring->msg.flags = ctrl_ring->current_phase; d2h_ring->msg.request_id = htol32(ring_to_create->create_req_id); d2h_ring->ring_id = htol16(DHD_D2H_RING_OFFSET(ring_to_create->idx, max_h2d_rings)); - d2h_ring->ring_type = BCMPCIE_D2H_RING_TYPE_DBGBUF_CPL; + d2h_ring->ring_type = ring_type; d2h_ring->max_items = htol16(D2HRING_DYNAMIC_INFO_MAX_ITEM); d2h_ring->len_item = htol16(D2HRING_INFO_BUFCMPLT_ITEMSIZE); d2h_ring->ring_ptr.low_addr = ring_to_create->base_addr.low_addr; @@ -7171,36 +7152,33 @@ dhd_send_d2h_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) d2h_ring->flags = 0; d2h_ring->msg.epoch = - dhd->prot->h2dring_ctrl_subn.seqnum % H2D_EPOCH_MODULO; - dhd->prot->h2dring_ctrl_subn.seqnum++; + ctrl_ring->seqnum % H2D_EPOCH_MODULO; + ctrl_ring->seqnum++; /* Update the flow_ring's WRITE index */ - dhd_prot_ring_write_complete(dhd, &dhd->prot->h2dring_ctrl_subn, d2h_ring, + dhd_prot_ring_write_complete(dhd, ctrl_ring, d2h_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D); + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + + return ret; err: - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + return ret; } static int -dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) +dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create, uint8 ring_type, uint32 id) { unsigned long flags; h2d_ring_create_req_t *h2d_ring; uint16 alloced = 0; uint8 i = 0; int ret = BCME_OK; + msgbuf_ring_t *ctrl_ring = &dhd->prot->h2dring_ctrl_subn; - -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); DHD_TRACE(("%s trying to send H2D ring create Req\n", __FUNCTION__)); @@ -7212,7 +7190,7 @@ dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) /* Request for ring buffer space */ h2d_ring = (h2d_ring_create_req_t *)dhd_prot_alloc_ring_space(dhd, - &dhd->prot->h2dring_ctrl_subn, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, + ctrl_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, &alloced, FALSE); if (h2d_ring == NULL) { @@ -7221,16 +7199,16 @@ dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) ret = BCME_NOMEM; goto err; } - ring_to_create->create_req_id = DHD_H2D_DBGRING_REQ_PKTID; + ring_to_create->create_req_id = (uint16)id; ring_to_create->create_pending = TRUE; /* Common msg buf hdr */ h2d_ring->msg.msg_type = MSG_TYPE_H2D_RING_CREATE; h2d_ring->msg.if_id = 0; h2d_ring->msg.request_id = htol32(ring_to_create->create_req_id); - h2d_ring->msg.flags = dhd->prot->h2dring_ctrl_subn.current_phase; + h2d_ring->msg.flags = ctrl_ring->current_phase; h2d_ring->ring_id = htol16(DHD_H2D_RING_OFFSET(ring_to_create->idx)); - h2d_ring->ring_type = BCMPCIE_H2D_RING_TYPE_DBGBUF_SUBMIT; + h2d_ring->ring_type = ring_type; h2d_ring->max_items = htol16(H2DRING_DYNAMIC_INFO_MAX_ITEM); h2d_ring->n_completion_ids = ring_to_create->n_completion_ids; h2d_ring->len_item = htol16(H2DRING_INFO_BUFPOST_ITEMSIZE); @@ -7243,18 +7221,19 @@ dhd_send_h2d_ringcreate(dhd_pub_t *dhd, msgbuf_ring_t *ring_to_create) h2d_ring->flags = 0; h2d_ring->msg.epoch = - dhd->prot->h2dring_ctrl_subn.seqnum % H2D_EPOCH_MODULO; - dhd->prot->h2dring_ctrl_subn.seqnum++; + ctrl_ring->seqnum % H2D_EPOCH_MODULO; + ctrl_ring->seqnum++; /* Update the flow_ring's WRITE index */ - dhd_prot_ring_write_complete(dhd, &dhd->prot->h2dring_ctrl_subn, h2d_ring, + dhd_prot_ring_write_complete(dhd, ctrl_ring, h2d_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D); + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + + return ret; err: - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + return ret; } @@ -7305,7 +7284,6 @@ dhd_prot_dma_indx_set(dhd_pub_t *dhd, uint16 new_index, uint8 type, uint16 ringi } /* dhd_prot_dma_indx_set */ - /** * dhd_prot_dma_indx_get - Fetch a WR or RD index from the dongle DMA-ed index * array. @@ -7458,7 +7436,6 @@ ret_no_mem: } /* dhd_prot_dma_indx_init */ - /** * Called on checking for 'completion' messages from the dongle. Returns next host buffer to read * from, or NULL if there are no more messages to read. @@ -7518,6 +7495,7 @@ dhd_prot_get_read_addr(dhd_pub_t *dhd, msgbuf_ring_t *ring, uint32 *available_le DHD_ERROR(("\r\n======================= \r\n")); #ifdef SUPPORT_LINKDOWN_RECOVERY if (wr >= ring->max_items) { + dhd_prot_debug_info_print(dhd); dhd->bus->read_shm_fail = TRUE; } #else @@ -7566,53 +7544,43 @@ int dhd_prot_h2d_mbdata_send_ctrlmsg(dhd_pub_t *dhd, uint32 mb_data) { h2d_mailbox_data_t *h2d_mb_data; uint16 alloced = 0; + msgbuf_ring_t *ctrl_ring = &dhd->prot->h2dring_ctrl_subn; + unsigned long flags; int num_post = 1; int i; - DHD_INFO(("%s Sending H2D MB data Req data 0x%04x\n", + DHD_ERROR(("%s Sending H2D MB data Req data 0x%04x\n", __FUNCTION__, mb_data)); - if (!dhd->prot->h2dring_ctrl_subn.inited) { + if (!ctrl_ring->inited) { DHD_ERROR(("%s: Ctrl Submit Ring: not inited\n", __FUNCTION__)); return BCME_ERROR; } -#ifdef PCIE_INB_DW - if ((INBAND_DW_ENAB(dhd->bus)) && - (dhdpcie_bus_get_pcie_inband_dw_state(dhd->bus) == - DW_DEVICE_DS_DEV_SLEEP)) { - if (mb_data == H2D_HOST_CONS_INT) { - /* One additional device_wake post needed */ - num_post = 2; - } - } -#endif /* PCIE_INB_DW */ for (i = 0; i < num_post; i ++) { + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); /* Request for ring buffer space */ h2d_mb_data = (h2d_mailbox_data_t *)dhd_prot_alloc_ring_space(dhd, - &dhd->prot->h2dring_ctrl_subn, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, + ctrl_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, &alloced, FALSE); if (h2d_mb_data == NULL) { DHD_ERROR(("%s: FATAL: No space in control ring to send H2D Mb data\n", __FUNCTION__)); + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return BCME_NOMEM; } memset(h2d_mb_data, 0, sizeof(h2d_mailbox_data_t)); - /* Common msg buf hdr */ + /* Common msg buf hdr */ h2d_mb_data->msg.msg_type = MSG_TYPE_H2D_MAILBOX_DATA; - h2d_mb_data->msg.flags = dhd->prot->h2dring_ctrl_subn.current_phase; + h2d_mb_data->msg.flags = ctrl_ring->current_phase; h2d_mb_data->msg.epoch = - dhd->prot->h2dring_ctrl_subn.seqnum % H2D_EPOCH_MODULO; - dhd->prot->h2dring_ctrl_subn.seqnum++; + ctrl_ring->seqnum % H2D_EPOCH_MODULO; + ctrl_ring->seqnum++; -#ifdef PCIE_INB_DW - /* post device_wake first */ - if ((num_post == 2) && (i == 0)) { - h2d_mb_data->mail_box_data = htol32(H2DMB_DS_DEVICE_WAKE); - } else -#endif /* PCIE_INB_DW */ + /* Update flow create message */ + h2d_mb_data->mail_box_data = htol32(mb_data); { h2d_mb_data->mail_box_data = htol32(mb_data); } @@ -7620,17 +7588,12 @@ int dhd_prot_h2d_mbdata_send_ctrlmsg(dhd_pub_t *dhd, uint32 mb_data) DHD_INFO(("%s Send H2D MB data Req data 0x%04x\n", __FUNCTION__, mb_data)); /* upd wrt ptr and raise interrupt */ - /* caller of dhd_prot_h2d_mbdata_send_ctrlmsg already holding general lock */ - dhd_prot_ring_write_complete(dhd, &dhd->prot->h2dring_ctrl_subn, h2d_mb_data, - DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D); -#ifdef PCIE_INB_DW - /* Add a delay if device_wake is posted */ - if ((num_post == 2) && (i == 0)) { - OSL_DELAY(1000); - } -#endif /* PCIE_INB_DW */ - } + dhd_prot_ring_write_complete_mbdata(dhd, ctrl_ring, h2d_mb_data, + DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, mb_data); + + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + } return 0; } @@ -7654,11 +7617,7 @@ dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) return BCME_NOMEM; } -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); /* Request for ctrl_ring buffer space */ flow_create_rqst = (tx_flowring_create_request_t *) @@ -7668,10 +7627,7 @@ dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) dhd_prot_flowrings_pool_release(dhd, flow_ring_node->flowid, flow_ring); DHD_ERROR(("%s: Flow Create Req flowid %d - failure ring space\n", __FUNCTION__, flow_ring_node->flowid)); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); return BCME_NOMEM; } @@ -7723,10 +7679,7 @@ dhd_prot_flow_ring_create(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) /* update control subn ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ctrl_ring, flow_create_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return BCME_OK; } /* dhd_prot_flow_ring_create */ @@ -7754,22 +7707,27 @@ dhd_prot_process_h2d_ring_create_complete(dhd_pub_t *dhd, void *buf) ltoh16(resp->cmplt.status), ltoh16(resp->cmplt.ring_id), ltoh32(resp->cmn_hdr.request_id))); - if (ltoh32(resp->cmn_hdr.request_id) != DHD_H2D_DBGRING_REQ_PKTID) { + if ((ltoh32(resp->cmn_hdr.request_id) != DHD_H2D_DBGRING_REQ_PKTID) && + (ltoh32(resp->cmn_hdr.request_id) != DHD_H2D_BTLOGRING_REQ_PKTID)) { DHD_ERROR(("invalid request ID with h2d ring create complete\n")); return; } - if (!dhd->prot->h2dring_info_subn->create_pending) { + if (dhd->prot->h2dring_info_subn->create_req_id == ltoh32(resp->cmn_hdr.request_id) && + !dhd->prot->h2dring_info_subn->create_pending) { DHD_ERROR(("info ring create status for not pending submit ring\n")); } if (ltoh16(resp->cmplt.status) != BCMPCIE_SUCCESS) { - DHD_ERROR(("info ring create failed with status %d\n", + DHD_ERROR(("info/btlog ring create failed with status %d\n", ltoh16(resp->cmplt.status))); return; } - dhd->prot->h2dring_info_subn->create_pending = FALSE; - dhd->prot->h2dring_info_subn->inited = TRUE; - dhd_prot_infobufpost(dhd); + if (dhd->prot->h2dring_info_subn->create_req_id == ltoh32(resp->cmn_hdr.request_id)) { + dhd->prot->h2dring_info_subn->create_pending = FALSE; + dhd->prot->h2dring_info_subn->inited = TRUE; + DHD_ERROR(("info buffer post after ring create\n")); + dhd_prot_infobufpost(dhd, dhd->prot->h2dring_info_subn); + } } static void @@ -7780,22 +7738,25 @@ dhd_prot_process_d2h_ring_create_complete(dhd_pub_t *dhd, void *buf) ltoh16(resp->cmplt.status), ltoh16(resp->cmplt.ring_id), ltoh32(resp->cmn_hdr.request_id))); - if (ltoh32(resp->cmn_hdr.request_id) != DHD_D2H_DBGRING_REQ_PKTID) { + if ((ltoh32(resp->cmn_hdr.request_id) != DHD_D2H_DBGRING_REQ_PKTID) && + (ltoh32(resp->cmn_hdr.request_id) != DHD_D2H_BTLOGRING_REQ_PKTID)) { DHD_ERROR(("invalid request ID with d2h ring create complete\n")); return; } - if (!dhd->prot->d2hring_info_cpln->create_pending) { - DHD_ERROR(("info ring create status for not pending cpl ring\n")); - return; - } + if (ltoh32(resp->cmn_hdr.request_id) == DHD_D2H_DBGRING_REQ_PKTID) { + if (!dhd->prot->d2hring_info_cpln->create_pending) { + DHD_ERROR(("info ring create status for not pending cpl ring\n")); + return; + } - if (ltoh16(resp->cmplt.status) != BCMPCIE_SUCCESS) { - DHD_ERROR(("info cpl ring create failed with status %d\n", - ltoh16(resp->cmplt.status))); - return; + if (ltoh16(resp->cmplt.status) != BCMPCIE_SUCCESS) { + DHD_ERROR(("info cpl ring create failed with status %d\n", + ltoh16(resp->cmplt.status))); + return; + } + dhd->prot->d2hring_info_cpln->create_pending = FALSE; + dhd->prot->d2hring_info_cpln->inited = TRUE; } - dhd->prot->d2hring_info_cpln->create_pending = FALSE; - dhd->prot->d2hring_info_cpln->inited = TRUE; } static void @@ -7812,31 +7773,7 @@ dhd_prot_process_d2h_mb_data(dhd_pub_t *dhd, void* buf) static void dhd_prot_process_d2h_host_ts_complete(dhd_pub_t *dhd, void* buf) { -#ifdef DHD_TIMESYNC - host_timestamp_msg_cpl_t *host_ts_cpl; - uint32 pktid; - dhd_prot_t *prot = dhd->prot; - - host_ts_cpl = (host_timestamp_msg_cpl_t *)buf; - DHD_INFO(("%s host TS cpl: status %d, req_ID: 0x%04x, xt_id %d \n", __FUNCTION__, - host_ts_cpl->cmplt.status, host_ts_cpl->msg.request_id, host_ts_cpl->xt_id)); - - pktid = ltoh32(host_ts_cpl->msg.request_id); - if (prot->hostts_req_buf_inuse == FALSE) { - DHD_ERROR(("No Pending Host TS req, but completion\n")); - return; - } - prot->hostts_req_buf_inuse = FALSE; - if (pktid != DHD_H2D_HOSTTS_REQ_PKTID) { - DHD_ERROR(("Host TS req CPL, but req ID different 0x%04x, exp 0x%04x\n", - pktid, DHD_H2D_HOSTTS_REQ_PKTID)); - return; - } - dhd_timesync_handle_host_ts_complete(dhd->ts, host_ts_cpl->xt_id, - host_ts_cpl->cmplt.status); -#else /* DHD_TIMESYNC */ DHD_ERROR(("Timesunc feature not compiled in but GOT HOST_TS_COMPLETE\n")); -#endif /* DHD_TIMESYNC */ } @@ -7851,8 +7788,9 @@ void dhd_prot_clean_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info) void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info, struct bcmstrbuf *strbuf, const char * fmt) { - const char *default_fmt = "RD %d WR %d BASE(VA) %p BASE(PA) %x:%x" - " WORK ITEM SIZE %d MAX WORK ITEMS %d SIZE %d\n"; + const char *default_fmt = + "RD %d WR %d BASE(VA) %p BASE(PA) %x:%x SIZE %d " + "WORK_ITEM_SIZE %d MAX_WORK_ITEMS %d TOTAL_SIZE %d\n"; msgbuf_ring_t *flow_ring = (msgbuf_ring_t *)msgbuf_flow_info; uint16 rd, wr; uint32 dma_buf_len = flow_ring->max_items * flow_ring->item_len; @@ -7865,7 +7803,8 @@ void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info, bcm_bprintf(strbuf, fmt, rd, wr, flow_ring->dma_buf.va, ltoh32(flow_ring->base_addr.high_addr), ltoh32(flow_ring->base_addr.low_addr), - flow_ring->item_len, flow_ring->max_items, dma_buf_len); + flow_ring->item_len, flow_ring->max_items, + dma_buf_len); } void dhd_prot_print_info(dhd_pub_t *dhd, struct bcmstrbuf *strbuf) @@ -7932,23 +7871,15 @@ dhd_prot_flow_ring_delete(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) uint16 alloced = 0; msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); /* Request for ring buffer space */ flow_delete_rqst = (tx_flowring_delete_request_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (flow_delete_rqst == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DHD_ERROR(("%s: Flow Delete Req - failure ring space\n", __FUNCTION__)); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif return BCME_NOMEM; } @@ -7972,14 +7903,41 @@ dhd_prot_flow_ring_delete(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, flow_delete_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_OK; } +static void BCMFASTPATH +dhd_prot_flow_ring_fastdelete(dhd_pub_t *dhd, uint16 flowid, uint16 rd_idx) +{ + flow_ring_node_t *flow_ring_node = DHD_FLOW_RING(dhd, flowid); + msgbuf_ring_t *ring = (msgbuf_ring_t *)flow_ring_node->prot_info; + host_txbuf_cmpl_t txstatus; + host_txbuf_post_t *txdesc; + uint16 wr_idx; + + DHD_INFO(("%s: FAST delete ring, flowid=%d, rd_idx=%d, wr_idx=%d\n", + __FUNCTION__, flowid, rd_idx, ring->wr)); + + memset(&txstatus, 0, sizeof(txstatus)); + txstatus.compl_hdr.flow_ring_id = flowid; + txstatus.cmn_hdr.if_id = flow_ring_node->flow_info.ifindex; + wr_idx = ring->wr; + + while (wr_idx != rd_idx) { + if (wr_idx) + wr_idx--; + else + wr_idx = ring->max_items - 1; + txdesc = (host_txbuf_post_t *)((char *)DHD_RING_BGN_VA(ring) + + (wr_idx * ring->item_len)); + txstatus.cmn_hdr.request_id = txdesc->cmn_hdr.request_id; + dhd_prot_txstatus_process(dhd, &txstatus); + } +} + static void dhd_prot_flow_ring_delete_response_process(dhd_pub_t *dhd, void *msg) { @@ -7988,6 +7946,10 @@ dhd_prot_flow_ring_delete_response_process(dhd_pub_t *dhd, void *msg) DHD_ERROR(("%s: Flow Delete Response status = %d Flow %d\n", __FUNCTION__, flow_delete_resp->cmplt.status, flow_delete_resp->cmplt.flow_ring_id)); + if (dhd->fast_delete_ring_support) { + dhd_prot_flow_ring_fastdelete(dhd, flow_delete_resp->cmplt.flow_ring_id, + flow_delete_resp->read_idx); + } dhd_bus_flow_ring_delete_response(dhd->bus, flow_delete_resp->cmplt.flow_ring_id, flow_delete_resp->cmplt.status); } @@ -8038,22 +8000,14 @@ dhd_prot_flow_ring_flush(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) uint16 alloced = 0; msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); /* Request for ring buffer space */ flow_flush_rqst = (tx_flowring_flush_request_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (flow_flush_rqst == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DHD_ERROR(("%s: Flow Flush Req - failure ring space\n", __FUNCTION__)); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif return BCME_NOMEM; } @@ -8072,10 +8026,8 @@ dhd_prot_flow_ring_flush(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, flow_flush_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_OK; } /* dhd_prot_flow_ring_flush */ @@ -8112,22 +8064,14 @@ dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd_pub_t *dhd) msgbuf_ring_t *ctrl_ring = &prot->h2dring_ctrl_subn; const uint16 d2h_rings = BCMPCIE_D2H_COMMON_MSGRINGS; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ /* Claim space for d2h_ring number of d2h_ring_config_req_t messages */ - DHD_GENERAL_LOCK(dhd, flags); - + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); msg_start = dhd_prot_alloc_ring_space(dhd, ctrl_ring, d2h_rings, &alloced, TRUE); if (msg_start == NULL) { DHD_ERROR(("%s Msgbuf no space for %d D2H ring config soft doorbells\n", __FUNCTION__, d2h_rings)); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return; } @@ -8173,10 +8117,9 @@ dhd_msgbuf_ring_config_d2h_soft_doorbell(dhd_pub_t *dhd) /* update control subn ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ctrl_ring, msg_start, d2h_rings); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); + #endif /* DHD_D2H_SOFT_DOORBELL_SUPPORT */ } @@ -8188,72 +8131,387 @@ dhd_prot_process_d2h_ring_config_complete(dhd_pub_t *dhd, void *msg) ltoh16(((ring_config_resp_t *)msg)->compl_hdr.flow_ring_id))); } -int -dhd_prot_debug_dma_info_print(dhd_pub_t *dhd) +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT +void +copy_ext_trap_sig(dhd_pub_t *dhd, trap_t *tr) { - if (dhd->bus->is_linkdown) { - DHD_ERROR(("\n ------- SKIP DUMPING DMA Registers " - "due to PCIe link down ------- \r\n")); - return 0; + uint32 *ext_data = dhd->extended_trap_data; + hnd_ext_trap_hdr_t *hdr; + const bcm_tlv_t *tlv; + + if (ext_data == NULL) { + return; } + /* First word is original trap_data */ + ext_data++; - DHD_ERROR(("\n ------- DUMPING DMA Registers ------- \r\n")); - - //HostToDev - DHD_ERROR(("HostToDev TX: XmtCtrl=0x%08x XmtPtr=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x200, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x204, 0, 0))); - DHD_ERROR((" : XmtAddrLow=0x%08x XmtAddrHigh=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x208, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x20C, 0, 0))); - DHD_ERROR((" : XmtStatus0=0x%08x XmtStatus1=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x210, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x214, 0, 0))); - - DHD_ERROR(("HostToDev RX: RcvCtrl=0x%08x RcvPtr=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x220, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x224, 0, 0))); - DHD_ERROR((" : RcvAddrLow=0x%08x RcvAddrHigh=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x228, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x22C, 0, 0))); - DHD_ERROR((" : RcvStatus0=0x%08x RcvStatus1=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x230, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x234, 0, 0))); - - //DevToHost - DHD_ERROR(("DevToHost TX: XmtCtrl=0x%08x XmtPtr=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x240, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x244, 0, 0))); - DHD_ERROR((" : XmtAddrLow=0x%08x XmtAddrHigh=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x248, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x24C, 0, 0))); - DHD_ERROR((" : XmtStatus0=0x%08x XmtStatus1=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x250, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x254, 0, 0))); - - DHD_ERROR(("DevToHost RX: RcvCtrl=0x%08x RcvPtr=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x260, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x264, 0, 0))); - DHD_ERROR((" : RcvAddrLow=0x%08x RcvAddrHigh=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x268, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x26C, 0, 0))); - DHD_ERROR((" : RcvStatus0=0x%08x RcvStatus1=0x%08x\n", - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x270, 0, 0), - si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x274, 0, 0))); + /* Followed by the extended trap data header */ + hdr = (hnd_ext_trap_hdr_t *)ext_data; - return 0; + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_SIGNATURE); + if (tlv) { + memcpy(tr, &tlv->data, sizeof(struct _trap_struct)); + } +} +#define TRAP_T_NAME_OFFSET(var) {#var, OFFSETOF(trap_t, var)} + +typedef struct { + char name[HANG_INFO_TRAP_T_NAME_MAX]; + uint32 offset; +} hang_info_trap_t; + +static hang_info_trap_t hang_info_trap_tbl[] = { + {"reason", 0}, + {"ver", VENDOR_SEND_HANG_EXT_INFO_VER}, + {"stype", 0}, + TRAP_T_NAME_OFFSET(type), + TRAP_T_NAME_OFFSET(epc), + TRAP_T_NAME_OFFSET(cpsr), + TRAP_T_NAME_OFFSET(spsr), + TRAP_T_NAME_OFFSET(r0), + TRAP_T_NAME_OFFSET(r1), + TRAP_T_NAME_OFFSET(r2), + TRAP_T_NAME_OFFSET(r3), + TRAP_T_NAME_OFFSET(r4), + TRAP_T_NAME_OFFSET(r5), + TRAP_T_NAME_OFFSET(r6), + TRAP_T_NAME_OFFSET(r7), + TRAP_T_NAME_OFFSET(r8), + TRAP_T_NAME_OFFSET(r9), + TRAP_T_NAME_OFFSET(r10), + TRAP_T_NAME_OFFSET(r11), + TRAP_T_NAME_OFFSET(r12), + TRAP_T_NAME_OFFSET(r13), + TRAP_T_NAME_OFFSET(r14), + TRAP_T_NAME_OFFSET(pc), + {"", 0} +}; + +#define TAG_TRAP_IS_STATE(tag) \ + ((tag == TAG_TRAP_MEMORY) || (tag == TAG_TRAP_PCIE_Q) || (tag == TAG_TRAP_WLC_STATE)) + +static void +copy_hang_info_head(char *dest, trap_t *src, int len, int field_name, + int *bytes_written, int *cnt, char *cookie) +{ + uint8 *ptr; + int remain_len; + int i; + + ptr = (uint8 *)src; + + memset(dest, 0, len); + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + + /* hang reason, hang info ver */ + for (i = 0; (i < HANG_INFO_TRAP_T_SUBTYPE_IDX) && (*cnt < HANG_FIELD_CNT_MAX); + i++, (*cnt)++) { + if (field_name) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%s:%c", + hang_info_trap_tbl[i].name, HANG_KEY_DEL); + } + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%d%c", + hang_info_trap_tbl[i].offset, HANG_KEY_DEL); + + } + + if (*cnt < HANG_FIELD_CNT_MAX) { + if (field_name) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%s:%c", + "cookie", HANG_KEY_DEL); + } + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%s%c", + cookie, HANG_KEY_DEL); + (*cnt)++; + } + + if (*cnt < HANG_FIELD_CNT_MAX) { + if (field_name) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%s:%c", + hang_info_trap_tbl[HANG_INFO_TRAP_T_SUBTYPE_IDX].name, + HANG_KEY_DEL); + } + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%08x%c", + hang_info_trap_tbl[HANG_INFO_TRAP_T_SUBTYPE_IDX].offset, + HANG_KEY_DEL); + (*cnt)++; + } + + if (*cnt < HANG_FIELD_CNT_MAX) { + if (field_name) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%s:%c", + hang_info_trap_tbl[HANG_INFO_TRAP_T_EPC_IDX].name, + HANG_KEY_DEL); + } + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%08x%c", + *(uint32 *) + (ptr + hang_info_trap_tbl[HANG_INFO_TRAP_T_EPC_IDX].offset), + HANG_KEY_DEL); + (*cnt)++; + } +} + +static void +copy_hang_info_trap_t(char *dest, trap_t *src, int len, int field_name, + int *bytes_written, int *cnt, char *cookie) +{ + uint8 *ptr; + int remain_len; + int i; + + ptr = (uint8 *)src; + + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + + for (i = HANG_INFO_TRAP_T_OFFSET_IDX; + (hang_info_trap_tbl[i].name[0] != 0) && (*cnt < HANG_FIELD_CNT_MAX); + i++, (*cnt)++) { + if (field_name) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%c%s:", + HANG_RAW_DEL, hang_info_trap_tbl[i].name); + } + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%c%08x", + HANG_RAW_DEL, *(uint32 *)(ptr + hang_info_trap_tbl[i].offset)); + } +} + +static void +copy_hang_info_stack(dhd_pub_t *dhd, char *dest, int *bytes_written, int *cnt) +{ + int remain_len; + int i = 0; + const uint32 *stack; + uint32 *ext_data = dhd->extended_trap_data; + hnd_ext_trap_hdr_t *hdr; + const bcm_tlv_t *tlv; + int remain_stack_cnt = 0; + uint32 dummy_data = 0; + int bigdata_key_stack_cnt = 0; + + if (ext_data == NULL) { + return; + } + /* First word is original trap_data */ + ext_data++; + + /* Followed by the extended trap data header */ + hdr = (hnd_ext_trap_hdr_t *)ext_data; + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_STACK); + + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + + if (tlv) { + stack = (const uint32 *)tlv->data; + + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, + "%08x", *(uint32 *)(stack++)); + (*cnt)++; + if (*cnt >= HANG_FIELD_CNT_MAX) { + return; + } + for (i = 1; i < (uint32)(tlv->len / sizeof(uint32)); i++, bigdata_key_stack_cnt++) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + /* Raw data for bigdata use '_' and Key data for bigdata use space */ + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, + "%c%08x", + i <= HANG_INFO_BIGDATA_KEY_STACK_CNT ? HANG_KEY_DEL : HANG_RAW_DEL, + *(uint32 *)(stack++)); + + (*cnt)++; + if ((*cnt >= HANG_FIELD_CNT_MAX) || + (i >= HANG_FIELD_TRAP_T_STACK_CNT_MAX)) { + return; + } + } + } + + remain_stack_cnt = HANG_FIELD_TRAP_T_STACK_CNT_MAX - i; + + for (i = 0; i < remain_stack_cnt; i++) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%c%08x", + HANG_RAW_DEL, dummy_data); + (*cnt)++; + if (*cnt >= HANG_FIELD_CNT_MAX) { + return; + } + } + +} + +static void +get_hang_info_trap_subtype(dhd_pub_t *dhd, uint32 *subtype) +{ + uint32 i; + uint32 *ext_data = dhd->extended_trap_data; + hnd_ext_trap_hdr_t *hdr; + const bcm_tlv_t *tlv; + + /* First word is original trap_data */ + ext_data++; + + /* Followed by the extended trap data header */ + hdr = (hnd_ext_trap_hdr_t *)ext_data; + + /* Dump a list of all tags found before parsing data */ + for (i = TAG_TRAP_DEEPSLEEP; i < TAG_TRAP_LAST; i++) { + tlv = bcm_parse_tlvs(hdr->data, hdr->len, i); + if (tlv) { + if (!TAG_TRAP_IS_STATE(i)) { + *subtype = i; + return; + } + } + } } +static void +copy_hang_info_specific(dhd_pub_t *dhd, char *dest, int *bytes_written, int *cnt) +{ + int remain_len; + int i; + const uint32 *data; + uint32 *ext_data = dhd->extended_trap_data; + hnd_ext_trap_hdr_t *hdr; + const bcm_tlv_t *tlv; + int remain_trap_data = 0; + uint8 buf_u8[sizeof(uint32)] = { 0, }; + const uint8 *p_u8; + + if (ext_data == NULL) { + return; + } + /* First word is original trap_data */ + ext_data++; + + /* Followed by the extended trap data header */ + hdr = (hnd_ext_trap_hdr_t *)ext_data; + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_SIGNATURE); + if (tlv) { + /* header include tlv hader */ + remain_trap_data = (hdr->len - tlv->len - sizeof(uint16)); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_STACK); + if (tlv) { + /* header include tlv hader */ + remain_trap_data -= (tlv->len + sizeof(uint16)); + } + + data = (const uint32 *)(hdr->data + (hdr->len - remain_trap_data)); + + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + + for (i = 0; i < (uint32)(remain_trap_data / sizeof(uint32)) && *cnt < HANG_FIELD_CNT_MAX; + i++, (*cnt)++) { + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%c%08x", + HANG_RAW_DEL, *(uint32 *)(data++)); + } + + if (*cnt >= HANG_FIELD_CNT_MAX) { + return; + } + + remain_trap_data -= (sizeof(uint32) * i); + + if (remain_trap_data > sizeof(buf_u8)) { + DHD_ERROR(("%s: resize remain_trap_data\n", __FUNCTION__)); + remain_trap_data = sizeof(buf_u8); + } + + if (remain_trap_data) { + p_u8 = (const uint8 *)data; + for (i = 0; i < remain_trap_data; i++) { + buf_u8[i] = *(const uint8 *)(p_u8++); + } + + remain_len = VENDOR_SEND_HANG_EXT_INFO_LEN - *bytes_written; + *bytes_written += scnprintf(&dest[*bytes_written], remain_len, "%c%08x", + HANG_RAW_DEL, ltoh32_ua(buf_u8)); + (*cnt)++; + } +} + +void +copy_hang_info_trap(dhd_pub_t *dhd) +{ + trap_t tr; + int bytes_written; + int trap_subtype = 0; + + if (!dhd || !dhd->hang_info) { + DHD_ERROR(("%s dhd=%p hang_info=%p\n", __FUNCTION__, + dhd, (dhd ? dhd->hang_info : NULL))); + return; + } + + if (!dhd->dongle_trap_occured) { + DHD_ERROR(("%s: dongle_trap_occured is FALSE\n", __FUNCTION__)); + return; + } + + memset(&tr, 0x00, sizeof(struct _trap_struct)); + + copy_ext_trap_sig(dhd, &tr); + get_hang_info_trap_subtype(dhd, &trap_subtype); + + hang_info_trap_tbl[HANG_INFO_TRAP_T_REASON_IDX].offset = HANG_REASON_DONGLE_TRAP; + hang_info_trap_tbl[HANG_INFO_TRAP_T_SUBTYPE_IDX].offset = trap_subtype; + + bytes_written = 0; + dhd->hang_info_cnt = 0; + get_debug_dump_time(dhd->debug_dump_time_hang_str); + copy_debug_dump_time(dhd->debug_dump_time_str, dhd->debug_dump_time_hang_str); + + copy_hang_info_head(dhd->hang_info, &tr, VENDOR_SEND_HANG_EXT_INFO_LEN, FALSE, + &bytes_written, &dhd->hang_info_cnt, dhd->debug_dump_time_hang_str); + + DHD_INFO(("hang info haed cnt: %d len: %d data: %s\n", + dhd->hang_info_cnt, (int)strlen(dhd->hang_info), dhd->hang_info)); + + clear_debug_dump_time(dhd->debug_dump_time_hang_str); + + if (dhd->hang_info_cnt < HANG_FIELD_CNT_MAX) { + copy_hang_info_stack(dhd, dhd->hang_info, &bytes_written, &dhd->hang_info_cnt); + DHD_INFO(("hang info stack cnt: %d len: %d data: %s\n", + dhd->hang_info_cnt, (int)strlen(dhd->hang_info), dhd->hang_info)); + } + + if (dhd->hang_info_cnt < HANG_FIELD_CNT_MAX) { + copy_hang_info_trap_t(dhd->hang_info, &tr, VENDOR_SEND_HANG_EXT_INFO_LEN, FALSE, + &bytes_written, &dhd->hang_info_cnt, dhd->debug_dump_time_hang_str); + DHD_INFO(("hang info trap_t cnt: %d len: %d data: %s\n", + dhd->hang_info_cnt, (int)strlen(dhd->hang_info), dhd->hang_info)); + } + + if (dhd->hang_info_cnt < HANG_FIELD_CNT_MAX) { + copy_hang_info_specific(dhd, dhd->hang_info, &bytes_written, &dhd->hang_info_cnt); + DHD_INFO(("hang info specific cnt: %d len: %d data: %s\n", + dhd->hang_info_cnt, (int)strlen(dhd->hang_info), dhd->hang_info)); + } + +} +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ + int dhd_prot_debug_info_print(dhd_pub_t *dhd) { dhd_prot_t *prot = dhd->prot; msgbuf_ring_t *ring; uint16 rd, wr; - uint32 intstatus = 0; - uint32 intmask = 0; - uint32 mbintstatus = 0; - uint32 d2h_mb_data = 0; uint32 dma_buf_len; DHD_ERROR(("\n ------- DUMPING VERSION INFORMATION ------- \r\n")); @@ -8265,6 +8523,8 @@ dhd_prot_debug_info_print(dhd_pub_t *dhd) prot->device_ipc_version, prot->host_ipc_version, prot->active_ipc_version)); + DHD_ERROR(("d2h_intr_method -> %s\n", + dhd->bus->d2h_intr_method ? "PCIE_MSI" : "PCIE_INTX")); DHD_ERROR(("max Host TS bufs to post: %d, posted %d\n", prot->max_tsbufpost, prot->cur_ts_bufs_posted)); DHD_ERROR(("max INFO bufs to post: %d, posted %d\n", @@ -8324,84 +8584,40 @@ dhd_prot_debug_info_print(dhd_pub_t *dhd) dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, ring->idx); dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, ring->idx); DHD_ERROR(("InfoCpl: From Shared Mem: RD: %d WR %d \r\n", rd, wr)); - DHD_ERROR(("InfoCpl: Expected seq num: %d \r\n", ring->seqnum % H2D_EPOCH_MODULO)); + DHD_ERROR(("InfoCpl: Expected seq num: %d \r\n", ring->seqnum % D2H_EPOCH_MODULO)); + } + + ring = &prot->d2hring_tx_cpln; + if (ring) { + dma_buf_len = ring->max_items * ring->item_len; + DHD_ERROR(("TxCpl: Mem Info: BASE(VA) %p BASE(PA) %x:%x SIZE %d \r\n", + ring->dma_buf.va, ltoh32(ring->base_addr.high_addr), + ltoh32(ring->base_addr.low_addr), dma_buf_len)); + DHD_ERROR(("TxCpl: From Host mem: RD: %d WR %d \r\n", ring->rd, ring->wr)); + dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, ring->idx); + dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, ring->idx); + DHD_ERROR(("TxCpl: From Shared Mem: RD: %d WR %d \r\n", rd, wr)); + DHD_ERROR(("TxCpl: Expected seq num: %d \r\n", ring->seqnum % D2H_EPOCH_MODULO)); + } + + ring = &prot->d2hring_rx_cpln; + if (ring) { + dma_buf_len = ring->max_items * ring->item_len; + DHD_ERROR(("RxCpl: Mem Info: BASE(VA) %p BASE(PA) %x:%x SIZE %d \r\n", + ring->dma_buf.va, ltoh32(ring->base_addr.high_addr), + ltoh32(ring->base_addr.low_addr), dma_buf_len)); + DHD_ERROR(("RxCpl: From Host mem: RD: %d WR %d \r\n", ring->rd, ring->wr)); + dhd_bus_cmn_readshared(dhd->bus, &rd, RING_RD_UPD, ring->idx); + dhd_bus_cmn_readshared(dhd->bus, &wr, RING_WR_UPD, ring->idx); + DHD_ERROR(("RxCpl: From Shared Mem: RD: %d WR %d \r\n", rd, wr)); + DHD_ERROR(("RxCpl: Expected seq num: %d \r\n", ring->seqnum % D2H_EPOCH_MODULO)); } DHD_ERROR(("%s: cur_ioctlresp_bufs_posted %d cur_event_bufs_posted %d\n", __FUNCTION__, prot->cur_ioctlresp_bufs_posted, prot->cur_event_bufs_posted)); - if (!dhd->bus->is_linkdown && dhd->bus->intstatus != (uint32)-1) { - DHD_ERROR(("\n ------- DUMPING INTR Status and Masks ------- \r\n")); - intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, - PCIMailBoxInt, 0, 0); - intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, - PCIMailBoxMask, 0, 0); - mbintstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, - PCID2H_MailBox, 0, 0); - dhd_bus_cmn_readshared(dhd->bus, &d2h_mb_data, D2H_MB_DATA, 0); - - DHD_ERROR(("intstatus=0x%x intmask=0x%x mbintstatus=0x%x\n", - intstatus, intmask, mbintstatus)); - DHD_ERROR(("d2h_mb_data=0x%x def_intmask=0x%x \r\n", d2h_mb_data, - dhd->bus->def_intmask)); - - DHD_ERROR(("host pcie_irq enabled = %d\n", dhdpcie_irq_enabled(dhd->bus))); - - DHD_ERROR(("\n ------- DUMPING PCIE Registers ------- \r\n")); - /* hwnbu-twiki.sj.broadcom.com/bin/view/Mwgroup/CurrentPcieGen2ProgramGuide */ - DHD_ERROR(("Status Command(0x%x)=0x%x, BaseAddress0(0x%x)=0x%x\n", - PCIECFGREG_STATUS_CMD, - dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_STATUS_CMD, sizeof(uint32)), - PCIECFGREG_BASEADDR0, - dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_BASEADDR0, sizeof(uint32)))); - DHD_ERROR(("LinkCtl(0x%x)=0x%x DeviceStatusControl2(0x%x)=0x%x " - "L1SSControl(0x%x)=0x%x\n", PCIECFGREG_LINK_STATUS_CTRL, - dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_LINK_STATUS_CTRL, - sizeof(uint32)), PCIECFGGEN_DEV_STATUS_CTRL2, - dhd_pcie_config_read(dhd->bus->osh, PCIECFGGEN_DEV_STATUS_CTRL2, - sizeof(uint32)), PCIECFGREG_PML1_SUB_CTRL1, - dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_PML1_SUB_CTRL1, - sizeof(uint32)))); - - /* hwnbu-twiki.sj.broadcom.com/twiki/pub/Mwgroup/ - * CurrentPcieGen2ProgramGuide/pcie_ep.htm - */ - DHD_ERROR(("ClkReq0(0x%x)=0x%x ClkReq1(0x%x)=0x%x ClkReq2(0x%x)=0x%x " - "ClkReq3(0x%x)=0x%x\n", PCIECFGREG_PHY_DBG_CLKREQ0, - dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ0), - PCIECFGREG_PHY_DBG_CLKREQ1, - dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ1), - PCIECFGREG_PHY_DBG_CLKREQ2, - dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ2), - PCIECFGREG_PHY_DBG_CLKREQ3, - dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ3))); - - DHD_ERROR(("Pcie RC Error Status Val=0x%x\n", - dhdpcie_rc_access_cap(dhd->bus, PCIE_EXTCAP_ID_ERR, - PCIE_EXTCAP_AER_UCERR_OFFSET, TRUE, FALSE, 0))); - - DHD_ERROR(("RootPort PCIe linkcap=0x%08x\n", - dhd_debug_get_rc_linkcap(dhd->bus))); - - DHD_ERROR(("\n ------- DUMPING INTR enable/disable counters ------- \r\n")); - DHD_ERROR(("resume_intr_enable_count=%lu dpc_intr_enable_count=%lu\n" - "isr_intr_disable_count=%lu suspend_intr_disable_count=%lu\n" - "dpc_return_busdown_count=%lu\n", - dhd->bus->resume_intr_enable_count, dhd->bus->dpc_intr_enable_count, - dhd->bus->isr_intr_disable_count, dhd->bus->suspend_intr_disable_count, - dhd->bus->dpc_return_busdown_count)); - - } - dhd_prot_debug_dma_info_print(dhd); -#ifdef DHD_FW_COREDUMP - if (dhd->memdump_enabled) { -#ifdef DHD_SSSR_DUMP - if (dhd->sssr_inited) { - dhdpcie_sssr_dump(dhd); - } -#endif /* DHD_SSSR_DUMP */ - } -#endif /* DHD_FW_COREDUMP */ + dhd_pcie_debug_info_dump(dhd); + return 0; } @@ -8459,7 +8675,7 @@ dhd_prot_metadata_dbg_set(dhd_pub_t *dhd, bool val) dhd_prot_t *prot = dhd->prot; #if DHD_DBG_SHOW_METADATA prot->metadata_dbg = val; -#endif +#endif // endif return (uint32)prot->metadata_dbg; } @@ -8585,7 +8801,6 @@ dhd_rxchain_commit(dhd_pub_t *dhd) #endif /* DHD_RX_CHAINING */ - #ifdef IDLE_TX_FLOW_MGMT int dhd_prot_flow_ring_resume(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) @@ -8604,12 +8819,8 @@ dhd_prot_flow_ring_resume(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) __FUNCTION__, flow_ring_node->flowid)); return BCME_NOMEM; } -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); /* Request for ctrl_ring buffer space */ flow_resume_rqst = (tx_idle_flowring_resume_request_t *) @@ -8619,10 +8830,7 @@ dhd_prot_flow_ring_resume(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) dhd_prot_flowrings_pool_release(dhd, flow_ring_node->flowid, flow_ring); DHD_ERROR(("%s: Flow resume Req flowid %d - failure ring space\n", __FUNCTION__, flow_ring_node->flowid)); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return BCME_NOMEM; } @@ -8656,10 +8864,7 @@ dhd_prot_flow_ring_resume(dhd_pub_t *dhd, flow_ring_node_t *flow_ring_node) /* update control subn ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ctrl_ring, flow_resume_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return BCME_OK; } /* dhd_prot_flow_ring_create */ @@ -8674,23 +8879,15 @@ dhd_prot_flow_ring_batch_suspend_request(dhd_pub_t *dhd, uint16 *ringid, uint16 uint16 alloced = 0; msgbuf_ring_t *ring = &prot->h2dring_ctrl_subn; -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhd->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - - DHD_GENERAL_LOCK(dhd, flags); + DHD_RING_LOCK(ring->ring_lock, flags); /* Request for ring buffer space */ flow_suspend_rqst = (tx_idle_flowring_suspend_request_t *) dhd_prot_alloc_ring_space(dhd, ring, 1, &alloced, FALSE); if (flow_suspend_rqst == NULL) { - DHD_GENERAL_UNLOCK(dhd, flags); + DHD_RING_UNLOCK(ring->ring_lock, flags); DHD_ERROR(("%s: Flow suspend Req - failure ring space\n", __FUNCTION__)); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif return BCME_NOMEM; } @@ -8713,25 +8910,45 @@ dhd_prot_flow_ring_batch_suspend_request(dhd_pub_t *dhd, uint16 *ringid, uint16 /* update ring's WR index and ring doorbell to dongle */ dhd_prot_ring_write_complete(dhd, ring, flow_suspend_rqst, 1); - DHD_GENERAL_UNLOCK(dhd, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhd->bus); -#endif + + DHD_RING_UNLOCK(ring->ring_lock, flags); return BCME_OK; } #endif /* IDLE_TX_FLOW_MGMT */ +static const char* etd_trap_name(hnd_ext_tag_trap_t tag) +{ + switch (tag) + { + case TAG_TRAP_SIGNATURE: return "TAG_TRAP_SIGNATURE"; + case TAG_TRAP_STACK: return "TAG_TRAP_STACK"; + case TAG_TRAP_MEMORY: return "TAG_TRAP_MEMORY"; + case TAG_TRAP_DEEPSLEEP: return "TAG_TRAP_DEEPSLEEP"; + case TAG_TRAP_PSM_WD: return "TAG_TRAP_PSM_WD"; + case TAG_TRAP_PHY: return "TAG_TRAP_PHY"; + case TAG_TRAP_BUS: return "TAG_TRAP_BUS"; + case TAG_TRAP_MAC_SUSP: return "TAG_TRAP_MAC_SUSP"; + case TAG_TRAP_BACKPLANE: return "TAG_TRAP_BACKPLANE"; + case TAG_TRAP_PCIE_Q: return "TAG_TRAP_PCIE_Q"; + case TAG_TRAP_WLC_STATE: return "TAG_TRAP_WLC_STATE"; + case TAG_TRAP_MAC_WAKE: return "TAG_TRAP_MAC_WAKE"; + case TAG_TRAP_LAST: + default: + return "Unknown"; + } + return "Unknown"; +} int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) { uint32 i; uint32 *ext_data; hnd_ext_trap_hdr_t *hdr; - bcm_tlv_t *tlv; - trap_t *tr; - uint32 *stack; - hnd_ext_trap_bp_err_t *bpe; + const bcm_tlv_t *tlv; + const trap_t *tr; + const uint32 *stack; + const hnd_ext_trap_bp_err_t *bpe; uint32 raw_len; ext_data = dhdp->extended_trap_data; @@ -8753,6 +8970,14 @@ int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) hdr = (hnd_ext_trap_hdr_t *)ext_data; bcm_bprintf(b, "version: %d, len: %d\n", hdr->version, hdr->len); + /* Dump a list of all tags found before parsing data */ + bcm_bprintf(b, "\nTags Found:\n"); + for (i = 0; i < TAG_TRAP_LAST; i++) { + tlv = bcm_parse_tlvs(hdr->data, hdr->len, i); + if (tlv) + bcm_bprintf(b, "Tag: %d (%s), Length: %d\n", i, etd_trap_name(i), tlv->len); + } + if (raw) { raw_len = sizeof(hnd_ext_trap_hdr_t) + (hdr->len / 4) + (hdr->len % 4 ? 1 : 0); @@ -8769,8 +8994,8 @@ int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_SIGNATURE); if (tlv) { - bcm_bprintf(b, "\nTAG_TRAP_SIGNATURE len: %d\n", tlv->len); - tr = (trap_t *)tlv->data; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_SIGNATURE), tlv->len); + tr = (const trap_t *)tlv->data; bcm_bprintf(b, "TRAP %x: pc %x, lr %x, sp %x, cpsr %x, spsr %x\n", tr->type, tr->pc, tr->r14, tr->r13, tr->cpsr, tr->spsr); @@ -8783,8 +9008,8 @@ int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_STACK); if (tlv) { - bcm_bprintf(b, "\nTAG_TRAP_STACK len: %d\n", tlv->len); - stack = (uint32 *)tlv->data; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_STACK), tlv->len); + stack = (const uint32 *)tlv->data; for (i = 0; i < (uint32)(tlv->len / 4); i++) { bcm_bprintf(b, " 0x%08x\n", *stack); @@ -8795,8 +9020,8 @@ int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_BACKPLANE); if (tlv) { - bcm_bprintf(b, "\nTAG_TRAP_BACKPLANE len: %d\n", tlv->len); - bpe = (hnd_ext_trap_bp_err_t *)tlv->data; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_BACKPLANE), tlv->len); + bpe = (const hnd_ext_trap_bp_err_t *)tlv->data; bcm_bprintf(b, " error: %x\n", bpe->error); bcm_bprintf(b, " coreid: %x\n", bpe->coreid); bcm_bprintf(b, " baseaddr: %x\n", bpe->baseaddr); @@ -8814,10 +9039,230 @@ int dhd_prot_dump_extended_trap(dhd_pub_t *dhdp, struct bcmstrbuf *b, bool raw) bcm_bprintf(b, " errlogflags: %x\n", bpe->errlogflags); } + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_MEMORY); + if (tlv) + { + const hnd_ext_trap_heap_err_t* hme; + + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_MEMORY), tlv->len); + hme = (const hnd_ext_trap_heap_err_t *)tlv->data; + bcm_bprintf(b, " arena total: %d\n", hme->arena_total); + bcm_bprintf(b, " heap free: %d\n", hme->heap_free); + bcm_bprintf(b, " heap in use: %d\n", hme->heap_inuse); + bcm_bprintf(b, " mf count: %d\n", hme->mf_count); + bcm_bprintf(b, " stack LWM: %x\n", hme->stack_lwm); + + bcm_bprintf(b, " Histogram:\n"); + for (i = 0; i < (HEAP_HISTOGRAM_DUMP_LEN * 2); i += 2) { + if (hme->heap_histogm[i] == 0xfffe) + bcm_bprintf(b, " Others\t%d\t?\n", hme->heap_histogm[i + 1]); + else if (hme->heap_histogm[i] == 0xffff) + bcm_bprintf(b, " >= 256K\t%d\t?\n", hme->heap_histogm[i + 1]); + else + bcm_bprintf(b, " %d\t%d\t%d\n", hme->heap_histogm[i] << 2, + hme->heap_histogm[i + 1], (hme->heap_histogm[i] << 2) + * hme->heap_histogm[i + 1]); + } + + bcm_bprintf(b, " Max free block: %d\n", hme->max_sz_free_blk[0] << 2); + for (i = 1; i < HEAP_MAX_SZ_BLKS_LEN; i++) { + bcm_bprintf(b, " Next lgst free block: %d\n", hme->max_sz_free_blk[i] << 2); + } + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_PCIE_Q); + if (tlv) + { + const hnd_ext_trap_pcie_mem_err_t* pqme; + + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_PCIE_Q), tlv->len); + pqme = (const hnd_ext_trap_pcie_mem_err_t *)tlv->data; + bcm_bprintf(b, " d2h queue len: %x\n", pqme->d2h_queue_len); + bcm_bprintf(b, " d2h req queue len: %x\n", pqme->d2h_req_queue_len); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_WLC_STATE); + if (tlv) + { + const hnd_ext_trap_wlc_mem_err_t* wsme; + + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_WLC_STATE), tlv->len); + wsme = (const hnd_ext_trap_wlc_mem_err_t *)tlv->data; + bcm_bprintf(b, " instance: %d\n", wsme->instance); + bcm_bprintf(b, " associated: %d\n", wsme->associated); + bcm_bprintf(b, " peer count: %d\n", wsme->peer_cnt); + bcm_bprintf(b, " client count: %d\n", wsme->soft_ap_client_cnt); + bcm_bprintf(b, " TX_AC_BK_FIFO: %d\n", wsme->txqueue_len[0]); + bcm_bprintf(b, " TX_AC_BE_FIFO: %d\n", wsme->txqueue_len[1]); + bcm_bprintf(b, " TX_AC_VI_FIFO: %d\n", wsme->txqueue_len[2]); + bcm_bprintf(b, " TX_AC_VO_FIFO: %d\n", wsme->txqueue_len[3]); + + if (tlv->len >= (sizeof(*wsme) * 2)) { + wsme++; + bcm_bprintf(b, "\n instance: %d\n", wsme->instance); + bcm_bprintf(b, " associated: %d\n", wsme->associated); + bcm_bprintf(b, " peer count: %d\n", wsme->peer_cnt); + bcm_bprintf(b, " client count: %d\n", wsme->soft_ap_client_cnt); + bcm_bprintf(b, " TX_AC_BK_FIFO: %d\n", wsme->txqueue_len[0]); + bcm_bprintf(b, " TX_AC_BE_FIFO: %d\n", wsme->txqueue_len[1]); + bcm_bprintf(b, " TX_AC_VI_FIFO: %d\n", wsme->txqueue_len[2]); + bcm_bprintf(b, " TX_AC_VO_FIFO: %d\n", wsme->txqueue_len[3]); + } + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_PHY); + if (tlv) + { + const hnd_ext_trap_phydbg_t* phydbg; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_PHY), tlv->len); + phydbg = (const hnd_ext_trap_phydbg_t *)tlv->data; + bcm_bprintf(b, " err: 0x%x\n", phydbg->err); + bcm_bprintf(b, " RxFeStatus: 0x%x\n", phydbg->RxFeStatus); + bcm_bprintf(b, " TxFIFOStatus0: 0x%x\n", phydbg->TxFIFOStatus0); + bcm_bprintf(b, " TxFIFOStatus1: 0x%x\n", phydbg->TxFIFOStatus1); + bcm_bprintf(b, " RfseqMode: 0x%x\n", phydbg->RfseqMode); + bcm_bprintf(b, " RfseqStatus0: 0x%x\n", phydbg->RfseqStatus0); + bcm_bprintf(b, " RfseqStatus1: 0x%x\n", phydbg->RfseqStatus1); + bcm_bprintf(b, " RfseqStatus_Ocl: 0x%x\n", phydbg->RfseqStatus_Ocl); + bcm_bprintf(b, " RfseqStatus_Ocl1: 0x%x\n", phydbg->RfseqStatus_Ocl1); + bcm_bprintf(b, " OCLControl1: 0x%x\n", phydbg->OCLControl1); + bcm_bprintf(b, " TxError: 0x%x\n", phydbg->TxError); + bcm_bprintf(b, " bphyTxError: 0x%x\n", phydbg->bphyTxError); + bcm_bprintf(b, " TxCCKError: 0x%x\n", phydbg->TxCCKError); + bcm_bprintf(b, " TxCtrlWrd0: 0x%x\n", phydbg->TxCtrlWrd0); + bcm_bprintf(b, " TxCtrlWrd1: 0x%x\n", phydbg->TxCtrlWrd1); + bcm_bprintf(b, " TxCtrlWrd2: 0x%x\n", phydbg->TxCtrlWrd2); + bcm_bprintf(b, " TxLsig0: 0x%x\n", phydbg->TxLsig0); + bcm_bprintf(b, " TxLsig1: 0x%x\n", phydbg->TxLsig1); + bcm_bprintf(b, " TxVhtSigA10: 0x%x\n", phydbg->TxVhtSigA10); + bcm_bprintf(b, " TxVhtSigA11: 0x%x\n", phydbg->TxVhtSigA11); + bcm_bprintf(b, " TxVhtSigA20: 0x%x\n", phydbg->TxVhtSigA20); + bcm_bprintf(b, " TxVhtSigA21: 0x%x\n", phydbg->TxVhtSigA21); + bcm_bprintf(b, " txPktLength: 0x%x\n", phydbg->txPktLength); + bcm_bprintf(b, " txPsdulengthCtr: 0x%x\n", phydbg->txPsdulengthCtr); + bcm_bprintf(b, " gpioClkControl: 0x%x\n", phydbg->gpioClkControl); + bcm_bprintf(b, " gpioSel: 0x%x\n", phydbg->gpioSel); + bcm_bprintf(b, " pktprocdebug: 0x%x\n", phydbg->pktprocdebug); + for (i = 0; i < 3; i++) + bcm_bprintf(b, " gpioOut[%d]: 0x%x\n", i, phydbg->gpioOut[i]); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_PSM_WD); + if (tlv) + { + const hnd_ext_trap_psmwd_t* psmwd; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_PSM_WD), tlv->len); + psmwd = (const hnd_ext_trap_psmwd_t *)tlv; + bcm_bprintf(b, " version: 0x%x\n", psmwd->version); + bcm_bprintf(b, " maccontrol: 0x%x\n", psmwd->i32_maccontrol); + bcm_bprintf(b, " maccommand: 0x%x\n", psmwd->i32_maccommand); + bcm_bprintf(b, " macintstatus: 0x%x\n", psmwd->i32_macintstatus); + bcm_bprintf(b, " phydebug: 0x%x\n", psmwd->i32_phydebug); + bcm_bprintf(b, " clk_ctl_st: 0x%x\n", psmwd->i32_clk_ctl_st); + for (i = 0; i < 3; i++) + bcm_bprintf(b, " psmdebug[%d]: 0x%x\n", i, psmwd->i32_psmdebug[i]); + bcm_bprintf(b, " gated clock en: 0x%x\n", psmwd->i16_0x1a8); + bcm_bprintf(b, " Rcv Fifo Ctrl: 0x%x\n", psmwd->i16_0x406); + bcm_bprintf(b, " Rx ctrl 1: 0x%x\n", psmwd->i16_0x408); + bcm_bprintf(b, " Rxe Status 1: 0x%x\n", psmwd->i16_0x41a); + bcm_bprintf(b, " Rxe Status 2: 0x%x\n", psmwd->i16_0x41c); + bcm_bprintf(b, " rcv wrd count 0: 0x%x\n", psmwd->i16_0x424); + bcm_bprintf(b, " rcv wrd count 1: 0x%x\n", psmwd->i16_0x426); + bcm_bprintf(b, " RCV_LFIFO_STS: 0x%x\n", psmwd->i16_0x456); + bcm_bprintf(b, " PSM_SLP_TMR: 0x%x\n", psmwd->i16_0x480); + bcm_bprintf(b, " PSM BRC: 0x%x\n", psmwd->i16_0x490); + bcm_bprintf(b, " TXE CTRL: 0x%x\n", psmwd->i16_0x500); + bcm_bprintf(b, " TXE Status: 0x%x\n", psmwd->i16_0x50e); + bcm_bprintf(b, " TXE_xmtdmabusy: 0x%x\n", psmwd->i16_0x55e); + bcm_bprintf(b, " TXE_XMTfifosuspflush: 0x%x\n", psmwd->i16_0x566); + bcm_bprintf(b, " IFS Stat: 0x%x\n", psmwd->i16_0x690); + bcm_bprintf(b, " IFS_MEDBUSY_CTR: 0x%x\n", psmwd->i16_0x692); + bcm_bprintf(b, " IFS_TX_DUR: 0x%x\n", psmwd->i16_0x694); + bcm_bprintf(b, " SLow_CTL: 0x%x\n", psmwd->i16_0x6a0); + bcm_bprintf(b, " TXE_AQM fifo Ready: 0x%x\n", psmwd->i16_0x838); + bcm_bprintf(b, " Dagg ctrl: 0x%x\n", psmwd->i16_0x8c0); + bcm_bprintf(b, " shm_prewds_cnt: 0x%x\n", psmwd->shm_prewds_cnt); + bcm_bprintf(b, " shm_txtplufl_cnt: 0x%x\n", psmwd->shm_txtplufl_cnt); + bcm_bprintf(b, " shm_txphyerr_cnt: 0x%x\n", psmwd->shm_txphyerr_cnt); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_MAC_SUSP); + if (tlv) + { + const hnd_ext_trap_macsusp_t* macsusp; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_MAC_SUSP), tlv->len); + macsusp = (const hnd_ext_trap_macsusp_t *)tlv; + bcm_bprintf(b, " version: %d\n", macsusp->version); + bcm_bprintf(b, " trap_reason: %d\n", macsusp->trap_reason); + bcm_bprintf(b, " maccontrol: 0x%x\n", macsusp->i32_maccontrol); + bcm_bprintf(b, " maccommand: 0x%x\n", macsusp->i32_maccommand); + bcm_bprintf(b, " macintstatus: 0x%x\n", macsusp->i32_macintstatus); + for (i = 0; i < 4; i++) + bcm_bprintf(b, " phydebug[%d]: 0x%x\n", i, macsusp->i32_phydebug[i]); + for (i = 0; i < 8; i++) + bcm_bprintf(b, " psmdebug[%d]: 0x%x\n", i, macsusp->i32_psmdebug[i]); + bcm_bprintf(b, " Rxe Status_1: 0x%x\n", macsusp->i16_0x41a); + bcm_bprintf(b, " Rxe Status_2: 0x%x\n", macsusp->i16_0x41c); + bcm_bprintf(b, " PSM BRC: 0x%x\n", macsusp->i16_0x490); + bcm_bprintf(b, " TXE Status: 0x%x\n", macsusp->i16_0x50e); + bcm_bprintf(b, " TXE xmtdmabusy: 0x%x\n", macsusp->i16_0x55e); + bcm_bprintf(b, " TXE XMTfifosuspflush: 0x%x\n", macsusp->i16_0x566); + bcm_bprintf(b, " IFS Stat: 0x%x\n", macsusp->i16_0x690); + bcm_bprintf(b, " IFS MEDBUSY CTR: 0x%x\n", macsusp->i16_0x692); + bcm_bprintf(b, " IFS TX DUR: 0x%x\n", macsusp->i16_0x694); + bcm_bprintf(b, " WEP CTL: 0x%x\n", macsusp->i16_0x7c0); + bcm_bprintf(b, " TXE AQM fifo Ready: 0x%x\n", macsusp->i16_0x838); + bcm_bprintf(b, " MHP status: 0x%x\n", macsusp->i16_0x880); + bcm_bprintf(b, " shm_prewds_cnt: 0x%x\n", macsusp->shm_prewds_cnt); + bcm_bprintf(b, " shm_ucode_dbgst: 0x%x\n", macsusp->shm_ucode_dbgst); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_MAC_WAKE); + if (tlv) + { + const hnd_ext_trap_macenab_t* macwake; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_MAC_WAKE), tlv->len); + macwake = (const hnd_ext_trap_macenab_t *)tlv; + bcm_bprintf(b, " version: 0x%x\n", macwake->version); + bcm_bprintf(b, " trap_reason: 0x%x\n", macwake->trap_reason); + bcm_bprintf(b, " maccontrol: 0x%x\n", macwake->i32_maccontrol); + bcm_bprintf(b, " maccommand: 0x%x\n", macwake->i32_maccommand); + bcm_bprintf(b, " macintstatus: 0x%x\n", macwake->i32_macintstatus); + for (i = 0; i < 8; i++) + bcm_bprintf(b, " psmdebug[%d]: 0x%x\n", i, macwake->i32_psmdebug[i]); + bcm_bprintf(b, " clk_ctl_st: 0x%x\n", macwake->i32_clk_ctl_st); + bcm_bprintf(b, " powerctl: 0x%x\n", macwake->i32_powerctl); + bcm_bprintf(b, " gated clock en: 0x%x\n", macwake->i16_0x1a8); + bcm_bprintf(b, " PSM_SLP_TMR: 0x%x\n", macwake->i16_0x480); + bcm_bprintf(b, " PSM BRC: 0x%x\n", macwake->i16_0x490); + bcm_bprintf(b, " TSF CTL: 0x%x\n", macwake->i16_0x600); + bcm_bprintf(b, " IFS Stat: 0x%x\n", macwake->i16_0x690); + bcm_bprintf(b, " IFS_MEDBUSY_CTR: 0x%x\n", macwake->i16_0x692); + bcm_bprintf(b, " Slow_CTL: 0x%x\n", macwake->i16_0x6a0); + bcm_bprintf(b, " Slow_FRAC: 0x%x\n", macwake->i16_0x6a6); + bcm_bprintf(b, " fast power up delay: 0x%x\n", macwake->i16_0x6a8); + bcm_bprintf(b, " Slow_PER: 0x%x\n", macwake->i16_0x6aa); + bcm_bprintf(b, " shm_ucode_dbgst: 0x%x\n", macwake->shm_ucode_dbgst); + } + + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_BUS); + if (tlv) + { + const bcm_dngl_pcie_hc_t* hc; + bcm_bprintf(b, "\n%s len: %d\n", etd_trap_name(TAG_TRAP_BUS), tlv->len); + hc = (const bcm_dngl_pcie_hc_t *)tlv->data; + bcm_bprintf(b, " version: 0x%x\n", hc->version); + bcm_bprintf(b, " reserved: 0x%x\n", hc->reserved); + bcm_bprintf(b, " pcie_err_ind_type: 0x%x\n", hc->pcie_err_ind_type); + bcm_bprintf(b, " pcie_flag: 0x%x\n", hc->pcie_flag); + bcm_bprintf(b, " pcie_control_reg: 0x%x\n", hc->pcie_control_reg); + for (i = 0; i < HC_PCIEDEV_CONFIG_REGLIST_MAX; i++) + bcm_bprintf(b, " pcie_config_regs[%d]: 0x%x\n", i, hc->pcie_config_regs[i]); + } + return BCME_OK; } - #ifdef BCMPCIE int dhd_prot_send_host_timestamp(dhd_pub_t *dhdp, uchar *tlvs, uint16 tlv_len, @@ -8828,49 +9273,40 @@ dhd_prot_send_host_timestamp(dhd_pub_t *dhdp, uchar *tlvs, uint16 tlv_len, unsigned long flags; uint16 alloced = 0; uchar *ts_tlv_buf; + msgbuf_ring_t *ctrl_ring = &prot->h2dring_ctrl_subn; if ((tlvs == NULL) || (tlv_len == 0)) { DHD_ERROR(("%s: argument error tlv: %p, tlv_len %d\n", __FUNCTION__, tlvs, tlv_len)); return -1; } -#ifdef PCIE_INB_DW - if (dhd_prot_inc_hostactive_devwake_assert(dhdp->bus) != BCME_OK) - return BCME_ERROR; -#endif /* PCIE_INB_DW */ - DHD_GENERAL_LOCK(dhdp, flags); + DHD_RING_LOCK(ctrl_ring->ring_lock, flags); /* if Host TS req already pending go away */ if (prot->hostts_req_buf_inuse == TRUE) { DHD_ERROR(("one host TS request already pending at device\n")); - DHD_GENERAL_UNLOCK(dhdp, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhdp->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return -1; } /* Request for cbuf space */ - ts_req = (host_timestamp_msg_t*)dhd_prot_alloc_ring_space(dhdp, &prot->h2dring_ctrl_subn, + ts_req = (host_timestamp_msg_t*)dhd_prot_alloc_ring_space(dhdp, ctrl_ring, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D, &alloced, FALSE); if (ts_req == NULL) { DHD_ERROR(("couldn't allocate space on msgring to send host TS request\n")); - DHD_GENERAL_UNLOCK(dhdp, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhdp->bus); -#endif + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return -1; } /* Common msg buf hdr */ ts_req->msg.msg_type = MSG_TYPE_HOSTTIMSTAMP; ts_req->msg.if_id = 0; - ts_req->msg.flags = prot->h2dring_ctrl_subn.current_phase; + ts_req->msg.flags = ctrl_ring->current_phase; ts_req->msg.request_id = DHD_H2D_HOSTTS_REQ_PKTID; - ts_req->msg.epoch = prot->h2dring_ctrl_subn.seqnum % H2D_EPOCH_MODULO; - prot->h2dring_ctrl_subn.seqnum++; + ts_req->msg.epoch = ctrl_ring->seqnum % H2D_EPOCH_MODULO; + ctrl_ring->seqnum++; ts_req->xt_id = xt_id; ts_req->seqnum = seqnum; @@ -8893,19 +9329,15 @@ dhd_prot_send_host_timestamp(dhd_pub_t *dhdp, uchar *tlvs, uint16 tlv_len, ts_req->msg.request_id, ts_req->input_data_len, ts_req->xt_id, ts_req->seqnum)); - /* upd wrt ptr and raise interrupt */ - dhd_prot_ring_write_complete(dhdp, &prot->h2dring_ctrl_subn, ts_req, + dhd_prot_ring_write_complete(dhdp, ctrl_ring, ts_req, DHD_FLOWRING_DEFAULT_NITEMS_POSTED_H2D); - DHD_GENERAL_UNLOCK(dhdp, flags); -#ifdef PCIE_INB_DW - dhd_prot_dec_hostactive_ack_pending_dsreq(dhdp->bus); -#endif + + DHD_RING_UNLOCK(ctrl_ring->ring_lock, flags); return 0; } /* dhd_prot_send_host_timestamp */ - bool dhd_prot_data_path_tx_timestamp_logging(dhd_pub_t *dhd, bool enable, bool set) { @@ -8923,6 +9355,33 @@ dhd_prot_data_path_rx_timestamp_logging(dhd_pub_t *dhd, bool enable, bool set) return dhd->prot->rx_ts_log_enabled; } + +bool +dhd_prot_pkt_noretry(dhd_pub_t *dhd, bool enable, bool set) +{ + if (set) + dhd->prot->no_retry = enable; + + return dhd->prot->no_retry; +} + +bool +dhd_prot_pkt_noaggr(dhd_pub_t *dhd, bool enable, bool set) +{ + if (set) + dhd->prot->no_aggr = enable; + + return dhd->prot->no_aggr; +} + +bool +dhd_prot_pkt_fixed_rate(dhd_pub_t *dhd, bool enable, bool set) +{ + if (set) + dhd->prot->fixed_rate = enable; + + return dhd->prot->fixed_rate; +} #endif /* BCMPCIE */ void @@ -8934,56 +9393,16 @@ dhd_prot_dma_indx_free(dhd_pub_t *dhd) dhd_dma_buf_free(dhd, &prot->d2h_dma_indx_rd_buf); } -static void BCMFASTPATH -dhd_prot_process_fw_timestamp(dhd_pub_t *dhd, void* buf) +void +dhd_msgbuf_delay_post_ts_bufs(dhd_pub_t *dhd) { -#ifdef DHD_TIMESYNC - fw_timestamp_event_msg_t *resp; - uint32 pktid; - uint16 buflen, seqnum; - void * pkt; - unsigned long flags; - - resp = (fw_timestamp_event_msg_t *)buf; - pktid = ltoh32(resp->msg.request_id); - buflen = ltoh16(resp->buf_len); - seqnum = ltoh16(resp->seqnum); - -#if defined(DHD_PKTID_AUDIT_RING) - DHD_PKTID_AUDIT(dhd, dhd->prot->pktid_ctrl_map, pktid, - DHD_DUPLICATE_FREE); -#endif /* DHD_PKTID_AUDIT_RING */ - - DHD_INFO(("id 0x%04x, len %d, phase 0x%02x, seqnum %d\n", - pktid, buflen, resp->msg.flags, ltoh16(resp->seqnum))); - - if (!dhd->prot->cur_ts_bufs_posted) { - DHD_ERROR(("tsbuf posted are zero, but there is a completion\n")); - return; - } - - dhd->prot->cur_ts_bufs_posted--; if (dhd->prot->max_tsbufpost > 0) dhd_msgbuf_rxbuf_post_ts_bufs(dhd); +} - DHD_GENERAL_LOCK(dhd, flags); - pkt = dhd_prot_packet_get(dhd, pktid, PKTTYPE_TSBUF_RX, TRUE); - DHD_GENERAL_UNLOCK(dhd, flags); - - if (!pkt) { - DHD_ERROR(("no ts buffer associated with pktid 0x%04x\n", pktid)); - return; - } - - PKTSETLEN(dhd->osh, pkt, buflen); - dhd_timesync_handle_fw_timestamp(dhd->ts, PKTDATA(dhd->osh, pkt), buflen, seqnum); -#ifdef DHD_USE_STATIC_CTRLBUF - PKTFREE_STATIC(dhd->osh, pkt, TRUE); -#else - PKTFREE(dhd->osh, pkt, TRUE); -#endif /* DHD_USE_STATIC_CTRLBUF */ -#else /* DHD_TIMESYNC */ +static void BCMFASTPATH +dhd_prot_process_fw_timestamp(dhd_pub_t *dhd, void* buf) +{ DHD_ERROR(("Timesunc feature not compiled in but GOT FW TS message\n")); -#endif /* DHD_TIMESYNC */ } diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pcie.c b/drivers/net/wireless/bcmdhd_oo/dhd_pcie.c index e00cc944500d8c14047dc708ca75b072b4299339..ab4594d48dab957abb99291759d77d32c6d99be3 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pcie.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pcie.c @@ -1,14 +1,14 @@ /* * DHD Bus Module for PCIE * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,10 +24,9 @@ * * <> * - * $Id: dhd_pcie.c 736723 2017-12-18 08:37:35Z $ + * $Id: dhd_pcie.c 740024 2018-01-10 12:20:47Z $ */ - /* include files */ #include #include @@ -35,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -61,17 +62,13 @@ #endif /* DHDTCPACK_SUPPRESS */ #include -#ifdef DHD_TIMESYNC -#include -#endif /* DHD_TIMESYNC */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#include +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ -#if defined(BCMEMBEDIMAGE) -#ifndef DHD_EFI -#include BCMEMBEDIMAGE -#else -#include -#endif /* !DHD_EFI */ -#endif /* BCMEMBEDIMAGE */ +#if defined(DEBUGGER) || defined(DHD_DSCOPE) +#include +#endif /* DEBUGGER || DHD_DSCOPE */ #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ #define MAX_WKLK_IDLE_CHECK 3 /* times wake_lock checked before deciding not to suspend */ @@ -81,8 +78,25 @@ /* Temporary war to fix precommit till sync issue between trunk & precommit branch is resolved */ /* CTO Prevention Recovery */ +#ifdef BCMQT_HW +#define CTO_TO_CLEAR_WAIT_MS 10000 +#define CTO_TO_CLEAR_WAIT_MAX_CNT 100 +#else #define CTO_TO_CLEAR_WAIT_MS 1000 #define CTO_TO_CLEAR_WAIT_MAX_CNT 10 +#endif // endif + +/* Fetch address of a member in the pciedev_shared structure in dongle memory */ +#define DHD_PCIE_SHARED_MEMBER_ADDR(bus, member) \ + (bus)->shared_addr + OFFSETOF(pciedev_shared_t, member) + +/* Fetch address of a member in rings_info_ptr structure in dongle memory */ +#define DHD_RING_INFO_MEMBER_ADDR(bus, member) \ + (bus)->pcie_sh->rings_info_ptr + OFFSETOF(ring_info_t, member) + +/* Fetch address of a member in the ring_mem structure in dongle memory */ +#define DHD_RING_MEM_MEMBER_ADDR(bus, ringid, member) \ + (bus)->ring_sh[ringid].ring_mem_addr + OFFSETOF(ring_mem_t, member) #if defined(SUPPORT_MULTIPLE_BOARD_REV) extern unsigned int system_rev; @@ -102,7 +116,7 @@ static int dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 act const char *name, void *params, int plen, void *arg, int len, int val_size); static int dhdpcie_bus_lpback_req(struct dhd_bus *bus, uint32 intval); -static int dhdpcie_bus_dmaxfer_req(struct dhd_bus *bus, +static int dhdpcie_bus_dmaxfer_req(struct dhd_bus *bus, uint32 len, uint32 srcdelay, uint32 destdelay, uint32 d11_lpbk, uint32 core_num, uint32 wait); static int dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter); @@ -126,8 +140,8 @@ static uint16 dhdpcie_bus_rtcm16(dhd_bus_t *bus, ulong offset); static void dhdpcie_bus_wtcm32(dhd_bus_t *bus, ulong offset, uint32 data); static uint32 dhdpcie_bus_rtcm32(dhd_bus_t *bus, ulong offset); #ifdef DHD_SUPPORT_64BIT -static void dhdpcie_bus_wtcm64(dhd_bus_t *bus, ulong offset, uint64 data); -static uint64 dhdpcie_bus_rtcm64(dhd_bus_t *bus, ulong offset); +static void dhdpcie_bus_wtcm64(dhd_bus_t *bus, ulong offset, uint64 data) __attribute__ ((used)); +static uint64 dhdpcie_bus_rtcm64(dhd_bus_t *bus, ulong offset) __attribute__ ((used)); #endif /* DHD_SUPPORT_64BIT */ static void dhdpcie_bus_cfg_set_bar0_win(dhd_bus_t *bus, uint32 data); static void dhdpcie_bus_reg_unmap(osl_t *osh, volatile char *addr, int size); @@ -137,32 +151,32 @@ static void dhd_fillup_ring_sharedptr_info(dhd_bus_t *bus, ring_info_t *ring_inf extern void dhd_dpc_enable(dhd_pub_t *dhdp); extern void dhd_dpc_kill(dhd_pub_t *dhdp); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static void dhdpcie_handle_mb_data(dhd_bus_t *bus); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef IDLE_TX_FLOW_MGMT static void dhd_bus_check_idle_scan(dhd_bus_t *bus); static void dhd_bus_idle_scan(dhd_bus_t *bus); #endif /* IDLE_TX_FLOW_MGMT */ -#ifdef BCMEMBEDIMAGE -static int dhdpcie_download_code_array(dhd_bus_t *bus); -#endif /* BCMEMBEDIMAGE */ - - #ifdef EXYNOS_PCIE_DEBUG extern void exynos_pcie_register_dump(int ch_num); #endif /* EXYNOS_PCIE_DEBUG */ #define PCI_VENDOR_ID_BROADCOM 0x14e4 +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#define MAX_D3_ACK_TIMEOUT 100 +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #define DHD_DEFAULT_DOORBELL_TIMEOUT 200 /* ms */ -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) -static uint dhd_doorbell_timeout = DHD_DEFAULT_DOORBELL_TIMEOUT; -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ static bool dhdpcie_check_firmware_compatible(uint32 f_api_version, uint32 h_api_version); static void dhdpcie_cto_error_recovery(struct dhd_bus *bus); -#ifdef BCM_ASLR_HEAP +static int dhdpcie_init_d11status(struct dhd_bus *bus); + static void dhdpcie_wrt_rnd(struct dhd_bus *bus); -#endif /* BCM_ASLR_HEAP */ extern uint16 dhd_prot_get_h2d_max_txpost(dhd_pub_t *dhd); extern void dhd_prot_set_h2d_max_txpost(dhd_pub_t *dhd, uint16 max_txpost); @@ -208,113 +222,101 @@ enum { IOV_TRAPDATA, IOV_TRAPDATA_RAW, IOV_CTO_PREVENTION, -#ifdef PCIE_OOB - IOV_OOB_BT_REG_ON, - IOV_OOB_ENABLE, -#endif /* PCIE_OOB */ IOV_PCIE_WD_RESET, - IOV_CTO_THRESHOLD, -#ifdef DHD_EFI - IOV_CONTROL_SIGNAL, -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - IOV_DEEP_SLEEP, -#endif /* PCIE_OOB || PCIE_INB_DW */ -#endif /* DHD_EFI */ -#ifdef DEVICE_TX_STUCK_DETECT - IOV_DEVICE_TX_STUCK_DETECT, -#endif /* DEVICE_TX_STUCK_DETECT */ - IOV_INB_DW_ENABLE, + IOV_DUMP_DONGLE, IOV_IDMA_ENABLE, IOV_IFRM_ENABLE, IOV_CLEAR_RING, -#ifdef DHD_EFI - IOV_WIFI_PROPERTIES, - IOV_OTP_DUMP -#endif + IOV_DAR_ENABLE, + IOV_DNGL_CAPS, /**< returns string with dongle capabilities */ +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + IOV_GDB_SERVER, /**< starts gdb server on given interface */ +#endif /* DEBUGGER || DHD_DSCOPE */ + IOV_INB_DW_ENABLE, + IOV_CTO_THRESHOLD, + IOV_PCIE_LAST /**< unused IOVAR */ }; - const bcm_iovar_t dhdpcie_iovars[] = { - {"intr", IOV_INTR, 0, 0, IOVT_BOOL, 0 }, - {"memsize", IOV_MEMSIZE, 0, 0, IOVT_UINT32, 0 }, - {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, 0, IOVT_BOOL, 0 }, - {"vars", IOV_VARS, 0, 0, IOVT_BUFFER, 0 }, - {"devreset", IOV_DEVRESET, 0, 0, IOVT_BOOL, 0 }, - {"pcie_device_trap", IOV_FORCE_FW_TRAP, 0, 0, 0, 0 }, + {"intr", IOV_INTR, 0, 0, IOVT_BOOL, 0 }, + {"memsize", IOV_MEMSIZE, 0, 0, IOVT_UINT32, 0 }, + {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, 0, IOVT_BOOL, 0 }, + {"vars", IOV_VARS, 0, 0, IOVT_BUFFER, 0 }, + {"devreset", IOV_DEVRESET, 0, 0, IOVT_UINT8, 0 }, + {"pcie_device_trap", IOV_FORCE_FW_TRAP, 0, 0, 0, 0 }, {"pcie_lpbk", IOV_PCIE_LPBK, 0, 0, IOVT_UINT32, 0 }, - {"cc_nvmshadow", IOV_CC_NVMSHADOW, 0, 0, IOVT_BUFFER, 0 }, - {"ramsize", IOV_RAMSIZE, 0, 0, IOVT_UINT32, 0 }, - {"ramstart", IOV_RAMSTART, 0, 0, IOVT_UINT32, 0 }, - {"pcie_dmaxfer", IOV_PCIE_DMAXFER, 0, 0, IOVT_BUFFER, 3 * sizeof(int32) }, + {"cc_nvmshadow", IOV_CC_NVMSHADOW, 0, 0, IOVT_BUFFER, 0 }, + {"ramsize", IOV_RAMSIZE, 0, 0, IOVT_UINT32, 0 }, + {"ramstart", IOV_RAMSTART, 0, 0, IOVT_UINT32, 0 }, + {"pcie_dmaxfer", IOV_PCIE_DMAXFER, 0, 0, IOVT_BUFFER, 3 * sizeof(int32) }, {"pcie_suspend", IOV_PCIE_SUSPEND, 0, 0, IOVT_UINT32, 0 }, -#ifdef PCIE_OOB - {"oob_bt_reg_on", IOV_OOB_BT_REG_ON, 0, 0, IOVT_UINT32, 0 }, - {"oob_enable", IOV_OOB_ENABLE, 0, 0, IOVT_UINT32, 0 }, -#endif /* PCIE_OOB */ {"sleep_allowed", IOV_SLEEP_ALLOWED, 0, 0, IOVT_BOOL, 0 }, - {"dngl_isolation", IOV_DONGLEISOLATION, 0, 0, IOVT_UINT32, 0 }, + {"dngl_isolation", IOV_DONGLEISOLATION, 0, 0, IOVT_UINT32, 0 }, {"ltrsleep_on_unload", IOV_LTRSLEEPON_UNLOOAD, 0, 0, IOVT_UINT32, 0 }, - {"dump_ringupdblk", IOV_DUMP_RINGUPD_BLOCK, 0, 0, IOVT_BUFFER, 0 }, - {"dma_ring_indices", IOV_DMA_RINGINDICES, 0, 0, IOVT_UINT32, 0}, + {"dump_ringupdblk", IOV_DUMP_RINGUPD_BLOCK, 0, 0, IOVT_BUFFER, 0 }, + {"dma_ring_indices", IOV_DMA_RINGINDICES, 0, 0, IOVT_UINT32, 0}, {"metadata_dbg", IOV_METADATA_DBG, 0, 0, IOVT_BOOL, 0 }, - {"rx_metadata_len", IOV_RX_METADATALEN, 0, 0, IOVT_UINT32, 0 }, - {"tx_metadata_len", IOV_TX_METADATALEN, 0, 0, IOVT_UINT32, 0 }, - {"db1_for_mb", IOV_DB1_FOR_MB, 0, 0, IOVT_UINT32, 0 }, + {"rx_metadata_len", IOV_RX_METADATALEN, 0, 0, IOVT_UINT32, 0 }, + {"tx_metadata_len", IOV_TX_METADATALEN, 0, 0, IOVT_UINT32, 0 }, + {"db1_for_mb", IOV_DB1_FOR_MB, 0, 0, IOVT_UINT32, 0 }, {"txp_thresh", IOV_TXP_THRESHOLD, 0, 0, IOVT_UINT32, 0 }, - {"buzzz_dump", IOV_BUZZZ_DUMP, 0, 0, IOVT_UINT32, 0 }, - {"flow_prio_map", IOV_FLOW_PRIO_MAP, 0, 0, IOVT_UINT32, 0 }, + {"buzzz_dump", IOV_BUZZZ_DUMP, 0, 0, IOVT_UINT32, 0 }, + {"flow_prio_map", IOV_FLOW_PRIO_MAP, 0, 0, IOVT_UINT32, 0 }, #ifdef DHD_PCIE_RUNTIMEPM - {"idletime", IOV_IDLETIME, 0, 0, IOVT_INT32, 0 }, + {"idletime", IOV_IDLETIME, 0, 0, IOVT_INT32, 0 }, #endif /* DHD_PCIE_RUNTIMEPM */ - {"rxbound", IOV_RXBOUND, 0, 0, IOVT_UINT32, 0 }, - {"txbound", IOV_TXBOUND, 0, 0, IOVT_UINT32, 0 }, - {"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 }, + {"rxbound", IOV_RXBOUND, 0, 0, IOVT_UINT32, 0 }, + {"txbound", IOV_TXBOUND, 0, 0, IOVT_UINT32, 0 }, + {"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 }, {"h2d_mb_data", IOV_H2D_MAILBOXDATA, 0, 0, IOVT_UINT32, 0 }, {"inforings", IOV_INFORINGS, 0, 0, IOVT_UINT32, 0 }, {"h2d_phase", IOV_H2D_PHASE, 0, 0, IOVT_UINT32, 0 }, {"force_trap_bad_h2d_phase", IOV_H2D_ENABLE_TRAP_BADPHASE, 0, 0, IOVT_UINT32, 0 }, {"h2d_max_txpost", IOV_H2D_TXPOST_MAX_ITEM, 0, 0, IOVT_UINT32, 0 }, - {"trap_data", IOV_TRAPDATA, 0, 0, IOVT_BUFFER, 0 }, + {"trap_data", IOV_TRAPDATA, 0, 0, IOVT_BUFFER, 0 }, {"trap_data_raw", IOV_TRAPDATA_RAW, 0, 0, IOVT_BUFFER, 0 }, - {"cto_prevention", IOV_CTO_PREVENTION, 0, 0, IOVT_UINT32, 0 }, + {"cto_prevention", IOV_CTO_PREVENTION, 0, 0, IOVT_UINT32, 0 }, {"pcie_wd_reset", IOV_PCIE_WD_RESET, 0, 0, IOVT_BOOL, 0 }, - {"cto_threshold", IOV_CTO_THRESHOLD, 0, 0, IOVT_UINT32, 0 }, -#ifdef DHD_EFI - {"control_signal", IOV_CONTROL_SIGNAL, 0, 0, IOVT_UINT32, 0}, -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - {"deep_sleep", IOV_DEEP_SLEEP, 0, 0, IOVT_UINT32, 0}, -#endif /* PCIE_OOB || PCIE_INB_DW */ -#endif /* DHD_EFI */ - {"inb_dw_enable", IOV_INB_DW_ENABLE, 0, 0, IOVT_UINT32, 0 }, -#ifdef DEVICE_TX_STUCK_DETECT - {"dev_tx_stuck_monitor", IOV_DEVICE_TX_STUCK_DETECT, 0, 0, IOVT_UINT32, 0 }, -#endif /* DEVICE_TX_STUCK_DETECT */ + {"dump_dongle", IOV_DUMP_DONGLE, 0, 0, IOVT_BUFFER, + MAX(sizeof(dump_dongle_in_t), sizeof(dump_dongle_out_t))}, + {"clear_ring", IOV_CLEAR_RING, 0, 0, IOVT_UINT32, 0 }, {"idma_enable", IOV_IDMA_ENABLE, 0, 0, IOVT_UINT32, 0 }, {"ifrm_enable", IOV_IFRM_ENABLE, 0, 0, IOVT_UINT32, 0 }, - {"clear_ring", IOV_CLEAR_RING, 0, 0, IOVT_UINT32, 0 }, -#ifdef DHD_EFI - {"properties", IOV_WIFI_PROPERTIES, 0, 0, IOVT_BUFFER, 0}, - {"otp_dump", IOV_OTP_DUMP, 0, 0, IOVT_BUFFER, 0}, -#endif + {"dar_enable", IOV_DAR_ENABLE, 0, 0, IOVT_UINT32, 0 }, + {"cap", IOV_DNGL_CAPS, 0, 0, IOVT_BUFFER, 0}, +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + {"gdb_server", IOV_GDB_SERVER, 0, 0, IOVT_UINT32, 0 }, +#endif /* DEBUGGER || DHD_DSCOPE */ + {"inb_dw_enable", IOV_INB_DW_ENABLE, 0, 0, IOVT_UINT32, 0 }, + {"cto_threshold", IOV_CTO_THRESHOLD, 0, 0, IOVT_UINT32, 0 }, {NULL, 0, 0, 0, 0, 0 } }; - #define MAX_READ_TIMEOUT 5 * 1000 * 1000 #ifndef DHD_RXBOUND #define DHD_RXBOUND 64 -#endif +#endif // endif #ifndef DHD_TXBOUND #define DHD_TXBOUND 64 -#endif +#endif // endif #define DHD_INFORING_BOUND 32 +#define DHD_BTLOGRING_BOUND 32 uint dhd_rxbound = DHD_RXBOUND; uint dhd_txbound = DHD_TXBOUND; +#if defined(DEBUGGER) || defined(DHD_DSCOPE) +/** the GDB debugger layer will call back into this (bus) layer to read/write dongle memory */ +static struct dhd_gdb_bus_ops_s bus_ops = { + .read_u16 = dhdpcie_bus_rtcm16, + .read_u32 = dhdpcie_bus_rtcm32, + .write_u32 = dhdpcie_bus_wtcm32, +}; +#endif /* DEBUGGER || DHD_DSCOPE */ + /** * Register/Unregister functions are called by the main DHD entry point (eg module insertion) to * link with the bus driver, in order to look for or await the device. @@ -336,7 +338,6 @@ dhd_bus_unregister(void) return; } - /** returns a host virtual address */ uint32 * dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size) @@ -352,6 +353,63 @@ dhdpcie_bus_reg_unmap(osl_t *osh, volatile char *addr, int size) } /** + * retrun H2D Doorbell registers address + * use DAR registers instead of enum register for corerev >= 23 (4347B0) + */ +static INLINE uint +dhd_bus_db0_addr_get(struct dhd_bus *bus) +{ + uint addr = PCIH2D_MailBox; + uint dar_addr = DAR_PCIH2D_DB0_0(bus->sih->buscorerev); + + return ((DAR_ACTIVE(bus->dhd)) ? dar_addr : addr); +} + +static INLINE uint +dhd_bus_db0_addr_2_get(struct dhd_bus *bus) +{ + return ((DAR_ACTIVE(bus->dhd)) ? DAR_PCIH2D_DB2_0(bus->sih->buscorerev) : PCIH2D_MailBox_2); +} + +static INLINE uint +dhd_bus_db1_addr_get(struct dhd_bus *bus) +{ + return ((DAR_ACTIVE(bus->dhd)) ? DAR_PCIH2D_DB0_1(bus->sih->buscorerev) : PCIH2D_DB1); +} + +static INLINE uint +dhd_bus_db1_addr_1_get(struct dhd_bus *bus) +{ + return ((DAR_ACTIVE(bus->dhd)) ? DAR_PCIH2D_DB1_1(bus->sih->buscorerev) : PCIH2D_DB1_1); +} + +static INLINE void +dhd_bus_pcie_pwr_req(struct dhd_bus *bus) +{ + si_corereg(bus->sih, bus->sih->buscoreidx, + DAR_PCIE_PWR_CTRL(bus->sih->buscorerev), + ((SRPWR_DMN0_PCIE_MASK | SRPWR_DMN1_ARMBPSD_MASK) << SRPWR_REQON_SHIFT), + ((SRPWR_DMN0_PCIE_MASK | SRPWR_DMN1_ARMBPSD_MASK) << SRPWR_REQON_SHIFT)); + +} + +bool +dhdpcie_chip_support_msi(dhd_bus_t *bus) +{ + DHD_ERROR(("%s: buscorerev=%d chipid=0x%x\n", + __FUNCTION__, bus->sih->buscorerev, si_chipid(bus->sih))); + if (bus->sih->buscorerev <= 14 || + si_chipid(bus->sih) == BCM4361_CHIP_ID || + si_chipid(bus->sih) == BCM4359_CHIP_ID) { + return FALSE; + } else { + return TRUE; + } +} + +/** + * Called once for each hardware (dongle) instance that this DHD manages. + * * 'regs' is the host virtual address that maps to the start of the PCIe BAR0 window. The first 4096 * bytes in this window are mapped to the backplane address in the PCIEBAR0Window register. The * precondition is that the PCIEBAR0Window register 'points' at the PCIe core. @@ -377,18 +435,11 @@ dhd_bus_t* dhdpcie_bus_attach(osl_t *osh, /* Save pci_dev into dhd_bus, as it may be needed in dhd_attach */ bus->dev = (struct pci_dev *)pci_dev; - dll_init(&bus->flowring_active_list); #ifdef IDLE_TX_FLOW_MGMT bus->active_list_last_process_ts = OSL_SYSUPTIME(); #endif /* IDLE_TX_FLOW_MGMT */ -#ifdef DEVICE_TX_STUCK_DETECT - /* Enable the Device stuck detection feature by default */ - bus->dev_tx_stuck_monitor = TRUE; - bus->device_tx_stuck_check = OSL_SYSUPTIME(); -#endif /* DEVICE_TX_STUCK_DETECT */ - /* Attach pcie shared structure */ if (!(bus->pcie_sh = MALLOCZ(osh, sizeof(pciedev_shared_t)))) { DHD_ERROR(("%s: MALLOC of bus->pcie_sh failed\n", __FUNCTION__)); @@ -418,11 +469,18 @@ dhd_bus_t* dhdpcie_bus_attach(osl_t *osh, #endif /* IDLE_TX_FLOW_MGMT */ bus->irq_registered = FALSE; +#ifdef DHD_MSI_SUPPORT + bus->d2h_intr_method = enable_msi && dhdpcie_chip_support_msi(bus) ? + PCIE_MSI : PCIE_INTX; +#else + bus->d2h_intr_method = PCIE_INTX; +#endif /* DHD_MSI_SUPPORT */ + DHD_TRACE(("%s: EXIT SUCCESS\n", __FUNCTION__)); #ifdef DHD_FW_COREDUMP g_dhd_bus = bus; -#endif +#endif // endif return bus; } while (0); @@ -438,6 +496,15 @@ dhd_bus_t* dhdpcie_bus_attach(osl_t *osh, return NULL; } +bool +dhd_bus_skip_clm(dhd_pub_t *dhdp) +{ + switch (dhd_bus_chip_id(dhdp)) { + default: + return FALSE; + } +} + uint dhd_bus_chip(struct dhd_bus *bus) { @@ -459,10 +526,10 @@ dhd_bus_pub(struct dhd_bus *bus) return bus->dhd; } -const void * +void * dhd_bus_sih(struct dhd_bus *bus) { - return (const void *)bus->sih; + return (void *)bus->sih; } void * @@ -499,17 +566,8 @@ dhdpcie_bus_intstatus(dhd_bus_t *bus) uint32 intstatus = 0; uint32 intmask = 0; - if ((bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) && - bus->wait_for_d3_ack) { -#ifdef DHD_EFI - DHD_INFO(("%s: trying to clear intstatus during suspend (%d)" - " or suspend in progress %d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); -#else - DHD_ERROR(("%s: trying to clear intstatus during suspend (%d)" - " or suspend in progress %d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); -#endif /* !DHD_EFI */ + if (bus->bus_low_power_state == DHD_BUS_D3_ACK_RECIEVED) { + DHD_ERROR(("%s: trying to clear intstatus after D3 Ack\n", __FUNCTION__)); return intstatus; } if ((bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4) || @@ -519,15 +577,16 @@ dhdpcie_bus_intstatus(dhd_bus_t *bus) intstatus &= I_MB; } else { /* this is a PCIE core register..not a config register... */ - intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); + intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_int, 0, 0); /* this is a PCIE core register..not a config register... */ - intmask = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); - + intmask = si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_mask, 0, 0); intstatus &= intmask; /* Is device removed. intstatus & intmask read 0xffffffff */ if (intstatus == (uint32)-1) { DHD_ERROR(("%s: Device is removed or Link is down.\n", __FUNCTION__)); + bus->is_linkdown = TRUE; + dhd_pcie_debug_info_dump(bus->dhd); #ifdef CUSTOMER_HW4_DEBUG #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) bus->dhd->hang_reason = HANG_REASON_PCIE_LINK_DOWN; @@ -537,14 +596,13 @@ dhdpcie_bus_intstatus(dhd_bus_t *bus) return intstatus; } - /* * The fourth argument to si_corereg is the "mask" fields of the register to update * and the fifth field is the "value" to update. Now if we are interested in only * few fields of the "mask" bit map, we should not be writing back what we read * By doing so, we might clear/ack interrupts that are not handled yet. */ - si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, bus->def_intmask, + si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_int, bus->def_intmask, intstatus); intstatus &= bus->def_intmask; @@ -579,16 +637,13 @@ dhdpcie_bus_isr(dhd_bus_t *bus) } if (bus->dhd->dongle_reset) { - DHD_ERROR(("%s : dongle is reset\n", __FUNCTION__)); break; } if (bus->dhd->busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s : bus is down \n", __FUNCTION__)); break; } - if (PCIECTO_ENAB(bus->dhd)) { /* read pci_intstatus */ intstatus = dhdpcie_bus_cfg_read_dword(bus, PCI_INT_STATUS, 4); @@ -602,11 +657,15 @@ dhdpcie_bus_isr(dhd_bus_t *bus) } } + if (bus->d2h_intr_method == PCIE_MSI) { + /* For MSI, as intstatus is cleared by firmware, no need to read */ + goto skip_intstatus_read; + } + intstatus = dhdpcie_bus_intstatus(bus); /* Check if the interrupt is ours or not */ if (intstatus == 0) { - DHD_ERROR(("%s : this interrupt is not ours\n", __FUNCTION__)); break; } @@ -616,13 +675,11 @@ dhdpcie_bus_isr(dhd_bus_t *bus) /* return error for 0xFFFFFFFF */ if (intstatus == (uint32)-1) { - DHD_ERROR(("%s : wrong interrupt status val : 0x%x\n", - __FUNCTION__, intstatus)); dhdpcie_disable_irq_nosync(bus); - bus->is_linkdown = TRUE; - break; + return BCME_ERROR; } +skip_intstatus_read: /* Overall operation: * - Mask further interrupts * - Read/ack intstatus @@ -636,7 +693,13 @@ dhdpcie_bus_isr(dhd_bus_t *bus) bus->ipend = TRUE; bus->isr_intr_disable_count++; - dhdpcie_bus_intr_disable(bus); /* Disable interrupt using IntMask!! */ + + /* For Linux, Macos etc (otherthan NDIS) instead of disabling + * dongle interrupt by clearing the IntMask, disable directly + * interrupt from the host side, so that host will not recieve + * any interrupts at all, even though dongle raises interrupts + */ + dhdpcie_disable_irq_nosync(bus); /* Disable interrupt!! */ bus->intdis = TRUE; @@ -714,7 +777,6 @@ dhdpcie_set_pwr_state(dhd_bus_t *bus, uint state) } return BCME_OK; - } int @@ -736,7 +798,7 @@ dhdpcie_config_check(dhd_bus_t *bus) } int -dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr) +dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr) { uint32 i; osl_t *osh = bus->osh; @@ -752,7 +814,7 @@ dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr) if (restore_pmcsr) OSL_PCI_WRITE_CONFIG(osh, PCIECFGREG_PM_CSR, - sizeof(uint32), bus->saved_config.pmcsr); + sizeof(uint32), bus->saved_config.pmcsr); OSL_PCI_WRITE_CONFIG(osh, PCIECFGREG_MSI_CAP, sizeof(uint32), bus->saved_config.msi_cap); OSL_PCI_WRITE_CONFIG(osh, PCIECFGREG_MSI_ADDR_L, sizeof(uint32), @@ -776,10 +838,10 @@ dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr) OSL_PCI_WRITE_CONFIG(osh, PCIECFGREG_PML1_SUB_CTRL2, sizeof(uint32), bus->saved_config.l1pm1); - OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR0_WIN, - sizeof(uint32), bus->saved_config.bar0_win); - OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR1_WIN, - sizeof(uint32), bus->saved_config.bar1_win); + OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR0_WIN, sizeof(uint32), + bus->saved_config.bar0_win); + OSL_PCI_WRITE_CONFIG(bus->osh, PCI_BAR1_WIN, sizeof(uint32), + bus->saved_config.bar1_win); return BCME_OK; } @@ -827,21 +889,53 @@ dhdpcie_config_save(dhd_bus_t *bus) sizeof(uint32)); bus->saved_config.bar1_win = OSL_PCI_READ_CONFIG(osh, PCI_BAR1_WIN, sizeof(uint32)); + return BCME_OK; } #ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY dhd_pub_t *link_recovery = NULL; #endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ + +static void +dhdpcie_bus_intr_init(dhd_bus_t *bus) +{ + uint buscorerev = bus->sih->buscorerev; + bus->pcie_mailbox_int = PCIMailBoxInt(buscorerev); + bus->pcie_mailbox_mask = PCIMailBoxMask(buscorerev); + bus->d2h_mb_mask = PCIE_MB_D2H_MB_MASK(buscorerev); + bus->def_intmask = PCIE_MB_D2H_MB_MASK(buscorerev); + if (buscorerev < 64) { + bus->def_intmask |= PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1; + } +} + +#ifdef DHD_DISABLE_ASPM +void +dhd_bus_aspm_enable(dhd_bus_t *bus, bool enable) +{ + uint val; + val = dhd_pcie_config_read(bus->osh, PCIECFGREG_LINK_STATUS_CTRL, sizeof(uint32)); + if (enable) { + dhd_pcie_config_write(bus->osh, PCIECFGREG_LINK_STATUS_CTRL, sizeof(uint32), + (val | PCIE_ASPM_L1_ENAB)); + } else { + dhd_pcie_config_write(bus->osh, PCIECFGREG_LINK_STATUS_CTRL, sizeof(uint32), + (val & (~PCIE_ASPM_L1_ENAB))); + } + DHD_ERROR(("%s: %s\n", __FUNCTION__, (enable ? "ENABLE" : "DISABLE"))); +} +#endif /* DHD_DISABLE_ASPM */ + static bool dhdpcie_dongle_attach(dhd_bus_t *bus) { - osl_t *osh = bus->osh; volatile void *regsva = (volatile void*)bus->regs; - uint16 devid = bus->cl_devid; + uint16 devid; uint32 val; sbpcieregs_t *sbpcieregs; + bool dongle_isolation; DHD_TRACE(("%s: ENTER\n", __FUNCTION__)); @@ -852,15 +946,17 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) bus->alp_only = TRUE; bus->sih = NULL; - /* Set bar0 window to si_enum_base */ - dhdpcie_bus_cfg_set_bar0_win(bus, SI_ENUM_BASE); - /* Checking PCIe bus status with reading configuration space */ val = OSL_PCI_READ_CONFIG(osh, PCI_CFG_VID, sizeof(uint32)); if ((val & 0xFFFF) != VENDOR_BROADCOM) { DHD_ERROR(("%s : failed to read PCI configuration space!\n", __FUNCTION__)); goto fail; } + devid = (val >> 16) & 0xFFFF; + bus->cl_devid = devid; + + /* Set bar0 window to si_enum_base */ + dhdpcie_bus_cfg_set_bar0_win(bus, si_enum_base(devid)); /* * Checking PCI_SPROM_CONTROL register for preventing invalid address access @@ -872,14 +968,6 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) goto fail; } -#ifdef DHD_EFI - /* Save good copy of PCIe config space */ - if (BCME_OK != dhdpcie_config_save(bus)) { - DHD_ERROR(("%s : failed to save PCI configuration space!\n", __FUNCTION__)); - goto fail; - } -#endif /* DHD_EFI */ - /* si_attach() will provide an SI handle and scan the backplane */ if (!(bus->sih = si_attach((uint)devid, osh, regsva, PCI_BUS, bus, &bus->vars, &bus->varsz))) { @@ -897,22 +985,33 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) goto fail; } + BCM_REFERENCE(dongle_isolation); #ifndef DONGLE_ENABLE_ISOLATION /* Enable CLKREQ# */ dhdpcie_clkreq(bus->osh, 1, 1); + /* + * bus->dhd will be NULL if it is called from dhd_bus_attach, so need to reset + * without checking dongle_isolation flag, but if it is called via some other path + * like quiesce FLR, then based on dongle_isolation flag, watchdog_reset should + * be called. + */ + if (bus->dhd == NULL) { + dongle_isolation = FALSE; /* dhd_attach not yet happened, do watchdog reset */ + } else { + dongle_isolation = bus->dhd->dongle_isolation; + } /* * Issue CC watchdog to reset all the cores on the chip - similar to rmmod dhd * This is required to avoid spurious interrupts to the Host and bring back * dongle to a sane state (on host soft-reboot / watchdog-reboot). */ - pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *) bus->regs); + if (dongle_isolation == FALSE) { + pcie_watchdog_reset(bus->osh, bus->sih, + WD_ENABLE_MASK, WD_SSRESET_PCIE_F0_EN); + } #endif /* !DONGLE_ENABLE_ISOLATION */ -#ifdef DHD_EFI - dhdpcie_dongle_pwr_toggle(bus); -#endif - si_setcore(bus->sih, PCIE2_CORE_ID, 0); sbpcieregs = (sbpcieregs_t*)(bus->regs); @@ -934,16 +1033,21 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) } if (si_setcore(bus->sih, SYSMEM_CORE_ID, 0)) { - /* Only set dongle RAMSIZE to default value when ramsize is not adjusted */ + /* Only set dongle RAMSIZE to default value when BMC vs ARM usage of SYSMEM is not + * adjusted. + */ if (!bus->ramsize_adjusted) { if (!(bus->orig_ramsize = si_sysmem_size(bus->sih))) { DHD_ERROR(("%s: failed to find SYSMEM memory!\n", __FUNCTION__)); goto fail; } - /* also populate base address */ - bus->dongle_ram_base = CA7_4365_RAM_BASE; - /* Default reserve 1.75MB for CA7 */ - bus->orig_ramsize = 0x1c0000; + switch ((uint16)bus->sih->chip) { + default: + /* also populate base address */ + bus->dongle_ram_base = CA7_4365_RAM_BASE; + bus->orig_ramsize = 0x1c0000; /* Reserve 1.75MB for CA7 */ + break; + } } } else if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { @@ -990,7 +1094,9 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) bus->dongle_ram_base = ((bus->sih->chiprev < 9) ? CR4_4349_RAM_BASE : CR4_4349_RAM_BASE_FROM_REV_9); break; - case BCM4347_CHIP_GRPID: + case BCM4347_CHIP_ID: + case BCM4357_CHIP_ID: + case BCM4361_CHIP_ID: bus->dongle_ram_base = CR4_4347_RAM_BASE; break; default: @@ -1014,25 +1120,16 @@ dhdpcie_dongle_attach(dhd_bus_t *bus) bus->srmemsize = si_socram_srmem_size(bus->sih); - - bus->def_intmask = PCIE_MB_D2H_MB_MASK | PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1; + dhdpcie_bus_intr_init(bus); /* Set the poll and/or interrupt flags */ bus->intr = (bool)dhd_intr; +#ifdef DHD_DISABLE_ASPM + dhd_bus_aspm_enable(bus, FALSE); +#endif /* DHD_DISABLE_ASPM */ - bus->wait_for_d3_ack = 1; -#ifdef PCIE_OOB - dhdpcie_oob_init(bus); -#endif /* PCIE_OOB */ -#ifdef PCIE_INB_DW - bus->inb_enabled = TRUE; -#endif /* PCIE_INB_DW */ - bus->dongle_in_ds = FALSE; bus->idma_enabled = TRUE; bus->ifrm_enabled = TRUE; -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - bus->ds_enabled = TRUE; -#endif DHD_TRACE(("%s: EXIT: SUCCESS\n", __FUNCTION__)); return 0; @@ -1058,42 +1155,42 @@ dhpcie_bus_mask_interrupt(dhd_bus_t *bus) return 0; } +/* Non atomic function, caller should hold appropriate lock */ void dhdpcie_bus_intr_enable(dhd_bus_t *bus) { DHD_TRACE(("%s Enter\n", __FUNCTION__)); if (bus && bus->sih && !bus->is_linkdown) { + /* Skip after recieving D3 ACK */ + if (bus->bus_low_power_state == DHD_BUS_D3_ACK_RECIEVED) { + return; + } if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4)) { dhpcie_bus_unmask_interrupt(bus); } else { - /* Skip after recieving D3 ACK */ - if ((bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) && - bus->wait_for_d3_ack) { - return; - } - si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, + si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_mask, bus->def_intmask, bus->def_intmask); } } DHD_TRACE(("%s Exit\n", __FUNCTION__)); } +/* Non atomic function, caller should hold appropriate lock */ void dhdpcie_bus_intr_disable(dhd_bus_t *bus) { DHD_TRACE(("%s Enter\n", __FUNCTION__)); if (bus && bus->sih && !bus->is_linkdown) { + /* Skip after recieving D3 ACK */ + if (bus->bus_low_power_state == DHD_BUS_D3_ACK_RECIEVED) { + return; + } if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4)) { dhpcie_bus_mask_interrupt(bus); } else { - /* Skip after recieving D3 ACK */ - if ((bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) && - bus->wait_for_d3_ack) { - return; - } - si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, + si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_mask, bus->def_intmask, 0); } } @@ -1107,15 +1204,27 @@ dhdpcie_bus_intr_disable(dhd_bus_t *bus) * whether the busstate is DHD_BUS_DOWN or DHD_BUS_DOWN_IN_PROGRESS, if so * they will exit from there itself without marking dhd_bus_busy_state as BUSY. */ -static void +void dhdpcie_advertise_bus_cleanup(dhd_pub_t *dhdp) { unsigned long flags; int timeleft; - DHD_GENERAL_LOCK(dhdp, flags); - dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS; - DHD_GENERAL_UNLOCK(dhdp, flags); +#ifdef DHD_PCIE_RUNTIMEPM + dhdpcie_runtime_bus_wake(dhdp, TRUE, dhdpcie_advertise_bus_cleanup); +#endif /* DHD_PCIE_RUNTIMEPM */ + + dhdp->dhd_watchdog_ms_backup = dhd_watchdog_ms; + if (dhdp->dhd_watchdog_ms_backup) { + DHD_ERROR(("%s: Disabling wdtick before dhd deinit\n", + __FUNCTION__)); + dhd_os_wd_timer(dhdp, 0); + } + if (dhdp->busstate != DHD_BUS_DOWN) { + DHD_GENERAL_LOCK(dhdp, flags); + dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS; + DHD_GENERAL_UNLOCK(dhdp, flags); + } timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state); if ((timeleft == 0) || (timeleft == 1)) { @@ -1137,25 +1246,20 @@ dhdpcie_bus_remove_prep(dhd_bus_t *bus) bus->dhd->busstate = DHD_BUS_DOWN; DHD_GENERAL_UNLOCK(bus->dhd, flags); -#ifdef PCIE_INB_DW - /* De-Initialize the lock to serialize Device Wake Inband activities */ - if (bus->inb_lock) { - dhd_os_spin_lock_deinit(bus->dhd->osh, bus->inb_lock); - bus->inb_lock = NULL; - } -#endif - - dhd_os_sdlock(bus->dhd); if (bus->sih && !bus->dhd->dongle_isolation) { /* Has insmod fails after rmmod issue in Brix Android */ - /* if the pcie link is down, watchdog reset should not be done, as it may hang */ - if (!bus->is_linkdown) - pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *) bus->regs); - else - DHD_ERROR(("%s: skipping watchdog reset, due to pcie link down ! \n", - __FUNCTION__)); + + /* if the pcie link is down, watchdog reset + * should not be done, as it may hang + */ + + if (!bus->is_linkdown) { + + pcie_watchdog_reset(bus->osh, bus->sih, + WD_ENABLE_MASK, WD_SSRESET_PCIE_F0_EN); + } bus->dhd->is_pcie_watchdog_reset = TRUE; } @@ -1165,12 +1269,30 @@ dhdpcie_bus_remove_prep(dhd_bus_t *bus) DHD_TRACE(("%s Exit\n", __FUNCTION__)); } +void +dhd_init_bus_lock(dhd_bus_t *bus) +{ + if (!bus->bus_lock) { + bus->bus_lock = dhd_os_spin_lock_init(bus->dhd->osh); + } +} + +void +dhd_deinit_bus_lock(dhd_bus_t *bus) +{ + if (bus->bus_lock) { + dhd_os_spin_lock_deinit(bus->dhd->osh, bus->bus_lock); + bus->bus_lock = NULL; + } +} + /** Detach and free everything */ void dhdpcie_bus_release(dhd_bus_t *bus) { bool dongle_isolation = FALSE; osl_t *osh = NULL; + unsigned long flags_bus; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1180,17 +1302,29 @@ dhdpcie_bus_release(dhd_bus_t *bus) ASSERT(osh); if (bus->dhd) { +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + debugger_close(); +#endif /* DEBUGGER || DHD_DSCOPE */ dhdpcie_advertise_bus_cleanup(bus->dhd); dongle_isolation = bus->dhd->dongle_isolation; bus->dhd->is_pcie_watchdog_reset = FALSE; dhdpcie_bus_remove_prep(bus); if (bus->intr) { + DHD_BUS_LOCK(bus->bus_lock, flags_bus); dhdpcie_bus_intr_disable(bus); + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); dhdpcie_free_irq(bus); } - dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE); + dhd_deinit_bus_lock(bus); + /** + * dhdpcie_bus_release_dongle free bus->sih handle, which is needed to + * access Dongle registers. + * dhd_detach will communicate with dongle to delete flowring ..etc. + * So dhdpcie_bus_release_dongle should be called only after the dhd_detach. + */ dhd_detach(bus->dhd); + dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE); dhd_free(bus->dhd); bus->dhd = NULL; } @@ -1216,7 +1350,6 @@ dhdpcie_bus_release(dhd_bus_t *bus) MFREE(osh, bus->console.buf, bus->console.bufsize); } - /* Finally free bus info */ MFREE(osh, bus, sizeof(dhd_bus_t)); @@ -1225,7 +1358,6 @@ dhdpcie_bus_release(dhd_bus_t *bus) DHD_TRACE(("%s: Exit\n", __FUNCTION__)); } /* dhdpcie_bus_release */ - void dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag) { @@ -1240,12 +1372,11 @@ dhdpcie_bus_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bo if (bus->sih) { if (!dongle_isolation && - (bus->dhd && !bus->dhd->is_pcie_watchdog_reset)) + (bus->dhd && !bus->dhd->is_pcie_watchdog_reset)) { pcie_watchdog_reset(bus->osh, bus->sih, - (sbpcieregs_t *) bus->regs); -#ifdef DHD_EFI - dhdpcie_dongle_pwr_toggle(bus); -#endif + WD_ENABLE_MASK, WD_SSRESET_PCIE_F0_EN); + } + if (bus->ltrsleep_on_unload) { si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, u.pcie2.ltr_state), ~0, 0); @@ -1326,7 +1457,7 @@ dhdpcie_bus_release_malloc(dhd_bus_t *bus, osl_t *osh) void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) { uint32 status; - unsigned long flags; + unsigned long flags, flags_bus; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1344,7 +1475,14 @@ void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) bus->dhd->busstate = DHD_BUS_DOWN; DHD_GENERAL_UNLOCK(bus->dhd, flags); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_set(&bus->dhd->block_bus, TRUE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + + DHD_BUS_LOCK(bus->bus_lock, flags_bus); dhdpcie_bus_intr_disable(bus); + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); + status = dhdpcie_bus_cfg_read_dword(bus, PCIIntstatus, 4); dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, status); @@ -1352,6 +1490,12 @@ void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) dhd_dpc_kill(bus->dhd); } +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_disable(dhd_bus_to_dev(bus)); + pm_runtime_set_suspended(dhd_bus_to_dev(bus)); + pm_runtime_enable(dhd_bus_to_dev(bus)); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + /* Clear rx control and wake any waiters */ dhd_os_set_ioctl_resp_timeout(IOCTL_DISABLE_TIMEOUT); dhd_wakeup_ioctl_event(bus->dhd, IOCTL_RETURN_ON_BUS_STOP); @@ -1360,140 +1504,14 @@ done: return; } -#ifdef DEVICE_TX_STUCK_DETECT -void -dhd_bus_send_msg_to_daemon(int reason) -{ - bcm_to_info_t to_info; - - to_info.magic = BCM_TO_MAGIC; - to_info.reason = reason; - - dhd_send_msg_to_daemon(NULL, (void *)&to_info, sizeof(bcm_to_info_t)); - return; -} - -/** - * scan the flow rings in active list to check if stuck and notify application - * The conditions for warn/stuck detection are - * 1. Flow ring is active - * 2. There are packets to be consumed by the consumer (wr != rd) - * If 1 and 2 are true, then - * 3. Warn, if Tx completion is not received for a duration of DEVICE_TX_STUCK_WARN_DURATION - * 4. Trap FW, if Tx completion is not received for a duration of DEVICE_TX_STUCK_DURATION - */ -static void -dhd_bus_device_tx_stuck_scan(dhd_bus_t *bus) -{ - uint32 tx_cmpl; - unsigned long list_lock_flags; - unsigned long ring_lock_flags; - dll_t *item, *prev; - flow_ring_node_t *flow_ring_node; - bool ring_empty; - bool active; - - DHD_FLOWRING_LIST_LOCK(bus->dhd->flowring_list_lock, list_lock_flags); - - for (item = dll_tail_p(&bus->flowring_active_list); - !dll_end(&bus->flowring_active_list, item); item = prev) { - - prev = dll_prev_p(item); - - flow_ring_node = dhd_constlist_to_flowring(item); - DHD_FLOWRING_LOCK(flow_ring_node->lock, ring_lock_flags); - tx_cmpl = flow_ring_node->tx_cmpl; - active = flow_ring_node->active; - ring_empty = dhd_prot_is_cmpl_ring_empty(bus->dhd, flow_ring_node->prot_info); - DHD_FLOWRING_UNLOCK(flow_ring_node->lock, ring_lock_flags); - - if (ring_empty) { - /* reset conters... etc */ - flow_ring_node->stuck_count = 0; - flow_ring_node->tx_cmpl_prev = tx_cmpl; - continue; - } - /** - * DEVICE_TX_STUCK_WARN_DURATION, DEVICE_TX_STUCK_DURATION are integer - * representation of time, to decide if a flow is in warn state or stuck. - * - * flow_ring_node->stuck_count is an integer counter representing how long - * tx_cmpl is not received though there are pending packets in the ring - * to be consumed by the dongle for that particular flow. - * - * This method of determining time elapsed is helpful in sleep/wake scenarios. - * If host sleeps and wakes up, that sleep time is not considered into - * stuck duration. - */ - if ((tx_cmpl == flow_ring_node->tx_cmpl_prev) && active) { - - flow_ring_node->stuck_count++; - - DHD_ERROR(("%s: flowid: %d tx_cmpl: %u tx_cmpl_prev: %u stuck_count: %d\n", - __func__, flow_ring_node->flowid, tx_cmpl, - flow_ring_node->tx_cmpl_prev, flow_ring_node->stuck_count)); - - switch (flow_ring_node->stuck_count) { - case DEVICE_TX_STUCK_WARN_DURATION: - /** - * Notify Device Tx Stuck Notification App about the - * device Tx stuck warning for this flowid. - * App will collect the logs required. - */ - DHD_ERROR(("stuck warning for flowid: %d sent to app\n", - flow_ring_node->flowid)); - dhd_bus_send_msg_to_daemon(REASON_DEVICE_TX_STUCK_WARNING); - break; - case DEVICE_TX_STUCK_DURATION: - /** - * Notify Device Tx Stuck Notification App about the - * device Tx stuck info for this flowid. - * App will collect the logs required. - */ - DHD_ERROR(("stuck information for flowid: %d sent to app\n", - flow_ring_node->flowid)); - dhd_bus_send_msg_to_daemon(REASON_DEVICE_TX_STUCK); - break; - default: - break; - } - } else { - flow_ring_node->tx_cmpl_prev = tx_cmpl; - flow_ring_node->stuck_count = 0; - } - } - DHD_FLOWRING_LIST_UNLOCK(bus->dhd->flowring_list_lock, list_lock_flags); -} /** - * schedules dhd_bus_device_tx_stuck_scan after DEVICE_TX_STUCK_CKECK_TIMEOUT, - * to determine if any flowid is stuck. + * Watchdog timer function. + * @param dhd Represents a specific hardware (dongle) instance that this DHD manages */ -static void -dhd_bus_device_stuck_scan(dhd_bus_t *bus) -{ - uint32 time_stamp; /* in millisec */ - uint32 diff; - - /* Need not run the algorith if Dongle has trapped */ - if (bus->dhd->dongle_trap_occured) { - return; - } - time_stamp = OSL_SYSUPTIME(); - diff = time_stamp - bus->device_tx_stuck_check; - if (diff > DEVICE_TX_STUCK_CKECK_TIMEOUT) { - dhd_bus_device_tx_stuck_scan(bus); - bus->device_tx_stuck_check = OSL_SYSUPTIME(); - } - return; -} -#endif /* DEVICE_TX_STUCK_DETECT */ - -/** Watchdog timer function */ bool dhd_bus_watchdog(dhd_pub_t *dhd) { unsigned long flags; - dhd_bus_t *bus; - bus = dhd->bus; + dhd_bus_t *bus = dhd->bus; DHD_GENERAL_LOCK(dhd, flags); if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd) || @@ -1508,53 +1526,18 @@ bool dhd_bus_watchdog(dhd_pub_t *dhd) dhdpcie_runtime_bus_wake(dhd, TRUE, __builtin_return_address(0)); #endif /* DHD_PCIE_RUNTIMEPM */ - - /* Poll for console output periodically */ if (dhd->busstate == DHD_BUS_DATA && - dhd_console_ms != 0 && !bus->d3_suspend_pending) { + dhd->dhd_console_ms != 0 && + bus->bus_low_power_state == DHD_BUS_NO_LOW_POWER_STATE) { bus->console.count += dhd_watchdog_ms; - if (bus->console.count >= dhd_console_ms) { - bus->console.count -= dhd_console_ms; + if (bus->console.count >= dhd->dhd_console_ms) { + bus->console.count -= dhd->dhd_console_ms; /* Make sure backplane clock is on */ if (dhdpcie_bus_readconsole(bus) < 0) - dhd_console_ms = 0; /* On error, stop trying */ - } - } - -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - /* If haven't communicated with device for a while, deassert the Device_Wake GPIO */ - if (dhd_doorbell_timeout != 0 && dhd->busstate == DHD_BUS_DATA && - dhd->up && dhd_timeout_expired(&bus->doorbell_timer)) { - dhd_bus_set_device_wake(bus, FALSE); - } -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - if (bus->ds_exit_timeout) { - bus->ds_exit_timeout --; - if (bus->ds_exit_timeout == 1) { - DHD_ERROR(("DS-EXIT TIMEOUT\n")); - bus->ds_exit_timeout = 0; - bus->inband_ds_exit_to_cnt++; - } - } - if (bus->host_sleep_exit_timeout) { - bus->host_sleep_exit_timeout --; - if (bus->host_sleep_exit_timeout == 1) { - DHD_ERROR(("HOST_SLEEP-EXIT TIMEOUT\n")); - bus->host_sleep_exit_timeout = 0; - bus->inband_host_sleep_exit_to_cnt++; - } + dhd->dhd_console_ms = 0; /* On error, stop trying */ } } -#endif /* PCIE_INB_DW */ - -#ifdef DEVICE_TX_STUCK_DETECT - if (dhd->bus->dev_tx_stuck_monitor == TRUE) { - dhd_bus_device_stuck_scan(dhd->bus); - } -#endif /* DEVICE_TX_STUCK_DETECT */ DHD_GENERAL_LOCK(dhd, flags); DHD_BUS_BUSY_CLEAR_IN_WD(dhd); @@ -1678,8 +1661,8 @@ static int concate_revision_bcm4359(dhd_bus_t *bus, char *fw_path, char *nv_path #define CHIP_REV_A1 2 #define CHIP_REV_B0 3 #define CHIP_REV_B1 4 -#define CHIP_REV_C0 5 -#define CHIP_REV_C1 6 +#define CHIP_REV_B2 5 +#define CHIP_REV_C0 6 #define BOARD_TYPE_EPA 0x080f #define BOARD_TYPE_IPA 0x0827 #define BOARD_TYPE_IPA_OLD 0x081a @@ -1741,7 +1724,15 @@ naming_info_t bcm4361_naming_table[] = { { {"r031_1kl_b0"}, {"_r030_b0"}, {"_b0"} }, /* exceptional case : r31 -> r30 */ { {"r032_1kl_b0"}, {"_r032_b0"}, {"_b0"} }, { {"r033_1kl_b0"}, {"_r033_b0"}, {"_b0"} }, - { {"r034_1kl_b0"}, {"_r034_b0"}, {"_b0"} } + { {"r034_1kl_b0"}, {"_r034_b0"}, {"_b0"} }, + { {"r02a_e32a_b2"}, {"_r02a_b2"}, {"_b2"} }, + { {"r02b_e32a_b2"}, {"_r02b_b2"}, {"_b2"} }, + { {"r020_1qw_b2"}, {"_r020_b2"}, {"_b2"} }, + { {"r021_1qw_b2"}, {"_r021_b2"}, {"_b2"} }, + { {"r022_1qw_b2"}, {"_r022_b2"}, {"_b2"} }, + { {"r031_1qw_b2"}, {"_r031_b2"}, {"_b2"} }, + { {"r032_1qw_b2"}, {"_r032_b2"}, {"_b2"} }, + { {"r041_1qw_b2"}, {"_r041_b2"}, {"_b2"} } }; static naming_info_t * @@ -1810,13 +1801,13 @@ dhd_parse_board_information_bcm4361(dhd_bus_t *bus, int *boardtype, for (i = 0; i < ARRAYSIZE(boardtype_backplane_addr); i++) { /* Write new OTP and PMU configuration */ if (si_backplane_access(bus->sih, boardtype_backplane_addr[i], sizeof(int), - &boardtype_backplane_data[i], FALSE) < 0) { + &boardtype_backplane_data[i], FALSE) != BCME_OK) { DHD_ERROR(("invalid size/addr combination\n")); return BCME_ERROR; } if (si_backplane_access(bus->sih, boardtype_backplane_addr[i], sizeof(int), - &int_val, TRUE) < 0) { + &int_val, TRUE) != BCME_OK) { DHD_ERROR(("invalid size/addr combination\n")); return BCME_ERROR; } @@ -1828,7 +1819,7 @@ dhd_parse_board_information_bcm4361(dhd_bus_t *bus, int *boardtype, /* read tuple raw data */ for (i = 0; i < CIS_TUPLE_MAX_COUNT; i++) { if (si_backplane_access(bus->sih, CIS_TUPLE_START_ADDRESS + i * sizeof(uint32), - sizeof(uint32), &raw_data[i], TRUE) < 0) { + sizeof(uint32), &raw_data[i], TRUE) != BCME_OK) { break; } } @@ -1885,9 +1876,11 @@ dhd_find_naming_info_by_chip_rev(naming_info_t table[], int table_size, naming_info_t *info = &table[0]; char *cid_info = NULL; - if (bus) { - chip_rev = bus->sih->chiprev; + if (!bus || !bus->sih) { + DHD_ERROR(("%s:bus(%p) or bus->sih is NULL\n", __FUNCTION__, bus)); + return NULL; } + chip_rev = bus->sih->chiprev; if (dhd_parse_board_information_bcm4361(bus, &board_type, vid, &vid_length) != BCME_OK) { @@ -2015,7 +2008,19 @@ dhd_get_chipid(dhd_pub_t *dhd) return 0; } -/* Download firmware image and nvram image */ +/** + * Loads firmware given by caller supplied path and nvram image into PCIe dongle. + * + * BCM_REQUEST_FW specific : + * Given the chip type, determines the to be used file paths within /lib/firmware/brcm/ containing + * firmware and nvm for that chip. If the download fails, retries download with a different nvm file + * + * BCMEMBEDIMAGE specific: + * If bus->fw_path is empty, or if the download of bus->fw_path failed, firmware contained in header + * file will be used instead. + * + * @return BCME_OK on success + */ int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, char *pfw_path, char *pnv_path) @@ -2045,6 +2050,19 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, return ret; } +/** + * Loads firmware given by 'bus->fw_path' into PCIe dongle. + * + * BCM_REQUEST_FW specific : + * Given the chip type, determines the to be used file paths within /lib/firmware/brcm/ containing + * firmware and nvm for that chip. If the download fails, retries download with a different nvm file + * + * BCMEMBEDIMAGE specific: + * If bus->fw_path is empty, or if the download of bus->fw_path failed, firmware contained in header + * file will be used instead. + * + * @return BCME_OK on success + */ static int dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) { @@ -2084,15 +2102,20 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh) #endif /* BCM_REQUEST_FW */ DHD_OS_WAKE_LOCK(bus->dhd); - ret = _dhdpcie_download_firmware(bus); DHD_OS_WAKE_UNLOCK(bus->dhd); return ret; -} +} /* dhdpcie_download_firmware */ #define DHD_MEMORY_SET_PATTERN 0xAA +/** + * Downloads a file containing firmware into dongle memory. In case of a .bea file, the DHD + * is updated with the event logging partitions within that file as well. + * + * @param pfw_path Path to .bin or .bea file + */ static int dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path) { @@ -2107,17 +2130,14 @@ dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path) bool store_reset; char *imgbuf = NULL; uint8 *memblock = NULL, *memptr; - int offset_end = bus->ramsize; -#ifndef DHD_EFI DHD_ERROR(("%s: download firmware %s\n", __FUNCTION__, pfw_path)); -#endif /* DHD_EFI */ /* Should succeed in opening image if it is actually given through registry * entry or in module param. */ - imgbuf = dhd_os_open_image(pfw_path); + imgbuf = dhd_os_open_image1(bus->dhd, pfw_path); if (imgbuf == NULL) { goto err; } @@ -2155,7 +2175,6 @@ dhdpcie_download_code_file(struct dhd_bus *bus, char *pfw_path) /* check if CR4/CA7 */ store_reset = (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) || si_setcore(bus->sih, ARMCA7_CORE_ID, 0)); - /* Download image with MEMBLOCK size */ while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, imgbuf))) { if (len < 0) { @@ -2255,7 +2274,7 @@ err: DHD_OS_PREFREE(bus->dhd, p_org_fw, org_fw_size); #else VMFREE(bus->dhd->osh, p_org_fw, org_fw_size); -#endif +#endif // endif } #endif /* DHD_FW_MEM_CORRUPTION */ if (memblock) { @@ -2263,7 +2282,7 @@ err: } if (imgbuf) { - dhd_os_close_image(imgbuf); + dhd_os_close_image1(bus->dhd, imgbuf); } return bcmerror; @@ -2286,11 +2305,7 @@ dhdpcie_download_nvram(struct dhd_bus *bus) bool local_alloc = FALSE; pnv_path = bus->nv_path; -#ifdef BCMEMBEDIMAGE - nvram_file_exists = TRUE; -#else nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0')); -#endif /* First try UEFI */ len = MAX_NVRAMBUF_SIZE; @@ -2319,26 +2334,12 @@ dhdpcie_download_nvram(struct dhd_bus *bus) if (len > 0 && len <= MAX_NVRAMBUF_SIZE && memblock != NULL) { bufp = (char *) memblock; -#ifdef CACHE_FW_IMAGES - if (bus->processed_nvram_params_len) { - len = bus->processed_nvram_params_len; - } - - if (!bus->processed_nvram_params_len) { - bufp[len] = 0; - if (nvram_uefi_exists || nvram_file_exists) { - len = process_nvram_vars(bufp, len); - bus->processed_nvram_params_len = len; - } - } else -#else { bufp[len] = 0; if (nvram_uefi_exists || nvram_file_exists) { len = process_nvram_vars(bufp, len); } } -#endif /* CACHE_FW_IMAGES */ DHD_ERROR(("%s: process_nvram_vars len %d\n", __FUNCTION__, len)); #ifdef CUSTOMER_HW4_DEBUG @@ -2363,7 +2364,6 @@ dhdpcie_download_nvram(struct dhd_bus *bus) } } - err: if (memblock) { if (local_alloc) { @@ -2376,140 +2376,8 @@ err: return bcmerror; } - -#ifdef BCMEMBEDIMAGE -int -dhdpcie_download_code_array(struct dhd_bus *bus) -{ - int bcmerror = -1; - int offset = 0; - unsigned char *p_dlarray = NULL; - unsigned int dlarray_size = 0; - unsigned int downloded_len, remaining_len, len; - char *p_dlimagename, *p_dlimagever, *p_dlimagedate; - uint8 *memblock = NULL, *memptr; - - downloded_len = 0; - remaining_len = 0; - len = 0; - -#ifdef DHD_EFI - p_dlarray = rtecdc_fw_arr; - dlarray_size = sizeof(rtecdc_fw_arr); -#else - p_dlarray = dlarray; - dlarray_size = sizeof(dlarray); - p_dlimagename = dlimagename; - p_dlimagever = dlimagever; - p_dlimagedate = dlimagedate; -#endif /* DHD_EFI */ - -#ifndef DHD_EFI - if ((p_dlarray == 0) || (dlarray_size == 0) ||(dlarray_size > bus->ramsize) || - (p_dlimagename == 0) || (p_dlimagever == 0) || (p_dlimagedate == 0)) - goto err; -#endif /* DHD_EFI */ - - memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); - if (memblock == NULL) { - DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK)); - goto err; - } - if ((uint32)(uintptr)memblock % DHD_SDALIGN) - memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); - - while (downloded_len < dlarray_size) { - remaining_len = dlarray_size - downloded_len; - if (remaining_len >= MEMBLOCK) - len = MEMBLOCK; - else - len = remaining_len; - - memcpy(memptr, (p_dlarray + downloded_len), len); - /* check if CR4/CA7 */ - if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0) || - si_setcore(bus->sih, SYSMEM_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 = dhdpcie_bus_membytes(bus, TRUE, offset, (uint8 *)memptr, len); - downloded_len += len; - if (bcmerror) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - offset += MEMBLOCK; - } - -#ifdef DHD_DEBUG - /* Upload and compare the downloaded code */ - { - unsigned char *ularray = NULL; - unsigned int uploded_len; - uploded_len = 0; - bcmerror = -1; - ularray = MALLOC(bus->dhd->osh, dlarray_size); - if (ularray == NULL) - goto upload_err; - /* Upload image to verify downloaded contents. */ - offset = bus->dongle_ram_base; - memset(ularray, 0xaa, dlarray_size); - while (uploded_len < dlarray_size) { - remaining_len = dlarray_size - uploded_len; - if (remaining_len >= MEMBLOCK) - len = MEMBLOCK; - else - len = remaining_len; - bcmerror = dhdpcie_bus_membytes(bus, FALSE, offset, - (uint8 *)(ularray + uploded_len), len); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto upload_err; - } - - uploded_len += len; - offset += MEMBLOCK; - } -#ifdef DHD_EFI - if (memcmp(p_dlarray, ularray, dlarray_size)) { - DHD_ERROR(("%s: Downloaded image is corrupted ! \n", __FUNCTION__)); - goto upload_err; - } else - DHD_ERROR(("%s: Download, Upload and compare succeeded .\n", __FUNCTION__)); -#else - if (memcmp(p_dlarray, ularray, dlarray_size)) { - DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n", - __FUNCTION__, p_dlimagename, p_dlimagever, p_dlimagedate)); - goto upload_err; - - } else - DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n", - __FUNCTION__, p_dlimagename, p_dlimagever, p_dlimagedate)); -#endif /* DHD_EFI */ - -upload_err: - if (ularray) - MFREE(bus->dhd->osh, ularray, dlarray_size); - } -#endif /* DHD_DEBUG */ -err: - - if (memblock) - MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN); - - return bcmerror; -} /* dhdpcie_download_code_array */ -#endif /* BCMEMBEDIMAGE */ - - -static int -dhdpcie_ramsize_read_image(struct dhd_bus *bus, char *buf, int len) +static int +dhdpcie_ramsize_read_image(struct dhd_bus *bus, char *buf, int len) { int bcmerror = BCME_ERROR; char *imgbuf = NULL; @@ -2519,7 +2387,8 @@ dhdpcie_ramsize_read_image(struct dhd_bus *bus, char *buf, int len) /* External image takes precedence if specified */ if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { - imgbuf = dhd_os_open_image(bus->fw_path); + // opens and seeks to correct file offset: + imgbuf = dhd_os_open_image1(bus->dhd, bus->fw_path); if (imgbuf == NULL) { DHD_ERROR(("%s: Failed to open firmware file\n", __FUNCTION__)); goto err; @@ -2536,12 +2405,11 @@ dhdpcie_ramsize_read_image(struct dhd_bus *bus, char *buf, int len) err: if (imgbuf) - dhd_os_close_image(imgbuf); + dhd_os_close_image1(bus->dhd, imgbuf); return bcmerror; } - /* The ramsize can be changed in the dongle image, for example 4365 chip share the sysmem * with BMC and we can adjust how many sysmem belong to CA7 during dongle compilation. * So in DHD we need to detect this case and update the correct dongle RAMSIZE as well. @@ -2575,13 +2443,11 @@ dhdpcie_ramsize_adj(struct dhd_bus *bus) return; } -#ifndef BCMEMBEDIMAGE /* Out immediately if no image to download */ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { DHD_ERROR(("%s: no fimrware file\n", __FUNCTION__)); return; } -#endif /* !BCMEMBEDIMAGE */ /* Get maximum RAMSIZE info search length */ for (i = 0; ; i++) { @@ -2605,26 +2471,7 @@ dhdpcie_ramsize_adj(struct dhd_bus *bus) /* External image takes precedence if specified */ if (dhdpcie_ramsize_read_image(bus, (char *)memptr, search_len) != BCME_OK) { -#if defined(BCMEMBEDIMAGE) && !defined(DHD_EFI) - unsigned char *p_dlarray = NULL; - unsigned int dlarray_size = 0; - char *p_dlimagename, *p_dlimagever, *p_dlimagedate; - - p_dlarray = dlarray; - dlarray_size = sizeof(dlarray); - p_dlimagename = dlimagename; - p_dlimagever = dlimagever; - p_dlimagedate = dlimagedate; - - if ((p_dlarray == 0) || (dlarray_size == 0) || (p_dlimagename == 0) || - (p_dlimagever == 0) || (p_dlimagedate == 0)) - goto err; - - ramsizeptr = p_dlarray; - ramsizelen = dlarray_size; -#else goto err; -#endif /* BCMEMBEDIMAGE && !DHD_EFI */ } else { ramsizeptr = memptr; @@ -2658,8 +2505,16 @@ err: MFREE(bus->dhd->osh, memptr, search_len); return; -} /* _dhdpcie_download_firmware */ +} /* dhdpcie_ramsize_adj */ +/** + * Downloads firmware file given by 'bus->fw_path' into PCIe dongle + * + * BCMEMBEDIMAGE specific: + * If bus->fw_path is empty, or if the download of bus->fw_path failed, firmware contained in header + * file will be used instead. + * + */ static int _dhdpcie_download_firmware(struct dhd_bus *bus) { @@ -2670,12 +2525,8 @@ _dhdpcie_download_firmware(struct dhd_bus *bus) /* Out immediately if no image to download */ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else DHD_ERROR(("%s: no fimrware file\n", __FUNCTION__)); return 0; -#endif } /* Adjust ram size */ dhdpcie_ramsize_adj(bus); @@ -2689,32 +2540,18 @@ _dhdpcie_download_firmware(struct dhd_bus *bus) /* External image takes precedence if specified */ if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { if (dhdpcie_download_code_file(bus, bus->fw_path)) { - DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__)); -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else + DHD_ERROR(("%s:%d dongle image file download failed\n", __FUNCTION__, + __LINE__)); goto err; -#endif } else { embed = FALSE; dlok = TRUE; } } -#ifdef BCMEMBEDIMAGE - if (embed) { - if (dhdpcie_download_code_array(bus)) { - DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__)); - goto err; - } else { - dlok = TRUE; - } - } -#else BCM_REFERENCE(embed); -#endif if (!dlok) { - DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__)); + DHD_ERROR(("%s:%d dongle image download failed\n", __FUNCTION__, __LINE__)); goto err; } @@ -2722,10 +2559,9 @@ _dhdpcie_download_firmware(struct dhd_bus *bus) /* If a valid nvram_arry is specified as above, it can be passed down to dongle */ /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */ - /* External nvram takes precedence if specified */ if (dhdpcie_download_nvram(bus)) { - DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__)); + DHD_ERROR(("%s:%d dongle nvram file download failed\n", __FUNCTION__, __LINE__)); goto err; } @@ -2870,7 +2706,6 @@ dhd_bus_dump_console_buffer(dhd_bus_t *bus) line[n] = ch; } - if (n > 0) { if (line[n - 1] == '\r') n--; @@ -2890,6 +2725,11 @@ exit: return; } +/** + * Opens the file given by bus->fw_path, reads part of the file into a buffer and closes the file. + * + * @return BCME_OK on success + */ static int dhdpcie_checkdied(dhd_bus_t *bus, char *data, uint size) { @@ -2901,6 +2741,7 @@ dhdpcie_checkdied(dhd_bus_t *bus, char *data, uint size) pciedev_shared_t *local_pciedev_shared = bus->pcie_sh; struct bcmstrbuf strbuf; unsigned long flags; + bool dongle_trap_occured = FALSE; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -2988,57 +2829,49 @@ dhdpcie_checkdied(dhd_bus_t *bus, char *data, uint size) if (bus->pcie_sh->flags & PCIE_SHARED_TRAP) { trap_t *tr = &bus->dhd->last_trap_info; - bus->dhd->dongle_trap_occured = TRUE; + dongle_trap_occured = TRUE; if ((bcmerror = dhdpcie_bus_membytes(bus, FALSE, bus->pcie_sh->trap_addr, (uint8*)tr, sizeof(trap_t))) < 0) { + bus->dhd->dongle_trap_occured = TRUE; goto done; } dhd_bus_dump_trap_info(bus, &strbuf); - - dhd_bus_dump_console_buffer(bus); } } if (bus->pcie_sh->flags & (PCIE_SHARED_ASSERT | PCIE_SHARED_TRAP)) { - printf("%s: %s\n", __FUNCTION__, strbuf.origbuf); -#ifdef REPORT_FATAL_TIMEOUTS - /** - * stop the timers as FW trapped - */ - if (dhd_stop_scan_timer(bus->dhd)) { - DHD_ERROR(("dhd_stop_scan_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_bus_timer(bus->dhd)) { - DHD_ERROR(("dhd_stop_bus_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_cmd_timer(bus->dhd)) { - DHD_ERROR(("dhd_stop_cmd_timer failed\n")); - ASSERT(0); - } - if (dhd_stop_join_timer(bus->dhd)) { - DHD_ERROR(("dhd_stop_join_timer failed\n")); - ASSERT(0); - } -#endif /* REPORT_FATAL_TIMEOUTS */ + DHD_FWLOG(("%s: %s\n", __FUNCTION__, strbuf.origbuf)); + /* wake up IOCTL wait event */ + dhd_wakeup_ioctl_event(bus->dhd, IOCTL_RETURN_ON_TRAP); + + dhd_bus_dump_console_buffer(bus); dhd_prot_debug_info_print(bus->dhd); #if defined(DHD_FW_COREDUMP) /* save core dump or write to a file */ if (bus->dhd->memdump_enabled) { +#ifdef DHD_SSSR_DUMP + if (bus->dhd->sssr_inited) { + dhdpcie_sssr_dump(bus->dhd); + } +#endif /* DHD_SSSR_DUMP */ bus->dhd->memdump_type = DUMP_TYPE_DONGLE_TRAP; dhdpcie_mem_dump(bus); } #endif /* DHD_FW_COREDUMP */ - /* wake up IOCTL wait event */ - dhd_wakeup_ioctl_event(bus->dhd, IOCTL_RETURN_ON_TRAP); + /* set the trap occured flag only after all the memdump, + * logdump and sssr dump collection has been scheduled + */ + if (dongle_trap_occured) + bus->dhd->dongle_trap_occured = TRUE; +#ifdef WL_CFGVENDOR_SEND_HANG_EVENT + copy_hang_info_trap(bus->dhd); +#endif /* WL_CFGVENDOR_SEND_HANG_EVENT */ dhd_schedule_reset(bus->dhd); - } DHD_GENERAL_LOCK(bus->dhd, flags); @@ -3055,7 +2888,6 @@ done: return bcmerror; } /* dhdpcie_checkdied */ - /* Custom copy of dhdpcie_mem_dump() that can be called at interrupt level */ void dhdpcie_mem_dump_bugcheck(dhd_bus_t *bus, uint8 *buf) { @@ -3101,7 +2933,6 @@ void dhdpcie_mem_dump_bugcheck(dhd_bus_t *bus, uint8 *buf) return; } - #if defined(DHD_FW_COREDUMP) static int dhdpcie_mem_dump(dhd_bus_t *bus) @@ -3123,6 +2954,11 @@ dhdpcie_mem_dump(dhd_bus_t *bus) } #endif /* SUPPORT_LINKDOWN_RECOVERY */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + if (pm_runtime_get_sync(dhd_bus_to_dev(bus)) < 0) + return BCME_ERROR; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + /* Get full mem size */ size = bus->ramsize; buf = dhd_get_fwdump_buf(bus->dhd, size); @@ -3140,7 +2976,9 @@ dhdpcie_mem_dump(dhd_bus_t *bus) if ((ret = dhdpcie_bus_membytes(bus, FALSE, start, databuf, read_size))) { DHD_ERROR(("%s: Error membytes %d\n", __FUNCTION__, ret)); +#ifdef DHD_DEBUG_UART bus->dhd->memdump_success = FALSE; +#endif /* DHD_DEBUG_UART */ return BCME_ERROR; } DHD_TRACE((".")); @@ -3150,11 +2988,18 @@ dhdpcie_mem_dump(dhd_bus_t *bus) start += read_size; databuf += read_size; } +#ifdef DHD_DEBUG_UART bus->dhd->memdump_success = TRUE; +#endif /* DHD_DEBUG_UART */ dhd_schedule_memdump(bus->dhd, buf, bus->ramsize); /* buf, actually soc_ram free handled in dhd_{free,clear} */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_mark_last_busy(dhd_bus_to_dev(bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(bus)); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + return ret; } @@ -3162,17 +3007,12 @@ int dhd_bus_mem_dump(dhd_pub_t *dhdp) { dhd_bus_t *bus = dhdp->bus; + int ret = BCME_ERROR; if (dhdp->busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s bus is down\n", __FUNCTION__)); return BCME_ERROR; } -#ifdef DHD_PCIE_RUNTIMEPM - if (dhdp->memdump_type == DUMP_TYPE_BY_SYSDUMP) { - DHD_ERROR(("%s : bus wakeup by SYSDUMP\n", __FUNCTION__)); - dhdpcie_runtime_bus_wake(dhdp, TRUE, __builtin_return_address(0)); - } -#endif /* DHD_PCIE_RUNTIMEPM */ if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(dhdp)) { DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state, so skip\n", @@ -3180,7 +3020,10 @@ dhd_bus_mem_dump(dhd_pub_t *dhdp) return BCME_ERROR; } - return dhdpcie_mem_dump(bus); + DHD_OS_WAKE_LOCK(dhdp); + ret = dhdpcie_mem_dump(bus); + DHD_OS_WAKE_UNLOCK(dhdp); + return ret; } int @@ -3201,9 +3044,7 @@ dhd_dongle_mem_dump(void) dhdpcie_runtime_bus_wake(g_dhd_bus->dhd, TRUE, __builtin_return_address(0)); #endif /* DHD_PCIE_RUNTIMEPM */ - DHD_OS_WAKE_LOCK(g_dhd_bus->dhd); dhd_bus_mem_dump(g_dhd_bus->dhd); - DHD_OS_WAKE_UNLOCK(g_dhd_bus->dhd); return 0; } EXPORT_SYMBOL(dhd_dongle_mem_dump); @@ -3223,7 +3064,7 @@ dhd_socram_dump(dhd_bus_t *bus) return 0; #else return -1; -#endif +#endif // endif } /** @@ -3242,7 +3083,6 @@ dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uin return BCME_ERROR; } - /* Detect endianness. */ little_endian = *(char *)&detect_endian_flag; @@ -3320,7 +3160,7 @@ dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs) int ret = BCME_OK; #ifdef DHD_LOSSLESS_ROAMING dhd_pub_t *dhdp = bus->dhd; -#endif +#endif // endif DHD_INFO(("%s: flow_id is %d\n", __FUNCTION__, flow_id)); /* ASSERT on flow_id */ @@ -3383,19 +3223,17 @@ dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs) eh = (struct ether_header *) pktdata; if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) { uint8 prio = (uint8)PKTPRIO(txp); - /* Restore to original priority for 802.1X packet */ if (prio == PRIO_8021D_NC) { PKTSETPRIO(txp, dhdp->prio_8021x); } } #endif /* DHD_LOSSLESS_ROAMING */ - /* Attempt to transfer packet over flow ring */ ret = dhd_prot_txdata(bus->dhd, txp, flow_ring_node->flow_info.ifindex); if (ret != BCME_OK) { /* may not have resources in flow ring */ DHD_INFO(("%s: Reinserrt %d\n", __FUNCTION__, ret)); - dhd_prot_txdata_write_flush(bus->dhd, flow_id, FALSE); + dhd_prot_txdata_write_flush(bus->dhd, flow_id); /* reinsert at head */ dhd_flow_queue_reinsert(bus->dhd, queue, txp); DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); @@ -3405,7 +3243,7 @@ dhd_bus_schedule_queue(struct dhd_bus *bus, uint16 flow_id, bool txs) } } - dhd_prot_txdata_write_flush(bus->dhd, flow_id, FALSE); + dhd_prot_txdata_write_flush(bus->dhd, flow_id); DHD_FLOWRING_UNLOCK(flow_ring_node->lock, flags); } @@ -3533,30 +3371,20 @@ dhd_bus_txdata(struct dhd_bus *bus, void *txp, uint8 ifidx) toss: DHD_INFO(("%s: Toss %d\n", __FUNCTION__, ret)); -/* for EFI, pass the 'send' flag as false, to avoid enqueuing the failed tx pkt -* into the Tx done queue -*/ -#ifdef DHD_EFI - PKTCFREE(bus->dhd->osh, txp, FALSE); -#else PKTCFREE(bus->dhd->osh, txp, TRUE); -#endif return ret; } /* dhd_bus_txdata */ - void dhd_bus_stop_queue(struct dhd_bus *bus) { dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); - bus->bus_flowctrl = TRUE; } void dhd_bus_start_queue(struct dhd_bus *bus) { dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); - bus->bus_flowctrl = TRUE; } /* Device console input function */ @@ -3671,7 +3499,7 @@ void dhd_bus_cmn_writeshared(dhd_bus_t *bus, void *data, uint32 len, uint8 type, uint16 ringid) { uint64 long_data; - uintptr tcm_offset; + ulong addr; /* dongle address */ DHD_INFO(("%s: writing to dongle type %d len %d\n", __FUNCTION__, type, len)); @@ -3682,179 +3510,118 @@ dhd_bus_cmn_writeshared(dhd_bus_t *bus, void *data, uint32 len, uint8 type, uint switch (type) { case D2H_DMA_SCRATCH_BUF: - { - pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr; + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, host_dma_scratch_buffer); long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)&(sh->host_dma_scratch_buffer); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case D2H_DMA_SCRATCH_BUF_LEN : - { - pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr; - tcm_offset = (uintptr)&(sh->host_dma_scratch_buffer_len); - dhdpcie_bus_wtcm32(bus, - (ulong)tcm_offset, (uint32) HTOL32(*(uint32 *)data)); + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, host_dma_scratch_buffer_len); + dhdpcie_bus_wtcm32(bus, addr, (uint32) HTOL32(*(uint32 *)data)); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case H2D_DMA_INDX_WR_BUF: - { - pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh; - long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)shmem->rings_info_ptr; - tcm_offset += OFFSETOF(ring_info_t, h2d_w_idx_hostaddr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_RING_INFO_MEMBER_ADDR(bus, h2d_w_idx_hostaddr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case H2D_DMA_INDX_RD_BUF: - { - pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh; long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)shmem->rings_info_ptr; - tcm_offset += OFFSETOF(ring_info_t, h2d_r_idx_hostaddr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_RING_INFO_MEMBER_ADDR(bus, h2d_r_idx_hostaddr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case D2H_DMA_INDX_WR_BUF: - { - pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh; long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)shmem->rings_info_ptr; - tcm_offset += OFFSETOF(ring_info_t, d2h_w_idx_hostaddr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_RING_INFO_MEMBER_ADDR(bus, d2h_w_idx_hostaddr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case D2H_DMA_INDX_RD_BUF: - { - pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh; long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)shmem->rings_info_ptr; - tcm_offset += OFFSETOF(ring_info_t, d2h_r_idx_hostaddr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_RING_INFO_MEMBER_ADDR(bus, d2h_r_idx_hostaddr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case H2D_IFRM_INDX_WR_BUF: - { - pciedev_shared_t *shmem = (pciedev_shared_t *)bus->pcie_sh; - long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)shmem->rings_info_ptr; - tcm_offset += OFFSETOF(ring_info_t, ifrm_w_idx_hostaddr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_RING_INFO_MEMBER_ADDR(bus, ifrm_w_idx_hostaddr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8*) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; - } case RING_ITEM_LEN : - tcm_offset = bus->ring_sh[ringid].ring_mem_addr; - tcm_offset += OFFSETOF(ring_mem_t, len_items); - dhdpcie_bus_wtcm16(bus, - (ulong)tcm_offset, (uint16) HTOL16(*(uint16 *)data)); + addr = DHD_RING_MEM_MEMBER_ADDR(bus, ringid, len_items); + dhdpcie_bus_wtcm16(bus, addr, (uint16) HTOL16(*(uint16 *)data)); break; case RING_MAX_ITEMS : - tcm_offset = bus->ring_sh[ringid].ring_mem_addr; - tcm_offset += OFFSETOF(ring_mem_t, max_item); - dhdpcie_bus_wtcm16(bus, - (ulong)tcm_offset, (uint16) HTOL16(*(uint16 *)data)); + addr = DHD_RING_MEM_MEMBER_ADDR(bus, ringid, max_item); + dhdpcie_bus_wtcm16(bus, addr, (uint16) HTOL16(*(uint16 *)data)); break; case RING_BUF_ADDR : long_data = HTOL64(*(uint64 *)data); - tcm_offset = bus->ring_sh[ringid].ring_mem_addr; - tcm_offset += OFFSETOF(ring_mem_t, base_addr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8 *) &long_data, len); + addr = DHD_RING_MEM_MEMBER_ADDR(bus, ringid, base_addr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *) &long_data, len); if (dhd_msg_level & DHD_INFO_VAL) { prhex(__FUNCTION__, data, len); } break; case RING_WR_UPD : - tcm_offset = bus->ring_sh[ringid].ring_state_w; - dhdpcie_bus_wtcm16(bus, - (ulong)tcm_offset, (uint16) HTOL16(*(uint16 *)data)); + addr = bus->ring_sh[ringid].ring_state_w; + dhdpcie_bus_wtcm16(bus, addr, (uint16) HTOL16(*(uint16 *)data)); break; case RING_RD_UPD : - tcm_offset = bus->ring_sh[ringid].ring_state_r; - dhdpcie_bus_wtcm16(bus, - (ulong)tcm_offset, (uint16) HTOL16(*(uint16 *)data)); + addr = bus->ring_sh[ringid].ring_state_r; + dhdpcie_bus_wtcm16(bus, addr, (uint16) HTOL16(*(uint16 *)data)); break; case D2H_MB_DATA: - dhdpcie_bus_wtcm32(bus, bus->d2h_mb_data_ptr_addr, - (uint32) HTOL32(*(uint32 *)data)); + addr = bus->d2h_mb_data_ptr_addr; + dhdpcie_bus_wtcm32(bus, addr, (uint32) HTOL32(*(uint32 *)data)); break; case H2D_MB_DATA: - dhdpcie_bus_wtcm32(bus, bus->h2d_mb_data_ptr_addr, - (uint32) HTOL32(*(uint32 *)data)); + addr = bus->h2d_mb_data_ptr_addr; + dhdpcie_bus_wtcm32(bus, addr, (uint32) HTOL32(*(uint32 *)data)); break; case HOST_API_VERSION: - { - pciedev_shared_t *sh = (pciedev_shared_t*) bus->shared_addr; - tcm_offset = (uintptr)sh + OFFSETOF(pciedev_shared_t, host_cap); - dhdpcie_bus_wtcm32(bus, - (ulong)tcm_offset, (uint32) HTOL32(*(uint32 *)data)); + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, host_cap); + dhdpcie_bus_wtcm32(bus, addr, (uint32) HTOL32(*(uint32 *)data)); break; - } case DNGL_TO_HOST_TRAP_ADDR: - { - pciedev_shared_t *sh = (pciedev_shared_t*) bus->shared_addr; long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)&(sh->host_trap_addr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, host_trap_addr); + dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *) &long_data, len); + DHD_INFO(("Wrote trap addr:0x%x\n", (uint32) HTOL32(*(uint32 *)data))); break; - } -#ifdef HOFFLOAD_MODULES - case WRT_HOST_MODULE_ADDR: - { - pciedev_shared_t *sh = (pciedev_shared_t*) bus->shared_addr; - long_data = HTOL64(*(uint64 *)data); - tcm_offset = (uintptr)&(sh->hoffload_addr); - dhdpcie_bus_membytes(bus, TRUE, - (ulong)tcm_offset, (uint8*) &long_data, len); - break; - } -#endif default: break; } @@ -3864,37 +3631,39 @@ dhd_bus_cmn_writeshared(dhd_bus_t *bus, void *data, uint32 len, uint8 type, uint void dhd_bus_cmn_readshared(dhd_bus_t *bus, void* data, uint8 type, uint16 ringid) { - ulong tcm_offset; + ulong addr; /* dongle address */ switch (type) { case RING_WR_UPD : - tcm_offset = bus->ring_sh[ringid].ring_state_w; - *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset)); + addr = bus->ring_sh[ringid].ring_state_w; + *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, addr)); break; + case RING_RD_UPD : - tcm_offset = bus->ring_sh[ringid].ring_state_r; - *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, tcm_offset)); + addr = bus->ring_sh[ringid].ring_state_r; + *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, addr)); break; + case TOTAL_LFRAG_PACKET_CNT : - { - pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr; - *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, - (ulong)(uintptr) &sh->total_lfrag_pkt_cnt)); + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, total_lfrag_pkt_cnt); + *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, addr)); break; - } + case H2D_MB_DATA: - *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->h2d_mb_data_ptr_addr)); + addr = bus->h2d_mb_data_ptr_addr; + *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, addr)); break; + case D2H_MB_DATA: - *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, bus->d2h_mb_data_ptr_addr)); + addr = bus->d2h_mb_data_ptr_addr; + *(uint32*)data = LTOH32(dhdpcie_bus_rtcm32(bus, addr)); break; + case MAX_HOST_RXBUFS : - { - pciedev_shared_t *sh = (pciedev_shared_t*)bus->shared_addr; - *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, - (ulong)(uintptr) &sh->max_host_rxbufs)); + addr = DHD_PCIE_SHARED_MEMBER_ADDR(bus, max_host_rxbufs); + *(uint16*)data = LTOH16(dhdpcie_bus_rtcm16(bus, addr)); break; - } + default : break; } @@ -3910,6 +3679,11 @@ dhd_bus_clearcounts(dhd_pub_t *dhdp) { } +/** + * @param params input buffer, NULL for 'set' operation. + * @param plen length of 'params' buffer, 0 for 'set' operation. + * @param arg output buffer + */ int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, void *params, int plen, void *arg, int len, bool set) @@ -3924,12 +3698,18 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, ASSERT(name); ASSERT(len >= 0); + if (!name || len < 0) + return BCME_BADARG; /* Get MUST have return space */ ASSERT(set || (arg && len)); + if (!(set || (arg && len))) + return BCME_BADARG; /* Set does NOT take qualifiers */ ASSERT(!set || (!params && !plen)); + if (!(!set || (!params && !plen))) + return BCME_BADARG; DHD_INFO(("%s: %s %s, len %d plen %d\n", __FUNCTION__, name, (set ? "set" : "get"), len, plen)); @@ -3939,7 +3719,6 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, goto exit; } - /* set up 'params' pointer in case this is a set command so that * the convenience int and bool code can be common to set and get */ @@ -4261,162 +4040,314 @@ done: #define PCIE_GEN2(sih) ((BUSTYPE((sih)->bustype) == PCI_BUS) && \ ((sih)->buscoretype == PCIE2_CORE_ID)) +#define PCIE_FLR_CAPAB_BIT 28 +#define PCIE_FUNCTION_LEVEL_RESET_BIT 15 +#define PCIE_SSRESET_STATUS_BIT 13 +#define PCIE_SSRESET_DISABLE_BIT 14 + +/* Change delays for only QT HW, FPGA and silicon uses same delay */ +#ifdef BCMQT_HW +#define DHD_FUNCTION_LEVEL_RESET_DELAY 300000u +#define DHD_SSRESET_STATUS_RETRY_DELAY 10000u +#else +#define DHD_FUNCTION_LEVEL_RESET_DELAY 55u /* 55 msec delay */ +#define DHD_SSRESET_STATUS_RETRY_DELAY 40u +#endif // endif +#define DHD_SSRESET_STATUS_RETRIES 50u + +int +dhd_bus_perform_flr(dhd_bus_t *bus, bool force_fail) +{ + bool flr_capab; + uint val; + int retry = 0; + + DHD_ERROR(("******** Perform FLR ********\n")); + + /* Read PCIE_CFG_DEVICE_CAPABILITY bit 28 to check FLR capability */ + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_DEVICE_CAPABILITY, sizeof(val)); + flr_capab = val & (1 << PCIE_FLR_CAPAB_BIT); + DHD_ERROR(("Read Device Capability: reg=0x%x read val=0x%x flr_capab=0x%x\n", + PCIE_CFG_DEVICE_CAPABILITY, val, flr_capab)); + if (!flr_capab) { + DHD_ERROR(("Chip does not support FLR\n")); + return BCME_UNSUPPORTED; + } + + /* Save pcie config space */ + DHD_ERROR(("Save Pcie Config Space\n")); + DHD_PCIE_CONFIG_SAVE(bus); + + /* Set bit 15 of PCIE_CFG_DEVICE_CONTROL */ + DHD_ERROR(("Set PCIE_FUNCTION_LEVEL_RESET_BIT(%d) of PCIE_CFG_DEVICE_CONTROL(0x%x)\n", + PCIE_FUNCTION_LEVEL_RESET_BIT, PCIE_CFG_DEVICE_CONTROL)); + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_DEVICE_CONTROL, sizeof(val)); + DHD_ERROR(("read_config: reg=0x%x read val=0x%x\n", PCIE_CFG_DEVICE_CONTROL, val)); + val = val | (1 << PCIE_FUNCTION_LEVEL_RESET_BIT); + DHD_ERROR(("write_config: reg=0x%x write val=0x%x\n", PCIE_CFG_DEVICE_CONTROL, val)); + OSL_PCI_WRITE_CONFIG(bus->osh, PCIE_CFG_DEVICE_CONTROL, sizeof(val), val); + + /* wait for DHD_FUNCTION_LEVEL_RESET_DELAY msec */ + DHD_ERROR(("Delay of %d msec\n", DHD_FUNCTION_LEVEL_RESET_DELAY)); + OSL_DELAY(DHD_FUNCTION_LEVEL_RESET_DELAY * 1000u); + + if (force_fail) { + DHD_ERROR(("Set PCIE_SSRESET_DISABLE_BIT(%d) of PCIE_CFG_SUBSYSTEM_CONTROL(0x%x)\n", + PCIE_SSRESET_DISABLE_BIT, PCIE_CFG_SUBSYSTEM_CONTROL)); + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_SUBSYSTEM_CONTROL, sizeof(val)); + DHD_ERROR(("read_config: reg=0x%x read val=0x%x\n", PCIE_CFG_SUBSYSTEM_CONTROL, + val)); + val = val | (1 << PCIE_SSRESET_DISABLE_BIT); + DHD_ERROR(("write_config: reg=0x%x write val=0x%x\n", PCIE_CFG_SUBSYSTEM_CONTROL, + val)); + OSL_PCI_WRITE_CONFIG(bus->osh, PCIE_CFG_SUBSYSTEM_CONTROL, sizeof(val), val); + + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_SUBSYSTEM_CONTROL, sizeof(val)); + DHD_ERROR(("read_config: reg=0x%x read val=0x%x\n", PCIE_CFG_SUBSYSTEM_CONTROL, + val)); + } + + /* Clear bit 15 of PCIE_CFG_DEVICE_CONTROL */ + DHD_ERROR(("Clear PCIE_FUNCTION_LEVEL_RESET_BIT(%d) of PCIE_CFG_DEVICE_CONTROL(0x%x)\n", + PCIE_FUNCTION_LEVEL_RESET_BIT, PCIE_CFG_DEVICE_CONTROL)); + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_DEVICE_CONTROL, sizeof(val)); + DHD_ERROR(("read_config: reg=0x%x read val=0x%x\n", PCIE_CFG_DEVICE_CONTROL, val)); + val = val & ~(1 << PCIE_FUNCTION_LEVEL_RESET_BIT); + DHD_ERROR(("write_config: reg=0x%x write val=0x%x\n", PCIE_CFG_DEVICE_CONTROL, val)); + OSL_PCI_WRITE_CONFIG(bus->osh, PCIE_CFG_DEVICE_CONTROL, sizeof(val), val); + + /* Wait till bit 13 of PCIE_CFG_SUBSYSTEM_CONTROL is cleared */ + DHD_ERROR(("Wait till PCIE_SSRESET_STATUS_BIT(%d) of PCIE_CFG_SUBSYSTEM_CONTROL(0x%x)" + "is cleared\n", PCIE_SSRESET_STATUS_BIT, PCIE_CFG_SUBSYSTEM_CONTROL)); + do { + val = OSL_PCI_READ_CONFIG(bus->osh, PCIE_CFG_SUBSYSTEM_CONTROL, sizeof(val)); + DHD_ERROR(("read_config: reg=0x%x read val=0x%x\n", + PCIE_CFG_SUBSYSTEM_CONTROL, val)); + val = val & (1 << PCIE_SSRESET_STATUS_BIT); + OSL_DELAY(DHD_SSRESET_STATUS_RETRY_DELAY); + } while (val && (retry++ < DHD_SSRESET_STATUS_RETRIES)); + + if (val) { + DHD_ERROR(("ERROR: reg=0x%x bit %d is not cleared\n", + PCIE_CFG_SUBSYSTEM_CONTROL, PCIE_SSRESET_STATUS_BIT)); + return BCME_ERROR; + } + + /* Restore pcie config space */ + DHD_ERROR(("Restore Pcie Config Space\n")); + DHD_PCIE_CONFIG_RESTORE(bus); + + DHD_ERROR(("******** FLR Succedeed ********\n")); + + return BCME_OK; +} + int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) { dhd_bus_t *bus = dhdp->bus; int bcmerror = 0; unsigned long flags; + unsigned long flags_bus; #ifdef CONFIG_ARCH_MSM int retry = POWERUP_MAX_RETRY; #endif /* CONFIG_ARCH_MSM */ - if (dhd_download_fw_on_driverload) { - bcmerror = dhd_bus_start(dhdp); - } else { - if (flag == TRUE) { /* Turn off WLAN */ - /* Removing Power */ - DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__)); + if (flag == TRUE) { /* Turn off WLAN */ + /* Removing Power */ + DHD_ERROR(("%s: == Power OFF ==\n", __FUNCTION__)); - bus->dhd->up = FALSE; + bus->dhd->up = FALSE; + + /* wait for other contexts to finish -- if required a call + * to OSL_DELAY for 1s can be added to give other contexts + * a chance to finish + */ + dhdpcie_advertise_bus_cleanup(bus->dhd); + + if (bus->dhd->busstate != DHD_BUS_DOWN) { +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_set(&bus->dhd->block_bus, TRUE); + dhd_flush_rx_tx_wq(bus->dhd); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ - if (bus->dhd->busstate != DHD_BUS_DOWN) { - dhdpcie_advertise_bus_cleanup(bus->dhd); - if (bus->intr) { - dhdpcie_bus_intr_disable(bus); - dhdpcie_free_irq(bus); - } #ifdef BCMPCIE_OOB_HOST_WAKE - /* Clean up any pending host wake IRQ */ - dhd_bus_oob_intr_set(bus->dhd, FALSE); - dhd_bus_oob_intr_unregister(bus->dhd); + /* Clean up any pending host wake IRQ */ + dhd_bus_oob_intr_set(bus->dhd, FALSE); + dhd_bus_oob_intr_unregister(bus->dhd); #endif /* BCMPCIE_OOB_HOST_WAKE */ - dhd_os_wd_timer(dhdp, 0); - dhd_bus_stop(bus, TRUE); - dhd_prot_reset(dhdp); - dhd_clear(dhdp); - dhd_bus_release_dongle(bus); - dhdpcie_bus_free_resource(bus); - bcmerror = dhdpcie_bus_disable_device(bus); - if (bcmerror) { - DHD_ERROR(("%s: dhdpcie_bus_disable_device: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + dhd_os_wd_timer(dhdp, 0); + dhd_bus_stop(bus, TRUE); + if (bus->intr) { + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + dhdpcie_bus_intr_disable(bus); + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); + dhdpcie_free_irq(bus); + } + dhd_deinit_bus_lock(bus); + dhd_bus_release_dongle(bus); + dhdpcie_bus_free_resource(bus); + bcmerror = dhdpcie_bus_disable_device(bus); + if (bcmerror) { + DHD_ERROR(("%s: dhdpcie_bus_disable_device: %d\n", + __FUNCTION__, bcmerror)); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_set(&bus->dhd->block_bus, FALSE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + } + /* Clean up protocol data after Bus Master Enable bit clear + * so that host can safely unmap DMA and remove the allocated buffers + * from the PKTID MAP. Some Applicantion Processors supported + * System MMU triggers Kernel panic when they detect to attempt to + * DMA-unmapped memory access from the devices which use the + * System MMU. Therefore, Kernel panic can be happened since it is + * possible that dongle can access to DMA-unmapped memory after + * calling the dhd_prot_reset(). + * For this reason, the dhd_prot_reset() and dhd_clear() functions + * should be located after the dhdpcie_bus_disable_device(). + */ + dhd_prot_reset(dhdp); + dhd_clear(dhdp); #ifdef CONFIG_ARCH_MSM - bcmerror = dhdpcie_bus_clock_stop(bus); - if (bcmerror) { - DHD_ERROR(("%s: host clock stop failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + bcmerror = dhdpcie_bus_clock_stop(bus); + if (bcmerror) { + DHD_ERROR(("%s: host clock stop failed: %d\n", + __FUNCTION__, bcmerror)); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_set(&bus->dhd->block_bus, FALSE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + goto done; + } #endif /* CONFIG_ARCH_MSM */ - DHD_GENERAL_LOCK(bus->dhd, flags); - bus->dhd->busstate = DHD_BUS_DOWN; - DHD_GENERAL_UNLOCK(bus->dhd, flags); - } else { - if (bus->intr) { - dhdpcie_free_irq(bus); - } + DHD_GENERAL_LOCK(bus->dhd, flags); + bus->dhd->busstate = DHD_BUS_DOWN; + DHD_GENERAL_UNLOCK(bus->dhd, flags); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + atomic_set(&bus->dhd->block_bus, FALSE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + } else { + if (bus->intr) { + dhdpcie_free_irq(bus); + } #ifdef BCMPCIE_OOB_HOST_WAKE - /* Clean up any pending host wake IRQ */ - dhd_bus_oob_intr_set(bus->dhd, FALSE); - dhd_bus_oob_intr_unregister(bus->dhd); + /* Clean up any pending host wake IRQ */ + dhd_bus_oob_intr_set(bus->dhd, FALSE); + dhd_bus_oob_intr_unregister(bus->dhd); #endif /* BCMPCIE_OOB_HOST_WAKE */ - dhd_dpc_kill(bus->dhd); - dhd_prot_reset(dhdp); - dhd_clear(dhdp); + dhd_dpc_kill(bus->dhd); + if (!bus->no_bus_init) { dhd_bus_release_dongle(bus); dhdpcie_bus_free_resource(bus); bcmerror = dhdpcie_bus_disable_device(bus); if (bcmerror) { DHD_ERROR(("%s: dhdpcie_bus_disable_device: %d\n", __FUNCTION__, bcmerror)); - goto done; } + /* Clean up protocol data after Bus Master Enable bit clear + * so that host can safely unmap DMA and remove the allocated + * buffers from the PKTID MAP. Some Applicantion Processors + * supported System MMU triggers Kernel panic when they detect + * to attempt to DMA-unmapped memory access from the devices + * which use the System MMU. + * Therefore, Kernel panic can be happened since it is possible + * that dongle can access to DMA-unmapped memory after calling + * the dhd_prot_reset(). + * For this reason, the dhd_prot_reset() and dhd_clear() functions + * should be located after the dhdpcie_bus_disable_device(). + */ + dhd_prot_reset(dhdp); + dhd_clear(dhdp); + } else { + bus->no_bus_init = FALSE; + } #ifdef CONFIG_ARCH_MSM - bcmerror = dhdpcie_bus_clock_stop(bus); - if (bcmerror) { - DHD_ERROR(("%s: host clock stop failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } -#endif /* CONFIG_ARCH_MSM */ + bcmerror = dhdpcie_bus_clock_stop(bus); + if (bcmerror) { + DHD_ERROR(("%s: host clock stop failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; } +#endif /* CONFIG_ARCH_MSM */ + } - bus->dhd->dongle_reset = TRUE; - DHD_ERROR(("%s: WLAN OFF Done\n", __FUNCTION__)); + bus->dhd->dongle_reset = TRUE; + DHD_ERROR(("%s: WLAN OFF Done\n", __FUNCTION__)); - } else { /* Turn on WLAN */ - if (bus->dhd->busstate == DHD_BUS_DOWN) { - /* Powering On */ - DHD_ERROR(("%s: == Power ON ==\n", __FUNCTION__)); + } else { /* Turn on WLAN */ + if (bus->dhd->busstate == DHD_BUS_DOWN) { + /* Powering On */ + DHD_ERROR(("%s: == Power ON ==\n", __FUNCTION__)); #ifdef CONFIG_ARCH_MSM - while (--retry) { - bcmerror = dhdpcie_bus_clock_start(bus); - if (!bcmerror) { - DHD_ERROR(("%s: dhdpcie_bus_clock_start OK\n", - __FUNCTION__)); - break; - } else { - OSL_SLEEP(10); - } + while (--retry) { + bcmerror = dhdpcie_bus_clock_start(bus); + if (!bcmerror) { + DHD_ERROR(("%s: dhdpcie_bus_clock_start OK\n", + __FUNCTION__)); + break; + } else { + OSL_SLEEP(10); } + } - if (bcmerror && !retry) { - DHD_ERROR(("%s: host pcie clock enable failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + if (bcmerror && !retry) { + DHD_ERROR(("%s: host pcie clock enable failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; + } #endif /* CONFIG_ARCH_MSM */ - bus->is_linkdown = 0; + bus->is_linkdown = 0; #ifdef SUPPORT_LINKDOWN_RECOVERY - bus->read_shm_fail = FALSE; + bus->read_shm_fail = FALSE; #endif /* SUPPORT_LINKDOWN_RECOVERY */ - bcmerror = dhdpcie_bus_enable_device(bus); - if (bcmerror) { - DHD_ERROR(("%s: host configuration restore failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + bcmerror = dhdpcie_bus_enable_device(bus); + if (bcmerror) { + DHD_ERROR(("%s: host configuration restore failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; + } - bcmerror = dhdpcie_bus_alloc_resource(bus); - if (bcmerror) { - DHD_ERROR(("%s: dhdpcie_bus_resource_alloc failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + bcmerror = dhdpcie_bus_alloc_resource(bus); + if (bcmerror) { + DHD_ERROR(("%s: dhdpcie_bus_resource_alloc failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; + } - bcmerror = dhdpcie_bus_dongle_attach(bus); - if (bcmerror) { - DHD_ERROR(("%s: dhdpcie_bus_dongle_attach failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } - - bcmerror = dhd_bus_request_irq(bus); - if (bcmerror) { - DHD_ERROR(("%s: dhd_bus_request_irq failed: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + bcmerror = dhdpcie_bus_dongle_attach(bus); + if (bcmerror) { + DHD_ERROR(("%s: dhdpcie_bus_dongle_attach failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; + } - bus->dhd->dongle_reset = FALSE; + bcmerror = dhd_bus_request_irq(bus); + if (bcmerror) { + DHD_ERROR(("%s: dhd_bus_request_irq failed: %d\n", + __FUNCTION__, bcmerror)); + goto done; + } - bcmerror = dhd_bus_start(dhdp); - if (bcmerror) { - DHD_ERROR(("%s: dhd_bus_start: %d\n", - __FUNCTION__, bcmerror)); - goto done; - } + bus->dhd->dongle_reset = FALSE; - bus->dhd->up = TRUE; - DHD_ERROR(("%s: WLAN Power On Done\n", __FUNCTION__)); - } else { - DHD_ERROR(("%s: what should we do here\n", __FUNCTION__)); + bcmerror = dhd_bus_start(dhdp); + if (bcmerror) { + DHD_ERROR(("%s: dhd_bus_start: %d\n", + __FUNCTION__, bcmerror)); goto done; } + + bus->dhd->up = TRUE; + /* Renabling watchdog which is disabled in dhdpcie_advertise_bus_cleanup */ + if (bus->dhd->dhd_watchdog_ms_backup) { + DHD_ERROR(("%s: Enabling wdtick after dhd init\n", + __FUNCTION__)); + dhd_os_wd_timer(bus->dhd, bus->dhd->dhd_watchdog_ms_backup); + } + DHD_ERROR(("%s: WLAN Power On Done\n", __FUNCTION__)); + } else { + DHD_ERROR(("%s: what should we do here\n", __FUNCTION__)); + goto done; } } @@ -4426,9 +4357,18 @@ done: bus->dhd->busstate = DHD_BUS_DOWN; DHD_GENERAL_UNLOCK(bus->dhd, flags); } - return bcmerror; } + +/** + * IOVAR handler of the DHD bus layer (in this case, the PCIe bus). + * + * @param actionid e.g. IOV_SVAL(IOV_PCIEREG) + * @param params input buffer + * @param plen length in [bytes] of input buffer 'params' + * @param arg output buffer + * @param len length in [bytes] of output buffer 'arg' + */ static int dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, void *params, int plen, void *arg, int len, int val_size) @@ -4465,7 +4405,6 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons switch (actionid) { - case IOV_SVAL(IOV_VARS): bcmerror = dhdpcie_downloadvars(bus, arg, len); break; @@ -4479,18 +4418,18 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons int core_num = 0; if (plen >= (int)sizeof(int_val) * 4) { bcopy((void*)((uintptr)params + 3 * sizeof(int_val)), - &int_val4, sizeof(int_val4)); + &int_val4, sizeof(int_val4)); } if (plen >= (int)sizeof(int_val) * 5) { bcopy((void*)((uintptr)params + 4 * sizeof(int_val)), - &wait, sizeof(wait)); + &wait, sizeof(wait)); } if (plen >= (int)sizeof(core_num) * 6) { bcopy((void*)((uintptr)params + 5 * sizeof(core_num)), - &core_num, sizeof(core_num)); + &core_num, sizeof(core_num)); } bcmerror = dhdpcie_bus_dmaxfer_req(bus, int_val, int_val2, int_val3, - int_val4, core_num, wait); + int_val4, core_num, wait); if (wait && bcmerror >= 0) { /* get the status of the dma transfer */ int_val4 = dhdmsgbuf_dmaxfer_status(bus->dhd); @@ -4507,15 +4446,6 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons break; } -#ifdef DEVICE_TX_STUCK_DETECT - case IOV_GVAL(IOV_DEVICE_TX_STUCK_DETECT): - int_val = bus->dev_tx_stuck_monitor; - bcopy(&int_val, arg, val_size); - break; - case IOV_SVAL(IOV_DEVICE_TX_STUCK_DETECT): - bus->dev_tx_stuck_monitor = (bool)int_val; - break; -#endif /* DEVICE_TX_STUCK_DETECT */ case IOV_GVAL(IOV_PCIE_SUSPEND): int_val = (bus->dhd->busstate == DHD_BUS_SUSPEND) ? 1 : 0; bcopy(&int_val, arg, val_size); @@ -4541,8 +4471,11 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons DHD_GENERAL_LOCK(bus->dhd, flags); DHD_BUS_BUSY_SET_SUSPEND_IN_PROGRESS(bus->dhd); DHD_GENERAL_UNLOCK(bus->dhd, flags); - +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + dhdpcie_bus_suspend(bus, TRUE, TRUE); +#else dhdpcie_bus_suspend(bus, TRUE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ DHD_GENERAL_LOCK(bus->dhd, flags); DHD_BUS_BUSY_CLEAR_SUSPEND_IN_PROGRESS(bus->dhd); @@ -4568,6 +4501,70 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons bcopy(&int_val, arg, val_size); break; + /* Debug related. Dumps core registers or one of the dongle memory */ + case IOV_GVAL(IOV_DUMP_DONGLE): + { + dump_dongle_in_t ddi = *(dump_dongle_in_t*)params; + dump_dongle_out_t *ddo = (dump_dongle_out_t*)arg; + uint32 *p = ddo->val; + const uint max_offset = 4096 - 1; /* one core contains max 4096/4 registers */ + + if (plen < sizeof(ddi) || len < sizeof(ddo)) { + bcmerror = BCME_BADARG; + break; + } + + switch (ddi.type) { + case DUMP_DONGLE_COREREG: + ddo->n_bytes = 0; + + if (si_setcoreidx(bus->sih, ddi.index) == NULL) { + break; // beyond last core: core enumeration ended + } + + ddo->address = si_addrspace(bus->sih, CORE_SLAVE_PORT_0, CORE_BASE_ADDR_0); + ddo->address += ddi.offset; // BP address at which this dump starts + + ddo->id = si_coreid(bus->sih); + ddo->rev = si_corerev(bus->sih); + + while (ddi.offset < max_offset && + sizeof(dump_dongle_out_t) + ddo->n_bytes < (uint)len) { + *p++ = si_corereg(bus->sih, ddi.index, ddi.offset, 0, 0); + ddi.offset += sizeof(uint32); + ddo->n_bytes += sizeof(uint32); + } + break; + default: + // TODO: implement d11 SHM/TPL dumping + bcmerror = BCME_BADARG; + break; + } + break; + } + + /* Debug related. Returns a string with dongle capabilities */ + case IOV_GVAL(IOV_DNGL_CAPS): + { + strncpy(arg, bus->dhd->fw_capabilities, + MIN(strlen(bus->dhd->fw_capabilities), (size_t)len)); + ((char*)arg)[len - 1] = '\0'; + break; + } + +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + case IOV_SVAL(IOV_GDB_SERVER): + /* debugger_*() functions may sleep, so cannot hold spinlock */ + DHD_PERIM_UNLOCK(bus->dhd); + if (int_val > 0) { + debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih)); + } else { + debugger_close(); + } + DHD_PERIM_LOCK(bus->dhd); + break; +#endif /* DEBUGGER || DHD_DSCOPE */ + #ifdef BCM_BUZZZ /* Dump dongle side buzzz trace to console */ case IOV_GVAL(IOV_BUZZZ_DUMP): @@ -4723,7 +4720,21 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons break; case IOV_SVAL(IOV_DEVRESET): - dhd_bus_devreset(bus->dhd, (uint8)bool_val); + switch (int_val) { + case DHD_BUS_DEVRESET_ON: + case DHD_BUS_DEVRESET_OFF: + dhd_bus_devreset(bus->dhd, (uint8)int_val); + break; + case DHD_BUS_DEVRESET_FLR: + dhd_bus_perform_flr(bus, FALSE); + break; + case DHD_BUS_DEVRESET_FLR_FORCE_FAIL: + dhd_bus_perform_flr(bus, TRUE); + break; + default: + DHD_ERROR(("%s: invalid argument for devreset\n", __FUNCTION__)); + break; + } break; case IOV_SVAL(IOV_FORCE_FW_TRAP): if (bus->dhd->busstate == DHD_BUS_DATA) @@ -4880,9 +4891,6 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons pcie_lnkst = si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, configdata), 0, 0); - /* 4347A0 in PCIEGEN1 doesn't support CTO prevention due to - * 4347A0 DAR Issue : JIRA:CRWLPCIEGEN2-443: Issue in DAR write - */ if ((bus->sih->buscorerev == 19) && (((pcie_lnkst >> PCI_LINK_SPEED_SHIFT) & PCI_LINK_SPEED_MASK) == PCIE_LNK_SPEED_GEN1)) { @@ -4930,69 +4938,11 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons case IOV_SVAL(IOV_PCIE_WD_RESET): if (bool_val) { - pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *) bus->regs); - } - break; -#ifdef DHD_EFI - case IOV_SVAL(IOV_CONTROL_SIGNAL): - { - bcmerror = dhd_control_signal(bus, arg, TRUE); - break; - } - - case IOV_GVAL(IOV_CONTROL_SIGNAL): - { - bcmerror = dhd_control_signal(bus, params, FALSE); - break; - } -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - case IOV_GVAL(IOV_DEEP_SLEEP): - int_val = bus->ds_enabled; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DEEP_SLEEP): - if (int_val == 1) { - bus->ds_enabled = TRUE; - /* Deassert */ - if (dhd_bus_set_device_wake(bus, FALSE) == BCME_OK) { -#ifdef PCIE_INB_DW - int timeleft; - timeleft = dhd_os_ds_enter_wait(bus->dhd, NULL); - if (timeleft == 0) { - DHD_ERROR(("DS-ENTER timeout\n")); - bus->ds_enabled = FALSE; - break; - } -#endif /* PCIE_INB_DW */ - } - else { - DHD_ERROR(("%s: Enable Deep Sleep failed !\n", __FUNCTION__)); - bus->ds_enabled = FALSE; - } - } - else if (int_val == 0) { - /* Assert */ - if (dhd_bus_set_device_wake(bus, TRUE) == BCME_OK) - bus->ds_enabled = FALSE; - else - DHD_ERROR(("%s: Disable Deep Sleep failed !\n", __FUNCTION__)); + pcie_watchdog_reset(bus->osh, bus->sih, + WD_ENABLE_MASK, WD_SSRESET_PCIE_F0_EN); } - else - DHD_ERROR(("%s: Invalid number, allowed only 0|1\n", __FUNCTION__)); - - break; -#endif /* PCIE_OOB || PCIE_INB_DW */ - - case IOV_GVAL(IOV_WIFI_PROPERTIES): - bcmerror = dhd_wifi_properties(bus, params); break; - case IOV_GVAL(IOV_OTP_DUMP): - bcmerror = dhd_otp_dump(bus, params); - break; -#endif /* DHD_EFI */ - case IOV_GVAL(IOV_IDMA_ENABLE): int_val = bus->idma_enabled; bcopy(&int_val, arg, val_size); @@ -5011,6 +4961,13 @@ dhdpcie_bus_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, cons bcopy(&int_val, arg, val_size); dhd_flow_rings_flush(bus->dhd, 0); break; + case IOV_GVAL(IOV_DAR_ENABLE): + int_val = bus->dar_enabled; + bcopy(&int_val, arg, val_size); + break; + case IOV_SVAL(IOV_DAR_ENABLE): + bus->dar_enabled = (bool)int_val; + break; default: bcmerror = BCME_UNSUPPORTED; break; @@ -5055,7 +5012,10 @@ dhd_bus_hostready(struct dhd_bus *bus) DHD_INFO_HW4(("%s : Read PCICMD Reg: 0x%08X\n", __FUNCTION__, dhd_pcie_config_read(bus->osh, PCI_CFG_CMD, sizeof(uint32)))); - si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_DB1, ~0, 0x12345678); + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } + si_corereg(bus->sih, bus->sih->buscoreidx, dhd_bus_db1_addr_get(bus), ~0, 0x12345678); bus->hostready_count ++; DHD_INFO_HW4(("%s: Ring Hostready:%d\n", __FUNCTION__, bus->hostready_count)); } @@ -5071,18 +5031,27 @@ dhdpcie_bus_clear_intstatus(struct dhd_bus *bus) dhdpcie_bus_cfg_write_dword(bus, PCIIntstatus, 4, intstatus); } else { /* this is a PCIE core register..not a config register... */ - intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); - si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, bus->def_intmask, + intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_int, 0, 0); + si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_int, bus->def_intmask, intstatus); } } int +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +dhdpcie_bus_suspend(struct dhd_bus *bus, bool state, bool byint) +#else dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ { int timeleft; int rc = 0; - unsigned long flags; + unsigned long flags, flags_bus; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + int d3_read_retry = 0; + uint32 d2h_mb_data = 0; + uint32 zero = 0; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ if (bus->dhd == NULL) { DHD_ERROR(("bus not inited\n")); @@ -5121,12 +5090,6 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) return BCME_OK; } - if (bus->d3_suspend_pending) { - DHD_ERROR(("Suspend pending ...\n")); - return BCME_ERROR; - } - - if (state) { int idle_retry = 0; int active; @@ -5140,89 +5103,86 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) /* Suspend */ DHD_ERROR(("%s: Entering suspend state\n", __FUNCTION__)); + bus->dhd->dhd_watchdog_ms_backup = dhd_watchdog_ms; + if (bus->dhd->dhd_watchdog_ms_backup) { + DHD_ERROR(("%s: Disabling wdtick before going to suspend\n", + __FUNCTION__)); + dhd_os_wd_timer(bus->dhd, 0); + } + DHD_GENERAL_LOCK(bus->dhd, flags); if (DHD_BUS_BUSY_CHECK_IN_TX(bus->dhd)) { DHD_ERROR(("Tx Request is not ended\n")); bus->dhd->busstate = DHD_BUS_DATA; DHD_GENERAL_UNLOCK(bus->dhd, flags); -#ifndef DHD_EFI return -EBUSY; -#else - return BCME_ERROR; -#endif } + bus->last_suspend_start_time = OSL_SYSUPTIME_US(); + /* stop all interface network queue. */ dhd_bus_stop_queue(bus); DHD_GENERAL_UNLOCK(bus->dhd, flags); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + if (byint) { + DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); + /* Clear wait_for_d3_ack before sending D3_INFORM */ + bus->wait_for_d3_ack = 0; + dhdpcie_send_mb_data(bus, H2D_HOST_D3_INFORM); + + timeleft = dhd_os_d3ack_wait(bus->dhd, &bus->wait_for_d3_ack); + DHD_OS_WAKE_LOCK_RESTORE(bus->dhd); + } else { + /* Clear wait_for_d3_ack before sending D3_INFORM */ + bus->wait_for_d3_ack = 0; + dhdpcie_send_mb_data(bus, H2D_HOST_D3_INFORM | H2D_HOST_ACK_NOINT); + while (!bus->wait_for_d3_ack && d3_read_retry < MAX_D3_ACK_TIMEOUT) { + dhdpcie_handle_mb_data(bus); + usleep_range(1000, 1500); + d3_read_retry++; + } + } +#else DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); -#ifdef DHD_TIMESYNC - /* disable time sync mechanism, if configed */ - dhd_timesync_control(bus->dhd, TRUE); -#endif /* DHD_TIMESYNC */ -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - dhd_bus_set_device_wake(bus, TRUE); -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ -#ifdef PCIE_OOB - bus->oob_presuspend = TRUE; -#endif -#ifdef PCIE_INB_DW - /* De-assert at this point for In-band device_wake */ - if (INBAND_DW_ENAB(bus)) { - dhd_bus_set_device_wake(bus, FALSE); - dhdpcie_bus_set_pcie_inband_dw_state(bus, DW_DEVICE_HOST_SLEEP_WAIT); - } -#endif /* PCIE_INB_DW */ - - /* Clear wait_for_d3_ack */ + + /* Clear wait_for_d3_ack before sending D3_INFORM */ bus->wait_for_d3_ack = 0; /* - * Send H2D_HOST_D3_INFORM to dongle and mark - * bus->d3_suspend_pending to TRUE in dhdpcie_send_mb_data + * Send H2D_HOST_D3_INFORM to dongle and mark bus->bus_low_power_state + * to DHD_BUS_D3_INFORM_SENT in dhd_prot_ring_write_complete_mbdata * inside atomic context, so that no more DBs will be * rung after sending D3_INFORM */ dhdpcie_send_mb_data(bus, H2D_HOST_D3_INFORM); /* Wait for D3 ACK for D3_ACK_RESP_TIMEOUT seconds */ - dhd_os_set_ioctl_resp_timeout(D3_ACK_RESP_TIMEOUT); + timeleft = dhd_os_d3ack_wait(bus->dhd, &bus->wait_for_d3_ack); #ifdef DHD_RECOVER_TIMEOUT if (bus->wait_for_d3_ack == 0) { /* If wait_for_d3_ack was not updated because D2H MB was not received */ - uint32 intstatus = 0; - uint32 intmask = 0; - intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); - intmask = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); - if ((intstatus) && (!intmask) && (timeleft == 0) && - (!dhd_query_bus_erros(bus->dhd))) { - - DHD_ERROR(("%s: D3 ACK trying again intstatus=%x intmask=%x\n", - __FUNCTION__, intstatus, intmask)); - DHD_ERROR(("\n ------- DUMPING INTR enable/disable counters\r\n")); - DHD_ERROR(("resume_intr_enable_count=%lu dpc_intr_en_count=%lu\n" - "isr_intr_disable_count=%lu suspend_intr_dis_count=%lu\n" - "dpc_return_busdown_count=%lu\n", - bus->resume_intr_enable_count, bus->dpc_intr_enable_count, - bus->isr_intr_disable_count, - bus->suspend_intr_disable_count, - bus->dpc_return_busdown_count)); - + uint32 intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, + bus->pcie_mailbox_int, 0, 0); + int host_irq_disabled = dhdpcie_irq_disabled(bus); + if ((intstatus) && (intstatus != (uint32)-1) && + (timeleft == 0) && (!dhd_query_bus_erros(bus->dhd))) { + DHD_ERROR(("%s: D3 ACK trying again intstatus=%x" + " host_irq_disabled=%d\n", + __FUNCTION__, intstatus, host_irq_disabled)); + dhd_pcie_intr_count_dump(bus->dhd); + dhd_print_tasklet_status(bus->dhd); dhd_prot_process_ctrlbuf(bus->dhd); - timeleft = dhd_os_d3ack_wait(bus->dhd, &bus->wait_for_d3_ack); - - /* Enable Back Interrupts using IntMask */ - dhdpcie_bus_intr_enable(bus); + /* Clear Interrupts */ + dhdpcie_bus_clear_intstatus(bus); } - - } /* bus->wait_for_d3_ack was 0 */ #endif /* DHD_RECOVER_TIMEOUT */ DHD_OS_WAKE_LOCK_RESTORE(bus->dhd); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ /* To allow threads that got pre-empted to complete. */ @@ -5240,6 +5200,13 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) DHD_ERROR(("%s():Suspend failed because of wakelock" "restoring Dongle to D0\n", __FUNCTION__)); + if (bus->dhd->dhd_watchdog_ms_backup) { + DHD_ERROR(("%s: Enabling wdtick due to wakelock active\n", + __FUNCTION__)); + dhd_os_wd_timer(bus->dhd, + bus->dhd->dhd_watchdog_ms_backup); + } + /* * Dongle still thinks that it has to be in D3 state until * it gets a D0 Inform, but we are backing off from suspend. @@ -5254,11 +5221,24 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) /* Clear wait_for_d3_ack to send D0_INFORM or host_ready */ bus->wait_for_d3_ack = 0; + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + bus->bus_low_power_state = DHD_BUS_NO_LOW_POWER_STATE; /* Enable back the intmask which was cleared in DPC * after getting D3_ACK. */ bus->resume_intr_enable_count++; + + /* For Linux, Macos etc (otherthan NDIS) enable back the dongle + * interrupts using intmask and host interrupts + * which were disabled in the dhdpcie_bus_isr()-> + * dhd_bus_handle_d3_ack(). + */ + /* Enable back interrupt using Intmask!! */ dhdpcie_bus_intr_enable(bus); + /* Enable back interrupt from Host side!! */ + dhdpcie_enable_irq(bus); + + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); if (bus->use_d0_inform) { DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); @@ -5270,37 +5250,24 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) dhd_bus_hostready(bus); DHD_GENERAL_LOCK(bus->dhd, flags); - bus->d3_suspend_pending = FALSE; bus->dhd->busstate = DHD_BUS_DATA; /* resume all interface network queue. */ dhd_bus_start_queue(bus); DHD_GENERAL_UNLOCK(bus->dhd, flags); rc = BCME_ERROR; } else { -#ifdef PCIE_OOB - bus->oob_presuspend = FALSE; - if (OOB_DW_ENAB(bus)) { - dhd_bus_set_device_wake(bus, FALSE); - } -#endif /* PCIE_OOB */ -#if defined(PCIE_OOB) || defined(BCMPCIE_OOB_HOST_WAKE) - bus->oob_presuspend = TRUE; -#endif /* PCIE_OOB || BCMPCIE_OOB_HOST_WAKE */ -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_HOST_SLEEP_WAIT) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_HOST_SLEEP); - } - } -#endif /* PCIE_INB_DW */ + /* Actual Suspend after no wakelock */ + /* At this time bus->bus_low_power_state will be + * made to DHD_BUS_D3_ACK_RECIEVED after recieving D3_ACK + * in dhd_bus_handle_d3_ack() + */ if (bus->use_d0_inform && (bus->api.fw_rev < PCIE_SHARED_VERSION_6)) { DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); dhdpcie_send_mb_data(bus, (H2D_HOST_D0_INFORM_IN_USE)); DHD_OS_WAKE_LOCK_RESTORE(bus->dhd); } + #if defined(BCMPCIE_OOB_HOST_WAKE) dhdpcie_oob_intr_set(bus, TRUE); #endif /* BCMPCIE_OOB_HOST_WAKE */ @@ -5308,29 +5275,40 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) DHD_GENERAL_LOCK(bus->dhd, flags); /* The Host cannot process interrupts now so disable the same. * No need to disable the dongle INTR using intmask, as we are - * already calling dhdpcie_bus_intr_disable from DPC context after - * getting D3_ACK. Code may not look symmetric between Suspend and + * already calling disabling INTRs from DPC context after + * getting D3_ACK in dhd_bus_handle_d3_ack. + * Code may not look symmetric between Suspend and * Resume paths but this is done to close down the timing window - * between DPC and suspend context. + * between DPC and suspend context and bus->bus_low_power_state + * will be set to DHD_BUS_D3_ACK_RECIEVED in DPC. */ - /* Disable interrupt from host side!! */ - dhdpcie_disable_irq_nosync(bus); - bus->dhd->d3ackcnt_timeout = 0; - bus->d3_suspend_pending = FALSE; bus->dhd->busstate = DHD_BUS_SUSPEND; DHD_GENERAL_UNLOCK(bus->dhd, flags); + DHD_ERROR(("%s: BaseAddress0(0x%x)=0x%x, " + "BaseAddress1(0x%x)=0x%x\n", __FUNCTION__, + PCIECFGREG_BASEADDR0, + dhd_pcie_config_read(bus->osh, + PCIECFGREG_BASEADDR0, sizeof(uint32)), + PCIECFGREG_BASEADDR1, + dhd_pcie_config_read(bus->osh, + PCIECFGREG_BASEADDR1, sizeof(uint32)))); /* Handle Host Suspend */ rc = dhdpcie_pci_suspend_resume(bus, state); + if (!rc) { + bus->last_suspend_end_time = OSL_SYSUPTIME_US(); + } } - } else if (timeleft == 0) { + } else if (timeleft == 0) { /* D3 ACK Timeout */ bus->dhd->d3ack_timeout_occured = TRUE; /* If the D3 Ack has timeout */ bus->dhd->d3ackcnt_timeout++; DHD_ERROR(("%s: resumed on timeout for D3 ACK d3_inform_cnt %d \n", - __FUNCTION__, bus->dhd->d3ackcnt_timeout)); + __FUNCTION__, bus->dhd->d3ackcnt_timeout)); + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + bus->bus_low_power_state = DHD_BUS_NO_LOW_POWER_STATE; + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); DHD_GENERAL_LOCK(bus->dhd, flags); - bus->d3_suspend_pending = FALSE; bus->dhd->busstate = DHD_BUS_DATA; /* resume all interface network queue. */ dhd_bus_start_queue(bus); @@ -5339,8 +5317,8 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) uint32 intstatus = 0; /* Check if PCIe bus status is valid */ - intstatus = si_corereg(bus->sih, - bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); + intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, + bus->pcie_mailbox_int, 0, 0); if (intstatus == (uint32)-1) { /* Invalidate PCIe bus status */ bus->is_linkdown = 1; @@ -5355,6 +5333,7 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) dhdpcie_mem_dump(bus); } #endif /* DHD_FW_COREDUMP */ + DHD_ERROR(("%s: Event HANG send up due to D3_ACK timeout\n", __FUNCTION__)); #ifdef SUPPORT_LINKDOWN_RECOVERY @@ -5366,13 +5345,11 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) } rc = -ETIMEDOUT; } - bus->wait_for_d3_ack = 1; - -#ifdef PCIE_OOB - bus->oob_presuspend = FALSE; -#endif /* PCIE_OOB */ } else { /* Resume */ + DHD_ERROR(("%s: Entering resume state\n", __FUNCTION__)); + bus->last_resume_start_time = OSL_SYSUPTIME_US(); + /** * PCIE2_BAR0_CORE2_WIN gets reset after D3 cold. * si_backplane_access(function to read/write backplane) @@ -5387,20 +5364,19 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) #if defined(BCMPCIE_OOB_HOST_WAKE) DHD_OS_OOB_IRQ_WAKE_UNLOCK(bus->dhd); #endif /* BCMPCIE_OOB_HOST_WAKE */ -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == DW_DEVICE_HOST_SLEEP) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, DW_DEVICE_HOST_WAKE_WAIT); - } - } -#endif /* PCIE_INB_DW */ rc = dhdpcie_pci_suspend_resume(bus, state); - -#ifdef BCMPCIE_OOB_HOST_WAKE - bus->oob_presuspend = FALSE; -#endif /* BCMPCIE_OOB_HOST_WAKE */ - - if (bus->dhd->busstate == DHD_BUS_SUSPEND) { + DHD_ERROR(("%s: BaseAddress0(0x%x)=0x%x, BaseAddress1(0x%x)=0x%x\n", + __FUNCTION__, PCIECFGREG_BASEADDR0, + dhd_pcie_config_read(bus->osh, PCIECFGREG_BASEADDR0, sizeof(uint32)), + PCIECFGREG_BASEADDR1, + dhd_pcie_config_read(bus->osh, PCIECFGREG_BASEADDR1, sizeof(uint32)))); + + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + /* set bus_low_power_state to DHD_BUS_NO_LOW_POWER_STATE */ + bus->bus_low_power_state = DHD_BUS_NO_LOW_POWER_STATE; + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); + + if (!rc && bus->dhd->busstate == DHD_BUS_SUSPEND) { if (bus->use_d0_inform) { DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); dhdpcie_send_mb_data(bus, (H2D_HOST_D0_INFORM)); @@ -5409,7 +5385,6 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) /* ring doorbell 1 (hostready) */ dhd_bus_hostready(bus); } - DHD_GENERAL_LOCK(bus->dhd, flags); bus->dhd->busstate = DHD_BUS_DATA; #ifdef DHD_PCIE_RUNTIMEPM @@ -5419,50 +5394,29 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state) wake_up_interruptible(&bus->rpm_queue); } #endif /* DHD_PCIE_RUNTIMEPM */ -#ifdef PCIE_OOB - /* - * Assert & Deassert the Device Wake. The following is the explanation for doing so. - * 0) At this point, - * Host is in suspend state, Link is in L2/L3, Dongle is in D3 Cold - * Device Wake is enabled. - * 1) When the Host comes out of Suspend, it first sends PERST# in the Link. - * Looking at this the Dongle moves from D3 Cold to NO DS State - * 2) Now The Host OS calls the "resume" function of DHD. From here the DHD first - * Asserts the Device Wake. - * From the defn, when the Device Wake is asserted, The dongle FW will ensure - * that the Dongle is out of deep sleep IF the device is already in deep sleep. - * But note that now the Dongle is NOT in Deep sleep and is actually in - * NO DS state. So just driving the Device Wake high does not trigger any state - * transitions. The Host should actually "Toggle" the Device Wake to ensure - * that Dongle synchronizes with the Host and starts the State Transition to D0. - * 4) Note that the above explanation is applicable Only when the Host comes out of - * suspend and the Dongle comes out of D3 Cold - */ - /* This logic is not required when hostready is enabled */ - - if (!bus->dhd->d2h_hostrdy_supported) { - if (OOB_DW_ENAB(bus)) { - dhd_bus_set_device_wake(bus, TRUE); - OSL_DELAY(1000); - dhd_bus_set_device_wake(bus, FALSE); - } - } -#endif /* PCIE_OOB */ /* resume all interface network queue. */ dhd_bus_start_queue(bus); - /* The Host is ready to process interrupts now so enable the same. */ /* TODO: for NDIS also we need to use enable_irq in future */ bus->resume_intr_enable_count++; + + /* For Linux, Macos etc (otherthan NDIS) enable back the dongle interrupts + * using intmask and host interrupts + * which were disabled in the dhdpcie_bus_isr()->dhd_bus_handle_d3_ack(). + */ dhdpcie_bus_intr_enable(bus); /* Enable back interrupt using Intmask!! */ dhdpcie_enable_irq(bus); /* Enable back interrupt from Host side!! */ + DHD_GENERAL_UNLOCK(bus->dhd, flags); -#ifdef DHD_TIMESYNC - DHD_OS_WAKE_LOCK_WAIVE(bus->dhd); - /* enable time sync mechanism, if configed */ - dhd_timesync_control(bus->dhd, FALSE); - DHD_OS_WAKE_LOCK_RESTORE(bus->dhd); -#endif /* DHD_TIMESYNC */ + + if (bus->dhd->dhd_watchdog_ms_backup) { + DHD_ERROR(("%s: Enabling wdtick after resume\n", + __FUNCTION__)); + dhd_os_wd_timer(bus->dhd, bus->dhd->dhd_watchdog_ms_backup); + } + + bus->last_resume_end_time = OSL_SYSUPTIME_US(); + } return rc; } @@ -5502,9 +5456,9 @@ dhdpcie_set_l1_entry_time(struct dhd_bus *bus, int l1_entry_time) /** Transfers bytes from host to dongle and to host again using DMA */ static int -dhdpcie_bus_dmaxfer_req(struct dhd_bus *bus, - uint32 len, uint32 srcdelay, uint32 destdelay, - uint32 d11_lpbk, uint32 core_num, uint32 wait) +dhdpcie_bus_dmaxfer_req(struct dhd_bus *bus, + uint32 len, uint32 srcdelay, uint32 destdelay, + uint32 d11_lpbk, uint32 core_num, uint32 wait) { int ret = 0; @@ -5537,9 +5491,8 @@ dhdpcie_bus_dmaxfer_req(struct dhd_bus *bus, ret = BCME_NOTREADY; return ret; -} - +} static int dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter) @@ -5661,7 +5614,6 @@ dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter) goto fail; } - 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__)); @@ -5687,12 +5639,10 @@ dhdpcie_bus_download_state(dhd_bus_t *bus, bool enter) goto fail; } -#ifdef BCM_ASLR_HEAP /* write a random number to TCM for the purpose of * randomizing heap address space. */ dhdpcie_wrt_rnd(bus); -#endif /* BCM_ASLR_HEAP */ /* switch back to arm core again */ if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) { @@ -5891,7 +5841,7 @@ dhdpcie_downloadvars(dhd_bus_t *bus, void *arg, int len) /* We assumed that string length of both ccode and * regrev values should not exceed WLC_CNTRY_BUF_SZ */ - if (sp && ep && ((ep - sp) <= WLC_CNTRY_BUF_SZ)) { + if (ep && ((ep - sp) <= WLC_CNTRY_BUF_SZ)) { sp++; while (*sp != '\0') { DHD_INFO(("%s: parse '%s', current sp = '%c'\n", @@ -6037,7 +5987,6 @@ dhdpcie_lcreg(osl_t *osh, uint32 mask, uint32 val) uint8 lcreg_offset; /* PCIE capability LCreg offset in the config space */ uint32 reg_val; - pcie_cap = dhdpcie_find_pci_capability(osh, PCI_CAP_PCIECAP_ID); if (!pcie_cap) { @@ -6062,8 +6011,6 @@ dhdpcie_lcreg(osl_t *osh, uint32 mask, uint32 val) return OSL_PCI_READ_CONFIG(osh, lcreg_offset, sizeof(uint32)); } - - uint8 dhdpcie_clkreq(osl_t *osh, uint32 mask, uint32 val) { @@ -6096,6 +6043,38 @@ dhdpcie_clkreq(osl_t *osh, uint32 mask, uint32 val) return 0; } +void dhd_dump_intr_counters(dhd_pub_t *dhd, struct bcmstrbuf *strbuf) +{ + bcm_bprintf(strbuf, "\n ------- DUMPING INTR enable/disable counters-------\n"); + bcm_bprintf(strbuf, "resume_intr_enable_count=%lu dpc_intr_enable_count=%lu\n" + "isr_intr_disable_count=%lu suspend_intr_disable_count=%lu\n" + "dpc_return_busdown_count=%lu\n", + dhd->bus->resume_intr_enable_count, dhd->bus->dpc_intr_enable_count, + dhd->bus->isr_intr_disable_count, dhd->bus->suspend_intr_disable_count, + dhd->bus->dpc_return_busdown_count); +#ifdef BCMPCIE_OOB_HOST_WAKE + bcm_bprintf(strbuf, "oob_intr_count=%lu oob_intr_enable_count=%lu" + " oob_intr_disable_count=%lu\n oob_irq_num=%d last_oob_irq_time=%llu\n", + dhd->bus->oob_intr_count, dhd->bus->oob_intr_enable_count, + dhd->bus->oob_intr_disable_count, dhdpcie_get_oob_irq_num(dhd->bus), + dhd->bus->last_oob_irq_time); +#endif /* BCMPCIE_OOB_HOST_WAKE */ + bcm_bprintf(strbuf, "\ncurrent_time=%llu isr_entry_time=%llu isr_exit_time=%llu\n" + "dpc_entry_time=%llu last_process_ctrlbuf_time=%llu " + "last_process_flowring_time=%llu last_process_txcpl_time=%llu\n" + "last_process_rxcpl_time=%llu last_process_infocpl_time=%llu " + "dpc_exit_time=%llu resched_dpc_time=%llu\n", + OSL_SYSUPTIME_US(), dhd->bus->isr_entry_time, dhd->bus->isr_exit_time, + dhd->bus->dpc_entry_time, dhd->bus->last_process_ctrlbuf_time, + dhd->bus->last_process_flowring_time, dhd->bus->last_process_txcpl_time, + dhd->bus->last_process_rxcpl_time, dhd->bus->last_process_infocpl_time, + dhd->bus->dpc_exit_time, dhd->bus->resched_dpc_time); + bcm_bprintf(strbuf, "\nlast_suspend_start_time=%llu last_suspend_end_time=%llu" + " last_resume_start_time=%llu last_resume_end_time=%llu\n", + dhd->bus->last_suspend_start_time, dhd->bus->last_suspend_end_time, + dhd->bus->last_resume_start_time, dhd->bus->last_resume_end_time); +} + void dhd_dump_intr_registers(dhd_pub_t *dhd, struct bcmstrbuf *strbuf) { uint32 intstatus = 0; @@ -6103,8 +6082,10 @@ void dhd_dump_intr_registers(dhd_pub_t *dhd, struct bcmstrbuf *strbuf) uint32 mbintstatus = 0; uint32 d2h_mb_data = 0; - intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); - intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCIMailBoxMask, 0, 0); + intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + dhd->bus->pcie_mailbox_int, 0, 0); + intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + dhd->bus->pcie_mailbox_mask, 0, 0); mbintstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, PCID2H_MailBox, 0, 0); dhd_bus_cmn_readshared(dhd->bus, &d2h_mb_data, D2H_MB_DATA, 0); @@ -6112,13 +6093,6 @@ void dhd_dump_intr_registers(dhd_pub_t *dhd, struct bcmstrbuf *strbuf) intstatus, intmask, mbintstatus); bcm_bprintf(strbuf, "d2h_mb_data=0x%x def_intmask=0x%x\n", d2h_mb_data, dhd->bus->def_intmask); - bcm_bprintf(strbuf, "\n ------- DUMPING INTR enable/disable counters-------\n"); - bcm_bprintf(strbuf, "resume_intr_enable_count=%lu dpc_intr_enable_count=%lu\n" - "isr_intr_disable_count=%lu suspend_intr_disable_count=%lu\n" - "dpc_return_busdown_count=%lu\n", - dhd->bus->resume_intr_enable_count, dhd->bus->dpc_intr_enable_count, - dhd->bus->isr_intr_disable_count, dhd->bus->suspend_intr_disable_count, - dhd->bus->dpc_return_busdown_count); } /** Add bus dump output to a buffer */ @@ -6158,6 +6132,7 @@ void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) dhd_prot_print_info(dhdp, strbuf); dhd_dump_intr_registers(dhdp, strbuf); + dhd_dump_intr_counters(dhdp, strbuf); bcm_bprintf(strbuf, "h2d_mb_data_ptr_addr 0x%x, d2h_mb_data_ptr_addr 0x%x\n", dhdp->bus->h2d_mb_data_ptr_addr, dhdp->bus->d2h_mb_data_ptr_addr); bcm_bprintf(strbuf, "dhd cumm_ctr %d\n", DHD_CUMM_CTR_READ(&dhdp->cumm_ctr)); @@ -6192,23 +6167,8 @@ void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) if (dhdp->d2h_hostrdy_supported) { bcm_bprintf(strbuf, "hostready count:%d\n", dhdp->bus->hostready_count); } -#ifdef PCIE_INB_DW - /* Inband device wake counters */ - if (INBAND_DW_ENAB(dhdp->bus)) { - bcm_bprintf(strbuf, "Inband device_wake assert count: %d\n", - dhdp->bus->inband_dw_assert_cnt); - bcm_bprintf(strbuf, "Inband device_wake deassert count: %d\n", - dhdp->bus->inband_dw_deassert_cnt); - bcm_bprintf(strbuf, "Inband DS-EXIT count: %d\n", - dhdp->bus->inband_ds_exit_host_cnt); - bcm_bprintf(strbuf, "Inband DS-EXIT count: %d\n", - dhdp->bus->inband_ds_exit_device_cnt); - bcm_bprintf(strbuf, "Inband DS-EXIT Timeout count: %d\n", - dhdp->bus->inband_ds_exit_to_cnt); - bcm_bprintf(strbuf, "Inband HOST_SLEEP-EXIT Timeout count: %d\n", - dhdp->bus->inband_host_sleep_exit_to_cnt); - } -#endif /* PCIE_INB_DW */ + bcm_bprintf(strbuf, "d2h_intr_method -> %s\n", + dhdp->bus->d2h_intr_method ? "PCIE_MSI" : "PCIE_INTX"); } /** @@ -6258,7 +6218,11 @@ dhd_bus_gen_devmb_intr(struct dhd_bus *bus) if (bus->db1_for_mb) { /* this is a pcie core register, not the config register */ DHD_INFO(("writing a mail box interrupt to the device, through doorbell 1\n")); - si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_DB1, ~0, 0x12345678); + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } + si_corereg(bus->sih, bus->sih->buscoreidx, dhd_bus_db1_addr_get(bus), + ~0, 0x12345678); } else { DHD_INFO(("writing a mail box interrupt to the device, through config space\n")); dhdpcie_bus_cfg_write_dword(bus, PCISBMbx, 4, (1 << 0)); @@ -6275,197 +6239,39 @@ dhdpcie_fw_trap(dhd_bus_t *bus) { /* Send the mailbox data and generate mailbox intr. */ dhdpcie_send_mb_data(bus, H2D_FW_TRAP); + /* For FWs that cannot interprete H2D_FW_TRAP */ + (void)dhd_wl_ioctl_set_intiovar(bus->dhd, "bus:disconnect", 99, WLC_SET_VAR, TRUE, 0); } -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) -void -dhd_bus_doorbell_timeout_reset(struct dhd_bus *bus) -{ - if (dhd_doorbell_timeout) - dhd_timeout_start(&bus->doorbell_timer, - (dhd_doorbell_timeout * 1000) / dhd_watchdog_ms); - else if (!(bus->dhd->busstate == DHD_BUS_SUSPEND)) { - dhd_bus_set_device_wake(bus, FALSE); - } -} -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ - -#ifdef PCIE_INB_DW - -void -dhd_bus_inb_ack_pending_ds_req(dhd_bus_t *bus) -{ - /* The DHD_BUS_INB_DW_LOCK must be held before - * calling this function !! - */ - if ((dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_DS_DEV_SLEEP_PEND) && - (bus->host_active_cnt == 0)) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, DW_DEVICE_DS_DEV_SLEEP); - dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK); - } -} - -int -dhd_bus_inb_set_device_wake(struct dhd_bus *bus, bool val) -{ - int timeleft; - unsigned long flags; - int ret; - - if (!INBAND_DW_ENAB(bus)) { - return BCME_ERROR; - } - - if (val) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - - /* - * Reset the Door Bell Timeout value. So that the Watchdog - * doesn't try to Deassert Device Wake, while we are in - * the process of still Asserting the same. - */ - if (dhd_doorbell_timeout) { - dhd_timeout_start(&bus->doorbell_timer, - (dhd_doorbell_timeout * 1000) / dhd_watchdog_ms); - } - - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_DS_DEV_SLEEP) { - /* Clear wait_for_ds_exit */ - bus->wait_for_ds_exit = 0; - ret = dhdpcie_send_mb_data(bus, H2DMB_DS_DEVICE_WAKE_ASSERT); - if (ret != BCME_OK) { - DHD_ERROR(("Failed: assert Inband device_wake\n")); - bus->wait_for_ds_exit = 1; - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - ret = BCME_ERROR; - goto exit; - } - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_DISABLED_WAIT); - bus->inband_dw_assert_cnt++; - } else { - DHD_INFO(("Not in DS SLEEP state \n")); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - ret = BCME_OK; - goto exit; - } - - /* - * Since we are going to wait/sleep .. release the lock. - * The Device Wake sanity is still valid, because - * a) If there is another context that comes in and tries - * to assert DS again and if it gets the lock, since - * ds_state would be now != DW_DEVICE_DS_DEV_SLEEP the - * context would return saying Not in DS Sleep. - * b) If ther is another context that comes in and tries - * to de-assert DS and gets the lock, - * since the ds_state is != DW_DEVICE_DS_DEV_WAKE - * that context would return too. This can not happen - * since the watchdog is the only context that can - * De-Assert Device Wake and as the first step of - * Asserting the Device Wake, we have pushed out the - * Door Bell Timeout. - * - */ - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - - if (!CAN_SLEEP()) { - /* Called from context that cannot sleep */ - OSL_DELAY(1000); - bus->wait_for_ds_exit = 1; - } else { - /* Wait for DS EXIT for DS_EXIT_TIMEOUT seconds */ - timeleft = dhd_os_ds_exit_wait(bus->dhd, &bus->wait_for_ds_exit); - if (!bus->wait_for_ds_exit && timeleft == 0) { - DHD_ERROR(("DS-EXIT timeout\n")); - bus->inband_ds_exit_to_cnt++; - bus->ds_exit_timeout = 0; - ret = BCME_ERROR; - goto exit; - } - } - - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_DEV_WAKE); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - - ret = BCME_OK; - } else { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - if ((dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_DS_DEV_WAKE)) { - ret = dhdpcie_send_mb_data(bus, H2DMB_DS_DEVICE_WAKE_DEASSERT); - if (ret != BCME_OK) { - DHD_ERROR(("Failed: deassert Inband device_wake\n")); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - goto exit; - } - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_ACTIVE); - bus->inband_dw_deassert_cnt++; - } else if ((dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_DS_DEV_SLEEP_PEND) && - (bus->host_active_cnt == 0)) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, DW_DEVICE_DS_DEV_SLEEP); - dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK); - } - - ret = BCME_OK; - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - } - -exit: - return ret; -} -#endif /* PCIE_INB_DW */ - - -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) -int -dhd_bus_set_device_wake(struct dhd_bus *bus, bool val) -{ - if (bus->ds_enabled) { -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - return dhd_bus_inb_set_device_wake(bus, val); - } -#endif /* PCIE_INB_DW */ -#ifdef PCIE_OOB - if (OOB_DW_ENAB(bus)) { - return dhd_os_oob_set_device_wake(bus, val); - } -#endif /* PCIE_OOB */ - } - return BCME_OK; -} -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ - /** mailbox doorbell ring function */ void dhd_bus_ringbell(struct dhd_bus *bus, uint32 value) { /* Skip after sending D3_INFORM */ - if (bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) { - DHD_ERROR(("%s: trying to ring the doorbell when in suspend state :" - "busstate=%d, d3_suspend_pending=%d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); + if (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { + DHD_ERROR(("%s: trying to ring the doorbell after D3 inform %d\n", + __FUNCTION__, bus->bus_low_power_state)); return; } if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4)) { - si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, PCIE_INTB, PCIE_INTB); + si_corereg(bus->sih, bus->sih->buscoreidx, bus->pcie_mailbox_int, + PCIE_INTB, PCIE_INTB); } else { /* this is a pcie core register, not the config regsiter */ DHD_INFO(("writing a door bell to the device\n")); if (IDMA_ACTIVE(bus->dhd)) { - si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_MailBox_2, + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } + si_corereg(bus->sih, bus->sih->buscoreidx, dhd_bus_db0_addr_2_get(bus), ~0, value); } else { + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } si_corereg(bus->sih, bus->sih->buscoreidx, - PCIH2D_MailBox, ~0, 0x12345678); + dhd_bus_db0_addr_get(bus), ~0, 0x12345678); } } } @@ -6476,14 +6282,16 @@ dhd_bus_ringbell_2(struct dhd_bus *bus, uint32 value, bool devwake) { /* this is a pcie core register, not the config regsiter */ /* Skip after sending D3_INFORM */ - if (bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) { - DHD_ERROR(("%s: trying to ring the doorbell when in suspend state :" - "busstate=%d, d3_suspend_pending=%d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); + if (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { + DHD_ERROR(("%s: trying to ring the doorbell after D3 inform %d\n", + __FUNCTION__, bus->bus_low_power_state)); return; } DHD_INFO(("writing a door bell 2 to the device\n")); - si_corereg(bus->sih, bus->sih->buscoreidx, PCIH2D_MailBox_2, + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } + si_corereg(bus->sih, bus->sih->buscoreidx, dhd_bus_db0_addr_2_get(bus), ~0, value); } @@ -6491,18 +6299,15 @@ void dhdpcie_bus_ringbell_fast(struct dhd_bus *bus, uint32 value) { /* Skip after sending D3_INFORM */ - if (bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) { - DHD_ERROR(("%s: trying to ring the doorbell when in suspend state :" - "busstate=%d, d3_suspend_pending=%d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); + if (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { + DHD_ERROR(("%s: trying to ring the doorbell after D3 inform %d\n", + __FUNCTION__, bus->bus_low_power_state)); return; } -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - if (OOB_DW_ENAB(bus)) { - dhd_bus_set_device_wake(bus, TRUE); + + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); } - dhd_bus_doorbell_timeout_reset(bus); -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr, value); } @@ -6510,21 +6315,15 @@ void dhdpcie_bus_ringbell_2_fast(struct dhd_bus *bus, uint32 value, bool devwake) { /* Skip after sending D3_INFORM */ - if (bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) { - DHD_ERROR(("%s: trying to ring the doorbell when in suspend state :" - "busstate=%d, d3_suspend_pending=%d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); + if (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { + DHD_ERROR(("%s: trying to ring the doorbell after D3 inform %d\n", + __FUNCTION__, bus->bus_low_power_state)); return; } -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - if (devwake) { - if (OOB_DW_ENAB(bus)) { - dhd_bus_set_device_wake(bus, TRUE); - } - } - dhd_bus_doorbell_timeout_reset(bus); -#endif /* defined(PCIE_OOB) || defined(PCIE_INB_DW) */ + if (DAR_PWRREQ(bus)) { + dhd_bus_pcie_pwr_req(bus); + } W_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_2_addr, value); } @@ -6533,10 +6332,9 @@ dhd_bus_ringbell_oldpcie(struct dhd_bus *bus, uint32 value) { uint32 w; /* Skip after sending D3_INFORM */ - if (bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) { - DHD_ERROR(("%s: trying to ring the doorbell when in suspend state :" - "busstate=%d, d3_suspend_pending=%d\n", - __FUNCTION__, bus->dhd->busstate, bus->d3_suspend_pending)); + if (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { + DHD_ERROR(("%s: trying to ring the doorbell after D3 inform %d\n", + __FUNCTION__, bus->bus_low_power_state)); return; } w = (R_REG(bus->pcie_mb_intr_osh, bus->pcie_mb_intr_addr) & ~PCIE_INTB) | PCIE_INTB; @@ -6549,14 +6347,14 @@ dhd_bus_get_mbintr_fn(struct dhd_bus *bus) if ((bus->sih->buscorerev == 2) || (bus->sih->buscorerev == 6) || (bus->sih->buscorerev == 4)) { bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx, - PCIMailBoxInt); + bus->pcie_mailbox_int); if (bus->pcie_mb_intr_addr) { bus->pcie_mb_intr_osh = si_osh(bus->sih); return dhd_bus_ringbell_oldpcie; } } else { bus->pcie_mb_intr_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx, - PCIH2D_MailBox); + dhd_bus_db0_addr_get(bus)); if (bus->pcie_mb_intr_addr) { bus->pcie_mb_intr_osh = si_osh(bus->sih); return dhdpcie_bus_ringbell_fast; @@ -6569,7 +6367,7 @@ dhd_mb_ring_2_t dhd_bus_get_mbintr_2_fn(struct dhd_bus *bus) { bus->pcie_mb_intr_2_addr = si_corereg_addr(bus->sih, bus->sih->buscoreidx, - PCIH2D_MailBox_2); + dhd_bus_db0_addr_2_get(bus)); if (bus->pcie_mb_intr_2_addr) { bus->pcie_mb_intr_osh = si_osh(bus->sih); return dhdpcie_bus_ringbell_2_fast; @@ -6585,6 +6383,8 @@ dhd_bus_dpc(struct dhd_bus *bus) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + bus->dpc_entry_time = OSL_SYSUPTIME_US(); + DHD_GENERAL_LOCK(bus->dhd, flags); /* Check for only DHD_BUS_DOWN and not for DHD_BUS_DOWN_IN_PROGRESS * to avoid IOCTL Resumed On timeout when ioctl is waiting for response @@ -6604,14 +6404,21 @@ dhd_bus_dpc(struct dhd_bus *bus) DHD_BUS_BUSY_SET_IN_DPC(bus->dhd); DHD_GENERAL_UNLOCK(bus->dhd, flags); - resched = dhdpcie_bus_process_mailbox_intr(bus, bus->intstatus); if (!resched) { bus->intstatus = 0; bus->dpc_intr_enable_count++; - dhdpcie_bus_intr_enable(bus); /* Enable back interrupt using Intmask!! */ + /* For Linux, Macos etc (otherthan NDIS) enable back the host interrupts + * which has been disabled in the dhdpcie_bus_isr() + */ + dhdpcie_enable_irq(bus); /* Enable back interrupt!! */ + bus->dpc_exit_time = OSL_SYSUPTIME_US(); + } else { + bus->resched_dpc_time = OSL_SYSUPTIME_US(); } + bus->dpc_sched = resched; + DHD_GENERAL_LOCK(bus->dhd, flags); DHD_BUS_BUSY_CLEAR_IN_DPC(bus->dhd); dhd_os_busbusy_wake(bus->dhd); @@ -6621,12 +6428,10 @@ dhd_bus_dpc(struct dhd_bus *bus) } - int dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data) { uint32 cur_h2d_mb_data = 0; - unsigned long flags; DHD_INFO_HW4(("%s: H2D_MB_DATA: 0x%08X\n", __FUNCTION__, h2d_mb_data)); @@ -6635,22 +6440,17 @@ dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data) return BCME_ERROR; } - DHD_GENERAL_LOCK(bus->dhd, flags); - if (bus->api.fw_rev >= PCIE_SHARED_VERSION_6 && !bus->use_mailbox) { DHD_INFO(("API rev is 6, sending mb data as H2D Ctrl message to dongle, 0x%04x\n", h2d_mb_data)); /* Prevent asserting device_wake during doorbell ring for mb data to avoid loop. */ -#ifdef PCIE_OOB - bus->oob_enabled = FALSE; -#endif /* PCIE_OOB */ - if (dhd_prot_h2d_mbdata_send_ctrlmsg(bus->dhd, h2d_mb_data)) { - DHD_ERROR(("failure sending the H2D Mailbox message to firmware\n")); - goto fail; + { + if (dhd_prot_h2d_mbdata_send_ctrlmsg(bus->dhd, h2d_mb_data)) { + DHD_ERROR(("failure sending the H2D Mailbox message " + "to firmware\n")); + goto fail; + } } -#ifdef PCIE_OOB - bus->oob_enabled = TRUE; -#endif /* PCIE_OOB */ goto done; } @@ -6677,10 +6477,6 @@ dhdpcie_send_mb_data(dhd_bus_t *bus, uint32 h2d_mb_data) done: if (h2d_mb_data == H2D_HOST_D3_INFORM) { DHD_INFO_HW4(("%s: send H2D_HOST_D3_INFORM to dongle\n", __FUNCTION__)); - /* Mark D3_INFORM in the atomic context to - * skip ringing H2D DB after D3_INFORM - */ - bus->d3_suspend_pending = TRUE; bus->d3_inform_cnt++; } if (h2d_mb_data == H2D_HOST_D0_INFORM_IN_USE) { @@ -6691,20 +6487,38 @@ done: DHD_INFO_HW4(("%s: send H2D_HOST_D0_INFORM to dongle\n", __FUNCTION__)); bus->d0_inform_cnt++; } - DHD_GENERAL_UNLOCK(bus->dhd, flags); return BCME_OK; - fail: - DHD_GENERAL_UNLOCK(bus->dhd, flags); return BCME_ERROR; } +static void +dhd_bus_handle_d3_ack(dhd_bus_t *bus) +{ + unsigned long flags_bus; + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + bus->suspend_intr_disable_count++; + /* Disable dongle Interrupts Immediately after D3 */ + + /* For Linux, Macos etc (otherthan NDIS) along with disabling + * dongle interrupt by clearing the IntMask, disable directly + * interrupt from the host side as well. Also clear the intstatus + * if it is set to avoid unnecessary intrrupts after D3 ACK. + */ + dhdpcie_bus_intr_disable(bus); /* Disable interrupt using IntMask!! */ + dhdpcie_bus_clear_intstatus(bus); + dhdpcie_disable_irq_nosync(bus); /* Disable host interrupt!! */ + + /* Set bus_low_power_state to DHD_BUS_D3_ACK_RECIEVED */ + bus->bus_low_power_state = DHD_BUS_D3_ACK_RECIEVED; + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); + bus->wait_for_d3_ack = 1; + dhd_os_d3ack_wake(bus->dhd); +} void dhd_bus_handle_mb_data(dhd_bus_t *bus, uint32 d2h_mb_data) { -#ifdef PCIE_INB_DW - unsigned long flags = 0; -#endif + DHD_INFO(("D2H_MB_DATA: 0x%04x\n", d2h_mb_data)); if (d2h_mb_data & D2H_DEV_FWHALT) { @@ -6719,100 +6533,40 @@ dhd_bus_handle_mb_data(dhd_bus_t *bus, uint32 d2h_mb_data) return; } if (d2h_mb_data & D2H_DEV_DS_ENTER_REQ) { - if ((bus->dhd->busstate == DHD_BUS_SUSPEND || bus->d3_suspend_pending) && - bus->wait_for_d3_ack) { + bool ds_acked = FALSE; + BCM_REFERENCE(ds_acked); + if (bus->bus_low_power_state == DHD_BUS_D3_ACK_RECIEVED) { DHD_ERROR(("DS-ENTRY AFTER D3-ACK!!!!! QUITING\n")); bus->dhd->busstate = DHD_BUS_DOWN; return; } /* what should we do */ DHD_INFO(("D2H_MB_DATA: DEEP SLEEP REQ\n")); -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == DW_DEVICE_DS_ACTIVE) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_DEV_SLEEP_PEND); - if (bus->host_active_cnt == 0) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_DEV_SLEEP); - dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK); - } - } - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - dhd_os_ds_enter_wake(bus->dhd); - } else -#endif /* PCIE_INB_DW */ { dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK); + DHD_INFO(("D2H_MB_DATA: sent DEEP SLEEP ACK\n")); } - if (IDMA_DS_ENAB(bus->dhd)) { - bus->dongle_in_ds = TRUE; - } - DHD_INFO(("D2H_MB_DATA: sent DEEP SLEEP ACK\n")); } if (d2h_mb_data & D2H_DEV_DS_EXIT_NOTE) { /* what should we do */ - bus->dongle_in_ds = FALSE; DHD_INFO(("D2H_MB_DATA: DEEP SLEEP EXIT\n")); -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - bus->inband_ds_exit_device_cnt++; - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_DS_DISABLED_WAIT) { - /* wake up only if some one is waiting in - * DW_DEVICE_DS_DISABLED_WAIT state - * in this case the waiter will change the state - * to DW_DEVICE_DS_DEV_WAKE - */ - bus->wait_for_ds_exit = 1; - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - dhd_os_ds_exit_wake(bus->dhd); - } else { - DHD_INFO(("D2H_MB_DATA: not in DW_DEVICE_DS_DISABLED_WAIT!\n")); - /* - * If there is no one waiting, then update the state from here - */ - bus->wait_for_ds_exit = 1; - dhdpcie_bus_set_pcie_inband_dw_state(bus, - DW_DEVICE_DS_DEV_WAKE); - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - } - } -#endif /* PCIE_INB_DW */ } if (d2h_mb_data & D2HMB_DS_HOST_SLEEP_EXIT_ACK) { /* what should we do */ DHD_INFO(("D2H_MB_DATA: D0 ACK\n")); -#ifdef PCIE_INB_DW - if (INBAND_DW_ENAB(bus)) { - DHD_BUS_INB_DW_LOCK(bus->inb_lock, flags); - if (dhdpcie_bus_get_pcie_inband_dw_state(bus) == - DW_DEVICE_HOST_WAKE_WAIT) { - dhdpcie_bus_set_pcie_inband_dw_state(bus, DW_DEVICE_DS_ACTIVE); - } - DHD_BUS_INB_DW_UNLOCK(bus->inb_lock, flags); - } -#endif /* PCIE_INB_DW */ } if (d2h_mb_data & D2H_DEV_D3_ACK) { /* what should we do */ DHD_INFO_HW4(("D2H_MB_DATA: D3 ACK\n")); if (!bus->wait_for_d3_ack) { - /* Disable dongle Interrupts Immediately after D3 */ - bus->suspend_intr_disable_count++; - dhdpcie_bus_intr_disable(bus); #if defined(DHD_HANG_SEND_UP_TEST) if (bus->dhd->req_hang_type == HANG_REASON_D3_ACK_TIMEOUT) { DHD_ERROR(("TEST HANG: Skip to process D3 ACK\n")); } else { - bus->wait_for_d3_ack = 1; - dhd_os_d3ack_wake(bus->dhd); + dhd_bus_handle_d3_ack(bus); } #else /* DHD_HANG_SEND_UP_TEST */ - bus->wait_for_d3_ack = 1; - dhd_os_d3ack_wake(bus->dhd); + dhd_bus_handle_d3_ack(bus); #endif /* DHD_HANG_SEND_UP_TEST */ } } @@ -6843,15 +6597,11 @@ dhdpcie_handle_mb_data(dhd_bus_t *bus) /* what should we do */ DHD_INFO(("D2H_MB_DATA: DEEP SLEEP REQ\n")); dhdpcie_send_mb_data(bus, H2D_HOST_DS_ACK); - if (IDMA_DS_ENAB(bus->dhd)) { - bus->dongle_in_ds = TRUE; - } DHD_INFO(("D2H_MB_DATA: sent DEEP SLEEP ACK\n")); } if (d2h_mb_data & D2H_DEV_DS_EXIT_NOTE) { /* what should we do */ DHD_INFO(("D2H_MB_DATA: DEEP SLEEP EXIT\n")); - bus->dongle_in_ds = FALSE; } if (d2h_mb_data & D2H_DEV_D3_ACK) { /* what should we do */ @@ -6861,12 +6611,10 @@ dhdpcie_handle_mb_data(dhd_bus_t *bus) if (bus->dhd->req_hang_type == HANG_REASON_D3_ACK_TIMEOUT) { DHD_ERROR(("TEST HANG: Skip to process D3 ACK\n")); } else { - bus->wait_for_d3_ack = 1; - dhd_os_d3ack_wake(bus->dhd); + dhd_bus_handle_d3_ack(bus); } #else /* DHD_HANG_SEND_UP_TEST */ - bus->wait_for_d3_ack = 1; - dhd_os_d3ack_wake(bus->dhd); + dhd_bus_handle_d3_ack(bus); #endif /* DHD_HANG_SEND_UP_TEST */ } } @@ -6878,6 +6626,11 @@ dhdpcie_read_handle_mb_data(dhd_bus_t *bus) uint32 d2h_mb_data = 0; uint32 zero = 0; + if (bus->is_linkdown) { + DHD_ERROR(("%s: PCIe link is down\n", __FUNCTION__)); + return; + } + dhd_bus_cmn_readshared(bus, &d2h_mb_data, D2H_MB_DATA, 0); if (!d2h_mb_data) return; @@ -6904,15 +6657,25 @@ dhdpcie_bus_process_mailbox_intr(dhd_bus_t *bus, uint32 intstatus) if (intstatus & (PCIE_MB_TOPCIE_FN0_0 | PCIE_MB_TOPCIE_FN0_1)) bus->api.handle_mb_data(bus); - if ((bus->dhd->busstate == DHD_BUS_SUSPEND) || - (bus->use_mailbox && bus->d3_suspend_pending)) { + if ((bus->dhd->busstate == DHD_BUS_SUSPEND) || (bus->use_mailbox && + (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE))) { DHD_ERROR(("%s: Bus is in power save state. " "Skip processing rest of ring buffers.\n", __FUNCTION__)); goto exit; } - if (intstatus & PCIE_MB_D2H_MB_MASK) { + /* Validate intstatus only for INTX case */ + if ((bus->d2h_intr_method == PCIE_MSI) || + ((bus->d2h_intr_method == PCIE_INTX) && (intstatus & bus->d2h_mb_mask))) { +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + if (pm_runtime_get(dhd_bus_to_dev(bus)) >= 0) { + resched = dhdpci_bus_read_frames(bus); + pm_runtime_mark_last_busy(dhd_bus_to_dev(bus)); + pm_runtime_put_autosuspend(dhd_bus_to_dev(bus)); + } +#else resched = dhdpci_bus_read_frames(bus); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ } } @@ -6936,11 +6699,12 @@ dhdpci_bus_read_frames(dhd_bus_t *bus) DHD_PERIM_LOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT)); dhd_prot_process_ctrlbuf(bus->dhd); + bus->last_process_ctrlbuf_time = OSL_SYSUPTIME_US(); /* Unlock to give chance for resp to be handled */ DHD_PERIM_UNLOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT)); /* Do not process rest of ring buf once bus enters low power state */ - if (!bus->use_mailbox && bus->d3_suspend_pending) { + if (!bus->use_mailbox && (bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE)) { DHD_ERROR(("%s: Bus is in power save state. " "Skip processing rest of ring buffers.\n", __FUNCTION__)); return FALSE; @@ -6949,19 +6713,23 @@ dhdpci_bus_read_frames(dhd_bus_t *bus) DHD_PERIM_LOCK_ALL((bus->dhd->fwder_unit % FWDER_MAX_UNIT)); /* update the flow ring cpls */ dhd_update_txflowrings(bus->dhd); + bus->last_process_flowring_time = OSL_SYSUPTIME_US(); /* With heavy TX traffic, we could get a lot of TxStatus * so add bound */ more |= dhd_prot_process_msgbuf_txcpl(bus->dhd, dhd_txbound); + bus->last_process_txcpl_time = OSL_SYSUPTIME_US(); /* With heavy RX traffic, this routine potentially could spend some time * processing RX frames without RX bound */ more |= dhd_prot_process_msgbuf_rxcpl(bus->dhd, dhd_rxbound); + bus->last_process_rxcpl_time = OSL_SYSUPTIME_US(); /* Process info ring completion messages */ more |= dhd_prot_process_msgbuf_infocpl(bus->dhd, DHD_INFORING_BOUND); + bus->last_process_infocpl_time = OSL_SYSUPTIME_US(); #ifdef IDLE_TX_FLOW_MGMT if (bus->enable_idle_flowring_mgmt) { @@ -6979,7 +6747,8 @@ dhdpci_bus_read_frames(dhd_bus_t *bus) #ifdef SUPPORT_LINKDOWN_RECOVERY if (bus->read_shm_fail) { /* Read interrupt state once again to confirm linkdown */ - int intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, PCIMailBoxInt, 0, 0); + int intstatus = si_corereg(bus->sih, bus->sih->buscoreidx, + bus->pcie_mailbox_int, 0, 0); if (intstatus != (uint32)-1) { DHD_ERROR(("%s: read SHM failed but intstatus is valid\n", __FUNCTION__)); #ifdef DHD_FW_COREDUMP @@ -7079,6 +6848,7 @@ dhdpcie_readshared(dhd_bus_t *bus) uint32 shaddr = 0; pciedev_shared_t *sh = bus->pcie_sh; dhd_timeout_t tmo; + bool idma_en = FALSE; shaddr = bus->dongle_ram_base + bus->ramsize - 4; /* start a timer for 5 seconds */ @@ -7095,7 +6865,11 @@ dhdpcie_readshared(dhd_bus_t *bus) __FUNCTION__, addr)); DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed)); #ifdef DEBUG_DNGL_INIT_FAIL +#ifdef CUSTOMER_HW4_DEBUG bus->dhd->memdump_enabled = DUMP_MEMFILE_BUGON; +#else + dhd_get_memdump_info(bus->dhd); +#endif /* CUSTOMER_HW4_DEBUG */ bus->dhd->memdump_type = DUMP_TYPE_DONGLE_INIT_FAILURE; dhdpcie_mem_dump(bus); #endif /* DEBUG_DNGL_INIT_FAIL */ @@ -7158,13 +6932,22 @@ dhdpcie_readshared(dhd_bus_t *bus) } #endif /* IDLE_TX_FLOW_MGMT */ - bus->dhd->idma_enable = (sh->flags & PCIE_SHARED_IDMA) ? TRUE : FALSE; - bus->dhd->ifrm_enable = (sh->flags & PCIE_SHARED_IFRM) ? TRUE : FALSE; + if (IDMA_CAPABLE(bus)) { + if (bus->sih->buscorerev == 23) { + } else { + idma_en = TRUE; + } + } - bus->dhd->idma_retention_ds = (sh->flags & PCIE_SHARED_IDMA_RETENTION_DS) ? TRUE : FALSE; + if (idma_en) { + bus->dhd->idma_enable = (sh->flags & PCIE_SHARED_IDMA) ? TRUE : FALSE; + bus->dhd->ifrm_enable = (sh->flags & PCIE_SHARED_IFRM) ? TRUE : FALSE; + } bus->dhd->d2h_sync_mode = sh->flags & PCIE_SHARED_D2H_SYNC_MODE_MASK; + bus->dhd->dar_enable = (sh->flags & PCIE_SHARED_DAR) ? TRUE : FALSE; + /* Does the FW support DMA'ing r/w indices */ if (sh->flags & PCIE_SHARED_DMA_INDEX) { if (!bus->dhd->dma_ring_upd_overwrite) { @@ -7192,6 +6975,17 @@ dhdpcie_readshared(dhd_bus_t *bus) bus->dhd->dma_d2h_ring_upd_support = FALSE; } + /* Does the firmware support fast delete ring? */ + if (sh->flags2 & PCIE_SHARED2_FAST_DELETE_RING) { + DHD_INFO(("%s: Firmware supports fast delete ring\n", + __FUNCTION__)); + bus->dhd->fast_delete_ring_support = TRUE; + } else { + DHD_INFO(("%s: Firmware does not support fast delete ring\n", + __FUNCTION__)); + bus->dhd->fast_delete_ring_support = FALSE; + } + /* get ring_info, ring_state and mb data ptrs and store the addresses in bus structure */ { ring_info_t ring_info; @@ -7203,7 +6997,6 @@ dhdpcie_readshared(dhd_bus_t *bus) bus->h2d_mb_data_ptr_addr = ltoh32(sh->h2d_mb_data_ptr); bus->d2h_mb_data_ptr_addr = ltoh32(sh->d2h_mb_data_ptr); - if (bus->api.fw_rev >= PCIE_SHARED_VERSION_6) { bus->max_tx_flowrings = ltoh16(ring_info.max_tx_flowrings); bus->max_submission_rings = ltoh16(ring_info.max_submission_queues); @@ -7301,23 +7094,12 @@ dhdpcie_readshared(dhd_bus_t *bus) bus->dhd->d2h_hostrdy_supported = ((sh->flags & PCIE_SHARED_HOSTRDY_SUPPORT) == PCIE_SHARED_HOSTRDY_SUPPORT); -#ifdef PCIE_OOB - bus->dhd->d2h_no_oob_dw = (sh->flags & PCIE_SHARED_NO_OOB_DW) ? TRUE : FALSE; -#endif /* PCIE_OOB */ - -#ifdef PCIE_INB_DW - bus->dhd->d2h_inband_dw = (sh->flags & PCIE_SHARED_INBAND_DS) ? TRUE : FALSE; -#endif /* PCIE_INB_DW */ - -#if defined(PCIE_OOB) && defined(PCIE_INB_DW) - DHD_ERROR(("FW supports Inband dw ? %s oob dw ? %s\n", - bus->dhd->d2h_inband_dw ? "Y":"N", - bus->dhd->d2h_no_oob_dw ? "N":"Y")); -#endif /* defined(PCIE_OOB) && defined(PCIE_INB_DW) */ - bus->dhd->ext_trap_data_supported = ((sh->flags2 & PCIE_SHARED2_EXTENDED_TRAP_DATA) == PCIE_SHARED2_EXTENDED_TRAP_DATA); + if ((sh->flags2 & PCIE_SHARED2_TXSTATUS_METADATA) == 0) + bus->dhd->pcie_txs_metadata_enable = 0; + return BCME_OK; } /* dhdpcie_readshared */ @@ -7447,28 +7229,17 @@ int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) bus->reg = si_setcore(bus->sih, PCIE2_CORE_ID, 0); ASSERT(bus->reg != NULL); + dhd_init_bus_lock(bus); + /* Set bus state according to enable result */ dhdp->busstate = DHD_BUS_DATA; - bus->d3_suspend_pending = FALSE; - -#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING) - if (bus->pcie_sh->flags2 & PCIE_SHARED_D2H_D11_TX_STATUS) { - uint32 flags2 = bus->pcie_sh->flags2; - uint32 addr; + bus->bus_low_power_state = DHD_BUS_NO_LOW_POWER_STATE; + dhdp->dhd_bus_busy_state = 0; - addr = bus->shared_addr + OFFSETOF(pciedev_shared_t, flags2); - flags2 |= PCIE_SHARED_H2D_D11_TX_STATUS; - ret = dhdpcie_bus_membytes(bus, TRUE, addr, - (uint8 *)&flags2, sizeof(flags2)); - if (ret < 0) { - DHD_ERROR(("%s: update flag bit (H2D_D11_TX_STATUS) failed\n", - __FUNCTION__)); - return ret; - } - bus->pcie_sh->flags2 = flags2; - bus->dhd->d11_tx_status = TRUE; + /* D11 status via PCIe completion header */ + if ((ret = dhdpcie_init_d11status(bus)) < 0) { + return ret; } -#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */ if (!dhd_download_fw_on_driverload) dhd_dpc_enable(bus->dhd); @@ -7485,14 +7256,6 @@ int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) bus->idletime = 0; #endif /* DHD_PCIE_RUNTIMEPM */ -#ifdef PCIE_INB_DW - /* Initialize the lock to serialize Device Wake Inband activities */ - if (!bus->inb_lock) { - bus->inb_lock = dhd_os_spin_lock_init(bus->dhd->osh); - } -#endif - - /* Make use_d0_inform TRUE for Rev 5 for backward compatibility */ if (bus->api.fw_rev < PCIE_SHARED_VERSION_6) { bus->use_d0_inform = TRUE; @@ -7515,101 +7278,116 @@ dhdpcie_init_shared_addr(dhd_bus_t *bus) dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val)); } - bool dhdpcie_chipmatch(uint16 vendor, uint16 device) { if (vendor != PCI_VENDOR_ID_BROADCOM) { -#ifndef DHD_EFI DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__, vendor, device)); -#endif /* DHD_EFI */ return (-ENODEV); } if ((device == BCM4350_D11AC_ID) || (device == BCM4350_D11AC2G_ID) || (device == BCM4350_D11AC5G_ID) || (device == BCM4350_CHIP_ID) || - (device == BCM43569_CHIP_ID)) + (device == BCM43569_CHIP_ID)) { return 0; + } if ((device == BCM4354_D11AC_ID) || (device == BCM4354_D11AC2G_ID) || - (device == BCM4354_D11AC5G_ID) || (device == BCM4354_CHIP_ID)) + (device == BCM4354_D11AC5G_ID) || (device == BCM4354_CHIP_ID)) { return 0; + } if ((device == BCM4356_D11AC_ID) || (device == BCM4356_D11AC2G_ID) || - (device == BCM4356_D11AC5G_ID) || (device == BCM4356_CHIP_ID)) + (device == BCM4356_D11AC5G_ID) || (device == BCM4356_CHIP_ID)) { return 0; + } if ((device == BCM4371_D11AC_ID) || (device == BCM4371_D11AC2G_ID) || - (device == BCM4371_D11AC5G_ID) || (device == BCM4371_CHIP_ID)) + (device == BCM4371_D11AC5G_ID) || (device == BCM4371_CHIP_ID)) { return 0; + } if ((device == BCM4345_D11AC_ID) || (device == BCM4345_D11AC2G_ID) || - (device == BCM4345_D11AC5G_ID) || BCM4345_CHIP(device)) + (device == BCM4345_D11AC5G_ID) || BCM4345_CHIP(device)) { return 0; + } if ((device == BCM43452_D11AC_ID) || (device == BCM43452_D11AC2G_ID) || - (device == BCM43452_D11AC5G_ID)) + (device == BCM43452_D11AC5G_ID)) { return 0; + } if ((device == BCM4335_D11AC_ID) || (device == BCM4335_D11AC2G_ID) || - (device == BCM4335_D11AC5G_ID) || (device == BCM4335_CHIP_ID)) + (device == BCM4335_D11AC5G_ID) || (device == BCM4335_CHIP_ID)) { return 0; + } if ((device == BCM43602_D11AC_ID) || (device == BCM43602_D11AC2G_ID) || - (device == BCM43602_D11AC5G_ID) || (device == BCM43602_CHIP_ID)) + (device == BCM43602_D11AC5G_ID) || (device == BCM43602_CHIP_ID)) { return 0; + } if ((device == BCM43569_D11AC_ID) || (device == BCM43569_D11AC2G_ID) || - (device == BCM43569_D11AC5G_ID) || (device == BCM43569_CHIP_ID)) + (device == BCM43569_D11AC5G_ID) || (device == BCM43569_CHIP_ID)) { return 0; + } if ((device == BCM4358_D11AC_ID) || (device == BCM4358_D11AC2G_ID) || - (device == BCM4358_D11AC5G_ID)) + (device == BCM4358_D11AC5G_ID)) { return 0; + } if ((device == BCM4349_D11AC_ID) || (device == BCM4349_D11AC2G_ID) || - (device == BCM4349_D11AC5G_ID) || (device == BCM4349_CHIP_ID)) + (device == BCM4349_D11AC5G_ID) || (device == BCM4349_CHIP_ID)) { return 0; + } if ((device == BCM4355_D11AC_ID) || (device == BCM4355_D11AC2G_ID) || - (device == BCM4355_D11AC5G_ID) || (device == BCM4355_CHIP_ID)) + (device == BCM4355_D11AC5G_ID) || (device == BCM4355_CHIP_ID)) { return 0; + } if ((device == BCM4359_D11AC_ID) || (device == BCM4359_D11AC2G_ID) || - (device == BCM4359_D11AC5G_ID)) + (device == BCM4359_D11AC5G_ID)) { return 0; + } if ((device == BCM43596_D11AC_ID) || (device == BCM43596_D11AC2G_ID) || - (device == BCM43596_D11AC5G_ID)) + (device == BCM43596_D11AC5G_ID)) { return 0; + } if ((device == BCM43597_D11AC_ID) || (device == BCM43597_D11AC2G_ID) || - (device == BCM43597_D11AC5G_ID)) + (device == BCM43597_D11AC5G_ID)) { return 0; + } if ((device == BCM4364_D11AC_ID) || (device == BCM4364_D11AC2G_ID) || - (device == BCM4364_D11AC5G_ID) || (device == BCM4364_CHIP_ID)) - return 0; - - if ((device == BCM4347_D11AC_ID) || (device == BCM4347_D11AC2G_ID) || - (device == BCM4347_D11AC5G_ID) || (device == BCM4347_CHIP_ID)) + (device == BCM4364_D11AC5G_ID) || (device == BCM4364_CHIP_ID)) { return 0; + } if ((device == BCM4361_D11AC_ID) || (device == BCM4361_D11AC2G_ID) || - (device == BCM4361_D11AC5G_ID) || (device == BCM4361_CHIP_ID)) + (device == BCM4361_D11AC5G_ID) || (device == BCM4361_CHIP_ID)) { + return 0; + } + if ((device == BCM4347_D11AC_ID) || (device == BCM4347_D11AC2G_ID) || + (device == BCM4347_D11AC5G_ID) || (device == BCM4347_CHIP_ID)) { return 0; + } if ((device == BCM4365_D11AC_ID) || (device == BCM4365_D11AC2G_ID) || - (device == BCM4365_D11AC5G_ID) || (device == BCM4365_CHIP_ID)) + (device == BCM4365_D11AC5G_ID) || (device == BCM4365_CHIP_ID)) { return 0; + } if ((device == BCM4366_D11AC_ID) || (device == BCM4366_D11AC2G_ID) || - (device == BCM4366_D11AC5G_ID) || (device == BCM4366_CHIP_ID)) + (device == BCM4366_D11AC5G_ID) || (device == BCM4366_CHIP_ID) || + (device == BCM43664_CHIP_ID) || (device == BCM43666_CHIP_ID)) { return 0; -#ifndef DHD_EFI + } DHD_ERROR(("%s: Unsupported vendor %x device %x\n", __FUNCTION__, vendor, device)); -#endif return (-ENODEV); } /* dhdpcie_chipmatch */ @@ -8110,7 +7888,6 @@ dhd_bus_check_idle_scan(dhd_bus_t *bus) return; } - /* scan the nodes in active list till it finds a non idle node */ void dhd_bus_idle_scan(dhd_bus_t *bus) @@ -8289,6 +8066,10 @@ dhd_bus_release_dongle(struct dhd_bus *bus) ASSERT(osh); if (bus->dhd) { +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + debugger_close(); +#endif /* DEBUGGER || DHD_DSCOPE */ + dongle_isolation = bus->dhd->dongle_isolation; dhdpcie_bus_release_dongle(bus, osh, dongle_isolation, TRUE); } @@ -8300,11 +8081,13 @@ dhd_bus_release_dongle(struct dhd_bus *bus) void dhdpcie_cto_init(struct dhd_bus *bus, bool enable) { + uint32 val; + if (enable) { dhdpcie_bus_cfg_write_dword(bus, PCI_INT_MASK, 4, PCI_CTO_INT_MASK | PCI_SBIM_MASK_SERR); - dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, SPROM_BACKPLANE_EN); - + val = dhdpcie_bus_cfg_read_dword(bus, PCI_SPROM_CONTROL, 4); + dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, val | SPROM_BACKPLANE_EN); if (bus->dhd->cto_threshold == 0) { bus->dhd->cto_threshold = PCIE_CTO_TO_THRESH_DEFAULT; } @@ -8318,7 +8101,8 @@ dhdpcie_cto_init(struct dhd_bus *bus, bool enable) PCIE_CTO_ENAB_MASK); } else { dhdpcie_bus_cfg_write_dword(bus, PCI_INT_MASK, 4, 0); - dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, 0); + val = dhdpcie_bus_cfg_read_dword(bus, PCI_SPROM_CONTROL, 4); + dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, val & ~SPROM_BACKPLANE_EN); si_corereg(bus->sih, bus->sih->buscoreidx, OFFSETOF(sbpcieregs_t, ctoctrl), ~0, 0); @@ -8330,6 +8114,7 @@ dhdpcie_cto_error_recovery(struct dhd_bus *bus) { uint32 pci_intmask, err_status; uint8 i = 0; + uint32 val; pci_intmask = dhdpcie_bus_cfg_read_dword(bus, PCI_INT_MASK, 4); dhdpcie_bus_cfg_write_dword(bus, PCI_INT_MASK, 4, pci_intmask & ~PCI_CTO_INT_MASK); @@ -8337,16 +8122,17 @@ dhdpcie_cto_error_recovery(struct dhd_bus *bus) DHD_OS_WAKE_LOCK(bus->dhd); /* reset backplane */ - dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, SPROM_CFG_TO_SB_RST); + val = dhdpcie_bus_cfg_read_dword(bus, PCI_SPROM_CONTROL, 4); + dhdpcie_bus_cfg_write_dword(bus, PCI_SPROM_CONTROL, 4, val | SPROM_CFG_TO_SB_RST); /* clear timeout error */ while (1) { err_status = si_corereg(bus->sih, bus->sih->buscoreidx, - OFFSETOF(sbpcieregs_t, dm_errlog), + DAR_ERRLOG(bus->sih->buscorerev), 0, 0); if (err_status & PCIE_CTO_ERR_MASK) { si_corereg(bus->sih, bus->sih->buscoreidx, - OFFSETOF(sbpcieregs_t, dm_errlog), + DAR_ERRLOG(bus->sih->buscorerev), ~0, PCIE_CTO_ERR_MASK); } else { break; @@ -8372,6 +8158,39 @@ dhdpcie_cto_error_recovery(struct dhd_bus *bus) DHD_OS_WAKE_UNLOCK(bus->dhd); } +#if defined(DBG_PKT_MON) || defined(DHD_PKT_LOGGING) +static int +dhdpcie_init_d11status(struct dhd_bus *bus) +{ + uint32 addr; + uint32 flags2; + int ret = 0; + + if (bus->pcie_sh->flags2 & PCIE_SHARED2_D2H_D11_TX_STATUS) { + flags2 = bus->pcie_sh->flags2; + addr = bus->shared_addr + OFFSETOF(pciedev_shared_t, flags2); + flags2 |= PCIE_SHARED2_H2D_D11_TX_STATUS; + ret = dhdpcie_bus_membytes(bus, TRUE, addr, + (uint8 *)&flags2, sizeof(flags2)); + if (ret < 0) { + DHD_ERROR(("%s: update flag bit (H2D_D11_TX_STATUS) failed\n", + __FUNCTION__)); + return ret; + } + bus->pcie_sh->flags2 = flags2; + bus->dhd->d11_tx_status = TRUE; + } + return ret; +} + +#else +static int +dhdpcie_init_d11status(struct dhd_bus *bus) +{ + return 0; +} +#endif /* DBG_PKT_MON || DHD_PKT_LOGGING */ + #ifdef BCMPCIE_OOB_HOST_WAKE int dhd_bus_oob_intr_register(dhd_pub_t *dhdp) @@ -8392,8 +8211,6 @@ dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable) } #endif /* BCMPCIE_OOB_HOST_WAKE */ - - bool dhdpcie_bus_get_pcie_hostready_supported(dhd_bus_t *bus) { @@ -8405,12 +8222,11 @@ dhd_pcie_dump_core_regs(dhd_pub_t * pub, uint32 index, uint32 first_addr, uint32 { dhd_bus_t *bus = pub->bus; uint32 coreoffset = index << 12; - uint32 core_addr = SI_ENUM_BASE + coreoffset; + uint32 core_addr = SI_ENUM_BASE(bus->sih) + coreoffset; uint32 value; - while (first_addr <= last_addr) { - core_addr = SI_ENUM_BASE + coreoffset + first_addr; + core_addr = SI_ENUM_BASE(bus->sih) + coreoffset + first_addr; if (si_backplane_access(bus->sih, core_addr, 4, &value, TRUE) != BCME_OK) { DHD_ERROR(("Invalid size/addr combination \n")); } @@ -8419,96 +8235,49 @@ dhd_pcie_dump_core_regs(dhd_pub_t * pub, uint32 index, uint32 first_addr, uint32 } } -#ifdef PCIE_OOB bool -dhdpcie_bus_get_pcie_oob_dw_supported(dhd_bus_t *bus) +dhdpcie_bus_get_pcie_idma_supported(dhd_bus_t *bus) { if (!bus->dhd) return FALSE; - if (bus->oob_enabled) { - return !bus->dhd->d2h_no_oob_dw; + else if (bus->idma_enabled) { + return bus->dhd->idma_enable; } else { return FALSE; } } -#endif /* PCIE_OOB */ -void -dhdpcie_bus_enab_pcie_dw(dhd_bus_t *bus, uint8 dw_option) -{ - DHD_ERROR(("ENABLING DW:%d\n", dw_option)); - bus->dw_option = dw_option; -} - -#ifdef PCIE_INB_DW bool -dhdpcie_bus_get_pcie_inband_dw_supported(dhd_bus_t *bus) +dhdpcie_bus_get_pcie_ifrm_supported(dhd_bus_t *bus) { if (!bus->dhd) return FALSE; - if (bus->inb_enabled) { - return bus->dhd->d2h_inband_dw; + else if (bus->ifrm_enabled) { + return bus->dhd->ifrm_enable; } else { return FALSE; } } -void -dhdpcie_bus_set_pcie_inband_dw_state(dhd_bus_t *bus, enum dhd_bus_ds_state state) -{ - if (!INBAND_DW_ENAB(bus)) - return; - - DHD_INFO(("%s:%d\n", __FUNCTION__, state)); - bus->dhd->ds_state = state; - if (state == DW_DEVICE_DS_DISABLED_WAIT || state == DW_DEVICE_DS_D3_INFORM_WAIT) { - bus->ds_exit_timeout = 100; - } - if (state == DW_DEVICE_HOST_WAKE_WAIT) { - bus->host_sleep_exit_timeout = 100; - } - if (state == DW_DEVICE_DS_DEV_WAKE) { - bus->ds_exit_timeout = 0; - } - if (state == DW_DEVICE_DS_ACTIVE) { - bus->host_sleep_exit_timeout = 0; - } -} - -enum dhd_bus_ds_state -dhdpcie_bus_get_pcie_inband_dw_state(dhd_bus_t *bus) -{ - if (!INBAND_DW_ENAB(bus)) - return DW_DEVICE_DS_INVALID; - return bus->dhd->ds_state; -} -#endif /* PCIE_INB_DW */ - bool -dhdpcie_bus_get_pcie_idma_supported(dhd_bus_t *bus) +dhdpcie_bus_get_pcie_dar_supported(dhd_bus_t *bus) { - if (!bus->dhd) + if (!bus->dhd) { return FALSE; - else if (bus->idma_enabled) { - return bus->dhd->idma_enable; + } else if (bus->dar_enabled) { + return bus->dhd->dar_enable; } else { return FALSE; } } -bool -dhdpcie_bus_get_pcie_ifrm_supported(dhd_bus_t *bus) +void +dhdpcie_bus_enab_pcie_dw(dhd_bus_t *bus, uint8 dw_option) { - if (!bus->dhd) - return FALSE; - else if (bus->ifrm_enabled) { - return bus->dhd->ifrm_enable; - } else { - return FALSE; - } + DHD_ERROR(("ENABLING DW:%d\n", dw_option)); + bus->dw_option = dw_option; } - void dhd_bus_dump_trap_info(dhd_bus_t *bus, struct bcmstrbuf *strbuf) { @@ -8592,12 +8361,13 @@ dhdpcie_get_sssr_fifo_dump(dhd_pub_t *dhd, uint *buf, uint fifo_size, } static int -dhdpcie_get_sssr_vasip_dump(dhd_pub_t *dhd, uint *buf, uint fifo_size, +dhdpcie_get_sssr_dig_dump(dhd_pub_t *dhd, uint *buf, uint fifo_size, uint addr_reg) { uint addr; uint val = 0; int i; + si_t *sih = dhd->bus->sih; DHD_ERROR(("%s\n", __FUNCTION__)); @@ -8611,24 +8381,131 @@ dhdpcie_get_sssr_vasip_dump(dhd_pub_t *dhd, uint *buf, uint fifo_size, return BCME_ERROR; } - /* Check if vasip clk is disabled, if yes enable it */ - addr = dhd->sssr_reg_info.vasip_regs.wrapper_regs.ioctrl; - dhd_sbreg_op(dhd, addr, &val, TRUE); - if (!val) { - val = 1; - dhd_sbreg_op(dhd, addr, &val, FALSE); - } + if (addr_reg) { + /* Check if vasip clk is disabled, if yes enable it */ + addr = dhd->sssr_reg_info.vasip_regs.wrapper_regs.ioctrl; + dhd_sbreg_op(dhd, addr, &val, TRUE); + if (!val) { + val = 1; + dhd_sbreg_op(dhd, addr, &val, FALSE); + } - addr = addr_reg; - /* Read 4 bytes at once and loop for fifo_size / 4 */ - for (i = 0; i < fifo_size / 4; i++, addr += 4) { - si_backplane_access(dhd->bus->sih, addr, sizeof(uint), &val, TRUE); - buf[i] = val; - OSL_DELAY(1); + addr = addr_reg; + /* Read 4 bytes at once and loop for fifo_size / 4 */ + for (i = 0; i < fifo_size / 4; i++, addr += 4) { + si_backplane_access(sih, addr, sizeof(uint), &val, TRUE); + buf[i] = val; + OSL_DELAY(1); + } + } else { + uint cur_coreid; + uint chipc_corerev; + chipcregs_t *chipcregs; + + /* Save the current core */ + cur_coreid = si_coreid(sih); + + /* Switch to ChipC */ + chipcregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); + + chipc_corerev = si_corerev(sih); + + if (chipc_corerev == 64) { + W_REG(si_osh(sih), &chipcregs->sr_memrw_addr, 0); + + /* Read 4 bytes at once and loop for fifo_size / 4 */ + for (i = 0; i < fifo_size / 4; i++) { + buf[i] = R_REG(si_osh(sih), &chipcregs->sr_memrw_data); + OSL_DELAY(1); + } + } + + /* Switch back to the original core */ + si_setcore(sih, cur_coreid, 0); } + return BCME_OK; } +#if defined(BCMPCIE) && defined(DHD_LOG_DUMP) +void +dhdpcie_get_etd_preserve_logs(dhd_pub_t *dhd, + uint8 *ext_trap_data, void *event_decode_data) +{ + hnd_ext_trap_hdr_t *hdr = NULL; + bcm_tlv_t *tlv; + eventlog_trapdata_info_t *etd_evtlog = NULL; + eventlog_trap_buf_info_t *evtlog_buf_arr = NULL; + uint arr_size = 0; + int i = 0; + int err = 0; + uint32 seqnum = 0; + + if (!ext_trap_data || !event_decode_data || !dhd) + return; + + if (!dhd->concise_dbg_buf) + return; + + /* First word is original trap_data, skip */ + ext_trap_data += sizeof(uint32); + + hdr = (hnd_ext_trap_hdr_t *)ext_trap_data; + tlv = bcm_parse_tlvs(hdr->data, hdr->len, TAG_TRAP_LOG_DATA); + if (tlv) { + etd_evtlog = (eventlog_trapdata_info_t *)tlv->data; + DHD_ERROR(("%s: etd_evtlog tlv found, num_elements=%x; " + "seq_num=%x; log_arr_addr=%x\n", __FUNCTION__, + (etd_evtlog->num_elements), + ntoh32(etd_evtlog->seq_num), (etd_evtlog->log_arr_addr))); + arr_size = (uint32)sizeof(*evtlog_buf_arr) * (etd_evtlog->num_elements); + if (!arr_size) { + DHD_ERROR(("%s: num event logs is zero! \n", __FUNCTION__)); + return; + } + evtlog_buf_arr = MALLOCZ(dhd->osh, arr_size); + if (!evtlog_buf_arr) { + DHD_ERROR(("%s: out of memory !\n", __FUNCTION__)); + return; + } + /* read the eventlog_trap_buf_info_t array from dongle memory */ + err = dhdpcie_bus_membytes(dhd->bus, FALSE, + (ulong)(etd_evtlog->log_arr_addr), + (uint8 *)evtlog_buf_arr, arr_size); + if (err != BCME_OK) { + DHD_ERROR(("%s: Error reading event log array from dongle !\n", + __FUNCTION__)); + goto err; + } + /* ntoh is required only for seq_num, because in the original + * case of event logs from info ring, it is sent from dongle in that way + * so for ETD also dongle follows same convention + */ + seqnum = ntoh32(etd_evtlog->seq_num); + memset(dhd->concise_dbg_buf, 0, CONCISE_DUMP_BUFLEN); + for (i = 0; i < (etd_evtlog->num_elements); ++i) { + /* read each individual event log buf from dongle memory */ + err = dhdpcie_bus_membytes(dhd->bus, FALSE, + ((ulong)evtlog_buf_arr[i].buf_addr), + dhd->concise_dbg_buf, (evtlog_buf_arr[i].len)); + if (err != BCME_OK) { + DHD_ERROR(("%s: Error reading event log buffer from dongle !\n", + __FUNCTION__)); + goto err; + } + dhd_dbg_msgtrace_log_parser(dhd, dhd->concise_dbg_buf, + event_decode_data, (evtlog_buf_arr[i].len), + FALSE, hton32(seqnum)); + ++seqnum; + } +err: + MFREE(dhd->osh, evtlog_buf_arr, arr_size); + } else { + DHD_ERROR(("%s: Error getting trap log data in ETD !\n", __FUNCTION__)); + } +} +#endif /* BCMPCIE && DHD_LOG_DUMP */ + static int dhdpcie_resume_chipcommon_powerctrl(dhd_pub_t *dhd) { @@ -8727,6 +8604,11 @@ dhdpcie_d11_check_outofreset(dhd_pub_t *dhd) for (i = 0; i < MAX_NUM_D11CORES; i++) { /* Check if bit 0 of resetctrl is cleared */ addr = dhd->sssr_reg_info.mac_regs[i].wrapper_regs.resetctrl; + if (!addr) { + DHD_ERROR(("%s: skipping for core[%d] as 'addr' is NULL\n", + __FUNCTION__, i)); + continue; + } dhd_sbreg_op(dhd, addr, &val, TRUE); if (!(val & 1)) { dhd->sssr_d11_outofreset[i] = TRUE; @@ -8902,7 +8784,7 @@ dhdpcie_sssr_dump_get_before_sr(dhd_pub_t *dhd) } if (dhd->sssr_reg_info.vasip_regs.vasip_sr_size) { - dhdpcie_get_sssr_vasip_dump(dhd, dhd->sssr_vasip_buf_before, + dhdpcie_get_sssr_dig_dump(dhd, dhd->sssr_dig_buf_before, dhd->sssr_reg_info.vasip_regs.vasip_sr_size, dhd->sssr_reg_info.vasip_regs.vasip_sr_addr); } @@ -8927,7 +8809,7 @@ dhdpcie_sssr_dump_get_after_sr(dhd_pub_t *dhd) } if (dhd->sssr_reg_info.vasip_regs.vasip_sr_size) { - dhdpcie_get_sssr_vasip_dump(dhd, dhd->sssr_vasip_buf_after, + dhdpcie_get_sssr_dig_dump(dhd, dhd->sssr_dig_buf_after, dhd->sssr_reg_info.vasip_regs.vasip_sr_size, dhd->sssr_reg_info.vasip_regs.vasip_sr_addr); } @@ -8983,9 +8865,6 @@ dhdpcie_sssr_dump(dhd_pub_t *dhd) wake_counts_t* dhd_bus_get_wakecount(dhd_pub_t *dhd) { - if (!dhd->bus) { - return NULL; - } return &dhd->bus->wake_counts; } int @@ -8995,27 +8874,404 @@ dhd_bus_get_bus_wake(dhd_pub_t *dhd) } #endif /* DHD_WAKE_STATUS */ -#ifdef BCM_ASLR_HEAP -/* Writes random number(s) to the TCM. FW upon initialization reads the metadata - * of the random number and then based on metadata, reads the random number from the TCM. +#define OTP_ADDRESS (SI_ENUM_BASE_DEFAULT + CC_SROM_OTP) +#define OTP_USER_AREA_OFFSET 0x80 +#define OTP_USER_AREA_ADDR (OTP_ADDRESS + OTP_USER_AREA_OFFSET) +#define OTP_VERSION_TUPLE_ID 0x15 +#define OTP_VENDOR_TUPLE_ID 0x80 +#define OTP_CIS_REGION_END_TUPLE_ID 0XFF +#define PMU_RES_STATE_REG_ADDR (SI_ENUM_BASE_DEFAULT + PMU_RES_STATE) +#define PMU_MINRESMASK_REG_ADDR (SI_ENUM_BASE_DEFAULT + MINRESMASKREG) +#define OTP_CTRL1_REG_ADDR (SI_ENUM_BASE_DEFAULT + 0xF4) +#define SPROM_CTRL_REG_ADDR (SI_ENUM_BASE_DEFAULT + CC_SROM_CTRL) +#define CHIP_COMMON_STATUS_REG_ADDR (SI_ENUM_BASE_DEFAULT + 0x2C) +#define PMU_OTP_PWR_ON_MASK 0xC47 + +int +dhdpcie_get_nvpath_otp(dhd_bus_t *bus, char* program, char *nv_path) +{ + uint32 val = 0; + uint16 chip_id = 0; + uint8 otp_data[2]; + char stepping[3]; + char module_name[5]; + char module_vendor = 0; + char module_rev[4]; + uint8 tuple_id = 0; + uint8 tuple_len = 0; + uint32 cur_offset = 0; + uint32 version_tuple_offset = 0; + char module_info[64]; + char progname[32]; + bool srom_present = 0, otp_present = 0; + uint32 sprom_ctrl = 0; + uint32 otp_ctrl = 0, minres_mask = 0; + int i = 0, j = 0, status = BCME_ERROR; + + if (!nv_path || !bus) { + return BCME_ERROR; + } + + /* read chip id first */ + if (si_backplane_access(bus->sih, SI_ENUM_BASE_DEFAULT, 4, &val, TRUE) != BCME_OK) { + DHD_ERROR(("%s: bkplane access error ! \n", __FUNCTION__)); + } + else { + chip_id = val & 0xffff; + } + + /* read SpromCtrl register */ + si_backplane_access(bus->sih, SPROM_CTRL_REG_ADDR, 4, &sprom_ctrl, TRUE); + val = sprom_ctrl; + + /* proceed only if OTP is present - i.e, the 5th bit OtpPresent is set + * and chip is 4355 or 4364 + */ + if ((val & 0x20) && (chip_id == 0x4355 || chip_id == 0x4364)) { + otp_present = 1; + + /* Check if the 4th bit (sprom_present) in CC Status REG is set */ + si_backplane_access(bus->sih, CHIP_COMMON_STATUS_REG_ADDR, 4, &val, TRUE); + if (val & 0x10) { + srom_present = 1; + } + + /* OTP power up sequence */ + /* 1. cache otp ctrl and enable OTP clock through OTPCtrl1 register */ + si_backplane_access(bus->sih, OTP_CTRL1_REG_ADDR, 4, &otp_ctrl, TRUE); + val = 0x1A0000; + si_backplane_access(bus->sih, OTP_CTRL1_REG_ADDR, 4, &val, FALSE); + + /* 2. enable OTP power through min res mask register in PMU */ + si_backplane_access(bus->sih, PMU_MINRESMASK_REG_ADDR, 4, &minres_mask, TRUE); + val = minres_mask | PMU_OTP_PWR_ON_MASK; + si_backplane_access(bus->sih, PMU_MINRESMASK_REG_ADDR, 4, &val, FALSE); + + /* 3. if srom is present, need to set OtpSelect 4th bit + * in SpromCtrl register to read otp + */ + if (srom_present) { + + val = sprom_ctrl | 0x10; + si_backplane_access(bus->sih, SPROM_CTRL_REG_ADDR, 4, &val, FALSE); + + } + /* Wait for PMU to power up. */ + OSL_DELAY(500); + si_backplane_access(bus->sih, PMU_RES_STATE_REG_ADDR, 4, &val, TRUE); + DHD_INFO(("%s: PMU_RES_STATE_REG_ADDR %x \n", __FUNCTION__, val)); + + si_backplane_access(bus->sih, SI_ENUM_BASE_DEFAULT, 4, &val, TRUE); + DHD_INFO(("%s: _SI_ENUM_BASE %x \n", __FUNCTION__, val)); + + si_backplane_access(bus->sih, OTP_ADDRESS, 2, &val, TRUE); + DHD_INFO(("%s: OTP_ADDRESS %x \n", __FUNCTION__, val)); + + cur_offset = OTP_USER_AREA_ADDR + 0x40; + /* read required data from otp to construct FW string name + * data like - chip info, module info. This is present in the + * form of a Vendor CIS Tuple whose format is provided by Olympic. + * The data is in the form of ASCII character strings. + * The Vendor tuple along with other CIS tuples are present + * in the OTP user area. A CIS tuple is a TLV format. + * (T = 1-byte, L = 1-byte, V = n-bytes) + */ + + /* Find the version tuple */ + while (tuple_id != OTP_CIS_REGION_END_TUPLE_ID) { + si_backplane_access(bus->sih, cur_offset, + 2, (uint *)otp_data, TRUE); + + tuple_id = otp_data[0]; + tuple_len = otp_data[1]; + if (tuple_id == OTP_VERSION_TUPLE_ID) { + version_tuple_offset = cur_offset; + break; + } + /* if its NULL tuple, skip */ + if (tuple_id == 0) + cur_offset += 1; + else + cur_offset += tuple_len + 2; + } + + /* skip the major, minor ver. numbers, manufacturer and product names */ + cur_offset = version_tuple_offset + 6; + + /* read the chip info */ + si_backplane_access(bus->sih, cur_offset, + 2, (uint *)otp_data, TRUE); + if (otp_data[0] == 's' && otp_data[1] == '=') { + /* read the stepping */ + cur_offset += 2; + stepping[2] = 0; + si_backplane_access(bus->sih, cur_offset, + 2, (uint *)stepping, TRUE); + /* read module info */ + memset(module_info, 0, 64); + cur_offset += 2; + si_backplane_access(bus->sih, cur_offset, + 2, (uint *)otp_data, TRUE); + while (otp_data[0] != OTP_CIS_REGION_END_TUPLE_ID && + otp_data[1] != OTP_CIS_REGION_END_TUPLE_ID) { + memcpy(&module_info[i], otp_data, 2); + i += 2; + cur_offset += 2; + si_backplane_access(bus->sih, cur_offset, + 2, (uint *)otp_data, TRUE); + } + /* replace any null characters found at the beginning + * and middle of the string + */ + for (j = 0; j < i; ++j) { + if (module_info[j] == 0) + module_info[j] = ' '; + } + DHD_ERROR(("OTP chip_info: s=%c%c; module info: %s \n", + stepping[0], stepping[1], module_info)); + /* extract the module name, revision and vendor + * information from the module info string + */ + for (i = 0; module_info[i]; i++) { + if (module_info[i] == 'M' && module_info[i + 1] == '=') { + memcpy(module_name, &module_info[i + 2], 4); + module_name[4] = 0; + i += 5; + } + else if (module_info[i] == 'm' && module_info[i + 1] == '=') { + memcpy(module_rev, &module_info[i + 2], 3); + module_rev[3] = 0; + i += 4; + } + else if (module_info[i] == 'V' && module_info[i + 1] == '=') { + module_vendor = module_info[i + 2]; + i += 2; + } + } + + /* construct the complete file path to nvram as per + * olympic conventions + */ + strncpy(progname, program, sizeof(progname)); + sprintf(nv_path, "P-%s_M-%s_V-%c__m-%s.txt", progname, module_name, + module_vendor, module_rev); + DHD_ERROR(("%s NVRAM path = %s\n", __FUNCTION__, nv_path)); + status = BCME_OK; + } + + /* restore back the registers to their previous values */ + if (srom_present) { + si_backplane_access(bus->sih, SPROM_CTRL_REG_ADDR, 4, &sprom_ctrl, FALSE); + } + + if (otp_present) { + si_backplane_access(bus->sih, PMU_MINRESMASK_REG_ADDR, 4, + &minres_mask, FALSE); + si_backplane_access(bus->sih, OTP_CTRL1_REG_ADDR, 4, &otp_ctrl, FALSE); + } + + } + return status; +} + +/* Writes random number(s) to the TCM. FW upon initialization reads this register + * to fetch the random number, and uses it to randomize heap address space layout. */ static void dhdpcie_wrt_rnd(struct dhd_bus *bus) { bcm_rand_metadata_t rnd_data; - uint32 rand_no; - uint32 count = 1; /* start with 1 random number */ + uint8 rand_buf[BCM_ENTROPY_HOST_NBYTES]; + uint32 count = BCM_ENTROPY_HOST_NBYTES; uint32 addr = bus->dongle_ram_base + (bus->ramsize - BCM_NVRAM_OFFSET_TCM) - ((bus->nvram_csm & 0xffff)* BCM_NVRAM_IMG_COMPRS_FACTOR + sizeof(rnd_data)); - rnd_data.signature = htol32(BCM_RNG_SIGNATURE); + rnd_data.signature = htol32(BCM_NVRAM_RNG_SIGNATURE); rnd_data.count = htol32(count); /* write the metadata about random number */ dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&rnd_data, sizeof(rnd_data)); /* scale back by number of random number counts */ - addr -= sizeof(count) * count; + addr -= count; /* Now write the random number(s) */ - rand_no = htol32(dhd_get_random_number()); - dhdpcie_bus_membytes(bus, TRUE, addr, (uint8 *)&rand_no, sizeof(rand_no)); + dhd_get_random_bytes(rand_buf, count); + dhdpcie_bus_membytes(bus, TRUE, addr, rand_buf, count); +} + +void +dhd_pcie_intr_count_dump(dhd_pub_t *dhd) +{ + DHD_ERROR(("\n ------- DUMPING INTR enable/disable counters ------- \r\n")); + DHD_ERROR(("resume_intr_enable_count=%lu dpc_intr_enable_count=%lu\n", + dhd->bus->resume_intr_enable_count, dhd->bus->dpc_intr_enable_count)); + DHD_ERROR(("isr_intr_disable_count=%lu suspend_intr_disable_count=%lu\n", + dhd->bus->isr_intr_disable_count, dhd->bus->suspend_intr_disable_count)); +#ifdef BCMPCIE_OOB_HOST_WAKE + DHD_ERROR(("oob_intr_count=%lu oob_intr_enable_count=%lu oob_intr_disable_count=%lu\n", + dhd->bus->oob_intr_count, dhd->bus->oob_intr_enable_count, + dhd->bus->oob_intr_disable_count)); + DHD_ERROR(("oob_irq_num=%d last_oob_irq_time=%llu\n", + dhdpcie_get_oob_irq_num(dhd->bus), dhd->bus->last_oob_irq_time)); +#endif /* BCMPCIE_OOB_HOST_WAKE */ + DHD_ERROR(("dpc_return_busdown_count=%lu\n", + dhd->bus->dpc_return_busdown_count)); + + DHD_ERROR(("\ncurrent_time=%llu isr_entry_time=%llu isr_exit_time=%llu\n", + OSL_SYSUPTIME_US(), dhd->bus->isr_entry_time, dhd->bus->isr_exit_time)); + DHD_ERROR(("dpc_entry_time=%llu last_process_ctrlbuf_time=%llu\n", + dhd->bus->dpc_entry_time, dhd->bus->last_process_ctrlbuf_time)); + DHD_ERROR(("last_process_flowring_time=%llu last_process_txcpl_time=%llu\n", + dhd->bus->last_process_flowring_time, dhd->bus->last_process_txcpl_time)); + DHD_ERROR(("last_process_rxcpl_time=%llu last_process_infocpl_time=%llu\n", + dhd->bus->last_process_rxcpl_time, dhd->bus->last_process_infocpl_time)); + DHD_ERROR(("dpc_exit_time=%llu resched_dpc_time=%llu\n", + dhd->bus->dpc_exit_time, dhd->bus->resched_dpc_time)); + + DHD_ERROR(("\nlast_suspend_start_time=%llu last_suspend_end_time=%llu\n", + dhd->bus->last_suspend_start_time, dhd->bus->last_suspend_end_time)); + DHD_ERROR(("last_resume_start_time=%llu last_resume_end_time=%llu\n", + dhd->bus->last_resume_start_time, dhd->bus->last_resume_end_time)); +} + +void +dhd_bus_intr_count_dump(dhd_pub_t *dhd) +{ + dhd_pcie_intr_count_dump(dhd); +} + +int +dhd_pcie_dma_info_dump(dhd_pub_t *dhd) +{ + if (dhd->bus->is_linkdown) { + DHD_ERROR(("\n ------- SKIP DUMPING DMA Registers " + "due to PCIe link down ------- \r\n")); + return 0; + } + + DHD_ERROR(("\n ------- DUMPING DMA Registers ------- \r\n")); + + //HostToDev + DHD_ERROR(("HostToDev TX: XmtCtrl=0x%08x XmtPtr=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x200, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x204, 0, 0))); + DHD_ERROR((" : XmtAddrLow=0x%08x XmtAddrHigh=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x208, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x20C, 0, 0))); + DHD_ERROR((" : XmtStatus0=0x%08x XmtStatus1=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x210, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x214, 0, 0))); + + DHD_ERROR(("HostToDev RX: RcvCtrl=0x%08x RcvPtr=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x220, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x224, 0, 0))); + DHD_ERROR((" : RcvAddrLow=0x%08x RcvAddrHigh=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x228, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x22C, 0, 0))); + DHD_ERROR((" : RcvStatus0=0x%08x RcvStatus1=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x230, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x234, 0, 0))); + + //DevToHost + DHD_ERROR(("DevToHost TX: XmtCtrl=0x%08x XmtPtr=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x240, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x244, 0, 0))); + DHD_ERROR((" : XmtAddrLow=0x%08x XmtAddrHigh=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x248, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x24C, 0, 0))); + DHD_ERROR((" : XmtStatus0=0x%08x XmtStatus1=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x250, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x254, 0, 0))); + + DHD_ERROR(("DevToHost RX: RcvCtrl=0x%08x RcvPtr=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x260, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x264, 0, 0))); + DHD_ERROR((" : RcvAddrLow=0x%08x RcvAddrHigh=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x268, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x26C, 0, 0))); + DHD_ERROR((" : RcvStatus0=0x%08x RcvStatus1=0x%08x\n", + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x270, 0, 0), + si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, 0x274, 0, 0))); + + return 0; +} + +int +dhd_pcie_debug_info_dump(dhd_pub_t *dhd) +{ + uint32 intstatus = 0; + uint32 intmask = 0; + uint32 mbintstatus = 0; + uint32 d2h_mb_data = 0; + int host_irq_disabled; + + DHD_ERROR(("bus->bus_low_power_state = %d\n", dhd->bus->bus_low_power_state)); + host_irq_disabled = dhdpcie_irq_disabled(dhd->bus); + DHD_ERROR(("host pcie_irq disabled = %d\n", host_irq_disabled)); + dhd_print_tasklet_status(dhd); + dhd_pcie_intr_count_dump(dhd); + + DHD_ERROR(("\n ------- DUMPING PCIE RC config space Registers ------- \r\n")); + DHD_ERROR(("Pcie RC Error Status Val=0x%x\n", + dhdpcie_rc_access_cap(dhd->bus, PCIE_EXTCAP_ID_ERR, + PCIE_EXTCAP_AER_UCERR_OFFSET, TRUE, FALSE, 0))); + + DHD_ERROR(("RootPort PCIe linkcap=0x%08x\n", + dhd_debug_get_rc_linkcap(dhd->bus))); + +#ifdef CUSTOMER_HW4_DEBUG + if (dhd->bus->is_linkdown) { + DHD_ERROR(("Skip dumping the PCIe registers due to PCIe Link down\n")); + return 0; + } +#endif /* CUSTOMER_HW4_DEBUG */ + + DHD_ERROR(("\n ------- DUMPING PCIE EP config space Registers ------- \r\n")); + DHD_ERROR(("Status Command(0x%x)=0x%x, BaseAddress0(0x%x)=0x%x BaseAddress1(0x%x)=0x%x\n", + PCIECFGREG_STATUS_CMD, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_STATUS_CMD, sizeof(uint32)), + PCIECFGREG_BASEADDR0, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_BASEADDR0, sizeof(uint32)), + PCIECFGREG_BASEADDR1, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_BASEADDR1, sizeof(uint32)))); + DHD_ERROR(("LinkCtl(0x%x)=0x%x DeviceStatusControl2(0x%x)=0x%x " + "L1SSControl(0x%x)=0x%x\n", PCIECFGREG_LINK_STATUS_CTRL, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_LINK_STATUS_CTRL, + sizeof(uint32)), PCIECFGGEN_DEV_STATUS_CTRL2, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGGEN_DEV_STATUS_CTRL2, + sizeof(uint32)), PCIECFGREG_PML1_SUB_CTRL1, + dhd_pcie_config_read(dhd->bus->osh, PCIECFGREG_PML1_SUB_CTRL1, + sizeof(uint32)))); + + intstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + dhd->bus->pcie_mailbox_int, 0, 0); + if (intstatus == (uint32)-1) { + DHD_ERROR(("Skip dumping the PCIe Core registers due to invalid intstatus\n")); + return 0; + } + + intmask = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + dhd->bus->pcie_mailbox_mask, 0, 0); + mbintstatus = si_corereg(dhd->bus->sih, dhd->bus->sih->buscoreidx, + PCID2H_MailBox, 0, 0); + DHD_ERROR(("\n ------- DUMPING INTR Status and Masks ------- \r\n")); + DHD_ERROR(("intstatus=0x%x intmask=0x%x mbintstatus=0x%x\n", + intstatus, intmask, mbintstatus)); + + dhd_bus_cmn_readshared(dhd->bus, &d2h_mb_data, D2H_MB_DATA, 0); + DHD_ERROR(("d2h_mb_data=0x%x def_intmask=0x%x \r\n", d2h_mb_data, + dhd->bus->def_intmask)); + + DHD_ERROR(("\n ------- DUMPING PCIE core Registers ------- \r\n")); + DHD_ERROR(("ClkReq0(0x%x)=0x%x ClkReq1(0x%x)=0x%x ClkReq2(0x%x)=0x%x " + "ClkReq3(0x%x)=0x%x\n", PCIECFGREG_PHY_DBG_CLKREQ0, + dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ0), + PCIECFGREG_PHY_DBG_CLKREQ1, + dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ1), + PCIECFGREG_PHY_DBG_CLKREQ2, + dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ2), + PCIECFGREG_PHY_DBG_CLKREQ3, + dhd_pcie_corereg_read(dhd->bus->sih, PCIECFGREG_PHY_DBG_CLKREQ3))); + + dhd_pcie_dma_info_dump(dhd); + + return 0; } -#endif /* BCM_ASLR_HEAP */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pcie.h b/drivers/net/wireless/bcmdhd_oo/dhd_pcie.h index 3163f14c4698067bb4d43383a7ee557a81fc2a52..1b9e2b7bdfc5e5fa58cc8c84bf07efc3574a2c91 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pcie.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pcie.h @@ -1,14 +1,14 @@ /* * Linux DHD Bus Module for PCIE * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,10 +24,9 @@ * * <> * - * $Id: dhd_pcie.h 727682 2017-10-23 04:45:57Z $ + * $Id: dhd_pcie.h 740024 2018-01-10 12:20:47Z $ */ - #ifndef dhd_pcie_h #define dhd_pcie_h @@ -42,11 +41,12 @@ #endif /* CONFIG_PCI_MSM */ #endif /* CONFIG_ARCH_MSM */ #ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY -#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) #include extern int exynos_pcie_register_event(struct exynos_pcie_register_event *reg); extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); -#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 */ +#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ #endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -59,7 +59,6 @@ extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); #define CUSTOM_DHD_RUNTIME_MS DEFAULT_DHD_RUNTIME_MS #endif /* CUSTOM_DHD_RUNTIME_MS */ - #ifndef MAX_IDLE_COUNT #define MAX_IDLE_COUNT 16 #endif /* MAX_IDLE_COUNT */ @@ -70,6 +69,7 @@ extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); #endif /* DHD_PCIE_RUNTIMEPM */ /* defines */ +#define PCIE_SHARED_VERSION PCIE_SHARED_VERSION_7 #define PCMSGBUF_HDRLEN 0 #define DONGLE_REG_MAP_SIZE (32 * 1024) @@ -88,10 +88,11 @@ extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); #define struct_pcie_register_event struct msm_pcie_register_event #endif /* CONFIG_ARCH_MSM */ #ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY -#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) #define struct_pcie_notify struct exynos_pcie_notify #define struct_pcie_register_event struct exynos_pcie_register_event -#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 */ +#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ #endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -107,24 +108,23 @@ extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); #define IDLE_FLOW_RING_TIMEOUT 5000 #endif /* IDLE_TX_FLOW_MGMT */ -#ifdef DEVICE_TX_STUCK_DETECT -#define DEVICE_TX_STUCK_CKECK_TIMEOUT 1000 /* 1 sec */ -#define DEVICE_TX_STUCK_TIMEOUT 10000 /* 10 secs */ -#define DEVICE_TX_STUCK_WARN_DURATION (DEVICE_TX_STUCK_TIMEOUT / DEVICE_TX_STUCK_CKECK_TIMEOUT) -#define DEVICE_TX_STUCK_DURATION (DEVICE_TX_STUCK_WARN_DURATION * 2) -#endif /* DEVICE_TX_STUCK_DETECT */ - /* implicit DMA for h2d wr and d2h rd indice from Host memory to TCM */ #define IDMA_ENAB(dhd) ((dhd)->idma_enable) #define IDMA_ACTIVE(dhd) (((dhd)->idma_enable) && ((dhd)->idma_inited)) -#define IDMA_DS_ENAB(dhd) ((dhd)->idma_retention_ds) -#define IDMA_DS_ACTIVE(dhd) ((dhd)->bus->dongle_in_ds) +#define IDMA_CAPABLE(bus) (((bus)->sih->buscorerev == 19) || ((bus)->sih->buscorerev >= 23)) /* IFRM (Implicit Flow Ring Manager enable and inited */ #define IFRM_ENAB(dhd) ((dhd)->ifrm_enable) #define IFRM_ACTIVE(dhd) (((dhd)->ifrm_enable) && ((dhd)->ifrm_inited)) +/* DAR registers use for h2d doorbell */ +#define DAR_ENAB(dhd) ((dhd)->dar_enable) +#define DAR_ACTIVE(dhd) (((dhd)->dar_enable) && ((dhd)->dar_inited)) + +/* DAR WAR for revs < 64 */ +#define DAR_PWRREQ(bus) (((bus)->_dar_war) && DAR_ACTIVE((bus)->dhd)) + /* PCIE CTO Prevention and Recovery */ #define PCIECTO_ENAB(dhd) ((dhd)->cto_enable) @@ -136,6 +136,8 @@ extern int exynos_pcie_deregister_event(struct exynos_pcie_register_event *reg); #define IDMA_IDX1 1 #define IDMA_IDX2 2 #define IDMA_IDX3 3 +#define DMA_TYPE_SHIFT 4 +#define DMA_TYPE_IDMA 1 #define DHDPCIE_CONFIG_HDR_SIZE 16 #define DHDPCIE_CONFIG_CHECK_DELAY_MS 10 /* 10ms */ @@ -159,7 +161,6 @@ typedef struct ring_sh_info { uint32 ring_state_r; } ring_sh_info_t; - #define DEVICE_WAKE_NONE 0 #define DEVICE_WAKE_OOB 1 #define DEVICE_WAKE_INB 2 @@ -206,13 +207,18 @@ typedef struct dhdpcie_config_save uint32 bar1_win; } dhdpcie_config_save_t; +/* The level of bus communication with the dongle */ +enum dhd_bus_low_power_state { + DHD_BUS_NO_LOW_POWER_STATE, /* Not in low power state */ + DHD_BUS_D3_INFORM_SENT, /* D3 INFORM sent */ + DHD_BUS_D3_ACK_RECIEVED, /* D3 ACK recieved */ +}; + +/** Instantiated once for each hardware (dongle) instance that this DHD manages */ typedef struct dhd_bus { - dhd_pub_t *dhd; + dhd_pub_t *dhd; /**< pointer to per hardware (dongle) unique instance */ struct pci_dev *rc_dev; /* pci RC device handle */ struct pci_dev *dev; /* pci device handle */ -#ifdef DHD_EFI - void *pcie_dev; -#endif dll_t flowring_active_list; /* constructed list of tx flowring queues */ #ifdef IDLE_TX_FLOW_MGMT @@ -220,13 +226,6 @@ typedef struct dhd_bus { /* stores the timestamp of active list processing */ #endif /* IDLE_TX_FLOW_MGMT */ -#ifdef DEVICE_TX_STUCK_DETECT - /* Flag to enable/disable device tx stuck monitor by DHD IOVAR dev_tx_stuck_monitor */ - uint32 dev_tx_stuck_monitor; - /* Stores the timestamp (msec) of the last device Tx stuck check */ - uint32 device_tx_stuck_check; -#endif /* DEVICE_TX_STUCK_DETECT */ - si_t *sih; /* Handle for SI calls */ char *vars; /* Variables (from CIS and/or other) */ uint varsz; /* Size of variables buffer */ @@ -251,10 +250,6 @@ typedef struct dhd_bus { uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */ char *fw_path; /* module_param: path to firmware image */ char *nv_path; /* module_param: path to nvram vars file */ -#ifdef CACHE_FW_IMAGES - int processed_nvram_params_len; /* Modified len of NVRAM info */ -#endif - struct pktq txq; /* Queue length used for flow-control */ @@ -278,7 +273,6 @@ typedef struct dhd_bus { ulong shared_addr; pciedev_shared_t *pcie_sh; - bool bus_flowctrl; uint32 dma_rxoffset; volatile char *regs; /* pci device memory va */ volatile char *tcm; /* pci device memory va */ @@ -309,6 +303,9 @@ typedef struct dhd_bus { /* version 3 shared struct related info end */ uint32 def_intmask; + uint32 d2h_mb_mask; + uint32 pcie_mailbox_mask; + uint32 pcie_mailbox_int; bool ltrsleep_on_unload; uint wait_for_d3_ack; uint16 max_tx_flowrings; @@ -320,19 +317,18 @@ typedef struct dhd_bus { dhd_timeout_t doorbell_timer; bool device_wake_state; -#ifdef PCIE_OOB - bool oob_enabled; -#endif /* PCIE_OOB */ bool irq_registered; + bool d2h_intr_method; #ifdef SUPPORT_LINKDOWN_RECOVERY #if defined(CONFIG_ARCH_MSM) || (defined(EXYNOS_PCIE_LINKDOWN_RECOVERY) && \ - defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895)) + defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810)) #ifdef CONFIG_ARCH_MSM uint8 no_cfg_restore; #endif /* CONFIG_ARCH_MSM */ struct_pcie_register_event pcie_event; #endif /* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && - * (CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895)) + * (CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810)) */ bool read_shm_fail; #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -349,51 +345,66 @@ typedef struct dhd_bus { uint32 d0_inform_in_use_cnt; uint8 force_suspend; uint8 is_linkdown; + uint8 no_bus_init; #ifdef IDLE_TX_FLOW_MGMT bool enable_idle_flowring_mgmt; #endif /* IDLE_TX_FLOW_MGMT */ struct dhd_pcie_rev api; bool use_mailbox; - bool d3_suspend_pending; bool use_d0_inform; + void *bus_lock; + enum dhd_bus_low_power_state bus_low_power_state; uint32 hostready_count; /* Number of hostready issued */ -#if defined(PCIE_OOB) || defined(BCMPCIE_OOB_HOST_WAKE) +#if defined(BCMPCIE_OOB_HOST_WAKE) bool oob_presuspend; -#endif /* PCIE_OOB || BCMPCIE_OOB_HOST_WAKE */ - bool dongle_in_ds; - uint8 dw_option; -#ifdef PCIE_INB_DW - bool inb_enabled; - uint32 ds_exit_timeout; - uint32 host_sleep_exit_timeout; - uint wait_for_ds_exit; - uint32 inband_dw_assert_cnt; /* # of inband device_wake assert */ - uint32 inband_dw_deassert_cnt; /* # of inband device_wake deassert */ - uint32 inband_ds_exit_host_cnt; /* # of DS-EXIT , host initiated */ - uint32 inband_ds_exit_device_cnt; /* # of DS-EXIT , device initiated */ - uint32 inband_ds_exit_to_cnt; /* # of DS-EXIT timeout */ - uint32 inband_host_sleep_exit_to_cnt; /* # of Host_Sleep exit timeout */ - void *inb_lock; /* Lock to serialize in band device wake activity */ - /* # of contexts in the host which currently want a FW transaction */ - uint32 host_active_cnt; -#endif /* PCIE_INB_DW */ +#endif // endif dhdpcie_config_save_t saved_config; ulong resume_intr_enable_count; ulong dpc_intr_enable_count; ulong isr_intr_disable_count; ulong suspend_intr_disable_count; ulong dpc_return_busdown_count; +#ifdef BCMPCIE_OOB_HOST_WAKE + ulong oob_intr_count; + ulong oob_intr_enable_count; + ulong oob_intr_disable_count; + uint64 last_oob_irq_time; +#endif /* BCMPCIE_OOB_HOST_WAKE */ + uint64 isr_entry_time; + uint64 isr_exit_time; + uint64 dpc_entry_time; + uint64 dpc_exit_time; + uint64 resched_dpc_time; + uint64 last_process_ctrlbuf_time; + uint64 last_process_flowring_time; + uint64 last_process_txcpl_time; + uint64 last_process_rxcpl_time; + uint64 last_process_infocpl_time; + uint64 last_suspend_start_time; + uint64 last_suspend_end_time; + uint64 last_resume_start_time; + uint64 last_resume_end_time; bool idma_enabled; bool ifrm_enabled; + bool dar_enabled; uint32 dmaxfer_complete; -#if defined(PCIE_OOB) || defined(PCIE_INB_DW) - bool ds_enabled; -#endif + uint8 dw_option; #ifdef DHD_PCIE_RUNTIMEPM bool chk_pm; /* To avoid counting of wake up from Runtime PM */ #endif /* DHD_PCIE_RUNTIMEPM */ + bool _dar_war; + uint8 dma_chan; } dhd_bus_t; +#ifdef DHD_MSI_SUPPORT +extern uint enable_msi; +#endif /* DHD_MSI_SUPPORT */ + +enum { + PCIE_INTX = 0, + PCIE_MSI = 1 +}; + /* function declarations */ extern uint32* dhdpcie_bus_reg_map(osl_t *osh, ulong addr, int size); @@ -413,7 +424,11 @@ extern int32 dhdpcie_bus_isr(struct dhd_bus *bus); extern void dhdpcie_free_irq(dhd_bus_t *bus); extern void dhdpcie_bus_ringbell_fast(struct dhd_bus *bus, uint32 value); extern void dhdpcie_bus_ringbell_2_fast(struct dhd_bus *bus, uint32 value, bool devwake); +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +extern int dhdpcie_bus_suspend(struct dhd_bus *bus, bool state, bool byint); +#else extern int dhdpcie_bus_suspend(struct dhd_bus *bus, bool state); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ extern int dhdpcie_pci_suspend_resume(struct dhd_bus *bus, bool state); extern uint32 dhdpcie_force_alp(struct dhd_bus *bus, bool enable); extern uint32 dhdpcie_set_l1_entry_time(struct dhd_bus *bus, int force_l1_entry_time); @@ -436,36 +451,39 @@ extern int dhdpcie_disable_device(dhd_bus_t *bus); extern int dhdpcie_alloc_resource(dhd_bus_t *bus); extern void dhdpcie_free_resource(dhd_bus_t *bus); extern int dhdpcie_bus_request_irq(struct dhd_bus *bus); + extern int dhdpcie_enable_device(dhd_bus_t *bus); + #ifdef BCMPCIE_OOB_HOST_WAKE extern int dhdpcie_oob_intr_register(dhd_bus_t *bus); extern void dhdpcie_oob_intr_unregister(dhd_bus_t *bus); extern void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable); +extern int dhdpcie_get_oob_irq_num(dhd_bus_t *bus); #endif /* BCMPCIE_OOB_HOST_WAKE */ -#ifdef PCIE_OOB -extern void dhd_oob_set_bt_reg_on(struct dhd_bus *bus, bool val); -extern int dhd_oob_get_bt_reg_on(struct dhd_bus *bus); -extern void dhdpcie_oob_init(dhd_bus_t *bus); -extern void dhd_bus_doorbell_timeout_reset(struct dhd_bus *bus); -extern int dhd_os_oob_set_device_wake(struct dhd_bus *bus, bool val); -extern void dhd_os_ib_set_device_wake(struct dhd_bus *bus, bool val); -#endif /* PCIE_OOB */ + +#ifdef DHD_DISABLE_ASPM +extern void dhd_bus_aspm_enable(dhd_bus_t *bus, bool enable); + +static INLINE void +dhd_pcie_config_write(osl_t *osh, uint offset, uint size, uint val) +{ + OSL_DELAY(100); + return OSL_PCI_WRITE_CONFIG(osh, offset, size, val); +} +#endif /* DHD_DISABLE_ASPM */ #if defined(CONFIG_ARCH_EXYNOS) #define SAMSUNG_PCIE_VENDOR_ID 0x144d #if defined(CONFIG_MACH_UNIVERSAL5433) #define SAMSUNG_PCIE_DEVICE_ID 0xa5e3 #define SAMSUNG_PCIE_CH_NUM -#elif defined(CONFIG_MACH_UNIVERSAL7420) +#elif defined(CONFIG_MACH_UNIVERSAL7420) || defined(CONFIG_SOC_EXYNOS7420) #define SAMSUNG_PCIE_DEVICE_ID 0xa575 #define SAMSUNG_PCIE_CH_NUM 1 #elif defined(CONFIG_SOC_EXYNOS8890) #define SAMSUNG_PCIE_DEVICE_ID 0xa544 #define SAMSUNG_PCIE_CH_NUM 0 -#elif defined(CONFIG_SOC_EXYNOS7420) -#define SAMSUNG_PCIE_DEVICE_ID 0xa575 -#define SAMSUNG_PCIE_CH_NUM 1 -#elif defined(CONFIG_SOC_EXYNOS8895) +#elif defined(CONFIG_SOC_EXYNOS8895) || defined(CONFIG_SOC_EXYNOS9810) #define SAMSUNG_PCIE_DEVICE_ID 0xecec #define SAMSUNG_PCIE_CH_NUM 0 #else @@ -483,9 +501,11 @@ extern void dhd_os_ib_set_device_wake(struct dhd_bus *bus, bool val); #define MSM_PCIE_DEVICE_ID 0x0104 #elif defined(CONFIG_ARCH_MSM8998) #define MSM_PCIE_DEVICE_ID 0x0105 +#elif defined(CONFIG_ARCH_SDM845) +#define MSM_PCIE_DEVICE_ID 0x0106 #else #error "Not supported platform" -#endif +#endif // endif #endif /* CONFIG_ARCH_MSM */ #if defined(CONFIG_X86) @@ -498,6 +518,9 @@ extern void dhd_os_ib_set_device_wake(struct dhd_bus *bus, bool val); #define TEGRA_PCIE_DEVICE_ID 0x4347 #endif /* CONFIG_ARCH_TEGRA */ +#define DUMMY_PCIE_VENDOR_ID 0xffff +#define DUMMY_PCIE_DEVICE_ID 0xffff + #if defined(CONFIG_ARCH_EXYNOS) #define PCIE_RC_VENDOR_ID SAMSUNG_PCIE_VENDOR_ID #define PCIE_RC_DEVICE_ID SAMSUNG_PCIE_DEVICE_ID @@ -511,7 +534,9 @@ extern void dhd_os_ib_set_device_wake(struct dhd_bus *bus, bool val); #define PCIE_RC_VENDOR_ID TEGRA_PCIE_VENDOR_ID #define PCIE_RC_DEVICE_ID TEGRA_PCIE_DEVICE_ID #else -#error "Not supported platform" +/* Use dummy vendor and device IDs */ +#define PCIE_RC_VENDOR_ID DUMMY_PCIE_VENDOR_ID +#define PCIE_RC_DEVICE_ID DUMMY_PCIE_DEVICE_ID #endif /* CONFIG_ARCH_EXYNOS */ #ifdef USE_EXYNOS_PCIE_RC_PMPATCH @@ -553,23 +578,20 @@ int bcmpcie_set_get_wake(struct dhd_bus *bus, int flag); #endif /* DHD_WAKE_STATUS */ extern bool dhdpcie_bus_get_pcie_hostready_supported(dhd_bus_t *bus); extern void dhd_bus_hostready(struct dhd_bus *bus); -#ifdef PCIE_OOB -extern bool dhdpcie_bus_get_pcie_oob_dw_supported(dhd_bus_t *bus); -#endif /* PCIE_OOB */ -#ifdef PCIE_INB_DW -extern bool dhdpcie_bus_get_pcie_inband_dw_supported(dhd_bus_t *bus); -extern void dhdpcie_bus_set_pcie_inband_dw_state(dhd_bus_t *bus, - enum dhd_bus_ds_state state); -extern enum dhd_bus_ds_state dhdpcie_bus_get_pcie_inband_dw_state(dhd_bus_t *bus); -extern const char * dhd_convert_inb_state_names(enum dhd_bus_ds_state inbstate); -extern const char * dhd_convert_dsval(uint32 val, bool d2h); -extern int dhd_bus_inb_set_device_wake(struct dhd_bus *bus, bool val); -extern void dhd_bus_inb_ack_pending_ds_req(dhd_bus_t *bus); -#endif /* PCIE_INB_DW */ extern void dhdpcie_bus_enab_pcie_dw(dhd_bus_t *bus, uint8 dw_option); -extern bool dhdpcie_irq_enabled(struct dhd_bus *bus); +extern int dhdpcie_irq_disabled(struct dhd_bus *bus); + +static INLINE bool dhdpcie_is_arm_halted(struct dhd_bus *bus) {return TRUE;} +static INLINE int dhd_os_wifi_platform_set_power(uint32 value) {return BCME_OK; } + +int dhdpcie_config_check(dhd_bus_t *bus); +int dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr); +int dhdpcie_config_save(dhd_bus_t *bus); +int dhdpcie_set_pwr_state(dhd_bus_t *bus, uint state); + extern bool dhdpcie_bus_get_pcie_idma_supported(dhd_bus_t *bus); extern bool dhdpcie_bus_get_pcie_ifrm_supported(dhd_bus_t *bus); +extern bool dhdpcie_bus_get_pcie_dar_supported(dhd_bus_t *bus); static INLINE uint32 dhd_pcie_config_read(osl_t *osh, uint offset, uint size) @@ -589,21 +611,9 @@ dhd_pcie_corereg_read(si_t *sih, uint val) #ifdef DHD_SSSR_DUMP extern int dhdpcie_sssr_dump(dhd_pub_t *dhd); #endif /* DHD_SSSR_DUMP */ +extern int dhdpcie_get_nvpath_otp(dhd_bus_t *bus, char *program, char *nv_path); -#ifdef DHD_EFI -extern int dhd_os_wifi_platform_set_power(uint32 value); -int dhd_control_signal(dhd_bus_t *bus, char *arg, int set); -extern int dhd_wifi_properties(struct dhd_bus *bus, char *arg); -extern bool dhdpcie_is_arm_halted(struct dhd_bus *bus); -extern void dhdpcie_dongle_pwr_toggle(dhd_bus_t *bus); -extern int dhd_otp_dump(dhd_bus_t *bus, char *arg); -#else -static INLINE int dhd_os_wifi_platform_set_power(uint32 value) {return BCME_OK; } -static INLINE bool dhdpcie_is_arm_halted(struct dhd_bus *bus) {return TRUE;} -#endif /* DHD_EFI */ -int dhdpcie_config_check(dhd_bus_t *bus); -int dhdpcie_config_restore(dhd_bus_t *bus, bool restore_pmcsr); -int dhdpcie_config_save(dhd_bus_t *bus); -int dhdpcie_set_pwr_state(dhd_bus_t *bus, uint state); - +extern int dhd_pcie_debug_info_dump(dhd_pub_t *dhd); +extern void dhd_pcie_intr_count_dump(dhd_pub_t *dhd); +extern void dhdpcie_bus_clear_intstatus(dhd_bus_t *bus); #endif /* dhd_pcie_h */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pcie_linux.c b/drivers/net/wireless/bcmdhd_oo/dhd_pcie_linux.c index bf7937b3667b9a854e32e069d50ff0010910b307..38dc9514c738f0e11ba57913e280ef0b8ad50893 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pcie_linux.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pcie_linux.c @@ -1,14 +1,14 @@ /* * Linux DHD Bus Module for PCIE * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,10 +24,9 @@ * * <> * - * $Id: dhd_pcie_linux.c 732289 2017-11-16 14:22:26Z $ + * $Id: dhd_pcie_linux.c 740051 2018-01-10 13:56:33Z $ */ - /* include files */ #include #include @@ -58,9 +57,17 @@ #include #endif /* CONFIG_PCI_MSM */ #endif /* CONFIG_ARCH_MSM */ -#ifdef PCIE_OOB -#include "ftdi_sio_external.h" -#endif /* PCIE_OOB */ + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#include +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +#ifndef AUTO_SUSPEND_TIMEOUT +#define AUTO_SUSPEND_TIMEOUT 1000 +#endif /* AUTO_SUSPEND_TIMEOUT */ +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #include #ifdef USE_SMMU_ARCH_MSM #include @@ -83,18 +90,6 @@ do { \ *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ } while (0) -#ifdef PCIE_OOB -#define HOST_WAKE 4 /* GPIO_0 (HOST_WAKE) - Output from WLAN */ -#define DEVICE_WAKE 5 /* GPIO_1 (DEVICE_WAKE) - Input to WLAN */ -#define BIT_WL_REG_ON 6 -#define BIT_BT_REG_ON 7 - -int gpio_handle_val = 0; -unsigned char gpio_port = 0; -unsigned char gpio_direction = 0; -#define OOB_PORT "ttyUSB0" -#endif /* PCIE_OOB */ - /* user defined data structures */ typedef struct dhd_pc_res { @@ -134,7 +129,6 @@ typedef struct dhdpcie_info #endif /* USE_SMMU_ARCH_MSM */ } dhdpcie_info_t; - struct pcos_info { dhdpcie_info_t *pc; spinlock_t lock; @@ -175,7 +169,11 @@ static int dhdpcie_init(struct pci_dev *pdev); static irqreturn_t dhdpcie_isr(int irq, void *arg); /* OS Routine functions for PCI suspend/resume */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int dhdpcie_set_suspend_resume(struct pci_dev *dev, bool state, bool byint); +#else static int dhdpcie_set_suspend_resume(dhd_bus_t *bus, bool state); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ static int dhdpcie_resume_host_dev(dhd_bus_t *bus); static int dhdpcie_suspend_host_dev(dhd_bus_t *bus); static int dhdpcie_resume_dev(struct pci_dev *dev); @@ -186,10 +184,22 @@ static int dhdpcie_pm_prepare(struct device *dev); static int dhdpcie_pm_resume(struct device *dev); static void dhdpcie_pm_complete(struct device *dev); #else +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int dhdpcie_pm_system_suspend_noirq(struct device * dev); +static int dhdpcie_pm_system_resume_noirq(struct device * dev); +#else static int dhdpcie_pci_suspend(struct pci_dev *dev, pm_message_t state); static int dhdpcie_pci_resume(struct pci_dev *dev); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #endif /* DHD_PCIE_RUNTIMEPM */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int dhdpcie_pm_runtime_suspend(struct device * dev); +static int dhdpcie_pm_runtime_resume(struct device * dev); +static int dhdpcie_pm_system_suspend_noirq(struct device * dev); +static int dhdpcie_pm_system_resume_noirq(struct device * dev); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + static struct pci_device_id dhdpcie_pci_devid[] __devinitdata = { { vendor: 0x14e4, device: PCI_ANY_ID, @@ -212,6 +222,13 @@ static const struct dev_pm_ops dhd_pcie_pm_ops = { .complete = dhdpcie_pm_complete, }; #endif /* DHD_PCIE_RUNTIMEPM */ +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static const struct dev_pm_ops dhdpcie_pm_ops = { + SET_RUNTIME_PM_OPS(dhdpcie_pm_runtime_suspend, dhdpcie_pm_runtime_resume, NULL) + .suspend_noirq = dhdpcie_pm_system_suspend_noirq, + .resume_noirq = dhdpcie_pm_system_resume_noirq +}; +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ static struct pci_driver dhdpcie_driver = { node: {&dhdpcie_driver.node, &dhdpcie_driver.node}, @@ -221,13 +238,13 @@ static struct pci_driver dhdpcie_driver = { remove: dhdpcie_pci_remove, #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) save_state: NULL, -#endif -#ifdef DHD_PCIE_RUNTIMEPM +#endif // endif +#if defined(DHD_PCIE_RUNTIMEPM) || defined(DHD_PCIE_NATIVE_RUNTIMEPM) .driver.pm = &dhd_pcie_pm_ops, #else suspend: dhdpcie_pci_suspend, resume: dhdpcie_pci_resume, -#endif /* DHD_PCIE_RUNTIMEPM */ +#endif /* DHD_PCIE_RUNTIMEPM || DHD_PCIE_NATIVE_RUNTIMEPM */ }; int dhdpcie_init_succeeded = FALSE; @@ -273,13 +290,11 @@ static int dhdpcie_smmu_init(struct pci_dev *pdev, void *smmu_cxt) DHD_ERROR(("%s : SMMU init start\n", __FUNCTION__)); -#ifdef SET_DMA_MASK_64BIT if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) || pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { DHD_ERROR(("%s: DMA set 64bit mask failed.\n", __FUNCTION__)); return -EINVAL; } -#endif /* SET_DMA_MASK_64BIT */ mapping = arm_iommu_create_mapping(&platform_bus_type, smmu_info->smmu_iova_start, smmu_info->smmu_iova_len); @@ -385,12 +400,14 @@ static int dhdpcie_pm_prepare(struct device *dev) dhdpcie_info_t *pch = pci_get_drvdata(pdev); dhd_bus_t *bus = NULL; - if (pch) { - bus = pch->bus; - DHD_DISABLE_RUNTIME_PM(bus->dhd); + if (!pch || !pch->bus) { + return 0; } + bus = pch->bus; + DHD_DISABLE_RUNTIME_PM(bus->dhd); bus->chk_pm = TRUE; + return 0; } @@ -413,10 +430,8 @@ static int dhdpcie_pm_resume(struct device *dev) DHD_BUS_BUSY_SET_RESUME_IN_PROGRESS(bus->dhd); DHD_GENERAL_UNLOCK(bus->dhd, flags); - if (!bus->dhd->dongle_reset) { + if (!bus->dhd->dongle_reset) ret = dhdpcie_set_suspend_resume(bus, FALSE); - bus->chk_pm = FALSE; - } DHD_GENERAL_LOCK(bus->dhd, flags); DHD_BUS_BUSY_CLEAR_RESUME_IN_PROGRESS(bus->dhd); @@ -432,11 +447,14 @@ static void dhdpcie_pm_complete(struct device *dev) dhdpcie_info_t *pch = pci_get_drvdata(pdev); dhd_bus_t *bus = NULL; - if (pch) { - bus = pch->bus; - DHD_ENABLE_RUNTIME_PM(bus->dhd); + if (!pch || !pch->bus) { + return; } + bus = pch->bus; + DHD_ENABLE_RUNTIME_PM(bus->dhd); + bus->chk_pm = FALSE; + return; } #else @@ -507,8 +525,11 @@ static int dhdpcie_pci_resume(struct pci_dev *pdev) } #endif /* DHD_PCIE_RUNTIMEPM */ - +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int dhdpcie_set_suspend_resume(dhd_bus_t *bus, bool state, bool byint) +#else static int dhdpcie_set_suspend_resume(dhd_bus_t *bus, bool state) +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ { int ret = 0; @@ -531,8 +552,11 @@ static int dhdpcie_set_suspend_resume(dhd_bus_t *bus, bool state) #endif /* DHD_PCIE_RUNTIMEPM */ return ret; } - +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + ret = dhdpcie_bus_suspend(bus, state, byint); +#else ret = dhdpcie_bus_suspend(bus, state); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ #ifdef DHD_PCIE_RUNTIMEPM mutex_unlock(&bus->pm_lock); @@ -541,6 +565,109 @@ static int dhdpcie_set_suspend_resume(dhd_bus_t *bus, bool state) return ret; } +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM +static int dhdpcie_pm_runtime_suspend(struct device * dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + dhdpcie_info_t *pch = pci_get_drvdata(pdev); + dhd_bus_t *bus = NULL; + int ret = 0; + + if (!pch) + return -EBUSY; + + bus = pch->bus; + + DHD_RPM(("%s Enter\n", __FUNCTION__)); + + if (atomic_read(&bus->dhd->block_bus)) + return -EHOSTDOWN; + + dhd_netif_stop_queue(bus); + atomic_set(&bus->dhd->block_bus, TRUE); + + if (dhdpcie_set_suspend_resume(pdev, TRUE, TRUE)) { + pm_runtime_mark_last_busy(dev); + ret = -EAGAIN; + } + + atomic_set(&bus->dhd->block_bus, FALSE); + dhd_bus_start_queue(bus); + + return ret; +} + +static int dhdpcie_pm_runtime_resume(struct device * dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + dhdpcie_info_t *pch = pci_get_drvdata(pdev); + dhd_bus_t *bus = pch->bus; + + DHD_RPM(("%s Enter\n", __FUNCTION__)); + + if (atomic_read(&bus->dhd->block_bus)) + return -EHOSTDOWN; + + if (dhdpcie_set_suspend_resume(pdev, FALSE, TRUE)) + return -EAGAIN; + + return 0; +} + +static int dhdpcie_pm_system_suspend_noirq(struct device * dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + dhdpcie_info_t *pch = pci_get_drvdata(pdev); + dhd_bus_t *bus = NULL; + int ret; + + DHD_RPM(("%s Enter\n", __FUNCTION__)); + + if (!pch) + return -EBUSY; + + bus = pch->bus; + + if (atomic_read(&bus->dhd->block_bus)) + return -EHOSTDOWN; + + dhd_netif_stop_queue(bus); + atomic_set(&bus->dhd->block_bus, TRUE); + + ret = dhdpcie_set_suspend_resume(pdev, TRUE, FALSE); + + if (ret) { + dhd_bus_start_queue(bus); + atomic_set(&bus->dhd->block_bus, FALSE); + } + + return ret; +} + +static int dhdpcie_pm_system_resume_noirq(struct device * dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + dhdpcie_info_t *pch = pci_get_drvdata(pdev); + dhd_bus_t *bus = NULL; + int ret; + + if (!pch) + return -EBUSY; + + bus = pch->bus; + + DHD_RPM(("%s Enter\n", __FUNCTION__)); + + ret = dhdpcie_set_suspend_resume(pdev, FALSE, FALSE); + + atomic_set(&bus->dhd->block_bus, FALSE); + dhd_bus_start_queue(bus); + pm_runtime_mark_last_busy(dhd_bus_to_dev(bus)); + + return ret; +} +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) extern void dhd_dpc_tasklet_kill(dhd_pub_t *dhdp); #endif /* OEM_ANDROID && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ @@ -568,7 +695,7 @@ static int dhdpcie_suspend_dev(struct pci_dev *dev) pci_enable_wake(dev, PCI_D0, TRUE); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) if (pci_is_enabled(dev)) -#endif +#endif // endif pci_disable_device(dev); ret = pci_set_power_state(dev, PCI_D3hot); @@ -792,19 +919,21 @@ int dhdpcie_pci_suspend_resume(dhd_bus_t *bus, bool state) struct pci_dev *dev = bus->dev; if (state) { -#ifndef BCMPCIE_OOB_HOST_WAKE +#if !defined(BCMPCIE_OOB_HOST_WAKE) dhdpcie_pme_active(bus->osh, state); -#endif /* !BCMPCIE_OOB_HOST_WAKE */ +#endif // endif rc = dhdpcie_suspend_dev(dev); if (!rc) { dhdpcie_suspend_host_dev(bus); } } else { - dhdpcie_resume_host_dev(bus); - rc = dhdpcie_resume_dev(dev); -#ifndef BCMPCIE_OOB_HOST_WAKE - dhdpcie_pme_active(bus->osh, state); -#endif /* !BCMPCIE_OOB_HOST_WAKE */ + rc = dhdpcie_resume_host_dev(bus); + if (!rc) { + rc = dhdpcie_resume_dev(dev); +#if !defined(BCMPCIE_OOB_HOST_WAKE) + dhdpcie_pme_active(bus->osh, state); +#endif // endif + } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) #if defined(DHD_HANG_SEND_UP_TEST) if (bus->is_linkdown || @@ -815,7 +944,7 @@ int dhdpcie_pci_suspend_resume(dhd_bus_t *bus, bool state) bus->dhd->hang_reason = HANG_REASON_PCIE_RC_LINK_UP_FAIL; dhd_os_send_hang_message(bus->dhd); } -#endif +#endif // endif } return rc; } @@ -829,11 +958,11 @@ static int dhdpcie_device_scan(struct device *dev, void *data) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif pcidev = container_of(dev, struct pci_dev, dev); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (pcidev->vendor != 0x14e4) return 0; @@ -852,7 +981,6 @@ dhdpcie_bus_register(void) { int error = 0; - #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) if (!(error = pci_module_init(&dhdpcie_driver))) return 0; @@ -877,7 +1005,6 @@ dhdpcie_bus_register(void) return error; } - void dhdpcie_bus_unregister(void) { @@ -901,6 +1028,18 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + /* + Since MSM PCIe RC dev usage conunt already incremented +2 even + before dhdpcie_pci_probe() called, then we inevitably to call + pm_runtime_put_noidle() two times to make the count start with zero. + */ + + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + #ifdef BCMPCIE_DISABLE_ASYNC_SUSPEND /* disable async suspend */ device_disable_async_suspend(&pdev->dev); @@ -924,7 +1063,6 @@ dhdpcie_detach(dhdpcie_info_t *pch) return 0; } - void __devexit dhdpcie_pci_remove(struct pci_dev *pdev) { @@ -937,25 +1075,33 @@ dhdpcie_pci_remove(struct pci_dev *pdev) bus = pch->bus; osh = pch->osh; -#ifdef SUPPORT_LINKDOWN_RECOVERY +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_get_noresume(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + if (bus) { +#ifdef SUPPORT_LINKDOWN_RECOVERY #ifdef CONFIG_ARCH_MSM msm_pcie_deregister_event(&bus->pcie_event); #endif /* CONFIG_ARCH_MSM */ #ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY -#ifdef CONFIG_SOC_EXYNOS8890 +#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) exynos_pcie_deregister_event(&bus->pcie_event); -#endif /* CONFIG_SOC_EXYNOS8890 */ +#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || + * CONFIG_SOC_EXYNOS9810 + */ #endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ - } #endif /* SUPPORT_LINKDOWN_RECOVERY */ - bus->rc_dev = NULL; + bus->rc_dev = NULL; - dhdpcie_bus_release(bus); + dhdpcie_bus_release(bus); + } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) if (pci_is_enabled(pdev)) -#endif +#endif // endif pci_disable_device(pdev); #ifdef BCMPCIE_OOB_HOST_WAKE /* pcie os info detach */ @@ -971,7 +1117,6 @@ dhdpcie_pci_remove(struct pci_dev *pdev) /* osl detach */ osl_detach(osh); - dhdpcie_init_succeeded = FALSE; DHD_TRACE(("%s Exit\n", __FUNCTION__)); @@ -979,19 +1124,59 @@ dhdpcie_pci_remove(struct pci_dev *pdev) return; } -/* Free Linux irq */ +/* Enable Linux Msi */ +int +dhdpcie_enable_msi(struct pci_dev *pdev, unsigned int min_vecs, unsigned int max_vecs) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + return pci_alloc_irq_vectors(pdev, min_vecs, max_vecs, PCI_IRQ_MSI); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) + return pci_enable_msi_range(pdev, min_vecs, max_vecs); +#else + return pci_enable_msi_block(pdev, max_vecs); +#endif // endif +} + +/* Disable Linux Msi */ +void +dhdpcie_disable_msi(struct pci_dev *pdev) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0)) + pci_free_irq_vectors(pdev); +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) + pci_disable_msi(pdev); +#else + pci_disable_msi(pdev); +#endif // endif + return; +} + +/* Request Linux irq */ int dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info) { dhd_bus_t *bus = dhdpcie_info->bus; struct pci_dev *pdev = dhdpcie_info->bus->dev; + int host_irq_disabled; if (!bus->irq_registered) { snprintf(dhdpcie_info->pciname, sizeof(dhdpcie_info->pciname), "dhdpcie:%s", pci_name(pdev)); + + if (bus->d2h_intr_method == PCIE_MSI) { + if (dhdpcie_enable_msi(pdev, 1, 1) < 0) { + DHD_ERROR(("%s: dhdpcie_enable_msi() failed\n", __FUNCTION__)); + dhdpcie_disable_msi(pdev); + bus->d2h_intr_method = PCIE_INTX; + } + } + if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED, dhdpcie_info->pciname, bus) < 0) { DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__)); + if (bus->d2h_intr_method == PCIE_MSI) { + dhdpcie_disable_msi(pdev); + } return -1; } else { @@ -1001,14 +1186,15 @@ dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info) DHD_ERROR(("%s: PCI IRQ is already registered\n", __FUNCTION__)); } - if (!dhdpcie_irq_enabled(bus)) { - DHD_ERROR(("%s: PCIe IRQ was disabled, so, enabled it again\n", __FUNCTION__)); + host_irq_disabled = dhdpcie_irq_disabled(bus); + if (host_irq_disabled) { + DHD_ERROR(("%s: PCIe IRQ was disabled(%d), so, enabled it again\n", + __FUNCTION__, host_irq_disabled)); dhdpcie_enable_irq(bus); } DHD_TRACE(("%s %s\n", __FUNCTION__, dhdpcie_info->pciname)); - return 0; /* SUCCESS */ } @@ -1034,7 +1220,7 @@ dhdpcie_get_pcieirq(struct dhd_bus *bus, unsigned int *irq) #define PRINTF_RESOURCE "0x%016llx" #else #define PRINTF_RESOURCE "0x%08x" -#endif +#endif // endif #ifdef EXYNOS_PCIE_MODULE_PATCH #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) @@ -1051,7 +1237,6 @@ Parametrs: 1: struct pci_dev *pdev -- pci device structure 2: pci_res -- structure containing pci configuration space values - Return value: int - Status (TRUE or FALSE) @@ -1070,7 +1255,7 @@ int dhdpcie_get_resource(dhdpcie_info_t *dhdpcie_info) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) if (bcm_pcie_default_state) { pci_load_saved_state(pdev, bcm_pcie_default_state); - pci_restore_state(pdev); + pci_restore_state(pdev); } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ #endif /* EXYNOS_MODULE_PATCH */ @@ -1112,22 +1297,20 @@ int dhdpcie_get_resource(dhdpcie_info_t *dhdpcie_info) #endif /* EXYNOS_MODULE_PATCH */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) - if (!dhd_download_fw_on_driverload) { - /* Backup PCIe configuration so as to use Wi-Fi on/off process - * in case of built in driver - */ - pci_save_state(pdev); - dhdpcie_info->default_state = pci_store_saved_state(pdev); - - if (dhdpcie_info->default_state == NULL) { - DHD_ERROR(("%s pci_store_saved_state returns NULL\n", - __FUNCTION__)); - REG_UNMAP(dhdpcie_info->regs); - REG_UNMAP(dhdpcie_info->tcm); - pci_disable_device(pdev); - break; - } - } + /* Backup PCIe configuration so as to use Wi-Fi on/off process + * in case of built in driver + */ + pci_save_state(pdev); + dhdpcie_info->default_state = pci_store_saved_state(pdev); + + if (dhdpcie_info->default_state == NULL) { + DHD_ERROR(("%s pci_store_saved_state returns NULL\n", + __FUNCTION__)); + REG_UNMAP(dhdpcie_info->regs); + REG_UNMAP(dhdpcie_info->tcm); + pci_disable_device(pdev); + break; + } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ DHD_TRACE(("%s:Phys addr : reg space = %p base addr 0x"PRINTF_RESOURCE" \n", @@ -1167,7 +1350,8 @@ int dhdpcie_scan_resource(dhdpcie_info_t *dhdpcie_info) #ifdef SUPPORT_LINKDOWN_RECOVERY #if defined(CONFIG_ARCH_MSM) || (defined(EXYNOS_PCIE_LINKDOWN_RECOVERY) && \ - (defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895))) + (defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810))) void dhdpcie_linkdown_cb(struct_pcie_notify *noti) { struct pci_dev *pdev = (struct pci_dev *)noti->user; @@ -1197,7 +1381,7 @@ void dhdpcie_linkdown_cb(struct_pcie_notify *noti) } #endif /* CONFIG_ARCH_MSM || (EXYNOS_PCIE_LINKDOWN_RECOVERY && - * (CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895)) + * (CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810)) */ #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -1310,7 +1494,6 @@ int dhdpcie_init(struct pci_dev *pdev) /* Get RC Device Handle */ bus->rc_dev = pci_get_device(PCIE_RC_VENDOR_ID, PCIE_RC_DEVICE_ID, NULL); - #ifdef DONGLE_ENABLE_ISOLATION bus->dhd->dongle_isolation = TRUE; #endif /* DONGLE_ENABLE_ISOLATION */ @@ -1322,16 +1505,20 @@ int dhdpcie_init(struct pci_dev *pdev) bus->pcie_event.callback = dhdpcie_linkdown_cb; bus->pcie_event.options = MSM_PCIE_CONFIG_NO_RECOVERY; msm_pcie_register_event(&bus->pcie_event); - bus->no_cfg_restore = 0; + bus->no_cfg_restore = FALSE; + bus->no_bus_init = FALSE; #endif /* CONFIG_ARCH_MSM */ #ifdef EXYNOS_PCIE_LINKDOWN_RECOVERY -#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) bus->pcie_event.events = EXYNOS_PCIE_EVENT_LINKDOWN; bus->pcie_event.user = pdev; bus->pcie_event.mode = EXYNOS_PCIE_TRIGGER_CALLBACK; bus->pcie_event.callback = dhdpcie_linkdown_cb; exynos_pcie_register_event(&bus->pcie_event); -#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 */ +#endif /* CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || + * CONFIG_SOC_EXYNOS9810 + */ #endif /* EXYNOS_PCIE_LINKDOWN_RECOVERY */ bus->read_shm_fail = FALSE; #endif /* SUPPORT_LINKDOWN_RECOVERY */ @@ -1386,6 +1573,12 @@ int dhdpcie_init(struct pci_dev *pdev) dhdpcie_init_succeeded = TRUE; +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + pm_runtime_set_autosuspend_delay(&pdev->dev, AUTO_SUSPEND_TIMEOUT); + pm_runtime_use_autosuspend(&pdev->dev); + atomic_set(&bus->dhd->block_bus, FALSE); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__)); return 0; /* return SUCCESS */ @@ -1433,6 +1626,9 @@ dhdpcie_free_irq(dhd_bus_t *bus) if (bus->irq_registered) { free_irq(pdev->irq, bus); bus->irq_registered = FALSE; + if (bus->d2h_intr_method == PCIE_MSI) { + dhdpcie_disable_msi(pdev); + } } else { DHD_ERROR(("%s: PCIe IRQ is not registered\n", __FUNCTION__)); } @@ -1459,16 +1655,18 @@ Interrupt Service routine checks for the status register, disable interrupt and queue DPC if mail box interrupts are raised. */ - irqreturn_t dhdpcie_isr(int irq, void *arg) { dhd_bus_t *bus = (dhd_bus_t*)arg; - - if (!dhdpcie_bus_isr(bus)) { - DHD_ERROR(("%s: dhdpcie_bus_isr returns with FALSE\n", __FUNCTION__)); - } - return IRQ_HANDLED; + int32 ret; + bus->isr_entry_time = OSL_SYSUPTIME_US(); + ret = dhdpcie_bus_isr(bus); + bus->isr_exit_time = OSL_SYSUPTIME_US(); + if (ret) + return TRUE; + else + return FALSE; } int @@ -1513,19 +1711,16 @@ dhdpcie_enable_irq(dhd_bus_t *bus) return BCME_OK; } -bool -dhdpcie_irq_enabled(dhd_bus_t *bus) +int +dhdpcie_irq_disabled(dhd_bus_t *bus) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) struct irq_desc *desc = irq_to_desc(bus->dev->irq); /* depth will be zero, if enabled */ - if (!desc->depth) { - DHD_ERROR(("%s: depth:%d\n", __FUNCTION__, desc->depth)); - } - return desc->depth ? FALSE : TRUE; + return desc->depth; #else - /* return TRUE by default as there is no support for lower versions */ - return TRUE; + /* return ERROR by default as there is no support for lower versions */ + return BCME_ERROR; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) */ } @@ -1669,6 +1864,19 @@ dhdpcie_enable_device(dhd_bus_t *bus) pci_load_saved_state(bus->dev, pch->default_state); #endif /* LINUX_VERSION >= 3.14.0 && LINUX_VERSION < 3.19.0 && !CONFIG_SOC_EXYNOS8890 */ + /* Check if Device ID is valid */ + if (bus->dev->state_saved) { + uint32 vid, saved_vid; + pci_read_config_dword(bus->dev, PCI_CFG_VID, &vid); + saved_vid = bus->dev->saved_config_space[PCI_CFG_VID]; + if (vid != saved_vid) { + DHD_ERROR(("%s: VID(0x%x) is different from saved VID(0x%x) " + "Skip the bus init\n", __FUNCTION__, vid, saved_vid)); + bus->no_bus_init = TRUE; + return BCME_ERROR; + } + } + pci_restore_state(bus->dev); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) */ @@ -1819,6 +2027,32 @@ dhdpcie_bus_request_irq(struct dhd_bus *bus) } #ifdef BCMPCIE_OOB_HOST_WAKE +int dhdpcie_get_oob_irq_num(dhd_bus_t *bus) +{ + dhdpcie_info_t *pch; + dhdpcie_os_info_t *dhdpcie_osinfo; + + if (bus == NULL) { + DHD_ERROR(("%s: bus is NULL\n", __FUNCTION__)); + return 0; + } + + if (bus->dev == NULL) { + DHD_ERROR(("%s: bus->dev is NULL\n", __FUNCTION__)); + return 0; + } + + pch = pci_get_drvdata(bus->dev); + if (pch == NULL) { + DHD_ERROR(("%s: pch is NULL\n", __FUNCTION__)); + return 0; + } + + dhdpcie_osinfo = (dhdpcie_os_info_t *)pch->os_cxt; + + return dhdpcie_osinfo ? dhdpcie_osinfo->oob_irq_num : 0; +} + void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable) { unsigned long flags; @@ -1847,8 +2081,10 @@ void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable) (dhdpcie_osinfo->oob_irq_num > 0)) { if (enable) { enable_irq(dhdpcie_osinfo->oob_irq_num); + bus->oob_intr_enable_count++; } else { disable_irq_nosync(dhdpcie_osinfo->oob_irq_num); + bus->oob_intr_disable_count++; } dhdpcie_osinfo->oob_irq_enabled = enable; } @@ -1858,9 +2094,12 @@ void dhdpcie_oob_intr_set(dhd_bus_t *bus, bool enable) static irqreturn_t wlan_oob_irq(int irq, void *data) { dhd_bus_t *bus; + unsigned long flags_bus; DHD_TRACE(("%s: IRQ Triggered\n", __FUNCTION__)); bus = (dhd_bus_t *)data; dhdpcie_oob_intr_set(bus, FALSE); + bus->last_oob_irq_time = OSL_SYSUPTIME_US(); + bus->oob_intr_count++; #ifdef DHD_WAKE_STATUS #ifdef DHD_PCIE_RUNTIMEPM /* This condition is for avoiding counting of wake up from Runtime PM */ @@ -1873,9 +2112,17 @@ static irqreturn_t wlan_oob_irq(int irq, void *data) #ifdef DHD_PCIE_RUNTIMEPM dhdpcie_runtime_bus_wake(bus->dhd, FALSE, wlan_oob_irq); #endif /* DHD_PCIE_RUNTIMPM */ - if (bus->dhd->up && bus->oob_presuspend) { +#ifdef DHD_PCIE_NATIVE_RUNTIMEPM + dhd_bus_wakeup_work(bus->dhd); +#endif /* DHD_PCIE_NATIVE_RUNTIMEPM */ + DHD_BUS_LOCK(bus->bus_lock, flags_bus); + /* Hold wakelock if bus_low_power_state is + * DHD_BUS_D3_INFORM_SENT OR DHD_BUS_D3_ACK_RECIEVED + */ + if (bus->dhd->up && bus->bus_low_power_state != DHD_BUS_NO_LOW_POWER_STATE) { DHD_OS_OOB_IRQ_WAKE_LOCK_TIMEOUT(bus->dhd, OOB_WAKE_LOCK_TIMEOUT); } + DHD_BUS_UNLOCK(bus->bus_lock, flags_bus); return IRQ_HANDLED; } @@ -1923,6 +2170,11 @@ int dhdpcie_oob_intr_register(dhd_bus_t *bus) err = enable_irq_wake(dhdpcie_osinfo->oob_irq_num); if (!err) { dhdpcie_osinfo->oob_irq_wake_enabled = TRUE; + } else { + /* On Hikey platform enable_irq_wake() is failing with error + * ENXIO (No such device or address). This is because the callback function + * irq_set_wake() is not registered in kernel, hence returning BCME_OK. + */ } dhdpcie_osinfo->oob_irq_enabled = TRUE; } @@ -1977,105 +2229,6 @@ void dhdpcie_oob_intr_unregister(dhd_bus_t *bus) } #endif /* BCMPCIE_OOB_HOST_WAKE */ -#ifdef PCIE_OOB -void dhdpcie_oob_init(dhd_bus_t *bus) -{ - gpio_handle_val = get_handle(OOB_PORT); - if (gpio_handle_val < 0) - { - DHD_ERROR(("%s: Could not get GPIO handle.\n", __FUNCTION__)); - ASSERT(FALSE); - } - - gpio_direction = 0; - ftdi_set_bitmode(gpio_handle_val, 0, BITMODE_BITBANG); - - /* Note BT core is also enabled here */ - gpio_port = 1 << BIT_WL_REG_ON | 1 << BIT_BT_REG_ON | 1 << DEVICE_WAKE; - gpio_write_port(gpio_handle_val, gpio_port); - - gpio_direction = 1 << BIT_WL_REG_ON | 1 << BIT_BT_REG_ON | 1 << DEVICE_WAKE; - ftdi_set_bitmode(gpio_handle_val, gpio_direction, BITMODE_BITBANG); - - bus->oob_enabled = TRUE; - bus->oob_presuspend = FALSE; - - /* drive the Device_Wake GPIO low on startup */ - bus->device_wake_state = TRUE; - dhd_bus_set_device_wake(bus, FALSE); - dhd_bus_doorbell_timeout_reset(bus); - -} - -void -dhd_oob_set_bt_reg_on(struct dhd_bus *bus, bool val) -{ - DHD_INFO(("Set Device_Wake to %d\n", val)); - if (val) - { - gpio_port = gpio_port | (1 << BIT_BT_REG_ON); - gpio_write_port(gpio_handle_val, gpio_port); - } else { - gpio_port = gpio_port & (0xff ^ (1 << BIT_BT_REG_ON)); - gpio_write_port(gpio_handle_val, gpio_port); - } -} - -int -dhd_oob_get_bt_reg_on(struct dhd_bus *bus) -{ - int ret; - uint8 val; - ret = gpio_read_port(gpio_handle_val, &val); - - if (ret < 0) { - DHD_ERROR(("gpio_read_port returns %d\n", ret)); - return ret; - } - - if (val & (1 << BIT_BT_REG_ON)) - { - ret = 1; - } else { - ret = 0; - } - - return ret; -} - -int -dhd_os_oob_set_device_wake(struct dhd_bus *bus, bool val) -{ - if (bus->device_wake_state != val) - { - DHD_INFO(("Set Device_Wake to %d\n", val)); - - if (bus->oob_enabled && !bus->oob_presuspend) - { - if (val) - { - gpio_port = gpio_port | (1 << DEVICE_WAKE); - gpio_write_port_non_block(gpio_handle_val, gpio_port); - } else { - gpio_port = gpio_port & (0xff ^ (1 << DEVICE_WAKE)); - gpio_write_port_non_block(gpio_handle_val, gpio_port); - } - } - - bus->device_wake_state = val; - } - return BCME_OK; -} - -INLINE void -dhd_os_ib_set_device_wake(struct dhd_bus *bus, bool val) -{ - /* TODO: Currently Inband implementation of Device_Wake is not supported, - * so this function is left empty later this can be used to support the same. - */ -} -#endif /* PCIE_OOB */ - #ifdef DHD_PCIE_RUNTIMEPM bool dhd_runtimepm_state(dhd_pub_t *dhd) { @@ -2084,7 +2237,6 @@ bool dhd_runtimepm_state(dhd_pub_t *dhd) bus = dhd->bus; DHD_GENERAL_LOCK(dhd, flags); - bus->idlecount++; DHD_TRACE(("%s : Enter \n", __FUNCTION__)); @@ -2223,6 +2375,7 @@ bool dhdpcie_is_resume_done(dhd_pub_t *dhdp) return bus->runtime_resume_done; } #endif /* DHD_PCIE_RUNTIMEPM */ + struct device * dhd_bus_to_dev(dhd_bus_t *bus) { struct pci_dev *pdev; @@ -2233,41 +2386,3 @@ struct device * dhd_bus_to_dev(dhd_bus_t *bus) else return NULL; } -#ifdef HOFFLOAD_MODULES -void -dhd_free_module_memory(struct dhd_bus *bus, struct module_metadata *hmem) -{ - struct device *dev = &bus->dev->dev; - if (hmem) { - dma_unmap_single(dev, (dma_addr_t) hmem->data_addr, hmem->size, DMA_TO_DEVICE); - kfree(hmem->data); - hmem->data = NULL; - hmem->size = 0; - } else { - DHD_ERROR(("dev:%p pci unmapping error\n", dev)); - } -} - -void * -dhd_alloc_module_memory(struct dhd_bus *bus, uint32_t size, struct module_metadata *hmem) -{ - struct device *dev = &bus->dev->dev; - if (!hmem->data) { - hmem->data = kzalloc(size, GFP_KERNEL); - if (!hmem->data) { - DHD_ERROR(("dev:%p mem alloc failure\n", dev)); - return NULL; - } - } - hmem->size = size; - DHD_INFO(("module size: 0x%x \n", hmem->size)); - hmem->data_addr = (u64) dma_map_single(dev, hmem->data, hmem->size, DMA_TO_DEVICE); - if (dma_mapping_error(dev, hmem->data_addr)) { - DHD_ERROR(("dev:%p dma mapping error\n", dev)); - kfree(hmem->data); - hmem->data = NULL; - return hmem->data; - } - return hmem->data; -} -#endif /* HOFFLOAD_MODULES */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.c b/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.c index d7548904ab45439048511dfa3bbc22e7967a845f..eaf83d22afe58ad2667b3a80fc61aecfe53f5903 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.c @@ -1,14 +1,14 @@ /* * DHD debugability packet logging support * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_pktlog.c 735507 2017-12-11 01:31:34Z $ + * $Id: dhd_pktlog.c 737760 2017-12-22 07:59:12Z $ */ #include @@ -34,11 +34,12 @@ #include #include #include +#include #ifdef DHD_PKT_LOGGING #ifndef strtoul #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) -#endif +#endif // endif extern int wl_pattern_atoh(char *src, char *dst); extern uint32 __dhd_dbg_pkt_hash(uintptr_t pkt, uint32 pktid); extern wifi_tx_packet_fate __dhd_dbg_map_tx_status_to_pkt_fate(uint16 status); @@ -62,24 +63,18 @@ dhd_os_attach_pktlog(dhd_pub_t *dhdp) if (unlikely(!pktlog)) { DHD_ERROR(("%s(): could not allocate memory for - " "dhd_pktlog_t\n", __FUNCTION__)); - goto fail; + return BCME_ERROR; } dhdp->pktlog = pktlog; - dhdp->pktlog->tx_pktlog_ring = dhd_pktlog_ring_init(MAX_PKT_LOG_LEN); - dhdp->pktlog->rx_pktlog_ring = dhd_pktlog_ring_init(MAX_PKT_LOG_LEN); + dhdp->pktlog->tx_pktlog_ring = dhd_pktlog_ring_init(dhdp, MIN_PKTLOG_LEN); + dhdp->pktlog->rx_pktlog_ring = dhd_pktlog_ring_init(dhdp, MIN_PKTLOG_LEN); dhdp->pktlog->pktlog_filter = dhd_pktlog_filter_init(MAX_DHD_PKTLOG_FILTER_LEN); DHD_ERROR(("%s(): dhd_os_attach_pktlog attach\n", __FUNCTION__)); return BCME_OK; -fail: - if (pktlog) { - kfree(pktlog); - } - - return BCME_ERROR; } int @@ -93,7 +88,6 @@ dhd_os_detach_pktlog(dhd_pub_t *dhdp) dhd_pktlog_ring_deinit(dhdp->pktlog->tx_pktlog_ring); dhd_pktlog_ring_deinit(dhdp->pktlog->rx_pktlog_ring); - dhd_pktlog_filter_deinit(dhdp->pktlog->pktlog_filter); DHD_ERROR(("%s(): dhd_os_attach_pktlog detach\n", __FUNCTION__)); @@ -104,13 +98,18 @@ dhd_os_detach_pktlog(dhd_pub_t *dhdp) } dhd_pktlog_ring_t* -dhd_pktlog_ring_init(int size) +dhd_pktlog_ring_init(dhd_pub_t *dhdp, int size) { gfp_t kflags; uint32 alloc_len; dhd_pktlog_ring_t *ring; dhd_pktlog_ring_info_t *ring_info = NULL; + if (!dhdp) { + DHD_ERROR(("%s(): dhdp is NULL\n", __FUNCTION__)); + return NULL; + } + kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; alloc_len = sizeof(dhd_pktlog_ring_t); @@ -138,15 +137,14 @@ dhd_pktlog_ring_init(int size) ring->start = TRUE; ring->pktlog_minmize = FALSE; + ring->pktlog_len = size; + ring->dhdp = dhdp; + spin_lock_init(&ring->pktlog_ring_lock); DHD_ERROR(("%s(): pktlog ring init success\n", __FUNCTION__)); return ring; fail: - if (ring_info) { - kfree(ring_info); - } - if (ring) { kfree(ring); } @@ -158,16 +156,42 @@ int dhd_pktlog_ring_deinit(dhd_pktlog_ring_t *ring) { int ret = BCME_OK; + void *data = NULL; + dhd_pktlog_ring_info_t *ring_info; if (!ring) { DHD_ERROR(("%s(): ring is NULL\n", __FUNCTION__)); return -EINVAL; } + if (!ring->dhdp) { + DHD_ERROR(("%s(): dhdp is NULL\n", __FUNCTION__)); + return -EINVAL; + } + + /* stop pkt log */ + ring->start = FALSE; + + /* free ring_info->info.pkt */ + if (dhd_pktlog_ring_set_nextpos(ring) == BCME_OK) { + while (dhd_pktlog_ring_get_nextbuf(ring, &data) == BCME_OK) { + ring_info = (dhd_pktlog_ring_info_t *)data; + + if (ring_info && ring_info->info.pkt) { + PKTFREE(ring->dhdp->osh, ring_info->info.pkt, TRUE); + DHD_PKT_LOG(("%s(): pkt free pos %d\n", + __FUNCTION__, ring->next_pos)); + ring_info->info.pkt = NULL; + } + } + } + if (ring->pktlog_ring_info) { kfree(ring->pktlog_ring_info); + ring->pktlog_ring_info = NULL; } kfree(ring); + ring = NULL; DHD_ERROR(("%s(): pktlog ring deinit\n", __FUNCTION__)); @@ -178,13 +202,13 @@ int dhd_pktlog_ring_set_nextpos(dhd_pktlog_ring_t *ringbuf) { if (!ringbuf) { - DHD_PKT_LOG(("%s(): ringbuf is NULL\n", __FUNCTION__)); + DHD_ERROR(("%s(): ringbuf is NULL\n", __FUNCTION__)); return BCME_ERROR; } /* ring buffer is empty */ if (ringbuf->front == ringbuf->rear) { - DHD_PKT_LOG(("%s(): ringbuf empty\n", __FUNCTION__)); + DHD_ERROR(("%s(): ringbuf empty\n", __FUNCTION__)); return BCME_ERROR; } @@ -233,7 +257,7 @@ dhd_pktlog_ring_get_nextbuf(dhd_pktlog_ring_t *ringbuf, void **data) return BCME_ERROR; } - ringbuf->next_pos = (ringbuf->next_pos + 1) % MAX_PKT_LOG_LEN; + ringbuf->next_pos = (ringbuf->next_pos + 1) % ringbuf->pktlog_len; DHD_PKT_LOG(("%s(): ringbuf next next pos %d\n", __FUNCTION__, ringbuf->next_pos)); @@ -255,7 +279,7 @@ dhd_pktlog_ring_set_prevpos(dhd_pktlog_ring_t *ringbuf) return BCME_ERROR; } - ringbuf->prev_pos = (ringbuf->rear + MAX_PKT_LOG_LEN - 1) % MAX_PKT_LOG_LEN; + ringbuf->prev_pos = (ringbuf->rear + ringbuf->pktlog_len - 1) % ringbuf->pktlog_len; return BCME_OK; } @@ -304,7 +328,7 @@ dhd_pktlog_ring_get_prevbuf(dhd_pktlog_ring_t *ringbuf, void **data) return BCME_ERROR; } - ringbuf->prev_pos = (ringbuf->prev_pos + MAX_PKT_LOG_LEN - 1) % MAX_PKT_LOG_LEN; + ringbuf->prev_pos = (ringbuf->prev_pos + ringbuf->pktlog_len - 1) % ringbuf->pktlog_len; DHD_PKT_LOG(("%s(): ringbuf next prev pos %d\n", __FUNCTION__, ringbuf->prev_pos)); @@ -317,6 +341,7 @@ dhd_pktlog_ring_get_writebuf(dhd_pktlog_ring_t *ringbuf, void **data) dhd_pktlog_ring_info_t *ring_info; uint16 write_pos = 0; uint16 next_write_pos = 0; + unsigned long flags = 0; if (!ringbuf || !data) { DHD_PKT_LOG(("%s(): ringbuf=%p data=%p\n", @@ -324,11 +349,15 @@ dhd_pktlog_ring_get_writebuf(dhd_pktlog_ring_t *ringbuf, void **data) return BCME_ERROR; } + /* PKTLOG Ring Lock */ + spin_lock_irqsave(&ringbuf->pktlog_ring_lock, flags); write_pos = ringbuf->rear; - next_write_pos = (ringbuf->rear + 1) % MAX_PKT_LOG_LEN; + next_write_pos = (ringbuf->rear + 1) % ringbuf->pktlog_len; *data = ((dhd_pktlog_ring_info_t *)ringbuf->pktlog_ring_info) + write_pos; if (*data == NULL) { DHD_PKT_LOG(("%s(): write_pos %d data NULL\n", __FUNCTION__, write_pos)); + /* PKTLOG Ring Unlock */ + spin_unlock_irqrestore(&ringbuf->pktlog_ring_lock, flags); return BCME_ERROR; } @@ -342,11 +371,17 @@ dhd_pktlog_ring_get_writebuf(dhd_pktlog_ring_t *ringbuf, void **data) PKTFREE(ringbuf->dhdp->osh, ring_info->info.pkt, TRUE); DHD_PKT_LOG(("%s(): ringbuf full next write %d pkt free\n", __FUNCTION__, next_write_pos)); + ring_info->info.pkt = NULL; + } else { + DHD_PKT_LOG(("%s(): invalid index : front<%u>, next_pos<%d> \n", + __FUNCTION__, ringbuf->front, next_write_pos)); } - ringbuf->front = (ringbuf->front + 1) % MAX_PKT_LOG_LEN; + ringbuf->front = (ringbuf->front + 1) % ringbuf->pktlog_len; } ringbuf->rear = next_write_pos; + /* PKTLOG Ring Unlock */ + spin_unlock_irqrestore(&ringbuf->pktlog_ring_lock, flags); DHD_PKT_LOG(("%s(): next write pos %d front %d \n", __FUNCTION__, next_write_pos, ringbuf->front)); @@ -580,10 +615,6 @@ dhd_pktlog_filter_init(int size) return filter; fail: - if (filter_info) { - kfree(filter_info); - } - if (filter) { kfree(filter); } @@ -721,8 +752,10 @@ dhd_pktlog_filter_add(dhd_pktlog_filter_t *filter, char *arg) return BCME_ERROR; } - prhex("filter", (char *)&filter->info[filter->list_cnt].pattern[0], - (pattern_size * 2)); + prhex("mask", (char *)&filter->info[filter->list_cnt].mask[0], + mask_size); + prhex("pattern", (char *)&filter->info[filter->list_cnt].pattern[0], + pattern_size); if (mask_size != pattern_size) { DHD_ERROR(("%s(): Mask and pattern not the same size\n", __FUNCTION__)); @@ -958,7 +991,6 @@ dhd_pktlog_pkts_write_file(dhd_pktlog_ring_t *ringbuf, struct file *w_pcap_fp, i } if (dhd_pktlog_ring_set_nextpos(ringbuf) != BCME_OK) { - DHD_ERROR(("%s(): fail set next pos\n", __FUNCTION__)); return BCME_ERROR; } @@ -1076,7 +1108,6 @@ dhd_pktlog_write_file(dhd_pub_t *dhdp) mm_segment_t old_fs; uint32 file_mode; char dump_path[128]; - struct timeval curtime; int ret = BCME_OK; dhd_pktlog_ring_t *tx_pktlog_ring; dhd_pktlog_ring_t *rx_pktlog_ring; @@ -1114,13 +1145,32 @@ dhd_pktlog_write_file(dhd_pub_t *dhdp) set_fs(KERNEL_DS); memset(dump_path, 0, sizeof(dump_path)); - do_gettimeofday(&curtime); - snprintf(dump_path, sizeof(dump_path), "%s_%ld.%ld.pcap", - DHD_PKTLOG_DUMP_PATH "pktlog_dump", - (unsigned long)curtime.tv_sec, (unsigned long)curtime.tv_usec); + get_debug_dump_time(dhdp->debug_dump_time_pktlog_str); + if (dhdp->memdump_type == DUMP_TYPE_BY_SYSDUMP) { + if (dhdp->debug_dump_subcmd == CMD_UNWANTED) { + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_PKTLOG_DUMP_PATH DHD_PKTLOG_DUMP_TYPE + DHD_DUMP_SUBSTR_UNWANTED); + } else if (dhdp->debug_dump_subcmd == CMD_DISCONNECTED) { + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_PKTLOG_DUMP_PATH DHD_PKTLOG_DUMP_TYPE + DHD_DUMP_SUBSTR_DISCONNECTED); + } else { + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_PKTLOG_DUMP_PATH DHD_PKTLOG_DUMP_TYPE); + } + } else { + snprintf(dump_path, sizeof(dump_path), "%s", + DHD_PKTLOG_DUMP_PATH DHD_PKTLOG_DUMP_TYPE); + } + snprintf(dump_path, sizeof(dump_path), "%s_" "%s" + ".pcap", dump_path, + dhdp->debug_dump_time_pktlog_str); file_mode = O_CREAT | O_WRONLY; + clear_debug_dump_time(dhdp->debug_dump_time_pktlog_str); + DHD_ERROR(("pktlog_dump_pcap = %s\n", dump_path)); w_pcap_fp = filp_open(dump_path, file_mode, 0664); @@ -1175,6 +1225,55 @@ fail: DHD_ERROR(("pktlog write file is end, err = %d\n", ret)); +#ifdef DHD_DUMP_MNGR + if (ret >= 0) { + dhd_dump_file_manage_enqueue(dhdp, dump_path, DHD_PKTLOG_DUMP_TYPE); + } +#endif /* DHD_DUMP_MNGR */ + return ret; } + +dhd_pktlog_ring_t* +dhd_pktlog_ring_change_size(dhd_pktlog_ring_t *ringbuf, int size) +{ + uint32 alloc_len; + uint32 pktlog_start; + uint32 pktlog_minmize; + dhd_pktlog_ring_t *pktlog_ring; + dhd_pub_t *dhdp; + + if (!ringbuf) { + DHD_ERROR(("%s(): ringbuf is NULL\n", __FUNCTION__)); + return NULL; + } + + alloc_len = size; + if (alloc_len < MIN_PKTLOG_LEN) { + alloc_len = MIN_PKTLOG_LEN; + } + if (alloc_len > MAX_PKTLOG_LEN) { + alloc_len = MAX_PKTLOG_LEN; + } + DHD_ERROR(("ring size requested: %d alloc: %d\n", size, alloc_len)); + + /* backup variable */ + pktlog_start = ringbuf->start; + pktlog_minmize = ringbuf->pktlog_minmize; + dhdp = ringbuf->dhdp; + + /* free ring_info */ + dhd_pktlog_ring_deinit(ringbuf); + + /* alloc ring_info */ + pktlog_ring = dhd_pktlog_ring_init(dhdp, alloc_len); + + /* restore variable */ + if (pktlog_ring) { + pktlog_ring->start = pktlog_start; + pktlog_ring->pktlog_minmize = pktlog_minmize; + } + + return pktlog_ring; +} #endif /* DHD_PKT_LOGGING */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.h b/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.h index 5f4ec078828c2bd51e0fafb39e9ae36bf74b7db8..5ea8aa3341a8d8d5b00822afd2cb9d16a45960ed 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pktlog.h @@ -1,14 +1,14 @@ /* * DHD debugability packet logging header file * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_pktlog.h 717188 2017-08-23 11:47:08Z $ + * $Id: dhd_pktlog.h 734837 2017-12-06 13:28:15Z $ */ #ifndef __DHD_PKTLOG_H_ @@ -35,7 +35,8 @@ #ifdef DHD_PKT_LOGGING #define DHD_PKT_LOG(args) DHD_INFO(args) -#define MAX_PKT_LOG_LEN (32 * 10) +#define MIN_PKTLOG_LEN (32 * 10) +#define MAX_PKTLOG_LEN (32 * 100) #define MAX_DHD_PKTLOG_FILTER_LEN 10 #define MAX_MASK_PATTERN_FILTER_LEN 64 #define PKTLOG_TXPKT_CASE 0x0001 @@ -65,14 +66,16 @@ typedef struct dhd_pktlog_ring_info typedef struct dhd_pktlog_ring { - dhd_pktlog_ring_info_t *pktlog_ring_info; - dhd_pub_t *dhdp; uint16 front; uint16 rear; uint16 prev_pos; uint16 next_pos; uint32 start; uint32 pktlog_minmize; + uint32 pktlog_len; + dhd_pktlog_ring_info_t *pktlog_ring_info; + dhd_pub_t *dhdp; + spinlock_t pktlog_ring_lock; } dhd_pktlog_ring_t; typedef struct dhd_pktlog_filter_info @@ -118,7 +121,7 @@ typedef struct dhd_pktlog_pcap_hdr extern int dhd_os_attach_pktlog(dhd_pub_t *dhdp); extern int dhd_os_detach_pktlog(dhd_pub_t *dhdp); -extern dhd_pktlog_ring_t* dhd_pktlog_ring_init(int size); +extern dhd_pktlog_ring_t* dhd_pktlog_ring_init(dhd_pub_t *dhdp, int size); extern int dhd_pktlog_ring_deinit(dhd_pktlog_ring_t *ring); extern int dhd_pktlog_ring_set_nextpos(dhd_pktlog_ring_t *ringbuf); extern int dhd_pktlog_ring_get_nextbuf(dhd_pktlog_ring_t *ringbuf, void **data); @@ -129,6 +132,7 @@ extern int dhd_pktlog_ring_tx_pkts(dhd_pub_t *dhdp, void *pkt, uint32 pktid); extern int dhd_pktlog_ring_tx_status(dhd_pub_t *dhdp, void *pkt, uint32 pktid, uint16 status); extern int dhd_pktlog_ring_rx_pkts(dhd_pub_t *dhdp, void *pkt); +extern dhd_pktlog_ring_t* dhd_pktlog_ring_change_size(dhd_pktlog_ring_t *ringbuf, int size); #define DHD_PKTLOG_TX(dhdp, pkt, pktid) \ { \ @@ -191,6 +195,6 @@ extern int dhd_pktlog_write_file(dhd_pub_t *dhdp); #define DHD_PKTLOG_FATE_INFO_STR_LEN 256 #define DHD_PKTLOG_FATE_INFO_FORMAT "BRCM_Packet_Fate" - +#define DHD_PKTLOG_DUMP_TYPE "pktlog_dump" #endif /* DHD_PKT_LOGGING */ #endif /* __DHD_PKTLOG_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pno.c b/drivers/net/wireless/bcmdhd_oo/dhd_pno.c index 15da63a2dc736f24019a0942fbe3a7882d921397..af9f150191f906540fc7959795617a98b56f0434 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pno.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pno.c @@ -2,14 +2,14 @@ * Broadcom Dongle Host Driver (DHD) * Prefered Network Offload and Wi-Fi Location Service(WLS) code. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,12 +25,12 @@ * * <> * - * $Id: dhd_pno.c 735359 2017-12-08 10:56:04Z $ + * $Id: dhd_pno.c 736010 2017-12-13 08:45:59Z $ */ #if defined(GSCAN_SUPPORT) && !defined(PNO_SUPPORT) #error "GSCAN needs PNO to be enabled!" -#endif +#endif // endif #ifdef PNO_SUPPORT #include @@ -85,11 +85,19 @@ } \ } while (0) #define PNO_GET_PNOSTATE(dhd) ((dhd_pno_status_info_t *)dhd->pno_state) -#define PNO_BESTNET_LEN 1024 + +#define PNO_BESTNET_LEN WLC_IOCTL_MEDLEN + #define PNO_ON 1 #define PNO_OFF 0 +#define CHANNEL_2G_MIN 1 #define CHANNEL_2G_MAX 14 +#define CHANNEL_5G_MIN 34 #define CHANNEL_5G_MAX 165 +#define IS_2G_CHANNEL(ch) ((ch >= CHANNEL_2G_MIN) && \ + (ch <= CHANNEL_2G_MAX)) +#define IS_5G_CHANNEL(ch) ((ch >= CHANNEL_5G_MIN) && \ + (ch <= CHANNEL_5G_MAX)) #define MAX_NODE_CNT 5 #define WLS_SUPPORTED(pno_state) (pno_state->wls_supported == TRUE) #define TIME_DIFF(timestamp1, timestamp2) (abs((uint32)(timestamp1/1000) \ @@ -114,21 +122,33 @@ static int _dhd_pno_flush_ssid(dhd_pub_t *dhd); static wl_pfn_gscan_ch_bucket_cfg_t * dhd_pno_gscan_create_channel_list(dhd_pub_t *dhd, dhd_pno_status_info_t *pno_state, - uint16 *chan_list, uint32 *num_buckets, uint32 *num_buckets_to_fw); + uint16 *chan_list, uint32 *num_buckets, uint32 *num_buckets_to_fw); #endif /* GSCAN_SUPPORT */ + static int dhd_pno_set_legacy_pno(dhd_pub_t *dhd, uint16 scan_fr, int pno_repeat, - int pno_freq_expo_max, uint16 *channel_list, int nchan); + int pno_freq_expo_max, uint16 *channel_list, int nchan); static inline bool -is_dfs(uint16 channel) +is_dfs(dhd_pub_t *dhd, uint16 channel) { - if (channel >= 52 && channel <= 64) /* class 2 */ - return TRUE; - else if (channel >= 100 && channel <= 140) /* class 4 */ - return TRUE; - else + u32 ch; + s32 err; + u8 buf[32]; + + ch = wl_ch_host_to_driver(channel); + err = dhd_iovar(dhd, 0, "per_chan_info", (char *)&ch, + sizeof(u32), buf, sizeof(buf), FALSE); + if (unlikely(err)) { + DHD_ERROR(("get per chan info failed:%d\n", err)); return FALSE; + } + /* Check the channel flags returned by fw */ + if (*((u32 *)buf) & WL_CHAN_PASSIVE) { + return TRUE; + } + return FALSE; } + int dhd_pno_clean(dhd_pub_t *dhd) { @@ -193,7 +213,7 @@ convert_fw_rel_time_to_systime(struct timespec *ts, uint32 fw_ts_ms) static void dhd_pno_idx_to_ssid(struct dhd_pno_gscan_params *gscan_params, - dhd_epno_results_t *res, uint32 idx) + dhd_epno_results_t *res, uint32 idx) { dhd_pno_ssid_t *iter, *next; int i; @@ -210,7 +230,7 @@ dhd_pno_idx_to_ssid(struct dhd_pno_gscan_params *gscan_params, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &gscan_params->epno_cfg.epno_ssid_list, list) { if (i++ == idx) { @@ -228,7 +248,8 @@ exit: } /* Translate HAL flag bitmask to BRCM FW flag bitmask */ -void dhd_pno_translate_epno_fw_flags(uint32 *flags) +void +dhd_pno_translate_epno_fw_flags(uint32 *flags) { uint32 in_flags, fw_flags = 0; in_flags = *flags; @@ -242,7 +263,7 @@ void dhd_pno_translate_epno_fw_flags(uint32 *flags) } if (!(in_flags & DHD_EPNO_STRICT_MATCH) && - !(in_flags & DHD_EPNO_HIDDEN_SSID)) { + !(in_flags & DHD_EPNO_HIDDEN_SSID)) { fw_flags |= WL_PFN_SSID_IMPRECISE_MATCH; } @@ -258,7 +279,8 @@ void dhd_pno_translate_epno_fw_flags(uint32 *flags) } /* Translate HAL auth bitmask to BRCM FW bitmask */ -void dhd_pno_set_epno_auth_flag(uint32 *wpa_auth) +void +dhd_pno_set_epno_auth_flag(uint32 *wpa_auth) { switch (*wpa_auth) { case DHD_PNO_AUTH_CODE_OPEN: @@ -315,7 +337,6 @@ exit: return err; } -#ifdef GSCAN_SUPPORT static int _dhd_pno_flush_ssid(dhd_pub_t *dhd) { @@ -323,13 +344,13 @@ _dhd_pno_flush_ssid(dhd_pub_t *dhd) wl_pfn_t pfn_elem; memset(&pfn_elem, 0, sizeof(wl_pfn_t)); pfn_elem.flags = htod32(WL_PFN_FLUSH_ALL_SSIDS); + err = dhd_iovar(dhd, 0, "pfn_add", (char *)&pfn_elem, sizeof(wl_pfn_t), NULL, 0, TRUE); if (err < 0) { DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__)); } return err; } -#endif /* GSCAN_SUPPORT */ static bool is_batch_retrieval_complete(struct dhd_pno_gscan_params *gscan_params) @@ -582,7 +603,6 @@ _dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t #else if (mode == DHD_PNO_BATCH_MODE) { #endif /* GSCAN_SUPPORT */ - int _tmp = pfn_param.bestn; /* set bestn to calculate the max mscan which firmware supports */ err = dhd_iovar(dhd, 0, "pfnmem", (char *)&_tmp, sizeof(_tmp), NULL, 0, TRUE); @@ -610,9 +630,8 @@ _dhd_pno_set(dhd_pub_t *dhd, const dhd_pno_params_t *pno_params, dhd_pno_mode_t exit: return err; } - static int -_dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head *ssid_list, int nssid) +_dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head* ssid_list, int nssid) { int err = BCME_OK; int i = 0, mem_needed; @@ -625,7 +644,7 @@ _dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head *ssid_list, int nssid) return BCME_ERROR; } mem_needed = (sizeof(wl_pfn_t) * nssid); - pfn_elem_buf = (wl_pfn_t *) kzalloc(mem_needed, GFP_KERNEL); + pfn_elem_buf = (wl_pfn_t *) MALLOCZ(dhd->osh, mem_needed); if (!pfn_elem_buf) { DHD_ERROR(("%s: Can't malloc %d bytes!\n", __FUNCTION__, mem_needed)); return BCME_NOMEM; @@ -634,7 +653,7 @@ _dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head *ssid_list, int nssid) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, ssid_list, list) { pfn_elem_buf[i].infra = htod32(1); pfn_elem_buf[i].auth = htod32(DOT11_OPEN_SYSTEM); @@ -663,7 +682,7 @@ _dhd_pno_add_ssid(dhd_pub_t *dhd, struct list_head *ssid_list, int nssid) if (err < 0) { DHD_ERROR(("%s : failed to execute pfn_add\n", __FUNCTION__)); } - kfree(pfn_elem_buf); + MFREE(dhd->osh, pfn_elem_buf, mem_needed); return err; } /* qsort compare function */ @@ -725,35 +744,37 @@ _dhd_pno_get_channels(dhd_pub_t *dhd, uint16 *d_chan_list, err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VALID_CHANNELS, chan_buf, sizeof(chan_buf), FALSE, 0); if (err < 0) { DHD_ERROR(("failed to get channel list (err: %d)\n", err)); - goto exit; + return err; } for (i = 0, j = 0; i < dtoh32(list->count) && i < *nchan; i++) { - if (band == WLC_BAND_2G) { - if (dtoh32(list->element[i]) > CHANNEL_2G_MAX) - continue; - } else if (band == WLC_BAND_5G) { - if (dtoh32(list->element[i]) <= CHANNEL_2G_MAX) - continue; - if (skip_dfs && is_dfs(dtoh32(list->element[i]))) - continue; - - } else if (band == WLC_BAND_AUTO) { - if (skip_dfs || !is_dfs(dtoh32(list->element[i]))) + if (IS_2G_CHANNEL(dtoh32(list->element[i]))) { + if (!(band & WLC_BAND_2G)) { + /* Skip, if not 2g */ continue; - - } else { /* All channels */ - if (skip_dfs && is_dfs(dtoh32(list->element[i]))) + } + /* fall through to include the channel */ + } else if (IS_5G_CHANNEL(dtoh32(list->element[i]))) { + bool dfs_channel = is_dfs(dhd, dtoh32(list->element[i])); + if ((skip_dfs && dfs_channel) || + (!(band & WLC_BAND_5G) && !dfs_channel)) { + /* Skip the channel if: + * the DFS bit is NOT set & the channel is a dfs channel + * the band 5G is not set & the channel is a non DFS 5G channel + */ continue; - } - if (dtoh32(list->element[i]) <= CHANNEL_5G_MAX) { - d_chan_list[j++] = (uint16) dtoh32(list->element[i]); + } + /* fall through to include the channel */ } else { - err = BCME_BADCHAN; - goto exit; + /* Not in range. Bad channel */ + DHD_ERROR(("Not in range. bad channel\n")); + *nchan = 0; + return BCME_BADCHAN; } + + /* Include the channel */ + d_chan_list[j++] = (uint16) dtoh32(list->element[i]); } *nchan = j; -exit: return err; } static int @@ -770,7 +791,7 @@ _dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batc #ifdef PNO_DEBUG char *_base_bp; char msg[150]; -#endif +#endif // endif dhd_pno_bestnet_entry_t *iter, *next; dhd_pno_scan_results_t *siter, *snext; dhd_pno_best_header_t *phead, *pprev; @@ -792,12 +813,12 @@ _dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batc #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(siter, snext, ¶ms_batch->get_batch.expired_scan_results_list, list) { #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif phead = siter->bestnetheader; while (phead != NULL) { /* if left_size is less than bestheader total size , stop this */ @@ -816,17 +837,17 @@ _dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batc #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &phead->entry_list, list) { #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif t_delta = jiffies_to_msecs(jiffies - iter->recorded_time); #ifdef PNO_DEBUG _base_bp = bp; memset(msg, 0, sizeof(msg)); -#endif +#endif // endif /* BSSID info */ bp += nreadsize = snprintf(bp, nleftsize, "bssid=%s\n", bcm_ether_ntoa((const struct ether_addr *)&iter->BSSID, eabuf)); @@ -863,7 +884,7 @@ _dhd_pno_convert_format(dhd_pub_t *dhd, struct dhd_pno_batch_params *params_batc #ifdef PNO_DEBUG memcpy(msg, _base_bp, bp - _base_bp); DHD_PNO(("Entry : \n%s", msg)); -#endif +#endif // endif } bp += nreadsize = snprintf(bp, nleftsize, "%s", SCAN_END_MARKER); DHD_PNO(("%s", SCAN_END_MARKER)); @@ -892,11 +913,11 @@ exit: #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif if (list_empty(¶ms_batch->get_batch.expired_scan_results_list)) { #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif params_batch->get_batch.batch_started = FALSE; bp += snprintf(bp, nleftsize, "%s", RESULTS_END_MARKER); DHD_PNO(("%s", RESULTS_END_MARKER)); @@ -921,7 +942,7 @@ _dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool on #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(siter, snext, head, list) { if (only_last) { @@ -952,7 +973,7 @@ _dhd_pno_clear_all_batch_results(dhd_pub_t *dhd, struct list_head *head, bool on } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif return removed_scan_cnt; } @@ -1005,16 +1026,16 @@ _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mod #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, ¶ms->params_legacy.ssid_list, list) { list_del(&iter->list); - kfree(iter); + MFREE(dhd->osh, iter, sizeof(struct dhd_pno_ssid)); } } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif params->params_legacy.nssid = 0; params->params_legacy.scan_fr = 0; params->params_legacy.pno_freq_expo_max = 0; @@ -1055,15 +1076,15 @@ _dhd_pno_reinitialize_prof(dhd_pub_t *dhd, dhd_pno_params_t *params, dhd_pno_mod #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, ¶ms->params_hotlist.bssid_list, list) { list_del(&iter->list); - kfree(iter); + MFREE(dhd->osh, iter, sizeof(struct dhd_pno_ssid)); } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif } params->params_hotlist.scan_fr = 0; params->params_hotlist.nbssid = 0; @@ -1102,10 +1123,11 @@ int dhd_pno_stop_for_ssid(dhd_pub_t *dhd) { int err = BCME_OK; - uint32 mode = 0; + uint32 mode = 0, cnt = 0; dhd_pno_status_info_t *_pno_state; - dhd_pno_params_t *_params; - wl_pfn_bssid_t *p_pfn_bssid = NULL; + dhd_pno_params_t *_params = NULL; + wl_pfn_bssid_t *p_pfn_bssid = NULL, *tmp_bssid; + NULL_CHECK(dhd, "dev is NULL", err); NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); _pno_state = PNO_GET_PNOSTATE(dhd); @@ -1179,8 +1201,8 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) /* restart HOTLIST SCAN */ struct dhd_pno_bssid *iter, *next; _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); - p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) * - _params->params_hotlist.nbssid, GFP_KERNEL); + p_pfn_bssid = MALLOCZ(dhd->osh, sizeof(wl_pfn_bssid_t) * + _params->params_hotlist.nbssid); if (p_pfn_bssid == NULL) { DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array" " (count: %d)", @@ -1193,17 +1215,26 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif + cnt = 0; + tmp_bssid = p_pfn_bssid; list_for_each_entry_safe(iter, next, &_params->params_hotlist.bssid_list, list) { - memcpy(&p_pfn_bssid->macaddr, + memcpy(&tmp_bssid->macaddr, &iter->macaddr, ETHER_ADDR_LEN); - p_pfn_bssid->flags = iter->flags; - p_pfn_bssid++; + tmp_bssid->flags = iter->flags; + if (cnt < _params->params_hotlist.nbssid) { + tmp_bssid++; + cnt++; + } else { + DHD_ERROR(("%s: Allocated insufficient memory\n", + __FUNCTION__)); + break; + } } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist); if (err < 0) { _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; @@ -1221,7 +1252,10 @@ dhd_pno_stop_for_ssid(dhd_pub_t *dhd) } } exit: - kfree(p_pfn_bssid); + if (p_pfn_bssid) { + MFREE(dhd->osh, p_pfn_bssid, sizeof(wl_pfn_bssid_t) * + _params->params_hotlist.nbssid); + } return err; } @@ -1235,7 +1269,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int enable) } static int -dhd_pno_add_to_ssid_list(struct list_head *ptr, wlc_ssid_ext_t *ssid_list, +dhd_pno_add_to_ssid_list(dhd_pub_t *dhd, struct list_head *ptr, wlc_ssid_ext_t *ssid_list, int nssid, int *num_ssid_added) { int ret = BCME_OK; @@ -1255,8 +1289,8 @@ dhd_pno_add_to_ssid_list(struct list_head *ptr, wlc_ssid_ext_t *ssid_list, ret = BCME_ERROR; goto exit; } - - _pno_ssid = kzalloc(sizeof(struct dhd_pno_ssid), GFP_KERNEL); + _pno_ssid = (struct dhd_pno_ssid *)MALLOCZ(dhd->osh, + sizeof(struct dhd_pno_ssid)); if (_pno_ssid == NULL) { DHD_ERROR(("%s : failed to allocate struct dhd_pno_ssid\n", __FUNCTION__)); @@ -1282,7 +1316,6 @@ int dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid, uint16 scan_fr, int pno_repeat, int pno_freq_expo_max, uint16 *channel_list, int nchan) { - dhd_pno_status_info_t *_pno_state; dhd_pno_params_t *_params; struct dhd_pno_legacy_params *params_legacy; @@ -1310,18 +1343,18 @@ dhd_pno_set_for_ssid(dhd_pub_t *dhd, wlc_ssid_ext_t* ssid_list, int nssid, INIT_LIST_HEAD(¶ms_legacy->ssid_list); - if (dhd_pno_add_to_ssid_list(¶ms_legacy->ssid_list, ssid_list, - nssid, ¶ms_legacy->nssid) < 0) { + if (dhd_pno_add_to_ssid_list(dhd, ¶ms_legacy->ssid_list, ssid_list, + nssid, ¶ms_legacy->nssid) < 0) { _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_LEGACY_MODE); return BCME_ERROR; } DHD_PNO(("%s enter : nssid %d, scan_fr :%d, pno_repeat :%d," - "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__, - params_legacy->nssid, scan_fr, pno_repeat, pno_freq_expo_max, nchan)); + "pno_freq_expo_max: %d, nchan :%d\n", __FUNCTION__, + params_legacy->nssid, scan_fr, pno_repeat, pno_freq_expo_max, nchan)); return dhd_pno_set_legacy_pno(dhd, scan_fr, pno_repeat, - pno_freq_expo_max, channel_list, nchan); + pno_freq_expo_max, channel_list, nchan); } @@ -1340,13 +1373,14 @@ dhd_pno_set_legacy_pno(dhd_pub_t *dhd, uint16 scan_fr, int pno_repeat, struct list_head *ssid_list; _pno_state = PNO_GET_PNOSTATE(dhd); + _params = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS]); /* If GSCAN is also ON will handle this down below */ #ifdef GSCAN_SUPPORT if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE && !(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) { #else - if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { + if (_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) { #endif /* GSCAN_SUPPORT */ DHD_ERROR(("%s : Legacy PNO mode was already started, " "will disable previous one to start new one\n", __FUNCTION__)); @@ -1368,13 +1402,13 @@ dhd_pno_set_legacy_pno(dhd_pub_t *dhd, uint16 scan_fr, int pno_repeat, else { tot_nchan = WL_NUMCHANNELS; err = _dhd_pno_get_channels(dhd, _chan_list, &tot_nchan, - (WLC_BAND_2G | WLC_BAND_5G), FALSE); + (WLC_BAND_2G | WLC_BAND_5G), FALSE); if (err < 0) { tot_nchan = 0; DHD_PNO(("Could not get channel list for PNO SSID\n")); } else { for (i = 0; i < tot_nchan; i++) - _params->params_legacy.chan_list[i] = _chan_list[i]; + _params->params_legacy.chan_list[i] = _chan_list[i]; } } #endif /* GSCAN_SUPPORT */ @@ -1557,7 +1591,7 @@ dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *batch_params) } DHD_PNO(("\n")); } -#endif +#endif // endif if (_params->params_batch.nchan) { /* copy the channel list into local array */ memcpy(_chan_list, _params->params_batch.chan_list, sizeof(_chan_list)); @@ -1626,11 +1660,10 @@ exit: return err; } - #ifdef GSCAN_SUPPORT static int -dhd_set_epno_params(dhd_pub_t *dhd, wl_pfn_ssid_params_t *params, bool set) +dhd_set_epno_params(dhd_pub_t *dhd, wl_ssid_ext_params_t *params, bool set) { wl_pfn_ssid_cfg_t cfg; int err; @@ -1642,7 +1675,7 @@ dhd_set_epno_params(dhd_pub_t *dhd, wl_pfn_ssid_params_t *params, bool set) if (!set) cfg.flags |= WL_PFN_SSID_CFG_CLEAR; else if (params) - memcpy(&cfg.params, params, sizeof(wl_pfn_ssid_params_t)); + memcpy(&cfg.params, params, sizeof(wl_ssid_ext_params_t)); err = dhd_iovar(dhd, 0, "pfn_ssid_cfg", (char *)&cfg, sizeof(wl_pfn_ssid_cfg_t), NULL, 0, TRUE); if (err != BCME_OK) { @@ -1685,7 +1718,7 @@ dhd_pno_set_epno(dhd_pub_t *dhd) if (gscan_params->epno_cfg.num_epno_ssid) { DHD_PNO(("num_epno_ssid %d\n", gscan_params->epno_cfg.num_epno_ssid)); if ((err = _dhd_pno_add_ssid(dhd, &gscan_params->epno_cfg.epno_ssid_list, - gscan_params->epno_cfg.num_epno_ssid)) < 0) { + gscan_params->epno_cfg.num_epno_ssid)) < 0) { DHD_ERROR(("failed to add ssid list (err %d) to firmware\n", err)); return err; } @@ -1697,9 +1730,8 @@ dhd_pno_set_epno(dhd_pub_t *dhd) return err; } - static void -dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params, +dhd_pno_reset_cfg_gscan(dhd_pub_t *dhd, dhd_pno_params_t *_params, dhd_pno_status_info_t *_pno_state, uint8 flags) { DHD_PNO(("%s enter\n", __FUNCTION__)); @@ -1722,15 +1754,15 @@ dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &_params->params_gscan.hotlist_bssid_list, list) { list_del(&iter->list); - kfree(iter); + MFREE(dhd->osh, iter, sizeof(struct dhd_pno_bssid)); } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif } _params->params_gscan.nbssid_hotlist = 0; DHD_PNO(("Flush Hotlist Config\n")); @@ -1743,18 +1775,18 @@ dhd_pno_reset_cfg_gscan(dhd_pno_params_t *_params, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &epno_cfg->epno_ssid_list, list) { list_del(&iter->list); - kfree(iter); + MFREE(dhd->osh, iter, sizeof(struct dhd_pno_bssid)); } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif - epno_cfg->num_epno_ssid = 0; +#endif // endif + epno_cfg->num_epno_ssid = 0; } - memset(&epno_cfg->params, 0, sizeof(wl_pfn_ssid_params_t)); + memset(&epno_cfg->params, 0, sizeof(wl_ssid_ext_params_t)); DHD_PNO(("Flushed ePNO Config\n")); } @@ -1783,7 +1815,8 @@ dhd_pno_unlock_batch_results(dhd_pub_t *dhd) return; } -int dhd_wait_batch_results_complete(dhd_pub_t *dhd) +int +dhd_wait_batch_results_complete(dhd_pub_t *dhd) { dhd_pno_status_info_t *_pno_state; dhd_pno_params_t *_params; @@ -1886,7 +1919,7 @@ dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, int8 flags; if (flush) { - dhd_pno_reset_cfg_gscan(_params, _pno_state, + dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state, GSCAN_FLUSH_HOTLIST_CFG); } @@ -1898,8 +1931,8 @@ dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, } for (i = 0, bssid_ptr = ptr->bssid; i < ptr->nbssid; i++, bssid_ptr++) { - _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL); - + _pno_bssid = (struct dhd_pno_bssid *)MALLOCZ(dhd->osh, + sizeof(struct dhd_pno_bssid)); if (!_pno_bssid) { DHD_ERROR(("_pno_bssid is NULL, cannot kalloc %zd bytes", sizeof(struct dhd_pno_bssid))); @@ -1977,24 +2010,24 @@ dhd_pno_set_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, break; case DHD_PNO_EPNO_CFG_ID: if (flush) { - dhd_pno_reset_cfg_gscan(_params, _pno_state, - GSCAN_FLUSH_EPNO_CFG); + dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state, + GSCAN_FLUSH_EPNO_CFG); } break; case DHD_PNO_EPNO_PARAMS_ID: if (flush) { memset(&_params->params_gscan.epno_cfg.params, 0, - sizeof(wl_pfn_ssid_params_t)); + sizeof(wl_ssid_ext_params_t)); } if (buf) { memcpy(&_params->params_gscan.epno_cfg.params, buf, - sizeof(wl_pfn_ssid_params_t)); + sizeof(wl_ssid_ext_params_t)); } break; default: - err = BCME_BADARG; - DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type)); - break; + err = BCME_BADARG; + DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type)); + break; } exit: mutex_unlock(&_pno_state->pno_mutex); @@ -2002,7 +2035,6 @@ exit: } - static bool validate_gscan_params(struct dhd_pno_gscan_params *gscan_params) { @@ -2040,7 +2072,6 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); wl_pfn_gscan_ch_bucket_cfg_t *ch_bucket = NULL; wl_pfn_gscan_cfg_t *pfn_gscan_cfg_t = NULL; - wl_pfn_significant_bssid_t *p_pfn_significant_bssid = NULL; wl_pfn_bssid_t *p_pfn_bssid = NULL; dhd_pno_params_t *_params; bool fw_flushed = FALSE; @@ -2097,7 +2128,8 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) if ((_pno_state->pno_mode & DHD_PNO_LEGACY_MODE) && !gscan_params->epno_cfg.num_epno_ssid) { struct dhd_pno_legacy_params *params_legacy; - params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); + params_legacy = + &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); if ((err = _dhd_pno_add_ssid(dhd, ¶ms_legacy->ssid_list, params_legacy->nssid)) < 0) { @@ -2170,8 +2202,8 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) if (gscan_params->nbssid_hotlist) { struct dhd_pno_bssid *iter, *next; wl_pfn_bssid_t *ptr; - p_pfn_bssid = (wl_pfn_bssid_t *)kzalloc(sizeof(wl_pfn_bssid_t) * - gscan_params->nbssid_hotlist, GFP_KERNEL); + p_pfn_bssid = (wl_pfn_bssid_t *)MALLOCZ(dhd->osh, + sizeof(wl_pfn_bssid_t) * gscan_params->nbssid_hotlist); if (p_pfn_bssid == NULL) { DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array" " (count: %d)", @@ -2186,20 +2218,20 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &gscan_params->hotlist_bssid_list, list) { char buffer_hotlist[64]; memcpy(&ptr->macaddr, &iter->macaddr, ETHER_ADDR_LEN); - DHD_PNO(("%s\n", bcm_ether_ntoa(&ptr->macaddr, buffer_hotlist))); BCM_REFERENCE(buffer_hotlist); + DHD_PNO(("%s\n", bcm_ether_ntoa(&ptr->macaddr, buffer_hotlist))); ptr->flags = iter->flags; ptr++; } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif err = _dhd_pno_add_bssid(dhd, p_pfn_bssid, gscan_params->nbssid_hotlist); if (err < 0) { @@ -2208,6 +2240,7 @@ dhd_pno_set_for_gscan(dhd_pub_t *dhd, struct dhd_pno_gscan_params *gscan_params) goto exit; } } + if ((err = _dhd_pno_enable(dhd, PNO_ON)) < 0) { DHD_ERROR(("%s : failed to enable PNO err %d\n", __FUNCTION__, err)); } @@ -2224,8 +2257,8 @@ exit: _pno_state->pno_mode &= ~DHD_PNO_GSCAN_MODE; } } - kfree(p_pfn_significant_bssid); - kfree(p_pfn_bssid); + MFREE(dhd->osh, p_pfn_bssid, + sizeof(wl_pfn_bssid_t) * gscan_params->nbssid_hotlist); if (pfn_gscan_cfg_t) { MFREE(dhd->osh, pfn_gscan_cfg_t, gscan_param_size); } @@ -2412,9 +2445,10 @@ dhd_pno_stop_for_gscan(dhd_pub_t *dhd) params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); _pno_state->pno_mode &= ~DHD_PNO_LEGACY_MODE; + DHD_PNO(("Restarting Legacy PNO SSID scan...\n")); memcpy(chan_list, params_legacy->chan_list, - (params_legacy->nchan * sizeof(uint16))); + (params_legacy->nchan * sizeof(uint16))); err = dhd_pno_set_legacy_pno(dhd, params_legacy->scan_fr, params_legacy->pno_repeat, params_legacy->pno_freq_expo_max, chan_list, params_legacy->nchan); @@ -2452,7 +2486,7 @@ dhd_pno_initiate_gscan_request(dhd_pub_t *dhd, bool run, bool flush) } else { if (flush) { mutex_lock(&_pno_state->pno_mutex); - dhd_pno_reset_cfg_gscan(params, _pno_state, GSCAN_FLUSH_ALL_CFG); + dhd_pno_reset_cfg_gscan(dhd, params, _pno_state, GSCAN_FLUSH_ALL_CFG); mutex_unlock(&_pno_state->pno_mutex); } /* Need to stop all gscan */ @@ -2518,7 +2552,7 @@ exit: } /* Cleanup any consumed results - * Return TRUE if all results consumed, else FALSE + * Return TRUE if all results consumed else FALSE */ int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd) { @@ -2536,7 +2570,9 @@ int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd) while (iter) { if (iter->tot_consumed == iter->tot_count) { tmp = iter->next; - kfree(iter); + MFREE(dhd->osh, iter, + ((iter->tot_count - 1) * sizeof(wifi_gscan_result_t)) + + sizeof(gscan_results_cache_t)); iter = tmp; } else break; @@ -2553,16 +2589,26 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) uint32 timestamp = 0, ts = 0, i, j, timediff; dhd_pno_params_t *params; dhd_pno_status_info_t *_pno_state; - wl_pfn_lnet_info_v2_t *plnetinfo; + wl_pfn_lnet_info_v1_t *plnetinfo; + wl_pfn_lnet_info_v2_t *plnetinfo_v2; struct dhd_pno_gscan_params *gscan_params; - wl_pfn_lscanresults_v2_t *plbestnet = NULL; + wl_pfn_lscanresults_v1_t *plbestnet_v1 = NULL; + wl_pfn_lscanresults_v2_t *plbestnet_v2 = NULL; gscan_results_cache_t *iter, *tail; wifi_gscan_result_t *result; uint8 *nAPs_per_scan = NULL; uint8 num_scans_in_cur_iter; uint16 count; + uint16 fwcount; + uint16 fwstatus = PFN_INCOMPLETE; struct timespec tm_spec; + /* Static asserts in _dhd_pno_get_for_batch() below guarantee the v1 and v2 + * net_info and subnet_info structures are compatible in size and SSID offset, + * allowing v1 to be safely used in the code below except for lscanresults + * fields themselves (status, count, offset to netinfo). + */ + NULL_CHECK(dhd, "dhd is NULL\n", err); NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); @@ -2589,13 +2635,14 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) goto exit; } - plbestnet = (wl_pfn_lscanresults_v2_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN); - if (!plbestnet) { + plbestnet_v1 = (wl_pfn_lscanresults_v1_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN); + if (!plbestnet_v1) { DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", __FUNCTION__, - PNO_BESTNET_LEN)); + (int)PNO_BESTNET_LEN)); err = BCME_NOMEM; goto exit; } + plbestnet_v2 = (wl_pfn_lscanresults_v2_t *)plbestnet_v1; mutex_lock(&_pno_state->pno_mutex); @@ -2610,11 +2657,9 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) timediff = timediff >> 1; /* Ok, now lets start getting results from the FW */ - plbestnet->status = PFN_INCOMPLETE; tail = gscan_params->gscan_batch_cache; - while (plbestnet->status != PFN_COMPLETE) { - memset(plbestnet, 0, PNO_BESTNET_LEN); - err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet, PNO_BESTNET_LEN, + do { + err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet_v1, PNO_BESTNET_LEN, FALSE); if (err < 0) { DHD_ERROR(("%s : Cannot get all the batch results, err :%d\n", @@ -2622,124 +2667,274 @@ _dhd_pno_get_gscan_batch_from_fw(dhd_pub_t *dhd) goto exit_mutex_unlock; } get_monotonic_boottime(&tm_spec); - DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version, - plbestnet->status, plbestnet->count)); - if (plbestnet->version != PFN_SCANRESULT_VERSION) { - err = BCME_VERSION; - DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n", - plbestnet->version, PFN_SCANRESULT_VERSION)); - goto exit_mutex_unlock; - } - if (plbestnet->count == 0) { - DHD_PNO(("No more batch results\n")); - goto exit_mutex_unlock; - } - num_scans_in_cur_iter = 0; - timestamp = plbestnet->netinfo[0].timestamp; - /* find out how many scans' results did we get in this batch of FW results */ - for (i = 0, count = 0; i < plbestnet->count; i++, count++) { - plnetinfo = &plbestnet->netinfo[i]; - /* Unlikely to happen, but just in case the results from - * FW doesnt make sense..... Assume its part of one single scan + + if (plbestnet_v1->version == PFN_LBEST_SCAN_RESULT_VERSION_V1) { + fwstatus = plbestnet_v1->status; + fwcount = plbestnet_v1->count; + plnetinfo = &plbestnet_v1->netinfo[0]; + + DHD_PNO(("ver %d, status : %d, count %d\n", + plbestnet_v1->version, fwstatus, fwcount)); + + if (fwcount == 0) { + DHD_PNO(("No more batch results\n")); + goto exit_mutex_unlock; + } + if (fwcount > BESTN_MAX) { + DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n", + __FUNCTION__, fwcount, (int)BESTN_MAX)); + /* Process only BESTN_MAX number of results per batch */ + fwcount = BESTN_MAX; + } + num_scans_in_cur_iter = 0; + + timestamp = plnetinfo->timestamp; + /* find out how many scans' results did we get in + * this batch of FW results */ - if (num_scans_in_cur_iter >= gscan_params->mscan) { - num_scans_in_cur_iter = 0; - count = plbestnet->count; - break; + for (i = 0, count = 0; i < fwcount; i++, count++, plnetinfo++) { + /* Unlikely to happen, but just in case the results from + * FW doesnt make sense..... Assume its part of one single scan + */ + if (num_scans_in_cur_iter >= gscan_params->mscan) { + num_scans_in_cur_iter = 0; + count = fwcount; + break; + } + if (TIME_DIFF_MS(timestamp, plnetinfo->timestamp) > timediff) { + nAPs_per_scan[num_scans_in_cur_iter] = count; + count = 0; + num_scans_in_cur_iter++; + } + timestamp = plnetinfo->timestamp; } - if (TIME_DIFF_MS(timestamp, plnetinfo->timestamp) > timediff) { + if (num_scans_in_cur_iter < gscan_params->mscan) { nAPs_per_scan[num_scans_in_cur_iter] = count; - count = 0; num_scans_in_cur_iter++; } - timestamp = plnetinfo->timestamp; - } - if (num_scans_in_cur_iter < gscan_params->mscan) { - nAPs_per_scan[num_scans_in_cur_iter] = count; - num_scans_in_cur_iter++; - } - DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter)); - plnetinfo = &plbestnet->netinfo[0]; + DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter)); + /* reset plnetinfo to the first item for the next loop */ + plnetinfo -= i; + + for (i = 0; i < num_scans_in_cur_iter; i++) { + iter = (gscan_results_cache_t *) + MALLOCZ(dhd->osh, ((nAPs_per_scan[i] - 1) * + sizeof(wifi_gscan_result_t)) + + sizeof(gscan_results_cache_t)); + if (!iter) { + DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", + __FUNCTION__, gscan_params->mscan)); + err = BCME_NOMEM; + goto exit_mutex_unlock; + } + /* Need this check because the new set of results from FW + * maybe a continuation of previous sets' scan results + */ + if (TIME_DIFF_MS(ts, plnetinfo->timestamp) > timediff) { + iter->scan_id = ++gscan_params->scan_id; + } else { + iter->scan_id = gscan_params->scan_id; + } + DHD_PNO(("scan_id %d tot_count %d \n", + gscan_params->scan_id, nAPs_per_scan[i])); + iter->tot_count = nAPs_per_scan[i]; + iter->tot_consumed = 0; + iter->flag = 0; + if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) { + DHD_PNO(("This scan is aborted\n")); + iter->flag = (ENABLE << PNO_STATUS_ABORT); + } else if (gscan_params->reason) { + iter->flag = (ENABLE << gscan_params->reason); + } + + if (!tail) { + gscan_params->gscan_batch_cache = iter; + } else { + tail->next = iter; + } + tail = iter; + iter->next = NULL; + for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo++) { + result = &iter->results[j]; + + result->channel = + wf_channel2mhz(plnetinfo->pfnsubnet.channel, + (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + result->rssi = (int32) plnetinfo->RSSI; + result->beacon_period = 0; + result->capability = 0; + result->rtt = (uint64) plnetinfo->rtt0; + result->rtt_sd = (uint64) plnetinfo->rtt1; + result->ts = convert_fw_rel_time_to_systime(&tm_spec, + plnetinfo->timestamp); + ts = plnetinfo->timestamp; + if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("%s: Invalid SSID length %d\n", + __FUNCTION__, + plnetinfo->pfnsubnet.SSID_len)); + plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + } + memcpy(result->ssid, plnetinfo->pfnsubnet.SSID, + plnetinfo->pfnsubnet.SSID_len); + result->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0'; + memcpy(&result->macaddr, &plnetinfo->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + + DHD_PNO(("\tSSID : ")); + DHD_PNO(("\n")); + DHD_PNO(("\tBSSID: "MACDBG"\n", + MAC2STRDBG(result->macaddr.octet))); + DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", + plnetinfo->pfnsubnet.channel, + plnetinfo->RSSI, plnetinfo->timestamp)); + DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", + plnetinfo->rtt0, plnetinfo->rtt1)); + + } + } + + } else if (plbestnet_v2->version == PFN_LBEST_SCAN_RESULT_VERSION_V2) { + fwstatus = plbestnet_v2->status; + fwcount = plbestnet_v2->count; + plnetinfo_v2 = (wl_pfn_lnet_info_v2_t*)&plbestnet_v2->netinfo[0]; - for (i = 0; i < num_scans_in_cur_iter; i++) { - iter = (gscan_results_cache_t *) - kmalloc(((nAPs_per_scan[i] - 1) * sizeof(wifi_gscan_result_t)) + - sizeof(gscan_results_cache_t), GFP_KERNEL); - if (!iter) { - DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", - __FUNCTION__, gscan_params->mscan)); - err = BCME_NOMEM; + DHD_PNO(("ver %d, status : %d, count %d\n", + plbestnet_v2->version, fwstatus, fwcount)); + + if (fwcount == 0) { + DHD_PNO(("No more batch results\n")); goto exit_mutex_unlock; } - /* Need this check because the new set of results from FW - * maybe a continuation of previous sets' scan results + if (fwcount > BESTN_MAX) { + DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n", + __FUNCTION__, fwcount, (int)BESTN_MAX)); + /* Process only BESTN_MAX number of results per batch */ + fwcount = BESTN_MAX; + } + num_scans_in_cur_iter = 0; + + timestamp = plnetinfo_v2->timestamp; + /* find out how many scans' results did we get + * in this batch of FW results */ - if (TIME_DIFF_MS(ts, plnetinfo->timestamp) > timediff) { - iter->scan_id = ++gscan_params->scan_id; - } else { - iter->scan_id = gscan_params->scan_id; - } - DHD_PNO(("scan_id %d tot_count %d ch_bucket %x\n", - gscan_params->scan_id, nAPs_per_scan[i], - plbestnet->scan_ch_buckets[i])); - iter->tot_count = nAPs_per_scan[i]; - iter->scan_ch_bucket = plbestnet->scan_ch_buckets[i]; - iter->tot_consumed = 0; - iter->flag = 0; - if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) { - DHD_PNO(("This scan is aborted\n")); - iter->flag = (ENABLE << PNO_STATUS_ABORT); - } else if (gscan_params->reason) { - iter->flag = (ENABLE << gscan_params->reason); - } - - if (!tail) { - gscan_params->gscan_batch_cache = iter; - } else { - tail->next = iter; + for (i = 0, count = 0; i < fwcount; i++, count++, plnetinfo_v2++) { + /* Unlikely to happen, but just in case the results from + * FW doesnt make sense..... Assume its part of one single scan + */ + if (num_scans_in_cur_iter >= gscan_params->mscan) { + num_scans_in_cur_iter = 0; + count = fwcount; + break; + } + if (TIME_DIFF_MS(timestamp, plnetinfo_v2->timestamp) > timediff) { + nAPs_per_scan[num_scans_in_cur_iter] = count; + count = 0; + num_scans_in_cur_iter++; + } + timestamp = plnetinfo_v2->timestamp; + } + if (num_scans_in_cur_iter < gscan_params->mscan) { + nAPs_per_scan[num_scans_in_cur_iter] = count; + num_scans_in_cur_iter++; } - tail = iter; - iter->next = NULL; - for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo++) { - result = &iter->results[j]; - result->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel, - (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); - result->rssi = (int32) plnetinfo->RSSI; - /* Info not available & not expected */ - result->beacon_period = 0; - result->capability = 0; - result->rtt = (uint64) plnetinfo->rtt0; - result->rtt_sd = (uint64) plnetinfo->rtt1; - result->ts = convert_fw_rel_time_to_systime(&tm_spec, - plnetinfo->timestamp); - ts = plnetinfo->timestamp; - if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { - DHD_ERROR(("%s: Invalid SSID length %d\n", - __FUNCTION__, plnetinfo->pfnsubnet.SSID_len)); - plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + DHD_PNO(("num_scans_in_cur_iter %d\n", num_scans_in_cur_iter)); + /* reset plnetinfo to the first item for the next loop */ + plnetinfo_v2 -= i; + + for (i = 0; i < num_scans_in_cur_iter; i++) { + iter = (gscan_results_cache_t *) + MALLOCZ(dhd->osh, ((nAPs_per_scan[i] - 1) * + sizeof(wifi_gscan_result_t)) + + sizeof(gscan_results_cache_t)); + if (!iter) { + DHD_ERROR(("%s :Out of memory!! Cant malloc %d bytes\n", + __FUNCTION__, gscan_params->mscan)); + err = BCME_NOMEM; + goto exit_mutex_unlock; + } + /* Need this check because the new set of results from FW + * maybe a continuation of previous sets' scan results + */ + if (TIME_DIFF_MS(ts, plnetinfo_v2->timestamp) > timediff) { + iter->scan_id = ++gscan_params->scan_id; + } else { + iter->scan_id = gscan_params->scan_id; + } + DHD_PNO(("scan_id %d tot_count %d ch_bucket %x\n", + gscan_params->scan_id, nAPs_per_scan[i], + plbestnet_v2->scan_ch_buckets[i])); + iter->tot_count = nAPs_per_scan[i]; + iter->scan_ch_bucket = plbestnet_v2->scan_ch_buckets[i]; + iter->tot_consumed = 0; + iter->flag = 0; + if (plnetinfo_v2->flags & PFN_PARTIAL_SCAN_MASK) { + DHD_PNO(("This scan is aborted\n")); + iter->flag = (ENABLE << PNO_STATUS_ABORT); + } else if (gscan_params->reason) { + iter->flag = (ENABLE << gscan_params->reason); } - memcpy(result->ssid, plnetinfo->pfnsubnet.u.SSID, - plnetinfo->pfnsubnet.SSID_len); - result->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0'; - memcpy(&result->macaddr, &plnetinfo->pfnsubnet.BSSID, - ETHER_ADDR_LEN); - DHD_PNO(("\tSSID : ")); - DHD_PNO(("\n")); - DHD_PNO(("\tBSSID: "MACDBG"\n", - MAC2STRDBG(result->macaddr.octet))); - DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", - plnetinfo->pfnsubnet.channel, - plnetinfo->RSSI, plnetinfo->timestamp)); - DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", - plnetinfo->rtt0, plnetinfo->rtt1)); + if (!tail) { + gscan_params->gscan_batch_cache = iter; + } else { + tail->next = iter; + } + tail = iter; + iter->next = NULL; + for (j = 0; j < nAPs_per_scan[i]; j++, plnetinfo_v2++) { + result = &iter->results[j]; + + result->channel = + wf_channel2mhz(plnetinfo_v2->pfnsubnet.channel, + (plnetinfo_v2->pfnsubnet.channel <= + CH_MAX_2G_CHANNEL? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + result->rssi = (int32) plnetinfo_v2->RSSI; + /* Info not available & not expected */ + result->beacon_period = 0; + result->capability = 0; + result->rtt = (uint64) plnetinfo_v2->rtt0; + result->rtt_sd = (uint64) plnetinfo_v2->rtt1; + result->ts = convert_fw_rel_time_to_systime(&tm_spec, + plnetinfo_v2->timestamp); + ts = plnetinfo_v2->timestamp; + if (plnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("%s: Invalid SSID length %d\n", + __FUNCTION__, + plnetinfo_v2->pfnsubnet.SSID_len)); + plnetinfo_v2->pfnsubnet.SSID_len = + DOT11_MAX_SSID_LEN; + } + memcpy(result->ssid, plnetinfo_v2->pfnsubnet.u.SSID, + plnetinfo_v2->pfnsubnet.SSID_len); + result->ssid[plnetinfo_v2->pfnsubnet.SSID_len] = '\0'; + memcpy(&result->macaddr, &plnetinfo_v2->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + + DHD_PNO(("\tSSID : ")); + DHD_PNO(("\n")); + DHD_PNO(("\tBSSID: "MACDBG"\n", + MAC2STRDBG(result->macaddr.octet))); + DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", + plnetinfo_v2->pfnsubnet.channel, + plnetinfo_v2->RSSI, plnetinfo_v2->timestamp)); + DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", + plnetinfo_v2->rtt0, plnetinfo_v2->rtt1)); + } } + + } else { + err = BCME_VERSION; + DHD_ERROR(("bestnet fw version %d not supported\n", + plbestnet_v1->version)); + goto exit_mutex_unlock; } - } + } while (fwstatus == PFN_INCOMPLETE); + exit_mutex_unlock: mutex_unlock(&_pno_state->pno_mutex); exit: @@ -2749,8 +2944,8 @@ exit: if (nAPs_per_scan) { MFREE(dhd->osh, nAPs_per_scan, gscan_params->mscan * sizeof(uint8)); } - if (plbestnet) { - MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN); + if (plbestnet_v1) { + MFREE(dhd->osh, plbestnet_v1, PNO_BESTNET_LEN); } DHD_PNO(("Batch retrieval done!\n")); return err; @@ -2768,13 +2963,14 @@ dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, dhd_epno_ssid_cfg_t *epno_cfg; dhd_pno_status_info_t *_pno_state; - if (!dhd || !dhd->pno_state) { DHD_ERROR(("NULL POINTER : %s\n", __FUNCTION__)); return NULL; } + _pno_state = PNO_GET_PNOSTATE(dhd); _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS]; + if (!len) { DHD_ERROR(("%s: len is NULL\n", __FUNCTION__)); return NULL; @@ -2783,7 +2979,7 @@ dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, switch (type) { case DHD_PNO_GET_CAPABILITIES: ptr = (dhd_pno_gscan_capabilities_t *) - kmalloc(sizeof(dhd_pno_gscan_capabilities_t), GFP_KERNEL); + MALLOCZ(dhd->osh, sizeof(dhd_pno_gscan_capabilities_t)); if (!ptr) break; /* Hardcoding these values for now, need to get @@ -2840,7 +3036,7 @@ dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, *len = 0; } else { mem_needed = sizeof(uint32) * nchan; - p = (uint32 *) kmalloc(mem_needed, GFP_KERNEL); + p = (uint32 *)MALLOCZ(dhd->osh, mem_needed); if (!p) { DHD_ERROR(("%s: Unable to malloc %d bytes\n", __FUNCTION__, mem_needed)); @@ -2862,25 +3058,25 @@ dhd_pno_get_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, case DHD_PNO_GET_NEW_EPNO_SSID_ELEM: epno_cfg = &_params->params_gscan.epno_cfg; if (epno_cfg->num_epno_ssid >= - MAX_EPNO_SSID_NUM) { + MAX_EPNO_SSID_NUM) { DHD_ERROR(("Excessive number of ePNO SSIDs programmed %d\n", - epno_cfg->num_epno_ssid)); + epno_cfg->num_epno_ssid)); return NULL; } if (!epno_cfg->num_epno_ssid) { INIT_LIST_HEAD(&epno_cfg->epno_ssid_list); } - ssid_elem = kzalloc(sizeof(dhd_pno_ssid_t), GFP_KERNEL); + ssid_elem = MALLOCZ(dhd->osh, sizeof(dhd_pno_ssid_t)); if (!ssid_elem) { DHD_ERROR(("EPNO ssid: cannot alloc %zd bytes", - sizeof(dhd_pno_ssid_t))); + sizeof(dhd_pno_ssid_t))); return NULL; } epno_cfg->num_epno_ssid++; list_add_tail(&ssid_elem->list, &epno_cfg->epno_ssid_list); ret = ssid_elem; + *len = sizeof(dhd_pno_ssid_t); break; - default: DHD_ERROR(("%s: Unrecognized cmd type - %d\n", __FUNCTION__, type)); break; @@ -2899,15 +3095,31 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) uint32 timestamp = 0; dhd_pno_params_t *_params = NULL; dhd_pno_status_info_t *_pno_state = NULL; - wl_pfn_lscanresults_v2_t *plbestnet = NULL; - wl_pfn_lnet_info_v2_t *plnetinfo; + wl_pfn_lscanresults_v1_t *plbestnet_v1 = NULL; + wl_pfn_lscanresults_v2_t *plbestnet_v2 = NULL; + wl_pfn_lnet_info_v1_t *plnetinfo; + wl_pfn_lnet_info_v2_t *plnetinfo_v2; dhd_pno_bestnet_entry_t *pbestnet_entry; dhd_pno_best_header_t *pbestnetheader = NULL; dhd_pno_scan_results_t *pscan_results = NULL, *siter, *snext; bool allocate_header = FALSE; + uint16 fwstatus = PFN_INCOMPLETE; + uint16 fwcount; + NULL_CHECK(dhd, "dhd is NULL", err); NULL_CHECK(dhd->pno_state, "pno_state is NULL", err); + /* The static asserts below guarantee the v1 and v2 net_info and subnet_info + * structures are compatible in size and SSID offset, allowing v1 to be safely + * used in the code below except for lscanresults fields themselves + * (status, count, offset to netinfo). + */ + STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t)); + STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t)); + STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t)); + STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) == + OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID)); + DHD_PNO(("%s enter\n", __FUNCTION__)); _pno_state = PNO_GET_PNOSTATE(dhd); @@ -2942,7 +3154,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(siter, snext, &_params->params_batch.get_batch.scan_results_list, list) { list_move_tail(&siter->list, @@ -2950,7 +3162,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif _params->params_batch.get_batch.top_node_cnt = 0; _params->params_batch.get_batch.expired_tot_scan_cnt = _params->params_batch.get_batch.tot_scan_cnt; @@ -2982,17 +3194,15 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) list_add(&pscan_results->list, &_params->params_batch.get_batch.scan_results_list); } - plbestnet = (wl_pfn_lscanresults_v2_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN); - if (!(plbestnet)) - { - DHD_ERROR(("(%s) : plbestnet (%p) is NULL\n", __FUNCTION__, (plbestnet))); - goto exit; - } + + plbestnet_v1 = (wl_pfn_lscanresults_v1_t *)MALLOC(dhd->osh, PNO_BESTNET_LEN); + NULL_CHECK(plbestnet_v1, "failed to allocate buffer for bestnet", err); + plbestnet_v2 = (wl_pfn_lscanresults_v2_t*)plbestnet_v1; + DHD_PNO(("%s enter\n", __FUNCTION__)); - memset(plbestnet, 0, PNO_BESTNET_LEN); - while (plbestnet->status != PFN_COMPLETE) { - memset(plbestnet, 0, PNO_BESTNET_LEN); - err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet, PNO_BESTNET_LEN, 0); + do { + err = dhd_iovar(dhd, 0, "pfnlbest", NULL, 0, (char *)plbestnet_v1, PNO_BESTNET_LEN, + FALSE); if (err < 0) { if (err == BCME_EPERM) { DHD_ERROR(("we cannot get the batching data " @@ -3005,102 +3215,229 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) goto exit; } } - DHD_PNO(("ver %d, status : %d, count %d\n", plbestnet->version, - plbestnet->status, plbestnet->count)); - if (plbestnet->version != PFN_SCANRESULT_VERSION) { - err = BCME_VERSION; - DHD_ERROR(("bestnet version(%d) is mismatch with Driver version(%d)\n", - plbestnet->version, PFN_SCANRESULT_VERSION)); - goto exit; - } - plnetinfo = plbestnet->netinfo; - for (i = 0; i < plbestnet->count; i++) { - pbestnet_entry = (dhd_pno_bestnet_entry_t *) - MALLOC(dhd->osh, BESTNET_ENTRY_SIZE); - if (pbestnet_entry == NULL) { - err = BCME_NOMEM; - DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n")); + + if (plbestnet_v1->version == PFN_LBEST_SCAN_RESULT_VERSION_V1) { + fwstatus = plbestnet_v1->status; + fwcount = plbestnet_v1->count; + plnetinfo = &plbestnet_v1->netinfo[0]; + if (fwcount == 0) { + DHD_PNO(("No more batch results\n")); goto exit; } - memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE); - pbestnet_entry->recorded_time = jiffies; /* record the current time */ - /* create header for the first entry */ - allocate_header = (i == 0)? TRUE : FALSE; - /* check whether the new generation is started or not */ - if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp) - > TIME_MIN_DIFF)) - allocate_header = TRUE; - timestamp = plnetinfo->timestamp; - if (allocate_header) { - pbestnetheader = (dhd_pno_best_header_t *) - MALLOC(dhd->osh, BEST_HEADER_SIZE); - if (pbestnetheader == NULL) { + if (fwcount > BESTN_MAX) { + DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n", + __FUNCTION__, fwcount, (int)BESTN_MAX)); + /* Process only BESTN_MAX number of results per batch */ + fwcount = BESTN_MAX; + } + for (i = 0; i < fwcount; i++) { + pbestnet_entry = (dhd_pno_bestnet_entry_t *) + MALLOC(dhd->osh, BESTNET_ENTRY_SIZE); + if (pbestnet_entry == NULL) { + err = BCME_NOMEM; + DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n")); + goto exit; + } + memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE); + /* record the current time */ + pbestnet_entry->recorded_time = jiffies; + /* create header for the first entry */ + allocate_header = (i == 0)? TRUE : FALSE; + /* check whether the new generation is started or not */ + if (timestamp && (TIME_DIFF(timestamp, plnetinfo->timestamp) + > TIME_MIN_DIFF)) + allocate_header = TRUE; + timestamp = plnetinfo->timestamp; + if (allocate_header) { + pbestnetheader = (dhd_pno_best_header_t *) + MALLOC(dhd->osh, BEST_HEADER_SIZE); + if (pbestnetheader == NULL) { + err = BCME_NOMEM; + if (pbestnet_entry) + MFREE(dhd->osh, pbestnet_entry, + BESTNET_ENTRY_SIZE); + DHD_ERROR(("failed to allocate" + " dhd_pno_bestnet_entry\n")); + goto exit; + } + /* increase total cnt of bestnet header */ + pscan_results->cnt_header++; + /* need to record the reason to call dhd_pno_get_for_bach */ + if (reason) + pbestnetheader->reason = (ENABLE << reason); + memset(pbestnetheader, 0, BEST_HEADER_SIZE); + /* initialize the head of linked list */ + INIT_LIST_HEAD(&(pbestnetheader->entry_list)); + /* link the pbestnet heaer into existed list */ + if (pscan_results->bestnetheader == NULL) + /* In case of header */ + pscan_results->bestnetheader = pbestnetheader; + else { + dhd_pno_best_header_t *head = + pscan_results->bestnetheader; + pscan_results->bestnetheader = pbestnetheader; + pbestnetheader->next = head; + } + } + pbestnet_entry->channel = plnetinfo->pfnsubnet.channel; + pbestnet_entry->RSSI = plnetinfo->RSSI; + if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) { + /* if RSSI is positive value, we assume that + * this scan is aborted by other scan + */ + DHD_PNO(("This scan is aborted\n")); + pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT); + } + pbestnet_entry->rtt0 = plnetinfo->rtt0; + pbestnet_entry->rtt1 = plnetinfo->rtt1; + pbestnet_entry->timestamp = plnetinfo->timestamp; + if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("%s: Invalid SSID length" + " %d: trimming it to max\n", + __FUNCTION__, plnetinfo->pfnsubnet.SSID_len)); + plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + } + pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len; + memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.SSID, + pbestnet_entry->SSID_len); + memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + /* add the element into list */ + list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list); + /* increase best entry count */ + pbestnetheader->tot_cnt++; + pbestnetheader->tot_size += BESTNET_ENTRY_SIZE; + DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1)); + DHD_PNO(("\tSSID : ")); + for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++) + DHD_PNO(("%c", plnetinfo->pfnsubnet.SSID[j])); + DHD_PNO(("\n")); + DHD_PNO(("\tBSSID: "MACDBG"\n", + MAC2STRDBG(plnetinfo->pfnsubnet.BSSID.octet))); + DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", + plnetinfo->pfnsubnet.channel, + plnetinfo->RSSI, plnetinfo->timestamp)); + DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, + plnetinfo->rtt1)); + plnetinfo++; + } + } else if (plbestnet_v2->version == PFN_LBEST_SCAN_RESULT_VERSION_V2) { + fwstatus = plbestnet_v2->status; + fwcount = plbestnet_v2->count; + plnetinfo_v2 = (wl_pfn_lnet_info_v2_t*)&plbestnet_v2->netinfo[0]; + if (fwcount == 0) { + DHD_PNO(("No more batch results\n")); + goto exit; + } + if (fwcount > BESTN_MAX) { + DHD_ERROR(("%s :fwcount %d is greater than BESTN_MAX %d \n", + __FUNCTION__, fwcount, (int)BESTN_MAX)); + /* Process only BESTN_MAX number of results per batch */ + fwcount = BESTN_MAX; + } + DHD_PNO(("ver %d, status : %d, count %d\n", + plbestnet_v2->version, fwstatus, fwcount)); + + for (i = 0; i < fwcount; i++) { + pbestnet_entry = (dhd_pno_bestnet_entry_t *) + MALLOC(dhd->osh, BESTNET_ENTRY_SIZE); + if (pbestnet_entry == NULL) { err = BCME_NOMEM; - if (pbestnet_entry) - MFREE(dhd->osh, pbestnet_entry, - BESTNET_ENTRY_SIZE); DHD_ERROR(("failed to allocate dhd_pno_bestnet_entry\n")); goto exit; } - /* increase total cnt of bestnet header */ - pscan_results->cnt_header++; - /* need to record the reason to call dhd_pno_get_for_bach */ - if (reason) - pbestnetheader->reason = (ENABLE << reason); - memset(pbestnetheader, 0, BEST_HEADER_SIZE); - /* initialize the head of linked list */ - INIT_LIST_HEAD(&(pbestnetheader->entry_list)); - /* link the pbestnet heaer into existed list */ - if (pscan_results->bestnetheader == NULL) - /* In case of header */ - pscan_results->bestnetheader = pbestnetheader; - else { - dhd_pno_best_header_t *head = pscan_results->bestnetheader; - pscan_results->bestnetheader = pbestnetheader; - pbestnetheader->next = head; + memset(pbestnet_entry, 0, BESTNET_ENTRY_SIZE); + /* record the current time */ + pbestnet_entry->recorded_time = jiffies; + /* create header for the first entry */ + allocate_header = (i == 0)? TRUE : FALSE; + /* check whether the new generation is started or not */ + if (timestamp && (TIME_DIFF(timestamp, plnetinfo_v2->timestamp) + > TIME_MIN_DIFF)) + allocate_header = TRUE; + timestamp = plnetinfo_v2->timestamp; + if (allocate_header) { + pbestnetheader = (dhd_pno_best_header_t *) + MALLOC(dhd->osh, BEST_HEADER_SIZE); + if (pbestnetheader == NULL) { + err = BCME_NOMEM; + if (pbestnet_entry) + MFREE(dhd->osh, pbestnet_entry, + BESTNET_ENTRY_SIZE); + DHD_ERROR(("failed to allocate" + " dhd_pno_bestnet_entry\n")); + goto exit; + } + /* increase total cnt of bestnet header */ + pscan_results->cnt_header++; + /* need to record the reason to call dhd_pno_get_for_bach */ + if (reason) + pbestnetheader->reason = (ENABLE << reason); + memset(pbestnetheader, 0, BEST_HEADER_SIZE); + /* initialize the head of linked list */ + INIT_LIST_HEAD(&(pbestnetheader->entry_list)); + /* link the pbestnet heaer into existed list */ + if (pscan_results->bestnetheader == NULL) + /* In case of header */ + pscan_results->bestnetheader = pbestnetheader; + else { + dhd_pno_best_header_t *head = + pscan_results->bestnetheader; + pscan_results->bestnetheader = pbestnetheader; + pbestnetheader->next = head; + } + } + /* fills the best network info */ + pbestnet_entry->channel = plnetinfo_v2->pfnsubnet.channel; + pbestnet_entry->RSSI = plnetinfo_v2->RSSI; + if (plnetinfo_v2->flags & PFN_PARTIAL_SCAN_MASK) { + /* if RSSI is positive value, we assume that + * this scan is aborted by other scan + */ + DHD_PNO(("This scan is aborted\n")); + pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT); + } + pbestnet_entry->rtt0 = plnetinfo_v2->rtt0; + pbestnet_entry->rtt1 = plnetinfo_v2->rtt1; + pbestnet_entry->timestamp = plnetinfo_v2->timestamp; + if (plnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("%s: Invalid SSID length" + " %d: trimming it to max\n", + __FUNCTION__, plnetinfo_v2->pfnsubnet.SSID_len)); + plnetinfo_v2->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; } + pbestnet_entry->SSID_len = plnetinfo_v2->pfnsubnet.SSID_len; + memcpy(pbestnet_entry->SSID, plnetinfo_v2->pfnsubnet.u.SSID, + pbestnet_entry->SSID_len); + memcpy(&pbestnet_entry->BSSID, &plnetinfo_v2->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + /* add the element into list */ + list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list); + /* increase best entry count */ + pbestnetheader->tot_cnt++; + pbestnetheader->tot_size += BESTNET_ENTRY_SIZE; + DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1)); + DHD_PNO(("\tSSID : ")); + for (j = 0; j < plnetinfo_v2->pfnsubnet.SSID_len; j++) + DHD_PNO(("%c", plnetinfo_v2->pfnsubnet.u.SSID[j])); + DHD_PNO(("\n")); + DHD_PNO(("\tBSSID: "MACDBG"\n", + MAC2STRDBG(plnetinfo_v2->pfnsubnet.BSSID.octet))); + DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", + plnetinfo_v2->pfnsubnet.channel, + plnetinfo_v2->RSSI, plnetinfo_v2->timestamp)); + DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo_v2->rtt0, + plnetinfo_v2->rtt1)); + plnetinfo_v2++; } - /* fills the best network info */ - pbestnet_entry->channel = plnetinfo->pfnsubnet.channel; - pbestnet_entry->RSSI = plnetinfo->RSSI; - if (plnetinfo->flags & PFN_PARTIAL_SCAN_MASK) { - /* if RSSI is positive value, we assume that - * this scan is aborted by other scan - */ - DHD_PNO(("This scan is aborted\n")); - pbestnetheader->reason = (ENABLE << PNO_STATUS_ABORT); - } - pbestnet_entry->rtt0 = plnetinfo->rtt0; - pbestnet_entry->rtt1 = plnetinfo->rtt1; - pbestnet_entry->timestamp = plnetinfo->timestamp; - if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { - DHD_ERROR(("%s: Invalid SSID length %d: trimming it to max\n", - __FUNCTION__, plnetinfo->pfnsubnet.SSID_len)); - plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; - } - pbestnet_entry->SSID_len = plnetinfo->pfnsubnet.SSID_len; - memcpy(pbestnet_entry->SSID, plnetinfo->pfnsubnet.u.SSID, - pbestnet_entry->SSID_len); - memcpy(&pbestnet_entry->BSSID, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN); - /* add the element into list */ - list_add_tail(&pbestnet_entry->list, &pbestnetheader->entry_list); - /* increase best entry count */ - pbestnetheader->tot_cnt++; - pbestnetheader->tot_size += BESTNET_ENTRY_SIZE; - DHD_PNO(("Header %d\n", pscan_results->cnt_header - 1)); - DHD_PNO(("\tSSID : ")); - for (j = 0; j < plnetinfo->pfnsubnet.SSID_len; j++) - DHD_PNO(("%c", plnetinfo->pfnsubnet.u.SSID[j])); - DHD_PNO(("\n")); - DHD_PNO(("\tBSSID: "MACDBG"\n", - MAC2STRDBG(plnetinfo->pfnsubnet.BSSID.octet))); - DHD_PNO(("\tchannel: %d, RSSI: %d, timestamp: %d ms\n", - plnetinfo->pfnsubnet.channel, - plnetinfo->RSSI, plnetinfo->timestamp)); - DHD_PNO(("\tRTT0 : %d, RTT1: %d\n", plnetinfo->rtt0, plnetinfo->rtt1)); - plnetinfo++; + } else { + err = BCME_VERSION; + DHD_ERROR(("bestnet fw version %d not supported\n", + plbestnet_v1->version)); + goto exit; } - } + } while (fwstatus != PFN_COMPLETE); + if (pscan_results->cnt_header == 0) { /* In case that we didn't get any data from the firmware * Remove the current scan_result list from get_bach.scan_results_list. @@ -3121,7 +3458,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(siter, snext, &_params->params_batch.get_batch.scan_results_list, list) { list_move_tail(&siter->list, @@ -3129,7 +3466,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif /* reset gloval values after moving to expired list */ _params->params_batch.get_batch.top_node_cnt = 0; _params->params_batch.get_batch.expired_tot_scan_cnt = @@ -3144,8 +3481,8 @@ convert_format: } } exit: - if (plbestnet) - MFREE(dhd->osh, plbestnet, PNO_BESTNET_LEN); + if (plbestnet_v1) + MFREE(dhd->osh, plbestnet_v1, PNO_BESTNET_LEN); if (_params) { _params->params_batch.get_batch.buf = NULL; _params->params_batch.get_batch.bufsize = 0; @@ -3167,11 +3504,11 @@ _dhd_pno_get_batch_handler(struct work_struct *work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif _pno_state = container_of(work, struct dhd_pno_status_info, work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif dhd = _pno_state->dhd; if (dhd == NULL) { DHD_ERROR(("%s : dhd is NULL\n", __FUNCTION__)); @@ -3223,7 +3560,7 @@ dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) msecs_to_jiffies(GSCAN_BATCH_GET_MAX_WAIT)); } } else -#endif +#endif // endif { if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { DHD_ERROR(("%s: Batching SCAN mode is not enabled\n", __FUNCTION__)); @@ -3243,7 +3580,7 @@ dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason) #ifdef GSCAN_SUPPORT if (!(_pno_state->pno_mode & DHD_PNO_GSCAN_MODE)) -#endif +#endif // endif err = params_batch->get_batch.bytes_written; exit: return err; @@ -3278,7 +3615,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) DHD_PNO(("Gscan is ongoing, nothing to stop here\n")); return err; } -#endif +#endif // endif if (!(_pno_state->pno_mode & DHD_PNO_BATCH_MODE)) { DHD_ERROR(("%s : PNO BATCH MODE is not enabled\n", __FUNCTION__)); @@ -3301,9 +3638,9 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) _params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); err = dhd_pno_set_legacy_pno(dhd, _params_legacy->scan_fr, - _params_legacy->pno_repeat, - _params_legacy->pno_freq_expo_max, - _params_legacy->chan_list, _params_legacy->nchan); + _params_legacy->pno_repeat, + _params_legacy->pno_freq_expo_max, + _params_legacy->chan_list, _params_legacy->nchan); if (err < 0) { DHD_ERROR(("%s : failed to restart legacy PNO scan(err: %d)\n", __FUNCTION__, err)); @@ -3312,8 +3649,8 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) } else if (_pno_state->pno_mode & DHD_PNO_HOTLIST_MODE) { struct dhd_pno_bssid *iter, *next; _params = &(_pno_state->pno_params_arr[INDEX_OF_HOTLIST_PARAMS]); - p_pfn_bssid = kzalloc(sizeof(wl_pfn_bssid_t) * - _params->params_hotlist.nbssid, GFP_KERNEL); + p_pfn_bssid = (wl_pfn_bssid_t *)MALLOCZ(dhd->osh, + sizeof(wl_pfn_bssid_t) * _params->params_hotlist.nbssid); if (p_pfn_bssid == NULL) { DHD_ERROR(("%s : failed to allocate wl_pfn_bssid_t array" " (count: %d)", @@ -3327,7 +3664,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(iter, next, &_params->params_hotlist.bssid_list, list) { memcpy(&p_pfn_bssid[i].macaddr, &iter->macaddr, ETHER_ADDR_LEN); @@ -3336,7 +3673,7 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif err = dhd_pno_set_for_hotlist(dhd, p_pfn_bssid, &_params->params_hotlist); if (err < 0) { _pno_state->pno_mode &= ~DHD_PNO_HOTLIST_MODE; @@ -3356,7 +3693,8 @@ dhd_pno_stop_for_batch(dhd_pub_t *dhd) exit: _params = &_pno_state->pno_params_arr[INDEX_OF_BATCH_PARAMS]; _dhd_pno_reinitialize_prof(dhd, _params, DHD_PNO_BATCH_MODE); - kfree(p_pfn_bssid); + MFREE(dhd->osh, p_pfn_bssid, + sizeof(wl_pfn_bssid_t) * _params->params_hotlist.nbssid); return err; } @@ -3433,7 +3771,7 @@ dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, } DHD_PNO(("\n")); } -#endif +#endif // endif if (_params->params_hotlist.nchan) { /* copy the channel list into local array */ memcpy(_chan_list, _params->params_hotlist.chan_list, @@ -3491,7 +3829,8 @@ dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, } } for (i = 0; i < hotlist_params->nbssid; i++) { - _pno_bssid = kzalloc(sizeof(struct dhd_pno_bssid), GFP_KERNEL); + _pno_bssid = (struct dhd_pno_bssid *)MALLOCZ(dhd->osh, + sizeof(struct dhd_pno_bssid)); NULL_CHECK(_pno_bssid, "_pfn_bssid is NULL", err); memcpy(&_pno_bssid->macaddr, &p_pfn_bssid[i].macaddr, ETHER_ADDR_LEN); _pno_bssid->flags = p_pfn_bssid[i].flags; @@ -3552,7 +3891,6 @@ dhd_pno_stop_for_hotlist(dhd_pub_t *dhd) struct dhd_pno_legacy_params *_params_legacy; _params_legacy = &(_pno_state->pno_params_arr[INDEX_OF_LEGACY_PARAMS].params_legacy); - err = dhd_pno_set_legacy_pno(dhd, _params_legacy->scan_fr, _params_legacy->pno_repeat, _params_legacy->pno_freq_expo_max, _params_legacy->chan_list, _params_legacy->nchan); @@ -3639,7 +3977,9 @@ dhd_gscan_hotlist_cache_cleanup(dhd_pub_t *dhd, hotlist_type_t type) while (iter) { tmp = iter->next; - kfree(iter); + MFREE(dhd->osh, iter, + ((iter->tot_count - 1) * sizeof(wifi_gscan_result_t)) + + sizeof(gscan_results_cache_t)); iter = tmp; } @@ -3663,11 +4003,11 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, uint32 len, int #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif gscan_result = (wl_gscan_result_t *)data; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (!gscan_result) { DHD_ERROR(("Invalid gscan result (NULL pointer)\n")); goto exit; @@ -3700,13 +4040,15 @@ dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *data, uint32 len, int DHD_ERROR(("%s: Invalid SSID length:%u\n", __FUNCTION__, bi->SSID_len)); goto exit; } - mem_needed = OFFSETOF(wifi_gscan_full_result_t, ie_data) + bi_ie_length; - result = (wifi_gscan_full_result_t *) kmalloc(mem_needed, GFP_KERNEL); + + mem_needed = OFFSETOF(wifi_gscan_full_result_t, ie_data) + bi->ie_length; + result = (wifi_gscan_full_result_t *)MALLOC(dhd->osh, mem_needed); if (!result) { DHD_ERROR(("%s Cannot malloc scan result buffer %d bytes\n", __FUNCTION__, mem_needed)); goto exit; } + result->scan_ch_bucket = gscan_result->scan_ch_bucket; memcpy(result->fixed.ssid, bi->SSID, bi->SSID_len); result->fixed.ssid[bi->SSID_len] = '\0'; @@ -3744,60 +4086,106 @@ dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, uint32 event, int return NULL; gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); - if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) { + if (event == WLC_E_PFN_NET_FOUND || event == WLC_E_PFN_NET_LOST) { #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif - wl_pfn_scanresults_v2_t *pfn_result = (wl_pfn_scanresults_v2_t *)data; - wl_pfn_net_info_v2_t *net; +#endif // endif + wl_pfn_scanresults_v1_t *pfn_result = (wl_pfn_scanresults_v1_t *)data; + wl_pfn_scanresults_v2_t *pfn_result_v2 = (wl_pfn_scanresults_v2_t *)data; + wl_pfn_net_info_v1_t *net; + wl_pfn_net_info_v2_t *net_v2; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif - if (pfn_result->version != PFN_SCANRESULT_VERSION) { - DHD_ERROR(("%s event %d: Incorrect version %d %d\n", __FUNCTION__, event, - pfn_result->version, PFN_SCANRESULT_VERSION)); - return NULL; - } - /* Check if count of pfn results is corrupted */ - if (pfn_result->count > EVENT_MAX_NETCNT_V2) { - DHD_ERROR(("%s event %d: pfn results count %d" - "exceeds the max limit\n", __FUNCTION__, event, - pfn_result->count)); - return NULL; - } - - count = pfn_result->count; - mem_needed = sizeof(dhd_epno_results_t) * count; - results = (dhd_epno_results_t *) kmalloc(mem_needed, GFP_KERNEL); - if (!results) { - DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__, - mem_needed)); - return NULL; - } - for (i = 0; i < count; i++) { - net = &pfn_result->netinfo[i]; - results[i].rssi = net->RSSI; - results[i].channel = wf_channel2mhz(net->pfnsubnet.channel, - (net->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); - results[i].flags = (event == WLC_E_PFN_NET_FOUND) ? - WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST; - results[i].ssid_len = min(net->pfnsubnet.SSID_len, - (uint8)DOT11_MAX_SSID_LEN); - bssid = &results[i].bssid; - memcpy(bssid, &net->pfnsubnet.BSSID, ETHER_ADDR_LEN); - if (!net->pfnsubnet.SSID_len) { - dhd_pno_idx_to_ssid(gscan_params, &results[i], - net->pfnsubnet.u.index); - } else { - memcpy(results[i].ssid, net->pfnsubnet.u.SSID, results[i].ssid_len); +#endif // endif + if (pfn_result->version == PFN_SCANRESULT_VERSION_V1) { + /* Check if count of pfn results is corrupted */ + if (pfn_result->count > EVENT_MAX_NETCNT_V1) { + DHD_ERROR(("%s event %d: pfn results count %d" + "exceeds the max limit\n", + __FUNCTION__, event, pfn_result->count)); + return NULL; + } + count = pfn_result->count; + mem_needed = sizeof(dhd_epno_results_t) * count; + results = (dhd_epno_results_t *)MALLOC(dhd->osh, mem_needed); + if (!results) { + DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__, + mem_needed)); + return NULL; } - memcpy(ssid, results[i].ssid, results[i].ssid_len); - ssid[results[i].ssid_len] = '\0'; - DHD_PNO(("ssid - %s bssid "MACDBG" ch %d rssi %d flags %d\n", - ssid, MAC2STRDBG(bssid->octet), results[i].channel, - results[i].rssi, results[i].flags)); + for (i = 0; i < count; i++) { + net = &pfn_result->netinfo[i]; + results[i].rssi = net->RSSI; + results[i].channel = wf_channel2mhz(net->pfnsubnet.channel, + (net->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + results[i].flags = (event == WLC_E_PFN_NET_FOUND) ? + WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST; + results[i].ssid_len = min(net->pfnsubnet.SSID_len, + (uint8)DOT11_MAX_SSID_LEN); + bssid = &results[i].bssid; + memcpy(bssid, &net->pfnsubnet.BSSID, ETHER_ADDR_LEN); + if (!net->pfnsubnet.SSID_len) { + DHD_ERROR(("%s: Gscan results indexing is not" + " supported in version 1 \n", __FUNCTION__)); + MFREE(dhd->osh, results, mem_needed); + return NULL; + } else { + memcpy(results[i].ssid, net->pfnsubnet.SSID, + results[i].ssid_len); + } + memcpy(ssid, results[i].ssid, results[i].ssid_len); + ssid[results[i].ssid_len] = '\0'; + DHD_PNO(("ssid - %s bssid "MACDBG" ch %d rssi %d flags %d\n", + ssid, MAC2STRDBG(bssid->octet), results[i].channel, + results[i].rssi, results[i].flags)); + } + } else if (pfn_result_v2->version == PFN_SCANRESULT_VERSION_V2) { + /* Check if count of pfn results is corrupted */ + if (pfn_result_v2->count > EVENT_MAX_NETCNT_V2) { + DHD_ERROR(("%s event %d: pfn results count %d" + "exceeds the max limit\n", + __FUNCTION__, event, pfn_result_v2->count)); + return NULL; + } + count = pfn_result_v2->count; + mem_needed = sizeof(dhd_epno_results_t) * count; + results = (dhd_epno_results_t *)MALLOC(dhd->osh, mem_needed); + if (!results) { + DHD_ERROR(("%s: Can't malloc %d bytes for results\n", __FUNCTION__, + mem_needed)); + return NULL; + } + for (i = 0; i < count; i++) { + net_v2 = &pfn_result_v2->netinfo[i]; + results[i].rssi = net_v2->RSSI; + results[i].channel = wf_channel2mhz(net_v2->pfnsubnet.channel, + (net_v2->pfnsubnet.channel <= CH_MAX_2G_CHANNEL ? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + results[i].flags = (event == WLC_E_PFN_NET_FOUND) ? + WL_PFN_SSID_EXT_FOUND: WL_PFN_SSID_EXT_LOST; + results[i].ssid_len = min(net_v2->pfnsubnet.SSID_len, + (uint8)DOT11_MAX_SSID_LEN); + bssid = &results[i].bssid; + memcpy(bssid, &net_v2->pfnsubnet.BSSID, ETHER_ADDR_LEN); + if (!net_v2->pfnsubnet.SSID_len) { + dhd_pno_idx_to_ssid(gscan_params, &results[i], + net_v2->pfnsubnet.u.index); + } else { + memcpy(results[i].ssid, net_v2->pfnsubnet.u.SSID, + results[i].ssid_len); + } + memcpy(ssid, results[i].ssid, results[i].ssid_len); + ssid[results[i].ssid_len] = '\0'; + DHD_PNO(("ssid - %s bssid "MACDBG" ch %d rssi %d flags %d\n", + ssid, MAC2STRDBG(bssid->octet), results[i].channel, + results[i].rssi, results[i].flags)); + } + } else { + DHD_ERROR(("%s event %d: Incorrect version %d , not supported\n", + __FUNCTION__, event, pfn_result->version)); + return NULL; } } *size = mem_needed; @@ -3806,7 +4194,7 @@ dhd_pno_process_epno_result(dhd_pub_t *dhd, const void *data, uint32 event, int void * dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, - int *send_evt_bytes, hotlist_type_t type) + int *send_evt_bytes, hotlist_type_t type, u32 *buf_len) { void *ptr = NULL; dhd_pno_status_info_t *_pno_state = PNO_GET_PNOSTATE(dhd); @@ -3814,79 +4202,165 @@ dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif - wl_pfn_scanresults_v2_t *results = (wl_pfn_scanresults_v2_t *)event_data; +#endif // endif + wl_pfn_scanresults_v1_t *results_v1 = (wl_pfn_scanresults_v1_t *)event_data; + wl_pfn_scanresults_v2_t *results_v2 = (wl_pfn_scanresults_v2_t *)event_data; #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif wifi_gscan_result_t *hotlist_found_array; - wl_pfn_net_info_v2_t *plnetinfo; + wl_pfn_net_info_v1_t *pnetinfo; + wl_pfn_net_info_v2_t *pnetinfo_v2; gscan_results_cache_t *gscan_hotlist_cache; - int malloc_size = 0, i, total = 0; + uint32 malloc_size = 0, i, total = 0; struct timespec tm_spec; + uint16 fwstatus; + uint16 fwcount; - gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); + /* Static asserts in _dhd_pno_get_for_batch() above guarantee the v1 and v2 + * net_info and subnet_info structures are compatible in size and SSID offset, + * allowing v1 to be safely used in the code below except for lscanresults + * fields themselves (status, count, offset to netinfo). + */ - if ((results->count == 0) || (results->count > EVENT_MAX_NETCNT_V2)) { - DHD_ERROR(("%s: wrong result count:%d\n", __FUNCTION__, results->count)); - *send_evt_bytes = 0; - return ptr; - } + *buf_len = 0; + if (results_v1->version == PFN_SCANRESULTS_VERSION_V1) { + fwstatus = results_v1->status; + fwcount = results_v1->count; + pnetinfo = &results_v1->netinfo[0]; - get_monotonic_boottime(&tm_spec); - malloc_size = sizeof(gscan_results_cache_t) + - ((results->count - 1) * sizeof(wifi_gscan_result_t)); - gscan_hotlist_cache = (gscan_results_cache_t *) kmalloc(malloc_size, GFP_KERNEL); + gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); - if (!gscan_hotlist_cache) { - DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size)); - *send_evt_bytes = 0; - return ptr; - } + if (!fwcount || (fwcount > EVENT_MAX_NETCNT_V1)) { + DHD_ERROR(("%s: wrong v1 fwcount:%d\n", __FUNCTION__, fwcount)); + *send_evt_bytes = 0; + return ptr; + } - if (type == HOTLIST_FOUND) { - gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found; - gscan_params->gscan_hotlist_found = gscan_hotlist_cache; - DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, results->count)); - } else { - gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost; - gscan_params->gscan_hotlist_lost = gscan_hotlist_cache; - DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, results->count)); - } + get_monotonic_boottime(&tm_spec); + malloc_size = sizeof(gscan_results_cache_t) + + ((fwcount - 1) * sizeof(wifi_gscan_result_t)); + gscan_hotlist_cache = (gscan_results_cache_t *)MALLOC(dhd->osh, malloc_size); + if (!gscan_hotlist_cache) { + DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size)); + *send_evt_bytes = 0; + return ptr; + } + + *buf_len = malloc_size; + if (type == HOTLIST_FOUND) { + gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found; + gscan_params->gscan_hotlist_found = gscan_hotlist_cache; + DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, fwcount)); + } else { + gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost; + gscan_params->gscan_hotlist_lost = gscan_hotlist_cache; + DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, fwcount)); + } + + gscan_hotlist_cache->tot_count = fwcount; + gscan_hotlist_cache->tot_consumed = 0; - gscan_hotlist_cache->tot_count = results->count; - gscan_hotlist_cache->tot_consumed = 0; - gscan_hotlist_cache->scan_ch_bucket = results->scan_ch_bucket; - plnetinfo = results->netinfo; + for (i = 0; i < fwcount; i++, pnetinfo++) { + hotlist_found_array = &gscan_hotlist_cache->results[i]; + memset(hotlist_found_array, 0, sizeof(wifi_gscan_result_t)); + hotlist_found_array->channel = wf_channel2mhz(pnetinfo->pfnsubnet.channel, + (pnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + hotlist_found_array->rssi = (int32) pnetinfo->RSSI; + + hotlist_found_array->ts = + convert_fw_rel_time_to_systime(&tm_spec, + (pnetinfo->timestamp * 1000)); + if (pnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", + pnetinfo->pfnsubnet.SSID_len)); + pnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + } + memcpy(hotlist_found_array->ssid, pnetinfo->pfnsubnet.SSID, + pnetinfo->pfnsubnet.SSID_len); + hotlist_found_array->ssid[pnetinfo->pfnsubnet.SSID_len] = '\0'; + + memcpy(&hotlist_found_array->macaddr, &pnetinfo->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + DHD_PNO(("\t%s "MACDBG" rssi %d\n", + hotlist_found_array->ssid, + MAC2STRDBG(hotlist_found_array->macaddr.octet), + hotlist_found_array->rssi)); + } + } else if (results_v2->version == PFN_SCANRESULTS_VERSION_V2) { + fwstatus = results_v2->status; + fwcount = results_v2->count; + pnetinfo_v2 = (wl_pfn_net_info_v2_t*)&results_v2->netinfo[0]; - for (i = 0; i < results->count; i++, plnetinfo++) { - hotlist_found_array = &gscan_hotlist_cache->results[i]; - memset(hotlist_found_array, 0, sizeof(wifi_gscan_result_t)); - hotlist_found_array->channel = wf_channel2mhz(plnetinfo->pfnsubnet.channel, - (plnetinfo->pfnsubnet.channel <= CH_MAX_2G_CHANNEL? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); - hotlist_found_array->rssi = (int32) plnetinfo->RSSI; + gscan_params = &(_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS].params_gscan); - hotlist_found_array->ts = - convert_fw_rel_time_to_systime(&tm_spec, (plnetinfo->timestamp * 1000)); - if (plnetinfo->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { - DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", - plnetinfo->pfnsubnet.SSID_len)); - plnetinfo->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + if (!fwcount || (fwcount > EVENT_MAX_NETCNT_V2)) { + DHD_ERROR(("%s: wrong v2 fwcount:%d\n", __FUNCTION__, fwcount)); + *send_evt_bytes = 0; + return ptr; } - memcpy(hotlist_found_array->ssid, plnetinfo->pfnsubnet.u.SSID, - plnetinfo->pfnsubnet.SSID_len); - hotlist_found_array->ssid[plnetinfo->pfnsubnet.SSID_len] = '\0'; - memcpy(&hotlist_found_array->macaddr, &plnetinfo->pfnsubnet.BSSID, ETHER_ADDR_LEN); - DHD_PNO(("\t%s "MACDBG" rssi %d\n", - hotlist_found_array->ssid, - MAC2STRDBG(hotlist_found_array->macaddr.octet), - hotlist_found_array->rssi)); - } + get_monotonic_boottime(&tm_spec); + malloc_size = sizeof(gscan_results_cache_t) + + ((fwcount - 1) * sizeof(wifi_gscan_result_t)); + gscan_hotlist_cache = + (gscan_results_cache_t *)MALLOC(dhd->osh, malloc_size); + if (!gscan_hotlist_cache) { + DHD_ERROR(("%s Cannot Malloc %d bytes!!\n", __FUNCTION__, malloc_size)); + *send_evt_bytes = 0; + return ptr; + } + *buf_len = malloc_size; + if (type == HOTLIST_FOUND) { + gscan_hotlist_cache->next = gscan_params->gscan_hotlist_found; + gscan_params->gscan_hotlist_found = gscan_hotlist_cache; + DHD_PNO(("%s enter, FOUND results count %d\n", __FUNCTION__, fwcount)); + } else { + gscan_hotlist_cache->next = gscan_params->gscan_hotlist_lost; + gscan_params->gscan_hotlist_lost = gscan_hotlist_cache; + DHD_PNO(("%s enter, LOST results count %d\n", __FUNCTION__, fwcount)); + } + gscan_hotlist_cache->tot_count = fwcount; + gscan_hotlist_cache->tot_consumed = 0; + gscan_hotlist_cache->scan_ch_bucket = results_v2->scan_ch_bucket; - if (results->status == PFN_COMPLETE) { + for (i = 0; i < fwcount; i++, pnetinfo_v2++) { + hotlist_found_array = &gscan_hotlist_cache->results[i]; + memset(hotlist_found_array, 0, sizeof(wifi_gscan_result_t)); + hotlist_found_array->channel = + wf_channel2mhz(pnetinfo_v2->pfnsubnet.channel, + (pnetinfo_v2->pfnsubnet.channel <= CH_MAX_2G_CHANNEL? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G)); + hotlist_found_array->rssi = (int32) pnetinfo_v2->RSSI; + + hotlist_found_array->ts = + convert_fw_rel_time_to_systime(&tm_spec, + (pnetinfo_v2->timestamp * 1000)); + if (pnetinfo_v2->pfnsubnet.SSID_len > DOT11_MAX_SSID_LEN) { + DHD_ERROR(("Invalid SSID length %d: trimming it to max\n", + pnetinfo_v2->pfnsubnet.SSID_len)); + pnetinfo_v2->pfnsubnet.SSID_len = DOT11_MAX_SSID_LEN; + } + memcpy(hotlist_found_array->ssid, pnetinfo_v2->pfnsubnet.u.SSID, + pnetinfo_v2->pfnsubnet.SSID_len); + hotlist_found_array->ssid[pnetinfo_v2->pfnsubnet.SSID_len] = '\0'; + + memcpy(&hotlist_found_array->macaddr, &pnetinfo_v2->pfnsubnet.BSSID, + ETHER_ADDR_LEN); + DHD_PNO(("\t%s "MACDBG" rssi %d\n", + hotlist_found_array->ssid, + MAC2STRDBG(hotlist_found_array->macaddr.octet), + hotlist_found_array->rssi)); + } + } else { + DHD_ERROR(("%s: event version %d not supported\n", + __FUNCTION__, results_v1->version)); + *send_evt_bytes = 0; + return ptr; + } + if (fwstatus == PFN_COMPLETE) { ptr = (void *) gscan_hotlist_cache; while (gscan_hotlist_cache) { total += gscan_hotlist_cache->tot_count; @@ -3898,6 +4372,7 @@ dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, return ptr; } #endif /* GSCAN_SUPPORT */ + int dhd_pno_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) { @@ -3968,7 +4443,7 @@ int dhd_pno_init(dhd_pub_t *dhd) #ifdef GSCAN_SUPPORT init_waitqueue_head(&_pno_state->batch_get_wait); #endif /* GSCAN_SUPPORT */ - buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + buf = MALLOC(dhd->osh, WLC_IOCTL_SMLEN); if (!buf) { DHD_ERROR((":%s buf alloc err.\n", __FUNCTION__)); return BCME_NOMEM; @@ -3984,7 +4459,7 @@ int dhd_pno_init(dhd_pub_t *dhd) __FUNCTION__)); } exit: - kfree(buf); + MFREE(dhd->osh, buf, WLC_IOCTL_SMLEN); return err; } int dhd_pno_deinit(dhd_pub_t *dhd) @@ -4007,7 +4482,7 @@ int dhd_pno_deinit(dhd_pub_t *dhd) if (_pno_state->pno_mode & DHD_PNO_GSCAN_MODE) { _params = &_pno_state->pno_params_arr[INDEX_OF_GSCAN_PARAMS]; mutex_lock(&_pno_state->pno_mutex); - dhd_pno_reset_cfg_gscan(_params, _pno_state, GSCAN_FLUSH_ALL_CFG); + dhd_pno_reset_cfg_gscan(dhd, _params, _pno_state, GSCAN_FLUSH_ALL_CFG); mutex_unlock(&_pno_state->pno_mutex); } #endif /* GSCAN_SUPPORT */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_pno.h b/drivers/net/wireless/bcmdhd_oo/dhd_pno.h index 7b56c5512bb394191a38877e00fa9e53cf51f5ad..66c41b673520200721c92c8ae1b268d9d2dfbe45 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_pno.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_pno.h @@ -2,14 +2,14 @@ * Header file of Broadcom Dongle Host Driver (DHD) * Prefered Network Offload code and Wi-Fi Location Service(WLS) code. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dhd_pno.h 707287 2017-06-27 06:44:29Z $ + * $Id: dhd_pno.h 722186 2017-09-19 07:03:42Z $ */ #ifndef __DHD_PNO_H__ @@ -322,7 +322,6 @@ typedef struct dhd_pno_gscan_channel_bucket { uint16 chan_list[GSCAN_MAX_CHANNELS_IN_BUCKET]; } dhd_pno_gscan_channel_bucket_t; - #define DHD_PNO_AUTH_CODE_OPEN 1 /* Open */ #define DHD_PNO_AUTH_CODE_PSK 2 /* WPA_PSK or WPA2PSK */ #define DHD_PNO_AUTH_CODE_EAPOL 4 /* any EAPOL */ @@ -350,15 +349,15 @@ typedef struct dhd_epno_results { } dhd_epno_results_t; typedef struct wifi_gscan_result { - uint64 ts; /* Time of discovery */ - char ssid[DOT11_MAX_SSID_LEN+1]; /* null terminated */ - struct ether_addr macaddr; /* BSSID */ - uint32 channel; /* channel frequency in MHz */ - int32 rssi; /* in db */ - uint64 rtt; /* in nanoseconds */ - uint64 rtt_sd; /* standard deviation in rtt */ - uint16 beacon_period; /* units are Kusec */ - uint16 capability; /* Capability information */ + uint64 ts; /* Time of discovery */ + char ssid[DOT11_MAX_SSID_LEN+1]; /* null terminated */ + struct ether_addr macaddr; /* BSSID */ + uint32 channel; /* channel frequency in MHz */ + int32 rssi; /* in db */ + uint64 rtt; /* in nanoseconds */ + uint64 rtt_sd; /* standard deviation in rtt */ + uint16 beacon_period; /* units are Kusec */ + uint16 capability; /* Capability information */ uint32 pad; } wifi_gscan_result_t; @@ -393,7 +392,7 @@ typedef struct dhd_pno_gscan_capabilities { } dhd_pno_gscan_capabilities_t; typedef struct dhd_epno_ssid_cfg { - wl_pfn_ssid_params_t params; + wl_ssid_ext_params_t params; uint32 num_epno_ssid; struct list_head epno_ssid_list; } dhd_epno_ssid_cfg_t; @@ -411,7 +410,7 @@ struct dhd_pno_gscan_params { uint16 max_ch_bucket_freq; gscan_results_cache_t *gscan_batch_cache; gscan_results_cache_t *gscan_hotlist_found; - gscan_results_cache_t *gscan_hotlist_lost; + gscan_results_cache_t*gscan_hotlist_lost; uint16 nbssid_hotlist; struct dhd_pno_gscan_channel_bucket channel_bucket[GSCAN_MAX_CH_BUCKETS]; struct list_head hotlist_bssid_list; @@ -443,6 +442,7 @@ typedef struct gscan_hotlist_scan_params { } gscan_hotlist_scan_params_t; #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */ + typedef union dhd_pno_params { struct dhd_pno_legacy_params params_legacy; struct dhd_pno_batch_params params_batch; @@ -451,6 +451,7 @@ typedef union dhd_pno_params { struct dhd_pno_gscan_params params_gscan; #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */ } dhd_pno_params_t; + typedef struct dhd_pno_status_info { dhd_pub_t *dhd; struct work_struct work; @@ -506,7 +507,7 @@ extern int dhd_dev_pno_run_gscan(struct net_device *dev, bool run, bool flush); extern int dhd_dev_pno_enable_full_scan_result(struct net_device *dev, bool real_time); int dhd_retreive_batch_scan_results(dhd_pub_t *dhd); extern void * dhd_dev_hotlist_scan_event(struct net_device *dev, - const void *data, int *send_evt_bytes, hotlist_type_t type); + const void *data, int *send_evt_bytes, hotlist_type_t type, u32 *buf_len); void * dhd_dev_process_full_gscan_result(struct net_device *dev, const void *data, uint32 len, int *send_evt_bytes); extern int dhd_dev_gscan_batch_cache_cleanup(struct net_device *dev); @@ -527,7 +528,6 @@ extern int dhd_pno_set_for_batch(dhd_pub_t *dhd, struct dhd_pno_batch_params *ba extern int dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason); - extern int dhd_pno_stop_for_batch(dhd_pub_t *dhd); extern int dhd_pno_set_for_hotlist(dhd_pub_t *dhd, wl_pfn_bssid_t *p_pfn_bssid, @@ -554,7 +554,7 @@ extern int dhd_pno_enable_full_scan_result(dhd_pub_t *dhd, bool real_time_flag); extern int dhd_pno_cfg_gscan(dhd_pub_t *dhd, dhd_pno_gscan_cmd_cfg_t type, void *buf); extern int dhd_dev_retrieve_batch_scan(struct net_device *dev); extern void *dhd_handle_hotlist_scan_evt(dhd_pub_t *dhd, const void *event_data, - int *send_evt_bytes, hotlist_type_t type); + int *send_evt_bytes, hotlist_type_t type, u32 *buf_len); extern void *dhd_process_full_gscan_result(dhd_pub_t *dhd, const void *event_data, uint32 len, int *send_evt_bytes); extern int dhd_gscan_batch_cache_cleanup(dhd_pub_t *dhd); @@ -567,6 +567,6 @@ extern int dhd_pno_set_epno(dhd_pub_t *dhd); extern int dhd_pno_flush_fw_epno(dhd_pub_t *dhd); extern void dhd_pno_set_epno_auth_flag(uint32 *wpa_auth); #endif /* GSCAN_SUPPORT */ -#endif +#endif // endif #endif /* __DHD_PNO_H__ */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_proto.h b/drivers/net/wireless/bcmdhd_oo/dhd_proto.h index 3e66bcb5b0da43df2291e14f4445a0b200595af1..c929f4101ce5b4f1f9a361f1c1a82e9832f93150 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_proto.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_proto.h @@ -4,14 +4,14 @@ * Provides type definitions and function prototypes used to link the * DHD OS, bus, and protocol modules. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: dhd_proto.h 727682 2017-10-23 04:45:57Z $ + * $Id: dhd_proto.h 724495 2017-10-02 20:36:38Z $ */ #ifndef _dhd_proto_h_ @@ -37,9 +37,9 @@ #include #ifdef BCMPCIE #include -#endif +#endif // endif -#define DEFAULT_IOCTL_RESP_TIMEOUT 4000 +#define DEFAULT_IOCTL_RESP_TIMEOUT 5000 #ifndef IOCTL_RESP_TIMEOUT /* In milli second default value for Production FW */ #define IOCTL_RESP_TIMEOUT DEFAULT_IOCTL_RESP_TIMEOUT @@ -49,7 +49,7 @@ #define MFG_IOCTL_RESP_TIMEOUT 20000 /* In milli second default value for MFG FW */ #endif /* MFG_IOCTL_RESP_TIMEOUT */ -#define DEFAULT_D3_ACK_RESP_TIMEOUT 1000 +#define DEFAULT_D3_ACK_RESP_TIMEOUT 2000 #ifndef D3_ACK_RESP_TIMEOUT #define D3_ACK_RESP_TIMEOUT DEFAULT_D3_ACK_RESP_TIMEOUT #endif /* D3_ACK_RESP_TIMEOUT */ @@ -156,7 +156,7 @@ extern void dhd_prot_print_flow_ring(dhd_pub_t *dhd, void *msgbuf_flow_info, struct bcmstrbuf *strbuf, const char * fmt); extern void dhd_prot_print_info(dhd_pub_t *dhd, struct bcmstrbuf *strbuf); extern void dhd_prot_update_txflowring(dhd_pub_t *dhdp, uint16 flow_id, void *msgring_info); -extern void dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flow_id, bool in_lock); +extern void dhd_prot_txdata_write_flush(dhd_pub_t *dhd, uint16 flow_id); extern uint32 dhd_prot_txp_threshold(dhd_pub_t *dhd, bool set, uint32 val); extern void dhd_prot_reset(dhd_pub_t *dhd); @@ -180,6 +180,9 @@ extern int dhd_prot_send_host_timestamp(dhd_pub_t *dhdp, uchar *tlv, uint16 tlv_ uint16 seq, uint16 xt_id); extern bool dhd_prot_data_path_tx_timestamp_logging(dhd_pub_t *dhd, bool enable, bool set); extern bool dhd_prot_data_path_rx_timestamp_logging(dhd_pub_t *dhd, bool enable, bool set); +extern bool dhd_prot_pkt_noretry(dhd_pub_t *dhd, bool enable, bool set); +extern bool dhd_prot_pkt_noaggr(dhd_pub_t *dhd, bool enable, bool set); +extern bool dhd_prot_pkt_fixed_rate(dhd_pub_t *dhd, bool enable, bool set); #else /* BCMPCIE */ #define dhd_prot_send_host_timestamp(a, b, c, d, e) 0 #define dhd_prot_data_path_tx_timestamp_logging(a, b, c) 0 diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_rtt.c b/drivers/net/wireless/bcmdhd_oo/dhd_rtt.c index c58ca93fc435e07d146b66ee069c8aa4ac7ce793..b179ec26edae7ad34ace49f9d951905c8048b803 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_rtt.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_rtt.c @@ -1,14 +1,14 @@ /* * Broadcom Dongle Host Driver (DHD), RTT * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -98,7 +98,6 @@ struct rtt_noti_callback { dhd_rtt_compl_noti_fn noti_fn; }; - /* bitmask indicating which command groups; */ typedef enum { FTM_SUBCMD_FLAG_METHOD = 0x01, /* FTM method command */ @@ -113,7 +112,6 @@ typedef enum { FTM_CONFIG_CAT_AVAIL = 3, /* 'config avail' */ } ftm_config_category_t; - typedef struct ftm_subcmd_info { int16 version; /* FTM version (optional) */ char *name; /* cmd-name string as cmdline input */ @@ -122,7 +120,6 @@ typedef struct ftm_subcmd_info { ftm_subcmd_flag_t cmdflag; /* CMD flag (optional) */ } ftm_subcmd_info_t; - typedef struct ftm_config_options_info { uint32 flags; /* wl_proxd_flags_t/wl_proxd_session_flags_t */ bool enable; @@ -150,14 +147,21 @@ typedef struct ftm_strmap_entry { char *text; } ftm_strmap_entry_t; - typedef struct ftm_status_map_host_entry { wl_proxd_status_t proxd_status; rtt_reason_t rtt_reason; } ftm_status_map_host_entry_t; +static uint16 +rtt_result_ver(uint16 tlvid, const uint8 *p_data); + +static int +dhd_rtt_convert_results_to_host_v1(rtt_report_t *rtt_report, const uint8 *p_data, + uint16 tlvid, uint16 len); + static int -dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 tlvid, uint16 len); +dhd_rtt_convert_results_to_host_v2(rtt_report_t *rtt_report, const uint8 *p_data, + uint16 tlvid, uint16 len); static wifi_rate_t dhd_rtt_convert_rate_to_host(uint32 ratespec); @@ -197,103 +201,105 @@ static const ftm_status_map_host_entry_t ftm_status_map_info[] = { /* ftm tlv-id mapping */ static const ftm_strmap_entry_t ftm_tlvid_loginfo[] = { - /* { WL_PROXD_TLV_ID_xxx, "text for WL_PROXD_TLV_ID_xxx" }, */ - { WL_PROXD_TLV_ID_NONE, "none" }, - { WL_PROXD_TLV_ID_METHOD, "method" }, - { WL_PROXD_TLV_ID_FLAGS, "flags" }, - { WL_PROXD_TLV_ID_CHANSPEC, "chanspec" }, - { WL_PROXD_TLV_ID_TX_POWER, "tx power" }, - { WL_PROXD_TLV_ID_RATESPEC, "ratespec" }, - { WL_PROXD_TLV_ID_BURST_DURATION, "burst duration" }, - { WL_PROXD_TLV_ID_BURST_PERIOD, "burst period" }, - { WL_PROXD_TLV_ID_BURST_FTM_SEP, "burst ftm sep" }, - { WL_PROXD_TLV_ID_BURST_NUM_FTM, "burst num ftm" }, - { WL_PROXD_TLV_ID_NUM_BURST, "num burst" }, - { WL_PROXD_TLV_ID_FTM_RETRIES, "ftm retries" }, - { WL_PROXD_TLV_ID_BSS_INDEX, "BSS index" }, - { WL_PROXD_TLV_ID_BSSID, "bssid" }, - { WL_PROXD_TLV_ID_INIT_DELAY, "burst init delay" }, - { WL_PROXD_TLV_ID_BURST_TIMEOUT, "burst timeout" }, - { WL_PROXD_TLV_ID_EVENT_MASK, "event mask" }, - { WL_PROXD_TLV_ID_FLAGS_MASK, "flags mask" }, - { WL_PROXD_TLV_ID_PEER_MAC, "peer addr" }, - { WL_PROXD_TLV_ID_FTM_REQ, "ftm req" }, - { WL_PROXD_TLV_ID_LCI_REQ, "lci req" }, - { WL_PROXD_TLV_ID_LCI, "lci" }, - { WL_PROXD_TLV_ID_CIVIC_REQ, "civic req" }, - { WL_PROXD_TLV_ID_CIVIC, "civic" }, - { WL_PROXD_TLV_ID_AVAIL, "availability" }, - { WL_PROXD_TLV_ID_SESSION_FLAGS, "session flags" }, - { WL_PROXD_TLV_ID_SESSION_FLAGS_MASK, "session flags mask" }, - { WL_PROXD_TLV_ID_RX_MAX_BURST, "rx max bursts" }, - { WL_PROXD_TLV_ID_RANGING_INFO, "ranging info" }, - { WL_PROXD_TLV_ID_RANGING_FLAGS, "ranging flags" }, - { WL_PROXD_TLV_ID_RANGING_FLAGS_MASK, "ranging flags mask" }, + /* { WL_PROXD_TLV_ID_xxx, "text for WL_PROXD_TLV_ID_xxx" }, */ + { WL_PROXD_TLV_ID_NONE, "none" }, + { WL_PROXD_TLV_ID_METHOD, "method" }, + { WL_PROXD_TLV_ID_FLAGS, "flags" }, + { WL_PROXD_TLV_ID_CHANSPEC, "chanspec" }, + { WL_PROXD_TLV_ID_TX_POWER, "tx power" }, + { WL_PROXD_TLV_ID_RATESPEC, "ratespec" }, + { WL_PROXD_TLV_ID_BURST_DURATION, "burst duration" }, + { WL_PROXD_TLV_ID_BURST_PERIOD, "burst period" }, + { WL_PROXD_TLV_ID_BURST_FTM_SEP, "burst ftm sep" }, + { WL_PROXD_TLV_ID_BURST_NUM_FTM, "burst num ftm" }, + { WL_PROXD_TLV_ID_NUM_BURST, "num burst" }, + { WL_PROXD_TLV_ID_FTM_RETRIES, "ftm retries" }, + { WL_PROXD_TLV_ID_BSS_INDEX, "BSS index" }, + { WL_PROXD_TLV_ID_BSSID, "bssid" }, + { WL_PROXD_TLV_ID_INIT_DELAY, "burst init delay" }, + { WL_PROXD_TLV_ID_BURST_TIMEOUT, "burst timeout" }, + { WL_PROXD_TLV_ID_EVENT_MASK, "event mask" }, + { WL_PROXD_TLV_ID_FLAGS_MASK, "flags mask" }, + { WL_PROXD_TLV_ID_PEER_MAC, "peer addr" }, + { WL_PROXD_TLV_ID_FTM_REQ, "ftm req" }, + { WL_PROXD_TLV_ID_LCI_REQ, "lci req" }, + { WL_PROXD_TLV_ID_LCI, "lci" }, + { WL_PROXD_TLV_ID_CIVIC_REQ, "civic req" }, + { WL_PROXD_TLV_ID_CIVIC, "civic" }, + { WL_PROXD_TLV_ID_AVAIL, "availability" }, + { WL_PROXD_TLV_ID_SESSION_FLAGS, "session flags" }, + { WL_PROXD_TLV_ID_SESSION_FLAGS_MASK, "session flags mask" }, + { WL_PROXD_TLV_ID_RX_MAX_BURST, "rx max bursts" }, + { WL_PROXD_TLV_ID_RANGING_INFO, "ranging info" }, + { WL_PROXD_TLV_ID_RANGING_FLAGS, "ranging flags" }, + { WL_PROXD_TLV_ID_RANGING_FLAGS_MASK, "ranging flags mask" }, /* output - 512 + x */ - { WL_PROXD_TLV_ID_STATUS, "status" }, - { WL_PROXD_TLV_ID_COUNTERS, "counters" }, - { WL_PROXD_TLV_ID_INFO, "info" }, - { WL_PROXD_TLV_ID_RTT_RESULT, "rtt result" }, - { WL_PROXD_TLV_ID_AOA_RESULT, "aoa result" }, - { WL_PROXD_TLV_ID_SESSION_INFO, "session info" }, - { WL_PROXD_TLV_ID_SESSION_STATUS, "session status" }, - { WL_PROXD_TLV_ID_SESSION_ID_LIST, "session ids" }, + { WL_PROXD_TLV_ID_STATUS, "status" }, + { WL_PROXD_TLV_ID_COUNTERS, "counters" }, + { WL_PROXD_TLV_ID_INFO, "info" }, + { WL_PROXD_TLV_ID_RTT_RESULT, "rtt result" }, + { WL_PROXD_TLV_ID_AOA_RESULT, "aoa result" }, + { WL_PROXD_TLV_ID_SESSION_INFO, "session info" }, + { WL_PROXD_TLV_ID_SESSION_STATUS, "session status" }, + { WL_PROXD_TLV_ID_SESSION_ID_LIST, "session ids" }, /* debug tlvs can be added starting 1024 */ - { WL_PROXD_TLV_ID_DEBUG_MASK, "debug mask" }, - { WL_PROXD_TLV_ID_COLLECT, "collect" }, - { WL_PROXD_TLV_ID_STRBUF, "result" }, - { WL_PROXD_TLV_ID_COLLECT_DATA, "collect-data" }, - { WL_PROXD_TLV_ID_RI_RR, "ri_rr" }, - { WL_PROXD_TLV_ID_COLLECT_CHAN_DATA, "chan est"} + { WL_PROXD_TLV_ID_DEBUG_MASK, "debug mask" }, + { WL_PROXD_TLV_ID_COLLECT, "collect" }, + { WL_PROXD_TLV_ID_STRBUF, "result" }, + { WL_PROXD_TLV_ID_COLLECT_DATA, "collect-data" }, + { WL_PROXD_TLV_ID_RI_RR, "ri_rr" }, + { WL_PROXD_TLV_ID_COLLECT_CHAN_DATA, "chan est"}, + { WL_PROXD_TLV_ID_MF_STATS_DATA, "mf_stats_data"} }; static const ftm_strmap_entry_t ftm_event_type_loginfo[] = { - /* wl_proxd_event_type_t, text-string */ - { WL_PROXD_EVENT_NONE, "none" }, - { WL_PROXD_EVENT_SESSION_CREATE, "session create" }, - { WL_PROXD_EVENT_SESSION_START, "session start" }, - { WL_PROXD_EVENT_FTM_REQ, "FTM req" }, - { WL_PROXD_EVENT_BURST_START, "burst start" }, - { WL_PROXD_EVENT_BURST_END, "burst end" }, - { WL_PROXD_EVENT_SESSION_END, "session end" }, - { WL_PROXD_EVENT_SESSION_RESTART, "session restart" }, - { WL_PROXD_EVENT_BURST_RESCHED, "burst rescheduled" }, - { WL_PROXD_EVENT_SESSION_DESTROY, "session destroy" }, - { WL_PROXD_EVENT_RANGE_REQ, "range request" }, - { WL_PROXD_EVENT_FTM_FRAME, "FTM frame" }, - { WL_PROXD_EVENT_DELAY, "delay" }, - { WL_PROXD_EVENT_VS_INITIATOR_RPT, "initiator-report " }, /* rx */ - { WL_PROXD_EVENT_RANGING, "ranging " }, - { WL_PROXD_EVENT_COLLECT, "collect" }, + /* wl_proxd_event_type_t, text-string */ + { WL_PROXD_EVENT_NONE, "none" }, + { WL_PROXD_EVENT_SESSION_CREATE, "session create" }, + { WL_PROXD_EVENT_SESSION_START, "session start" }, + { WL_PROXD_EVENT_FTM_REQ, "FTM req" }, + { WL_PROXD_EVENT_BURST_START, "burst start" }, + { WL_PROXD_EVENT_BURST_END, "burst end" }, + { WL_PROXD_EVENT_SESSION_END, "session end" }, + { WL_PROXD_EVENT_SESSION_RESTART, "session restart" }, + { WL_PROXD_EVENT_BURST_RESCHED, "burst rescheduled" }, + { WL_PROXD_EVENT_SESSION_DESTROY, "session destroy" }, + { WL_PROXD_EVENT_RANGE_REQ, "range request" }, + { WL_PROXD_EVENT_FTM_FRAME, "FTM frame" }, + { WL_PROXD_EVENT_DELAY, "delay" }, + { WL_PROXD_EVENT_VS_INITIATOR_RPT, "initiator-report " }, /* rx initiator-rpt */ + { WL_PROXD_EVENT_RANGING, "ranging " }, + { WL_PROXD_EVENT_COLLECT, "collect" }, + { WL_PROXD_EVENT_MF_STATS, "mf_stats" }, }; /* * session-state --> text string mapping */ static const ftm_strmap_entry_t ftm_session_state_value_loginfo[] = { - /* wl_proxd_session_state_t, text string */ - { WL_PROXD_SESSION_STATE_CREATED, "created" }, - { WL_PROXD_SESSION_STATE_CONFIGURED, "configured" }, - { WL_PROXD_SESSION_STATE_STARTED, "started" }, - { WL_PROXD_SESSION_STATE_DELAY, "delay" }, - { WL_PROXD_SESSION_STATE_USER_WAIT, "user-wait" }, - { WL_PROXD_SESSION_STATE_SCHED_WAIT, "sched-wait" }, - { WL_PROXD_SESSION_STATE_BURST, "burst" }, - { WL_PROXD_SESSION_STATE_STOPPING, "stopping" }, - { WL_PROXD_SESSION_STATE_ENDED, "ended" }, - { WL_PROXD_SESSION_STATE_DESTROYING, "destroying" }, - { WL_PROXD_SESSION_STATE_NONE, "none" } + /* wl_proxd_session_state_t, text string */ + { WL_PROXD_SESSION_STATE_CREATED, "created" }, + { WL_PROXD_SESSION_STATE_CONFIGURED, "configured" }, + { WL_PROXD_SESSION_STATE_STARTED, "started" }, + { WL_PROXD_SESSION_STATE_DELAY, "delay" }, + { WL_PROXD_SESSION_STATE_USER_WAIT, "user-wait" }, + { WL_PROXD_SESSION_STATE_SCHED_WAIT, "sched-wait" }, + { WL_PROXD_SESSION_STATE_BURST, "burst" }, + { WL_PROXD_SESSION_STATE_STOPPING, "stopping" }, + { WL_PROXD_SESSION_STATE_ENDED, "ended" }, + { WL_PROXD_SESSION_STATE_DESTROYING, "destroying" }, + { WL_PROXD_SESSION_STATE_NONE, "none" } }; /* * ranging-state --> text string mapping */ static const ftm_strmap_entry_t ftm_ranging_state_value_loginfo [] = { - /* wl_proxd_ranging_state_t, text string */ - { WL_PROXD_RANGING_STATE_NONE, "none" }, - { WL_PROXD_RANGING_STATE_NOTSTARTED, "nonstarted" }, - { WL_PROXD_RANGING_STATE_INPROGRESS, "inprogress" }, - { WL_PROXD_RANGING_STATE_DONE, "done" }, + /* wl_proxd_ranging_state_t, text string */ + { WL_PROXD_RANGING_STATE_NONE, "none" }, + { WL_PROXD_RANGING_STATE_NOTSTARTED, "nonstarted" }, + { WL_PROXD_RANGING_STATE_INPROGRESS, "inprogress" }, + { WL_PROXD_RANGING_STATE_DONE, "done" }, }; /* @@ -329,13 +335,13 @@ static const ftm_strmap_entry_t ftm_status_value_loginfo[] = { * time interval unit --> text string mapping */ static const ftm_strmap_entry_t ftm_tmu_value_loginfo[] = { - /* wl_proxd_tmu_t, text-string */ - { WL_PROXD_TMU_TU, "TU" }, - { WL_PROXD_TMU_SEC, "sec" }, - { WL_PROXD_TMU_MILLI_SEC, "ms" }, - { WL_PROXD_TMU_MICRO_SEC, "us" }, - { WL_PROXD_TMU_NANO_SEC, "ns" }, - { WL_PROXD_TMU_PICO_SEC, "ps" } + /* wl_proxd_tmu_t, text-string */ + { WL_PROXD_TMU_TU, "TU" }, + { WL_PROXD_TMU_SEC, "sec" }, + { WL_PROXD_TMU_MILLI_SEC, "ms" }, + { WL_PROXD_TMU_MICRO_SEC, "us" }, + { WL_PROXD_TMU_NANO_SEC, "ns" }, + { WL_PROXD_TMU_PICO_SEC, "ps" } }; #define RSPEC_BW(rspec) ((rspec) & WL_RSPEC_BW_MASK) @@ -443,10 +449,10 @@ rate_mcs2rate(uint mcs, uint nss, uint bw, int sgi) } /* wlc_rate_mcs2rate */ /** take a well formed ratespec_t arg and return phy rate in [Kbps] units */ -int +static uint32 rate_rspec2rate(uint32 rspec) { - int rate = -1; + int rate = 0; if (RSPEC_ISLEGACY(rspec)) { rate = 500 * (rspec & WL_RSPEC_RATE_MASK); @@ -463,16 +469,17 @@ rate_rspec2rate(uint32 rspec) } else if (RSPEC_ISVHT(rspec)) { uint mcs = (rspec & WL_RSPEC_VHT_MCS_MASK); uint nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT; - - ASSERT(mcs <= 9); - ASSERT(nss <= 8); + if (mcs > 9 || nss > 8) { + DHD_RTT(("%s: Invalid mcs %d or nss %d\n", __FUNCTION__, mcs, nss)); + goto exit; + } rate = rate_mcs2rate(mcs, nss, RSPEC_BW(rspec), RSPEC_ISSGI(rspec)); } else { - ASSERT(0); + DHD_RTT(("%s: wrong rspec:%d\n", __FUNCTION__, rspec)); } - - return (rate == 0) ? -1 : rate; +exit: + return rate; } char resp_buf[WLC_IOCTL_SMLEN]; @@ -572,7 +579,6 @@ ftm_map_id_to_str(int32 id, const ftm_strmap_entry_t *p_table, uint32 num_entrie return "invalid"; } - #ifdef RTT_DEBUG /* define entry, e.g. { WL_PROXD_CMD_xxx, "WL_PROXD_CMD_xxx" } */ @@ -614,7 +620,6 @@ ftm_cmdid_to_str(uint16 cmdid) } #endif /* RTT_DEBUG */ - /* * convert BCME_xxx error codes into related error strings * note, bcmerrorstr() defined in bcmutils is for BCMDRIVER only, @@ -668,7 +673,6 @@ ftm_session_state_value_to_logstr(wl_proxd_session_state_t state) ARRAYSIZE(ftm_session_state_value_loginfo)); } - #ifdef WL_CFG80211 /* * send 'proxd' iovar for all ftm get-related commands @@ -711,7 +715,6 @@ exit: return status; } - static wl_proxd_iov_t * rtt_alloc_getset_buf(wl_proxd_method_t method, wl_proxd_session_id_t session_id, wl_proxd_cmd_t cmdid, uint16 tlvs_bufsize, uint16 *p_out_bufsize) @@ -749,7 +752,6 @@ rtt_alloc_getset_buf(wl_proxd_method_t method, wl_proxd_session_id_t session_id, return p_proxd_iov; } - static int dhd_rtt_common_get_handler(dhd_pub_t *dhd, ftm_subcmd_info_t *p_subcmd_info, wl_proxd_method_t method, @@ -762,7 +764,7 @@ dhd_rtt_common_get_handler(dhd_pub_t *dhd, ftm_subcmd_info_t *p_subcmd_info, DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n", __FUNCTION__, method, session_id, p_subcmd_info->cmdid, ftm_cmdid_to_str(p_subcmd_info->cmdid))); -#endif +#endif // endif /* alloc mem for ioctl headr + reserved 0 bufsize for tlvs (initialize to zero) */ p_proxd_iov = rtt_alloc_getset_buf(method, session_id, p_subcmd_info->cmdid, 0, &proxd_iovsize); @@ -807,7 +809,7 @@ dhd_rtt_common_set_handler(dhd_pub_t *dhd, const ftm_subcmd_info_t *p_subcmd_inf DHD_RTT(("enter %s: method=%d, session_id=%d, cmdid=%d(%s)\n", __FUNCTION__, method, session_id, p_subcmd_info->cmdid, ftm_cmdid_to_str(p_subcmd_info->cmdid))); -#endif +#endif // endif /* allocate and initialize a temp buffer for 'set proxd' iovar */ proxd_iovsize = 0; @@ -822,7 +824,7 @@ dhd_rtt_common_set_handler(dhd_pub_t *dhd, const ftm_subcmd_info_t *p_subcmd_inf if (ret != BCME_OK) { DHD_RTT(("error: IOVAR failed, status=%d\n", ret)); } -#endif +#endif // endif /* clean up */ kfree(p_proxd_iov); @@ -830,19 +832,218 @@ dhd_rtt_common_set_handler(dhd_pub_t *dhd, const ftm_subcmd_info_t *p_subcmd_inf } #endif /* WL_CFG80211 */ +#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-qual" +#endif // endif + +/* gets the length and returns the version + * of the wl_proxd_collect_event_t version + */ +static uint +rtt_collect_data_event_ver(uint16 len) +{ + if (len > sizeof(wl_proxd_collect_event_data_v3_t)) { + return WL_PROXD_COLLECT_EVENT_DATA_VERSION_MAX; + } else if (len == sizeof(wl_proxd_collect_event_data_v3_t)) { + return WL_PROXD_COLLECT_EVENT_DATA_VERSION_3; + } else if (len == sizeof(wl_proxd_collect_event_data_v2_t)) { + return WL_PROXD_COLLECT_EVENT_DATA_VERSION_2; + } else { + return WL_PROXD_COLLECT_EVENT_DATA_VERSION_1; + } +} + +static void +rtt_collect_event_data_display(uint8 ver, void *ctx, const uint8 *p_data, uint16 len) +{ + int i; + wl_proxd_collect_event_data_v1_t *p_collect_data_v1 = NULL; + wl_proxd_collect_event_data_v2_t *p_collect_data_v2 = NULL; + wl_proxd_collect_event_data_v3_t *p_collect_data_v3 = NULL; + + if (!ctx || !p_data) { + return; + } + + switch (ver) { + case WL_PROXD_COLLECT_EVENT_DATA_VERSION_1: + DHD_RTT(("\tVERSION_1\n")); + memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v1_t)); + p_collect_data_v1 = (wl_proxd_collect_event_data_v1_t *)ctx; + DHD_RTT(("\tH_RX\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v1->H_RX[i] = ltoh32_ua(&p_collect_data_v1->H_RX[i]); + DHD_RTT(("\t%u\n", p_collect_data_v1->H_RX[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tH_LB\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v1->H_LB[i] = ltoh32_ua(&p_collect_data_v1->H_LB[i]); + DHD_RTT(("\t%u\n", p_collect_data_v1->H_LB[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tri_rr\n")); + for (i = 0; i < FTM_TPK_RI_RR_LEN; i++) { + DHD_RTT(("\t%u\n", p_collect_data_v1->ri_rr[i])); + } + p_collect_data_v1->phy_err_mask = ltoh32_ua(&p_collect_data_v1->phy_err_mask); + DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v1->phy_err_mask)); + break; + case WL_PROXD_COLLECT_EVENT_DATA_VERSION_2: + memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v2_t)); + p_collect_data_v2 = (wl_proxd_collect_event_data_v2_t *)ctx; + DHD_RTT(("\tH_RX\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v2->H_RX[i] = ltoh32_ua(&p_collect_data_v2->H_RX[i]); + DHD_RTT(("\t%u\n", p_collect_data_v2->H_RX[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tH_LB\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v2->H_LB[i] = ltoh32_ua(&p_collect_data_v2->H_LB[i]); + DHD_RTT(("\t%u\n", p_collect_data_v2->H_LB[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tri_rr\n")); + for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) { + DHD_RTT(("\t%u\n", p_collect_data_v2->ri_rr[i])); + } + p_collect_data_v2->phy_err_mask = ltoh32_ua(&p_collect_data_v2->phy_err_mask); + DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v2->phy_err_mask)); + break; + case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3: + memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_v3_t)); + p_collect_data_v3 = (wl_proxd_collect_event_data_v3_t *)ctx; + switch (p_collect_data_v3->version) { + case WL_PROXD_COLLECT_EVENT_DATA_VERSION_3: + if (p_collect_data_v3->length != + (len - OFFSETOF(wl_proxd_collect_event_data_v3_t, H_LB))) { + DHD_RTT(("\tversion/length mismatch\n")); + break; + } + DHD_RTT(("\tH_RX\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v3->H_RX[i] = + ltoh32_ua(&p_collect_data_v3->H_RX[i]); + DHD_RTT(("\t%u\n", p_collect_data_v3->H_RX[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tH_LB\n")); + for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { + p_collect_data_v3->H_LB[i] = + ltoh32_ua(&p_collect_data_v3->H_LB[i]); + DHD_RTT(("\t%u\n", p_collect_data_v3->H_LB[i])); + } + DHD_RTT(("\n")); + DHD_RTT(("\tri_rr\n")); + for (i = 0; i < FTM_TPK_RI_RR_LEN_SECURE_2_0; i++) { + DHD_RTT(("\t%u\n", p_collect_data_v3->ri_rr[i])); + } + p_collect_data_v3->phy_err_mask = + ltoh32_ua(&p_collect_data_v3->phy_err_mask); + DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data_v3->phy_err_mask)); + break; + /* future case */ + } + break; + } +} + +static uint16 +rtt_result_ver(uint16 tlvid, const uint8 *p_data) +{ + uint16 ret = BCME_OK; + const wl_proxd_rtt_result_v2_t *r_v2 = NULL; + + switch (tlvid) { + case WL_PROXD_TLV_ID_RTT_RESULT: + BCM_REFERENCE(p_data); + ret = WL_PROXD_RTT_RESULT_VERSION_1; + break; + case WL_PROXD_TLV_ID_RTT_RESULT_V2: + if (p_data) { + r_v2 = (const wl_proxd_rtt_result_v2_t *)p_data; + if (r_v2->version == WL_PROXD_RTT_RESULT_VERSION_2) { + ret = WL_PROXD_RTT_RESULT_VERSION_2; + } + } + break; + default: + DHD_ERROR(("%s: > Unsupported TLV ID %d\n", + __FUNCTION__, tlvid)); + break; + } + return ret; +} + +/* pretty hex print a contiguous buffer */ +static void +rtt_prhex(const char *msg, const uint8 *buf, uint nbytes) +{ + char line[128], *p; + int len = sizeof(line); + int nchar; + uint i; + + if (msg && (msg[0] != '\0')) + DHD_RTT(("%s:\n", msg)); + + p = line; + for (i = 0; i < nbytes; i++) { + if (i % 16 == 0) { + nchar = snprintf(p, len, " %04d: ", i); /* line prefix */ + p += nchar; + len -= nchar; + } + if (len > 0) { + nchar = snprintf(p, len, "%02x ", buf[i]); + p += nchar; + len -= nchar; + } + + if (i % 16 == 15) { + DHD_RTT(("%s\n", line)); /* flush line */ + p = line; + len = sizeof(line); + } + } + + /* flush last partial line */ + if (p != line) + DHD_RTT(("%s\n", line)); +} + static int -rtt_unpack_xtlv_cbfn(void *ctx, uint8 *p_data, uint16 tlvid, uint16 len) +rtt_unpack_xtlv_cbfn(void *ctx, const uint8 *p_data, uint16 tlvid, uint16 len) { int ret = BCME_OK; int i; wl_proxd_ftm_session_status_t *p_data_info = NULL; - wl_proxd_collect_event_data_t *p_collect_data = NULL; uint32 chan_data_entry = 0; + uint16 expected_rtt_result_ver = 0; + + BCM_REFERENCE(p_data_info); switch (tlvid) { case WL_PROXD_TLV_ID_RTT_RESULT: - ret = dhd_rtt_convert_results_to_host((rtt_report_t *)ctx, - p_data, tlvid, len); + case WL_PROXD_TLV_ID_RTT_RESULT_V2: + DHD_RTT(("WL_PROXD_TLV_ID_RTT_RESULT\n")); + expected_rtt_result_ver = rtt_result_ver(tlvid, p_data); + switch (expected_rtt_result_ver) { + case WL_PROXD_RTT_RESULT_VERSION_1: + ret = dhd_rtt_convert_results_to_host_v1((rtt_report_t *)ctx, + p_data, tlvid, len); + break; + case WL_PROXD_RTT_RESULT_VERSION_2: + ret = dhd_rtt_convert_results_to_host_v2((rtt_report_t *)ctx, + p_data, tlvid, len); + break; + default: + DHD_ERROR((" > Unsupported RTT_RESULT version\n")); + ret = BCME_UNSUPPORTED; + break; + } break; case WL_PROXD_TLV_ID_SESSION_STATUS: DHD_RTT(("WL_PROXD_TLV_ID_SESSION_STATUS\n")); @@ -859,26 +1060,9 @@ rtt_unpack_xtlv_cbfn(void *ctx, uint8 *p_data, uint16 tlvid, uint16 len) break; case WL_PROXD_TLV_ID_COLLECT_DATA: DHD_RTT(("WL_PROXD_TLV_ID_COLLECT_DATA\n")); - memcpy(ctx, p_data, sizeof(wl_proxd_collect_event_data_t)); - p_collect_data = (wl_proxd_collect_event_data_t *)ctx; - DHD_RTT(("\tH_RX\n")); - for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { - p_collect_data->H_RX[i] = ltoh32_ua(&p_collect_data->H_RX[i]); - DHD_RTT(("\t%u\n", p_collect_data->H_RX[i])); - } - DHD_RTT(("\n")); - DHD_RTT(("\tH_LB\n")); - for (i = 0; i < K_TOF_COLLECT_H_SIZE_20MHZ; i++) { - p_collect_data->H_LB[i] = ltoh32_ua(&p_collect_data->H_LB[i]); - DHD_RTT(("\t%u\n", p_collect_data->H_LB[i])); - } - DHD_RTT(("\n")); - DHD_RTT(("\tri_rr\n")); - for (i = 0; i < FTM_TPK_RI_RR_LEN; i++) { - DHD_RTT(("\t%u\n", p_collect_data->ri_rr[i])); - } - p_collect_data->phy_err_mask = ltoh32_ua(&p_collect_data->phy_err_mask); - DHD_RTT(("\tphy_err_mask=0x%x\n", p_collect_data->phy_err_mask)); + rtt_collect_event_data_display( + rtt_collect_data_event_ver(len), + ctx, p_data, len); break; case WL_PROXD_TLV_ID_COLLECT_CHAN_DATA: DHD_RTT(("WL_PROXD_TLV_ID_COLLECT_CHAN_DATA\n")); @@ -889,6 +1073,11 @@ rtt_unpack_xtlv_cbfn(void *ctx, uint8 *p_data, uint16 tlvid, uint16 len) DHD_RTT(("\t%u\n", chan_data_entry)); } break; + case WL_PROXD_TLV_ID_MF_STATS_DATA: + DHD_RTT(("WL_PROXD_TLV_ID_MF_STATS_DATA\n")); + DHD_RTT(("\tmf stats len=%u\n", len)); + rtt_prhex("", p_data, len); + break; default: DHD_ERROR(("> Unsupported TLV ID %d\n", tlvid)); ret = BCME_ERROR; @@ -928,7 +1117,7 @@ rtt_handle_config_options(wl_proxd_session_id_t session_id, wl_proxd_tlv_t **p_t flags_mask = htol32(flags_mask); /* setup flags_mask TLV */ ret = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left, - type, sizeof(uint32), &flags_mask, BCM_XTLV_OPTION_ALIGN32); + type, sizeof(uint32), (uint8 *)&flags_mask, BCM_XTLV_OPTION_ALIGN32); if (ret != BCME_OK) { DHD_ERROR(("%s : bcm_pack_xltv_entry() for mask flags failed, status=%d\n", __FUNCTION__, ret)); @@ -939,12 +1128,12 @@ rtt_handle_config_options(wl_proxd_session_id_t session_id, wl_proxd_tlv_t **p_t WL_PROXD_TLV_ID_FLAGS : WL_PROXD_TLV_ID_SESSION_FLAGS; /* setup flags TLV */ ret = bcm_pack_xtlv_entry((uint8 **)p_tlv, p_buf_space_left, - type, sizeof(uint32), &flags, BCM_XTLV_OPTION_ALIGN32); + type, sizeof(uint32), (uint8 *)&flags, BCM_XTLV_OPTION_ALIGN32); if (ret != BCME_OK) { #ifdef RTT_DEBUG DHD_RTT(("%s: bcm_pack_xltv_entry() for flags failed, status=%d\n", __FUNCTION__, ret)); -#endif +#endif // endif } exit: return ret; @@ -1012,7 +1201,7 @@ rtt_handle_config_general(wl_proxd_session_id_t session_id, wl_proxd_tlv_t **p_t } ret = bcm_pack_xtlv_entry((uint8 **) p_tlv, p_buf_space_left, - p_config_param_info->tlvid, src_data_size, p_src_data, + p_config_param_info->tlvid, src_data_size, (uint8 *)p_src_data, BCM_XTLV_OPTION_ALIGN32); if (ret != BCME_OK) { DHD_ERROR(("%s: bcm_pack_xltv_entry() failed," @@ -1253,7 +1442,7 @@ dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry_safe(entry, next, &rtt_status->rtt_results_cache, list) { list_del(&entry->list); @@ -1267,19 +1456,19 @@ dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif } /* send the rtt complete event to wake up the user process */ #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry(iter, &rtt_status->noti_fn_list, list) { iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache); } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif /* reinitialize the HEAD */ INIT_LIST_HEAD(&rtt_status->rtt_results_cache); /* clear information for rtt_config */ @@ -1295,7 +1484,6 @@ dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt) return err; } - #ifdef WL_CFG80211 static int dhd_rtt_start(dhd_pub_t *dhd) @@ -1303,6 +1491,7 @@ dhd_rtt_start(dhd_pub_t *dhd) int err = BCME_OK; char eabuf[ETHER_ADDR_STR_LEN]; char chanbuf[CHANSPEC_STR_LEN]; + int pm = PM_OFF; int ftm_cfg_cnt = 0; int ftm_param_cnt = 0; uint32 rspec = 0; @@ -1310,7 +1499,6 @@ dhd_rtt_start(dhd_pub_t *dhd) ftm_config_param_info_t ftm_params[FTM_MAX_PARAMS]; rtt_target_info_t *rtt_target; rtt_status_info_t *rtt_status; - int pm = PM_OFF; struct net_device *dev = dhd_linux_get_primary_netdev(dhd); NULL_CHECK(dhd, "dhd is NULL", err); @@ -1331,6 +1519,7 @@ dhd_rtt_start(dhd_pub_t *dhd) DHD_RTT(("RTT is stopped\n")); goto exit; } + rtt_status->pm = PM_OFF; err = wldev_ioctl_get(dev, WLC_GET_PM, &rtt_status->pm, sizeof(rtt_status->pm)); if (err) { DHD_ERROR(("Failed to get the PM value\n")); @@ -1494,9 +1683,9 @@ exit: /* disable FTM */ dhd_rtt_ftm_enable(dhd, FALSE); if (rtt_status->pm_restore) { + pm = PM_FAST; DHD_ERROR(("pm_restore =%d func =%s \n", rtt_status->pm_restore, __FUNCTION__)); - pm = PM_FAST; err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm)); if (err) { DHD_ERROR(("Failed to set PM \n")); @@ -1524,7 +1713,7 @@ dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry(iter, &rtt_status->noti_fn_list, list) { if (iter->noti_fn == noti_fn) { goto exit; @@ -1532,7 +1721,7 @@ dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif cb = kmalloc(sizeof(struct rtt_noti_callback), GFP_ATOMIC); if (!cb) { err = -ENOMEM; @@ -1560,7 +1749,7 @@ dhd_rtt_unregister_noti_callback(dhd_pub_t *dhd, dhd_rtt_compl_noti_fn noti_fn) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry(iter, &rtt_status->noti_fn_list, list) { if (iter->noti_fn == noti_fn) { cb = iter; @@ -1570,7 +1759,7 @@ dhd_rtt_unregister_noti_callback(dhd_pub_t *dhd, dhd_rtt_compl_noti_fn noti_fn) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif spin_unlock_bh(¬i_list_lock); if (cb) { @@ -1583,30 +1772,51 @@ static wifi_rate_t dhd_rtt_convert_rate_to_host(uint32 rspec) { wifi_rate_t host_rate; + uint32 bandwidth; memset(&host_rate, 0, sizeof(wifi_rate_t)); - if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_RATE) { + if (RSPEC_ISLEGACY(rspec)) { host_rate.preamble = 0; - } else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_HT) { + } else if (RSPEC_ISHT(rspec)) { host_rate.preamble = 2; host_rate.rateMcsIdx = rspec & WL_RSPEC_RATE_MASK; - } else if ((rspec & WL_RSPEC_ENCODING_MASK) == WL_RSPEC_ENCODE_VHT) { + } else if (RSPEC_ISVHT(rspec)) { host_rate.preamble = 3; host_rate.rateMcsIdx = rspec & WL_RSPEC_VHT_MCS_MASK; host_rate.nss = (rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT; } - host_rate.bw = (rspec & WL_RSPEC_BW_MASK) - 1; + + bandwidth = RSPEC_BW(rspec); + switch (bandwidth) { + case WL_RSPEC_BW_20MHZ: + host_rate.bw = RTT_RATE_20M; + break; + case WL_RSPEC_BW_40MHZ: + host_rate.bw = RTT_RATE_40M; + break; + case WL_RSPEC_BW_80MHZ: + host_rate.bw = RTT_RATE_80M; + break; + case WL_RSPEC_BW_160MHZ: + host_rate.bw = RTT_RATE_160M; + break; + default: + host_rate.bw = RTT_RATE_20M; + break; + } + host_rate.bitrate = rate_rspec2rate(rspec) / 100; /* 100kbps */ DHD_RTT(("bit rate : %d\n", host_rate.bitrate)); return host_rate; } - +#define FTM_FRAME_TYPES {"SETUP", "TRIGGER", "TIMESTAMP"} static int -dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 tlvid, uint16 len) +dhd_rtt_convert_results_to_host_v1(rtt_report_t *rtt_report, const uint8 *p_data, + uint16 tlvid, uint16 len) { + int i; int err = BCME_OK; char eabuf[ETHER_ADDR_STR_LEN]; - wl_proxd_rtt_result_t *p_data_info; wl_proxd_result_flags_t flags; wl_proxd_session_state_t session_state; wl_proxd_status_t proxd_status; @@ -1615,14 +1825,35 @@ dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 #endif /* LINUX_VER >= 2.6.39 */ uint32 ratespec; uint32 avg_dist; - wl_proxd_rtt_sample_t *p_sample; + const wl_proxd_rtt_result_v1_t *p_data_info = NULL; + const wl_proxd_rtt_sample_v1_t *p_sample_avg = NULL; + const wl_proxd_rtt_sample_v1_t *p_sample = NULL; wl_proxd_intvl_t rtt; wl_proxd_intvl_t p_time; + uint16 num_rtt = 0, snr = 0, bitflips = 0; + wl_proxd_phy_error_t tof_phy_error = 0; + wl_proxd_phy_error_t tof_phy_tgt_error = 0; + wl_proxd_snr_t tof_target_snr = 0; + wl_proxd_bitflips_t tof_target_bitflips = 0; + int16 rssi = 0; + int32 dist = 0; + uint8 num_ftm = 0; + char *ftm_frame_types[] = FTM_FRAME_TYPES; + + BCM_REFERENCE(ftm_frame_types); + BCM_REFERENCE(dist); + BCM_REFERENCE(rssi); + BCM_REFERENCE(tof_target_bitflips); + BCM_REFERENCE(tof_target_snr); + BCM_REFERENCE(tof_phy_tgt_error); + BCM_REFERENCE(tof_phy_error); + BCM_REFERENCE(bitflips); + BCM_REFERENCE(snr); NULL_CHECK(rtt_report, "rtt_report is NULL", err); NULL_CHECK(p_data, "p_data is NULL", err); DHD_RTT(("%s enter\n", __FUNCTION__)); - p_data_info = (wl_proxd_rtt_result_t *) p_data; + p_data_info = (const wl_proxd_rtt_result_v1_t *) p_data; /* unpack and format 'flags' for display */ flags = ltoh16_ua(&p_data_info->flags); @@ -1656,14 +1887,14 @@ dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 p_data_info->num_ftm)); /* in a session */ } /* show 'avg_rtt' sample */ - p_sample = &p_data_info->avg_rtt; - ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)); + p_sample_avg = &p_data_info->avg_rtt; + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)); DHD_RTT((">\tavg_rtt sample: rssi=%d rtt=%d%s std_deviation =%d.%d ratespec=0x%08x\n", - (int16) ltoh16_ua(&p_sample->rssi), - ltoh32_ua(&p_sample->rtt.intvl), - ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)), + (int16) ltoh16_ua(&p_sample_avg->rssi), + ltoh32_ua(&p_sample_avg->rtt.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)), ltoh16_ua(&p_data_info->sd_rtt)/10, ltoh16_ua(&p_data_info->sd_rtt)%10, - ltoh32_ua(&p_sample->ratespec))); + ltoh32_ua(&p_sample_avg->ratespec))); /* set peer address */ rtt_report->addr = p_data_info->peer; @@ -1730,6 +1961,287 @@ dhd_rtt_convert_results_to_host(rtt_report_t *rtt_report, uint8 *p_data, uint16 ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.burst_duration.tmu)))); DHD_RTT(("rtt_report->burst_duration : %d\n", rtt_report->burst_duration)); } + + /* display detail if available */ + num_rtt = ltoh16_ua(&p_data_info->num_rtt); + if (num_rtt > 0) { + DHD_RTT((">\tnum rtt: %d samples\n", num_rtt)); + p_sample = &p_data_info->rtt[0]; + for (i = 0; i < num_rtt; i++) { + snr = 0; + bitflips = 0; + tof_phy_error = 0; + tof_phy_tgt_error = 0; + tof_target_snr = 0; + tof_target_bitflips = 0; + rssi = 0; + dist = 0; + num_ftm = p_data_info->num_ftm; + /* FTM frames 1,4,7,11 have valid snr, rssi and bitflips */ + if ((i % num_ftm) == 1) { + rssi = (wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi); + snr = (wl_proxd_snr_t) ltoh16_ua(&p_sample->snr); + bitflips = (wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips); + tof_phy_error = + (wl_proxd_phy_error_t) + ltoh32_ua(&p_sample->tof_phy_error); + tof_phy_tgt_error = + (wl_proxd_phy_error_t) + ltoh32_ua(&p_sample->tof_tgt_phy_error); + tof_target_snr = + (wl_proxd_snr_t) + ltoh16_ua(&p_sample->tof_tgt_snr); + tof_target_bitflips = + (wl_proxd_bitflips_t) + ltoh16_ua(&p_sample->tof_tgt_bitflips); + dist = ltoh32_ua(&p_sample->distance); + } else { + rssi = -1; + snr = 0; + bitflips = 0; + dist = 0; + tof_target_bitflips = 0; + tof_target_snr = 0; + tof_phy_tgt_error = 0; + } + DHD_RTT((">\t sample[%d]: id=%d rssi=%d snr=0x%x bitflips=%d" + " tof_phy_error %x tof_phy_tgt_error %x target_snr=0x%x" + " target_bitflips=%d dist=%d rtt=%d%s status %s" + " Type %s coreid=%d\n", + i, p_sample->id, rssi, snr, + bitflips, tof_phy_error, tof_phy_tgt_error, + tof_target_snr, + tof_target_bitflips, dist, + ltoh32_ua(&p_sample->rtt.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)), + ftm_status_value_to_logstr(ltoh32_ua(&p_sample->status)), + ftm_frame_types[i % num_ftm], p_sample->coreid)); + p_sample++; + } + } + return err; +} + +static int +dhd_rtt_convert_results_to_host_v2(rtt_report_t *rtt_report, const uint8 *p_data, + uint16 tlvid, uint16 len) +{ + int i; + int err = BCME_OK; + char eabuf[ETHER_ADDR_STR_LEN]; + wl_proxd_result_flags_t flags; + wl_proxd_session_state_t session_state; + wl_proxd_status_t proxd_status; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) + struct timespec ts; +#endif /* LINUX_VER >= 2.6.39 */ + uint32 ratespec; + uint32 avg_dist; + const wl_proxd_rtt_result_v2_t *p_data_info = NULL; + const wl_proxd_rtt_sample_v2_t *p_sample_avg = NULL; + const wl_proxd_rtt_sample_v2_t *p_sample = NULL; + uint16 num_rtt = 0; + wl_proxd_intvl_t rtt; + wl_proxd_intvl_t p_time; + uint16 snr = 0, bitflips = 0; + wl_proxd_phy_error_t tof_phy_error = 0; + wl_proxd_phy_error_t tof_phy_tgt_error = 0; + wl_proxd_snr_t tof_target_snr = 0; + wl_proxd_bitflips_t tof_target_bitflips = 0; + int16 rssi = 0; + int32 dist = 0; + uint32 chanspec = 0; + uint8 num_ftm = 0; + char *ftm_frame_types[] = FTM_FRAME_TYPES; + + BCM_REFERENCE(ftm_frame_types); + BCM_REFERENCE(dist); + BCM_REFERENCE(rssi); + BCM_REFERENCE(tof_target_bitflips); + BCM_REFERENCE(tof_target_snr); + BCM_REFERENCE(tof_phy_tgt_error); + BCM_REFERENCE(tof_phy_error); + BCM_REFERENCE(bitflips); + BCM_REFERENCE(snr); + BCM_REFERENCE(chanspec); + + NULL_CHECK(rtt_report, "rtt_report is NULL", err); + NULL_CHECK(p_data, "p_data is NULL", err); + DHD_RTT(("%s enter\n", __FUNCTION__)); + p_data_info = (const wl_proxd_rtt_result_v2_t *) p_data; + /* unpack and format 'flags' for display */ + flags = ltoh16_ua(&p_data_info->flags); + /* session state and status */ + session_state = ltoh16_ua(&p_data_info->state); + proxd_status = ltoh32_ua(&p_data_info->status); + bcm_ether_ntoa((&(p_data_info->peer)), eabuf); + ftm_session_state_value_to_logstr(session_state); + ftm_status_value_to_logstr(proxd_status); + DHD_RTT((">\tTarget(%s) session state=%d(%s), status=%d(%s)\n", + eabuf, + session_state, + ftm_session_state_value_to_logstr(session_state), + proxd_status, + ftm_status_value_to_logstr(proxd_status))); + /* show avg_dist (1/256m units), burst_num */ + avg_dist = ltoh32_ua(&p_data_info->avg_dist); + if (avg_dist == 0xffffffff) { /* report 'failure' case */ + DHD_RTT((">\tavg_dist=-1m, burst_num=%d, valid_measure_cnt=%d\n", + ltoh16_ua(&p_data_info->burst_num), + p_data_info->num_valid_rtt)); /* in a session */ + avg_dist = FTM_INVALID; + } else { + DHD_RTT((">\tavg_dist=%d.%04dm, burst_num=%d, valid_measure_cnt=%d num_ftm=%d\n", + avg_dist >> 8, /* 1/256m units */ + ((avg_dist & 0xff) * 625) >> 4, + ltoh16_ua(&p_data_info->burst_num), + p_data_info->num_valid_rtt, + p_data_info->num_ftm)); /* in a session */ + } + + /* show 'avg_rtt' sample */ + /* in v2, avg_rtt is the first element of the variable rtt[] */ + p_sample_avg = &p_data_info->rtt[0]; + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)); + DHD_RTT((">\tavg_rtt sample: rssi=%d rtt=%d%s std_deviation =%d.%d" + "ratespec=0x%08x chanspec=0x%08x\n", + (int16) ltoh16_ua(&p_sample_avg->rssi), + ltoh32_ua(&p_sample_avg->rtt.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample_avg->rtt.tmu)), + ltoh16_ua(&p_data_info->sd_rtt)/10, ltoh16_ua(&p_data_info->sd_rtt)%10, + ltoh32_ua(&p_sample_avg->ratespec), + ltoh32_ua(&p_sample_avg->chanspec))); + + /* set peer address */ + rtt_report->addr = p_data_info->peer; + + /* burst num */ + rtt_report->burst_num = ltoh16_ua(&p_data_info->burst_num); + + /* success num */ + rtt_report->success_num = p_data_info->num_valid_rtt; + + /* actual number of FTM supported by peer */ + rtt_report->num_per_burst_peer = p_data_info->num_ftm; + rtt_report->negotiated_burst_num = p_data_info->num_ftm; + + /* status */ + rtt_report->status = ftm_get_statusmap_info(proxd_status, + &ftm_status_map_info[0], ARRAYSIZE(ftm_status_map_info)); + + /* rssi (0.5db) */ + rtt_report->rssi = ABS((wl_proxd_rssi_t)ltoh16_ua(&p_sample_avg->rssi)) * 2; + + /* rx rate */ + ratespec = ltoh32_ua(&p_sample_avg->ratespec); + rtt_report->rx_rate = dhd_rtt_convert_rate_to_host(ratespec); + + /* tx rate */ + if (flags & WL_PROXD_RESULT_FLAG_VHTACK) { + rtt_report->tx_rate = dhd_rtt_convert_rate_to_host(0x2010010); + } else { + rtt_report->tx_rate = dhd_rtt_convert_rate_to_host(0xc); + } + + /* rtt_sd */ + rtt.tmu = ltoh16_ua(&p_sample_avg->rtt.tmu); + rtt.intvl = ltoh32_ua(&p_sample_avg->rtt.intvl); + rtt_report->rtt = (wifi_timespan)FTM_INTVL2NSEC(&rtt) * 1000; /* nano -> pico seconds */ + rtt_report->rtt_sd = ltoh16_ua(&p_data_info->sd_rtt); /* nano -> 0.1 nano */ + DHD_RTT(("rtt_report->rtt : %llu\n", rtt_report->rtt)); + DHD_RTT(("rtt_report->rssi : %d (0.5db)\n", rtt_report->rssi)); + + /* average distance */ + if (avg_dist != FTM_INVALID) { + rtt_report->distance = (avg_dist >> 8) * 1000; /* meter -> mm */ + rtt_report->distance += (avg_dist & 0xff) * 1000 / 256; + } else { + rtt_report->distance = FTM_INVALID; + } + /* time stamp */ + /* get the time elapsed from boot time */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) + get_monotonic_boottime(&ts); + rtt_report->ts = (uint64)TIMESPEC_TO_US(ts); +#endif /* LINUX_VER >= 2.6.39 */ + + if (proxd_status == WL_PROXD_E_REMOTE_FAIL) { + /* retry time after failure */ + p_time.intvl = ltoh32_ua(&p_data_info->u.retry_after.intvl); + p_time.tmu = ltoh16_ua(&p_data_info->u.retry_after.tmu); + rtt_report->retry_after_duration = FTM_INTVL2SEC(&p_time); /* s -> s */ + DHD_RTT((">\tretry_after: %d%s\n", + ltoh32_ua(&p_data_info->u.retry_after.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.retry_after.tmu)))); + } else { + /* burst duration */ + p_time.intvl = ltoh32_ua(&p_data_info->u.retry_after.intvl); + p_time.tmu = ltoh16_ua(&p_data_info->u.retry_after.tmu); + rtt_report->burst_duration = FTM_INTVL2MSEC(&p_time); /* s -> ms */ + DHD_RTT((">\tburst_duration: %d%s\n", + ltoh32_ua(&p_data_info->u.burst_duration.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_data_info->u.burst_duration.tmu)))); + DHD_RTT(("rtt_report->burst_duration : %d\n", rtt_report->burst_duration)); + } + /* display detail if available */ + num_rtt = ltoh16_ua(&p_data_info->num_rtt); + if (num_rtt > 0) { + DHD_RTT((">\tnum rtt: %d samples\n", num_rtt)); + p_sample = &p_data_info->rtt[1]; + for (i = 0; i < num_rtt; i++) { + snr = 0; + bitflips = 0; + tof_phy_error = 0; + tof_phy_tgt_error = 0; + tof_target_snr = 0; + tof_target_bitflips = 0; + rssi = 0; + dist = 0; + num_ftm = p_data_info->num_ftm; + /* FTM frames 1,4,7,11 have valid snr, rssi and bitflips */ + if ((i % num_ftm) == 1) { + rssi = (wl_proxd_rssi_t) ltoh16_ua(&p_sample->rssi); + snr = (wl_proxd_snr_t) ltoh16_ua(&p_sample->snr); + bitflips = (wl_proxd_bitflips_t) ltoh16_ua(&p_sample->bitflips); + tof_phy_error = + (wl_proxd_phy_error_t) + ltoh32_ua(&p_sample->tof_phy_error); + tof_phy_tgt_error = + (wl_proxd_phy_error_t) + ltoh32_ua(&p_sample->tof_tgt_phy_error); + tof_target_snr = + (wl_proxd_snr_t) + ltoh16_ua(&p_sample->tof_tgt_snr); + tof_target_bitflips = + (wl_proxd_bitflips_t) + ltoh16_ua(&p_sample->tof_tgt_bitflips); + dist = ltoh32_ua(&p_sample->distance); + chanspec = ltoh32_ua(&p_sample->chanspec); + } else { + rssi = -1; + snr = 0; + bitflips = 0; + dist = 0; + tof_target_bitflips = 0; + tof_target_snr = 0; + tof_phy_tgt_error = 0; + } + DHD_RTT((">\t sample[%d]: id=%d rssi=%d snr=0x%x bitflips=%d" + " tof_phy_error %x tof_phy_tgt_error %x target_snr=0x%x" + " target_bitflips=%d dist=%d rtt=%d%s status %s Type %s" + " coreid=%d chanspec=0x%08x\n", + i, p_sample->id, rssi, snr, + bitflips, tof_phy_error, tof_phy_tgt_error, + tof_target_snr, + tof_target_bitflips, dist, + ltoh32_ua(&p_sample->rtt.intvl), + ftm_tmu_value_to_logstr(ltoh16_ua(&p_sample->rtt.tmu)), + ftm_status_value_to_logstr(ltoh32_ua(&p_sample->status)), + ftm_frame_types[i % num_ftm], p_sample->coreid, + chanspec)); + p_sample++; + } + } return err; } @@ -1742,19 +2254,17 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) wl_proxd_event_t *p_event; wl_proxd_event_type_t event_type; wl_proxd_ftm_session_status_t session_status; - wl_proxd_collect_event_data_t *collect_event_data; const ftm_strmap_entry_t *p_loginfo; rtt_result_t *rtt_result; gfp_t kflags; #ifdef WL_CFG80211 int idx; - struct rtt_noti_callback *iter; - bool is_new = TRUE; rtt_status_info_t *rtt_status; - rtt_result_t *next2; - rtt_results_header_t *next = NULL; rtt_target_info_t *rtt_target_info; - rtt_results_header_t *entry, *rtt_results_header = NULL; + struct rtt_noti_callback *iter; + rtt_results_header_t *entry, *next, *rtt_results_header = NULL; + rtt_result_t *next2; + bool is_new = TRUE; #endif /* WL_CFG80211 */ DHD_RTT(("Enter %s \n", __FUNCTION__)); @@ -1832,7 +2342,7 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif /* find a rtt_report_header for this mac address */ list_for_each_entry(entry, &rtt_status->rtt_results_cache, list) { if (!memcmp(&entry->peer_mac, &event->addr, ETHER_ADDR_LEN)) { @@ -1844,7 +2354,7 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif #endif /* WL_CFG80211 */ switch (event_type) { case WL_PROXD_EVENT_SESSION_CREATE: @@ -1972,13 +2482,12 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) } else { DHD_RTT(("RTT_STOPPED\n")); rtt_status->status = RTT_STOPPED; - /* to turn on mpc mode */ schedule_work(&rtt_status->work); /* notify the completed information to others */ #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_entry(iter, &rtt_status->noti_fn_list, list) { iter->noti_fn(iter->ctx, &rtt_status->rtt_results_cache); } @@ -1999,7 +2508,7 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif /* reinitialize the HEAD */ INIT_LIST_HEAD(&rtt_status->rtt_results_cache); /* clear information for rtt_config */ @@ -2034,24 +2543,43 @@ dhd_rtt_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data) case WL_PROXD_EVENT_COLLECT: DHD_RTT(("WL_PROXD_EVENT_COLLECT\n")); if (tlvs_len > 0) { - collect_event_data = kzalloc(sizeof(wl_proxd_collect_event_data_t), kflags); - if (!collect_event_data) { + void *buffer = NULL; + if (!(buffer = kzalloc(tlvs_len, kflags))) { ret = -ENOMEM; goto exit; } /* unpack TLVs and invokes the cbfn to print the event content TLVs */ - ret = bcm_unpack_xtlv_buf((void *) collect_event_data, + ret = bcm_unpack_xtlv_buf(buffer, (uint8 *)&p_event->tlvs[0], tlvs_len, BCM_XTLV_OPTION_NONE, rtt_unpack_xtlv_cbfn); - kfree(collect_event_data); + kfree(buffer); if (ret != BCME_OK) { - DHD_ERROR(("%s : Failed to unpack xtlv for an event\n", - __FUNCTION__)); + DHD_ERROR(("%s : Failed to unpack xtlv for event %d\n", + __FUNCTION__, event_type)); + goto exit; + } + } + break; + case WL_PROXD_EVENT_MF_STATS: + DHD_RTT(("WL_PROXD_EVENT_MF_STATS\n")); + if (tlvs_len > 0) { + void *buffer = NULL; + if (!(buffer = kzalloc(tlvs_len, kflags))) { + ret = -ENOMEM; + goto exit; + } + /* unpack TLVs and invokes the cbfn to print the event content TLVs */ + ret = bcm_unpack_xtlv_buf(buffer, + (uint8 *)&p_event->tlvs[0], tlvs_len, + BCM_XTLV_OPTION_NONE, rtt_unpack_xtlv_cbfn); + kfree(buffer); + if (ret != BCME_OK) { + DHD_ERROR(("%s : Failed to unpack xtlv for event %d\n", + __FUNCTION__, event_type)); goto exit; } } break; - default: DHD_ERROR(("WLC_E_PROXD: not supported EVENT Type:%d\n", event_type)); @@ -2076,11 +2604,11 @@ dhd_rtt_work(struct work_struct *work) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif rtt_status = container_of(work, rtt_status_info_t, work); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (rtt_status == NULL) { DHD_ERROR(("%s : rtt_status is NULL\n", __FUNCTION__)); return; @@ -2215,6 +2743,7 @@ dhd_rtt_enable_responder(dhd_pub_t *dhd, wifi_channel_info *channel_info) DHD_ERROR(("Failed to set the chanspec \n")); } } + rtt_status->pm = PM_OFF; err = wldev_ioctl_get(dev, WLC_GET_PM, &rtt_status->pm, sizeof(rtt_status->pm)); DHD_RTT(("Current PM value read %d\n", rtt_status->pm)); if (err) { @@ -2272,6 +2801,7 @@ dhd_rtt_cancel_responder(dhd_pub_t *dhd) rtt_status_info_t *rtt_status; int pm = 0; struct net_device *dev = dhd_linux_get_primary_netdev(dhd); + NULL_CHECK(dhd, "dhd is NULL", err); rtt_status = GET_RTTSTATE(dhd); NULL_CHECK(rtt_status, "rtt_status is NULL", err); @@ -2388,7 +2918,7 @@ dhd_rtt_deinit(dhd_pub_t *dhd) #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif if (!list_empty(&rtt_status->noti_fn_list)) { list_for_each_entry_safe(iter, iter2, &rtt_status->noti_fn_list, list) { @@ -2410,7 +2940,7 @@ dhd_rtt_deinit(dhd_pub_t *dhd) } #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif kfree(rtt_status->rtt_config.target_info); kfree(dhd->rtt_state); dhd->rtt_state = NULL; diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_rtt.h b/drivers/net/wireless/bcmdhd_oo/dhd_rtt.h index b3ca820b747823c24e8decea134bd3e557ab367c..55c0ed7ffefe72dd1ea8c0b469c1125bfc3d559a 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_rtt.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_rtt.h @@ -1,14 +1,14 @@ /* * Broadcom Dongle Host Driver (DHD), RTT * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -45,7 +45,7 @@ #ifndef BIT #define BIT(x) (1 << (x)) -#endif +#endif // endif /* DSSS, CCK and 802.11n rates in [500kbps] units */ #define WL_MAXRATE 108 /* in 500kbps units */ @@ -126,7 +126,6 @@ enum { RTT_PREAMBLE_VHT = BIT(2) }; - enum { RTT_BW_5 = BIT(0), RTT_BW_10 = BIT(1), @@ -135,6 +134,14 @@ enum { RTT_BW_80 = BIT(4), RTT_BW_160 = BIT(5) }; + +enum rtt_rate_bw { + RTT_RATE_20M, + RTT_RATE_40M, + RTT_RATE_80M, + RTT_RATE_160M +}; + #define FTM_MAX_NUM_BURST_EXP 14 #define HAS_11MC_CAP(cap) (cap & RTT_CAP_FTM_WAY) #define HAS_ONEWAY_CAP(cap) (cap & RTT_CAP_ONE_WAY) @@ -228,7 +235,6 @@ typedef struct rtt_status_info { dhd_pub_t *dhd; int8 status; /* current status for the current entry */ int8 txchain; /* current device tx chain */ - int8 mpc; /* indicate we change mpc mode */ int pm; /* to save current value of pm */ int8 pm_restore; /* flag to reset the old value of pm */ int8 cur_idx; /* current entry to do RTT */ @@ -309,7 +315,6 @@ typedef struct rtt_capabilities { uint8 bw_support; /* bit mask indicate what BW is supported */ } rtt_capabilities_t; - /* RTT responder information */ typedef struct wifi_rtt_responder { wifi_channel_info channel; /* channel of responder */ @@ -334,10 +339,8 @@ dhd_dev_rtt_unregister_noti_callback(struct net_device *dev, dhd_rtt_compl_noti_ int dhd_dev_rtt_capability(struct net_device *dev, rtt_capabilities_t *capa); -#ifdef WL_CFG80211 int dhd_dev_rtt_avail_channel(struct net_device *dev, wifi_channel_info *channel_info); -#endif /* WL_CFG80211 */ int dhd_dev_rtt_enable_responder(struct net_device *dev, wifi_channel_info *channel_info); @@ -357,7 +360,6 @@ dhd_rtt_set_cfg(dhd_pub_t *dhd, rtt_config_params_t *params); int dhd_rtt_stop(dhd_pub_t *dhd, struct ether_addr *mac_list, int mac_cnt); - int dhd_rtt_register_noti_callback(dhd_pub_t *dhd, void *ctx, dhd_rtt_compl_noti_fn noti_fn); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_sdio.c b/drivers/net/wireless/bcmdhd_oo/dhd_sdio.c index 5f76439701f31735a18b96845b23d14db2abe135..ce64a5c7db4e6eab7d531aaa8e37974dbe23b70e 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_sdio.c @@ -1,14 +1,14 @@ /* * DHD Bus Module for SDIO * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,17 +24,13 @@ * * <> * - * $Id: dhd_sdio.c 733461 2017-11-28 12:05:07Z $ + * $Id: dhd_sdio.c 721361 2017-09-14 05:33:32Z $ */ #include #include #include -#ifdef BCMEMBEDIMAGE -#include BCMEMBEDIMAGE -#endif /* BCMEMBEDIMAGE */ - #include #include #include @@ -72,7 +68,7 @@ #ifdef PROP_TXSTATUS #include -#endif +#endif // endif #ifdef DHDTCPACK_SUPPRESS #include #endif /* DHDTCPACK_SUPPRESS */ @@ -81,6 +77,10 @@ #include #endif /* BT_OVER_SDIO */ +#if defined(DEBUGGER) || defined(DHD_DSCOPE) +#include +#endif /* DEBUGGER || DHD_DSCOPE */ + bool dhd_mp_halting(dhd_pub_t *dhdp); extern void bcmsdh_waitfor_iodrain(void *sdh); extern void bcmsdh_reject_ioreqs(void *sdh, bool reject); @@ -88,10 +88,9 @@ extern bool bcmsdh_fatal_error(void *sdh); static int dhdsdio_suspend(void *context); static int dhdsdio_resume(void *context); - #ifndef DHDSDIO_MEM_DUMP_FNAME #define DHDSDIO_MEM_DUMP_FNAME "mem_dump" -#endif +#endif // endif #define QLEN (1024) /* bulk rx and tx queue lengths */ #define FCHI (QLEN - 10) @@ -103,11 +102,11 @@ static int dhdsdio_resume(void *context); #define READ_FRM_CNT_RETRIES 3 #ifndef DHD_RXBOUND #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ -#endif +#endif // endif #ifndef DHD_TXBOUND #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ -#endif +#endif // endif #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ @@ -118,10 +117,10 @@ static int dhdsdio_resume(void *context); #ifndef DHD_FIRSTREAD #define DHD_FIRSTREAD 32 -#endif +#endif // endif #if !ISPOWEROF2(DHD_FIRSTREAD) #error DHD_FIRSTREAD is not a power of 2! -#endif +#endif // endif /* Total length of frame header for dongle protocol */ #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) @@ -132,15 +131,15 @@ static int dhdsdio_resume(void *context); #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN) #else #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN) -#endif +#endif // endif /* Space for header read, limit for data packets */ #ifndef MAX_HDR_READ #define MAX_HDR_READ 32 -#endif +#endif // endif #if !ISPOWEROF2(MAX_HDR_READ) #error MAX_HDR_READ is not a power of 2! -#endif +#endif // endif #define MAX_RX_DATASZ 2048 @@ -158,13 +157,13 @@ static int dhdsdio_resume(void *context); #if (PMU_MAX_TRANSITION_DLY <= 1000000) #undef PMU_MAX_TRANSITION_DLY #define PMU_MAX_TRANSITION_DLY 1000000 -#endif +#endif // endif /* hooks for limiting threshold custom tx num in rx processing */ #define DEFAULT_TXINRX_THRES 0 #ifndef CUSTOM_TXINRX_THRES #define CUSTOM_TXINRX_THRES DEFAULT_TXINRX_THRES -#endif +#endif // endif /* Value for ChipClockCSR during initial setup */ #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ) @@ -184,7 +183,7 @@ DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) DEFINE_MUTEX(_dhd_sdio_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ -#endif +#endif // endif #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW extern unsigned int system_hw_rev; @@ -443,7 +442,6 @@ typedef struct dhd_bus { #endif /* defined (BT_OVER_SDIO) */ } dhd_bus_t; - /* * Whenever DHD_IDLE_IMMEDIATE condition is handled, we have to now check if * BT is active too. Instead of adding #ifdef code in all the places, we thought @@ -488,9 +486,6 @@ extern uint sd_f1_blocksize; extern uint *dhd_spi_lockcount; #endif /* BCMSPI_ANDROID */ -#if defined(BT_OVER_SDIO) -extern dhd_pub_t *g_dhd_pub; -#endif /* (BT_OVER_SDIO) */ extern void dhd_os_wd_timer(void *bus, uint wdtick); int dhd_enableOOB(dhd_pub_t *dhd, bool sleep); @@ -536,11 +531,23 @@ static const uint retry_limit = 2; /* Force even SD lengths (some host controllers mess up on odd bytes) */ static bool forcealign; +#if defined(DEBUGGER) +static uint32 dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr); +static void dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val); + +/** the debugger layer will call back into this (bus) layer to read/write dongle memory */ +static struct dhd_dbg_bus_ops_s bus_ops = { + .read_u16 = NULL, + .read_u32 = dhd_sdio_reg_read, + .write_u32 = dhd_sdio_reg_write, +}; +#endif /* DEBUGGER */ + #define ALIGNMENT 4 #if defined(OOB_INTR_ONLY) && defined(HW_OOB) extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); -#endif +#endif // endif #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD @@ -681,7 +688,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, uint count); -#endif +#endif // endif static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size); #ifdef DHD_DEBUG @@ -726,9 +733,6 @@ static int dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path); #endif /* DHD_UCODE_DOWNLOAD */ static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path); static int dhdsdio_download_nvram(dhd_bus_t *bus); -#ifdef BCMEMBEDIMAGE -static int dhdsdio_download_code_array(dhd_bus_t *bus); -#endif static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep); static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok); static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus); @@ -737,10 +741,6 @@ static int dhd_bcmsdh_send_buffer(void *bus, uint8 *frame, uint16 len); static int dhdsdio_set_sdmode(dhd_bus_t *bus, int32 sd_mode); static int dhdsdio_sdclk(dhd_bus_t *bus, bool on); static void dhdsdio_advertise_bus_cleanup(dhd_pub_t *dhdp); -#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT -int dhd_get_system_rev(void); -#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ - #if defined(BT_OVER_SDIO) static int extract_hex_field(char * line, uint16 start_pos, uint16 num_chars, uint16 * value); @@ -755,11 +755,6 @@ static int _dhdsdio_download_btfw(struct dhd_bus *bus); static int dhd_bus_ulp_reinit_fw(dhd_bus_t *bus); #endif /* DHD_ULP */ -#ifdef DHD_WAKE_STATUS -int bcmsdh_get_total_wake(bcmsdh_info_t *bcmsdh); -int bcmsdh_set_get_wake(bcmsdh_info_t *bcmsdh, int flag); -#endif /* DHD_WAKE_STATUS */ - static void dhdsdio_tune_fifoparam(struct dhd_bus *bus) { @@ -863,8 +858,8 @@ dhdsdio_oobwakeup_init(dhd_bus_t *bus) bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP); - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); /* Set device for gpio1 wakeup */ bcmsdh_reg_write(bus->sdh, addr, 4, 2); @@ -891,23 +886,17 @@ dhdsdio_sr_cap(dhd_bus_t *bus) if (bus->sih->chip == BCM43430_CHIP_ID || bus->sih->chip == BCM43018_CHIP_ID) { /* check if fw initialized sr engine */ - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, sr_control1); + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, sr_control1); if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0) cap = TRUE; return cap; } - 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); - bcmsdh_reg_write(bus->sdh, addr, 4, 3); - core_capext = bcmsdh_reg_read(bus->sdh, data, 4); - } else if ((bus->sih->chip == BCM4330_CHIP_ID) || - (BCM4347_CHIP(bus->sih->chip))) { + if ( + 0) { core_capext = FALSE; } else if ((bus->sih->chip == BCM4335_CHIP_ID) || (bus->sih->chip == BCM4339_CHIP_ID) || - (bus->sih->chip == BCM43349_CHIP_ID) || BCM4345_CHIP(bus->sih->chip) || (bus->sih->chip == BCM4354_CHIP_ID) || (bus->sih->chip == BCM4358_CHIP_ID) || @@ -925,19 +914,15 @@ dhdsdio_sr_cap(dhd_bus_t *bus) if (!(core_capext)) return FALSE; - if (bus->sih->chip == BCM4324_CHIP_ID) { - /* FIX: Should change to query SR control register instead */ - cap = TRUE; - } else if ((bus->sih->chip == BCM4335_CHIP_ID) || + if ((bus->sih->chip == BCM4335_CHIP_ID) || (bus->sih->chip == BCM4339_CHIP_ID) || - (bus->sih->chip == BCM43349_CHIP_ID) || BCM4345_CHIP(bus->sih->chip) || (bus->sih->chip == BCM4354_CHIP_ID) || (bus->sih->chip == BCM4358_CHIP_ID) || (bus->sih->chip == BCM4350_CHIP_ID)) { uint32 enabval = 0; - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3); enabval = bcmsdh_reg_read(bus->sdh, data, 4); @@ -960,29 +945,12 @@ dhdsdio_sr_cap(dhd_bus_t *bus) return cap; } -static int -dhdsdio_srwar_init(dhd_bus_t *bus) -{ - bcmsdh_gpio_init(bus->sdh); - -#ifdef USE_OOB_GPIO1 - dhdsdio_oobwakeup_init(bus); -#endif - - - return 0; -} - static int dhdsdio_sr_init(dhd_bus_t *bus) { uint8 val; int err = 0; - if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) - dhdsdio_srwar_init(bus); - - if (bus->sih->chip == BCM43012_CHIP_ID) { val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL); val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT; @@ -1062,7 +1030,7 @@ dhdsdio_clk_kso_init(dhd_bus_t *bus) #define DEFAULT_MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) #ifndef CUSTOM_MAX_KSO_ATTEMPTS #define CUSTOM_MAX_KSO_ATTEMPTS DEFAULT_MAX_KSO_ATTEMPTS -#endif +#endif // endif static int dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) @@ -1077,7 +1045,6 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); - /* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared. * So the further reads of KSO register could fail. Thereby just bailing out immediately * after clearing KSO bit, to avoid polling of KSO bit. @@ -1113,7 +1080,6 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); } while (try_cnt++ < CUSTOM_MAX_KSO_ATTEMPTS); - 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)); @@ -1255,16 +1221,6 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on) DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__)); dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); } - - if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) { - SPINWAIT_SLEEP(sdioh_spinwait_sleep, - (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE), - GPIO_DEV_SRSTATE_TIMEOUT); - - if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) { - DHD_ERROR(("ERROR: GPIO_DEV_SRSTATE still low!\n")); - } - } #ifdef USE_CMD14 err = bcmsdh_sleep(bus->sdh, FALSE); if (SLPAUTO_ENAB(bus) && (err != 0)) { @@ -1374,7 +1330,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) clkctl = 0; sdh = bus->sdh; - if (!KSO_ENAB(bus)) return BCME_OK; @@ -1391,7 +1346,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) dhdsdio_wkwlan(bus, TRUE); #endif /* BCMSPI */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); if (err) { ht_avail_error++; @@ -1410,7 +1364,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) ht_avail_error = 0; } - /* Check current status */ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (err) { @@ -1444,7 +1397,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); } } - +#ifndef BCMSDIOLITE /* Otherwise, wait here (polling) for HT Avail */ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { SPINWAIT_SLEEP(sdioh_spinwait_sleep, @@ -1461,7 +1414,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl)); return BCME_ERROR; } - +#endif /* BCMSDIOLITE */ /* Mark clock available */ bus->clkstate = CLK_AVAIL; DHD_INFO(("CLKCTL: turned ON\n")); @@ -1696,7 +1649,7 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) /* Now remove the SD clock */ ret = dhdsdio_sdclk(bus, FALSE); #ifdef DHD_DEBUG - if (dhd_console_ms == 0) + if (bus->dhd->dhd_console_ms == 0) #endif /* DHD_DEBUG */ if (bus->poll == 0) dhd_os_wd_timer(bus->dhd, 0); @@ -1732,10 +1685,10 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) if (sleep) { /* Don't sleep if something is pending */ #ifdef DHD_USE_IDLECOUNT - if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq) || bus->readframes || - bus->ctrl_frame_stat) + if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq) || + bus->readframes || bus->ctrl_frame_stat) #else - if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) + if (bus->dpc_sched || bus->rxskip || pktq_n_pkts_tot(&bus->txq)) #endif /* DHD_USE_IDLECOUNT */ return BCME_BUSY; @@ -1759,7 +1712,6 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) } #endif /* !BT_OVER_SDIO */ - if (!SLPAUTO_ENAB(bus)) { /* Disable SDIO interrupts (no longer interested) */ bcmsdh_intr_disable(bus->sdh); @@ -1802,7 +1754,6 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) /* Force pad isolation off if possible (in case power never toggled) */ bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); - /* Make sure the controller has the bus up */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); @@ -1830,12 +1781,12 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) dhd_pub_t *dhd = bus->dhd; net = dhd_idx2net(dhd, 0); if (net != NULL) { - DHD_ERROR(("<<<<<< WIFI HANG by KSO Enabled failure\n")); + DHD_ERROR(("<< WIFI HANG by KSO Enabled failure\n")); dhd_os_sdunlock(dhd); net_os_send_hang_message(net); dhd_os_sdlock(dhd); } else { - DHD_ERROR(("<<<<< WIFI HANG Fail because net is NULL\n")); + DHD_ERROR(("<< WIFI HANG Fail because net is NULL\n")); } } #endif /* BT_OVER_SDIO */ @@ -2047,13 +1998,14 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); /* Check for existing queue, current flow-control, pending event, or pending clock */ - if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || + if (dhd_deferred_tx || bus->fcstate || pktq_n_pkts_tot(&bus->txq) || bus->dpc_sched || (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || (bus->clkstate != CLK_AVAIL)) { bool deq_ret; int pkq_len; - DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq))); + DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, + pktq_n_pkts_tot(&bus->txq))); bus->fcqueued++; /* Priority based enq */ @@ -2081,14 +2033,14 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) ret = BCME_OK; dhd_os_sdlock_txq(bus->dhd); - pkq_len = pktq_len(&bus->txq); + pkq_len = pktq_n_pkts_tot(&bus->txq); dhd_os_sdunlock_txq(bus->dhd); if (pkq_len >= FCHI) { bool wlfc_enabled = FALSE; #ifdef PROP_TXSTATUS wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) != WLFC_UNSUPPORTED); -#endif +#endif // endif if (!wlfc_enabled && dhd_doflow) { dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); } @@ -2096,10 +2048,10 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) #ifdef DHD_DEBUG dhd_os_sdlock_txq(bus->dhd); - if (pktq_plen(&bus->txq, prec) > qcount[prec]) - qcount[prec] = pktq_plen(&bus->txq, prec); + if (pktqprec_n_pkts(&bus->txq, prec) > qcount[prec]) + qcount[prec] = pktqprec_n_pkts(&bus->txq, prec); dhd_os_sdunlock_txq(bus->dhd); -#endif +#endif // endif /* Schedule DPC if needed to send queued packet(s) */ if (dhd_deferred_tx && !bus->dpc_sched) { @@ -2111,7 +2063,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) #ifdef SDTEST chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL); -#endif +#endif // endif /* Lock: we're about to use shared data/code (and SDIO) */ dhd_os_sdlock(bus->dhd); @@ -2536,9 +2488,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) #ifdef DHD_LOSSLESS_ROAMING uint8 *pktdata; struct ether_header *eh; -#ifdef BDC - struct bdc_header *bdc_header; -#endif #endif /* DHD_LOSSLESS_ROAMING */ DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -2583,9 +2532,8 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) pktdata = (uint8 *)PKTDATA(osh, pkts[i]); #ifdef BDC /* Skip BDC header */ - bdc_header = (struct bdc_header *)pktdata; pktdata += BDC_HEADER_LEN + ((struct bdc_header *)pktdata)->dataOffset; -#endif +#endif // endif eh = (struct ether_header *)pktdata; if (eh->ether_type == hton16(ETHER_TYPE_802_1X)) { uint8 prio = (uint8)PKTPRIO(pkts[i]); @@ -2593,11 +2541,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) /* Restore to original priority for 802.1X packet */ if (prio == PRIO_8021D_NC) { PKTSETPRIO(pkts[i], dhd->prio_8021x); -#ifdef BDC - /* Restore to original priority in BDC header */ - bdc_header->priority = - (dhd->prio_8021x & BDC_PRIORITY_MASK); -#endif } } #endif /* DHD_LOSSLESS_ROAMING */ @@ -2629,7 +2572,7 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) } dhd_os_sdlock_txq(bus->dhd); - txpktqlen = pktq_len(&bus->txq); + txpktqlen = pktq_n_pkts_tot(&bus->txq); dhd_os_sdunlock_txq(bus->dhd); /* Do flow-control if needed */ @@ -2637,7 +2580,7 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) bool wlfc_enabled = FALSE; #ifdef PROP_TXSTATUS wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED); -#endif +#endif // endif if (!wlfc_enabled && dhd_doflow && dhd->txoff) { dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); } @@ -2722,7 +2665,6 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) ASSERT(ISALIGNED((uintptr)frame, 2)); - /* Need to lock here to protect txseq and SDIO tx calls */ dhd_os_sdlock(bus->dhd); @@ -2766,7 +2708,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) if (!TXCTLOK(bus) || !dhd_ulp_f2_ready(bus->dhd, bus->sdh)) #else if (!TXCTLOK(bus)) -#endif +#endif // endif { DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n", __FUNCTION__, bus->tx_max, bus->tx_seq)); @@ -2826,7 +2768,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) } else if (DHD_HDRS_ON()) { prhex("TxHdr", frame, MIN(len, 16)); } -#endif +#endif // endif ret = dhd_bcmsdh_send_buffer(bus, frame, len); } bus->ctrl_frame_stat = FALSE; @@ -2854,13 +2796,12 @@ done: if (g_pm_control == TRUE) { return -BCME_ERROR; } else { - return -ETIMEDOUT; + return -ETIMEDOUT; } #else return -ETIMEDOUT; #endif /* DHD_PM_CONTROL_FROM_FILE */ } - if (ret == BCME_NODEVICE) err_nodevice++; else @@ -2959,8 +2900,6 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) return -ETIMEDOUT; #endif /* DHD_PM_CONTROL_FROM_FILE */ } - - if (bus->dhd->dongle_trap_occured) return -EREMOTEIO; @@ -3013,12 +2952,15 @@ enum { IOV_VARS, #ifdef SOFTAP IOV_FWPATH, -#endif +#endif // endif IOV_TXGLOMSIZE, IOV_TXGLOMMODE, IOV_HANGREPORT, IOV_TXINRX_THRES, IOV_SDIO_SUSPEND +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + IOV_GDB_SERVER, /**< starts gdb server on given interface */ +#endif /* DEBUGGER || DHD_DSCOPE */ }; const bcm_iovar_t dhdsdio_iovars[] = { @@ -3067,11 +3009,14 @@ const bcm_iovar_t dhdsdio_iovars[] = { {"devsleep", IOV_DEVSLEEP, 0, 0, IOVT_UINT32, 0 }, #ifdef SOFTAP {"fwpath", IOV_FWPATH, 0, 0, IOVT_BUFFER, 0 }, -#endif +#endif // endif {"txglomsize", IOV_TXGLOMSIZE, 0, 0, IOVT_UINT32, 0 }, {"fw_hang_report", IOV_HANGREPORT, 0, 0, IOVT_BOOL, 0 }, {"txinrx_thres", IOV_TXINRX_THRES, 0, 0, IOVT_INT32, 0 }, {"sdio_suspend", IOV_SDIO_SUSPEND, 0, 0, IOVT_UINT32, 0 }, +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + {"gdb_server", IOV_GDB_SERVER, 0, 0, IOVT_UINT32, 0 }, +#endif /* DEBUGGER || DHD_DSCOPE */ {NULL, 0, 0, 0, 0, 0 } }; @@ -3095,13 +3040,13 @@ dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) dhd_bus_t *bus = dhdp->bus; #if defined(DHD_WAKE_STATUS) && defined(DHD_WAKE_EVENT_STATUS) int i; -#endif +#endif // endif bcm_bprintf(strbuf, "Bus SDIO structure:\n"); bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", bus->hostintmask, bus->intstatus, bus->sdpcm_ver); bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n", - bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, + bus->fcstate, pktq_n_pkts_tot(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, bus->rxlen, bus->rx_seq); bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n", bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); @@ -3648,7 +3593,6 @@ dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size) line[n] = ch; } - if (n > 0) { if (line[n - 1] == '\r') n--; @@ -3767,7 +3711,7 @@ dhd_socram_dump(dhd_bus_t * bus) return (dhdsdio_mem_dump(bus)); #else return -1; -#endif +#endif // endif } int @@ -3808,22 +3752,14 @@ err: } #ifdef DHD_DEBUG - -#define CC_PLL_CHIPCTRL_SERIAL_ENAB (1 << 24) -#define CC_CHIPCTRL_JTAG_SEL (1 << 3) -#define CC_CHIPCTRL_GPIO_SEL (0x3) -#define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334 (1 << 28) - static int dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) { int int_val; uint32 addr, data, uart_enab = 0; - uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL; - uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL; - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); - data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); + addr = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_addr); + data = SI_ENUM_BASE(bus->sih) + OFFSETOF(chipcregs_t, chipcontrol_data); *bcmerror = 0; bcmsdh_reg_write(bus->sdh, addr, 4, 1); @@ -3837,24 +3773,6 @@ dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) return -1; } - if (bus->sih->chip == BCM4330_CHIP_ID) { - uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; - } else if (bus->sih->chip == BCM4334_CHIP_ID || - bus->sih->chip == BCM43340_CHIP_ID || - bus->sih->chip == BCM43341_CHIP_ID || - bus->sih->chip == BCM43342_CHIP_ID || - 0) { - if (enable) { - /* Moved to PMU chipcontrol 1 from 4330 */ - int_val &= ~gpio_sel; - int_val |= jtag_sel; - } else { - int_val |= gpio_sel; - int_val &= ~jtag_sel; - } - uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334; - } - if (!set) return (int_val & uart_enab); if (enable) @@ -3866,21 +3784,10 @@ dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) *bcmerror = BCME_SDIO_ERROR; return -1; } - if (bus->sih->chip == BCM4330_CHIP_ID) { - uint32 chipcontrol; - addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol); - chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4); - chipcontrol &= ~jtag_sel; - if (enable) { - chipcontrol |= jtag_sel; - chipcontrol &= ~gpio_sel; - } - bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol); - } return (int_val & uart_enab); } -#endif +#endif // endif static int dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, @@ -3901,7 +3808,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch bool_val = (int_val != 0) ? TRUE : FALSE; - /* Some ioctls use the bus */ dhd_os_sdlock(bus->dhd); @@ -4011,8 +3917,6 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch sd1idle = bool_val; break; - - case IOV_GVAL(IOV_RAMSIZE): int_val = (int32)bus->ramsize; bcopy(&int_val, arg, val_size); @@ -4134,7 +4038,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch bcopy(params, &sdreg, sizeof(sdreg)); - addr = SI_ENUM_BASE + sdreg.offset; + addr = SI_ENUM_BASE(bus->sih) + sdreg.offset; size = sdreg.func; int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); if (bcmsdh_regfail(bus->sdh)) @@ -4150,7 +4054,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch bcopy(params, &sdreg, sizeof(sdreg)); - addr = SI_ENUM_BASE + sdreg.offset; + addr = SI_ENUM_BASE(bus->sih) + sdreg.offset; size = sdreg.func; bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value); if (bcmsdh_regfail(bus->sdh)) @@ -4219,10 +4123,8 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch dhd_serialconsole(bus, TRUE, bool_val, &bcmerror); break; - #endif /* DHD_DEBUG */ - #ifdef SDTEST case IOV_GVAL(IOV_EXTLOOP): int_val = (int32)bus->ext_loop; @@ -4268,8 +4170,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, ((uint8)mesbusyctrl | 0x80), NULL); break; -#endif - +#endif // endif case IOV_GVAL(IOV_DONGLEISOLATION): int_val = bus->dhd->dongle_isolation; @@ -4365,6 +4266,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch } break; +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + case IOV_SVAL(IOV_GDB_SERVER): + if (bool_val == TRUE) { + debugger_init((void *) bus, &bus_ops, int_val, SI_ENUM_BASE(bus->sih)); + } else { + debugger_close(); + } + break; +#endif /* DEBUGGER || DHD_DSCOPE */ + default: bcmerror = BCME_UNSUPPORTED; break; @@ -4471,9 +4382,12 @@ dhdsdio_write_vars(dhd_bus_t *bus) * Determine the length token: * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. */ +#ifdef DHD_DEBUG if (bcmerror) { varsizew = 0; - } else { + } else +#endif /* DHD_DEBUG */ + { varsizew = varsize / 4; varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); varsizew = htol32(varsizew); @@ -4590,16 +4504,22 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) */ if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) dhdsdio_devram_remap(bus, TRUE); - +#ifdef BCMSDIOLITE + if (!si_setcore(bus->sih, CC_CORE_ID, 0)) { + DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } +#else 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; } +#endif // endif 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__)); @@ -4613,13 +4533,20 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); goto fail; } - +#ifdef BCMSDIOLITE + if (!si_setcore(bus->sih, CC_CORE_ID, 0)) { + DHD_ERROR(("%s: Can't set to Chip Common core?\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } +#else 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; } +#endif // endif W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); /* switch back to arm core again */ @@ -4856,7 +4783,7 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) #ifdef PROP_TXSTATUS wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED); -#endif +#endif // endif if (!wlfc_enabled) { #ifdef DHDTCPACK_SUPPRESS /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt, @@ -4895,7 +4822,7 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) #if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD) extern uint sd_txglom; -#endif +#endif // endif void dhd_txglom_enable(dhd_pub_t *dhdp, bool enable) { @@ -5025,14 +4952,17 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", __FUNCTION__, enable, ready, tmo.elapsed)); - /* If F2 successfully enabled, set core and enable interrupts */ if (ready == enable) { /* Make sure we're talking to the core. */ +#ifdef BCMSDIOLITE + bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0); + ASSERT(bus->regs != NULL); +#else if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0))) bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0); ASSERT(bus->regs != NULL); - +#endif // endif /* Set up the interrupt mask and enable interrupts */ bus->hostintmask = HOSTINTMASK; /* corerev 4 could use the newer interrupt logic to detect the frames */ @@ -5249,7 +5179,6 @@ dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) goto done; } - /* Read remainder of frame body into the rxctl buffer */ sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, (bus->rxctl + firstread), rdlen, NULL, NULL, NULL); @@ -5270,7 +5199,7 @@ gotpkt: if (DHD_BYTES_ON() && DHD_CTL_ON()) { prhex("RxCtrl", bus->rxctl, len); } -#endif +#endif // endif /* Point to valid data and indicate its length */ bus->rxctl += doff; @@ -5465,8 +5394,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) prhex("SUPERFRAME", PKTDATA(osh, pfirst), MIN(PKTLEN(osh, pfirst), 48)); } -#endif - +#endif // endif /* Validate the superframe header */ dptr = (uint8 *)PKTDATA(osh, pfirst); @@ -5541,7 +5469,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) if (DHD_GLOM_ON()) { prhex("subframe", dptr, 32); } -#endif +#endif // endif if ((uint16)~(sublen^check)) { DHD_ERROR(("%s (subframe %d): HW hdr error: " @@ -5616,7 +5544,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) if (DHD_BYTES_ON() && DHD_DATA_ON()) { prhex("Rx Subframe Data", dptr, dlen); } -#endif +#endif // endif PKTSETLEN(osh, pfirst, sublen); PKTPULL(osh, pfirst, doff); @@ -5707,7 +5635,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) return num; } - /* Return TRUE if there may be more frames to read */ static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) @@ -5740,7 +5667,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) #if defined(DHD_DEBUG) || defined(SDTEST) bool sdtest = FALSE; /* To limit message spew from test mode */ -#endif +#endif // endif DHD_TRACE(("%s: Enter\n", __FUNCTION__)); bus->readframes = TRUE; @@ -5759,7 +5686,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) maxframes = bus->pktgen_count; sdtest = TRUE; } -#endif +#endif // endif /* Not finished unless we encounter no more frames indication */ *finished = FALSE; @@ -5827,7 +5754,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) */ bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ? FALSE : TRUE; -#endif +#endif // endif } /* Handle glomming separately */ @@ -6039,7 +5966,6 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) continue; } - /* Extract software header fields */ chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); @@ -6132,7 +6058,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) } else if (DHD_HDRS_ON()) { prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); } -#endif +#endif // endif if (chan == SDPCM_CONTROL_CHANNEL) { if (bus->bus == SPI_BUS) { @@ -6199,7 +6125,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if (DHD_BYTES_ON() || DHD_HDRS_ON()) { prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); } -#endif +#endif // endif /* Extract hardware header fields */ len = ltoh16_ua(bus->rxhdr); @@ -6362,7 +6288,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if (DHD_BYTES_ON() && DHD_DATA_ON()) { prhex("Rx Data", PKTDATA(osh, pkt), len); } -#endif +#endif // endif deliver: /* Save superframe descriptor and allocate packet frame */ @@ -6374,7 +6300,7 @@ deliver: if (DHD_GLOM_ON()) { prhex("Glom Data", PKTDATA(osh, pkt), len); } -#endif +#endif // endif PKTSETLEN(osh, pkt, len); ASSERT(doff == SDPCM_HDRLEN); PKTPULL(osh, pkt, SDPCM_HDRLEN); @@ -6707,10 +6633,14 @@ dhdsdio_dpc(dhd_bus_t *bus) goto exit; } } -#endif +#endif // endif } +#ifdef DHD_UCODE_DOWNLOAD +exit_ucode: +#endif /* DHD_UCODE_DOWNLOAD */ + /* Just being here means nothing more to do for chipactive */ if (intstatus & I_CHIPACTIVE) { /* ASSERT(bus->clkstate == CLK_AVAIL); */ @@ -6804,7 +6734,7 @@ clkwait: #ifdef PROP_TXSTATUS dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE); -#endif +#endif // endif if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) dhdsdio_sendpendctl(bus); @@ -7107,7 +7037,7 @@ dhdsdio_pktgen(dhd_bus_t *bus) data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN); } -#endif +#endif // endif /* Send it */ if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) { @@ -7159,7 +7089,6 @@ dhdsdio_sdtest_set(dhd_bus_t *bus, uint count) bus->pktgen_fail++; } - static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) { @@ -7278,7 +7207,7 @@ int dhd_bus_oob_intr_register(dhd_pub_t *dhdp) #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus); -#endif +#endif // endif return err; } @@ -7286,14 +7215,14 @@ void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp) { #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) bcmsdh_oob_intr_unregister(dhdp->bus->sdh); -#endif +#endif // endif } void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable) { #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) bcmsdh_oob_intr_set(dhdp->bus->sdh, enable); -#endif +#endif // endif } void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub) @@ -7391,17 +7320,17 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) #ifdef DHD_DEBUG /* Poll for console output periodically */ - if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) { + if (dhdp->busstate == DHD_BUS_DATA && dhdp->dhd_console_ms != 0) { bus->console.count += dhd_watchdog_ms; - if (bus->console.count >= dhd_console_ms) { - bus->console.count -= dhd_console_ms; + if (bus->console.count >= dhdp->dhd_console_ms) { + bus->console.count -= dhdp->dhd_console_ms; /* Make sure backplane clock is on */ if (SLPAUTO_ENAB(bus)) dhdsdio_bussleep(bus, FALSE); else dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); if (dhdsdio_readconsole(bus) < 0) - dhd_console_ms = 0; /* On error, stop trying */ + dhdp->dhd_console_ms = 0; /* On error, stop trying */ } } #endif /* DHD_DEBUG */ @@ -7417,7 +7346,7 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) bus->pktgen_tick = 0; dhdsdio_pktgen(bus); } -#endif +#endif // endif /* On idle timeout clear activity flag and/or turn off clock */ #ifdef DHD_USE_IDLECOUNT @@ -7477,7 +7406,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) DHD_LINUX_GENERAL_LOCK(dhdp, flags); DHD_BUS_BUSY_CLEAR_IN_WD(dhdp); - dhd_os_busbusy_wake(dhdp); DHD_LINUX_GENERAL_UNLOCK(dhdp, flags); return bus->ipend; @@ -7545,7 +7473,7 @@ done: return rv; } -#ifdef DHD_DEBUG +#if defined(DHD_DEBUG) && !defined(BCMSDIOLITE) static void dhd_dump_cis(uint fn, uint8 *cis) { @@ -7578,38 +7506,10 @@ dhd_dump_cis(uint fn, uint8 *cis) static bool dhdsdio_chipmatch(uint16 chipid) { - if (chipid == BCM4336_CHIP_ID) - return TRUE; - if (chipid == BCM4330_CHIP_ID) - return TRUE; - if (chipid == BCM43237_CHIP_ID) - return TRUE; - if (chipid == BCM43362_CHIP_ID) - return TRUE; - if (chipid == BCM4314_CHIP_ID) - return TRUE; - if (chipid == BCM43242_CHIP_ID) - return TRUE; - if (chipid == BCM43340_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 == BCM4339_CHIP_ID) return TRUE; - if (chipid == BCM43349_CHIP_ID) - return TRUE; if (BCM4345_CHIP(chipid)) return TRUE; if (chipid == BCM4350_CHIP_ID) @@ -7618,18 +7518,15 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4358_CHIP_ID) return TRUE; - if (chipid == BCM43569_CHIP_ID) - return TRUE; if (chipid == BCM43430_CHIP_ID) return TRUE; if (chipid == BCM43018_CHIP_ID) return TRUE; if (BCM4349_CHIP(chipid)) return TRUE; - if (BCM4347_CHIP(chipid)) - return TRUE; if (chipid == BCM4364_CHIP_ID) return TRUE; + if (chipid == BCM43012_CHIP_ID) return TRUE; @@ -7652,7 +7549,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, } mutex_lock(&_dhd_sdio_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ -#endif +#endif // endif /* Init global variables at run-time, not as part of the declaration. * This is required to support init/de-init of the driver. Initialization @@ -7687,7 +7584,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid)); /* We make assumptions about address window mappings */ - ASSERT((uintptr)regsva == SI_ENUM_BASE); + ASSERT((uintptr)regsva == si_enum_base(devid)); /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start * means early parse could fail, so here we should get either an ID @@ -7737,7 +7634,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */ #ifdef BT_OVER_SDIO bus->bt_use_count = 0; -#endif +#endif // endif #if defined(SUPPORT_P2P_GO_PS) init_waitqueue_head(&bus->bus_sleep); @@ -7754,10 +7651,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__)); goto fail; } -#if defined(BT_OVER_SDIO) - g_dhd_pub = bus->dhd; - DHD_ERROR(("%s: g_dhd_pub %p\n", __FUNCTION__, g_dhd_pub)); -#endif /* defined (BT_OVER_SDIO) */ /* Allocate buffers */ if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { @@ -7821,11 +7714,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, #ifdef BCMHOST_XTAL_PU_TIME_MOD bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11); -#ifdef BCM4330_CHIP - bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x0000F801); -#else bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001); -#endif /* BCM4330_CHIP */ #endif /* BCMHOST_XTAL_PU_TIME_MOD */ #if defined(MULTIPLE_SUPPLICANT) @@ -7833,7 +7722,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, mutex_unlock(&_dhd_sdio_mutex_lock_); DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -#endif +#endif // endif return bus; @@ -7846,289 +7735,11 @@ forcereturn: mutex_unlock(&_dhd_sdio_mutex_lock_); DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -#endif +#endif // endif 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) @@ -8141,26 +7752,23 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, int32 value; int err = 0; - bus->alp_only = TRUE; bus->sih = NULL; /* Return the window to backplane enumeration space for core access */ - if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) { + if (dhdsdio_set_siaddr_window(bus, si_enum_base(devid))) { DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__)); } #if defined(DHD_DEBUG) && !defined(CUSTOMER_HW4_DEBUG) DHD_ERROR(("F1 signature read @0x18000000=0x%4x\n", - bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4))); + bcmsdh_reg_read(bus->sdh, si_enum_base(devid), 4))); #endif /* DHD_DEBUG && !CUSTOMER_HW4_DEBUG */ #ifndef BCMSPI /* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */ /* Force PLL off until si_attach() programs PLL control regs */ - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); if (!err) clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); @@ -8188,7 +7796,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, #else numfn = 0; /* internally func is hardcoded to 1 as gSPI has cis on F1 only */ #endif /* !BCMSPI */ - +#ifndef BCMSDIOLITE for (fn = 0; fn <= numfn; fn++) { if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); @@ -8226,7 +7834,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, } #endif /* DHD_DEBUG */ } - +#else + BCM_REFERENCE(cis); + BCM_REFERENCE(fn); +#endif /* DHD_DEBUG */ while (fn-- > 0) { ASSERT(cis[fn]); MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); @@ -8248,12 +7859,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg)); #endif /* DHD_DEBUG */ -#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)) { @@ -8267,12 +7872,8 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, else bus->kso = TRUE; - if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) { - } - si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength); - /* Get info on the ARM and SOCRAM cores... */ if (!DHD_NOPMU(bus)) { if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) || @@ -8299,13 +7900,11 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, switch ((uint16)bus->sih->chip) { case BCM4335_CHIP_ID: case BCM4339_CHIP_ID: - case BCM43349_CHIP_ID: bus->dongle_ram_base = CR4_4335_RAM_BASE; break; case BCM4350_CHIP_ID: case BCM4354_CHIP_ID: case BCM4358_CHIP_ID: - case BCM43569_CHIP_ID: bus->dongle_ram_base = CR4_4350_RAM_BASE; break; case BCM4360_CHIP_ID: @@ -8323,9 +7922,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, case BCM4364_CHIP_ID: bus->dongle_ram_base = CR4_4364_RAM_BASE; break; - case BCM4347_CHIP_GRPID: - bus->dongle_ram_base = CR4_4347_RAM_BASE; - break; default: bus->dongle_ram_base = 0; DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n", @@ -8343,11 +7939,18 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, } /* ...but normally deal with the SDPCMDEV core */ +#ifdef BCMSDIOLITE + if (!(bus->regs = si_setcore(bus->sih, CC_CORE_ID, 0))) { + DHD_ERROR(("%s: failed to find Chip Common core!\n", __FUNCTION__)); + goto fail; + } +#else if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) && !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) { DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__)); goto fail; } +#endif // endif bus->sdpcmrev = si_corerev(bus->sih); /* Set core control so an SDIO reset does a backplane reset */ @@ -8367,7 +7970,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, } #endif /* BCMSPI */ - pktq_init(&bus->txq, (PRIOMASK + 1), QLEN); /* Locate an appropriately-aligned portion of hdrbuf */ @@ -8439,8 +8041,6 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) dhdsdio_pktgen_init(bus); #endif /* SDTEST */ - /* set PMU minimum resource mask to default */ - dhd_bus_set_default_min_res_mask(bus); #ifndef BCMSPI /* Disable F2 to clear any intermediate frame state on the dongle */ bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); @@ -8583,6 +8183,9 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh) ASSERT(osh); if (bus->dhd) { +#if defined(DEBUGGER) || defined(DHD_DSCOPE) + debugger_close(); +#endif /* DEBUGGER || DHD_DSCOPE */ dongle_isolation = bus->dhd->dongle_isolation; dhd_detach(bus->dhd); } @@ -8602,7 +8205,7 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh) #ifdef DHD_DEBUG if (bus->console.buf != NULL) MFREE(osh, bus->console.buf, bus->console.bufsize); -#endif +#endif // endif #ifdef DHDENABLE_TAILPAD if (bus->pad_pkt) @@ -8626,7 +8229,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) if (bus->rxbuf) { #ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->rxbuf, bus->rxblen); -#endif +#endif // endif bus->rxctl = bus->rxbuf = NULL; bus->rxlen = 0; } @@ -8634,7 +8237,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) if (bus->databuf) { #ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->databuf, MAX_DATA_BUF); -#endif +#endif // endif bus->databuf = NULL; } @@ -8645,7 +8248,6 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) } - static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag) { @@ -8694,8 +8296,7 @@ dhdsdio_disconnect(void *ptr) } mutex_lock(&_dhd_sdio_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ -#endif - +#endif // endif if (bus) { ASSERT(bus->dhd); @@ -8711,7 +8312,6 @@ dhdsdio_disconnect(void *ptr) #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ #endif /* LINUX */ - DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); } @@ -8819,7 +8419,6 @@ dhdsdio_resume(void *context) return 0; } - /* Register/Unregister functions are called by the main DHD entry * point (e.g. module insertion) to link with the bus driver, in * order to look for or await the device. @@ -8861,96 +8460,6 @@ void dhd_bus_unreg_sdio_notify(void) } #endif /* defined(BCMLXSDMMC) */ -#ifdef BCMEMBEDIMAGE -static int -dhdsdio_download_code_array(struct dhd_bus *bus) -{ - int bcmerror = -1; - int offset = 0; - unsigned char *ularray = NULL; - - DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__)); - - /* 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) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - - offset += MEMBLOCK; - } - - if (offset < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, TRUE, offset, - (uint8 *) (dlarray + offset), sizeof(dlarray) - offset); - if (bcmerror) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); - goto err; - } - } - -#ifdef DHD_DEBUG - /* Upload and compare the downloaded code */ - { - ularray = MALLOC(bus->dhd->osh, bus->ramsize); - /* Upload image to verify downloaded contents. */ - offset = 0; - memset(ularray, 0xaa, bus->ramsize); - while ((offset + MEMBLOCK) < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - - offset += MEMBLOCK; - } - - if (offset < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, FALSE, offset, - ularray + offset, sizeof(dlarray) - offset); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); - goto err; - } - } - - if (memcmp(dlarray, ularray, sizeof(dlarray))) { - DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n", - __FUNCTION__, dlimagename, dlimagever, dlimagedate)); - goto err; - } else - DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n", - __FUNCTION__, dlimagename, dlimagever, dlimagedate)); - - } -#endif /* DHD_DEBUG */ - -err: - if (ularray) - MFREE(bus->dhd->osh, ularray, bus->ramsize); - return bcmerror; -} -#endif /* BCMEMBEDIMAGE */ - static int dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) { @@ -8963,11 +8472,11 @@ dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) #ifdef DHD_DEBUG_DOWNLOADTIME unsigned long initial_jiffies = 0; uint firmware_sz = 0; -#endif +#endif // endif DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path)); - image = dhd_os_open_image(pfw_path); + image = dhd_os_open_image1(bus->dhd, pfw_path); if (image == NULL) goto err; @@ -8986,7 +8495,7 @@ dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) #ifdef DHD_DEBUG_DOWNLOADTIME initial_jiffies = jiffies; -#endif +#endif // endif /* Download image */ while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) { @@ -9016,20 +8525,20 @@ dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) offset += memblock_size; #ifdef DHD_DEBUG_DOWNLOADTIME firmware_sz += len; -#endif +#endif // endif } #ifdef DHD_DEBUG_DOWNLOADTIME DHD_ERROR(("Firmware download time for %u bytes: %u ms\n", firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies))); -#endif +#endif // endif err: if (memblock) MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN); if (image) - dhd_os_close_image(image); + dhd_os_close_image1(bus->dhd, image); return bcmerror; } @@ -9066,13 +8575,13 @@ dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path) #ifdef DHD_DEBUG_DOWNLOADTIME unsigned long initial_jiffies = 0; uint firmware_sz = 0; -#endif +#endif // endif DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, ucode_path)); ucode_base = dhdsdio_ucode_base(bus); - image = dhd_os_open_image(ucode_path); + image = dhd_os_open_image1(bus->dhd, ucode_path); if (image == NULL) goto err; @@ -9091,7 +8600,7 @@ dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path) #ifdef DHD_DEBUG_DOWNLOADTIME initial_jiffies = jiffies; -#endif +#endif // endif /* Download image */ while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, image))) { @@ -9111,23 +8620,23 @@ dhdsdio_download_ucode_file(struct dhd_bus *bus, char *ucode_path) offset += memblock_size; #ifdef DHD_DEBUG_DOWNLOADTIME firmware_sz += len; -#endif +#endif // endif } #ifdef DHD_DEBUG_DOWNLOADTIME DHD_ERROR(("ucode download time for %u bytes: %u ms\n", firmware_sz, jiffies_to_msecs(jiffies - initial_jiffies))); -#endif +#endif // endif err: if (memblock) MFREE(bus->dhd->osh, memblock, memblock_size + DHD_SDALIGN); if (image) - dhd_os_close_image(image); + dhd_os_close_image1(bus->dhd, image); return bcmerror; -} +} /* dhdsdio_download_ucode_file */ void dhd_bus_ucode_download(struct dhd_bus *bus) @@ -9176,7 +8685,7 @@ dhdsdio_download_nvram(struct dhd_bus *bus) /* For Get nvram from UEFI */ if (nvram_file_exists) - image = dhd_os_open_image(pnv_path); + image = dhd_os_open_image1(bus->dhd, pnv_path); memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE); if (memblock == NULL) { @@ -9214,7 +8723,7 @@ err: MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE); if (image) - dhd_os_close_image(image); + dhd_os_close_image1(bus->dhd, image); return bcmerror; } @@ -9229,11 +8738,7 @@ _dhdsdio_download_firmware(struct dhd_bus *bus) /* Out immediately if no image to download */ if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else return 0; -#endif } /* Keep arm in reset */ @@ -9246,29 +8751,14 @@ _dhdsdio_download_firmware(struct dhd_bus *bus) if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { if (dhdsdio_download_code_file(bus, bus->fw_path)) { DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__)); -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else goto err; -#endif } else { embed = FALSE; dlok = TRUE; } } -#ifdef BCMEMBEDIMAGE - if (embed) { - if (dhdsdio_download_code_array(bus)) { - DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__)); - goto err; - } else { - dlok = TRUE; - } - } -#else BCM_REFERENCE(embed); -#endif if (!dlok) { DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__)); goto err; @@ -9391,10 +8881,10 @@ dhd_bus_pub(struct dhd_bus *bus) return bus->dhd; } -const void * +void * dhd_bus_sih(struct dhd_bus *bus) { - return (const void *)bus->sih; + return (void *)bus->sih; } void * @@ -9501,7 +8991,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) /* Attempt to re-attach & download */ if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh, - (uint32 *)SI_ENUM_BASE, + (uint32 *)(uintptr)si_enum_base(bus->cl_devid), bus->cl_devid)) { DHD_LINUX_GENERAL_LOCK(bus->dhd, flags); @@ -9527,7 +9017,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) #if !defined(IGNORE_ETH0_DOWN) /* Restore flow control */ dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF); -#endif +#endif // endif dhd_os_wd_timer(dhdp, dhd_watchdog_ms); DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); @@ -9612,76 +9102,8 @@ 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) -/* Just print chip revision for BCM4330 */ -static int -concate_revision_bcm4330(dhd_bus_t *bus) -{ - uint chipver; - chipver = bus->sih->chiprev; - - if (chipver == 3) - DHD_ERROR(("---- CHIP bcm4330 B1 ----\n")); - else if (chipver == 4) - DHD_ERROR(("---- CHIP bcm4330 B2 ----\n")); - else - DHD_ERROR(("----- Invalid chip version -----\n")); - return 0; -} - -static int -concate_revision_bcm4334(dhd_bus_t *bus, char *fw_path, char *nv_path) -{ -#define REV_ID_ADDR 0x1E008F90 -#define BCM4334_B1_UNIQUE 0x30312E36 - - uint chipver; - uint32 unique_id; - uint8 data[4]; -#if defined(SUPPORT_MULTIPLE_CHIPS) - char chipver_tag[10] = "_4334"; -#else - char chipver_tag[4] = ""; -#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ - - DHD_TRACE(("%s: BCM4334 Multiple Revision Check\n", __FUNCTION__)); - if (bus->sih->chip != BCM4334_CHIP_ID) { - DHD_ERROR(("%s:Chip is not BCM4334\n", __FUNCTION__)); - return -1; - } - chipver = bus->sih->chiprev; - if (chipver == 0x2) { - dhdsdio_membytes(bus, FALSE, REV_ID_ADDR, data, 4); - unique_id = load32_ua(data); - if (unique_id == BCM4334_B1_UNIQUE) - chipver = 0x01; - } - - DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); - if (chipver == 1) { - DHD_ERROR(("----- CHIP bcm4334_B0 -----\n")); - strcat(chipver_tag, "_b0"); - } else if (chipver == 2) { - DHD_ERROR(("----- CHIP bcm4334_B1 -----\n")); - strcat(chipver_tag, "_b1"); - } else if (chipver == 3) { - DHD_ERROR(("----- CHIP bcm4334_B2 -----\n")); - strcat(chipver_tag, "_b2"); - } else { - DHD_ERROR(("----- Invalid chip version -----\n")); - return -1; - } - - strcat(fw_path, chipver_tag); -#if defined(SUPPORT_MULTIPLE_CHIPS) - strcat(nv_path, chipver_tag); -#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ - -#undef REV_ID_ADDR -#undef BCM4334_B1_UNIQUE - return 0; -} +#if defined(SUPPORT_MULTIPLE_REVISION) static int concate_revision_bcm4335(dhd_bus_t *bus, char *fw_path, char *nv_path) { @@ -9746,64 +9168,6 @@ concate_revision_bcm4339(dhd_bus_t *bus, char *fw_path, char *nv_path) return 0; } -static int -concate_revision_bcm43349(dhd_bus_t *bus, char *fw_path, char *nv_path) -{ - uint chipver; -#if defined(SUPPORT_MULTIPLE_CHIPS) - char chipver_tag[10] = "_43349"; -#else - char chipver_tag[4] = {0, }; -#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ - - DHD_TRACE(("%s: BCM43349 Multiple Revision Check\n", __FUNCTION__)); - if (bus->sih->chip != BCM43349_CHIP_ID) { - DHD_ERROR(("%s:Chip is not BCM43349\n", __FUNCTION__)); - return -1; - } - chipver = bus->sih->chiprev; - DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); - if (chipver == 0x1) { - DHD_ERROR(("----- CHIP bcm43349_A0 -----\n")); - strcat(chipver_tag, "_a0"); - } else { - DHD_ERROR(("----- CHIP bcm43349 unknown revision %d -----\n", chipver)); - } - - strcat(fw_path, chipver_tag); - strcat(nv_path, chipver_tag); - return 0; -} - -static int concate_revision_bcm43241(dhd_bus_t *bus, char *fw_path, char *nv_path) -{ - uint32 chip_ver; -#if defined(SUPPORT_MULTIPLE_CHIPS) - char chipver_tag[10] = "_43241"; -#else - char chipver_tag[4] = {0, }; -#endif /* defined(SUPPORT_MULTIPLE_CHIPS) */ - - DHD_TRACE(("%s: BCM43241 Multiple Revision Check\n", __FUNCTION__)); - - chip_ver = bus->sih->chiprev; - - if (chip_ver == 2) { - DHD_ERROR(("----- CHIP bcm43241_B0 -----\n")); - strcat(chipver_tag, "_b0"); - } else if (chip_ver == 5) { - DHD_ERROR(("----- CHIP bcm43241_B4 -----\n")); - strcat(chipver_tag, "_b4"); - } else { - DHD_ERROR(("----- Invalid chip version -----\n")); - return -1; - } - - strcat(fw_path, chipver_tag); - strcat(nv_path, chipver_tag); - return 0; -} - static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path) { uint32 chip_ver; @@ -9819,7 +9183,7 @@ static int concate_revision_bcm4350(dhd_bus_t *bus, char *fw_path, char *nv_path strcat(chipver_tag, "_4354"); else strcat(chipver_tag, "_4350"); -#endif +#endif // endif if (chip_ver == 3) { DHD_ERROR(("----- CHIP 4354 A0 -----\n")); @@ -9862,29 +9226,6 @@ static int concate_revision_bcm4354(dhd_bus_t *bus, char *fw_path, char *nv_path return 0; } -#ifdef SUPPORT_MULTIPLE_CHIP_4345X -static int -concate_revision_bcm4345x(dhd_bus_t *bus, - char *fw_path, char *nv_path) -{ - uint32 chip_id; - char chipver_tag[10] = "_43454"; - - chip_id = bus->sih->chip; - - if (chip_id == BCM43454_CHIP_ID) { - DHD_ERROR(("----- CHIP 43454 -----\n")); - strcat(fw_path, chipver_tag); - strcat(nv_path, chipver_tag); - } else if (chip_id == BCM4345_CHIP_ID) { - DHD_ERROR(("----- CHIP 43455 -----\n")); - } else { - DHD_ERROR(("----- Unknown chip , id r=%x -----\n", chip_id)); - } - - return 0; -} -#else /* SUPPORT_MULTIPLE_CHIP_4345X */ static int concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path) { @@ -9917,73 +9258,6 @@ concate_revision_bcm43454(dhd_bus_t *bus, char *fw_path, char *nv_path) return 0; } -static int -concate_revision_bcm43455(dhd_bus_t *bus, char *fw_path, char *nv_path) -{ - char chipver_tag[10] = {0, }; - uint32 chip_rev = 0; -#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT - int base_system_rev_for_nv = 0; -#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ - - DHD_TRACE(("%s: BCM43455 Multiple Revision Check\n", __FUNCTION__)); - if (bus->sih->chip != BCM4345_CHIP_ID) { - DHD_ERROR(("%s:Chip is not BCM43455!\n", __FUNCTION__)); - return -1; - } - - chip_rev = bus->sih->chiprev; - if (chip_rev == 0x9) { - DHD_ERROR(("----- CHIP 43456 -----\n")); - strcat(fw_path, "_c5"); - strcat(nv_path, "_c5"); - } else { - DHD_ERROR(("----- CHIP 43455 -----\n")); - } -#ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT - base_system_rev_for_nv = dhd_get_system_rev(); - if (base_system_rev_for_nv > 0) { - DHD_ERROR(("----- Board Rev [%d]-----\n", base_system_rev_for_nv)); - sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv); - } -#endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */ - strcat(nv_path, chipver_tag); - return 0; -} -#endif /* SUPPORT_MULTIPLE_CHIP_4345X */ - -static int -concate_revision_bcm43430(dhd_bus_t *bus, char *fw_path, char *nv_path) -{ - - uint chipver; - char chipver_tag[4] = {0, }; - - DHD_TRACE(("%s: BCM43430 Multiple Revision Check\n", __FUNCTION__)); - if (bus->sih->chip != BCM43430_CHIP_ID) { - DHD_ERROR(("%s:Chip is not BCM43430\n", __FUNCTION__)); - return BCME_ERROR; - } - chipver = bus->sih->chiprev; - DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); - if (chipver == 0x0) { - DHD_ERROR(("----- CHIP bcm4343S -----\n")); - strcat(chipver_tag, "_3s"); - } else if (chipver == 0x1) { - DHD_ERROR(("----- CHIP bcm43438 -----\n")); - } else if (chipver == 0x2) { - DHD_ERROR(("----- CHIP bcm43436L -----\n")); - strcat(chipver_tag, "_36"); - } else { - DHD_ERROR(("----- CHIP bcm43430 unknown revision %d -----\n", - chipver)); - } - - strcat(fw_path, chipver_tag); - strcat(nv_path, chipver_tag); - return 0; -} - int concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path) { @@ -9995,46 +9269,23 @@ concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path) } switch (bus->sih->chip) { - case BCM4330_CHIP_ID: - res = concate_revision_bcm4330(bus); - break; - case BCM4334_CHIP_ID: - res = concate_revision_bcm4334(bus, fw_path, nv_path); - break; case BCM4335_CHIP_ID: res = concate_revision_bcm4335(bus, fw_path, nv_path); + break; case BCM4339_CHIP_ID: res = concate_revision_bcm4339(bus, fw_path, nv_path); break; - case BCM43349_CHIP_ID: - res = concate_revision_bcm43349(bus, fw_path, nv_path); - break; - case BCM4324_CHIP_ID: - res = concate_revision_bcm43241(bus, fw_path, nv_path); - break; case BCM4350_CHIP_ID: res = concate_revision_bcm4350(bus, fw_path, nv_path); break; case BCM4354_CHIP_ID: res = concate_revision_bcm4354(bus, fw_path, nv_path); break; -#ifdef SUPPORT_MULTIPLE_CHIP_4345X - case BCM43454_CHIP_ID: - case BCM4345_CHIP_ID: - res = concate_revision_bcm4345x(bus, fw_path, nv_path); - break; -#else /* SUPPORT_MULTIPLE_CHIP_4345X */ case BCM43454_CHIP_ID: res = concate_revision_bcm43454(bus, fw_path, nv_path); break; - case BCM4345_CHIP_ID: - res = concate_revision_bcm43455(bus, fw_path, nv_path); - break; -#endif /* SUPPORT_MULTIPLE_CHIP_4345X */ - case BCM43430_CHIP_ID: - res = concate_revision_bcm43430(bus, fw_path, nv_path); - break; + default: DHD_ERROR(("REVISION SPECIFIC feature is not required\n")); return res; @@ -10046,7 +9297,6 @@ concate_revision(dhd_bus_t *bus, char *fw_path, char *nv_path) } #endif /* SUPPORT_MULTIPLE_REVISION */ - void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path) { @@ -10097,7 +9347,7 @@ dhd_bus_pktq_flush(dhd_pub_t *dhdp) #ifdef PROP_TXSTATUS wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED); -#endif +#endif // endif if (!wlfc_enabled) { #ifdef DHDTCPACK_SUPPRESS /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt, @@ -10135,10 +9385,10 @@ dhd_get_chipid(dhd_pub_t *dhd) #endif /* BCMSDIO */ #ifdef DEBUGGER -uint32 dhd_sdio_reg_read(void *h, uint32 addr) +static uint32 +dhd_sdio_reg_read(struct dhd_bus *bus, ulong addr) { uint32 rval; - struct dhd_bus *bus = (struct dhd_bus *) h; dhd_os_sdlock(bus->dhd); @@ -10153,10 +9403,9 @@ uint32 dhd_sdio_reg_read(void *h, uint32 addr) return rval; } -void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val) +static void +dhd_sdio_reg_write(struct dhd_bus *bus, ulong addr, uint32 val) { - struct dhd_bus *bus = (struct dhd_bus *) h; - dhd_os_sdlock(bus->dhd); BUS_WAKE(bus); @@ -10170,7 +9419,6 @@ void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val) #endif /* DEBUGGER */ - #if defined(BT_OVER_SDIO) uint8 dhd_bus_cfg_read(void *h, uint fun_num, uint32 addr, int *err) { @@ -10272,14 +9520,13 @@ _dhdsdio_download_btfw(struct dhd_bus *bus) void *image = NULL; uint8 *mem_blk = NULL, *mem_ptr = NULL, *data_ptr = NULL; - uint32 offset_addr = 0, offset_len = 0, bytes_to_write = 0; char *line = NULL; uint32 dest_addr = 0, num_bytes; uint16 hiAddress = 0; - uint32 start_addr, start_data, end_addr, end_data, i, index, pad; - uint32 bt2wlan_pwrup_adr; + uint32 start_addr, start_data, end_addr, end_data, i, index, pad, + bt2wlan_pwrup_adr; int addr_mode = BTFW_ADDR_MODE_EXTENDED; @@ -10288,7 +9535,7 @@ _dhdsdio_download_btfw(struct dhd_bus *bus) return 0; } - image = dhd_os_open_image(bus->btfw_path); + image = dhd_os_open_image1(bus->dhd, bus->btfw_path); if (image == NULL) goto err; @@ -10402,7 +9649,7 @@ err: MFREE(bus->dhd->osh, line, BTFW_MAX_STR_LEN); if (image) - dhd_os_close_image(image); + dhd_os_close_image1(bus->dhd, image); return bcm_error; } @@ -10483,7 +9730,7 @@ dhd_bus_set_default_min_res_mask(struct dhd_bus *bus) switch (bus->sih->chip) { case BCM4339_CHIP_ID: - bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE + 0x618, 4, 0x3fcaf377); + bcmsdh_reg_write(bus->sdh, SI_ENUM_BASE(bus->sih) + 0x618, 4, 0x3fcaf377); if (bcmsdh_regfail(bus->sdh)) { DHD_ERROR(("%s:%d Setting min_res_mask failed\n", __FUNCTION__, __LINE__)); return FALSE; @@ -10520,8 +9767,8 @@ dhd_bus_pmu_reg_reset(dhd_pub_t *dhdp) } } - #ifdef DHD_ULP + /* Function to disable console messages on entering ULP mode */ void dhd_bus_ulp_disable_console(dhd_pub_t *dhdp) @@ -10534,7 +9781,7 @@ dhd_bus_ulp_disable_console(dhd_pub_t *dhdp) /* Flush the console buffer before disabling */ dhdsdio_readconsole(dhdp->bus); - dhd_console_ms = 0; + dhdp->dhd_console_ms = 0; #endif /* DHD_DEBUG */ } @@ -10608,9 +9855,6 @@ int dhd_get_idletime(dhd_pub_t *dhd) wake_counts_t* dhd_bus_get_wakecount(dhd_pub_t *dhd) { - if (!dhd->bus) { - return NULL; - } return &dhd->bus->wake_counts; } int diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd_oo/dhd_sec_feature.h index a28e64efc6922f0c2ca2ff41ea1063772015f79c..4a893005f506aa84e8447ba66c2ef4643a4ba9ad 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_sec_feature.h @@ -1,14 +1,14 @@ /* * Customer HW 4 dependant file * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -27,7 +27,6 @@ * $Id: dhd_sec_feature.h$ */ - /* * ** Desciption *** * 1. Module vs COB @@ -71,11 +70,6 @@ #define READ_MACADDR #endif /* CONFIG_WIFI_BROADCOM_COB */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (defined(CONFIG_BCM4334) || \ - defined(CONFIG_BCM4334_MODULE)) -#define RXFRAME_THREAD -#endif /* (LINUX_VERSION >= VERSION(3, 4, 0)) && ( CONFIG_BCM4334 || CONFIG_BCM4334_MODULE) */ - #if defined(CONFIG_SEC_TRLTE_PROJECT) #define SUPPORT_MULTIPLE_BOARD_REV #endif /* CONFIG_SEC_TRLTE_PROJECT */ @@ -94,11 +88,12 @@ #ifdef BCMPCIE /* For EXYNOS PCIe RC Control */ #if defined(CONFIG_MACH_UNIVERSAL5433) || defined(CONFIG_MACH_UNIVERSAL7420) || \ - defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) + defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) #define EXYNOS_PCIE_LINKDOWN_RECOVERY #define USE_EXYNOS_PCIE_RC_PMPATCH #endif /* CONFIG_MACH_UNIVERSAL5433 || CONFIGA_MACH_UNIVERSAL7420 || - * CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 + * CONFIG_SOC_EXYNOS8890 || CONFIG_SOC_EXYNOS8895 || CONFIG_SOC_EXYNOS9810 */ #endif /* BCMPCIE */ @@ -113,13 +108,13 @@ #define ARGOS_P2P_TABLE_LABEL "P2P" #endif /* CONFIG_ARGOS */ -#if defined(CONFIG_ARCH_MSM8998) #ifndef DHD_LB_IRQSET +#if defined(CONFIG_ARCH_MSM8998) #define SET_PCIE_IRQ_CPU_CORE #define PCIE_IRQ_BIG_CORE 6 #define PCIE_IRQ_LITTLE_CORE 0 +#endif // endif #endif /* DHD_LB_IRQSET */ -#endif /* CONFIG_ARCH_MSM8998 */ /* PROJECTS START */ @@ -134,8 +129,7 @@ #define DPC_CPUCORE 4 #define RXF_CPUCORE 7 #define ARGOS_CPU_SCHEDULER -#elif (defined(CONFIG_MACH_UNIVERSAL5430) || defined(CONFIG_MACH_UNIVERSAL5433)) && \ - defined(CONFIG_BCM43455) +#elif defined(CONFIG_MACH_UNIVERSAL5430) && defined(CONFIG_BCM43455) #define CUSTOM_SET_CPUCORE #define PRIMARY_CPUCORE 0 #define MAX_RETRY_SET_CPUCORE 5 @@ -147,20 +141,6 @@ #define MAX_RETRY_SET_CPUCORE 5 #define DPC_CPUCORE 1 #define RXF_CPUCORE 2 -#elif defined(CONFIG_SOC_EXYNOS7870) && defined(CONFIG_BCM43455) -#define CUSTOM_SET_CPUCORE -#define PRIMARY_CPUCORE 0 -#define MAX_RETRY_SET_CPUCORE 5 -#define DPC_CPUCORE 1 -#define RXF_CPUCORE 2 -#define ARGOS_CPU_SCHEDULER -#elif defined(CONFIG_SOC_EXYNOS7870) && defined(CONFIG_BCM43456) -#define CUSTOM_SET_CPUCORE -#define PRIMARY_CPUCORE 0 -#define MAX_RETRY_SET_CPUCORE 5 -#define DPC_CPUCORE 1 -#define RXF_CPUCORE 2 -#define ARGOS_CPU_SCHEDULER #elif defined(CONFIG_MACH_UNIVERSAL5433) || defined(CONFIG_MACH_UNIVERSAL7420) || \ defined(CONFIG_SOC_EXYNOS8890) || defined(CONFIG_SOC_EXYNOS8895) #undef CUSTOM_SET_CPUCORE @@ -168,9 +148,7 @@ #define DPC_CPUCORE 4 #define RXF_CPUCORE 5 #define TASKLET_CPUCORE 5 -#ifndef DHD_LB_IRQSET #define ARGOS_CPU_SCHEDULER -#endif /* DHD_LB_IRQSET */ #define ARGOS_RPS_CPU_CTL #ifdef CONFIG_SOC_EXYNOS8895 @@ -214,12 +192,11 @@ #define DHD_LB_SECONDARY_CPUS (0x0E) #endif /* CONFIG_SOC_EXYNOS8890 */ #else /* !DHD_LB */ -#ifdef BCMPCIE #define ARGOS_DPC_TASKLET_CTL -#endif /* BCMPCIE */ #endif /* !DHD_LB */ -#if defined(CONFIG_ARCH_MSM) || defined(CONFIG_SOC_EXYNOS8895) +#if defined(CONFIG_ARCH_MSM) || defined(CONFIG_SOC_EXYNOS8895) || \ + defined(CONFIG_SOC_EXYNOS9810) #if defined(CONFIG_BCMDHD_PCIE) #define BCMPCIE_DISABLE_ASYNC_SUSPEND #endif /* CONFIG_BCMDHD_PCIE */ @@ -264,7 +241,6 @@ /* PROJECTS END */ - /* REGION CODE START */ #ifndef CONFIG_WLAN_REGION_CODE @@ -281,10 +257,6 @@ #endif /* CONFIG_WLAN_REGION_CODE == 150 */ #endif /* CONFIG_WLAN_REGION_CODE >= 100 && CONFIG_WLAN_REGION_CODE < 200 */ -#if defined(CONFIG_WIFI_MULTIPLE_CHIP) -#define SUPPORT_MULTIPLE_CHIP_4345X -#endif /* CONFIG_WIFI_MULTIPLE_CHIP */ - #if defined(CONFIG_V1A) || defined(CONFIG_V2A) || defined(CONFIG_MACH_VIENNAEUR) #define SUPPORT_MULTIPLE_CHIPS #endif /* CONFIG_V1A || CONFIG_V2A || CONFIG_MACH_VIENNAEUR */ diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.c b/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.c index b684d8cbc9995c20a7d57148c70fbc8c13c61ee2..9eaa011ae0328810c2b2c9c93b51766f780f9d6e 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.c +++ b/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.c @@ -1,14 +1,14 @@ /* * DHD PROP_TXSTATUS Module. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,11 +24,10 @@ * * <> * - * $Id: dhd_wlfc.c 735359 2017-12-08 10:56:04Z $ + * $Id: dhd_wlfc.c 735303 2017-12-08 06:20:29Z $ * */ - #include #include @@ -45,13 +44,12 @@ #ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */ #include #include -#endif +#endif // endif #ifdef DHDTCPACK_SUPPRESS #include #endif /* DHDTCPACK_SUPPRESS */ - /* * wlfc naming and lock rules: * @@ -66,12 +64,10 @@ #define WLFC_THREAD_RETRY_WAIT_MS 10000 /* 10 sec */ #endif /* defined (DHD_WLFC_THREAD) */ - #ifdef PROP_TXSTATUS #define DHD_WLFC_QMON_COMPLETE(entry) - /** reordering related */ #if defined(DHD_WLFC_THREAD) @@ -126,11 +122,10 @@ _dhd_wlfc_prec_enque(struct pktq *pq, int prec, void* p, bool qHead, ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; - PKTSETLINK(p, NULL); if (q->head == NULL) { /* empty queue */ q->head = p; @@ -184,8 +179,8 @@ _dhd_wlfc_prec_enque(struct pktq *pq, int prec, void* p, bool qHead, exit: - q->len++; - pq->len++; + q->n_pkts++; + pq->n_pkts_tot++; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; @@ -494,8 +489,12 @@ _dhd_wlfc_deque_afq(athost_wl_status_info_t* ctx, uint16 hslot, uint8 hcnt, uint } } - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); @@ -584,7 +583,6 @@ push_bdc_hdr: if (PKTSUMNEEDED(p)) h->flags |= BDC_FLAG_SUM_NEEDED; - h->priority = (PKTPRIO(p) & BDC_PRIORITY_MASK); h->flags2 = 0; h->dataOffset = dataOffset >> 2; @@ -764,12 +762,12 @@ _dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int pr /* Fast case, precedence queue is not full and we are also not * exceeding total queue length */ - if (!pktq_pfull(pq, prec) && !pktq_full(pq)) { + if (!pktqprec_full(pq, prec) && !pktq_full(pq)) { goto exit; } /* Determine precedence from which to evict packet, if any */ - if (pktq_pfull(pq, prec)) { + if (pktqprec_full(pq, prec)) { eprec = prec; } else if (pktq_full(pq)) { p = pktq_peek_tail(pq, &eprec); @@ -778,7 +776,7 @@ _dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int pr return FALSE; } if ((eprec > prec) || (eprec < 0)) { - if (!pktq_pempty(pq, prec)) { + if (!pktqprec_empty(pq, prec)) { eprec = prec; } else { return FALSE; @@ -789,7 +787,7 @@ _dhd_wlfc_prec_enq_with_drop(dhd_pub_t *dhdp, struct pktq *pq, void *pkt, int pr /* Evict if needed */ if (eprec >= 0) { /* Detect queueing to unconfigured precedence */ - ASSERT(!pktq_pempty(pq, eprec)); + ASSERT(!pktqprec_empty(pq, eprec)); /* Evict all fragmented frames */ dhd_prec_drop_pkts(dhdp, pq, eprec, _dhd_wlfc_prec_drop); } @@ -936,12 +934,12 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint if ((ctx->hostif_flow_state[if_id] == OFF) && !_dhd_wlfc_allow_fc(ctx, if_id)) return; - if ((pq->len <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { + if ((pq->n_pkts_tot <= WLFC_FLOWCONTROL_LOWATER) && (ctx->hostif_flow_state[if_id] == ON)) { /* start traffic */ ctx->hostif_flow_state[if_id] = OFF; /* WLFC_DBGMESG(("qlen:%02d, if:%02d, ->OFF, start traffic %s()\n", - pq->len, if_id, __FUNCTION__)); + pq->n_pkts_tot, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("F")); @@ -950,12 +948,12 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint ctx->toggle_host_if = 0; } - if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { + if (pq->n_pkts_tot >= WLFC_FLOWCONTROL_HIWATER && ctx->hostif_flow_state[if_id] == OFF) { /* stop traffic */ ctx->hostif_flow_state[if_id] = ON; /* WLFC_DBGMESG(("qlen:%02d, if:%02d, ->ON, stop traffic %s()\n", - pq->len, if_id, __FUNCTION__)); + pq->n_pkts_tot, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("N")); @@ -992,13 +990,13 @@ _dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descript DHD_PKTTAG_WLFCPKT_SET(PKTTAG(p), 1); #ifdef PROP_TXSTATUS_DEBUG ctx->stats.signal_only_pkts_sent++; -#endif +#endif // endif #if defined(BCMPCIE) rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx); #else rc = dhd_bus_txdata(dhdp->bus, p); -#endif +#endif // endif if (rc != BCME_OK) { _dhd_wlfc_pullheader(ctx, p); PKTFREE(ctx->osh, p, TRUE); @@ -1029,8 +1027,8 @@ _dhd_wlfc_traffic_pending_check(athost_wl_status_info_t* ctx, wlfc_mac_descripto bool rc = FALSE; if (entry->state == WLFC_STATE_CLOSE) { - if ((pktq_plen(&entry->psq, (prec << 1)) == 0) && - (pktq_plen(&entry->psq, ((prec << 1) + 1)) == 0)) { + if ((pktqprec_n_pkts(&entry->psq, (prec << 1)) == 0) && + (pktqprec_n_pkts(&entry->psq, ((prec << 1) + 1)) == 0)) { /* no packets in both 'normal' and 'suspended' queues */ if (entry->traffic_pending_bmp & NBITVAL(prec)) { rc = TRUE; @@ -1206,7 +1204,7 @@ _dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, #ifdef PROP_TXSTATUS_DEBUG h->items[hslot].push_time = OSL_SYSUPTIME(); -#endif +#endif // endif } else { DHD_ERROR(("%s() hanger_pushpkt() failed, rc: %d\n", __FUNCTION__, rc)); @@ -1345,7 +1343,7 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, int prec, entry->requested_credit--; #ifdef PROP_TXSTATUS_DEBUG entry->dstncredit_sent_packets++; -#endif +#endif // endif } else if (entry->requested_packet > 0) { entry->requested_packet--; DHD_PKTTAG_SETONETIMEPKTRQST(PKTTAG(p)); @@ -1395,7 +1393,6 @@ _dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec) return BCME_ERROR; } - /* A packet has been pushed, update traffic availability bitmap, if applicable */ _dhd_wlfc_traffic_pending_check(ctx, entry, prec); } @@ -1531,7 +1528,7 @@ _dhd_wlfc_pktq_flush(athost_wl_status_info_t* ctx, struct pktq *pq, /* Optimize flush, if pktq len = 0, just return. * pktq len of 0 means pktq's prec q's are all empty. */ - if (pq->len == 0) { + if (pq->n_pkts_tot == 0) { return; } @@ -1596,8 +1593,12 @@ _dhd_wlfc_pktq_flush(athost_wl_status_info_t* ctx, struct pktq *pq, } PKTFREE(ctx->osh, p, dir); - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + p = (head ? q->head : PKTLINK(prev)); } else { prev = p; @@ -1606,17 +1607,16 @@ _dhd_wlfc_pktq_flush(athost_wl_status_info_t* ctx, struct pktq *pq, } if (q->head == NULL) { - ASSERT(q->len == 0); + ASSERT(q->n_pkts == 0); q->tail = NULL; } } if (fn == NULL) - ASSERT(pq->len == 0); + ASSERT(pq->n_pkts_tot == 0); } /* _dhd_wlfc_pktq_flush */ - /** !BCMDBUS specific function. Dequeues a packet from the caller supplied queue. */ static void* _dhd_wlfc_pktq_pdeq_with_fn(struct pktq *pq, int prec, f_processpkt_t fn, void *arg) @@ -1653,9 +1653,13 @@ _dhd_wlfc_pktq_pdeq_with_fn(struct pktq *pq, int prec, f_processpkt_t fn, void * } } - q->len--; + q->n_pkts--; + + pq->n_pkts_tot--; - pq->len--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); @@ -1694,7 +1698,6 @@ _dhd_wlfc_cleanup_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg) } dhd_os_sdunlock_txq(dhd); - while ((pkt = head)) { head = PKTLINK(pkt); PKTSETLINK(pkt, NULL); @@ -1750,15 +1753,15 @@ _dhd_wlfc_cleanup(dhd_pub_t *dhd, f_processpkt_t fn, void *arg) for (i = 0; i < total_entries; i++) { if (table[i].occupied) { /* release packets held in PSQ (both delayed and suppressed) */ - if (table[i].psq.len) { + if (table[i].psq.n_pkts_tot) { WLFC_DBGMESG(("%s(): PSQ[%d].len = %d\n", - __FUNCTION__, i, table[i].psq.len)); + __FUNCTION__, i, table[i].psq.n_pkts_tot)); _dhd_wlfc_pktq_flush(wlfc, &table[i].psq, TRUE, fn, arg, Q_TYPE_PSQ); } /* free packets held in AFQ */ - if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.len)) { + if (WLFC_GET_AFQ(dhd->wlfc_mode) && (table[i].afq.n_pkts_tot)) { _dhd_wlfc_pktq_flush(wlfc, &table[i].afq, TRUE, fn, arg, Q_TYPE_AFQ); } @@ -1802,7 +1805,6 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* { int rc = BCME_OK; - if ((action == eWLFC_MAC_ENTRY_ACTION_ADD) || (action == eWLFC_MAC_ENTRY_ACTION_UPDATE)) { entry->occupied = 1; entry->state = WLFC_STATE_OPEN; @@ -1883,7 +1885,6 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* return rc; } /* _dhd_wlfc_mac_entry_update */ - #ifdef LIMIT_BORROW /** LIMIT_BORROW specific function */ @@ -2173,8 +2174,13 @@ dhd_wlfc_suppressed_acked_update(dhd_pub_t *dhd, uint16 hslot, uint8 prec, uint8 } } - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + ctx->pkt_cnt_in_q[DHD_PKTTAG_IF(PKTTAG(p))][prec]--; ctx->pkt_cnt_per_ac[prec]--; @@ -2234,10 +2240,12 @@ _dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len, remove_from_hanger = 0; } else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { wlfc->stats.wlc_tossed_pkts += len; - } - - else if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) { + } else if (status_flag == WLFC_CTL_PKTFLAG_SUPPRESS_ACKED) { wlfc->stats.pkt_freed += len; + } else if (status_flag == WLFC_CTL_PKTFLAG_EXPIRED) { + wlfc->stats.pkt_exptime += len; + } else if (status_flag == WLFC_CTL_PKTFLAG_DROPPED) { + wlfc->stats.pkt_dropped += len; } if (dhd->proptxstatus_txstatus_ignore) { @@ -2310,7 +2318,6 @@ _dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len, uint32 delta; old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[hslot].push_time; - wlfc->stats.latency_sample_count++; if (new_t > old_t) delta = new_t - old_t; @@ -2341,7 +2348,7 @@ _dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len, } #ifdef PROP_TXSTATUS_DEBUG entry->dstncredit_acks++; -#endif +#endif // endif } if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || @@ -2422,7 +2429,7 @@ _dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) for (i = 0; i < WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK; i++) { #ifdef PROP_TXSTATUS_DEBUG wlfc->stats.fifo_credits_back[i] += credits[i]; -#endif +#endif // endif /* update FIFO credits */ if (dhd->proptxstatus_mode == WLFC_FCMODE_EXPLICIT_CREDIT) @@ -2464,7 +2471,6 @@ _dhd_wlfc_fifocreditback_indicate(dhd_pub_t *dhd, uint8* credits) return BCME_OK; } /* _dhd_wlfc_fifocreditback_indicate */ - /** !BCMDBUS specific function */ static void _dhd_wlfc_suppress_txq(dhd_pub_t *dhd, f_processpkt_t fn, void *arg) @@ -2912,7 +2918,6 @@ int dhd_wlfc_enable(dhd_pub_t *dhd) wlfc->single_ac = 0; wlfc->single_ac_timestamp = 0; - exit: dhd_os_wlfc_unblock(dhd); @@ -3188,7 +3193,7 @@ dhd_wlfc_transfer_packets(void *data) no_credit = FALSE; } } -#endif +#endif // endif commit_info.needs_hdr = 1; commit_info.mac_entry = NULL; commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, @@ -3204,7 +3209,7 @@ dhd_wlfc_transfer_packets(void *data) if (lender != -1 && dhdp->wlfc_borrow_allowed) { _dhd_wlfc_return_credit(ctx, lender, ac); } -#endif +#endif // endif break; } @@ -3227,13 +3232,13 @@ dhd_wlfc_transfer_packets(void *data) dhdp->wlfc_borrow_allowed) { _dhd_wlfc_return_credit(ctx, lender, ac); } -#endif +#endif // endif } else { #ifdef LIMIT_BORROW if (lender != -1 && dhdp->wlfc_borrow_allowed) { _dhd_wlfc_return_credit(ctx, lender, ac); } -#endif +#endif // endif bus_retry_count++; if (bus_retry_count >= BUS_RETRIES) { DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); @@ -3306,7 +3311,7 @@ dhd_wlfc_transfer_packets(void *data) } else break; -#endif +#endif // endif commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, &(commit_info.ac_fifo_credit_spent), &(commit_info.needs_hdr), @@ -3316,7 +3321,7 @@ dhd_wlfc_transfer_packets(void *data) /* before borrow only one ac exists and now this only ac is empty */ #ifdef LIMIT_BORROW _dhd_wlfc_return_credit(ctx, lender, ac); -#endif +#endif // endif break; } @@ -3332,16 +3337,16 @@ dhd_wlfc_transfer_packets(void *data) if (commit_info.ac_fifo_credit_spent) { #ifndef LIMIT_BORROW ctx->FIFO_credit[ac]--; -#endif +#endif // endif } else { #ifdef LIMIT_BORROW _dhd_wlfc_return_credit(ctx, lender, ac); -#endif +#endif // endif } } else { #ifdef LIMIT_BORROW _dhd_wlfc_return_credit(ctx, lender, ac); -#endif +#endif // endif bus_retry_count++; if (bus_retry_count >= BUS_RETRIES) { DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); @@ -3405,7 +3410,6 @@ dhd_wlfc_commit_packets(dhd_pub_t *dhdp, f_commitpkt_t fcommit, void* commit_ctx ctx = (athost_wl_status_info_t*)dhdp->wlfc_state; - if (dhdp->proptxstatus_module_ignore) { if (pktbuf) { uint32 htod = 0; @@ -3484,7 +3488,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { #ifdef PROP_TXSTATUS_DEBUG wlfc->stats.signal_only_pkts_freed++; -#endif +#endif // endif /* is this a signal-only packet? */ _dhd_wlfc_pullheader(wlfc, txp); PKTFREE(wlfc->osh, txp, TRUE); @@ -3566,7 +3570,6 @@ dhd_wlfc_init(dhd_pub_t *dhd) WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE | WLFC_FLAGS_HOST_RXRERODER_ACTIVE; - /* try to enable/disable signaling by sending "tlv" iovar. if that fails, fallback to no flow control? Print a message for now. @@ -3615,7 +3618,7 @@ dhd_wlfc_init(dhd_pub_t *dhd) DHD_INFO(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret)); #ifdef LIMIT_BORROW dhd->wlfc_borrow_allowed = TRUE; -#endif +#endif // endif dhd_os_wlfc_unblock(dhd); if (dhd->plat_init) @@ -3766,7 +3769,6 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) _dhd_wlfc_hanger_delete(dhd, h); } - /* free top structure */ DHD_OS_PREFREE(dhd, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); @@ -3968,7 +3970,7 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) "(trans,supp_trans,onbus)" "= (%d,%s,%d),(%d,%d,%d)\n", i, - interfaces[i].psq.len, + interfaces[i].psq.n_pkts_tot, ((interfaces[i].state == WLFC_STATE_OPEN) ? "OPEN":"CLOSE"), interfaces[i].requested_credit, @@ -3981,21 +3983,21 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) "(delay3,sup3,afq3),(delay4,sup4,afq4) = (%d,%d,%d)," "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n", i, - interfaces[i].psq.q[0].len, - interfaces[i].psq.q[1].len, - interfaces[i].afq.q[0].len, - interfaces[i].psq.q[2].len, - interfaces[i].psq.q[3].len, - interfaces[i].afq.q[1].len, - interfaces[i].psq.q[4].len, - interfaces[i].psq.q[5].len, - interfaces[i].afq.q[2].len, - interfaces[i].psq.q[6].len, - interfaces[i].psq.q[7].len, - interfaces[i].afq.q[3].len, - interfaces[i].psq.q[8].len, - interfaces[i].psq.q[9].len, - interfaces[i].afq.q[4].len); + interfaces[i].psq.q[0].n_pkts, + interfaces[i].psq.q[1].n_pkts, + interfaces[i].afq.q[0].n_pkts, + interfaces[i].psq.q[2].n_pkts, + interfaces[i].psq.q[3].n_pkts, + interfaces[i].afq.q[1].n_pkts, + interfaces[i].psq.q[4].n_pkts, + interfaces[i].psq.q[5].n_pkts, + interfaces[i].afq.q[2].n_pkts, + interfaces[i].psq.q[6].n_pkts, + interfaces[i].psq.q[7].n_pkts, + interfaces[i].afq.q[3].n_pkts, + interfaces[i].psq.q[8].n_pkts, + interfaces[i].psq.q[9].n_pkts, + interfaces[i].afq.q[4].n_pkts); } } @@ -4005,13 +4007,13 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) ea = mac_table[i].ea; bcm_bprintf(strbuf, "MAC_table[%d].ea = " "["MACDBG"], if:%d \n", i, - MAC2STRDBG(ea), mac_table[i].interface_id); + MAC2STRDBG(ea), mac_table[i].interface_id); bcm_bprintf(strbuf, "MAC_table[%d].PSQ(len,state,credit)," "(trans,supp_trans,onbus)" "= (%d,%s,%d),(%d,%d,%d)\n", i, - mac_table[i].psq.len, + mac_table[i].psq.n_pkts_tot, ((mac_table[i].state == WLFC_STATE_OPEN) ? " OPEN":"CLOSE"), mac_table[i].requested_credit, @@ -4021,27 +4023,27 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) #ifdef PROP_TXSTATUS_DEBUG bcm_bprintf(strbuf, "MAC_table[%d]: (opened, closed) = (%d, %d)\n", i, mac_table[i].opened_ct, mac_table[i].closed_ct); -#endif +#endif // endif bcm_bprintf(strbuf, "MAC_table[%d].PSQ" "(delay0,sup0,afq0),(delay1,sup1,afq1),(delay2,sup2,afq2)," "(delay3,sup3,afq3),(delay4,sup4,afq4) =(%d,%d,%d)," "(%d,%d,%d),(%d,%d,%d),(%d,%d,%d),(%d,%d,%d)\n", i, - mac_table[i].psq.q[0].len, - mac_table[i].psq.q[1].len, - mac_table[i].afq.q[0].len, - mac_table[i].psq.q[2].len, - mac_table[i].psq.q[3].len, - mac_table[i].afq.q[1].len, - mac_table[i].psq.q[4].len, - mac_table[i].psq.q[5].len, - mac_table[i].afq.q[2].len, - mac_table[i].psq.q[6].len, - mac_table[i].psq.q[7].len, - mac_table[i].afq.q[3].len, - mac_table[i].psq.q[8].len, - mac_table[i].psq.q[9].len, - mac_table[i].afq.q[4].len); + mac_table[i].psq.q[0].n_pkts, + mac_table[i].psq.q[1].n_pkts, + mac_table[i].afq.q[0].n_pkts, + mac_table[i].psq.q[2].n_pkts, + mac_table[i].psq.q[3].n_pkts, + mac_table[i].afq.q[1].n_pkts, + mac_table[i].psq.q[4].n_pkts, + mac_table[i].psq.q[5].n_pkts, + mac_table[i].afq.q[2].n_pkts, + mac_table[i].psq.q[6].n_pkts, + mac_table[i].psq.q[7].n_pkts, + mac_table[i].afq.q[3].n_pkts, + mac_table[i].psq.q[8].n_pkts, + mac_table[i].psq.q[9].n_pkts, + mac_table[i].afq.q[4].n_pkts); } } @@ -4133,9 +4135,10 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) } #endif /* PROP_TXSTATUS_DEBUG */ bcm_bprintf(strbuf, "\n"); - bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out),(dropped,hdr_only,wlc_tossed)" + bcm_bprintf(strbuf, "wlfc- pkt((in,2bus,txstats,hdrpull,out)," + "(dropped,hdr_only,wlc_tossed,wlc_dropped,wlc_exptime)" "(freed,free_err,rollback)) = " - "((%d,%d,%d,%d,%d),(%d,%d,%d),(%d,%d,%d))\n", + "((%d,%d,%d,%d,%d),(%d,%d,%d,%d,%d),(%d,%d,%d))\n", wlfc->stats.pktin, wlfc->stats.pkt2bus, wlfc->stats.txstatus_in, @@ -4145,6 +4148,8 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) wlfc->stats.pktdropped, wlfc->stats.wlfc_header_only_pkt, wlfc->stats.wlc_tossed_pkts, + wlfc->stats.pkt_dropped, + wlfc->stats.pkt_exptime, wlfc->stats.pkt_freed, wlfc->stats.pkt_free_err, wlfc->stats.rollback); diff --git a/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.h b/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.h index 1e8b01f97a44b2ca5d8dfc975aaf1021bc0e970a..86ce806ae384ca3edf566e11efb253582d2164a6 100644 --- a/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.h +++ b/drivers/net/wireless/bcmdhd_oo/dhd_wlfc.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -14,7 +14,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. @@ -22,13 +22,12 @@ * * <> * - * $Id: dhd_wlfc.h 671530 2016-11-22 08:43:33Z $ + * $Id: dhd_wlfc.h 690477 2017-03-16 10:17:17Z $ * */ #ifndef __wlfc_host_driver_definitions_h__ #define __wlfc_host_driver_definitions_h__ - /* #define OOO_DEBUG */ #define KERNEL_THREAD_RETURN_TYPE int @@ -84,7 +83,7 @@ typedef struct wlfc_hanger_item { void* pkt; #ifdef PROP_TXSTATUS_DEBUG uint32 push_time; -#endif +#endif // endif struct wlfc_hanger_item *next; } wlfc_hanger_item_t; @@ -119,7 +118,7 @@ typedef struct wlfc_hanger { #define WLFC_FLOWCONTROL_HIWATER (WLFC_PSQ_LEN - 256) #undef WLFC_FLOWCONTROL_LOWATER #define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER / 4) -#endif +#endif // endif #define WLFC_LOG_BUF_SIZE (1024*1024) @@ -156,13 +155,12 @@ typedef struct wlfc_mac_descriptor { /** flag. TRUE when remote MAC is in suppressed state */ uint8 suppressed; - #ifdef PROP_TXSTATUS_DEBUG uint32 dstncredit_sent_packets; uint32 dstncredit_acks; uint32 opened_ct; uint32 closed_ct; -#endif +#endif // endif struct wlfc_mac_descriptor* prev; struct wlfc_mac_descriptor* next; } wlfc_mac_descriptor_t; @@ -201,6 +199,8 @@ typedef struct athost_wl_stat_counters { uint32 d11_suppress; uint32 wl_suppress; uint32 bad_suppress; + uint32 pkt_dropped; + uint32 pkt_exptime; uint32 pkt_freed; uint32 pkt_free_err; uint32 psq_wlsup_retx; @@ -229,7 +229,7 @@ typedef struct athost_wl_stat_counters { uint32 dropped_qfull[6]; uint32 signal_only_pkts_sent; uint32 signal_only_pkts_freed; -#endif +#endif // endif uint32 cleanup_txq_cnt; uint32 cleanup_psq_cnt; uint32 cleanup_fw_cnt; @@ -246,7 +246,7 @@ typedef struct athost_wl_stat_counters { #define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do {} while (0) #define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do {} while (0) #define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do {} while (0) -#endif +#endif // endif #define WLFC_PACKET_BOUND 10 #define WLFC_FCMODE_NONE 0 #define WLFC_FCMODE_IMPLIED_CREDIT 1 @@ -504,7 +504,7 @@ typedef struct dhd_pkttag { #else #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do {} while (0) #define DHD_WLFC_CTRINC_MAC_OPEN(entry) do {} while (0) -#endif +#endif // endif #ifdef BCM_OBJECT_TRACE #define DHD_PKTTAG_SET_SN(tag, val) ((dhd_pkttag_t*)(tag))->sn = (val) diff --git a/drivers/net/wireless/bcmdhd_oo/dngl_stats.h b/drivers/net/wireless/bcmdhd_oo/dngl_stats.h index b995ec5b0ed47e7b24bf903781703b362619656f..6bbe9fd140b81ecc4a7a76d5b66e91eea3b07841 100644 --- a/drivers/net/wireless/bcmdhd_oo/dngl_stats.h +++ b/drivers/net/wireless/bcmdhd_oo/dngl_stats.h @@ -2,14 +2,14 @@ * Common stats definitions for clients of dongle * ports * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: dngl_stats.h 681171 2017-01-25 05:27:08Z $ + * $Id: dngl_stats.h 716269 2017-08-17 09:22:46Z $ */ #ifndef _dngl_stats_h_ @@ -102,13 +102,16 @@ typedef enum { typedef struct { wifi_interface_mode mode; /* interface mode */ uint8 mac_addr[6]; /* interface mac address (self) */ + uint8 PAD[2]; wifi_connection_state state; /* connection state (valid for STA, CLI only) */ wifi_roam_state roaming; /* roaming state */ uint32 capabilities; /* WIFI_CAPABILITY_XXX (self) */ uint8 ssid[DOT11_MAX_SSID_LEN+1]; /* null terminated SSID */ uint8 bssid[ETHER_ADDR_LEN]; /* bssid */ + uint8 PAD[1]; uint8 ap_country_str[3]; /* country string advertised by AP */ uint8 country_str[3]; /* country string for this association */ + uint8 PAD[2]; } wifi_interface_info; typedef wifi_interface_info *wifi_interface_handle; @@ -149,7 +152,7 @@ typedef struct { /* channel statistics */ typedef struct { wifi_channel_info channel; /* channel */ - uint32 on_time; /* msecs the radio is awake (32 bits number + uint32 on_time; /* msecs the radio is awake (32 bits number * accruing over time) */ uint32 cca_busy_time; /* msecs the CCA register is busy (32 bits number diff --git a/drivers/net/wireless/bcmdhd_oo/document/ChangeHistory.txt b/drivers/net/wireless/bcmdhd_oo/document/ChangeHistory.txt index f47a1798f68bb451043692c1864703f4fc6c7799..5e39c5b00cefc34f7b21e6983c1fbd6ceac27272 100644 --- a/drivers/net/wireless/bcmdhd_oo/document/ChangeHistory.txt +++ b/drivers/net/wireless/bcmdhd_oo/document/ChangeHistory.txt @@ -1,617 +1,341 @@ -BCM4361 DHD 1.77.59 for Android Great/Dream & BCM4345X & BCM4343X Project -(Notes: 1.77.x is twigged off from 1.579.235.9) +BCM4361 DHD 100.10.163 for Android STAR Project -DHD 1.77.59 - 2017.12.22 -Others - - CS4139777(By Kwak Hogil) Fixed call mute issue during LCD Off(Changed Packet filter ID 107) - - CS4163743(By Kwak Hogil) Fixed code defect for wl_pattern_atoh() with invalid return value - - Changed MAC masking pattern and masking position to sync up with Firmware masking pattern - - Enhanced SoftAP/P2PGO keep alive to avoid unexpected keep alive disconnection - - Fixed a possible memory leak in dhdpcie_bus_write_vars - - Fixed missed SSID/MAC filtering in log for security reason - - Fixed parsing issue on wl_parse_ssid_list_tlv() for PNO setup - - -DHD 1.77.58 - 2017.12.18 +DHD 100.10.163 - 2017.12.29 Major Issue - - CS4083402(By Jeong Min Cheol) Added to define DHD_2G_ONLY_SUPPORT + - CS4079439(By Cho Seong Ji) Added the additional spin lock and debugging implementation to protect DMA map/unmap synchronization and logging the history for Exynos9810 platform * Issue summary - To support for 2.4G band only model requirement + Kernel Panic was happened during VoIP test * Analysis / Root cause - In order to support 2.4G band, it needs to block 5G band setting. + 1. Kernel panic was occurred due to SMMU fault from the IOMMU driver + 2. From the initial analysis of Samsung S.LSI, unsynchronization between DMA map and unmap could lead the SMMU fault issue * Solution - In order to enable this feature, it needs to define CONFIG_WLAN_5GDISABLE in kernel config + 1. Added new spinlock to sync up for DMA map/unmap implementation in the OS dependent layer of DHD to avoid the issue + 2. Provided the debug codes to narrow down the issue once it is reproduced - - Added to define DHD_DISABLE_VHTMODE + - CS4139777(By Kwak Hogil) Removed PKT filter ID 107: IPv4 Broadcast filter * Issue summary - To support for 802.11ac disable model requirement + VOWIFI mute issue happened after LCD off * Analysis / Root cause - In order to support 802.11ac disable, it needs to disable vhtmode + In this network, netmask is 255.255.253.0 so DUT IP address xxx.xxx.xxx.255 is not Broadcast. + But it was filtered by IPv4 Broadcast filter (ID 107) * Solution - In order to enable this feature, it needs to define CONFIG_WLAN_VHTDISABLE in kernel config + First, removed packet filter ID 107 not to block this unicast packet in this kind of network + + - CS4228470(By Kwak Hogil) Fixed ARP offload flag not to clean up Host IP address/ARP table after roaming done + * Issue summary + AP failed to do ARP resolution after roaming completed + * Analysis / Root cause + There was roaming patch code which clean up Host IP address/ARP table in DHD + From Android O, DHCP is not run after roaming if some requirements meet on framework side + So Host IP address was not set again in this case and it caused the problem ARP request was dropped after roaming + * Solution + It was caused by ARP_OL_HOST_AUTO_REPLY option that has not been used and not needed for Samsung model + Fixed to not use it, not to clean up Host IP address/ARP table after roaming done Kernel Panic - - CS3959621(By Kim Gwang Min) Added debug log in ISR for debugging dpc un-scheduling issue - - CS3959621(By Kim Gwang Min) Fixed watchdog reset due to deadlock path from PM handler + - CS4164502(By Jeong Min Cheol) Fixed potential kernel panic during deleting flowring with invalid flowid + - CS4198456(By Kim Gwang Min) Fixed kernel panic while collecting data for Mobile HotSpot BigData + - Added Null check routine in wl_cfg80211_deinit_p2p_discovery() / Kernel panic occurred while disable P2P discovery Interface + +Others + - CS4190889(By Kwak Hogil) Added DEBUG_DUMP private command option for unwanted/disconnected + - CS4233933(By Kwak Hogil) Print mask and pattern values for pktlog filter separately + - CS4261039(By Min SungBin) Fixed to use proper locally_generated value on cfg80211_disconnect() when upper layer request disconnection + - CS4272339 Fixed potential user space overflow issue in dhd_trace_read_proc() + - Added clearing timestamp for debug dump file after collecting memdump + - Added length check for handling logtrace events + - Changed 'escan is not ready' log as rate limit log style for avoid repeatedly printing log message + - Changed MAC OUI format for Bigdata + - Enhanced logtrace and version changed as V02 + - Enhanced SoftAP/P2PGO keep alive to avoid unexpected keep alive disconnection + - Fixed debug_dump not generated intermittently for scan busy case + - Fixed wrong length for memory free function in wl_event_q() + - Update correct STA channel for the Auto channel selection in case of STA/SoftAP concurrent mode -Others - - CS3898979(By Yoon Jae Ho) Fixed unintended hang issue by invalid deauth reason code from specific AP - - Enabled an Android private command for setting ADPS on BCM43456 - - Fixed connection fail if BDC is enabled in DHD and CAC is enabled in both STA and AP (SDIO only) +DHD 100.10.142 - 2017.12.15 +Major Issue + - CS4086723(By Jeong Min Cheol) Fixed WPS connection failure issue with Random MAC Scan feature + * Issue summary + WPS PBC connection failed with specific AP + * Analysis / Root cause + If Random MAC Scan feature enabled for WPS PBC, connection was failed due to PBC overlap + * Solution + Disabled conditionally Random MAC Scan feature for WPS PBC connection + +New Feature + - EWP : Added txbcmfrm in ecounters to get info on the behavior of softap beaconing history + - EWP : Implemented saving cookie to debug dump file -DHD 1.77.56.1 - 2017.11.30 Others - - Fixed link down by null BSSID during roaming + - CS3839380(By Nam Counjong) Changed default BTM delta + - CS3846389(By Kwak Hogil) Limit the number of dump files that DHD can store to local file system + - CS4034777(By Kim MinSoo) Enabled ARGOS notification callback, DHD TCP ACK suppress is disabled + - CS4058797(By Jeong Min Cheol) Added more debug logs to debug PKTID AUDIT failure issue + - CS4115086(By Kwak Hogil) Added android private command to change pkt logging size + - CS4138402(By Lee SoonHo) Added PCIe interrupt affinity configuration for P2P GO & SoftAP + - CS4154668(By Cho Seong Ji) Added interrupt status and time stamp information for debugging SCAN timeout issue + - CS4163743(By Kwak Hogil) Fixed code defect for wl_pattern_atoh() with invalid return value + - Added debug prints in log_dump/mem_dump/sssr_dump scheduling to debug in any scheduling issues + - Added new msglevel for IOVAR info dumping(DHD_IOVAR_MEM) + - Deferred code for free of log dump related buffer until workqueue is purged in dhd_detach() + - Fixed a possible memory leak in dhdpcie_bus_write_vars + - Fixed memory leak during android GETSTAINFO command processing for bigdata softap + - Fixed missed SSID/MAC filtering in log for security reason + - Fixed parsing issue on wl_parse_ssid_list_tlv() for PNO setup + - Fixed SSSR and debug dump were not getting collected during memory dump + - Fixed unsynchronized active_tx_count which gives incorrect information + - Optimized the livelock check loop to handle corner case of partial DMA -DHD 1.77.56 - 2017.11.30 +DHD 100.10.136 - 2017.12.01 Major Issue - - CS3928981 Fixed to allocate 64KB for WLAN_DHD_WLFC_BUF_SIZE on 32bit platform also + - CS3846890(By Kim MinSoo) Disabled DHD TCP ACK SUPPRESS for GS9 (Exynos 9810 platform) * Issue summary - A8/43455/NOS, couldn't operate screen mirroring over WFD only under the VSDB/MCC + N-DRIVE download TPUT was lower than the GN8 (Great) device * Analysis / Root cause - For a smooth VSDB/TX operation, PROP_TXSTATUS(WLFC) feature is being used - However, not enough pre-allocated memory for WLFC was allocated on 32bit platform - So VSDB/TX regression issue happened due to low pre-allocated memory size (16KB) + DHD TCP ACK suppress enable/disable controlled by ARGOS notification callback by current TPUT + Problem is DHD TCP ACK suppress is enabled by default for GS9 because GS9 does not use ARGOS feature in DHD * Solution - For WLFC_BUF_SIZE, pre-allocates 64KB for 32bit platform also + Disabled DHD TCP ACK suppress in DHD Makefile for GS9 + DHD TCP ACK suppress is replaced by TCP delayed ACK - - CS4011220 Block ADPS enable private command at RF test mode + - CS4048984(By Min SungBin) Skip dumping PCIe registers if PCIe link down has occurred * Issue summary - Have a trouble to measure RF performance at RF test mode by ADPS + The Kernel panic was triggered due to System MMU fault * Analysis / Root cause - During RF test mode, PM 0 is set to disable WiFi dongle PM operation including ADPS, - but “ADPS enable“ private command was called after setting PM 0 so ADPS was run again - This issue happened after enabling ADPS by default + 1. The PCIe link down has occurred before the Kernel panic + 2. The System MMU fault was triggered when host tried to access the configuration registers in EP + 3. It seemed that RC doesn?™t allow host to access any EP registers after the PCIe link down has occurred * Solution - Block “ADPS enable†private command when PM 0 is set for RF test mode + To avoid the Kernel panic, skip dumping any PCIe registers in EP if PCIe link down has occurred - - CS4034777 Enabled ARGOS notification callback for DHD TCP ACK suppress + - CS4050389(By Jeong Min Cheol) Fixed kernel panic due to unexpected suspend during DHD_LOG_DUMP * Issue summary - Low TPUT issue occurred in TCP long RTT environment + Kernel Panic is happened during DHD_LOG_DUMP * Analysis / Root cause - The reason is that DHD TCP ACK suppress was always enabled because ARGOS feature was removed in DHD + Wpa_supplicant triggered DEBUG_DUMP and then runtime suspend was entered + ITMON detected that dhd_log_dump tried to access pci bus after runtime suspend at this time * Solution - Turn off DHD TCP ACK suppress by default and enable ARGOS notification callback to control DHD TCP ACK suppress by current TPUT + Adding wakelock for avoiding unexpected runtime suspend during DHD_LOG_DUMP - - Configure 64bit DMA mask for MSM8998 (Default enabled: it can be controlled by the SET_DMA_MASK_64BIT definition in the Makefile) + - CS4050409(By ahn joongmin) CS4078469(By Seo Jung Kuk) CS4078386(By Cho Seong Ji) CS4075752(By Cho Seong Ji) Fixed kernel panic due to duplicate free in pktlogging feature * Issue summary - Kernel allocated the memory in swiotlb region for DMA mapping since the default DMA mask is set to 32bit + Kernel Panic has happened due to duplicate skb free in pktlogging feature * Analysis / Root cause - It's configured to 64bit mask for DMA mapping to check if kernel allocates the memory for DMA mapping to different region and TPUT is improved + Two different DHD threads indicated same function (dhd_pktlog_ring_get_writebuf) in the log + The reason is that it's a critical section but there was no synchronization object in the pktlog function * Solution - Based on the kernel DMA mapping guidance, DHD configure DMA mask to 64bit - -Security Patch - - CVE-2017-13161 V2017092501 Fixed buffer overrun issue in wl_parse_ssid_list_tlv() - - CVE-2017-13213 V2017081501 Fixed buffer overrun issue in wl_cfgvendor_set_bssid_blacklist() - - V2017081701 Fixed buffer overrun issue in wl_cfgvendor_set_ssid_whitelist() - - V2017082201 Fixed buffer overrun issue in wl_cfgvendor_set_rand_mac_oui() - - V2017082202 Fixed buffer overrun issue in wl_cfgvendor_set_bssid_pref() - -Others - - CS3742062 Added STP / XID packet filter - - CS3863852 Added log to detect abnormal skb operation - - CS3914585 Fixed RCC channel missing issue when scan result is more than 100 - - CS3927468 Added Bring-up patch for BCM43569 - - CS3976846 Clear the bus state related flags for recovery during turning on Wi-Fi - - Block processing the rest of ring buffers once PCIe bus enters low power state - - Enabled feature for the Dongle memory loopback test and the PCIE Non DMA M2M loopback test when CONFIG_SEC_FACTORY enabled case - (It should be sync up FW version with IGU35RC65_REL_13_38_45(GREAT), IGU3565T38RC13_REL_13_41_13(DREAM) or higher version) - - Fixed memory leak in PNO stop command - - -DHD 1.77.55.1 - 2017.11.10 -Others - - Disabled FW corruption test and PCIE Non DMA M2M loopback test in Makefile - (For enabling it, please modify Makefile and sync up FW version with IGU35RC65_REL_13_38_45(GREAT), IGU3565T38RC13_REL_13_41_13(DREAM) or higher version) - - -DHD 1.77.55 - 2017.11.10 -Others - - CS3750290 Fixed mis-merged Makefile for BCM43456 Bring-up patch - - CS3962099 Fixed lockup corner case of Non-DMA M2M loopback test - - -DHD 1.77.54 - 2017.11.03 -New Feature - - CS3688359 Added PCIe M2M non DMA loopback test in MFG mode - -Kernel Panic - - CS3830411 Fixed cpu lock up during de-init tcpack suppress module - -Security Patch - - CS3621122 Fixed vulnerability issue by dhd_parse_logstrs_file() which contains problematic code - -Others - - CS3509434 Changed beacon receive timeout - - CS3558828 Added NDO_CONFIG_SUPPORT - - CS3661384 Disabled WLAN_REASON_UNSPECIFIED reason code used as hang event code - - CS3685473 TPUT enhancement for A8 project (Exynos 5433 + BCM43455) - - CS3724694 Cancel roaming process when BSS was not matched - - CS3750290 Added BCM43456 Bring-up patch - - CS3799104 Added lock to protect vndr_oui_list - - CS3863852 Added log to detect abnormal skb operation - - Cleaned up the memory allocation logic of DHD_FW_MEM_CORRUPTION feature - - -DHD 1.77.48 - 2017.09.21 -Kernel Panic - - CS3275366 Fixed kernel panic issue when returning invalid dongle ram size - - CS3341471 Fixed kernel panic from ASSERT during driver initialization - - Fixed kernel panic during connection test on debugging mode - -Others - - CS3274682 Fixed low performance of NAS download due to CPU migration - - CS3291870 Fixed the current consumption issue on SoftAP due to the wl_wdwake wakelock (Available for SDIO projects) - - CS3409811 Supported private command of clearing pktlogging data for security - - CS3483269 Extended dongle_isolation for all customer platform using PCIe bus - - CS3508335 Limited some security information in debug_dump - - CS3509434 Added WLC_E_SET_SSID fail custom reason code - - CS3558874 Added Assoc Reject - WLC_E_STATUS_NO_NETWORKS status code for Assoc Reject Bigdata - - CS3585868 Integrated GREAT Android N OS features into DREAM/GREAT Android O OS project - - CS3591398 Enabled TCP ACK suppress enable/disable log message - - Support RSSI summation report feature (Available for Android O or later version) - - -DHD 1.77.44 - 2017.08.24 -Others - - CS3088602 Reduced value length of WSR counters variable - - CS3247015 Fixed disconnection during roaming on CISCO hidden networks - - CS3396150 Enabled legacy SCAN wakelock for SDIO Project - - CS3429070 Fixed SDIO init CLK issue for Exynos 7580 platform - - CS3455796 Changed path of wifi dump-files for DREAM/STAR - - -DHD 1.77.43 - 2017.08.11 -Security Patch - - V2017063001 Removed not required IOVAR for SDIO - - V2017063002 Added length check in event log handler - -Others - - CS3088602 Minimized Wifi Statistics Report for host buffer size limitation - - CS3247009 Changed FW/NVRAM/BLOB location following ANDROID PLATFORM VERSION - - CS3351562 Changed MAC address encoding due to security issue - - -DHD 1.77.37.3 - 2017.07.27 -Others - - CS3088602 Add missed 4 values while report to Framework - - CS3203998 Fixed to support big data of 11kv - - CS3215091 Fixed build error of detect consecutive hang event - - CS3255825 Changed path of wifi dump-files only if GREAT - - -DHD 1.77.37.2 - 2017.07.19 -Kernel Panic - - CS3203896 Fixed kernel panic caused by referred NULL Pointer in dhd_pktlog_pkts_write_file - - CS3204538 Fixed Kernel panic when D3_ACK timeout is occurred - -Others - - CS3215091 Detect consecutive hang event from dongle on factory binary - - CS3221222 Fixed wrong 11kv default setting - - CS3265424 CS3160208 Fixed to update correct DHD connection status on AUTO_ROAM operation - - CS3265424 CS3214374 Fixed Roaming event drop issue when roaming to same BSSID case + Added spin lock to protect critical section - -DHD 1.77.37 - 2017.07.04 New Feature - - CS2955162 Supported RSSI Logging - (This implementation should be sync up with FW 13.38.30 or higher version) - - CS3088602 Introduced Wifi Statistics Report for Big data logging + - EWP : Changed MAC masking pattern and masking position to sync up with Firmware masking pattern + - EWP : Set proper values for rxbeaconmbss and noise_level while Bigdata Report Kernel Panic - - CS1812549 Fixed kernel panic for GETSTAINFO command - - CS3114183 Fixed kernel panic that filp_close() referred NULL Pointer in dhd_pktlog_write_file() - - CS3179018 Changed log level of scan warn event log to prevent scan time out + - CS4050389(By Jeong Min Cheol) Fixed kernel panic due to unexpected suspend during DHD_LOG_DUMP + - Fixed Kernel panic by watchdong context - Disable watchdog before devreset off / Enable again after devreset on + - Fixed Kernel panic while collecting log dump after hang event occurred -Security Patch - - CVE-2017-0705 Added boundary check in wl_cfgvendor_significant_change_cfg() - - CVE-2017-0706 Added boundary check in wl_cfg80211_mgmt_tx() - - V2017053101 Added boundary check in dhd_process_full_gscan_result() - - V2017053102 Fixed Heap overflow in dhd_handle_swc_evt() - - V2017053103 Added boundary check in dhd_handle_hotlist_scan_evt() - - V2017053104 Added boundary check in dhd_pno_process_epno_result() - - V2017060101 Added boundary check in wl_escan_handler() - - Fixed overflow issue in wl_android_set_ibss_beacon_ouidata() - Others - - CS1760272 Added BCM43430 FW/NVRAM dual operation - - CS2459522 Re-enabled GEN_SOFTAP_INFO_FILE feature - - CS2554190 Enhanced Packet Logging feature - Used Pre-allocated buffer pool & Added private command & Added packet failure reason into pcap - - CS2901316 Fixed to send up common error code for Android-O VTS - - CS2901316 Fixed to use proper chipset number when parsing link stats - - CS3057710 Added spin lock for Packet Monitoring and Debugability feature - Avoid packet fetching on invalid states - - CS3057710 Disabled Android Packet Monitoring - - CS3059107 Fixed build error on BCM43455 A8 platform - - CS3092630 Added to HEX dump for host wake packet - - CS3093675 Fixed prevent issue in dhd_pktlog.c file - - CS3121464 Added to check invalid hang reason - - Added log for packet monitor entry functions - - -DHD 1.77.27.12 - 2017.06.20 + - CS2810592(By ahn joongmin) Added antenna mode information for HotSpot BigData Logging + - CS3898979(By Yoon Jae Ho) Fixed unintended hang issue by invalid deauth reason code from specific AP + - CS4043579(By Jeong Min Cheol) CS4050681(By Cho Seong Ji) Fixed coverity issues + - CS4043949(By Nam Counjong) Fixed dropping BTM request after roaming + - CS4045271(By Hogil Kwak) Added SET_ADPS log message + - CS4072384(By Jeong Min Cheol) Added more time stamps for debugging Resumed on timeout and D3_ACK timeout issue due to DPC scheduling problem + - CS4097050(By Min SungBin) Fixed cfg80211 layer warning for wl_bss_connect_done indication path + - Added wakeup RunTimePM code during wifi reloading + - Changed event_handler workqueue parameter for debugging scan timeout issue + - Cleaned up code for send up packets routine + - Disabled DHD RA (Router Advertisement) filter if APF is supported because APF can filter out RA frame + - Disabled handling of EVENT_LOG_TAG_TS - MAC address masked on firmware + - Disabled MAC address masking on firmware temporally + - Enabled WL_SCHED_SCAN for PNO + - Fixed buffer overrun issue on NAN code + - Fixed to clean up dongle arp table when roaming done + - Reduced scan event workqueue max count for avoid workqueue not scheduled issue + - Supported SDM845 cfg80211_connect_bss API changes + - Take SSSR dump only if memdump mode is enabled + + +DHD 100.10.126 - 2017.11.17 New Feature - - CS2554190 Enabled Packet Logging feature for Great Project + - EWP: Added collecting preserve log for TRAP + - EWP: Print preserve log when logstrs.bin is present Kernel Panic - - CS2931791 Fixed kernel panic when flushing packet in Tx queue for SDIO interface - - CS3024217 Fixed the Kernel panic when Kernel calls the CPU hotplug notification function during driver initialization - -Security Patch - - Enhanced event length check in is_wlc_event_frame() - - V2017052301 Added event length check in dhd_rtt_event_handler() - - V2017052302 Added event length check in wl_notify_rx_mgmt_frame() + - CS3863852 Changed the log level to DHD_ERROR_MEM for ICMP dump to avoid Kernel panic + - CS3987886 Fixed kernel panic by stack overflow during copy extended trap data + - Fixed Kernel Panic during static control buffer depletion Others - - CS2934714 Fixed MFG firmware loading failure with single nvram file - - CS3018308 Fixed repetitive connection drops of clients with Mobile Hotspot - - Added log for scan timeout issue - - Disabled Preempt when scan results sent to host - avoid scan timeout issue - - Provide roaming reason when WLC_E_ROAM_PREP event has occurred - (This patch should be sync up with FW 13.38.30 or higher version) - - Sync up Makefile/Kconfig with Samsung requirement + - CS3831435 Changed SoftAP power save status format in private command (ms -> min) + - CS3863518 Removed a carriage return character in SUPP_LOG() of wl_cfg80211_connect() + - CS3935040 IRQ Affinity set to Big core and blocking CPU migration to Big Core + - CS3976846 Clear the bus state related flags for recovery during turning on Wi-Fi + - CS3995917 Fixed to use P2P interface MAC address scheme as before + - CS4005452 Disabled ARP host auto reply option + - CS4011220 Block ADPS enable private command at RF test mode + - Block processing the rest of ring buffers once PCIe bus enters low power state + - Enabled feature for the Dongle memory loopback test and the PCIE Non DMA M2M loopback test when CONFIG_SEC_FACTORY enabled case + - Fixed Coverity defects - Buffer Overrun issue + - Fixed Coverity defects - Dereferencing NULL Pointer + - Fixed Coverity defects - Integer Overflow / Constant expression results -DHD 1.77.24 - 2017.06.02 +DHD 100.10.117.4 - 2017.11.08 Kernel Panic - - Fixed Kernel Panic in wl_event_handler() while doing STA+P2P stress test - -Security Patch - - Supported Heap ASLR(Address Space Layout Randomization) in dongle. Heap ASLR will be enabled when firmware supports it + - Block to send HANG event information to BIGDATA module to avoid Kernel Panic Others - - Fixed incorrect nvram path modification routines to support Murata module + - CS3955693 Disabled DHD_RECOVER_TIMEOUT feature for debugging SCAN timeout issue + - CS3959762 Print BAR0 and BAR1 information to debug D3_ACK timeout + - Fixed dongle trap issue during connect/disconnect stress test + - Print tasklet status for SCAN timeout debugging -DHD 1.77.22 - 2017.05.25 -Kernel Panic - - CS2714944 Fixed the Kernel Panic during dynamic TCP ACK suppress mode change in SDIO platform - +DHD 100.10.117.3 - 2017.11.07 Others - - CS2595140 Added an Android private command for setting ADPS - - CS2675989 Fixed reverse-order of EAP-Failure and deauth packet - - 11kv - Fixed BTM capability check - - Unified one DHD for Dream & Great Project with CONFIG_WLAN_GREAT define + - Disabled FW corruption test and PCIE Non DMA M2M loopback test in Makefile + (For enabling it, please modify Makefile and sync up FW version with IGUANA08T_REL_13_35_189 or higher version) -DHD 1.77.21 - 2017.05.19 -New Feature - - CS2459522 Disabled GEN_SOFTAP_INFO_FILE feature in Makefile - - Comment out ADPS define at Makefile - -Kernel Panic - - CS2472525 Avoid to trigger Kernel panic on abnormal devices during device initialization - - CS2716890 Fixed Scan timeout issue with blocking suspend during P2P scan +DHD 100.10.117.2 - 2017.11.06 +Others + - CS3944770 Fixed to set roam_prof failure issue + - CS3962099 Fixed lockup corner case of Non-DMA M2M loopback test + - Added registration of PCIe link down handler for Exynos9810 -Security Patch - - CVE-2017-0633 V2017022301 Enhanced wrong buffer usage in IOCTL path -Others - - CS2454032 Changed to implement wake stat support - - CS2460373 Added WIFI_LOGGER feature in Makefile - - CS2472434 Fixed roam failure on PMF required APs - - CS2475910 Print last roaming event log when link down is happened - - CS2642368 Fixed type casting issue in wl_android_send_action_frame() - - CS2761292 Added dhd rxq sdlock operation - - CS2769153 Fixed compile error on exymos5433 sdio model - - CS2791743 Fixed duplicated tx_error counter summation - - CS2793328 Relocated WLAN onoff delay on dhd_wlan_init_gpio() - - Added max payload length check in dhd_dbg_msgtrace_log_parser() function - - Changed the nvram file name to nvram.txt to support single nvram file - - Fixed assoc state sync issue between wpa_supplicant & DHD driver - - Fixed SoftAP interface delete issue observed while running APSTA stability test - - Fixed the spinlock related problem in the DHD_WAKE_STATUS feature - - -DHD 1.77.16 - 2017.05.01 +DHD 100.10.117 - 2017.11.03 New Feature - - CS2459522 Created .softap.info file when boot-up time for SoftAP information + - EWP : CS3846389 Changed Samsung Bigdata format for hang reason + - EWP : CS3846389 Removed OK string for android ewp filter command + - EWP : Enhanced debug log for SCAN timeout + - EWP : Reduced Firmaware log message + - EWP : Triggered mem_dump on interface delete failure + - EWP : Updated Bigdata report format of counters Kernel Panic - - CS2471281 Fixed null pointer reference exception during interface down - - CS2472873 Fixed to prevent accessing CPU hotplug call back before initialization - - CS2477559 Implement exception handling routines if DMA mapping error for TX data packet is happened + - CS3920857 Block to access dongle PCIe register if host fails to bring the PCIe link up + - CS3938108 Fixed the Kernel Panic issue when PCIe link down is occurred Security Patch - - CVE-2017-0568 V2017051814 Fixed buffer overrun in wl_run_escan() - - CVE-2017-0570 V2017051815 Removed unused file (wl_iw.c/wl_iw.h) - - CVE-2017-0574 V2017051817 Fixed vulnerability issues - - CVE-2017-0740 V2017030901 Fixed length overflow issue in dhd_wl_ioctl() function - -Others - - CS2456626 Enabled SETBAND API - - CS2470635 Enabled frameburst on SDIO platform - - CS2471300 Fixed Buffer overflow issue - - CS2473469 Added force disconnect when continuously update DPM event - - CS2474767 Fixed compile error for Dream project - - CS2476640 Added to control tcpack_suppress as throughput on BCM43455 - - CS2555123 Fixed page fault issue in dhd_wl_ioctl() - - Enabled CAC by default and modified CAC dynamically based on the interface - - Enabled Random MAC address scan by default for all WIFI chip - - Fixed wrong event message print log issue - - -DHD 1.77.12.1 - 2017.03.27 -Others - - CSP:1138026 Fixed compile error for Dream project - - -DHD 1.77.12 - 2017.03.22 -Others - - CSP:1122174 Fixed to clean up dongle arp table when using arp request host offloading option - - CSP:1136579 Removed gtk_key_info set fail error log - - Fixed memory buffer overrun with interworking IE - - -DHD 1.77.11 - 2017.03.17 -Others - - Removed unnecessary country code list in translate_custom_table - - Supported A3 project for BCM43438 - - -DHD 1.77.9.1 - 2017.03.28 -Kernel Panic - - CSP:1139481 Fixed null pointer reference exception during interface down - - -DHD 1.77.9 - 2017.03.14 -Kernel Panic - - CSP:1133051 Fixed livelock issue from unterminated tasklet - - CSP:1133633 Disabled Host PCIe IRQ to avoid continuous IRQ handling - -Others - - CSP:1128803 Removed checking NULL BSSID in dhd profile - - CSP:1129196 Changed SDIO Max Tx Glom Size and Fixed sg list entries limit exceed issue - - CSP:1129696 Added "P2P" label for argos to schedule PCIe interrupt on CPU core 5 - - Prevent BSSID mismatch issue between driver and dongle - - -DHD 1.77.7 - 2017.02.20 -Kernel Panic - - CSP:1128508 Skip dumping core registers in EP side if PCIe link is down - -Others - - CSP:1122486 Enhanced validate code for CID tuple parsing - - CSP:1125601 Invalidate PCI configuration saved state in order to reduce PCI resume latency - - CSP:1128080 Fixed data traffic can't reachable issue after suspend state for SDIO project - - CSP:1128215 Fixed nvram loading issue for murata module - - CSP:1128493 Added wakelock during get BSSID from dongle on wl_cfg80211_get_station() function - - CSP:1128803 Set timer to check null BSSID status of profile was continued - - Changed NAPI & PCIe IRQ CPU core number for Max TPUT (MSM 8998 Platform) - - -DHD 1.77.6 - 2017.02.13 -Others - - CSP:1126094 Block private command SETBAND - - CSP:1127636 Fixed WAPI connection failure - - Added exception case of CLM Blob file checking logic about MFG mode - - -DHD 1.77.5 - 2017.02.12 -Kernel Panic - - CSP:1126904 Block SOCRAM dump request if bus status is in suspend or suspend in progress - - Avoid kernel panic due to wrong ifidx during if create - -Others - - CSP:1126670 Removed Hard coded number from ARGOS_CPU_SCHDULER - - CSP:1126945 Blocking SSSR dump when memdump option is 0 - - CSP:1127862 Changing TXFL wake lock to timeout wake lock - - -DHD 1.77.4 - 2017.02.10 -Others - - CSP:1126670 Removed Hard coded number of PCIe IRQ for affinity set on MSM8998 - - Refactoring Blob download feature for runtime checking Blob/Non-Blob FW - + - CS3621122 Fixed vulnerability issue by dhd_parse_logstrs_file() which contains problematic code -DHD 1.77.3 - 2017.02.06 Others - - CSP:1096716 Fixed long BT deactivation time - - CSP:1124360 Sync up about support chip revision for BCM4345X - - CSP:1124967 Avoid dongle trap by multiple interface creation request - - CSP:1125141 Enhance the PKTID error handler - - CSP:1125601 Invalidate PCI configuration saved state in order to reduce PCI resume latency - - CSP:1126094 Fixed to set roam trigger when 11kv was off + - CS2554190 Removed dead code in Samsung packet logging feature + - CS3516646 Added the log to print invalid txdeauth count + - CS3768340 Changed EVENT_LOG printing style to reduce lines and print dongle time + - CS3831021 Fixed coverity tool reported issues + - CS3831435 Added Private command for SoftAP radio power save statistics + - CS3831435 Modified return string of softAP power save private command + - CS3914585 Fixed RCC channel missing issue when scan result is more than 100 + - Added a new VID information for SEMCO SWB-E32A module + - Added bounding logic to logtrace process events to relinquish CPU to others + - Added Kernel IRQ counts for debug purpose + - Changed for enabling wl events dynamically + - Changed the log format of PCIe ring buffer information + - Fixed link down by invalid RSSI + - Fixed memory leak in PNO stop command + - Fixed missing BTM query after join + - Hold wakelock during OOB IRQ to not allow to go to suspend -DHD 1.77.2 - 2017.01.30 +DHD 100.10.100.6 - 2017.11.30 Kernel Panic - - CSP:1124968 Block accessing EP's core register if host fails PCIe bus linkup + - Enabled l1ss after turning on WiFi on Exynos9810 Platform Others - - CSP:1118705 Link Status HAL API support for 32bit platfom on 64bit kernel - - CSP:1121807 Adding more debug logs for resumed on timeout issue debugging - - CSP:1124007 Changed ram_dump file path - - CSP:1124363 Fix idlecount update missing of RuntimePM - - CSP:1124608 Fixed the turn on failure in SoftAP only mode - - CSP:1121807 Adding more debug logs for resumed on timeout issue debugging - - Change ARGOS IRQ number (162) for Exynos 8895 platform - -Note: 1.77.x is twigged off from 1.579.235.9 + - Cleaned up the memory allocation logic of DHD_FW_MEM_CORRUPTION feature -DHD 1.579.235.9 - 2017.01.24 +DHD 100.10.100.5 - 2017.10.26 New Feature - - Added to Enable/Disable ADPS mode from ".adps.info" file - -Kernel Panic - - Fixed Kernel Panic during STA-GO connection test case - -11kv - - Fixed to send BTM query in dongle - - Override WNM Max Idle period to keep alive period - - Update RCC with channels in neighbor report response - -Others - - CSP:1104911 Added to get hostapd_cli STA_INFO command - - CSP:1111618 Disabled WLADPS_SEAK_AP_WAR feature - - CSP:1114400 Added private command for getting SNR - - CSP:1115484 Fixed vulnerability issues - - CSP:1120070 Added recovery method when reading shared memory is failed - - CSP:1122141 Changed GFP flags usage in osl_alloc_skb() - - CSP:1122486 Fixed potential buffer overflow issue in concate_revision_bcm4361() - - CSP:1122535 Recovery PCIe bus if host fails to read shared memory - - CSP:1122888 Implement the logtrace packet flush handler to fix the scan timeout issue - - Added Private command for LQCM - - Added to control scan suppress during RF test mode - - Enhanced more for nested connection case handling - - -DHD 1.579.235.7 - 2017.01.19 -Kernel Panic - - CSP:1119451 Block transmitting packets while host is in suspend state + - CS3688359 Added PCIe M2M non DMA loopback test in MFG mode Others - - CSP:1089681 Fixed build error on dhd_custom_exynos.c file - - CSP:1089681 Fixed L1ss doesn't work issue on Exynos8895 platform - - CSP:1110320 HANG event recovery simulation - - CSP:1117906 Changed log level for rxglom on SDIO platform - - CSP:1118380 Added file sync routine during socram file dump - - CSP:1118451 Prevent to duplicate connection request without disconnection - - CSP:1118705 Fixed miss match struct wifi_interface_info between DHD and HAL library - - CSP:1118926 Fixed for memory leakage in dhd_preinit_ioctls - - CSP:1122174 Disabled ARP host auto reply option - - 11kv - Enabled BSS Max Idle Period - - Disabled Packet monitoring and debug ability - - Enabled "SUPPORT_TRIGGER_HANG_EVENT" for hang test - - Enhance nested connection case handling - - Fixed D3 ACK timeout HANG send up issue - - Fixed missing mutex unlock in wl_cfg80211_tdls_config - - Fixed vulnerability issues - - Re-factorize MSM CFG function selection - - Removed unused file list - - -DHD 1.579.233 - 2017.01.05 -Kernel Panic - - CSP:1115833 Fixed kernel freeze issue due to tasklet count mismatch + - CS3831435 Added Private command for SoftAP radio power save statistics + - CS3847313 Fixed PCIe IRQ missing issue after PCIe bus resume + - Fixed Kernel IRQ warning during Wi-Fi on/off automation test + - Fixed scan timeout issue -Others - - CSP:1109459 Supported split ARGOS table - - CSP:1117264, 1114969 Modified IRQ affinity code to support Exynos & Qcom platform - - CSP:1117291 Enabled Dongle memdump operation for BCM43455 - - CSP:1118062 Added PCI config space restore check log during resume device - - CSP:1118325 Disabled Rx temperature feature - - 11kv - Added Android private command for BTM delta and disassociation timer threshold - - 11kv - Send BTM query after join/roam if AP doesnt support neighbor report - - Changed debug log level in dhd_find_sta function for performance degradation - - Changed hang reason code - PCIe link down - - Enabled MACEVENT logs by default - - Fixed ADPS issue for RF test - - Fixed for erroneous return code in set radio power save function - - Changed include file location - - -DHD 1.579.231 - 2016.12.23 -Kernel Panic - - CSP:1113202 Fixed race condition between runtime suspend and socram dump - - CSP:1114716 Increased P2P Provision Discovery Response dwell time - - Fixed CPU stall in smp_call_function_single on TX Load Balancing -Others - - CSP:1089681 Fixed PCIe link down issue with changing L1ss sequence during WiFi on - - CSP:1100087 Added get_valid_channel by HAL command on SoftAP - - CSP:1109793 Fixed compile error for BCM4345X project - - CSP:1109793 Fixed connection fail with specific AP - - CSP:1110795 Added check reason of file_open error - - CSP:1111136 Added TDLS LOCK/UNLOCK to protect tdls peer list - - CSP:1111618 Added WAR for avoid data stuck issue in D-Link825 AP - - CSP:1112125 Added MSM8998 architecture define to deferred init call - - CSP:1113518 Fixed WiFi turn on failure issue due to d3 ack failure handling - - CSP:1115484 Fixed vulnerability issues - - CSP:1115750 Fixed disconnect issue during country code setting time - - 11kv - Changed WBTEXT policy as real product case - - 11kv - Send neighbor report request after join - - Disabled OCL feature during RF test mode - - Enabled COUNTRY_SINGLE_REGREV feature for BCM43455 Project - (This patch should be sync up with FW 7.120.1 or higher version) - - -DHD 1.579.216 - 2016.12.07 +DHD 100.10.100 - 2017.10.20 New Feature - - Enabled CLM SINGLE REGREV feature - (This patch should be sync up with FW 13.35.42 or higher version) + - Added trap specific data to send hang reason code + - Enabled using a vendor command to send hang reason code with more parameters + - EWP : Added interface based counters + - EWP : Added more print for TRAP case + - EWP : Fixed current regression (40uA) due to ECounters timer + - EWP : Flushed all preserve log while collecting debug_dump + - EWP : Implemented Bigdata Serialization + - EWP : Reduced burst error printing for specific case Kernel Panic - - CSP:1104692 Fixed pktid audit failure issue with adding memory barrier + - CS3759879 Cleaned up wl_cfgnan_init to fix the Kernel panic + - CS3766435 Fixed the Kernel Panic due to SMMU fault + - CS3830411 Fixed cpu lock up during de-init tcpack suppress module + +Security Patch + - CVE-2017-13161 V2017092501 Fixed buffer overrun issue in wl_parse_ssid_list_tlv() Others - - CSP:1099699 Fixed DUT reset for link stats on framework - - CSP:1104452 Fixed for P2P connection failure due to M1 packet goes up with wrong interface - - CSP:1104795 Disabled ADPS when turn on RF TEST mode - - CSP:1106625 Fixed blob download malloc buffer size calculation code - - CSP:1108217 Changed mem allocation flag to GFP_ATOMIC in NAPI histogram dump - - 11kv - Fixed Makefile dependency - - Activated TSQ_MULTIPLIER to solve poor TCP/TX throughput - - Disabled RA filter when APF was supported - - Modified radio power save API along with the firmware change which enabled per-band radio power save setting - (This patch should be sync up with FW 13.35.42 or higher version) - - Re-factorize MSM CFG function selection - - -DHD 1.579.195 - 2016.11.16 -Others - - CSP:1091903 Fixed dialog token error in BTM query - - CSP:1097948 DHD info file path changed above android 7.0 version - - CSP:1099452 Fixed checking WBTEXT support on dongle - - CSP:1100087 Added to set Country code by HAL - - CSP:1100314 Added exception handling codes to debug PKTID AUDIT failure - - CSP:1100314 Enhanced read/write offset calculation for debug ring to fix the memory corruption problems - - CSP:1102277 Fixed get feature by HAL - - CSP:1102660 Removed SMMU hardware cache coherency related configuration code for MSM8998 platform - - 11kv - Send BTM query after join - - Added ICMP dump log - - Fixed to read cid info from module tuple - - Fixed to use same nvram file for Murata ES 3.0 and 3.1 - - Increased static pool size from 64 to 128 for Scan timeout issue - - Supported nvram file name extension for Murata module - - Use the pre-allocated buffer pool for INFO ring to avoid memory fragmentation - - -DHD 1.579.184 - 2016.10.26 + - CS2455903 Fixed invalid RSSI during roaming + - CS2810592 Added lock to protect event and stainfo data used HotSpot BigData Logging + - CS3724694 Cancel roaming process when BSS was not matched + - CS3744556 Fixed to use SoftAP MAC address scheme as before + - CS3757724 Supported SDM845 cfg80211_roamed API changes + - CS3768340 Changed EVENT_LOG style because too many logs are being printed + - CS3796854 Added the logs to track the PCIE host wake IRQ, suspend and resume timestamps in order to help debugging + - CS3799104 Added lock to protect vndr_oui_list + - Added error handling for role mismatch case during interface remove + - Added more debug information for buffer address used debug dump + - Added more debug information for scan timeout issue + - Added more debug information when PCIe link down is occurred + - Changed scan timeout timer trigger point to scan iovar returned successfully case + - Enabled CONFIG_BCMDHD_PREALLOC_MEMDUMP and CONFIG_BCMDHD_OOB_HOST_WAKE by default for all PCIe projects + - Enabled PCIe Runtime PM + - Enhanced scan mac feature for unsupported platform + - Fixed P2P group formation failure issue + - Logging PCIE ISR and DPC timestamps to help debugging for Resumed on Timeout and D3_ACK timeout issue + - Skip sending HANG event when driver status is not READY + + +DHD 100.10.86 - 2017.09.29 New Feature - - Enabled ADPS(Advanced Dynamic Power Save) Feature - -Kernel Panic - - CSP:1094253 Fixed Kernel Panic by registering Invalid netdev interface - - CSP:1096852 Changed kmalloc flags depending on interrupt state - - CSP:1098885 Enhance event log processing to avoid the possibility of buffer overflow + - Enabled Samsung Mobile HotSpot BigData Logging + - Enabled using a vendor command to send hang reason code with more parameters + - Enhanced Debugability - Added android private commands for verbose log level + - Enhanced Debugability - Added Extended TRAP + - Enhanced Debugability - Added interface based ecounters to save for Bigdata reporting + - Enhanced Debugability - Changed mutex instead of spinlock for debug ring access + - Enhanced Debugability - Updated Buffer management -Others - - CSP:1095855 Improved DHD_LOG_DUMP feature in order to logging for throttle log - - CSP:1096927 Fixed Prevent defect issue - NULL Referencing - - CSP:1097702 Fixed SSID length check on cfg80211_get_bss() - - CSP:1100314 Fixed the calculation of read/write offset for debug ring to avoid the possibility of buffer overflow - - CSP:1101214 Changed default CID info for BCM4361B0 chip - - Temporarily Disabled Android DEBUGABILITY feature - - Added to disable APF in suspend mode when HOSTAP mode - - Enhanced the functionality of dongle register dump - - Fix not turning RPM on SoftAP - - Fixed the D3_ACK timeout issue - - Updated BCM4361 module information - - -DHD 1.579.167 - 2016.10.07 Kernel Panic - - CSP:1092776 Replace API for file writing to prevent kernel panic - - CSP:1093684 Fixed kernel panic issue by curbssid null status in wl_cfg80211_is_event_from_connected_bssid() + - CS3726729 Fixed Kernel panic while charging test Others - - CSP:1070541 Added Private driver commands for high rate beacon transmission in softAP mode - - CSP:1070541 Added Private driver commands for radio power save in softAP mode - - CSP:1070553 Supported Private DRIVER commands to grab the RSSI of associated STAs in virtual interface softAP - - CSP:1093614 Fixed host memory leak issue by missing cfg80211_put_bss() - - CSP:1093614 Fixed Prevent warning issues - - CSP:1093851 Changed DHD information file path for N OS - - CSP:1094025 Fixed DHCP failure on WiFi-Sharing mode - - Block deauth packet for WPS disorder issue - - Disable running memdump by default regardless of '.memdump.info' - - Fixed legacy connection failure - - -DHD 1.579.152 - 2016.09.22 -- Initial Release for BCM4361 Dream Project + - CS3509434 Added WLC_E_SET_SSID fail custom reason code + - CS3558828 Added NDO_CONFIG_SUPPORT + - CS3591398 Enabled TCP ACK suppress enable/disable log message + - CS3661384 Disabled WLAN_REASON_UNSPECIFIED reason code used as hang event code + - CS3697438 Added deferred_module_init call for SDM845 platform + - CS3734421 Fixed redefine issue for WAPI related define + - Added 4361B2 MURATA module information + - Added missing clear vendor OUI list for fix memory leak + - Added pspretend_retry_limit iovar for fix P2P interface delete issue during bidirection tput test + - Changed dump filename timestamp format - YYMMDDhhmmss + - Changed malloc/free function as wrapper function of MALLOC/MFREE for further debugging purpose + - Enhanced loopback test for MFG build firmware + - Fixed P2P discovery failure issue after SoftAP tear down case + - Fixed RX load balancing - Potential CPU stall issue can be happen + - Increased LOG_DUMP memory size to 4MB + - Removed interrupt mask check on IOVAR/D3_ACK recover logic + + +DHD 100.10.72 - 2017.09.15 + - Initial release for BCM4361B2 diff --git a/drivers/net/wireless/bcmdhd_oo/hnd_pktpool.c b/drivers/net/wireless/bcmdhd_oo/hnd_pktpool.c index 0c5c3a8a3525a08675e667bd86b6632541f0dd86..93ad389cf2c3c262eff31d7b4cb865e257c67f25 100644 --- a/drivers/net/wireless/bcmdhd_oo/hnd_pktpool.c +++ b/drivers/net/wireless/bcmdhd_oo/hnd_pktpool.c @@ -1,14 +1,14 @@ /* * HND generic packet pool operation primitives * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_pktpool.c 613891 2016-01-20 10:05:44Z $ + * $Id: hnd_pktpool.c 677681 2017-01-04 09:10:30Z $ */ #include @@ -32,7 +32,12 @@ #include #include #include - +#ifdef BCMRESVFRAGPOOL +#include +#endif /* BCMRESVFRAGPOOL */ +#ifdef BCMFRWDPOOLREORG +#include +#endif /* BCMFRWDPOOLREORG */ /* mutex macros for thread safe */ #ifdef HND_PKTPOOL_THREAD_SAFE @@ -45,7 +50,7 @@ #define HND_PKTPOOL_MUTEX_DELETE(mutex) OSL_EXT_SUCCESS #define HND_PKTPOOL_MUTEX_ACQUIRE(mutex, msec) OSL_EXT_SUCCESS #define HND_PKTPOOL_MUTEX_RELEASE(mutex) OSL_EXT_SUCCESS -#endif +#endif // endif /* Registry size is one larger than max pools, as slot #0 is reserved */ #define PKTPOOLREG_RSVD_ID (0U) @@ -89,7 +94,6 @@ static void pktpool_avail_notify(pktpool_t *pktp); /** accessor functions required when ROMming this file, forced into RAM */ - pktpool_t * BCMRAMFN(get_pktpools_registry)(int id) { @@ -204,7 +208,7 @@ pktpool_deregister(pktpool_t * poolptr) /** * pktpool_init: * User provides a pktpool_t structure and specifies the number of packets to - * be pre-filled into the pool (pplen). + * be pre-filled into the pool (n_pkts). * pktpool_init first attempts to register the pool and fetch a unique poolid. * If registration fails, it is considered an BCME_ERR, caused by either the * registry was not pre-created (pktpool_attach) or the registry is full. @@ -216,12 +220,13 @@ pktpool_deregister(pktpool_t * poolptr) * of packets to be allocated during pktpool_init and fill the pool up after * reclaim stage. * - * @param pplen Number of packets to be pre-filled into the pool - * @param plen The size of all packets in a pool must be the same, [bytes] units. E.g. PKTBUFSZ. - * @param type e.g. 'lbuf_frag' + * @param n_pkts Number of packets to be pre-filled into the pool + * @param max_pkt_bytes The size of all packets in a pool must be the same. E.g. PKTBUFSZ. + * @param type e.g. 'lbuf_frag' */ int -pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 type) +pktpool_init(osl_t *osh, pktpool_t *pktp, int *n_pkts, int max_pkt_bytes, bool istx, + uint8 type) { int i, err = BCME_OK; int pktplen; @@ -229,9 +234,9 @@ pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 ASSERT(pktp != NULL); ASSERT(osh != NULL); - ASSERT(pplen != NULL); + ASSERT(n_pkts != NULL); - pktplen = *pplen; + pktplen = *n_pkts; bzero(pktp, sizeof(pktpool_t)); @@ -243,7 +248,7 @@ pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 pktp->inited = TRUE; pktp->istx = istx ? TRUE : FALSE; - pktp->plen = (uint16)plen; + pktp->max_pkt_bytes = (uint16)max_pkt_bytes; pktp->type = type; if (HND_PKTPOOL_MUTEX_CREATE("pktpool", &pktp->mutex) != OSL_EXT_SUCCESS) { @@ -255,7 +260,7 @@ pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 for (i = 0; i < pktplen; i++) { void *p; - p = PKTGET(osh, plen, TRUE); + p = PKTGET(osh, max_pkt_bytes, TRUE); if (p == NULL) { /* Not able to allocate all requested pkts @@ -277,13 +282,13 @@ pktpool_init(osl_t *osh, pktpool_t *pktp, int *pplen, int plen, bool istx, uint8 #ifdef BCMDBG_POOL pktp->dbg_q[pktp->dbg_qlen++].p = p; -#endif +#endif // endif } exit: - pktp->len = pktp->avail; + pktp->n_pkts = pktp->avail; - *pplen = pktp->len; /* number of packets managed by pool */ + *n_pkts = pktp->n_pkts; /* number of packets managed by pool */ return err; } /* pktpool_init */ @@ -306,11 +311,11 @@ pktpool_deinit(osl_t *osh, pktpool_t *pktp) #ifdef BCMDBG_POOL { int i; - for (i = 0; i <= pktp->len; i++) { + for (i = 0; i <= pktp->n_pkts; i++) { pktp->dbg_q[i].p = NULL; } } -#endif +#endif // endif while (pktp->freelist != NULL) { void * p = pktp->freelist; @@ -323,13 +328,13 @@ pktpool_deinit(osl_t *osh, pktpool_t *pktp) PKTFREE(osh, p, pktp->istx); /* free the packet */ freed++; - ASSERT(freed <= pktp->len); + ASSERT(freed <= pktp->n_pkts); } pktp->avail -= freed; ASSERT(pktp->avail == 0); - pktp->len -= freed; + pktp->n_pkts -= freed; pktpool_deregister(pktp); /* release previously acquired unique pool id */ POOLSETID(pktp, PKTPOOL_INVALID_ID); @@ -340,7 +345,7 @@ pktpool_deinit(osl_t *osh, pktpool_t *pktp) pktp->inited = FALSE; /* Are there still pending pkts? */ - ASSERT(pktp->len == 0); + ASSERT(pktp->n_pkts == 0); return 0; } @@ -350,19 +355,19 @@ pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) { void *p; int err = 0; - int len, psize, maxlen; + int n_pkts, psize, maxlen; /* protect shared resource */ if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return BCME_ERROR; - ASSERT(pktp->plen != 0); + ASSERT(pktp->max_pkt_bytes != 0); maxlen = pktp->maxlen; psize = minimal ? (maxlen >> 2) : maxlen; - for (len = (int)pktp->len; len < psize; len++) { + for (n_pkts = (int)pktp->n_pkts; n_pkts < psize; n_pkts++) { - p = PKTGET(osh, pktp->len, TRUE); + p = PKTGET(osh, pktp->n_pkts, TRUE); if (p == NULL) { err = BCME_NOMEM; @@ -388,6 +393,134 @@ pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal) return err; } +#ifdef BCMPOOLRECLAIM +/* New API to decrease the pkts from pool, but not deinit +*/ +uint16 +pktpool_reclaim(osl_t *osh, pktpool_t *pktp, uint16 free_cnt) +{ + uint16 freed = 0; + + pktpool_cb_extn_t cb = NULL; + void *arg = NULL; + + ASSERT(osh != NULL); + ASSERT(pktp != NULL); + + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) { + return freed; + } + + if (pktp->avail < free_cnt) { + free_cnt = pktp->avail; + } + + if (BCMSPLITRX_ENAB() && (pktp->type == lbuf_rxfrag)) { + /* If pool is shared rx frag pool, use call back fn to reclaim host address + * and Rx cpl ID associated with the pkt. + */ + ASSERT(pktp->cbext.cb != NULL); + + cb = pktp->cbext.cb; + arg = pktp->cbext.arg; + + } else if ((pktp->type == lbuf_basic) && (pktp->rxcplidfn.cb != NULL)) { + /* If pool is shared rx pool, use call back fn to freeup Rx cpl ID + * associated with the pkt. + */ + cb = pktp->rxcplidfn.cb; + arg = pktp->rxcplidfn.arg; + } + + while ((pktp->freelist != NULL) && (free_cnt)) { + void * p = pktp->freelist; + + pktp->freelist = PKTFREELIST(p); /* unlink head packet from free list */ + PKTSETFREELIST(p, NULL); + + if (cb != NULL) { + if (cb(pktp, arg, p, REMOVE_RXCPLID)) { + PKTSETFREELIST(p, pktp->freelist); + pktp->freelist = p; + break; + } + } + + PKTSETPOOL(osh, p, FALSE, NULL); /* clear pool ID tag in pkt */ + + PKTFREE(osh, p, pktp->istx); /* free the packet */ + + freed++; + free_cnt--; + } + + pktp->avail -= freed; + + pktp->n_pkts -= freed; + + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS) { + return freed; + } + + return freed; +} +#endif /* #ifdef BCMPOOLRECLAIM */ + +/* New API to empty the pkts from pool, but not deinit +* NOTE: caller is responsible to ensure, +* all pkts are available in pool for free; else LEAK ! +*/ +int +pktpool_empty(osl_t *osh, pktpool_t *pktp) +{ + uint16 freed = 0; + + ASSERT(osh != NULL); + ASSERT(pktp != NULL); + + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return BCME_ERROR; + +#ifdef BCMDBG_POOL + { + int i; + for (i = 0; i <= pktp->n_pkts; i++) { + pktp->dbg_q[i].p = NULL; + } + } +#endif // endif + + while (pktp->freelist != NULL) { + void * p = pktp->freelist; + + pktp->freelist = PKTFREELIST(p); /* unlink head packet from free list */ + PKTSETFREELIST(p, NULL); + + PKTSETPOOL(osh, p, FALSE, NULL); /* clear pool ID tag in pkt */ + + PKTFREE(osh, p, pktp->istx); /* free the packet */ + + freed++; + ASSERT(freed <= pktp->n_pkts); + } + + pktp->avail -= freed; + ASSERT(pktp->avail == 0); + + pktp->n_pkts -= freed; + + ASSERT(pktp->n_pkts == 0); + + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS) + return BCME_ERROR; + + return 0; +} + static void * pktpool_deq(pktpool_t *pktp) { @@ -401,7 +534,6 @@ pktpool_deq(pktpool_t *pktp) p = pktp->freelist; /* dequeue packet from head of pktpool free list */ pktp->freelist = PKTFREELIST(p); /* free list points to next packet */ - PKTSETFREELIST(p, NULL); pktp->avail--; @@ -417,9 +549,8 @@ pktpool_enq(pktpool_t *pktp, void *p) PKTSETFREELIST(p, pktp->freelist); /* insert at head of pktpool free list */ pktp->freelist = p; /* free list points to newly inserted packet */ - pktp->avail++; - ASSERT(pktp->avail <= pktp->len); + ASSERT(pktp->avail <= pktp->n_pkts); } /** utility for registering host addr fill function called from pciedev */ @@ -490,6 +621,14 @@ pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ASSERT(cb != NULL); + for (i = 0; i < pktp->cbcnt; i++) { + ASSERT(pktp->cbs[i].cb != NULL); + if ((cb == pktp->cbs[i].cb) && (arg == pktp->cbs[i].arg)) { + pktp->cbs[i].refcnt++; + goto done; + } + } + i = pktp->cbcnt; if (i == PKTPOOL_CB_MAX_AVL) { err = BCME_ERROR; @@ -499,6 +638,7 @@ pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) ASSERT(pktp->cbs[i].cb == NULL); pktp->cbs[i].cb = cb; pktp->cbs[i].arg = arg; + pktp->cbs[i].refcnt++; pktp->cbcnt++; done: @@ -509,6 +649,54 @@ done: return err; } +/* No BCMATTACHFN as it is used in a non-attach function */ +int +pktpool_avail_deregister(pktpool_t *pktp, pktpool_cb_t cb, void *arg) +{ + int err = 0; + int i, k; + + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) { + return BCME_ERROR; + } + + ASSERT(cb != NULL); + + for (i = 0; i < pktp->cbcnt; i++) { + ASSERT(pktp->cbs[i].cb != NULL); + if ((cb == pktp->cbs[i].cb) && (arg == pktp->cbs[i].arg)) { + pktp->cbs[i].refcnt--; + if (pktp->cbs[i].refcnt) { + /* Still there are references to this callback */ + goto done; + } + /* Moving any more callbacks to fill the hole */ + for (k = i+1; k < pktp->cbcnt; i++, k++) { + pktp->cbs[i].cb = pktp->cbs[k].cb; + pktp->cbs[i].arg = pktp->cbs[k].arg; + pktp->cbs[i].refcnt = pktp->cbs[k].refcnt; + } + + /* reset the last callback */ + pktp->cbs[i].cb = NULL; + pktp->cbs[i].arg = NULL; + pktp->cbs[i].refcnt = 0; + + pktp->cbcnt--; + goto done; + } + } + +done: + /* protect shared resource */ + if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS) { + return BCME_ERROR; + } + + return err; +} + /** Registers callback functions */ int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg) @@ -845,7 +1033,6 @@ pktpool_get(pktpool_t *pktp) if (HND_PKTPOOL_MUTEX_ACQUIRE(&pktp->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - p = pktpool_deq(pktp); if (p == NULL) { @@ -858,7 +1045,6 @@ pktpool_get(pktpool_t *pktp) goto done; } - done: /* protect shared resource */ if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS) @@ -877,7 +1063,7 @@ pktpool_free(pktpool_t *pktp, void *p) ASSERT(p != NULL); #ifdef BCMDBG_POOL /* pktpool_stop_trigger(pktp, p); */ -#endif +#endif // endif pktpool_enq(pktp, p); @@ -923,21 +1109,21 @@ pktpool_add(pktpool_t *pktp, void *p) ASSERT(p != NULL); - if (pktp->len == pktp->maxlen) { + if (pktp->n_pkts == pktp->maxlen) { err = BCME_RANGE; goto done; } /* pkts in pool have same length */ - ASSERT(pktp->plen == PKTLEN(OSH_NULL, p)); + ASSERT(pktp->max_pkt_bytes == PKTLEN(OSH_NULL, p)); PKTSETPOOL(OSH_NULL, p, TRUE, pktp); - pktp->len++; + pktp->n_pkts++; pktpool_enq(pktp, p); #ifdef BCMDBG_POOL pktp->dbg_q[pktp->dbg_qlen++].p = p; -#endif +#endif // endif done: /* protect shared resource */ @@ -965,7 +1151,7 @@ BCMRAMFN(pktpool_setmaxlen)(pktpool_t *pktp, uint16 maxlen) * since we currently do not reduce the pool len * already allocated */ - pktp->maxlen = (pktp->len > maxlen) ? pktp->len : maxlen; + pktp->maxlen = (pktp->n_pkts > maxlen) ? pktp->n_pkts : maxlen; /* protect shared resource */ if (HND_PKTPOOL_MUTEX_RELEASE(&pktp->mutex) != OSL_EXT_SUCCESS) @@ -1009,6 +1195,10 @@ pktpool_t *pktpool_shared = NULL; #ifdef BCMFRAGPOOL pktpool_t *pktpool_shared_lfrag = NULL; +#ifdef BCMRESVFRAGPOOL +pktpool_t *pktpool_resv_lfrag = NULL; +struct resv_info *resv_pool_info = NULL; +#endif /* BCMRESVFRAGPOOL */ #endif /* BCMFRAGPOOL */ pktpool_t *pktpool_shared_rxlfrag = NULL; @@ -1021,7 +1211,7 @@ static osl_t *pktpool_osh = NULL; int hnd_pktpool_init(osl_t *osh) { - int err; + int err = BCME_OK; int n; /* Construct a packet pool registry before initializing packet pools */ @@ -1046,7 +1236,19 @@ hnd_pktpool_init(osl_t *osh) err = BCME_NOMEM; goto error2; } -#endif +#if defined(BCMRESVFRAGPOOL) && !defined(BCMRESVFRAGPOOL_DISABLED) + resv_pool_info = hnd_resv_pool_alloc(osh); + if (resv_pool_info == NULL) { + ASSERT(0); + goto error2; + } + pktpool_resv_lfrag = resv_pool_info->pktp; + if (pktpool_resv_lfrag == NULL) { + ASSERT(0); + goto error2; + } +#endif /* RESVFRAGPOOL */ +#endif /* FRAGPOOL */ #if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED) pktpool_shared_rxlfrag = MALLOCZ(osh, sizeof(pktpool_t)); @@ -1055,8 +1257,7 @@ hnd_pktpool_init(osl_t *osh) err = BCME_NOMEM; goto error3; } -#endif - +#endif // endif /* * At this early stage, there's not enough memory to allocate all @@ -1072,6 +1273,7 @@ hnd_pktpool_init(osl_t *osh) * were not filled into the pool. */ n = 1; + MALLOC_SET_NOPERSIST(osh); /* Ensure subsequent allocations are non-persist */ if ((err = pktpool_init(osh, pktpool_shared, &n, PKTBUFSZ, FALSE, lbuf_basic)) != BCME_OK) { ASSERT(0); @@ -1087,7 +1289,16 @@ hnd_pktpool_init(osl_t *osh) goto error5; } pktpool_setmaxlen(pktpool_shared_lfrag, SHARED_FRAG_POOL_LEN); -#endif +#if defined(BCMRESVFRAGPOOL) && !defined(BCMRESVFRAGPOOL_DISABLED) + n = 0; /* IMPORTANT: DO NOT allocate any packets in resv pool */ + if (pktpool_init(osh, pktpool_resv_lfrag, + &n, PKTFRAGSZ, TRUE, lbuf_frag) == BCME_ERROR) { + ASSERT(0); + goto error5; + } + pktpool_setmaxlen(pktpool_resv_lfrag, RESV_FRAG_POOL_LEN); +#endif /* RESVFRAGPOOL */ +#endif /* BCMFRAGPOOL */ #if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED) n = 1; if ((err = pktpool_init(osh, pktpool_shared_rxlfrag, @@ -1096,25 +1307,52 @@ hnd_pktpool_init(osl_t *osh) goto error6; } pktpool_setmaxlen(pktpool_shared_rxlfrag, SHARED_RXFRAG_POOL_LEN); -#endif +#endif // endif + +#if defined(BCMFRWDPOOLREORG) && !defined(BCMFRWDPOOLREORG_DISABLED) + /* Attach poolreorg module */ + if ((frwd_poolreorg_info = poolreorg_attach(osh, +#if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED) + pktpool_shared_lfrag, +#else + NULL, +#endif // endif +#if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED) + pktpool_shared_rxlfrag, +#else + NULL, +#endif // endif + pktpool_shared)) == NULL) { + ASSERT(0); + goto error7; + } +#endif /* defined(BCMFRWDPOOLREORG) && !defined(BCMFRWDPOOLREORG_DISABLED) */ pktpool_osh = osh; + MALLOC_CLEAR_NOPERSIST(osh); return BCME_OK; +#if defined(BCMFRWDPOOLREORG) && !defined(BCMFRWDPOOLREORG_DISABLED) + /* detach poolreorg module */ + poolreorg_detach(frwd_poolreorg_info); +error7: +#endif /* defined(BCMFRWDPOOLREORG) && !defined(BCMFRWDPOOLREORG_DISABLED) */ + #if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED) + pktpool_deinit(osh, pktpool_shared_rxlfrag); error6: -#endif +#endif // endif #if defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED) pktpool_deinit(osh, pktpool_shared_lfrag); error5: -#endif +#endif // endif #if (defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED)) || \ (defined(BCMFRAGPOOL) && !defined(BCMFRAGPOOL_DISABLED)) pktpool_deinit(osh, pktpool_shared); -#endif +#endif // endif error4: #if defined(BCMRXFRAGPOOL) && !defined(BCMRXFRAGPOOL_DISABLED) @@ -1135,38 +1373,40 @@ error2: error1: pktpool_dettach(osh); error0: + MALLOC_CLEAR_NOPERSIST(osh); return err; } /* hnd_pktpool_init */ +/** is called at each 'wl up' */ int hnd_pktpool_fill(pktpool_t *pktpool, bool minimal) { return (pktpool_fill(pktpool_osh, pktpool, minimal)); } -/** refills pktpools after reclaim */ +/** refills pktpools after reclaim, is called once */ void hnd_pktpool_refill(bool minimal) { if (POOL_ENAB(pktpool_shared)) { - pktpool_fill(pktpool_osh, pktpool_shared, minimal); - } -/* fragpool reclaim */ -#ifdef BCMFRAGPOOL - if (POOL_ENAB(pktpool_shared_lfrag)) { #if defined(SRMEM) if (SRMEM_ENAB()) { - int maxlen = pktpool_maxlen(pktpool_shared); - int len = pktpool_len(pktpool_shared); + int maxlen = pktpool_max_pkts(pktpool_shared); + int n_pkts = pktpool_tot_pkts(pktpool_shared); - for (; len < maxlen; len++) { + for (; n_pkts < maxlen; n_pkts++) { void *p; - if ((p = PKTSRGET(pktpool_plen(pktpool_shared))) == NULL) + if ((p = PKTSRGET(pktpool_max_pkt_bytes(pktpool_shared))) == NULL) break; pktpool_add(pktpool_shared, p); } } #endif /* SRMEM */ + pktpool_fill(pktpool_osh, pktpool_shared, minimal); + } +/* fragpool reclaim */ +#ifdef BCMFRAGPOOL + if (POOL_ENAB(pktpool_shared_lfrag)) { pktpool_fill(pktpool_osh, pktpool_shared_lfrag, minimal); } #endif /* BCMFRAGPOOL */ @@ -1175,6 +1415,13 @@ hnd_pktpool_refill(bool minimal) if (POOL_ENAB(pktpool_shared_rxlfrag)) { pktpool_fill(pktpool_osh, pktpool_shared_rxlfrag, minimal); } -#endif +#endif // endif +#if defined(BCMFRAGPOOL) && defined(BCMRESVFRAGPOOL) + if (POOL_ENAB(pktpool_resv_lfrag)) { + int resv_size = (PKTFRAGSZ + LBUFFRAGSZ)*RESV_FRAG_POOL_LEN; + hnd_resv_pool_init(resv_pool_info, resv_size); + hnd_resv_pool_enable(resv_pool_info); + } +#endif /* BCMRESVFRAGPOOL */ } #endif /* BCMPKTPOOL */ diff --git a/drivers/net/wireless/bcmdhd_oo/hnd_pktq.c b/drivers/net/wireless/bcmdhd_oo/hnd_pktq.c index 743a23601a012886efd280dcce3f7c8e17052dbb..6027133e813a74eb64272a45823fb9d7c4a638d7 100644 --- a/drivers/net/wireless/bcmdhd_oo/hnd_pktq.c +++ b/drivers/net/wireless/bcmdhd_oo/hnd_pktq.c @@ -1,14 +1,14 @@ /* * HND generic pktq operation primitives * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_pktq.c 644628 2016-06-21 06:25:58Z $ + * $Id: hnd_pktq.c 698847 2017-05-11 00:10:48Z $ */ #include @@ -44,8 +44,13 @@ #define HND_PKTQ_MUTEX_DELETE(mutex) OSL_EXT_SUCCESS #define HND_PKTQ_MUTEX_ACQUIRE(mutex, msec) OSL_EXT_SUCCESS #define HND_PKTQ_MUTEX_RELEASE(mutex) OSL_EXT_SUCCESS -#endif /* */ +#endif /* HND_PKTQ_THREAD_SAFE */ +/* status during txfifo sync */ +#if defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) +#define TXQ_PKT_DEL 0x01 +#define HEAD_PKT_FLUSHED 0xFF +#endif /* defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) */ /* * osl multiple-precedence packet queue * hi_prec is always >= the number of the highest non-empty precedence @@ -63,7 +68,7 @@ pktq_penq(struct pktq *pq, int prec, void *p) ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -73,9 +78,9 @@ pktq_penq(struct pktq *pq, int prec, void *p) q->head = p; q->tail = p; - q->len++; + q->n_pkts++; - pq->len++; + pq->n_pkts_tot++; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; @@ -87,6 +92,39 @@ pktq_penq(struct pktq *pq, int prec, void *p) return p; } +/* + * osl simple, non-priority packet queue + */ +void * BCMFASTPATH +spktq_enq(struct spktq *spq, void *p) +{ + struct pktq_prec *q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(!spktq_full(spq)); + + PKTSETLINK(p, NULL); + + q = &spq->q; + + if (q->head) + PKTSETLINK(q->tail, p); + else + q->head = p; + + q->tail = p; + q->n_pkts++; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + void * BCMFASTPATH pktq_penq_head(struct pktq *pq, int prec, void *p) { @@ -100,7 +138,7 @@ pktq_penq_head(struct pktq *pq, int prec, void *p) ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -109,9 +147,9 @@ pktq_penq_head(struct pktq *pq, int prec, void *p) PKTSETLINK(p, q->head); q->head = p; - q->len++; + q->n_pkts++; - pq->len++; + pq->n_pkts_tot++; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; @@ -123,6 +161,215 @@ pktq_penq_head(struct pktq *pq, int prec, void *p) return p; } +void * BCMFASTPATH +spktq_enq_head(struct spktq *spq, void *p) +{ + struct pktq_prec *q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(!spktq_full(spq)); + + PKTSETLINK(p, NULL); + + q = &spq->q; + + if (q->head == NULL) + q->tail = p; + + PKTSETLINK(p, q->head); + q->head = p; + q->n_pkts++; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +pktq_pdeq(struct pktq *pq, int prec) +{ + struct pktq_prec *q; + void *p; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + goto done; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->n_pkts--; + + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + + PKTSETLINK(p, NULL); + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +spktq_deq(struct spktq *spq) +{ + struct pktq_prec *q; + void *p; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + q = &spq->q; + + if ((p = q->head) == NULL) + goto done; + + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + + PKTSETLINK(p, NULL); + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +pktq_pdeq_tail(struct pktq *pq, int prec) +{ + struct pktq_prec *q; + void *p, *prev; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + + if ((p = q->head) == NULL) + goto done; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->n_pkts--; + + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * BCMFASTPATH +spktq_deq_tail(struct spktq *spq) +{ + struct pktq_prec *q; + void *p, *prev; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + q = &spq->q; + + if ((p = q->head) == NULL) + goto done; + + for (prev = NULL; p != q->tail; p = PKTLINK(p)) + prev = p; + + if (prev) + PKTSETLINK(prev, NULL); + else + q->head = NULL; + + q->tail = prev; + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + +void * +pktq_peek_tail(struct pktq *pq, int *prec_out) +{ + int prec; + void *p = NULL; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return NULL; + + if (pq->n_pkts_tot == 0) + goto done; + + for (prec = 0; prec < pq->hi_prec; prec++) + if (pq->q[prec].head) + break; + + if (prec_out) + *prec_out = prec; + + p = pq->q[prec].tail; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + return NULL; + + return p; +} + /* * Append spktq 'list' to the tail of pktq 'pq' */ @@ -136,7 +383,7 @@ pktq_append(struct pktq *pq, int prec, struct spktq *list) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return; - list_q = &list->q[0]; + list_q = &list->q; /* empty list check */ if (list_q->head == NULL) @@ -146,7 +393,7 @@ pktq_append(struct pktq *pq, int prec, struct spktq *list) ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -156,16 +403,19 @@ pktq_append(struct pktq *pq, int prec, struct spktq *list) q->head = list_q->head; q->tail = list_q->tail; - q->len += list_q->len; - pq->len += list_q->len; + q->n_pkts += list_q->n_pkts; + pq->n_pkts_tot += list_q->n_pkts; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + list_q->head = NULL; list_q->tail = NULL; - list_q->len = 0; - list->len = 0; + list_q->n_pkts = 0; done: /* protect shared resource */ @@ -173,6 +423,53 @@ done: return; } +/* + * Append spktq 'list' to the tail of spktq 'spq' + */ +void BCMFASTPATH +spktq_append(struct spktq *spq, struct spktq *list) +{ + struct pktq_prec *q; + struct pktq_prec *list_q; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + list_q = &list->q; + + /* empty list check */ + if (list_q->head == NULL) + goto done; + + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ + + ASSERT(!spktq_full(spq)); + + q = &spq->q; + + if (q->head) + PKTSETLINK(q->tail, list_q->head); + else + q->head = list_q->head; + + q->tail = list_q->tail; + q->n_pkts += list_q->n_pkts; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; + +done: + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; +} + /* * Prepend spktq 'list' to the head of pktq 'pq' */ @@ -186,7 +483,7 @@ pktq_prepend(struct pktq *pq, int prec, struct spktq *list) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return; - list_q = &list->q[0]; + list_q = &list->q; /* empty list check */ if (list_q->head == NULL) @@ -196,7 +493,7 @@ pktq_prepend(struct pktq *pq, int prec, struct spktq *list) ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); + ASSERT(!pktqprec_full(pq, prec)); q = &pq->q[prec]; @@ -212,16 +509,19 @@ pktq_prepend(struct pktq *pq, int prec, struct spktq *list) q->tail = list_q->tail; } - q->len += list_q->len; - pq->len += list_q->len; + q->n_pkts += list_q->n_pkts; + pq->n_pkts_tot += list_q->n_pkts; if (pq->hi_prec < prec) pq->hi_prec = (uint8)prec; +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + list_q->head = NULL; list_q->tail = NULL; - list_q->len = 0; - list->len = 0; + list_q->n_pkts = 0; done: /* protect shared resource */ @@ -229,38 +529,57 @@ done: return; } -void * BCMFASTPATH -pktq_pdeq(struct pktq *pq, int prec) +/* + * Prepend spktq 'list' to the head of spktq 'spq' + */ +void BCMFASTPATH +spktq_prepend(struct spktq *spq, struct spktq *list) { struct pktq_prec *q; - void *p; + struct pktq_prec *list_q; /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return NULL; - - ASSERT(prec >= 0 && prec < pq->num_prec); + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; - q = &pq->q[prec]; + list_q = &list->q; - if ((p = q->head) == NULL) + /* empty list check */ + if (list_q->head == NULL) goto done; - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; + ASSERT(PKTLINK(list_q->tail) == NULL); /* terminated list */ - q->len--; + ASSERT(!spktq_full(spq)); - pq->len--; + q = &spq->q; - PKTSETLINK(p, NULL); + /* set the tail packet of list to point at the former pq head */ + PKTSETLINK(list_q->tail, q->head); + /* the new q head is the head of list */ + q->head = list_q->head; + + /* If the q tail was non-null, then it stays as is. + * If the q tail was null, it is now the tail of list + */ + if (q->tail == NULL) { + q->tail = list_q->tail; + } + + q->n_pkts += list_q->n_pkts; + +#ifdef WL_TXQ_STALL + list_q->dequeue_count += list_q->n_pkts; +#endif // endif + + list_q->head = NULL; + list_q->tail = NULL; + list_q->n_pkts = 0; done: /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return NULL; - - return p; + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; } void * BCMFASTPATH @@ -283,10 +602,13 @@ pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) if ((p = PKTLINK(prev_p)) == NULL) goto done; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(prev_p, PKTLINK(p)); PKTSETLINK(p, NULL); @@ -335,10 +657,13 @@ pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg) } } - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif PKTSETLINK(p, NULL); done: @@ -349,44 +674,6 @@ done: return p; } -void * BCMFASTPATH -pktq_pdeq_tail(struct pktq *pq, int prec) -{ - struct pktq_prec *q; - void *p, *prev; - - /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) - return NULL; - - ASSERT(prec >= 0 && prec < pq->num_prec); - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - goto done; - - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; - - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; - - q->tail = prev; - q->len--; - - pq->len--; - -done: - /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) - return NULL; - - return p; -} - bool BCMFASTPATH pktq_pdel(struct pktq *pq, void *pktbuf, int prec) { @@ -420,8 +707,13 @@ pktq_pdel(struct pktq *pq, void *pktbuf, int prec) q->tail = p; } - q->len--; - pq->len--; + q->n_pkts--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif + PKTSETLINK(pktbuf, NULL); ret = TRUE; @@ -452,9 +744,13 @@ _pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void* fltr_ctx, q->head = NULL; q->tail = NULL; - q->len = 0; + q->n_pkts = 0; + +#ifdef WL_TXQ_STALL + q->dequeue_count += wq.n_pkts; +#endif // endif - pq->len -= wq.len; + pq->n_pkts_tot -= wq.n_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -465,7 +761,11 @@ _pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void* fltr_ctx, /* unlink the current packet from the list */ wq.head = PKTLINK(p); PKTSETLINK(p, NULL); - wq.len--; + wq.n_pkts--; + +#ifdef WL_TXQ_STALL + wq.dequeue_count++; +#endif // endif /* call the filter function on current packet */ ASSERT(fltr != NULL); @@ -491,7 +791,7 @@ _pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fltr, void* fltr_ctx, } } - ASSERT(wq.len == 0); + ASSERT(wq.n_pkts == 0); } void @@ -514,10 +814,10 @@ pktq_filter(struct pktq *pq, pktq_filter_t fltr, void* fltr_ctx, if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return; - /* Optimize if pktq len = 0, just return. + /* Optimize if pktq n_pkts = 0, just return. * pktq len of 0 means pktq's prec q's are all empty. */ - if (pq->len > 0) { + if (pq->n_pkts_tot > 0) { filter = TRUE; } @@ -537,25 +837,114 @@ pktq_filter(struct pktq *pq, pktq_filter_t fltr, void* fltr_ctx, } } +void +spktq_filter(struct spktq *spq, pktq_filter_t fltr, void* fltr_ctx, + defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx) +{ + struct pktq_prec wq; + struct pktq_prec *q; + void *p = NULL; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return; + + q = &spq->q; + + /* Optimize if pktq_prec n_pkts = 0, just return. */ + if (q->n_pkts == 0) { + (void)HND_PKTQ_MUTEX_RELEASE(&spq->mutex); + return; + } + + wq = *q; + + q->head = NULL; + q->tail = NULL; + q->n_pkts = 0; + +#ifdef WL_TXQ_STALL + q->dequeue_count += wq.n_pkts; +#endif // endif + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return; + + /* start with the head of the work queue */ + + while ((p = wq.head) != NULL) { + /* unlink the current packet from the list */ + wq.head = PKTLINK(p); + PKTSETLINK(p, NULL); + wq.n_pkts--; + +#ifdef WL_TXQ_STALL + wq.dequeue_count++; +#endif // endif + + /* call the filter function on current packet */ + ASSERT(fltr != NULL); + switch ((*fltr)(fltr_ctx, p)) { + case PKT_FILTER_NOACTION: + /* put this packet back */ + spktq_enq(spq, p); + break; + + case PKT_FILTER_DELETE: + /* delete this packet */ + ASSERT(defer != NULL); + (*defer)(defer_ctx, p); + break; + + case PKT_FILTER_REMOVE: + /* pkt already removed from list */ + break; + + default: + ASSERT(0); + break; + } + } + + ASSERT(wq.n_pkts == 0); + + ASSERT(flush != NULL); + (*flush)(flush_ctx); +} + bool -pktq_init(struct pktq *pq, int num_prec, int max_len) +pktq_init(struct pktq *pq, int num_prec, int max_pkts) { int prec; - if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS) - return FALSE; - ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); /* pq is variable size; only zero out what's requested */ bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); + if (HND_PKTQ_MUTEX_CREATE("pktq", &pq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + pq->num_prec = (uint16)num_prec; - pq->max = (uint16)max_len; + pq->max_pkts = (uint16)max_pkts; for (prec = 0; prec < num_prec; prec++) - pq->q[prec].max = pq->max; + pq->q[prec].max_pkts = pq->max_pkts; + + return TRUE; +} + +bool +spktq_init(struct spktq *spq, int max_pkts) +{ + bzero(spq, sizeof(struct spktq)); + + if (HND_PKTQ_MUTEX_CREATE("spktq", &spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + spq->q.max_pkts = (uint16)max_pkts; return TRUE; } @@ -570,8 +959,18 @@ pktq_deinit(struct pktq *pq) return TRUE; } +bool +spktq_deinit(struct spktq *spq) +{ + BCM_REFERENCE(spq); + if (HND_PKTQ_MUTEX_DELETE(&spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + return TRUE; +} + void -pktq_set_max_plen(struct pktq *pq, int prec, int max_len) +pktq_set_max_plen(struct pktq *pq, int prec, int max_pkts) { ASSERT(prec >= 0 && prec < pq->num_prec); @@ -580,7 +979,7 @@ pktq_set_max_plen(struct pktq *pq, int prec, int max_len) return; if (prec < pq->num_prec) - pq->q[prec].max = (uint16)max_len; + pq->q[prec].max_pkts = (uint16)max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -598,7 +997,7 @@ pktq_deq(struct pktq *pq, int *prec_out) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -612,9 +1011,13 @@ pktq_deq(struct pktq *pq, int *prec_out) if ((q->head = PKTLINK(p)) == NULL) q->tail = NULL; - q->len--; + q->n_pkts--; - pq->len--; + pq->n_pkts_tot--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; @@ -640,7 +1043,7 @@ pktq_deq_tail(struct pktq *pq, int *prec_out) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; for (prec = 0; prec < pq->hi_prec; prec++) @@ -661,9 +1064,13 @@ pktq_deq_tail(struct pktq *pq, int *prec_out) q->head = NULL; q->tail = prev; - q->len--; + q->n_pkts--; + + pq->n_pkts_tot--; - pq->len--; +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; @@ -688,7 +1095,7 @@ pktq_peek(struct pktq *pq, int *prec_out) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -708,30 +1115,22 @@ done: } void * -pktq_peek_tail(struct pktq *pq, int *prec_out) +spktq_peek(struct spktq *spq) { - int prec; void *p = NULL; /* protect shared resource */ - if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (spq->q.n_pkts == 0) goto done; - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; - - if (prec_out) - *prec_out = prec; - - p = pq->q[prec].tail; + p = spq->q.head; done: /* protect shared resource */ - if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) return NULL; return p; @@ -752,6 +1151,21 @@ pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir) } } +void +spktq_flush(osl_t *osh, struct spktq *spq, bool dir) +{ + void *p; + + /* no need for a mutex protection! */ + + /* start with the head of the list */ + while ((p = spktq_deq(spq)) != NULL) { + + /* delete this packet */ + PKTFREE(osh, p, dir); + } +} + void pktq_flush(osl_t *osh, struct pktq *pq, bool dir) { @@ -761,10 +1175,10 @@ pktq_flush(osl_t *osh, struct pktq *pq, bool dir) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return; - /* Optimize flush, if pktq len = 0, just return. + /* Optimize flush, if pktq n_pkts_tot = 0, just return. * pktq len of 0 means pktq's prec q's are all empty. */ - if (pq->len > 0) { + if (pq->n_pkts_tot > 0) { flush = TRUE; } @@ -795,7 +1209,7 @@ pktq_mlen(struct pktq *pq, uint prec_bmp) for (prec = 0; prec <= pq->hi_prec; prec++) if (prec_bmp & (1 << prec)) - len += pq->q[prec].len; + len += pq->q[prec].n_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -816,7 +1230,7 @@ pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -853,7 +1267,7 @@ pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return NULL; - if (pq->len == 0) + if (pq->n_pkts_tot == 0) goto done; while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) @@ -871,12 +1285,16 @@ pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) if ((q->head = PKTLINK(p)) == NULL) q->tail = NULL; - q->len--; + q->n_pkts--; + +#ifdef WL_TXQ_STALL + q->dequeue_count++; +#endif // endif if (prec_out) *prec_out = prec; - pq->len--; + pq->n_pkts_tot--; PKTSETLINK(p, NULL); @@ -890,7 +1308,7 @@ done: #ifdef HND_PKTQ_THREAD_SAFE int -pktq_pavail(struct pktq *pq, int prec) +pktqprec_avail_pkts(struct pktq *pq, int prec) { int ret; @@ -900,7 +1318,7 @@ pktq_pavail(struct pktq *pq, int prec) ASSERT(prec >= 0 && prec < pq->num_prec); - ret = pq->q[prec].max - pq->q[prec].len; + ret = pq->q[prec].max_pkts - pq->q[prec].n_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -910,7 +1328,7 @@ pktq_pavail(struct pktq *pq, int prec) } bool -pktq_pfull(struct pktq *pq, int prec) +pktqprec_full(struct pktq *pq, int prec) { bool ret; @@ -920,7 +1338,7 @@ pktq_pfull(struct pktq *pq, int prec) ASSERT(prec >= 0 && prec < pq->num_prec); - ret = pq->q[prec].len >= pq->q[prec].max; + ret = pq->q[prec].n_pkts >= pq->q[prec].max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -938,7 +1356,7 @@ pktq_avail(struct pktq *pq) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return 0; - ret = pq->max - pq->len; + ret = pq->max_pkts - pq->n_pkts_tot; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -947,6 +1365,24 @@ pktq_avail(struct pktq *pq) return ret; } +int +spktq_avail(struct spktq *spq) +{ + int ret; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return 0; + + ret = spq->q.max_pkts - spq->q.n_pkts; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return 0; + + return ret; +} + bool pktq_full(struct pktq *pq) { @@ -956,7 +1392,7 @@ pktq_full(struct pktq *pq) if (HND_PKTQ_MUTEX_ACQUIRE(&pq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) return FALSE; - ret = pq->len >= pq->max; + ret = pq->n_pkts_tot >= pq->max_pkts; /* protect shared resource */ if (HND_PKTQ_MUTEX_RELEASE(&pq->mutex) != OSL_EXT_SUCCESS) @@ -964,4 +1400,23 @@ pktq_full(struct pktq *pq) return ret; } + +bool +spktq_full(struct spktq *spq) +{ + bool ret; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_ACQUIRE(&spq->mutex, OSL_EXT_TIME_FOREVER) != OSL_EXT_SUCCESS) + return FALSE; + + ret = spq->q.n_pkts >= spq->q.max_pkts; + + /* protect shared resource */ + if (HND_PKTQ_MUTEX_RELEASE(&spq->mutex) != OSL_EXT_SUCCESS) + return FALSE; + + return ret; +} + #endif /* HND_PKTQ_THREAD_SAFE */ diff --git a/drivers/net/wireless/bcmdhd_oo/hndpmu.c b/drivers/net/wireless/bcmdhd_oo/hndpmu.c index c76a943dab38e56483969a51fc881aeb0c36f76d..3a6da91ce9925695987748d8c06ac412edb37bed 100644 --- a/drivers/net/wireless/bcmdhd_oo/hndpmu.c +++ b/drivers/net/wireless/bcmdhd_oo/hndpmu.c @@ -2,14 +2,14 @@ * Misc utility routines for accessing PMU corerev specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,15 +25,15 @@ * * <> * - * $Id: hndpmu.c 657872 2016-09-02 22:17:34Z $ + * $Id: hndpmu.c 714395 2017-08-04 08:22:31Z $ */ - -/* +/** + * @file * 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. + * Throughout this code, the prefixes 'pmu1_' and 'pmu2_' are used. * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012) * pmu1_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop). It supports * fractional frequency generation. pmu2_ does not support fractional frequency generation. @@ -48,15 +48,18 @@ #include #include #include +#include #include +#include #if defined(BCMULP) #include #endif /* defined(BCMULP) */ #include #ifdef EVENT_LOG_COMPILE #include -#endif +#endif // endif #include +#include #define PMU_ERROR(args) @@ -66,6 +69,7 @@ * to be on except on private builds. */ #define PMU_NONE(args) +#define flags_shift 14 /** contains resource bit positions for a specific chip */ struct rsc_per_chip_s { @@ -73,110 +77,16 @@ struct rsc_per_chip_s { uint8 macphy_clkavail; uint8 ht_start; uint8 otp_pu; + uint8 macphy_aux_clkavail; }; typedef struct rsc_per_chip_s rsc_per_chip_t; - -/* SDIO Pad drive strength to select value mappings. - * The last strength value in each table must be 0 (the tri-state value). - */ -typedef struct { - uint8 strength; /* Pad Drive Strength in mA */ - uint8 sel; /* Chip-specific select value */ -} sdiod_drive_str_t; - -/* SDIO Drive Strength to sel value table for PMU Rev 1 */ -static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = { - {4, 0x2}, - {2, 0x3}, - {1, 0x0}, - {0, 0x0} }; - -/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ -static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = { - {12, 0x7}, - {10, 0x6}, - {8, 0x5}, - {6, 0x4}, - {4, 0x2}, - {2, 0x1}, - {0, 0x0} }; - - -/* SDIO Drive Strength to sel value table for PMU Rev 8 (1.8V) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab3[] = { - {32, 0x7}, - {26, 0x6}, - {22, 0x5}, - {16, 0x4}, - {12, 0x3}, - {8, 0x2}, - {4, 0x1}, - {0, 0x0} }; - -/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.8v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = { - {32, 0x6}, - {26, 0x7}, - {22, 0x4}, - {16, 0x5}, - {12, 0x2}, - {8, 0x3}, - {4, 0x0}, - {0, 0x1} }; - -/* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */ - -/* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */ - -/* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { - {6, 0x7}, - {5, 0x6}, - {4, 0x5}, - {3, 0x4}, - {2, 0x2}, - {1, 0x1}, - {0, 0x0} }; - -/* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */ - -/** SDIO Drive Strength to sel value table for PMU Rev 17 (1.8v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = { - {3, 0x3}, - {2, 0x2}, - {1, 0x1}, - {0, 0x0} }; - - -/** - * SDIO Drive Strength to sel value table for 43143 PMU Rev 17, see Confluence 43143 Toplevel - * architecture page, section 'PMU Chip Control 1 Register definition', click link to picture - * BCM43143_sel_sdio_signals.jpg. Valid after PMU Chip Control 0 Register, bit31 (override) has - * been written '1'. - */ -#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 - -static const sdiod_drive_str_t sdiod_drive_strength_tab7_3v3[] = { - /* note: for 14, 10, 6 and 2mA hw timing is not met according to rtl team */ - {16, 0x7}, - {12, 0x5}, - {8, 0x3}, - {4, 0x1} }; /* note: 43143 does not support tristate */ - +#if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED) +bool _pmustatsenab = TRUE; #else - -static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = { - /* note: for 7, 5, 3 and 1mA hw timing is not met according to rtl team */ - {8, 0x7}, - {6, 0x5}, - {4, 0x3}, - {2, 0x1} }; /* note: 43143 does not support tristate */ - -#endif /* BCM_SDIO_VDDIO */ - -#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) +bool _pmustatsenab = FALSE; +#endif /* BCMPMU_STATS */ /** * Balance between stable SDIO operation and power consumption is achieved using this function. @@ -190,106 +100,151 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab7_1v8[] = { void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) { - sdiod_drive_str_t *str_tab = NULL; - uint32 str_mask = 0; /* only alter desired bits in PMU chipcontrol 1 register */ - uint32 str_shift = 0; - uint32 str_ovr_pmuctl = PMU_CHIPCTL0; /* PMU chipcontrol register containing override bit */ - uint32 str_ovr_pmuval = 0; /* position of bit within this register */ - pmuregs_t *pmu; + /* + * Note: + * This function used to set the SDIO drive strength via PMU_CHIPCTL1 for the + * 43143, 4330, 4334, 4336, 43362 chips. These chips are now no longer supported, so + * the code has been deleted. + * Newer chips have the SDIO drive strength setting via a GCI Chip Control register, + * but the bit definitions are chip-specific. We are keeping this function available + * (accessed via DHD 'sdiod_drive' IOVar) in case these newer chips need to provide access. + */ + UNUSED_PARAMETER(sih); + UNUSED_PARAMETER(osh); + UNUSED_PARAMETER(drivestrength); +} + +void +si_switch_pmu_dependency(si_t *sih, uint mode) +{ +#ifdef DUAL_PMU_SEQUENCE + osl_t *osh = si_osh(sih); + uint32 current_res_state; + uint32 min_mask, max_mask; + const pmu_res_depend_t *pmu_res_depend_table = NULL; + uint pmu_res_depend_table_sz = 0; uint origidx; + pmuregs_t *pmu; + chipcregs_t *cc; + BCM_REFERENCE(cc); - if (!(sih->cccaps & CC_CAP_PMU)) { - return; - } - BCM_REFERENCE(sdiod_drive_strength_tab1); - BCM_REFERENCE(sdiod_drive_strength_tab2); - /* Remember original core before switch to chipc/pmu */ origidx = si_coreidx(sih); if (AOB_ENAB(sih)) { pmu = si_setcore(sih, PMU_CORE_ID, 0); + cc = si_setcore(sih, CC_CORE_ID, 0); } else { pmu = si_setcoreidx(sih, SI_CC_IDX); + cc = si_setcoreidx(sih, SI_CC_IDX); } ASSERT(pmu != NULL); - switch (SDIOD_DRVSTR_KEY(CHIPID(sih->chip), PMUREV(sih->pmurev))) { - case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 8): - case SDIOD_DRVSTR_KEY(BCM4336_CHIP_ID, 11): - if (PMUREV(sih->pmurev) == 8) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab3; - } else if (PMUREV(sih->pmurev) == 11) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; - } - str_mask = 0x00003800; - str_shift = 11; - break; - case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab4_1v8; - str_mask = 0x00003800; - str_shift = 11; - break; - case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab5_1v8; - str_mask = 0x00003800; - str_shift = 11; - break; - case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab6_1v8; - str_mask = 0x00001800; - str_shift = 11; - break; - case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17): -#if !defined(BCM_SDIO_VDDIO) || BCM_SDIO_VDDIO == 33 - if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_3v3)->strength) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_3v3; + current_res_state = R_REG(osh, &pmu->res_state); + min_mask = R_REG(osh, &pmu->min_res_mask); + max_mask = R_REG(osh, &pmu->max_res_mask); + W_REG(osh, &pmu->min_res_mask, (min_mask | current_res_state)); + switch (mode) { + case PMU_4364_1x1_MODE: + { + if (CHIPID(sih->chip) == BCM4364_CHIP_ID) { + pmu_res_depend_table = bcm4364a0_res_depend_1x1; + pmu_res_depend_table_sz = + ARRAYSIZE(bcm4364a0_res_depend_1x1); + max_mask = PMU_4364_MAX_MASK_1x1; + W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE); + W_REG(osh, &pmu->res_updn_timer, PMU_4364_SAVE_RESTORE_UPDNTIME_1x1); +#if defined(SAVERESTORE) + if (SR_ENAB()) { + /* Disable 3x3 SR engine */ + W_REG(osh, &cc->sr1_control0, + CC_SR0_4364_SR_ENG_CLK_EN | + CC_SR0_4364_SR_RSRC_TRIGGER | + CC_SR0_4364_SR_WD_MEM_MIN_DIV | + CC_SR0_4364_SR_INVERT_CLK | + CC_SR0_4364_SR_ENABLE_HT | + CC_SR0_4364_SR_ALLOW_PIC | + CC_SR0_4364_SR_PMU_MEM_DISABLE); + } +#endif /* SAVERESTORE */ + } + break; } -#else - if (drivestrength >= ARRAYLAST(sdiod_drive_strength_tab7_1v8)->strength) { - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab7_1v8; + case PMU_4364_3x3_MODE: + { + if (CHIPID(sih->chip) == BCM4364_CHIP_ID) { + W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE); + W_REG(osh, &pmu->res_updn_timer, + PMU_4364_SAVE_RESTORE_UPDNTIME_3x3); + /* Change the dependency table only if required */ + if ((max_mask != PMU_4364_MAX_MASK_3x3) || + (max_mask != PMU_4364_MAX_MASK_RSDB)) { + pmu_res_depend_table = bcm4364a0_res_depend_rsdb; + pmu_res_depend_table_sz = + ARRAYSIZE(bcm4364a0_res_depend_rsdb); + max_mask = PMU_4364_MAX_MASK_3x3; + } +#if defined(SAVERESTORE) + if (SR_ENAB()) { + /* Enable 3x3 SR engine */ + W_REG(osh, &cc->sr1_control0, + CC_SR0_4364_SR_ENG_CLK_EN | + CC_SR0_4364_SR_RSRC_TRIGGER | + CC_SR0_4364_SR_WD_MEM_MIN_DIV | + CC_SR0_4364_SR_INVERT_CLK | + CC_SR0_4364_SR_ENABLE_HT | + CC_SR0_4364_SR_ALLOW_PIC | + CC_SR0_4364_SR_PMU_MEM_DISABLE | + CC_SR0_4364_SR_ENG_EN_MASK); + } +#endif /* SAVERESTORE */ + } + break; } -#endif /* BCM_SDIO_VDDIO */ - str_mask = 0x00000007; - str_ovr_pmuval = PMU43143_CC0_SDIO_DRSTR_OVR; - break; - default: - PMU_MSG(("No SDIO Drive strength init done for chip %s rev %d pmurev %d\n", - bcm_chipname( - CHIPID(sih->chip), chn, 8), CHIPREV(sih->chiprev), PMUREV(sih->pmurev))); - break; - } - - if (str_tab != NULL) { - uint32 cc_data_temp; - int i; - - /* Pick the lowest available drive strength equal or greater than the - * requested strength. Drive strength of 0 requests tri-state. - */ - for (i = 0; drivestrength < str_tab[i].strength; i++) - ; - - if (i > 0 && drivestrength > str_tab[i].strength) - i--; - - W_REG(osh, &pmu->chipcontrol_addr, PMU_CHIPCTL1); - cc_data_temp = R_REG(osh, &pmu->chipcontrol_data); - cc_data_temp &= ~str_mask; - cc_data_temp |= str_tab[i].sel << str_shift; - W_REG(osh, &pmu->chipcontrol_data, cc_data_temp); - if (str_ovr_pmuval) { /* enables the selected drive strength */ - W_REG(osh, &pmu->chipcontrol_addr, str_ovr_pmuctl); - OR_REG(osh, &pmu->chipcontrol_data, str_ovr_pmuval); + case PMU_4364_RSDB_MODE: + default: + { + if (CHIPID(sih->chip) == BCM4364_CHIP_ID) { + W_REG(osh, &pmu->res_table_sel, RES4364_SR_SAVE_RESTORE); + W_REG(osh, &pmu->res_updn_timer, + PMU_4364_SAVE_RESTORE_UPDNTIME_3x3); + /* Change the dependency table only if required */ + if ((max_mask != PMU_4364_MAX_MASK_3x3) || + (max_mask != PMU_4364_MAX_MASK_RSDB)) { + pmu_res_depend_table = + bcm4364a0_res_depend_rsdb; + pmu_res_depend_table_sz = + ARRAYSIZE(bcm4364a0_res_depend_rsdb); + max_mask = PMU_4364_MAX_MASK_RSDB; + } +#if defined(SAVERESTORE) + if (SR_ENAB()) { + /* Enable 3x3 SR engine */ + W_REG(osh, &cc->sr1_control0, + CC_SR0_4364_SR_ENG_CLK_EN | + CC_SR0_4364_SR_RSRC_TRIGGER | + CC_SR0_4364_SR_WD_MEM_MIN_DIV | + CC_SR0_4364_SR_INVERT_CLK | + CC_SR0_4364_SR_ENABLE_HT | + CC_SR0_4364_SR_ALLOW_PIC | + CC_SR0_4364_SR_PMU_MEM_DISABLE | + CC_SR0_4364_SR_ENG_EN_MASK); + } +#endif /* SAVERESTORE */ + } + break; } - PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", - drivestrength, str_tab[i].strength)); } - - /* Return to original core */ + si_pmu_resdeptbl_upd(sih, osh, pmu, pmu_res_depend_table, pmu_res_depend_table_sz); + W_REG(osh, &pmu->max_res_mask, max_mask); + W_REG(osh, &pmu->min_res_mask, min_mask); + si_pmu_wait_for_steady_state(sih, osh, pmu); + /* Add some delay; allow resources to come up and settle. */ + OSL_DELAY(200); si_setcoreidx(sih, origidx); -} /* si_sdiod_drive_strength_init */ - +#endif /* DUAL_PMU_SEQUENCE */ +} #if defined(BCMULP) + int si_pmu_ulp_register(si_t *sih) { @@ -325,16 +280,111 @@ si_pmu_ulp_exit_cb(void *handle, uint8 *cache_data, return BCME_OK; } +void +si_pmu_ulp_chipconfig(si_t *sih, osl_t *osh) +{ + uint32 reg_val; + + BCM_REFERENCE(reg_val); + + if (CHIPID(sih->chip) == BCM43012_CHIP_ID) { + /* DS1 reset and clk enable init value config */ + si_pmu_chipcontrol(sih, PMU_CHIPCTL14, ~0x0, + (PMUCCTL14_43012_ARMCM3_RESET_INITVAL | + PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL | + PMUCCTL14_43012_SDIOD_RESET_INIVAL | + PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL | + PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL | + PMUCCTL14_43012_M2MDMA_RESET_INITVAL | + PMUCCTL14_43012_DOT11MAC_PHY_CLK_EN_INITVAL | + PMUCCTL14_43012_DOT11MAC_PHY_CNTL_EN_INITVAL)); + + /* Clear SFlash clock request and enable High Quality clock */ + CHIPC_REG(sih, clk_ctl_st, CCS_SFLASH_CLKREQ | CCS_HQCLKREQ, CCS_HQCLKREQ); + + reg_val = PMU_REG(sih, min_res_mask, ~0x0, ULP_MIN_RES_MASK); + ULP_DBG(("si_pmu_ulp_chipconfig: min_res_mask: 0x%08x\n", reg_val)); + + /* Force power switch off */ + si_pmu_chipcontrol(sih, PMU_CHIPCTL2, + (PMUCCTL02_43012_SUBCORE_PWRSW_FORCE_ON | + PMUCCTL02_43012_PHY_PWRSW_FORCE_ON), 0); + + } +} + void si_pmu_ulp_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period) { pmuregs_t *pmu; pmu = si_setcoreidx(sih, si_findcoreidx(sih, PMU_CORE_ID, 0)); W_REG(osh, &pmu->ILPPeriod, ilp_period); + si_lhl_ilp_config(sih, osh, ilp_period); } + +/** Initialize DS1 PMU hardware resources */ +void +si_pmu_ds1_res_init(si_t *sih, osl_t *osh) +{ + pmuregs_t *pmu; + uint origidx; + const pmu_res_updown_t *pmu_res_updown_table = NULL; + uint pmu_res_updown_table_sz = 0; + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + switch (CHIPID(sih->chip)) { + case BCM43012_CHIP_ID: + pmu_res_updown_table = bcm43012a0_res_updown_ds1; + pmu_res_updown_table_sz = ARRAYSIZE(bcm43012a0_res_updown_ds1); + break; + + default: + break; + } + + /* Program up/down timers */ + while (pmu_res_updown_table_sz--) { + ASSERT(pmu_res_updown_table != NULL); + PMU_MSG(("DS1: Changing rsrc %d res_updn_timer to 0x%x\n", + pmu_res_updown_table[pmu_res_updown_table_sz].resnum, + pmu_res_updown_table[pmu_res_updown_table_sz].updown)); + W_REG(osh, &pmu->res_table_sel, + pmu_res_updown_table[pmu_res_updown_table_sz].resnum); + W_REG(osh, &pmu->res_updn_timer, + pmu_res_updown_table[pmu_res_updown_table_sz].updown); + } + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + #endif /* defined(BCMULP) */ +uint32 +si_pmu_wake_bit_offset(si_t *sih) +{ + uint32 wakebit; + + switch (CHIPID(sih->chip)) { + case BCM4347_CHIP_GRPID: + wakebit = CC2_4347_GCI2WAKE_MASK; + break; + default: + wakebit = 0; + ASSERT(0); + break; + } + return wakebit; +} void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask) { @@ -380,3 +430,359 @@ si_pmu_fast_lpo_disable(si_t *sih) OSL_DELAY(1000); return BCME_OK; } + +#ifdef BCMPMU_STATS +/* + * 8 pmu statistics timer default map + * + * for CORE_RDY_AUX measure, set as below for timer 6 and 7 instead of CORE_RDY_MAIN. + * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX) + * { SRC_CORE_RDY_AUX, FALSE, TRUE, LEVEL_HIGH}, + * //core-n active duration : pmu_rsrc_state(CORE_RDY_AUX) + * { SRC_CORE_RDY_AUX, FALSE, TRUE, EDGE_RISE} + */ +static pmu_stats_timer_t pmustatstimer[] = { + { SRC_LINK_IN_L12, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l12 + { SRC_LINK_IN_L23, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //link_in_l23 + { SRC_PM_ST_IN_D0, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d0 + { SRC_PM_ST_IN_D3, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, //pm_st_in_d3 + //deep-sleep duration : pmu_rsrc_state(XTAL_PU) + { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_LEVEL_LOW}, + //deep-sleep entry count : pmu_rsrc_state(XTAL_PU) + { SRC_XTAL_PU, FALSE, TRUE, PMU_STATS_EDGE_FALL}, + //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN) + { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_LEVEL_HIGH}, + //core-n active duration : pmu_rsrc_state(CORE_RDY_MAIN) + { SRC_CORE_RDY_MAIN, FALSE, TRUE, PMU_STATS_EDGE_RISE} +}; + +static void +si_pmustatstimer_update(osl_t *osh, pmuregs_t *pmu, uint8 timerid) +{ + uint32 stats_timer_ctrl; + + W_REG(osh, &pmu->pmu_statstimer_addr, timerid); + stats_timer_ctrl = + ((pmustatstimer[timerid].src_num << PMU_ST_SRC_SHIFT) & + PMU_ST_SRC_MASK) | + ((pmustatstimer[timerid].cnt_mode << PMU_ST_CNT_MODE_SHIFT) & + PMU_ST_CNT_MODE_MASK) | + ((pmustatstimer[timerid].enable << PMU_ST_EN_SHIFT) & PMU_ST_EN_MASK) | + ((pmustatstimer[timerid].int_enable << PMU_ST_INT_EN_SHIFT) & PMU_ST_INT_EN_MASK); + W_REG(osh, &pmu->pmu_statstimer_ctrl, stats_timer_ctrl); + W_REG(osh, &pmu->pmu_statstimer_N, 0); +} + +void +si_pmustatstimer_int_enable(si_t *sih) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_int_disable(si_t *sih) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + AND_REG(osh, &pmu->pmuintmask0, ~PMU_INT_STAT_TIMER_INT_MASK); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_init(si_t *sih) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + uint32 core_cap_ext; + uint8 max_stats_timer_num; + int8 i; + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + core_cap_ext = R_REG(osh, &pmu->core_cap_ext); + + max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1; + + for (i = 0; i < max_stats_timer_num; i++) { + si_pmustatstimer_update(osh, pmu, i); + } + + OR_REG(osh, &pmu->pmuintmask0, PMU_INT_STAT_TIMER_INT_MASK); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_dump(si_t *sih) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + uint32 core_cap_ext, pmucapabilities, AlpPeriod, ILPPeriod, pmuintmask0, pmuintstatus; + uint8 max_stats_timer_num, max_stats_timer_src_num; + uint32 stat_timer_ctrl, stat_timer_N; + uint8 i; + uint32 current_time_ms = OSL_SYSUPTIME(); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + pmucapabilities = R_REG(osh, &pmu->pmucapabilities); + core_cap_ext = R_REG(osh, &pmu->core_cap_ext); + AlpPeriod = R_REG(osh, &pmu->slowclkperiod); + ILPPeriod = R_REG(osh, &pmu->ILPPeriod); + + max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> + PCAP_EXT_ST_NUM_SHIFT) + 1; + max_stats_timer_src_num = ((core_cap_ext & PCAP_EXT_ST_SRC_NUM_MASK) >> + PCAP_EXT_ST_SRC_NUM_SHIFT) + 1; + + pmuintstatus = R_REG(osh, &pmu->pmuintstatus); + pmuintmask0 = R_REG(osh, &pmu->pmuintmask0); + + PMU_ERROR(("%s : TIME %d\n", __FUNCTION__, current_time_ms)); + + PMU_ERROR(("\tMAX Timer Num %d, MAX Source Num %d\n", + max_stats_timer_num, max_stats_timer_src_num)); + PMU_ERROR(("\tpmucapabilities 0x%8x, core_cap_ext 0x%8x, AlpPeriod 0x%8x, ILPPeriod 0x%8x, " + "pmuintmask0 0x%8x, pmuintstatus 0x%8x, pmurev %d\n", + pmucapabilities, core_cap_ext, AlpPeriod, ILPPeriod, + pmuintmask0, pmuintstatus, PMUREV(sih->pmurev))); + + for (i = 0; i < max_stats_timer_num; i++) { + W_REG(osh, &pmu->pmu_statstimer_addr, i); + stat_timer_ctrl = R_REG(osh, &pmu->pmu_statstimer_ctrl); + stat_timer_N = R_REG(osh, &pmu->pmu_statstimer_N); + PMU_ERROR(("\t Timer %d : control 0x%8x, %d\n", + i, stat_timer_ctrl, stat_timer_N)); + } + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_start(si_t *sih, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + pmustatstimer[timerid].enable = TRUE; + + W_REG(osh, &pmu->pmu_statstimer_addr, timerid); + OR_REG(osh, &pmu->pmu_statstimer_ctrl, PMU_ST_ENAB << PMU_ST_EN_SHIFT); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_stop(si_t *sih, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + pmustatstimer[timerid].enable = FALSE; + + W_REG(osh, &pmu->pmu_statstimer_addr, timerid); + AND_REG(osh, &pmu->pmu_statstimer_ctrl, ~(PMU_ST_ENAB << PMU_ST_EN_SHIFT)); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_clear(si_t *sih, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + W_REG(osh, &pmu->pmu_statstimer_addr, timerid); + W_REG(osh, &pmu->pmu_statstimer_N, 0); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_clear_overflow(si_t *sih) +{ + uint8 i; + uint32 core_cap_ext; + uint8 max_stats_timer_num; + uint32 timerN; + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + core_cap_ext = R_REG(osh, &pmu->core_cap_ext); + max_stats_timer_num = ((core_cap_ext & PCAP_EXT_ST_NUM_MASK) >> PCAP_EXT_ST_NUM_SHIFT) + 1; + + for (i = 0; i < max_stats_timer_num; i++) { + W_REG(osh, &pmu->pmu_statstimer_addr, i); + timerN = R_REG(osh, &pmu->pmu_statstimer_N); + if (timerN == 0xFFFFFFFF) { + PMU_ERROR(("pmustatstimer overflow clear - timerid : %d\n", i)); + si_pmustatstimer_clear(sih, i); + } + } + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +uint32 +si_pmustatstimer_read(si_t *sih, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + uint32 stats_timer_N; + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + W_REG(osh, &pmu->pmu_statstimer_addr, timerid); + stats_timer_N = R_REG(osh, &pmu->pmu_statstimer_N); + + /* Return to original core */ + si_setcoreidx(sih, origidx); + + return stats_timer_N; +} + +void +si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + pmustatstimer[timerid].src_num = src_num; + si_pmustatstimer_update(osh, pmu, timerid); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} + +void +si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid) +{ + pmuregs_t *pmu; + uint origidx; + osl_t *osh = si_osh(sih); + + /* Remember original core before switch to chipc/pmu */ + origidx = si_coreidx(sih); + if (AOB_ENAB(sih)) { + pmu = si_setcore(sih, PMU_CORE_ID, 0); + } else { + pmu = si_setcoreidx(sih, SI_CC_IDX); + } + ASSERT(pmu != NULL); + + pmustatstimer[timerid].cnt_mode = cnt_mode; + si_pmustatstimer_update(osh, pmu, timerid); + + /* Return to original core */ + si_setcoreidx(sih, origidx); +} +#endif /* BCMPMU_STATS */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/802.11.h b/drivers/net/wireless/bcmdhd_oo/include/802.11.h index 495ce55aba2abc823be1b60116a0d1f7e689aef9..1d52c98488d3fb6d97caf5579a9c677032a70a7f 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/802.11.h +++ b/drivers/net/wireless/bcmdhd_oo/include/802.11.h @@ -1,14 +1,14 @@ /* * Fundamental types and constants relating to 802.11 * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: 802.11.h 700693 2017-05-20 20:29:07Z $ + * $Id: 802.11.h 737757 2017-12-22 07:38:13Z $ */ #ifndef _802_11_H_ @@ -32,27 +32,27 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif #ifndef _NET_ETHERNET_H_ #include -#endif +#endif // endif #include /* This marks the start of a packed structure section. */ #include - #define DOT11_TU_TO_US 1024 /* 802.11 Time Unit is 1024 microseconds */ /* Generic 802.11 frame constants */ #define DOT11_A3_HDR_LEN 24 /* d11 header length with A3 */ #define DOT11_A4_HDR_LEN 30 /* d11 header length with A4 */ #define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN /* MAC header length */ -#define DOT11_FCS_LEN 4 /* d11 FCS length */ +#define DOT11_FCS_LEN 4u /* d11 FCS length */ #define DOT11_ICV_LEN 4 /* d11 ICV length */ #define DOT11_ICV_AES_LEN 8 /* d11 ICV/AES length */ +#define DOT11_MAX_ICV_AES_LEN 16 /* d11 MAX ICV/AES length */ #define DOT11_QOS_LEN 2 /* d11 QoS length */ #define DOT11_HTC_LEN 4 /* d11 HT Control field length */ @@ -143,7 +143,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { uint16 durid; /* duration/ID */ struct ether_addr ra; /* receiver address */ } BWL_POST_PACKED_STRUCT; -#define DOT11_CTS_LEN 10 /* d11 CTS frame length */ +#define DOT11_CTS_LEN 10u /* d11 CTS frame length */ BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { uint16 fc; /* frame control */ @@ -404,14 +404,14 @@ BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { typedef struct dot11_action_frmhdr dot11_action_frmhdr_t; /* Action Field length */ -#define DOT11_ACTION_CATEGORY_LEN 1 -#define DOT11_ACTION_ACTION_LEN 1 -#define DOT11_ACTION_DIALOG_TOKEN_LEN 1 -#define DOT11_ACTION_CAPABILITY_LEN 2 -#define DOT11_ACTION_STATUS_CODE_LEN 2 -#define DOT11_ACTION_REASON_CODE_LEN 2 -#define DOT11_ACTION_TARGET_CH_LEN 1 -#define DOT11_ACTION_OPER_CLASS_LEN 1 +#define DOT11_ACTION_CATEGORY_LEN 1u +#define DOT11_ACTION_ACTION_LEN 1u +#define DOT11_ACTION_DIALOG_TOKEN_LEN 1u +#define DOT11_ACTION_CAPABILITY_LEN 2u +#define DOT11_ACTION_STATUS_CODE_LEN 2u +#define DOT11_ACTION_REASON_CODE_LEN 2u +#define DOT11_ACTION_TARGET_CH_LEN 1u +#define DOT11_ACTION_OPER_CLASS_LEN 1u #define DOT11_ACTION_FRMHDR_LEN 2 @@ -928,17 +928,46 @@ BWL_PRE_PACKED_STRUCT struct qos_cap_ie { typedef struct qos_cap_ie qos_cap_ie_t; BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { - uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ + uint8 id; /* 11, DOT11_MNG_QBSS_LOAD_ID */ uint8 length; - uint16 station_count; /* total number of STAs associated */ + uint16 station_count; /* total number of STAs associated */ uint8 channel_utilization; /* % of time, normalized to 255, QAP sensed medium busy */ - uint16 aac; /* available admission capacity */ + uint16 aac; /* available admission capacity */ } BWL_POST_PACKED_STRUCT; typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; -#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ +#define BSS_LOAD_IE_SIZE 7 /* BSS load IE size */ #define WLC_QBSS_LOAD_CHAN_FREE_MAX 0xff /* max for channel free score */ +/* Estimated Service Parameters (ESP) IE - 802.11-2016 9.4.2.174 */ +typedef BWL_PRE_PACKED_STRUCT struct dot11_esp_ie { + uint8 id; + uint8 length; + uint8 id_ext; + /* variable len info */ + uint8 esp_info_lists[]; +} BWL_POST_PACKED_STRUCT dot11_esp_ie_t; + +#define DOT11_ESP_IE_HDR_SIZE (OFFSETOF(dot11_esp_ie_t, esp_info_lists)) + +/* ESP Information list - 802.11-2016 9.4.2.174 */ +typedef BWL_PRE_PACKED_STRUCT struct dot11_esp_ie_info_list { + /* acess category, data format, ba win size */ + uint8 ac_df_baws; + /* estimated air time fraction */ + uint8 eat_frac; + /* data PPDU duration target (50us units) */ + uint8 ppdu_dur; +} BWL_POST_PACKED_STRUCT dot11_esp_ie_info_list_t; + +#define DOT11_ESP_IE_INFO_LIST_SIZE (sizeof(dot11_esp_ie_info_list_t)) + +#define DOT11_ESP_NBR_INFO_LISTS 4u /* max nbr of esp information lists */ +#define DOT11_ESP_INFO_LIST_AC_BK 0u /* access category of esp information list AC_BK */ +#define DOT11_ESP_INFO_LIST_AC_BE 1u /* access category of esp information list AC_BE */ +#define DOT11_ESP_INFO_LIST_AC_VI 2u /* access category of esp information list AC_VI */ +#define DOT11_ESP_INFO_LIST_AC_VO 3u /* access category of esp information list AC_VO */ + /* nom_msdu_size */ #define FIXED_MSDU_SIZE 0x8000 /* MSDU size is fixed */ #define MSDU_SIZE_MASK 0x7fff /* (Nominal or fixed) MSDU size */ @@ -969,7 +998,7 @@ typedef struct ti_ie ti_ie_t; #ifndef CISCO_AIRONET_OUI #define CISCO_AIRONET_OUI "\x00\x40\x96" /* Cisco AIRONET OUI */ -#endif +#endif // endif /* QoS FastLane IE. */ BWL_PRE_PACKED_STRUCT struct ccx_qfl_ie { uint8 id; /* 221, DOT11_MNG_VS_ID */ @@ -1060,6 +1089,7 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; #define FC_SUBTYPE_ACTION_NOACK 14 /* action no-ack */ /* Control Subtypes */ +#define FC_SUBTYPE_TRIGGER 2 /* Trigger frame */ #define FC_SUBTYPE_CTL_WRAPPER 7 /* Control Wrapper */ #define FC_SUBTYPE_BLOCKACK_REQ 8 /* Block Ack Req */ #define FC_SUBTYPE_BLOCKACK 9 /* Block Ack */ @@ -1116,6 +1146,7 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; #define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) /* action */ #define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) /* action no-ack */ +#define FC_CTL_TRIGGER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_TRIGGER) /* Trigger frame */ #define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) /* Control Wrapper */ #define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) /* Block Ack Req */ #define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) /* Block Ack */ @@ -1210,7 +1241,6 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; /* 12 is unused by STA but could be used by AP/GO */ #define DOT11_RC_DISASSOC_BTM 12 /* Disassociated due to BSS Transition Magmt */ - /* 32-39 are QSTA specific reasons added in 11e */ #define DOT11_RC_UNSPECIFIED_QOS 32 /* unspecified QoS-related reason */ #define DOT11_RC_INSUFFCIENT_BW 33 /* QAP lacks sufficient bandwidth */ @@ -1479,8 +1509,6 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; #define DOT11_MNG_AID_ID 197 /* Association ID IE */ #define DOT11_MNG_OPER_MODE_NOTIF_ID 199 /* d11 mgmt VHT oper mode notif */ #define DOT11_MNG_RNR_ID 201 -#define DOT11_MNG_HE_CAP_ID 202 -#define DOT11_MNG_HE_OP_ID 203 #define DOT11_MNG_FTM_PARAMS_ID 206 #define DOT11_MNG_TWT_ID 216 /* 11ah D5.0 */ #define DOT11_MNG_WPA_ID 221 /* d11 management WPA id */ @@ -1489,12 +1517,22 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; #define DOT11_MNG_VS_ID 221 /* d11 management Vendor Specific IE */ #define DOT11_MNG_MESH_CSP_ID 222 /* d11 Mesh Channel Switch Parameter */ #define DOT11_MNG_FILS_IND_ID 240 /* 11ai FILS Indication element */ +#define DOT11_MNG_FRAGMENT_ID 242 /* IE's fragment ID */ /* The follwing ID extensions should be defined >= 255 * i.e. the values should include 255 (DOT11_MNG_ID_EXT_ID + ID Extension). */ #define DOT11_MNG_ID_EXT_ID 255 /* Element ID Extension 11mc D4.3 */ -#define DOT11_MNG_RAPS_ID (DOT11_MNG_ID_EXT_ID+11) /* OFDMA Random Access Parameter Set */ +#define EXT_MNG_HE_CAP_ID 35 /* HE Capabilities, 11ax */ +#define DOT11_MNG_HE_CAP_ID (DOT11_MNG_ID_EXT_ID + EXT_MNG_HE_CAP_ID) +#define EXT_MNG_HE_OP_ID 36 /* HE Operation IE, 11ax */ +#define DOT11_MNG_HE_OP_ID (DOT11_MNG_ID_EXT_ID + EXT_MNG_HE_OP_ID) +#define EXT_MNG_RAPS_ID 37 /* OFDMA Random Access Parameter Set */ +#define DOT11_MNG_RAPS_ID (DOT11_MNG_ID_EXT_ID + EXT_MNG_RAPS_ID) +#define EXT_MNG_MU_EDCA_ID 38 /* MU EDCA Parameter Set */ +#define DOT11_MNG_MU_EDCA_ID (DOT11_MNG_ID_EXT_ID + EXT_MNG_MU_EDCA_ID) +#define EXT_MNG_SRPS_ID 39 /* Spatial Reuse Parameter Set */ +#define DOT11_MNG_SRPS_ID (DOT11_MNG_ID_EXT_ID + EXT_MNG_SRPS_ID) /* FILS ext ids */ #define FILS_REQ_PARAMS_EXT_ID 2 @@ -1505,6 +1543,8 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; #define DOT11_MNG_FILS_HLP_CONTAINER (DOT11_MNG_ID_EXT_ID + FILS_HLP_CONTAINER_EXT_ID) #define FILS_WRAPPED_DATA_EXT_ID 8 #define DOT11_MNG_FILS_WRAPPED_DATA (DOT11_MNG_ID_EXT_ID + FILS_WRAPPED_DATA_EXT_ID) +#define DOT11_ESP_EXT_ID 11u +#define DOT11_MNG_ESP (DOT11_MNG_ID_EXT_ID + DOT11_ESP_EXT_ID) #define FILS_NONCE_EXT_ID 13 #define DOT11_MNG_FILS_NONCE (DOT11_MNG_ID_EXT_ID + FILS_NONCE_EXT_ID) @@ -1643,15 +1683,12 @@ typedef struct ccx_qfl_ie ccx_qfl_ie_t; */ #define DOT11_EXT_CAP_MAX_IDX 76 -#ifdef WL_FTM #define DOT11_EXT_CAP_MAX_BIT_IDX 95 /* !!!update this please!!! */ -#else -#define DOT11_EXT_CAP_MAX_BIT_IDX 62 /* !!!update this please!!! */ -#endif + /* extended capability */ #ifndef DOT11_EXTCAP_LEN_MAX #define DOT11_EXTCAP_LEN_MAX ((DOT11_EXT_CAP_MAX_BIT_IDX + 8) >> 3) -#endif +#endif // endif BWL_PRE_PACKED_STRUCT struct dot11_extcap { uint8 extcap[DOT11_EXTCAP_LEN_MAX]; } BWL_POST_PACKED_STRUCT; @@ -1786,6 +1823,8 @@ typedef struct dot11_oper_mode_notif_ie dot11_oper_mode_notif_ie_t; #define DOT11_PUB_ACTION_GAS_CB_REQ 12 /* GAS Comeback Request */ #define DOT11_PUB_ACTION_FTM_REQ 32 /* FTM request */ #define DOT11_PUB_ACTION_FTM 33 /* FTM measurement */ +#define DOT11_PUB_ACTION_FTM_REQ_TRIGGER_START 1u /* FTM request start trigger */ +#define DOT11_PUB_ACTION_FTM_REQ_TRIGGER_STOP 0u /* FTM request stop trigger */ /* Block Ack action types */ #define DOT11_BA_ACTION_ADDBA_REQ 0 /* ADDBA Req action frame type */ @@ -1886,7 +1925,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_dls_resp { typedef struct dot11_dls_resp dot11_dls_resp_t; #define DOT11_DLS_RESP_LEN 16 /* Fixed length */ - /* ************* 802.11v related definitions. ************* */ /** BSS Management Transition Query frame header */ @@ -1967,7 +2005,6 @@ typedef struct dot11_bsstrans_resp dot11_bsstrans_resp_t; #define DOT11_BSSTRANS_RESP_STATUS_REJ_NO_SUITABLE_BSS 7 #define DOT11_BSSTRANS_RESP_STATUS_REJ_LEAVING_ESS 8 - /** BSS Max Idle Period element */ BWL_PRE_PACKED_STRUCT struct dot11_bss_max_idle_period_ie { uint8 id; /* 90, DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID */ @@ -2192,11 +2229,12 @@ BWL_PRE_PACKED_STRUCT struct dot11_tclas_proc_ie { typedef struct dot11_tclas_proc_ie dot11_tclas_proc_ie_t; #define DOT11_TCLAS_PROC_IE_LEN 3 /* Fixed length, include id and len */ +#define DOT11_TCLAS_PROC_LEN 1u /* Proc ie length is always 1 byte */ + #define DOT11_TCLAS_PROC_MATCHALL 0 /* All high level element need to match */ #define DOT11_TCLAS_PROC_MATCHONE 1 /* One high level element need to match */ #define DOT11_TCLAS_PROC_NONMATCH 2 /* Non match to any high level element */ - /* TSPEC element defined in 802.11 std section 8.4.2.32 - Not supported */ #define DOT11_TSPEC_IE_LEN 57 /* Fixed length */ @@ -2227,7 +2265,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_tfs_se { } BWL_POST_PACKED_STRUCT; typedef struct dot11_tfs_se dot11_tfs_se_t; - /** TFS response element */ BWL_PRE_PACKED_STRUCT struct dot11_tfs_resp_ie { uint8 id; /* 92, DOT11_MNG_TFS_RESPONSE_ID */ @@ -2320,7 +2357,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_tfs_notify_resp { typedef struct dot11_tfs_notify_resp dot11_tfs_notify_resp_t; #define DOT11_TFS_NOTIFY_RESP_LEN 3 /* Fixed length */ - /** WNM-Sleep Management Request frame header */ BWL_PRE_PACKED_STRUCT struct dot11_wnm_sleep_req { uint8 category; /* category of action frame (10) */ @@ -2660,7 +2696,6 @@ typedef struct dot11_rde_ie dot11_rde_ie_t; /* 11r - Size of the RDE (RIC Data Element) IE, including TLV header. */ #define DOT11_MNG_RDE_IE_LEN sizeof(dot11_rde_ie_t) - /* ************* 802.11k related definitions. ************* */ /* Radio measurements enabled capability ie */ @@ -2860,6 +2895,7 @@ typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; #define DOT11_RMREQ_BCN_REPDET_ID 2 #define DOT11_RMREQ_BCN_REQUEST_ID 10 #define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID +#define DOT11_RMREQ_BCN_LAST_RPT_IND_REQ_ID 164 /* Reporting Detail element definition */ #define DOT11_RMREQ_BCN_REPDET_FIXED 0 /* Fixed length fields only */ @@ -2870,10 +2906,44 @@ typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; #define DOT11_RMREQ_BCN_REPINFO_LEN 2 /* Beacon Reporting Information length */ #define DOT11_RMREQ_BCN_REPCOND_DEFAULT 0 /* Report to be issued after each measurement */ +/* Last Beacon Report Indication Request definition */ +#define DOT11_RMREQ_BCN_LAST_RPT_IND_REQ_ENAB 1 + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_last_bcn_rpt_ind_req { + uint8 id; /* DOT11_RMREQ_BCN_LAST_RPT_IND_REQ_ID */ + uint8 len; /* length of remaining fields */ + uint8 data; /* data = 1 means last bcn rpt ind requested */ +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_last_bcn_rpt_ind_req dot11_rmrep_last_bcn_rpt_ind_req_t; + /* Sub-element IDs for Beacon Report */ #define DOT11_RMREP_BCN_FRM_BODY 1 +#define DOT11_RMREP_BCN_FRM_BODY_FRAG_ID 2 +#define DOT11_RMREP_BCN_LAST_RPT_IND 164 #define DOT11_RMREP_BCN_FRM_BODY_LEN_MAX 224 /* 802.11k-2008 7.3.2.22.6 */ +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_bcn_frm_body_frag_id { + uint8 id; /* DOT11_RMREP_BCN_FRM_BODY_FRAG_ID */ + uint8 len; /* length of remaining fields */ + uint8 bcn_rpt_id; /* Bcn rpt instance ID */ + uint8 frag_info; /* fragment Id(7 bits) | More fragments(1 bit) */ +} BWL_POST_PACKED_STRUCT; + +typedef struct dot11_rmrep_bcn_frm_body_frag_id dot11_rmrep_bcn_frm_body_frag_id_t; +#define DOT11_RMREP_BCNRPT_FRAG_ID_DATA_LEN 2 +#define DOT11_RMREP_BCNRPT_FRAG_ID_SE_LEN sizeof(dot11_rmrep_bcn_frm_body_frag_id_t) +#define DOT11_RMREP_BCNRPT_FRAG_ID_NUM_SHIFT 1 + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_last_bcn_rpt_ind { + uint8 id; /* DOT11_RMREP_BCN_LAST_RPT_IND */ + uint8 len; /* length of remaining fields */ + uint8 data; /* data = 1 is last bcn rpt */ +} BWL_POST_PACKED_STRUCT; + +typedef struct dot11_rmrep_last_bcn_rpt_ind dot11_rmrep_last_bcn_rpt_ind_t; +#define DOT11_RMREP_LAST_BCN_RPT_IND_DATA_LEN 1 +#define DOT11_RMREP_LAST_BCN_RPT_IND_SE_LEN sizeof(dot11_rmrep_last_bcn_rpt_ind_t) + /* Sub-element IDs for Frame Report */ #define DOT11_RMREP_FRAME_COUNT_REPORT 1 @@ -3405,7 +3475,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time { typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t; #define DOT11_RMREQ_PAUSE_LEN 7 - /* Neighbor Report subelements ID (11k & 11v) */ #define DOT11_NGBR_TSF_INFO_SE_ID 1 #define DOT11_NGBR_CCS_SE_ID 2 @@ -3466,7 +3535,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_neighbor_rep_ie { typedef struct dot11_neighbor_rep_ie dot11_neighbor_rep_ie_t; #define DOT11_NEIGHBOR_REP_IE_FIXED_LEN 13 - /* MLME Enumerations */ #define DOT11_BSSTYPE_INFRASTRUCTURE 0 /* d11 infrastructure */ #define DOT11_BSSTYPE_INDEPENDENT 1 /* d11 independent */ @@ -3661,7 +3729,6 @@ typedef struct d11cnt { #define BRCM_PROP_OUI "\x00\x90\x4C" - #define BRCM_FTM_IE_TYPE 14 /* #define HT_CAP_IE_TYPE 51 @@ -3692,9 +3759,6 @@ enum { BRCM_FTM_VS_COLLECT_SUBTYPE = 2, /* FTM Collect debug protocol */ }; - - - /* brcm syscap_ie cap */ #define BRCM_SYSCAP_WET_TUNNEL 0x0100 /* Device with WET_TUNNEL support */ @@ -3801,6 +3865,7 @@ typedef struct btc_brcm_prop_ie btc_brcm_prop_ie_t; /* ************* HT definitions. ************* */ #define MCSSET_LEN 16 /* 16-bits per 8-bit set to give 128-bits bitmap of MCS Index */ #define MAX_MCS_NUM (128) /* max mcs number = 128 */ +#define BASIC_HT_MCS 0xFFu /* HT MCS supported rates */ BWL_PRE_PACKED_STRUCT struct ht_cap_ie { uint16 cap; @@ -3860,7 +3925,6 @@ typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; #define HT_CAP_RX_STBC_TWO_STREAM 0x2 /* rx STBC support of 1-2 spatial streams */ #define HT_CAP_RX_STBC_THREE_STREAM 0x3 /* rx STBC support of 1-3 spatial streams */ - #define HT_CAP_TXBF_CAP_IMPLICIT_TXBF_RX 0x1 #define HT_CAP_TXBF_CAP_NDP_RX 0x8 #define HT_CAP_TXBF_CAP_NDP_TX 0x10 @@ -3932,7 +3996,7 @@ typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; #define AMPDU_RX_FACTOR_BASE 8*1024 /* ampdu factor base for rx len */ #define AMPDU_RX_FACTOR_BASE_PWR 13 /* ampdu factor base for rx len in power of 2 */ -#define AMPDU_DELIMITER_LEN 4 /* length of ampdu delimiter */ +#define AMPDU_DELIMITER_LEN 4u /* length of ampdu delimiter */ #define AMPDU_DELIMITER_LEN_MAX 63 /* max length of ampdu delimiter(enforced in HW) */ #define HT_CAP_EXT_PCO 0x0001 @@ -4221,7 +4285,6 @@ typedef enum vht_cap_max_mpdu_len { #define VHT_MPDU_LIMIT_8K 7991 #define VHT_MPDU_LIMIT_11K 11454 - /** * VHT Operation IE (sec 8.4.2.161) */ @@ -4312,7 +4375,7 @@ typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; #if defined(WL_LEGACY_P2P) #define MAC_OUI "\x00\x17\xF2" /* MACOSX OUI */ #define MAC_OUI_TYPE_P2P 5 -#endif +#endif // endif #ifdef P2P_IE_OVRD #define WFA_OUI MAC_OUI @@ -4325,7 +4388,7 @@ typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; #else #define WFA_OUI_TYPE_TPC 8 #define WFA_OUI_TYPE_P2P 9 -#endif +#endif // endif #define WFA_OUI_TYPE_TPC 8 #ifdef WLTDLS @@ -4398,33 +4461,42 @@ typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; #ifdef BCMWAPI_WPI #define SMS4_KEY_LEN 16 #define SMS4_WPI_CBC_MAC_LEN 16 -#endif +#endif // endif /* 802.11r protocol definitions */ /** Mobility Domain IE */ BWL_PRE_PACKED_STRUCT struct dot11_mdid_ie { uint8 id; - uint8 len; + uint8 len; /* DOT11_MDID_IE_DATA_LEN (3) */ uint16 mdid; /* Mobility Domain Id */ uint8 cap; } BWL_POST_PACKED_STRUCT; typedef struct dot11_mdid_ie dot11_mdid_ie_t; +/* length of data portion of Mobility Domain IE */ +#define DOT11_MDID_IE_DATA_LEN 3 + #define FBT_MDID_CAP_OVERDS 0x01 /* Fast Bss transition over the DS support */ #define FBT_MDID_CAP_RRP 0x02 /* Resource request protocol support */ /** Fast Bss Transition IE */ BWL_PRE_PACKED_STRUCT struct dot11_ft_ie { uint8 id; - uint8 len; + uint8 len; /* At least equal to DOT11_FT_IE_FIXED_LEN (82) */ uint16 mic_control; /* Mic Control */ uint8 mic[16]; uint8 anonce[32]; uint8 snonce[32]; + /* Optional sub-elements follow */ } BWL_POST_PACKED_STRUCT; typedef struct dot11_ft_ie dot11_ft_ie_t; +/* Fixed length of data portion of Fast BSS Transition IE. There could be + * optional parameters, which if present, could raise the FT IE length to 255. + */ +#define DOT11_FT_IE_FIXED_LEN 82 + #define TIE_TYPE_RESERVED 0 #define TIE_TYPE_REASSOC_DEADLINE 1 #define TIE_TYPE_KEY_LIEFTIME 2 @@ -4505,7 +4577,7 @@ BWL_PRE_PACKED_STRUCT struct link_id_ie { struct ether_addr tdls_resp_mac; } BWL_POST_PACKED_STRUCT; typedef struct link_id_ie link_id_ie_t; -#define TDLS_LINK_ID_IE_LEN 18 +#define TDLS_LINK_ID_IE_LEN 18u /** Link Wakeup Schedule Element */ BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { @@ -4597,7 +4669,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_ftm { } BWL_POST_PACKED_STRUCT; typedef struct dot11_ftm dot11_ftm_t; - #define DOT11_FTM_ERR_NOT_CONT_OFFSET 1 #define DOT11_FTM_ERR_NOT_CONT_MASK 0x80 #define DOT11_FTM_ERR_NOT_CONT_SHIFT 7 @@ -4902,7 +4973,6 @@ enum { #define FTM_TPK_RI_PHY_LEN_SECURE_2_0 14 #define FTM_TPK_RR_PHY_LEN_SECURE_2_0 14 - BWL_PRE_PACKED_STRUCT struct dot11_ftm_vs_params { uint8 id; /* DOT11_MNG_VS_ID */ uint8 len; @@ -4982,8 +5052,12 @@ typedef struct dot11_ftm_sync_info dot11_ftm_sync_info_t; #define ANQP_ID_DOMAIN_NAME_LIST 268 #define ANQP_ID_EMERGENCY_ALERT_ID_URI 269 #define ANQP_ID_EMERGENCY_NAI 271 +#define ANQP_ID_NEIGHBOR_REPORT 272 #define ANQP_ID_VENDOR_SPECIFIC_LIST 56797 +/* 802.11u ANQP ID len */ +#define ANQP_INFORMATION_ID_LEN 2 + /* 802.11u ANQP OUI */ #define ANQP_OUI_SUBTYPE 9 diff --git a/drivers/net/wireless/bcmdhd_oo/include/802.11s.h b/drivers/net/wireless/bcmdhd_oo/include/802.11s.h index 2d66d0b52e1a594ddfdb01a015511020db4775c4..3d3d8f9bd85bc59cec51a727886c80e5ad5b4e8d 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/802.11s.h +++ b/drivers/net/wireless/bcmdhd_oo/include/802.11s.h @@ -1,14 +1,14 @@ /* * Fundamental types and constants relating to 802.11s Mesh * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -129,7 +129,6 @@ BWL_PRE_PACKED_STRUCT struct mesh_targetinfo { } BWL_POST_PACKED_STRUCT; typedef struct mesh_targetinfo mesh_targetinfo_t; - /* Mesh PREP IE */ BWL_PRE_PACKED_STRUCT struct mesh_prep_ie { uint8 id; @@ -160,7 +159,6 @@ BWL_PRE_PACKED_STRUCT struct mesh_prep_ie { } BWL_POST_PACKED_STRUCT; typedef struct mesh_prep_ie mesh_prep_ie_t; - /* Mesh PERR IE */ struct mesh_perr_ie { uint8 id; diff --git a/drivers/net/wireless/bcmdhd_oo/include/802.1d.h b/drivers/net/wireless/bcmdhd_oo/include/802.1d.h index 1b8dea5b117d72771f9c92a021efd31650e6ae35..efc60b870b530622cc302b2c656c27721f9d129d 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/802.1d.h +++ b/drivers/net/wireless/bcmdhd_oo/include/802.1d.h @@ -1,14 +1,14 @@ /* * Fundamental types and constants relating to 802.1D * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. diff --git a/drivers/net/wireless/bcmdhd_oo/include/802.3.h b/drivers/net/wireless/bcmdhd_oo/include/802.3.h index 6758ac048428a6f2cddd0deeb645c2d1c411c8aa..b96b3622bffde48fbee646b82f69c0ccfe34291a 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/802.3.h +++ b/drivers/net/wireless/bcmdhd_oo/include/802.3.h @@ -1,14 +1,14 @@ /* * Fundamental constants relating to 802.3 * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. diff --git a/drivers/net/wireless/bcmdhd_oo/include/aidmp.h b/drivers/net/wireless/bcmdhd_oo/include/aidmp.h index 10992e7635f435706fc9b3a589460fdf2c7d0e9a..aae2178b6fbceaf9e4606a3b05df708e33bf6c3e 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/aidmp.h +++ b/drivers/net/wireless/bcmdhd_oo/include/aidmp.h @@ -1,14 +1,14 @@ /* * Broadcom AMBA Interconnect definitions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: aidmp.h 614820 2016-01-23 17:16:17Z $ + * $Id: aidmp.h 617751 2016-02-08 09:04:22Z $ */ #ifndef _AIDMP_H @@ -114,7 +114,6 @@ #define SD_SG32 0x00000008 #define SD_SZ_ALIGN 0x00000fff - #if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) typedef volatile struct _aidmp { @@ -307,7 +306,6 @@ typedef volatile struct _aidmp { #define AI_OOBDINWIDTH 0x364 #define AI_OOBDOUTWIDTH 0x368 - #define AI_IOCTRLSET 0x400 #define AI_IOCTRLCLEAR 0x404 #define AI_IOCTRL 0x408 @@ -414,6 +412,13 @@ typedef volatile struct _aidmp { #define AI_OOBSEL_7_SHIFT 24 #define AI_IOCTRL_ENABLE_D11_PME (1 << 14) +/* bit Specific for AI_OOBSELOUTB30 */ +#define OOB_B_ALP_REQUEST 0 +#define OOB_B_HT_REQUEST 1 +#define OOB_B_ILP_REQUEST 2 +#define OOB_B_ALP_AVAIL_REQUEST 3 +#define OOB_B_HT_AVAIL_REQUEST 4 + /* mask for interrupts from each core to wrapper */ #define AI_OOBSELINA74_CORE_MASK 0x80808080 #define AI_OOBSELINA30_CORE_MASK 0x80808080 diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcm_cfg.h b/drivers/net/wireless/bcmdhd_oo/include/bcm_cfg.h index 12e3cb2ca27a5e6e74f1f1b53f225f459b31ab06..f77dace9c4881931cb242e5f57df86a23868456e 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcm_cfg.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcm_cfg.h @@ -1,14 +1,14 @@ /* * BCM common config options * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcm_cfg.h 514727 2014-11-12 03:02:48Z $ + * $Id: bcm_cfg.h 672943 2016-11-30 08:54:06Z $ */ #ifndef _bcm_cfg_h_ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcm_mpool_pub.h b/drivers/net/wireless/bcmdhd_oo/include/bcm_mpool_pub.h index f8ce7a78e5b4eda2b4fedf85c28ba5ee22742685..90a14e2693253e09afa8a7b263129ec6310f808a 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcm_mpool_pub.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcm_mpool_pub.h @@ -35,14 +35,14 @@ * and instrumentation on top of the heap, without modifying the heap * allocation implementation. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -50,7 +50,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. @@ -66,7 +66,6 @@ #include /* needed for uint16 */ - /* ************************************************************************** * @@ -97,7 +96,6 @@ typedef struct bcm_mpm_mgr *bcm_mpm_mgr_h; struct bcm_mp_pool; typedef struct bcm_mp_pool *bcm_mp_pool_h; - /* * To make instrumentation more readable, every memory * pool must have a readable name. Pool names are up to @@ -105,7 +103,6 @@ typedef struct bcm_mp_pool *bcm_mp_pool_h; */ #define BCM_MP_NAMELEN 8 - /* * Type definition for pool statistics. */ @@ -118,7 +115,6 @@ typedef struct bcm_mp_stats { uint16 failed_alloc; /* Failed allocations. */ } bcm_mp_stats_t; - /* ************************************************************************** * @@ -141,7 +137,6 @@ typedef struct bcm_mp_stats { */ int bcm_mpm_init(struct osl_info *osh, int max_pools, bcm_mpm_mgr_h *mgrp); - /* * bcm_mpm_deinit() - de-initialize the whole memory pool system. * @@ -186,7 +181,6 @@ int bcm_mpm_create_prealloc_pool(bcm_mpm_mgr_h mgr, const char poolname[BCM_MP_NAMELEN], bcm_mp_pool_h *newp); - /* * bcm_mpm_delete_prealloc_pool() - Delete a memory pool. This should only be called after * all memory objects have been freed back to the pool. @@ -225,7 +219,6 @@ int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, const char poolname[BCM_MP_NAMELEN], bcm_mp_pool_h *newp); - /* * bcm_mpm_delete_heap_pool() - Delete a memory pool. This should only be called after * all memory objects have been freed back to the pool. @@ -241,7 +234,6 @@ int bcm_mpm_create_heap_pool(bcm_mpm_mgr_h mgr, unsigned int obj_sz, */ int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); - /* * bcm_mpm_stats() - Return stats for all pools * @@ -258,7 +250,6 @@ int bcm_mpm_delete_heap_pool(bcm_mpm_mgr_h mgr, bcm_mp_pool_h *poolp); */ int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); - /* * bcm_mpm_dump() - Display statistics on all pools * @@ -273,7 +264,6 @@ int bcm_mpm_stats(bcm_mpm_mgr_h mgr, bcm_mp_stats_t *stats, int *nentries); */ int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); - /* * bcm_mpm_get_obj_size() - The size of memory objects may need to be padded to * compensate for alignment requirements of the objects. @@ -295,7 +285,6 @@ int bcm_mpm_dump(bcm_mpm_mgr_h mgr, struct bcmstrbuf *b); */ int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *padded_obj_sz); - /* *************************************************************************** * @@ -304,7 +293,6 @@ int bcm_mpm_get_obj_size(bcm_mpm_mgr_h mgr, unsigned int obj_sz, unsigned int *p *************************************************************************** */ - /* * bcm_mp_alloc() - Allocate a memory pool object. * @@ -345,7 +333,6 @@ int bcm_mp_free(bcm_mp_pool_h pool, void *objp); */ void bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); - /* * bcm_mp_dump() - Dump a pool * @@ -360,5 +347,4 @@ void bcm_mp_stats(bcm_mp_pool_h pool, bcm_mp_stats_t *stats); */ int bcm_mp_dump(bcm_mp_pool_h pool, struct bcmstrbuf *b); - #endif /* _BCM_MPOOL_PUB_H */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcm_ring.h b/drivers/net/wireless/bcmdhd_oo/include/bcm_ring.h index 721d7eab6b08467e413f1375f99d5808eefd88f3..373617560a1c5c4dffb60378ffde1432e9ed3de9 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcm_ring.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcm_ring.h @@ -6,14 +6,14 @@ * * NOTE: A ring of size N, may only hold N-1 elements. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -21,7 +21,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. @@ -29,7 +29,7 @@ * * <> * - * $Id: bcm_ring.h 596126 2015-10-29 19:53:48Z $ + * $Id: bcm_ring.h 700321 2017-05-18 16:09:07Z $ */ #ifndef __bcm_ring_included__ #define __bcm_ring_included__ @@ -101,14 +101,14 @@ * private L1 data cache. * +---------------------------------------------------------------------------- * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -116,12 +116,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: bcm_ring.h 596126 2015-10-29 19:53:48Z $ + * $Id: bcm_ring.h 700321 2017-05-18 16:09:07Z $ * * -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- * vim: set ts=4 noet sw=4 tw=80: @@ -133,7 +133,7 @@ #define __ring_aligned ____cacheline_aligned #else #define __ring_aligned -#endif +#endif // endif /* Conditional compile for debug */ /* #define BCM_RING_DEBUG */ @@ -166,7 +166,6 @@ typedef struct bcm_ring { /* Ring context */ int read __ring_aligned; /* READ index in a circular ring */ } bcm_ring_t; - static INLINE void bcm_ring_init(bcm_ring_t *ring); static INLINE void bcm_ring_copy(bcm_ring_t *to, bcm_ring_t *from); static INLINE bool bcm_ring_is_empty(bcm_ring_t *ring); @@ -195,7 +194,6 @@ static INLINE int bcm_ring_cons_avail(const bcm_ring_t *ring, const int ring_size); static INLINE void bcm_ring_cons_all(bcm_ring_t *ring); - /** * bcm_ring_init - initialize a ring context. * @ring: pointer to a ring context @@ -238,7 +236,6 @@ bcm_ring_is_empty(bcm_ring_t *ring) return (ring->read == ring->write); } - /** * __bcm_ring_next_write - determine the index where the next write may occur * (with wrap-around). @@ -254,7 +251,6 @@ __bcm_ring_next_write(bcm_ring_t *ring, const int ring_size) return ((ring->write + 1) % ring_size); } - /** * __bcm_ring_full - support function for ring full test. * @ring: pointer to a ring context @@ -268,7 +264,6 @@ __bcm_ring_full(bcm_ring_t *ring, int next_write) return (next_write == ring->read); } - /** * bcm_ring_is_full - "Boolean" test whether a ring is full. * @ring: pointer to a ring context @@ -285,7 +280,6 @@ bcm_ring_is_full(bcm_ring_t *ring, const int ring_size) return __bcm_ring_full(ring, next_write); } - /** * bcm_ring_prod_done - commit a previously pending index where production * was requested. @@ -300,7 +294,6 @@ bcm_ring_prod_done(bcm_ring_t *ring, int write) ring->write = write; } - /** * bcm_ring_prod_pend - Fetch in "pend" mode, the index where an element may be * produced. @@ -324,7 +317,6 @@ bcm_ring_prod_pend(bcm_ring_t *ring, int *pend_write, const int ring_size) return rtn; } - /** * bcm_ring_prod - Fetch and "commit" the next index where a ring element may * be produced. @@ -347,7 +339,6 @@ bcm_ring_prod(bcm_ring_t *ring, const int ring_size) return prod_write; } - /** * bcm_ring_cons_done - commit a previously pending read * @ring: pointer to a ring context @@ -360,7 +351,6 @@ bcm_ring_cons_done(bcm_ring_t *ring, int read) ring->read = read; } - /** * bcm_ring_cons_pend - fetch in "pend" mode, the next index where a ring * element may be consumed. @@ -384,7 +374,6 @@ bcm_ring_cons_pend(bcm_ring_t *ring, int *pend_read, const int ring_size) return rtn; } - /** * bcm_ring_cons - fetch and "commit" the next index where a ring element may * be consumed. @@ -405,7 +394,6 @@ bcm_ring_cons(bcm_ring_t *ring, const int ring_size) return cons_read; } - /** * bcm_ring_sync_read - on consumption, update peer's read index. * @peer: pointer to peer's producer ring context @@ -419,7 +407,6 @@ bcm_ring_sync_read(bcm_ring_t *peer, const bcm_ring_t *self) peer->read = self->read; /* flush read update to peer producer */ } - /** * bcm_ring_sync_write - on consumption, update peer's write index. * @peer: pointer to peer's consumer ring context @@ -433,7 +420,6 @@ bcm_ring_sync_write(bcm_ring_t *peer, const bcm_ring_t *self) peer->write = self->write; /* flush write update to peer consumer */ } - /** * bcm_ring_prod_avail - fetch total number of available empty slots in the * ring for production. @@ -454,7 +440,6 @@ bcm_ring_prod_avail(const bcm_ring_t *ring, const int ring_size) return prod_avail; } - /** * bcm_ring_cons_avail - fetch total number of available elements for consumption. * @ring: pointer to a ring context @@ -476,7 +461,6 @@ bcm_ring_cons_avail(const bcm_ring_t *ring, const int ring_size) return cons_avail; } - /** * bcm_ring_cons_all - set ring in state where all elements are consumed. * @ring: pointer to a ring context @@ -487,7 +471,6 @@ bcm_ring_cons_all(bcm_ring_t *ring) ring->read = ring->write; } - /** * Work Queue * A work Queue is composed of a ring of work items, of a specified depth. @@ -504,7 +487,6 @@ struct bcm_workq { typedef struct bcm_workq bcm_workq_t; - /* #define BCM_WORKQ_DEBUG */ #if defined(BCM_WORKQ_DEBUG) #define WORKQ_ASSERT(exp) ASSERT(exp) @@ -530,7 +512,6 @@ typedef struct bcm_workq bcm_workq_t; ((__elem_type *)((__workq)->buffer)) + (__index); \ }) - static INLINE void bcm_workq_init(bcm_workq_t *workq, bcm_workq_t *workq_peer, void *buffer, int ring_size); @@ -603,7 +584,6 @@ bcm_workq_cons_sync(bcm_workq_t *workq_cons) bcm_ring_sync_read(WORKQ_PEER_RING(workq_cons), WORKQ_RING(workq_cons)); } - /** * bcm_workq_prod_refresh - Fetch the updated consumer's read index * @workq_prod: producer's workq whose read index must be refreshed from peer @@ -630,5 +610,4 @@ bcm_workq_cons_refresh(bcm_workq_t *workq_cons) bcm_ring_sync_write(WORKQ_RING(workq_cons), WORKQ_PEER_RING(workq_cons)); } - #endif /* ! __bcm_ring_h_included__ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmbloom.h b/drivers/net/wireless/bcmdhd_oo/include/bcmbloom.h new file mode 100644 index 0000000000000000000000000000000000000000..62e8b01187cd741d1179fc874ae68a25dcb4dfde --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmbloom.h @@ -0,0 +1,79 @@ +/* + * Bloom filter support + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: bcmbloom.h 714397 2017-08-04 08:24:38Z $ + */ + +#ifndef _bcmbloom_h_ +#define _bcmbloom_h_ + +#include +#ifdef BCMDRIVER +#include +#else +#include /* For size_t */ +#endif // endif + +struct bcm_bloom_filter; +typedef struct bcm_bloom_filter bcm_bloom_filter_t; + +typedef void* (*bcm_bloom_alloc_t)(void *ctx, uint size); +typedef void (*bcm_bloom_free_t)(void *ctx, void *buf, uint size); +typedef uint (*bcm_bloom_hash_t)(void* ctx, uint idx, const uint8 *tag, uint len); + +/* create/allocate a bloom filter. filter size can be 0 for validate only filters */ +int bcm_bloom_create(bcm_bloom_alloc_t alloc_cb, + bcm_bloom_free_t free_cb, void *callback_ctx, uint max_hash, + uint filter_size /* bytes */, bcm_bloom_filter_t **bloom); + +/* destroy bloom filter */ +int bcm_bloom_destroy(bcm_bloom_filter_t **bloom, bcm_bloom_free_t free_cb); + +/* add a hash function to filter, return an index */ +int bcm_bloom_add_hash(bcm_bloom_filter_t *filter, bcm_bloom_hash_t hash, uint *idx); + +/* remove the hash function at index from filter */ +int bcm_bloom_remove_hash(bcm_bloom_filter_t *filter, uint idx); + +/* check if given tag is member of the filter. If buf is NULL and/or buf_len is 0 + * then use the internal state. BCME_OK if member, BCME_NOTFOUND if not, + * or other error (e.g. BADARG) + */ +bool bcm_bloom_is_member(bcm_bloom_filter_t *filter, + const uint8 *tag, uint tag_len, const uint8 *buf, uint buf_len); + +/* add a member to the filter. invalid for validate_only filters */ +int bcm_bloom_add_member(bcm_bloom_filter_t *filter, const uint8 *tag, uint tag_len); + +/* no support for remove member */ + +/* get the filter data from state. BCME_BUFTOOSHORT w/ required length in buf_len + * if supplied size is insufficient + */ +int bcm_bloom_get_filter_data(bcm_bloom_filter_t *filter, + uint buf_size, uint8 *buf, uint *buf_len); + +#endif /* _bcmbloom_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmcdc.h b/drivers/net/wireless/bcmdhd_oo/include/bcmcdc.h index 22fd8a0933bbfb8f0fa097458dc27e7b106409ed..f642142f23ab55221d324e6eadc79cc81d4fe639 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmcdc.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmcdc.h @@ -4,14 +4,14 @@ * * Definitions subject to change without notice. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: bcmcdc.h 676811 2016-12-24 20:48:46Z $ + * $Id: bcmcdc.h 700076 2017-05-17 14:42:22Z $ */ #ifndef _bcmcdc_h_ #define _bcmcdc_h_ @@ -89,6 +89,7 @@ struct bdc_header { #define BDC_HEADER_LEN 4 /* flags field bitmap */ +#define BDC_FLAG_EXEMPT 0x03 /* EXT_STA: encryption exemption (host -> dongle?) */ #define BDC_FLAG_80211_PKT 0x01 /* Packet is in 802.11 format (dongle -> host) */ #define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ #define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums: host->device */ @@ -117,19 +118,4 @@ struct bdc_header { #define BDC_SET_IF_IDX(hdr, idx) \ ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) -#define BDC_FLAG2_PAD_MASK 0xf0 -#define BDC_FLAG_PAD_MASK 0x03 -#define BDC_FLAG2_PAD_SHIFT 2 -#define BDC_FLAG_PAD_SHIFT 0 -#define BDC_FLAG2_PAD_IDX 0x3c -#define BDC_FLAG_PAD_IDX 0x03 -#define BDC_GET_PAD_LEN(hdr) \ - ((int)(((((hdr)->flags2) & BDC_FLAG2_PAD_MASK) >> BDC_FLAG2_PAD_SHIFT) | \ - ((((hdr)->flags) & BDC_FLAG_PAD_MASK) >> BDC_FLAG_PAD_SHIFT))) -#define BDC_SET_PAD_LEN(hdr, idx) \ - ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_PAD_MASK) | \ - (((idx) & BDC_FLAG2_PAD_IDX) << BDC_FLAG2_PAD_SHIFT))); \ - ((hdr)->flags = (((hdr)->flags & ~BDC_FLAG_PAD_MASK) | \ - (((idx) & BDC_FLAG_PAD_IDX) << BDC_FLAG_PAD_SHIFT))) - #endif /* _bcmcdc_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmdefs.h b/drivers/net/wireless/bcmdhd_oo/include/bcmdefs.h index 0af59ff4f7a65893dbf8188ca9660470dd0a3f21..a29c46e3e30faa25d12733bc95e081d532f5cafa 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmdefs.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmdefs.h @@ -1,14 +1,14 @@ /* * Misc system wide definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmdefs.h 657791 2016-09-02 15:14:42Z $ + * $Id: bcmdefs.h 700870 2017-05-22 19:05:22Z $ */ #ifndef _bcmdefs_h_ @@ -45,7 +45,23 @@ #define UNUSED_VAR __attribute__ ((unused)) #else #define UNUSED_VAR -#endif +#endif // endif + +/* GNU GCC 4.6+ supports selectively turning off a warning. + * Define these diagnostic macros to help suppress cast-qual warning + * until all the work can be done to fix the casting issues. + */ +#if defined(__GNUC__) && defined(STRICT_GCC_WARNINGS) && (__GNUC__ > 4 || (__GNUC__ == \ + 4 && __GNUC_MINOR__ >= 6)) +#define GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST() \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#define GCC_DIAGNOSTIC_POP() \ + _Pragma("GCC diagnostic pop") +#else +#define GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST() +#define GCC_DIAGNOSTIC_POP() +#endif /* Diagnostic macros not defined */ /* Compile-time assert can be used in place of ASSERT if the expression evaluates * to a constant at compile time. @@ -68,6 +84,12 @@ extern bool bcm_reclaimed; extern bool bcm_attach_part_reclaimed; extern bool bcm_preattach_part_reclaimed; +extern bool bcm_postattach_part_reclaimed; + +#define RECLAIMED() (bcm_reclaimed) +#define ATTACH_PART_RECLAIMED() (bcm_attach_part_reclaimed) +#define PREATTACH_PART_RECLAIMED() (bcm_preattach_part_reclaimed) +#define POSTATTACH_PART_RECLAIMED() (bcm_postattach_part_reclaimed) #if defined(BCM_RECLAIM_ATTACH_FN_DATA) #define _data __attribute__ ((__section__ (".dataini2." #_data))) _data @@ -84,13 +106,32 @@ extern bool bcm_preattach_part_reclaimed; #define BCMPREATTACHDATA(_data) __attribute__ ((__section__ (".dataini2." #_data))) _data #define BCMPREATTACHFN(_fn) __attribute__ ((__section__ (".textini2." #_fn), noinline)) _fn #endif /* PREATTACH_NORECLAIM */ +#define BCMPOSTATTACHDATA(_data) __attribute__ ((__section__ (".dataini5." #_data))) _data +#define BCMPOSTATTACHFN(_fn) __attribute__ ((__section__ (".textini5." #_fn), noinline)) _fn #else /* BCM_RECLAIM_ATTACH_FN_DATA */ #define _data _data #define _fn _fn #define BCMPREATTACHDATA(_data) _data #define BCMPREATTACHFN(_fn) _fn +#define BCMPOSTATTACHDATA(_data) _data +#define BCMPOSTATTACHFN(_fn) _fn #endif /* BCM_RECLAIM_ATTACH_FN_DATA */ +#ifdef BCMDBG_SR +/* + * Don't reclaim so we can compare SR ASM + */ +#define BCMPREATTACHDATASR(_data) _data +#define BCMPREATTACHFNSR(_fn) _fn +#define BCMATTACHDATASR(_data) _data +#define BCMATTACHFNSR(_fn) _fn +#else +#define BCMPREATTACHDATASR(_data) BCMPREATTACHDATA(_data) +#define BCMPREATTACHFNSR(_fn) BCMPREATTACHFN(_fn) +#define BCMATTACHDATASR(_data) _data +#define BCMATTACHFNSR(_fn) _fn +#endif // endif + #if defined(BCM_RECLAIM_INIT_FN_DATA) #define _data __attribute__ ((__section__ (".dataini1." #_data))) _data #define _fn __attribute__ ((__section__ (".textini1." #_fn), noinline)) _fn @@ -100,37 +141,92 @@ extern bool bcm_preattach_part_reclaimed; #define _fn _fn #ifndef CONST #define CONST const -#endif +#endif // endif #endif /* BCM_RECLAIM_INIT_FN_DATA */ /* Non-manufacture or internal attach function/dat */ #define BCMNMIATTACHFN(_fn) _fn #define BCMNMIATTACHDATA(_data) _data +#if defined(BCM_CISDUMP_NO_RECLAIM) +#define BCMCISDUMPATTACHFN(_fn) _fn +#define BCMCISDUMPATTACHDATA(_data) _data +#else +#define BCMCISDUMPATTACHFN(_fn) BCMNMIATTACHFN(_fn) +#define BCMCISDUMPATTACHDATA(_data) BCMNMIATTACHDATA(_data) +#endif // endif + +/* SROM with OTP support */ +#if defined(BCMOTPSROM) +#define BCMSROMATTACHFN(_fn) _fn +#define BCMSROMATTACHDATA(_data) _data +#else +#define BCMSROMATTACHFN(_fn) BCMNMIATTACHFN(_fn) +#define BCMSROMATTACHDATA(_data) BCMNMIATTACHFN(_data) +#endif /* BCMOTPSROM */ + +#if defined(BCM_CISDUMP_NO_RECLAIM) +#define BCMSROMCISDUMPATTACHFN(_fn) _fn +#define BCMSROMCISDUMPATTACHDATA(_data) _data +#else +#define BCMSROMCISDUMPATTACHFN(_fn) BCMSROMATTACHFN(_fn) +#define BCMSROMCISDUMPATTACHDATA(_data) BCMSROMATTACHDATA(_data) +#endif /* BCM_CISDUMP_NO_RECLAIM */ + #ifdef BCMNODOWN #define _fn _fn #else #define _fn _fn -#endif +#endif // endif #else /* BCM_RECLAIM */ -#define bcm_reclaimed 0 +#define bcm_reclaimed (1) +#define bcm_attach_part_reclaimed (1) +#define bcm_preattach_part_reclaimed (1) +#define bcm_postattach_part_reclaimed (1) #define _data _data #define _fn _fn #define BCM_SRM_ATTACH_DATA(_data) _data #define BCM_SRM_ATTACH_FN(_fn) _fn #define BCMPREATTACHDATA(_data) _data #define BCMPREATTACHFN(_fn) _fn +#define BCMPOSTATTACHDATA(_data) _data +#define BCMPOSTATTACHFN(_fn) _fn #define _data _data #define _fn _fn #define _fn _fn #define BCMNMIATTACHFN(_fn) _fn #define BCMNMIATTACHDATA(_data) _data +#define BCMSROMATTACHFN(_fn) _fn +#define BCMSROMATTACHDATA(_data) _data +#define BCMPREATTACHFNSR(_fn) _fn +#define BCMPREATTACHDATASR(_data) _data +#define BCMATTACHFNSR(_fn) _fn +#define BCMATTACHDATASR(_data) _data +#define BCMSROMATTACHFN(_fn) _fn +#define BCMSROMATTACHDATA(_data) _data +#define BCMCISDUMPATTACHFN(_fn) _fn +#define BCMCISDUMPATTACHDATA(_data) _data +#define BCMSROMCISDUMPATTACHFN(_fn) _fn +#define BCMSROMCISDUMPATTACHDATA(_data) _data #define CONST const +#define RECLAIMED() (bcm_reclaimed) +#define ATTACH_PART_RECLAIMED() (bcm_attach_part_reclaimed) +#define PREATTACH_PART_RECLAIMED() (bcm_preattach_part_reclaimed) +#define POSTATTACH_PART_RECLAIMED() (bcm_postattach_part_reclaimed) + #endif /* BCM_RECLAIM */ +#define BCMUCODEDATA(_data) _data + +#if defined(BCM_DMA_CT) && !defined(BCM_DMA_CT_DISABLED) +#define BCMUCODEFN(_fn) _fn +#else +#define BCMUCODEFN(_fn) _fn +#endif /* BCM_DMA_CT */ + #if !defined STB #undef BCM47XX_CA9 #endif /* STB */ @@ -141,13 +237,12 @@ extern bool bcm_preattach_part_reclaimed; #if defined(STB) #define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) #define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) -#else +#else /* mips || BCM47XX_CA9 || STB */ #define BCMFASTPATH #define BCMFASTPATH_HOST -#endif +#endif // endif #endif /* BCMFASTPATH */ - /* Use the BCMRAMFN() macro to tag functions in source that must be included in RAM (excluded from * ROM). This should eliminate the need to manually specify these functions in the ROM config file. * It should only be used in special cases where the function must be in RAM for *all* ROM-based @@ -155,6 +250,9 @@ extern bool bcm_preattach_part_reclaimed; */ #define BCMRAMFN(_fn) _fn +/* Use BCMSPECSYM() macro to tag symbols going to a special output section in the binary. */ +#define BCMSPECSYM(_sym) __attribute__ ((__section__ (".special." #_sym))) _sym + #define STATIC static /* Bus types */ @@ -172,21 +270,20 @@ extern bool bcm_preattach_part_reclaimed; #define BUSTYPE(bus) (BCMBUSTYPE) #else #define BUSTYPE(bus) (bus) -#endif +#endif // endif #ifdef BCMBUSCORETYPE #define BUSCORETYPE(ct) (BCMBUSCORETYPE) #else #define BUSCORETYPE(ct) (ct) -#endif +#endif // endif /* Allows size optimization for single-backplane image */ #ifdef BCMCHIPTYPE #define CHIPTYPE(bus) (BCMCHIPTYPE) #else #define CHIPTYPE(bus) (bus) -#endif - +#endif // endif /* Allows size optimization for SPROM support */ #if defined(BCMSPROMBUS) @@ -195,44 +292,48 @@ extern bool bcm_preattach_part_reclaimed; #define SPROMBUS (PCMCIA_BUS) #else #define SPROMBUS (PCI_BUS) -#endif +#endif // endif /* Allows size optimization for single-chip image */ #ifdef BCMCHIPID #define CHIPID(chip) (BCMCHIPID) #else #define CHIPID(chip) (chip) -#endif +#endif // endif #ifdef BCMCHIPREV #define CHIPREV(rev) (BCMCHIPREV) #else #define CHIPREV(rev) (rev) -#endif +#endif // endif #ifdef BCMPCIEREV #define PCIECOREREV(rev) (BCMPCIEREV) #else #define PCIECOREREV(rev) (rev) -#endif +#endif // endif #ifdef BCMPMUREV #define PMUREV(rev) (BCMPMUREV) #else #define PMUREV(rev) (rev) -#endif +#endif // endif #ifdef BCMCCREV #define CCREV(rev) (BCMCCREV) #else #define CCREV(rev) (rev) -#endif +#endif // endif #ifdef BCMGCIREV #define GCIREV(rev) (BCMGCIREV) #else #define GCIREV(rev) (rev) -#endif +#endif // endif + +#ifdef BCMCR4REV +#define CR4REV (BCMCR4REV) +#endif // endif /* Defines for DMA Address Width - Shared between OSL and HNDDMA */ #define DMADDR_MASK_32 0x0 /* Address mask for 32-bits */ @@ -293,7 +394,6 @@ typedef struct { #define MAX_DMA_SEGS 8 - typedef struct { void *oshdmah; /* Opaque handle for OSL to store its information */ uint origsize; /* Size of the virtual packet */ @@ -301,7 +401,6 @@ typedef struct { hnddma_seg_t segs[MAX_DMA_SEGS]; } hnddma_seg_map_t; - /* packet headroom necessary to accommodate the largest header in the system, (i.e TXOFF). * By doing, we avoid the need to allocate an extra buffer for the header when bridging to WL. * There is a compile time check in wlc.c which ensure that this value is at least as big @@ -316,13 +415,13 @@ typedef struct { #define BCMEXTRAHDROOM 224 #else #define BCMEXTRAHDROOM 204 -#endif +#endif // endif #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY */ /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef SDALIGN #define SDALIGN 32 -#endif +#endif // endif /* Headroom required for dongle-to-host communication. Packets allocated * locally in the dongle (e.g. for CDC ioctls or RNDIS messages) should @@ -336,15 +435,14 @@ typedef struct { #define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) - #if defined(NO_BCMDBG_ASSERT) # undef BCMDBG_ASSERT # undef BCMASSERT_LOG -#endif +#endif // endif #if defined(BCMASSERT_LOG) #define BCMASSERT_SUPPORT -#endif +#endif // endif /* Macros for doing definition and get/set of bitfields * Usage example, e.g. a three-bit field (bits 4-6): @@ -371,28 +469,25 @@ typedef struct { #else #define BCMSPACE #define bcmspace TRUE /* if (bcmspace) code is retained */ -#endif +#endif // endif /* Max. nvram variable table size */ #ifndef MAXSZ_NVRAM_VARS #ifdef LARGE_NVRAM_MAXSZ -#define MAXSZ_NVRAM_VARS LARGE_NVRAM_MAXSZ +#define MAXSZ_NVRAM_VARS (LARGE_NVRAM_MAXSZ * 2) #else -/* SROM12 changes */ -#define MAXSZ_NVRAM_VARS 6144 +#define LARGE_NVRAM_MAXSZ 8192 +#define MAXSZ_NVRAM_VARS (LARGE_NVRAM_MAXSZ * 2) #endif /* LARGE_NVRAM_MAXSZ */ #endif /* !MAXSZ_NVRAM_VARS */ - - -/* WL_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also +/* ROM_ENAB_RUNTIME_CHECK may be set based upon the #define below (for ROM builds). It may also * be defined via makefiles (e.g. ROM auto abandon unoptimized compiles). */ - #ifdef BCMLFRAG /* BCMLFRAG support enab macros */ extern bool _bcmlfrag; - #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) + #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) #define BCMLFRAG_ENAB() (_bcmlfrag) #elif defined(BCMLFRAG_DISABLED) #define BCMLFRAG_ENAB() (0) @@ -405,7 +500,7 @@ typedef struct { #ifdef BCMPCIEDEV /* BCMPCIEDEV support enab macros */ extern bool _pciedevenab; - #if defined(WL_ENAB_RUNTIME_CHECK) + #if defined(ROM_ENAB_RUNTIME_CHECK) #define BCMPCIEDEV_ENAB() (_pciedevenab) #elif defined(BCMPCIEDEV_ENABLED) #define BCMPCIEDEV_ENAB() 1 @@ -416,6 +511,19 @@ extern bool _pciedevenab; #define BCMPCIEDEV_ENAB() 0 #endif /* BCMPCIEDEV */ +#ifdef BCMRESVFRAGPOOL /* BCMRESVFRAGPOOL support enab macros */ +extern bool _resvfragpool_enab; + #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) + #define BCMRESVFRAGPOOL_ENAB() (_resvfragpool_enab) + #elif defined(BCMRESVFRAGPOOL_ENABLED) + #define BCMRESVFRAGPOOL_ENAB() 1 + #else + #define BCMRESVFRAGPOOL_ENAB() 0 + #endif +#else + #define BCMRESVFRAGPOOL_ENAB() 0 +#endif /* BCMPCIEDEV */ + #define BCMSDIODEV_ENAB() 0 /* Max size for reclaimable NVRAM array */ @@ -427,32 +535,66 @@ extern bool _pciedevenab; extern uint32 gFWID; +#ifdef BCMFRWDPOOLREORG /* BCMFRWDPOOLREORG support enab macros */ + extern bool _bcmfrwdpoolreorg; + #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) + #define BCMFRWDPOOLREORG_ENAB() (_bcmfrwdpoolreorg) + #elif defined(BCMFRWDPOOLREORG_DISABLED) + #define BCMFRWDPOOLREORG_ENAB() (0) + #else + #define BCMFRWDPOOLREORG_ENAB() (1) + #endif +#else + #define BCMFRWDPOOLREORG_ENAB() (0) +#endif /* BCMFRWDPOOLREORG */ + +#ifdef BCMPOOLRECLAIM /* BCMPOOLRECLAIM support enab macros */ + extern bool _bcmpoolreclaim; + #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) + #define BCMPOOLRECLAIM_ENAB() (_bcmpoolreclaim) + #elif defined(BCMPOOLRECLAIM_DISABLED) + #define BCMPOOLRECLAIM_ENAB() (0) + #else + #define BCMPOOLRECLAIM_ENAB() (1) + #endif +#else + #define BCMPOOLRECLAIM_ENAB() (0) +#endif /* BCMPOOLRECLAIM */ + /* Chip related low power flags (lpflags) */ -#define LPFLAGS_SI_GLOBAL_DISABLE (1 << 0) -#define LPFLAGS_SI_MEM_STDBY_DISABLE (1 << 1) -#define LPFLAGS_SI_SFLASH_DISABLE (1 << 2) -#define LPFLAGS_SI_BTLDO3P3_DISABLE (1 << 3) -#define LPFLAGS_SI_GCI_FORCE_REGCLK_DISABLE (1 << 4) -#define LPFLAGS_SI_FORCE_PWM_WHEN_RADIO_ON (1 << 5) -#define LPFLAGS_PHY_GLOBAL_DISABLE (1 << 16) -#define LPFLAGS_PHY_LP_DISABLE (1 << 17) -#define LPFLAGS_PSM_PHY_CTL (1 << 18) - -/* Chip related Cbuck modes */ -#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE0 0x00001c03 -#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE0 0x00492490 -#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE1 0x00001c03 -#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE1 0x00490410 - -/* Chip related dynamic cbuck mode mask */ - -#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE_MASK 0xFFFFFC00 -#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE_MASK 0xFFFFFFFF #ifndef PAD #define _PADLINE(line) pad ## line #define _XSTR(line) _PADLINE(line) #define PAD _XSTR(__LINE__) -#endif +#endif // endif + +#ifndef FRAG_HEADROOM +#define FRAG_HEADROOM 224 /* In absence of SFD, use default headroom of 224 */ +#endif // endif + +#define MODULE_DETACH(var, detach_func)\ + if (var) { \ + detach_func(var); \ + (var) = NULL; \ + } +#define MODULE_DETACH_2(var1, var2, detach_func) detach_func(var1, var2) +#define MODULE_DETACH_TYPECASTED(var, detach_func) detach_func(var) + +/* When building ROML image use runtime conditional to cause the compiler + * to compile everything but not to complain "defined but not used" + * as #ifdef would cause at the callsites. + * In the end functions called under if (0) {} will not be linked + * into the final binary if they're not called from other places either. + */ +#define BCM_ATTACH_REF_DECL() +#define BCM_ATTACH_REF() (1) + +/* Const in ROM else normal data in RAM */ +#if defined(ROM_ENAB_RUNTIME_CHECK) + #define ROMCONST CONST +#else + #define ROMCONST +#endif // endif #endif /* _bcmdefs_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmdevs.h b/drivers/net/wireless/bcmdhd_oo/include/bcmdevs.h index ed17dd53c73184d1738df9d9b9d509cf4da80b98..14d09fa2da7e4796733c7c442c8f493d88ce6a84 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmdevs.h @@ -1,14 +1,14 @@ /* * Broadcom device-specific manifest constants. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmdevs.h 625027 2016-03-15 08:20:18Z $ + * $Id: bcmdevs.h 724604 2017-10-03 11:03:38Z $ */ #ifndef _BCMDEVS_H @@ -47,7 +47,6 @@ #define VENDOR_RICOH 0x1180 /* Ricoh */ #define VENDOR_JMICRON 0x197b - /* PCMCIA vendor IDs */ #define VENDOR_BROADCOM_PCMCIA 0x02d0 @@ -61,29 +60,25 @@ #define BCM_DNGL_BL_PID_4319 0xbd16 #define BCM_DNGL_BL_PID_43236 0xbd17 #define BCM_DNGL_BL_PID_4332 0xbd18 -#define BCM_DNGL_BL_PID_4330 0xbd19 -#define BCM_DNGL_BL_PID_4334 0xbd1a -#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_43341 0xbd22 #define BCM_DNGL_BL_PID_4350 0xbd23 #define BCM_DNGL_BL_PID_4345 0xbd24 #define BCM_DNGL_BL_PID_4349 0xbd25 #define BCM_DNGL_BL_PID_4354 0xbd26 #define BCM_DNGL_BL_PID_43569 0xbd27 -#define BCM_DNGL_BL_PID_43909 0xbd28 #define BCM_DNGL_BL_PID_4373 0xbd29 #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 -/* HW USB BLOCK [CPULESS USB] PIDs */ -#define BCM_HWUSB_PID_43239 43239 +#ifdef DEPRECATED +#define BCM_DNGL_BL_PID_43239 0xbd1b +#define BCM_DNGL_BL_PID_4324 0xbd1c +#define BCM_DNGL_BL_PID_43242 0xbd1f +#define BCM_DNGL_BL_PID_43909 0xbd28 +#endif // endif /* PCI Device IDs */ #ifdef DEPRECATED /* These products have been deprecated */ @@ -117,68 +112,73 @@ #define BCM4329_D11N_ID 0x432e /* 4329 802.11n dualband device */ #define BCM4329_D11N2G_ID 0x432f /* 4329 802.11n 2.4G device */ #define BCM4329_D11N5G_ID 0x4330 /* 4329 802.11n 5G device */ +#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ +#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */ #define BCM4315_D11DUAL_ID 0x4334 /* 4315 802.11a/g id */ #define BCM4315_D11G_ID 0x4335 /* 4315 802.11g id */ #define BCM4315_D11A_ID 0x4336 /* 4315 802.11a id */ #define BCM4319_D11N_ID 0x4337 /* 4319 802.11n dualband device */ #define BCM4319_D11N2G_ID 0x4338 /* 4319 802.11n 2.4G device */ #define BCM4319_D11N5G_ID 0x4339 /* 4319 802.11n 5G device */ -#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ #define BCM43221_D11N2G_ID 0x4341 /* 43221 802.11n 2.4GHz device */ #define BCM43222_D11N_ID 0x4350 /* 43222 802.11n dualband device */ #define BCM43222_D11N2G_ID 0x4351 /* 43222 802.11n 2.4GHz device */ #define BCM43222_D11N5G_ID 0x4352 /* 43222 802.11n 5GHz device */ +#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ #define BCM43226_D11N_ID 0x4354 /* 43226 802.11n dualband device */ +#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ +#define BCM43231_D11N2G_ID 0x4340 /* 43231 802.11n 2.4GHz device */ +#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ +#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ +#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ +#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ +#define BCM43242_D11N_ID 0x4367 /* 43242 802.11n dualband device */ +#define BCM43242_D11N2G_ID 0x4368 /* 43242 802.11n 2.4G device */ +#define BCM43242_D11N5G_ID 0x4369 /* 43242 802.11n 5G device */ +#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ +#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ +#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ +#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ +#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ +#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ +#define BCM43342_D11N_ID 0x4383 /* 43342 802.11n dualband device */ +#define BCM43342_D11N2G_ID 0x4384 /* 43342 802.11n 2.4G device */ +#define BCM43342_D11N5G_ID 0x4385 /* 43342 802.11n 5G device */ +#define BCM43341_D11N_ID 0x4386 /* 43341 802.11n dualband device */ +#define BCM43341_D11N2G_ID 0x4387 /* 43341 802.11n 2.4G device */ +#define BCM43341_D11N5G_ID 0x4388 /* 43341 802.11n 5G device */ +#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ +#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ +#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ +#define BCM43909_D11AC_ID 0x43d0 /* 43909 802.11ac dualband device */ +#define BCM43909_D11AC2G_ID 0x43d1 /* 43909 802.11ac 2.4G device */ +#define BCM43909_D11AC5G_ID 0x43d2 /* 43909 802.11ac 5G device */ #endif /* DEPRECATED */ /* DEPRECATED but used */ #define BCM4306_D11G_ID 0x4320 /* 4306 802.11g */ #define BCM4306_D11A_ID 0x4321 /* 4306 802.11a */ #define BCM4306_D11DUAL_ID 0x4324 /* 4306 dual A+B */ +#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ +#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ #define BCM4318_D11G_ID 0x4318 /* 4318 802.11b/g id */ #define BCM4318_D11DUAL_ID 0x4319 /* 4318 802.11a/b/g id */ -/* DEPRECATED */ - -#define BCM53572_D11N2G_ID 0x4329 /* 53572 802.11n 2.4Ghz band id (same as BCM4321) */ #define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */ #define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db device */ +#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ +#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ +#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ +#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ +#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ +/* DEPRECATED */ + #define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */ #define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */ #define BCM43236_D11N5G_ID 0x4348 /* 43236 802.11n 5GHz device */ -#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */ -#define BCM43421_D11N_ID 0xA99D /* 43421 802.11n dualband device */ -#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */ -#define BCM4330_D11N_ID 0x4360 /* 4330 802.11n dualband device */ -#define BCM4330_D11N2G_ID 0x4361 /* 4330 802.11n 2.4G device */ -#define BCM4330_D11N5G_ID 0x4362 /* 4330 802.11n 5G device */ -#define BCM4336_D11N_ID 0x4343 /* 4336 802.11n 2.4GHz device */ #define BCM6362_D11N_ID 0x435f /* 6362 802.11n dualband device */ #define BCM6362_D11N2G_ID 0x433f /* 6362 802.11n 2.4Ghz band id */ #define BCM6362_D11N5G_ID 0x434f /* 6362 802.11n 5Ghz band id */ -#define BCM4331_D11N_ID 0x4331 /* 4331 802.11n dualband id */ -#define BCM4331_D11N2G_ID 0x4332 /* 4331 802.11n 2.4Ghz band id */ -#define BCM4331_D11N5G_ID 0x4333 /* 4331 802.11n 5Ghz band id */ -#define BCM43237_D11N_ID 0x4355 /* 43237 802.11n dualband device */ -#define BCM43237_D11N5G_ID 0x4356 /* 43237 802.11n 5GHz device */ -#define BCM43227_D11N2G_ID 0x4358 /* 43228 802.11n 2.4GHz device */ -#define BCM43228_D11N_ID 0x4359 /* 43228 802.11n DualBand device */ -#define BCM43228_D11N5G_ID 0x435a /* 43228 802.11n 5GHz device */ -#define BCM43362_D11N_ID 0x4363 /* 43362 802.11n 2.4GHz device */ -#define BCM43239_D11N_ID 0x4370 /* 43239 802.11n dualband device */ -#define BCM4324_D11N_ID 0x4374 /* 4324 802.11n dualband device */ #define BCM43217_D11N2G_ID 0x43a9 /* 43217 802.11n 2.4GHz device */ #define BCM43131_D11N2G_ID 0x43aa /* 43131 802.11n 2.4GHz device */ -#define BCM4314_D11N2G_ID 0x4364 /* 4314 802.11n 2.4G device */ -#define BCM43142_D11N2G_ID 0x4365 /* 43142 802.11n 2.4G device */ -#define BCM43143_D11N2G_ID 0x4366 /* 43143 802.11n 2.4G device */ -#define BCM4334_D11N_ID 0x4380 /* 4334 802.11n dualband device */ -#define BCM4334_D11N2G_ID 0x4381 /* 4334 802.11n 2.4G device */ -#define BCM4334_D11N5G_ID 0x4382 /* 4334 802.11n 5G device */ -#define BCM43342_D11N_ID 0x4383 /* 43342 802.11n dualband device */ -#define BCM43342_D11N2G_ID 0x4384 /* 43342 802.11n 2.4G device */ -#define BCM43342_D11N5G_ID 0x4385 /* 43342 802.11n 5G device */ -#define BCM43341_D11N_ID 0x4386 /* 43341 802.11n dualband device */ -#define BCM43341_D11N2G_ID 0x4387 /* 43341 802.11n 2.4G device */ -#define BCM43341_D11N5G_ID 0x4388 /* 43341 802.11n 5G device */ #define BCM4360_D11AC_ID 0x43a0 #define BCM4360_D11AC2G_ID 0x43a1 #define BCM4360_D11AC5G_ID 0x43a2 @@ -218,25 +218,15 @@ #define BCM43597_D11AC_ID 0x441c /* 43597 802.11ac dualband device */ #define BCM43597_D11AC2G_ID 0x441d /* 43597 802.11ac 2.4G device */ #define BCM43597_D11AC5G_ID 0x441e /* 43597 802.11ac 5G device */ -#define BCM43909_D11AC_ID 0x43d0 /* 43909 802.11ac dualband device */ -#define BCM43909_D11AC2G_ID 0x43d1 /* 43909 802.11ac 2.4G device */ -#define BCM43909_D11AC5G_ID 0x43d2 /* 43909 802.11ac 5G device */ #define BCM43012_D11N_ID 0xA804 /* 43012 802.11n dualband device */ #define BCM43012_D11N2G_ID 0xA805 /* 43012 802.11n 2.4G device */ #define BCM43012_D11N5G_ID 0xA806 /* 43012 802.11n 5G device */ /* PCI Subsystem ID */ -#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 /* 43143 802.11n 2.4G device */ - -#define BCM43242_D11N_ID 0x4367 /* 43242 802.11n dualband device */ -#define BCM43242_D11N2G_ID 0x4368 /* 43242 802.11n 2.4G device */ -#define BCM43242_D11N5G_ID 0x4369 /* 43242 802.11n 5G device */ - #define BCM4350_D11AC_ID 0x43a3 #define BCM4350_D11AC2G_ID 0x43a4 #define BCM4350_D11AC5G_ID 0x43a5 @@ -271,7 +261,6 @@ #define BCM43430_D11N2G_ID 0x43e2 /* 43430 802.11n 2.4G device */ #define BCM43018_D11N2G_ID 0x441b /* 43018 802.11n 2.4G device */ - #define BCM4347_D11AC_ID 0x440a /* 4347 802.11ac dualband device */ #define BCM4347_D11AC2G_ID 0x440b /* 4347 802.11ac 2.4G device */ #define BCM4347_D11AC5G_ID 0x440c /* 4347 802.11ac 5G device */ @@ -378,6 +367,10 @@ #define BCM43111_CHIP_ID 43111 /* 43111 chipcommon chipid (OTP chipid) */ #define BCM43112_CHIP_ID 43112 /* 43112 chipcommon chipid (OTP chipid) */ #define BCM4312_CHIP_ID 0x4312 /* 4312 chipcommon chipid */ +#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ +#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ +#define BCM43143_CHIP_ID 43143 /* 43143 chipcommon chipid */ +#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ #define BCM4315_CHIP_ID 0x4315 /* 4315 chip id */ #define BCM4318_CHIP_ID 0x4318 /* 4318 chipcommon chipid */ #define BCM4319_CHIP_ID 0x4319 /* 4319 chip id */ @@ -386,62 +379,59 @@ #define BCM4322_CHIP_ID 0x4322 /* 4322 chipcommon chipid */ #define BCM43221_CHIP_ID 43221 /* 43221 chipcommon chipid (OTP chipid) */ #define BCM43222_CHIP_ID 43222 /* 43222 chipcommon chipid */ +#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ +#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ #define BCM43226_CHIP_ID 43226 /* 43226 chipcommon chipid */ +#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ +#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ #define BCM43231_CHIP_ID 43231 /* 43231 chipcommon chipid (OTP chipid) */ -#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ +#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ +#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ +#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ +#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ +#define BCM43243_CHIP_ID 43243 /* 43243 chipcommon chipid */ #define BCM4325_CHIP_ID 0x4325 /* 4325 chip id */ #define BCM4328_CHIP_ID 0x4328 /* 4328 chip id */ #define BCM4329_CHIP_ID 0x4329 /* 4329 chipcommon chipid */ +#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ +#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ +#define BCM43349_CHIP_ID 43349 /* 43349(0xA955) chipcommon chipid */ +#define BCM43340_CHIP_ID 43340 /* 43340 chipcommon chipid */ +#define BCM43341_CHIP_ID 43341 /* 43341 chipcommon chipid */ +#define BCM43342_CHIP_ID 43342 /* 43342 chipcommon chipid */ +#define BCM4342_CHIP_ID 4342 /* 4342 chipcommon chipid (OTP, RBBU) */ +#define BCM43420_CHIP_ID 43420 /* 43420 chipcommon chipid (OTP, RBBU) */ +#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ +#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ +#define BCM43909_CHIP_ID 0xab85 /* 43909 chipcommon chipid */ #define BCM4712_CHIP_ID 0x4712 /* 4712 chipcommon chipid */ +#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ +#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ #endif /* DEPRECATED */ /* DEPRECATED but still referenced in components - start */ -#define BCM4716_CHIP_ID 0x4716 /* 4716 chipcommon chipid */ -#define BCM4748_CHIP_ID 0x4748 /* 4716 chipcommon chipid (OTP, RBBU) */ #define BCM47162_CHIP_ID 47162 /* 47162 chipcommon chipid */ #define BCM5354_CHIP_ID 0x5354 /* 5354 chipcommon chipid */ /* DEPRECATED but still referenced in components - end */ -#define BCM43224_CHIP_ID 43224 /* 43224 chipcommon chipid */ -#define BCM43225_CHIP_ID 43225 /* 43225 chipcommon chipid */ -#define BCM43227_CHIP_ID 43227 /* 43227 chipcommon chipid */ -#define BCM43228_CHIP_ID 43228 /* 43228 chipcommon chipid */ #define BCM43217_CHIP_ID 43217 /* 43217 chip id (OTP chipid) */ -#define BCM4313_CHIP_ID 0x4313 /* 4313 chip id */ #define BCM43131_CHIP_ID 43131 /* 43131 chip id (OTP chipid) */ #define BCM43234_CHIP_ID 43234 /* 43234 chipcommon chipid */ #define BCM43235_CHIP_ID 43235 /* 43235 chipcommon chipid */ #define BCM43236_CHIP_ID 43236 /* 43236 chipcommon chipid */ -#define BCM43237_CHIP_ID 43237 /* 43237 chipcommon chipid */ #define BCM43238_CHIP_ID 43238 /* 43238 chipcommon chipid */ -#define BCM43239_CHIP_ID 43239 /* 43239 chipcommon chipid */ -#define BCM43420_CHIP_ID 43420 /* 43222 chipcommon chipid (OTP, RBBU) */ -#define BCM43421_CHIP_ID 43421 /* 43224 chipcommon chipid (OTP, RBBU) */ #define BCM43428_CHIP_ID 43428 /* 43228 chipcommon chipid (OTP, RBBU) */ -#define BCM43431_CHIP_ID 43431 /* 4331 chipcommon chipid (OTP, RBBU) */ #define BCM43460_CHIP_ID 43460 /* 4360 chipcommon chipid (OTP, RBBU) */ -#define BCM4331_CHIP_ID 0x4331 /* 4331 chipcommon chipid */ -#define BCM4336_CHIP_ID 0x4336 /* 4336 chipcommon chipid */ -#define BCM43362_CHIP_ID 43362 /* 43362 chipcommon chipid */ -#define BCM4330_CHIP_ID 0x4330 /* 4330 chipcommon chipid */ +#define BCM43465_CHIP_ID 43465 /* 4366 chipcommon chipid (OTP, RBBU) */ +#define BCM43525_CHIP_ID 43525 /* 4365 chipcommon chipid (OTP, RBBU) */ +#define BCM47452_CHIP_ID 47452 /* 53573 chipcommon chipid (OTP, RBBU) */ #define BCM6362_CHIP_ID 0x6362 /* 6362 chipcommon chipid */ -#define BCM4314_CHIP_ID 0x4314 /* 4314 chipcommon chipid */ -#define BCM43142_CHIP_ID 43142 /* 43142 chipcommon chipid */ -#define BCM43143_CHIP_ID 43143 /* 43143 chipcommon chipid */ -#define BCM4324_CHIP_ID 0x4324 /* 4324 chipcommon chipid */ -#define BCM43242_CHIP_ID 43242 /* 43242 chipcommon chipid */ -#define BCM43243_CHIP_ID 43243 /* 43243 chipcommon chipid */ -#define BCM4334_CHIP_ID 0x4334 /* 4334 chipcommon chipid */ #define BCM4335_CHIP_ID 0x4335 /* 4335 chipcommon chipid */ #define BCM4339_CHIP_ID 0x4339 /* 4339 chipcommon chipid */ -#define BCM43349_CHIP_ID 43349 /* 43349(0xA955) chipcommon chipid */ #define BCM4360_CHIP_ID 0x4360 /* 4360 chipcommon chipid */ #define BCM4364_CHIP_ID 0x4364 /* 4364 chipcommon chipid */ #define BCM4352_CHIP_ID 0x4352 /* 4352 chipcommon chipid */ #define BCM43526_CHIP_ID 0xAA06 -#define BCM43340_CHIP_ID 43340 /* 43340 chipcommon chipid */ -#define BCM43341_CHIP_ID 43341 /* 43341 chipcommon chipid */ -#define BCM43342_CHIP_ID 43342 /* 43342 chipcommon chipid */ #define BCM4350_CHIP_ID 0x4350 /* 4350 chipcommon chipid */ #define BCM4354_CHIP_ID 0x4354 /* 4354 chipcommon chipid */ #define BCM4356_CHIP_ID 0x4356 /* 4356 chipcommon chipid */ @@ -456,6 +446,7 @@ #define BCM43570_CHIP_ID 0xAA32 /* 43570 chipcommon chipid */ #define BCM4358_CHIP_ID 0x4358 /* 4358 chipcommon chipid */ #define BCM43012_CHIP_ID 0xA804 /* 43012 chipcommon chipid */ + #define BCM4350_CHIP(chipid) ((CHIPID(chipid) == BCM4350_CHIP_ID) || \ (CHIPID(chipid) == BCM4354_CHIP_ID) || \ (CHIPID(chipid) == BCM43556_CHIP_ID) || \ @@ -493,13 +484,18 @@ #define BCM4349_CHIP(chipid) ((CHIPID(chipid) == BCM4349_CHIP_ID) || \ (CHIPID(chipid) == BCM4355_CHIP_ID) || \ (CHIPID(chipid) == BCM4359_CHIP_ID)) + +#define BCM4355_CHIP(chipid) (CHIPID(chipid) == BCM4355_CHIP_ID) + #define BCM4349_CHIP_GRPID BCM4349_CHIP_ID: \ case BCM4355_CHIP_ID: \ case BCM4359_CHIP_ID #define BCM43596_CHIP_ID 43596 /* 43596 chipcommon chipid */ + #define BCM4347_CHIP_ID 0x4347 /* 4347 chipcommon chipid */ #define BCM4357_CHIP_ID 0x4357 /* 4357 chipcommon chipid */ #define BCM4361_CHIP_ID 0x4361 /* 4361 chipcommon chipid */ + #define BCM4347_CHIP(chipid) ((CHIPID(chipid) == BCM4347_CHIP_ID) || \ (CHIPID(chipid) == BCM4357_CHIP_ID) || \ (CHIPID(chipid) == BCM4361_CHIP_ID)) @@ -509,11 +505,16 @@ #define BCM4365_CHIP_ID 0x4365 /* 4365 chipcommon chipid */ #define BCM4366_CHIP_ID 0x4366 /* 4366 chipcommon chipid */ +#define BCM43664_CHIP_ID 43664 /* 4366E chipcommon chipid */ +#define BCM43666_CHIP_ID 43666 /* 4365E chipcommon chipid */ #define BCM4365_CHIP(chipid) ((CHIPID(chipid) == BCM4365_CHIP_ID) || \ - (CHIPID(chipid) == BCM4366_CHIP_ID)) - - -#define BCM43909_CHIP_ID 0xab85 /* 43909 chipcommon chipid */ + (CHIPID(chipid) == BCM4366_CHIP_ID) || \ + (CHIPID(chipid) == BCM43664_CHIP_ID) || \ + (CHIPID(chipid) == BCM43666_CHIP_ID)) +#define CASE_BCM4365_CHIP case BCM4365_CHIP_ID: /* fallthrough */ \ + case BCM4366_CHIP_ID: /* fallthrough */ \ + case BCM43664_CHIP_ID: /* fallthrough */ \ + case BCM43666_CHIP_ID #define BCM43602_CHIP_ID 0xaa52 /* 43602 chipcommon chipid */ #define BCM43462_CHIP_ID 0xa9c6 /* 43462 chipcommon chipid */ @@ -528,7 +529,6 @@ #define BCM4402_CHIP_ID 0x4402 /* 4402 chipid */ #define BCM4704_CHIP_ID 0x4704 /* 4704 chipcommon chipid */ -#define BCM4706_CHIP_ID 0x5300 /* 4706 chipcommon chipid */ #define BCM4707_CHIP_ID 53010 /* 4707 chipcommon chipid */ #define BCM47094_CHIP_ID 53030 /* 47094 chipcommon chipid */ #define BCM53018_CHIP_ID 53018 /* 53018 chipcommon chipid */ @@ -536,20 +536,18 @@ ((chipid) == BCM53018_CHIP_ID) || \ ((chipid) == BCM47094_CHIP_ID)) #define BCM4710_CHIP_ID 0x4710 /* 4710 chipid */ -#define BCM4749_CHIP_ID 0x4749 /* 5357 chipcommon chipid (OTP, RBBU) */ #define BCM4785_CHIP_ID 0x4785 /* 4785 chipcommon chipid */ #define BCM5350_CHIP_ID 0x5350 /* 5350 chipcommon chipid */ #define BCM5352_CHIP_ID 0x5352 /* 5352 chipcommon chipid */ #define BCM5365_CHIP_ID 0x5365 /* 5365 chipcommon chipid */ -#define BCM5356_CHIP_ID 0x5356 /* 5356 chipcommon chipid */ -#define BCM5357_CHIP_ID 0x5357 /* 5357 chipcommon chipid */ -#define BCM53572_CHIP_ID 53572 /* 53572 chipcommon chipid */ #define BCM53573_CHIP_ID 53573 /* 53573 chipcommon chipid */ #define BCM53574_CHIP_ID 53574 /* 53574 chipcommon chipid */ #define BCM53573_CHIP(chipid) ((CHIPID(chipid) == BCM53573_CHIP_ID) || \ - (CHIPID(chipid) == BCM53574_CHIP_ID)) + (CHIPID(chipid) == BCM53574_CHIP_ID) || \ + (CHIPID(chipid) == BCM47452_CHIP_ID)) #define BCM53573_CHIP_GRPID BCM53573_CHIP_ID : \ - case BCM53574_CHIP_ID + case BCM53574_CHIP_ID : \ + case BCM47452_CHIP_ID #define BCM53573_DEVICE(devid) (((devid) == BCM53573_D11AC_ID) || \ ((devid) == BCM53573_D11AC2G_ID) || \ ((devid) == BCM53573_D11AC5G_ID) || \ @@ -558,6 +556,8 @@ ((devid) == BCM47189_D11AC5G_ID)) #define BCM7271_CHIP_ID 0x05c9 /* 7271 chipcommon chipid */ +#define BCM7271_CHIP(chipid) ((CHIPID(chipid) == BCM7271_CHIP_ID)) + #define BCM4373_CHIP_ID 0x4373 /* 4373 chipcommon chipid */ /* Package IDs */ @@ -577,38 +577,16 @@ #define BCM4716_PKG_ID 8 /* 4716 package id */ #define BCM4717_PKG_ID 9 /* 4717 package id */ #define BCM4718_PKG_ID 10 /* 4718 package id */ -#endif /* DEPRECATED */ -#define BCM5356_PKG_NONMODE 1 /* 5356 package without nmode suppport */ -#define BCM5358U_PKG_ID 8 /* 5358U package id */ -#define BCM5358_PKG_ID 9 /* 5358 package id */ -#define BCM47186_PKG_ID 10 /* 47186 package id */ -#define BCM5357_PKG_ID 11 /* 5357 package id */ -#define BCM5356U_PKG_ID 12 /* 5356U package id */ -#define BCM53572_PKG_ID 8 /* 53572 package id */ -#define BCM5357C0_PKG_ID 8 /* 5357c0 package id (the same as 53572) */ -#define BCM47188_PKG_ID 9 /* 47188 package id */ -#define BCM5358C0_PKG_ID 0xa /* 5358c0 package id */ -#define BCM5356C0_PKG_ID 0xb /* 5356c0 package id */ #define BCM4331TT_PKG_ID 8 /* 4331 12x12 package id */ #define BCM4331TN_PKG_ID 9 /* 4331 12x9 package id */ #define BCM4331TNA0_PKG_ID 0xb /* 4331 12x9 package id */ +#endif /* DEPRECATED */ #define BCM47189_PKG_ID 1 /* 47189 package id */ #define BCM53573_PKG_ID 0 /* 53573 package id */ -#define BCM4706L_PKG_ID 1 /* 4706L package id */ #define HDLSIM5350_PKG_ID 1 /* HDL simulator package id for a 5350 */ #define HDLSIM_PKG_ID 14 /* HDL simulator package id */ #define HWSIM_PKG_ID 15 /* Hardware simulator package id */ -#define BCM43224_FAB_CSM 0x8 /* the chip is manufactured by CSM */ -#define BCM43224_FAB_SMIC 0xa /* the chip is manufactured by SMIC */ -#define BCM4336_WLBGA_PKG_ID 0x8 -#define BCM4330_WLBGA_PKG_ID 0x0 -#define BCM4314PCIE_ARM_PKG_ID (8 | 0) /* 4314 QFN PCI package id, bit 3 tie high */ -#define BCM4314SDIO_PKG_ID (8 | 1) /* 4314 QFN SDIO package id */ -#define BCM4314PCIE_PKG_ID (8 | 2) /* 4314 QFN PCI (ARM-less) package id */ -#define BCM4314SDIO_ARM_PKG_ID (8 | 3) /* 4314 QFN SDIO (ARM-less) package id */ -#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) /* 4314 FpBGA SDIO package id */ -#define BCM4314DEV_PKG_ID (8 | 6) /* 4314 Developement package id */ #define BCM4707_PKG_ID 1 /* 4707 package id */ #define BCM4708_PKG_ID 2 /* 4708 package id */ @@ -674,6 +652,7 @@ #define BFL2_5G_PWRGAIN 0x00000010 /* Board supports 5G band power gain */ #define BFL2_PCIEWAR_OVR 0x00000020 /* Board overrides ASPM and Clkreq settings */ #define BFL2_CAESERS_BRD 0x00000040 /* Board is Caesers brd (unused by sw) */ +#define BFL2_WLCX_ATLAS 0x00000040 /* Board flag to initialize ECI for WLCX on FL-ATLAS */ #define BFL2_BTC3WIRE 0x00000080 /* Board support legacy 3 wire or 4 wire */ #define BFL2_BTCLEGACY 0x00000080 /* Board support legacy 3/4 wire, to replace * BFL2_BTC3WIRE @@ -708,10 +687,6 @@ #define BFL2_PWR_NOMINAL 0x04000000 /* 0: power reduction on, 1: no power reduction */ #define BFL2_EXTLNA_PWRSAVE 0x08000000 /* boardflag to enable ucode to apply power save */ /* ucode control of eLNA during Tx */ -#define BFL2_4313_RADIOREG 0x10000000 - /* board rework */ -#define BFL2_DYNAMIC_VMID 0x10000000 /* enable dynamic Vmid in idle TSSI CAL for 4331 */ - #define BFL2_SDR_EN 0x20000000 /* SDR enabled or disabled */ #define BFL2_DYNAMIC_VMID 0x10000000 /* boardflag to enable dynamic Vmid idle TSSI CAL */ #define BFL2_LNA1BYPFORTR2G 0x40000000 /* acphy, enable lna1 bypass for clip gain, 2g */ @@ -780,13 +755,18 @@ #define BFL3_AVVMID_FROM_NVRAM_SHIFT 30 /* Read Av Vmid from NVRAM */ #define BFL3_VLIN_EN_FROM_NVRAM_SHIFT 31 /* Enable Vlin from NVRAM */ -/* boardflags4 for SROM12 */ +/* boardflags4 for SROM12/SROM13 */ #define BFL4_SROM12_4dBPAD (1 << 0) /* To distinguigh between normal and 4dB pad board */ #define BFL4_SROM12_2G_DETTYPE (1 << 1) /* Determine power detector type for 2G */ #define BFL4_SROM12_5G_DETTYPE (1 << 2) /* Determine power detector type for 5G */ +#define BFL4_SROM13_DETTYPE_EN (1 << 3) /* using pa_dettype from SROM13 flags */ +#define BFL4_SROM13_CCK_SPUR_EN (1 << 4) /* using cck spur reduction setting in 4366 */ +#define BFL4_SROM13_1P5V_CBUCK (1 << 7) /* using 1.5V cbuck board in 4366 */ +#define BFL4_SROM13_EN_SW_TXRXCHAIN_MASK (1 << 8) /* Enable/disable bit for sw chain mask */ + #define BFL4_4364_HARPOON 0x0100 /* Harpoon module 4364 */ #define BFL4_4364_GODZILLA 0x0200 /* Godzilla module 4364 */ - +#define BFL4_BTCOEX_OVER_SECI 0x00000400 /* Enable btcoex over gci seci */ /* papd params */ #define PAPD_TX_ATTN_2G 0xFF @@ -811,7 +791,6 @@ #define PAPD_CALREF_DB_5G 0xFF00 #define PAPD_CALREF_DB_5G_SHIFT 8 - /* board specific GPIO assignment, gpio 0-3 are also customer-configurable led */ #define BOARD_GPIO_BTC3W_IN 0x850 /* bit 4 is RF_ACTIVE, bit 6 is STATUS, bit 11 is PRI */ #define BOARD_GPIO_BTC3W_OUT 0x020 /* bit 5 is TX_CONF */ @@ -833,12 +812,6 @@ #define BOARD_GPIO_13_WLAN_PWR 0x2000 /* throttle WLAN power on X14 board */ #define GPIO_BTC4W_OUT_4312 0x010 /* bit 4 is BT_IODISABLE */ -#define GPIO_BTC4W_OUT_43224 0x020 /* bit 5 is BT_IODISABLE */ -#define GPIO_BTC4W_OUT_43224_SHARED 0x0e0 /* bit 5 is BT_IODISABLE */ -#define GPIO_BTC4W_OUT_43225 0x0e0 /* bit 5 BT_IODISABLE, bit 6 SW_BT, bit 7 SW_WL */ -#define GPIO_BTC4W_OUT_43421 0x020 /* bit 5 is BT_IODISABLE */ -#define GPIO_BTC4W_OUT_4313 0x060 /* bit 5 SW_BT, bit 6 SW_WL */ -#define GPIO_BTC4W_OUT_4331_SHARED 0x010 /* GPIO 4 */ #define PCI_CFG_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ #define PCI_CFG_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ @@ -851,13 +824,6 @@ #define MIN_SLOW_CLK 32 /* us Slow clock period */ #define XTAL_ON_DELAY 1000 /* us crystal power-on delay */ - -/* 43341 Boards */ -#define BCM943341WLABGS_SSID 0x062d - -/* 43342 Boards */ -#define BCM943342FCAGBI_SSID 0x0641 - /* 43012 wlbga Board */ #define BCM943012WLREF_SSID 0x07d7 @@ -894,8 +860,6 @@ #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 RDL_RAM_SIZE_4350 0xC0000 diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmendian.h b/drivers/net/wireless/bcmdhd_oo/include/bcmendian.h index 00adedf1cd978cf34e83b6fecb52c7fcfeec598c..c9a95ae42d4f23a05161e465782b15afc7cd4e05 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmendian.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmendian.h @@ -1,14 +1,14 @@ /* * Byte order utilities * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmendian.h 514727 2014-11-12 03:02:48Z $ + * $Id: bcmendian.h 633810 2016-04-25 16:46:55Z $ * * This file by default provides proper behavior on little-endian architectures. * On big-endian architectures, IL_BIGENDIAN should be defined. @@ -68,7 +68,6 @@ ((uint64)((((uint64)(val) & 0x00000000ffffffffULL) << 32) | \ (((uint64)(val) & 0xffffffff00000000ULL) >> 32))) - /* Byte swapping macros * Host <=> Network (Big Endian) for 16- and 32-bit values * Host <=> Little-Endian for 16- and 32-bit values @@ -96,18 +95,34 @@ #define ltoh16_buf(buf, i) #define htol16_buf(buf, i) +#define ltoh32_buf(buf, i) +#define htol32_buf(buf, i) +#define ltoh64_buf(buf, i) +#define htol64_buf(buf, i) /* Unaligned loads and stores in host byte order */ #define load32_ua(a) ltoh32_ua(a) #define store32_ua(a, v) htol32_ua_store(v, a) #define load16_ua(a) ltoh16_ua(a) #define store16_ua(a, v) htol16_ua_store(v, a) +#define load64_ua(a) ltoh64_ua(a) +#define store64_ua(a, v) htol64_ua_store(v, a) #define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) #define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) #define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) #define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) +#define _LTOH64_UA(cp) ((uint64)(cp)[0] | ((uint64)(cp)[1] << 8) | \ + ((uint64)(cp)[2] << 16) | ((uint64)(cp)[3] << 24) | \ + ((uint64)(cp)[4] << 32) | ((uint64)(cp)[5] << 40) | \ + ((uint64)(cp)[6] << 48) | ((uint64)(cp)[7] << 56)) + +#define _NTOH64_UA(cp) ((uint64)(cp)[7] | ((uint64)(cp)[6] << 8) | \ + ((uint64)(cp)[5] << 16) | ((uint64)(cp)[4] << 24) | \ + ((uint64)(cp)[3] << 32) | ((uint64)(cp)[2] << 40) | \ + ((uint64)(cp)[1] << 48) | ((uint64)(cp)[0] << 56)) + #define ltoh_ua(ptr) \ (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)(ptr) : \ sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)(ptr)) : \ @@ -155,6 +170,24 @@ } \ }) +#define bcmswap32_buf(buf, len) ({ \ + uint32 *_buf = (uint32 *)(buf); \ + uint _wds = (len) / 4; \ + while (_wds--) { \ + *_buf = bcmswap32(*_buf); \ + _buf++; \ + } \ +}) + +#define bcmswap64_buf(buf, len) ({ \ + uint64 *_buf = (uint64 *)(buf); \ + uint _wds = (len) / 8; \ + while (_wds--) { \ + *_buf = bcmswap64(*_buf); \ + _buf++; \ + } \ +}) + #define htol16_ua_store(val, bytes) ({ \ uint16 _val = (val); \ uint8 *_bytes = (uint8 *)(bytes); \ @@ -171,6 +204,16 @@ _bytes[3] = _val >> 24; \ }) +#define htol64_ua_store(val, bytes) ({ \ + uint64 _val = (val); \ + uint8 *_bytes = (uint8 *)(bytes); \ + int i; \ + for (i = 0; i < (int)sizeof(_val); ++i) { \ + *_bytes++ = _val & 0xff; \ + _val >>= 8; \ + } \ +}) + #define hton16_ua_store(val, bytes) ({ \ uint16 _val = (val); \ uint8 *_bytes = (uint8 *)(bytes); \ @@ -197,6 +240,11 @@ _LTOH32_UA(_bytes); \ }) +#define ltoh64_ua(bytes) ({ \ + const uint8 *_bytes = (const uint8 *)(bytes); \ + _LTOH64_UA(_bytes); \ +}) + #define ntoh16_ua(bytes) ({ \ const uint8 *_bytes = (const uint8 *)(bytes); \ _NTOH16_UA(_bytes); \ @@ -207,6 +255,11 @@ _NTOH32_UA(_bytes); \ }) +#define ntoh64_ua(bytes) ({ \ + const uint8 *_bytes = (const uint8 *)(bytes); \ + _NTOH64_UA(_bytes); \ +}) + #else /* !__GNUC__ */ /* Inline versions avoid referencing the argument multiple times */ @@ -270,6 +323,19 @@ htol32_ua_store(uint32 val, uint8 *bytes) bytes[3] = val >> 24; } +/* + * Store 64-bit value to unaligned little-endian byte array. + */ +static INLINE void +htol64_ua_store(uint64 val, uint8 *bytes) +{ + int i; + for (i = 0; i < sizeof(val); ++i) { + *bytes++ = (uint8)(val & 0xff); + val >>= 8; + } +} + /* * Store 16-bit value to unaligned network-(big-)endian byte array. */ @@ -310,6 +376,15 @@ ltoh32_ua(const void *bytes) return _LTOH32_UA((const uint8 *)bytes); } +/* + * Load 64-bit value from unaligned little-endian byte array. + */ +static INLINE uint64 +ltoh64_ua(const void *bytes) +{ + return _LTOH64_UA((const uint8 *)bytes); +} + /* * Load 16-bit value from unaligned big-(network-)endian byte array. */ @@ -328,5 +403,14 @@ ntoh32_ua(const void *bytes) return _NTOH32_UA((const uint8 *)bytes); } +/* + * Load 64-bit value from unaligned big-(network-)endian byte array. + */ +static INLINE uint64 +ntoh64_ua(const void *bytes) +{ + return _NTOH64_UA((const uint8 *)bytes); +} + #endif /* !__GNUC__ */ #endif /* !_BCMENDIAN_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmeth.h b/drivers/net/wireless/bcmdhd_oo/include/bcmeth.h index e1d2d6669e91357ce91f1113b162bac429306fd0..761ea445e6aa2dfbffd2591f4834344a9420acbd 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmeth.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmeth.h @@ -1,14 +1,14 @@ /* * Broadcom Ethernettype protocol definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -36,7 +36,7 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include @@ -83,7 +83,6 @@ #define BCMILCP_SUBTYPE_CERT 32770 #define BCMILCP_SUBTYPE_SES 32771 - #define BCMILCP_BCM_SUBTYPE_RESERVED 0 #define BCMILCP_BCM_SUBTYPE_EVENT 1 #define BCMILCP_BCM_SUBTYPE_SES 2 @@ -110,7 +109,6 @@ typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr uint16 usr_subtype; } BWL_POST_PACKED_STRUCT bcmeth_hdr_t; - /* This marks the end of a packed structure section. */ #include diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmevent.h b/drivers/net/wireless/bcmdhd_oo/include/bcmevent.h index 0595028c7033dd38c9e3c8da1edb0ee70740b41b..cd76e65eec8b9b87b41ea08a45d25148305b4173 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmevent.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmevent.h @@ -3,14 +3,14 @@ * * Dependencies: bcmeth.h * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,7 +26,7 @@ * * <> * - * $Id: bcmevent.h 700076 2017-05-17 14:42:22Z $ + * $Id: bcmevent.h 738226 2017-12-27 18:10:00Z $ * */ @@ -43,7 +43,7 @@ #include #if defined(DNGL_EVENT_SUPPORT) #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include @@ -106,7 +106,7 @@ typedef union bcm_event_msg_u { wl_event_msg_t event; #if defined(DNGL_EVENT_SUPPORT) bcm_dngl_event_msg_t dngl_event; -#endif +#endif // endif /* add new event here */ } bcm_event_msg_u_t; @@ -284,9 +284,13 @@ typedef union bcm_event_msg_u { #define WLC_E_PFN_BSSID_SCAN_BACKOFF 168 /* PFN BSSID SCAN BAckoff event */ #define WLC_E_AGGR_EVENT 169 /* Aggregated event */ #define WLC_E_TVPM_MITIGATION 171 /* Change in mitigation applied by TVPM */ -#define WLC_E_LAST 172 /* highest val + 1 for range checking */ -#if (WLC_E_LAST > 172) -#error "WLC_E_LAST: Invalid value for last event; must be <= 172." +#define WLC_E_SCAN_START 172 /* Deprecated */ +#define WLC_E_SCAN 172 /* Scan event */ +#define WLC_E_MBO 173 /* MBO event */ +#define WLC_E_PHY_CAL 174 /* Phy calibration start indication to host */ +#define WLC_E_LAST 175 /* highest val + 1 for range checking */ +#if (WLC_E_LAST > 175) +#error "WLC_E_LAST: Invalid value for last event; must be <= 175." #endif /* WLC_E_LAST */ /* define an API for getting the string name of an event */ @@ -302,7 +306,6 @@ extern int is_wlc_event_frame(void *pktdata, uint pktlen, uint16 exp_usr_subtype void wl_event_to_host_order(wl_event_msg_t * evt); void wl_event_to_network_order(wl_event_msg_t * evt); - /* Event status codes */ #define WLC_E_STATUS_SUCCESS 0 /* operation was successful */ #define WLC_E_STATUS_FAIL 1 /* operation failed */ @@ -346,7 +349,6 @@ void wl_event_to_network_order(wl_event_msg_t * evt); #define WLC_E_STATUS_SLICE_SWAP_START 3 #define WLC_E_STATUS_SLICE_SWAP_COMPLETE 4 - /* SDB transition reason code */ #define WLC_E_REASON_HOST_DIRECT 0 #define WLC_E_REASON_INFRA_ASSOC 1 @@ -441,7 +443,6 @@ typedef struct wl_event_sdb_trans { #define WLC_E_SUP_WPA_PSK_M1_TMO 16 /* WPA PSK 4-way handshake M1 timeout */ #define WLC_E_SUP_WPA_PSK_M3_TMO 17 /* WPA PSK 4-way handshake M3 timeout */ - /* Ucode reason codes carried in the WLC_E_MACDBG event */ #define WLC_E_MACDBG_LIST_PSM 0 /* Dump list update for PSM registers */ #define WLC_E_MACDBG_LIST_PSMX 1 /* Dump list update for PSMx registers */ @@ -452,15 +453,36 @@ typedef struct wl_event_sdb_trans { * WLC_E_P2P_PROBREQ_MSG * WLC_E_ACTION_FRAME_RX */ -typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data { + +#define MAX_PHY_CORE_NUM 4u + +#define BCM_RX_FRAME_DATA_VERSION_2 2u + +typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data_v2 { + uint16 version; + uint16 len; + uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ + uint16 pad; + int32 rssi; + uint32 mactime; + uint32 rate; + int8 per_core_rssi[MAX_PHY_CORE_NUM]; +} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_v2_t; + +typedef BWL_PRE_PACKED_STRUCT struct wl_event_rx_frame_data_v1 { uint16 version; uint16 channel; /* Matches chanspec_t format from bcmwifi_channels.h */ int32 rssi; uint32 mactime; uint32 rate; -} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_t; +} BWL_POST_PACKED_STRUCT wl_event_rx_frame_data_v1_t; -#define BCM_RX_FRAME_DATA_VERSION 1 +#define BCM_RX_FRAME_DATA_VERSION_1 1u + +#ifndef WL_EVENT_RX_FRAME_DATA_ALIAS +#define BCM_RX_FRAME_DATA_VERSION BCM_RX_FRAME_DATA_VERSION_1 +typedef wl_event_rx_frame_data_v1_t wl_event_rx_frame_data_t; +#endif // endif /* WLC_E_IF event data */ typedef struct wl_event_data_if { @@ -509,7 +531,6 @@ typedef struct wl_event_data_rssi { #define WLC_E_LINK_ASSOC_REC 3 /* Link down because assoc recreate failed */ #define WLC_E_LINK_BSSCFG_DIS 4 /* Link down due to bsscfg down */ - /* WLC_E_NDIS_LINK event data */ typedef BWL_PRE_PACKED_STRUCT struct ndis_link_parms { struct ether_addr peer_mac; /* 6 bytes */ @@ -548,11 +569,22 @@ typedef BWL_PRE_PACKED_STRUCT struct ndis_link_parms { #define WLAN_TDLS_SET_SETUP_WFD_IE 12 #define WLAN_TDLS_SET_WFD_ENABLED 13 #define WLAN_TDLS_SET_WFD_DISABLED 14 -#endif +#endif // endif /* WLC_E_RANGING_EVENT subtypes */ #define WLC_E_RANGING_RESULTS 0 +#define PHY_CAL_EVT_VERSION 1 +typedef struct wlc_phy_cal_info { + uint16 version; /* structure version */ + uint16 length; /* length of the rest of the structure - pad */ + uint16 chanspec; + uint8 start; + uint8 phase; + int16 temp; + uint8 reason; + uint8 pad; +} wlc_phy_cal_info_t; /* GAS event data */ typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas { @@ -651,7 +683,6 @@ typedef BWL_PRE_PACKED_STRUCT struct proxd_event_ts_results { ts_sample_t ts_buff[1]; /* Timestamps */ } BWL_POST_PACKED_STRUCT wl_proxd_event_ts_results_t; - /* Video Traffic Interference Monitor Event */ #define INTFER_EVENT_VERSION 1 #define INTFER_STREAM_TYPE_NONTCP 1 @@ -672,7 +703,6 @@ typedef struct wl_rrm_event { char payload[1]; /* Measurement payload */ } wl_rrm_event_t; - /* WLC_E_PSTA_PRIMARY_INTF_IND event data */ typedef struct wl_psta_primary_intf_event { struct ether_addr prim_ea; /* primary intf ether addr */ @@ -689,7 +719,9 @@ typedef struct wl_dpsta_intf_event { } wl_dpsta_intf_event_t; /* ********** NAN protocol events/subevents ********** */ +#ifndef NAN_EVENT_BUFFER_SIZE #define NAN_EVENT_BUFFER_SIZE 512 /* max size */ +#endif /* NAN_EVENT_BUFFER_SIZE */ /* NAN Events sent by firmware */ /* @@ -716,16 +748,10 @@ typedef enum wl_nan_events { WL_NAN_EVENT_DATA_IF_ADD = 18, /* Unused */ WL_NAN_EVENT_DATA_PEER_ADD = 19, /* Event for peer add */ /* nan 2.0 */ - /* Will be removed after source code is committed. */ - WL_NAN_EVENT_DATA_IND = 20, WL_NAN_EVENT_PEER_DATAPATH_IND = 20, /* Incoming DP req */ - /* Will be removed after source code is committed. */ - WL_NAN_EVENT_DATA_CONF = 21, WL_NAN_EVENT_DATAPATH_ESTB = 21, /* DP Established */ WL_NAN_EVENT_SDF_RX = 22, /* SDF payload */ WL_NAN_EVENT_DATAPATH_END = 23, /* DP Terminate recvd */ - /* Below event needs to be removed after source code is committed. */ - WL_NAN_EVENT_DATA_END = 23, WL_NAN_EVENT_BCN_RX = 24, /* received beacon payload */ WL_NAN_EVENT_PEER_DATAPATH_RESP = 25, /* Peer's DP response */ WL_NAN_EVENT_PEER_DATAPATH_CONF = 26, /* Peer's DP confirm */ @@ -734,14 +760,40 @@ typedef enum wl_nan_events { WL_NAN_EVENT_RNG_TERM_IND = 29, /* Range Termination */ WL_NAN_EVENT_PEER_DATAPATH_SEC_INST = 30, /* Peer's DP sec install */ WL_NAN_EVENT_TXS = 31, /* for tx status of follow-up and SDFs */ + WL_NAN_EVENT_DW_START = 32, /* dw start */ + WL_NAN_EVENT_DW_END = 33, /* dw end */ + WL_NAN_EVENT_CHAN_BOUNDARY = 34, /* channel switch event */ + WL_NAN_EVENT_MR_CHANGED = 35, /* AMR or IMR changed event during DW */ + WL_NAN_EVENT_RNG_RESP_IND = 36, /* Range Response Rx */ + WL_NAN_EVENT_PEER_SCHED_UPD_NOTIF = 37, /* Peer's schedule update notification */ + WL_NAN_EVENT_PEER_SCHED_REQ = 38, /* Peer's schedule request */ + WL_NAN_EVENT_PEER_SCHED_RESP = 39, /* Peer's schedule response */ + WL_NAN_EVENT_PEER_SCHED_CONF = 40, /* Peer's schedule confirm */ + WL_NAN_EVENT_SENT_DATAPATH_END = 41, /* Sent DP terminate frame */ + WL_NAN_EVENT_SLOT_START = 42, /* SLOT_START event */ + WL_NAN_EVENT_SLOT_END = 43, /* SLOT_END event */ + WL_NAN_EVENT_HOST_ASSIST_REQ = 44, /* Requesting host assist */ + WL_NAN_EVENT_INVALID /* delimiter for max value */ } nan_app_events_e; -#define NAN_EV_MASK(ev) \ - (1 << (ev - 1)) +#define NAN_EV_MASK(ev) (1 << (ev - 1)) #define IS_NAN_EVT_ON(var, evt) ((var & (1 << (evt-1))) != 0) + +#define NAN_EV_MASK_SET(var, evt) \ + ((evt < WL_NAN_EVMASK_EXTN_LEN * 8) ? \ + ((*((uint8 *)var + ((evt - 1)/8))) |= (1 << ((evt - 1) %8))) : 0) +#define IS_NAN_EVENT_ON(var, evt) \ + ((evt < WL_NAN_EVMASK_EXTN_LEN * 8) && \ + (((*((uint8 *)var + ((evt - 1)/8))) & (1 << ((evt - 1) %8))) != 0)) + /* ******************* end of NAN section *************** */ +typedef enum wl_scan_events { + WL_SCAN_START = 1, + WL_SCAN_END = 2 +} wl_scan_events; + /* WLC_E_ULP event data */ #define WL_ULP_EVENT_VERSION 1 #define WL_ULP_DISABLE_CONSOLE 1 /* Disable console message on ULP entry */ @@ -774,7 +826,6 @@ typedef struct wl_event_radar_detect_data { radar_detected_event_info_t radar_info[2]; } wl_event_radar_detect_data_t; - #define WL_EVENT_MODESW_VER_1 1 #define WL_EVENT_MODESW_VER_CURRENT WL_EVENT_MODESW_VER_1 @@ -923,7 +974,10 @@ typedef enum { CHANSW_AWDL_OOB_AF = 25, /* channel switch due to AWDL OOB action frame */ CHANSW_TDLS = 26, /* channel switch due to TDLS */ CHANSW_PROXD = 27, /* channel switch due to PROXD */ - CHANSW_MAX_NUMBER = 28 /* max channel switch reason */ + CHANSW_SLOTTED_BSS = 28, /* channel switch due to slotted bss */ + CHANSW_SLOTTED_CMN_SYNC = 29, /* channel switch due to Common Sync Layer */ + CHANSW_SLOTTED_BSS_CAL = 30, /* channel switch due to Cal request from slotted bss */ + CHANSW_MAX_NUMBER = 31 /* max channel switch reason */ } wl_chansw_reason_t; #define CHANSW_REASON(reason) (1 << reason) @@ -939,7 +993,6 @@ typedef struct event_aggr_data { uint8 data[]; /* Aggregate buffer containing Events */ } event_aggr_data_t; - /* WLC_E_TVPM_MITIGATION event structure version */ #define WL_TVPM_MITIGATION_VERSION 1 @@ -958,4 +1011,93 @@ typedef struct wl_event_tvpm_mitigation { uint16 on_off; /* mitigation status bits */ } wl_event_tvpm_mitigation_t; +/* Event structures for sub health checks of PHY */ + +#define WL_PHY_HC_DESENSE_STATS_VER (1) +typedef struct wl_hc_desense_stats { + uint16 version; + uint16 chanspec; + int8 allowed_weakest_rssi; /* based on weakest link RSSI */ + uint8 ofdm_desense; /* Desense requested for OFDM */ + uint8 bphy_desense; /* Desense requested for bphy */ + int8 glitch_upd_wait; /* wait post ACI mitigation */ +} wl_hc_desense_stats_v1_t; + +#define WL_PHY_HC_TEMP_STATS_VER (1) +typedef struct wl_hc_temp_stats { + uint16 version; + uint16 chanspec; + int16 curtemp; /* Temperature */ + uint8 temp_disthresh; /* Threshold to reduce tx chain */ + uint8 temp_enthresh; /* Threshold to increase tx chains */ + uint tempsense_period; /* Temperature check period */ + bool heatedup; /* 1: temp throttling on */ + uint8 bitmap; /* Indicating rx and tx chains */ + uint8 pad[2]; +} wl_hc_temp_stats_v1_t; + +#define WL_PHY_HC_VCOCAL_STATS_VER (1) +typedef struct wl_hc_vcocal_stats { + uint16 version; + uint16 chanspec; + int16 curtemp; /* Temperature */ + /* Ring buffer - Maintains history of previous 16 wake/sleep cycles */ + uint16 vcocal_status_wake; + uint16 vcocal_status_sleep; + uint16 plllock_status_wake; + uint16 plllock_status_sleep; + /* Cal Codes */ + uint16 cc_maincap; + uint16 cc_secondcap; + uint16 cc_auxcap; +} wl_hc_vcocal_stats_v1_t; + +#define WL_PHY_HC_TXPWR_STATS_VER (1) +typedef struct wl_hc_tx_stats { + uint16 version; + uint16 chanspec; + int8 tgt_pwr[MAX_PHY_CORE_NUM]; /* Target pwr (qdBm) */ + int8 estPwr[MAX_PHY_CORE_NUM]; /* Rate corrected (qdBm) */ + int8 estPwr_adj[MAX_PHY_CORE_NUM]; /* Max power (qdBm) */ + uint8 baseindex[MAX_PHY_CORE_NUM]; /* Tx base index */ + int16 temp; /* Temperature */ + uint16 TxCtrlWrd[3]; /* 6 PHY ctrl bytes */ + int8 min_txpower; /* min tx power per ant */ + uint8 pad[3]; +} wl_hc_txpwr_stats_v1_t; + +typedef enum wl_mbo_event_type { + WL_MBO_E_CELLULAR_NW_SWITCH = 1, + /* ADD before this */ + WL_MBO_E_LAST = 2, /* highest val + 1 for range checking */ +} wl_mbo_event_type_t; + +/* WLC_E_MBO event structure version */ +#define WL_MBO_EVT_VER 1 + +struct wl_event_mbo { + uint16 version; /* structure version */ + uint16 length; /* length of the rest of the structure from type */ + wl_mbo_event_type_t type; /* Event type */ + uint8 data[]; /* Variable length data */ +}; + +/* WLC_E_MBO_CELLULAR_NW_SWITCH event structure version */ +#define WL_MBO_CELLULAR_NW_SWITCH_VER 1 + +/* WLC_E_MBO_CELLULAR_NW_SWITCH event data */ +struct wl_event_mbo_cell_nw_switch { + uint16 version; /* structure version */ + uint16 length; /* length of the rest of the structure from reason */ + /* Reason of switch as per MBO Tech spec */ + uint8 reason; + /* pad */ + uint8 pad; + /* delay after which re-association can be tried to current BSS (seconds) */ + uint16 reassoc_delay; + /* How long current association will be there (milli seconds). + * This is zero if not known or value is overflowing. + */ + uint32 assoc_time_remain; +}; #endif /* _BCMEVENT_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmiov.h b/drivers/net/wireless/bcmdhd_oo/include/bcmiov.h new file mode 100644 index 0000000000000000000000000000000000000000..585914de0bb32809bdad3fa6db1297c3ad1a4b34 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmiov.h @@ -0,0 +1,356 @@ +/* + * bcmiov.h + * Common iovar handling/parsing support - batching, parsing, sub-cmd dispatch etc. + * To be used in firmware and host apps or dhd - reducing code size, + * duplication, and maintenance overhead. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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$ + */ + +#ifndef _bcmiov_h_ +#define _bcmiov_h_ + +#include +#include +#include +#ifdef BCMDRIVER +#include +#else +#include /* For size_t */ +#endif /* BCMDRIVER */ + +/* Forward declarations */ +typedef uint16 bcm_iov_cmd_id_t; +typedef uint16 bcm_iov_cmd_flags_t; +typedef uint16 bcm_iov_cmd_mflags_t; +typedef struct bcm_iov_cmd_info bcm_iov_cmd_info_t; +typedef struct bcm_iov_cmd_digest bcm_iov_cmd_digest_t; +typedef struct bcm_iov_cmd_tlv_info bcm_iov_cmd_tlv_info_t; +typedef struct bcm_iov_buf bcm_iov_buf_t; +typedef struct bcm_iov_batch_buf bcm_iov_batch_buf_t; +typedef struct bcm_iov_parse_context bcm_iov_parse_context_t; +typedef struct bcm_iov_sub_cmd_context bcm_iov_sub_cmd_context_t; + +typedef void* (*bcm_iov_malloc_t)(void* alloc_ctx, size_t len); +typedef void (*bcm_iov_free_t)(void* alloc_ctx, void *buf, size_t len); + +typedef uint8 bcm_iov_tlp_data_type_t; +typedef struct bcm_iov_tlp bcm_iov_tlp_t; +typedef struct bcm_iov_tlp_node bcm_iov_tlp_node_t; +typedef struct bcm_iov_batch_subcmd bcm_iov_batch_subcmd_t; + +/* + * iov validation handler - All the common checks that are required + * for processing of iovars for any given command. + */ +typedef int (*bcm_iov_cmd_validate_t)(const bcm_iov_cmd_digest_t *dig, + uint32 actionid, const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); + +/* iov get handler - process subcommand specific input and return output. + * input and output may overlap, so the callee needs to check if + * that is supported. For xtlv data a tlv digest is provided to make + * parsing simpler. Output tlvs may be packed into output buffer using + * bcm xtlv support. olen is input/output parameter. On input contains + * max available obuf length and callee must fill the correct length + * to represent the length of output returned. + */ +typedef int (*bcm_iov_cmd_get_t)(const bcm_iov_cmd_digest_t *dig, + const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); + +/* iov set handler - process subcommand specific input and return output + * input and output may overlap, so the callee needs to check if + * that is supported. olen is input/output parameter. On input contains + * max available obuf length and callee must fill the correct length + * to represent the length of output returned. + */ +typedef int (*bcm_iov_cmd_set_t)(const bcm_iov_cmd_digest_t *dig, + const uint8* ibuf, size_t ilen, uint8 *obuf, size_t *olen); + +/* iov (sub-cmd) batch - a vector of commands. count can be zero + * to support a version query. Each command is a tlv - whose data + * portion may have an optional return status, followed by a fixed + * length data header, optionally followed by tlvs. + * cmd = type|length|[header][tlvs] + */ + +/* + * Batch sub-commands have status length included in the + * response length packed in TLV. + */ +#define BCM_IOV_STATUS_LEN sizeof(uint32) + +/* batch version is indicated by setting high bit. */ +#define BCM_IOV_BATCH_MASK 0x8000 + +/* + * Batched commands will have the following memory layout + * +--------+---------+--------+-------+ + * |version |count | is_set |sub-cmd| + * +--------+---------+--------+-------+ + * version >= 0x8000 + * count = number of sub-commands encoded in the iov buf + * sub-cmd one or more sub-commands for processing + * Where sub-cmd is padded byte buffer with memory layout as follows + * +--------+---------+-----------------------+-------------+------ + * |cmd-id |length |IN(options) OUT(status)|command data |...... + * +--------+---------+-----------------------+-------------+------ + * cmd-id =sub-command ID + * length = length of this sub-command + * IN(options) = On input processing options/flags for this command + * OUT(status) on output processing status for this command + * command data = encapsulated IOVAR data as a single structure or packed TLVs for each + * individual sub-command. + */ +struct bcm_iov_batch_subcmd { + uint16 id; + uint16 len; + union { + uint32 options; + uint32 status; + } u; + uint8 data[1]; +}; + +struct bcm_iov_batch_buf { + uint16 version; + uint8 count; + uint8 is_set; /* to differentiate set or get */ + struct bcm_iov_batch_subcmd cmds[0]; +}; + +/* non-batched command version = major|minor w/ major <= 127 */ +struct bcm_iov_buf { + uint16 version; + uint16 len; + bcm_iov_cmd_id_t id; + uint16 data[1]; /* 32 bit alignment may be repurposed by the command */ + /* command specific data follows */ +}; + +/* iov options flags */ +enum { + BCM_IOV_CMD_OPT_ALIGN_NONE = 0x0000, + BCM_IOV_CMD_OPT_ALIGN32 = 0x0001, + BCM_IOV_CMD_OPT_TERMINATE_SUB_CMDS = 0x0002 +}; + +/* iov command flags */ +enum { + BCM_IOV_CMD_FLAG_NONE = 0, + BCM_IOV_CMD_FLAG_STATUS_PRESENT = (1 << 0), /* status present at data start - output only */ + BCM_IOV_CMD_FLAG_XTLV_DATA = (1 << 1), /* data is a set of xtlvs */ + BCM_IOV_CMD_FLAG_HDR_IN_LEN = (1 << 2), /* length starts at version - non-bacthed only */ + BCM_IOV_CMD_FLAG_NOPAD = (1 << 3) /* No padding needed after iov_buf */ +}; + +/* information about the command, xtlv options and xtlvs_off are meaningful + * only if XTLV_DATA cmd flag is selected + */ +struct bcm_iov_cmd_info { + bcm_iov_cmd_id_t cmd; /* the (sub)command - module specific */ + bcm_iov_cmd_flags_t flags; /* checked by bcmiov but set by module */ + bcm_iov_cmd_mflags_t mflags; /* owned and checked by module */ + bcm_xtlv_opts_t xtlv_opts; + bcm_iov_cmd_validate_t validate_h; /* command validation handler */ + bcm_iov_cmd_get_t get_h; + bcm_iov_cmd_set_t set_h; + uint16 xtlvs_off; /* offset to beginning of xtlvs in cmd data */ + uint16 min_len_set; + uint16 max_len_set; + uint16 min_len_get; + uint16 max_len_get; +}; + +/* tlv digest to support parsing of xtlvs for commands w/ tlv data; the tlv + * digest is available in the handler for the command. The count and order in + * which tlvs appear in the digest are exactly the same as the order of tlvs + * passed in the registration for the command. Unknown tlvs are ignored. + * If registered tlvs are missing datap will be NULL. common iov rocessing + * acquires an input digest to process input buffer. The handler is responsible + * for constructing an output digest and use packing functions to generate + * the output buffer. The handler may use the input digest as output digest once + * the tlv data is extracted and used. Multiple tlv support involves allocation of + * tlp nodes, except the first, as required, + */ + +/* tlp data type indicates if the data is not used/invalid, input or output */ +enum { + BCM_IOV_TLP_NODE_INVALID = 0, + BCM_IOV_TLP_NODE_IN = 1, + BCM_IOV_TLP_NODE_OUT = 2 +}; + +struct bcm_iov_tlp { + uint16 type; + uint16 len; + uint16 nodeix; /* node index */ +}; + +/* tlp data for a given tlv - multiple tlvs of same type chained */ +struct bcm_iov_tlp_node { + uint8 *next; /* multiple tlv support */ + bcm_iov_tlp_data_type_t type; + uint8 *data; /* pointer to data in buffer or state */ +}; + +struct bcm_iov_cmd_digest { + uint32 version; /* Version */ + void *cmd_ctx; + struct wlc_bsscfg *bsscfg; + const bcm_iov_cmd_info_t *cmd_info; + uint16 max_tlps; /* number of tlps allocated */ + uint16 max_nodes; /* number of nods allocated */ + uint16 num_tlps; /* number of tlps valid */ + uint16 num_nodes; /* number of nods valid */ + uint16 tlps_off; /* offset to tlps */ + uint16 nodes_off; /* offset to nodes */ + /* + * bcm_iov_tlp_t tlps[max_tlps]; + * bcm_iov_tlp_node_t nodes[max_nodes] + */ +}; + +/* get length callback - default length is min_len taken from digest */ +typedef size_t (*bcm_iov_xtlv_get_len_t)(const bcm_iov_cmd_digest_t *dig, + const bcm_iov_cmd_tlv_info_t *tlv_info); + +/* pack to buffer data callback. under some conditions it might + * not be a straight copy and can refer to context(ual) information and + * endian conversions... + */ +typedef void (*bcm_iov_xtlv_pack_t)(const bcm_iov_cmd_digest_t *dig, + const bcm_iov_cmd_tlv_info_t *tlv_info, + uint8 *out_buf, const uint8 *in_data, size_t len); + +struct bcm_iov_cmd_tlv_info { + uint16 id; + uint16 min_len; /* inclusive */ + uint16 max_len; /* inclusive */ + bcm_iov_xtlv_get_len_t get_len; + bcm_iov_xtlv_pack_t pack; +}; + +/* + * module private parse context. Default version type len is uint16 + */ +enum { + BCM_IOV_PARSE_CMD_NONE = 0 +}; +typedef uint32 parse_context_opts_t; + +/* get digest callback */ +typedef int (*bcm_iov_get_digest_t)(void *cmd_ctx, bcm_iov_cmd_digest_t **dig); + +typedef struct bcm_iov_parse_config { + parse_context_opts_t options; /* to handle different ver lengths */ + bcm_iov_malloc_t alloc_fn; + bcm_iov_free_t free_fn; + bcm_iov_get_digest_t dig_fn; + int max_regs; + void *alloc_ctx; +} bcm_iov_parse_config_t; + +/* API */ + +/* All calls return an integer status code BCME_* unless otherwise indicated */ + +/* return length of allocation for 'num_cmds' commands. data_len + * includes length of data for all the commands excluding the headers + */ +size_t bcm_iov_get_alloc_len(int num_cmds, size_t data_len); + +/* create parsing context using allocator provided; max_regs provides + * the number of allowed registrations for commands using the context + * sub-components of a module may register their own commands indepdently + * using the parsing context. If digest callback is NULL or returns NULL, + * the (input) digest is allocated using the provided allocators and released on + * completion of processing. + */ +int bcm_iov_create_parse_context(const bcm_iov_parse_config_t *parse_cfg, + bcm_iov_parse_context_t **parse_ctx); + +/* free the parsing context; ctx is set to NULL on exit */ +int bcm_iov_free_parse_context(bcm_iov_parse_context_t **ctx, bcm_iov_free_t free_fn); + +/* Return the command context for the module */ +void *bcm_iov_get_cmd_ctx_info(bcm_iov_parse_context_t *parse_ctx); + +/* register a command info vector along with supported tlvs. Each command + * may support a subset of tlvs + */ +int bcm_iov_register_commands(bcm_iov_parse_context_t *parse_ctx, void *cmd_ctx, + const bcm_iov_cmd_info_t *info, size_t num_cmds, + const bcm_iov_cmd_tlv_info_t *tlv_info, size_t num_tlvs); + +/* pack the xtlvs provided in the digest. may returns BCME_BUFTOOSHORT, but the + * out_len is set to required length in that case. + */ +int bcm_iov_pack_xtlvs(const bcm_iov_cmd_digest_t *dig, bcm_xtlv_opts_t xtlv_opts, + uint8 *out_buf, size_t out_size, size_t *out_len); + +#ifdef BCMDRIVER +/* wlc modules register their iovar(s) using the parsing context w/ wlc layer + * during attach. + */ +struct wlc_if; +struct wlc_info; +extern struct wlc_bsscfg *bcm_iov_bsscfg_find_from_wlcif(struct wlc_info *wlc, + struct wlc_if *wlcif); +int bcm_iov_doiovar(void *parse_ctx, uint32 id, void *params, uint params_len, + void *arg, uint arg_len, uint vsize, struct wlc_if *intf); +#endif /* BCMDRIVER */ + +/* parsing context helpers */ + +/* get the maximum number of tlvs - can be used to allocate digest for all + * commands. the digest can be shared. Negative values are BCM_*, >=0, the + * number of tlvs + */ +int bcm_iov_parse_get_max_tlvs(const bcm_iov_parse_context_t *ctx); + +/* common packing support */ + +/* pack a buffer of uint8s - memcpy wrapper */ +int bcm_iov_pack_buf(const bcm_iov_cmd_digest_t *dig, uint8 *buf, + const uint8 *data, size_t len); + +#define bcm_iov_packv_u8 bcm_iov_pack_buf + +/* + * pack a buffer with uint16s - serialized in LE order, data points to uint16 + * length is not checked. + */ +int bcm_iov_packv_u16(const bcm_iov_cmd_digest_t *dig, uint8 *buf, + const uint16 *data, int n); + +/* + * pack a buffer with uint32s - serialized in LE order - data points to uint32 + * length is not checked. + */ +int bcm_iov_packv_u32(const bcm_iov_cmd_digest_t *dig, uint8 *buf, + const uint32 *data, int n); + +#endif /* _bcmiov_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmip.h b/drivers/net/wireless/bcmdhd_oo/include/bcmip.h index e5bb0ac66c59937ea379f37fb246e9707749a7eb..941548841c51cea6af2cb70d942eb8c7c9a42d1b 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmip.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmip.h @@ -1,14 +1,14 @@ /* * Fundamental constants relating to IP Protocol * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmip.h 700076 2017-05-17 14:42:22Z $ + * $Id: bcmip.h 705929 2017-06-20 00:06:46Z $ */ #ifndef _bcmip_h_ @@ -32,12 +32,11 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include - /* IPV4 and IPV6 common */ #define IP_VER_OFFSET 0x0 /* offset to version field */ #define IP_VER_MASK 0xf0 /* version mask */ @@ -74,6 +73,8 @@ #define IPV4_HLEN_MASK 0x0f /* IPV4 header length mask */ #define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) +#define IPV4_HLEN_MIN (4 * 5) /* IPV4 header minimum length */ + #define IPV4_ADDR_LEN 4 /* IPV4 address length */ #define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmipv6.h b/drivers/net/wireless/bcmdhd_oo/include/bcmipv6.h index 84e2b693b70ac8d6f354c3eb1078729ba95a133c..c6f1f05a439ce49e9185affdd11ddf4afd4a32ab 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmipv6.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmipv6.h @@ -1,14 +1,14 @@ /* * Fundamental constants relating to Neighbor Discovery Protocol * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,7 +32,7 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include @@ -86,7 +86,6 @@ BWL_PRE_PACKED_STRUCT struct ipv6_addr { uint8 addr[16]; } BWL_POST_PACKED_STRUCT; - /* ICMPV6 Header */ BWL_PRE_PACKED_STRUCT struct icmp6_hdr { uint8 icmp6_type; @@ -122,7 +121,6 @@ BWL_PRE_PACKED_STRUCT struct bcm_nd_msg { struct ipv6_addr target; } BWL_POST_PACKED_STRUCT; - /* Neighibor Solicitation/Advertisement Optional Structure */ BWL_PRE_PACKED_STRUCT struct nd_msg_opt { uint8 type; diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmmsgbuf.h b/drivers/net/wireless/bcmdhd_oo/include/bcmmsgbuf.h index e022acd99101e7e68040e7821878dce93815d134..4ee894d65eb468ad7a214ddb75fa70b59817495c 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmmsgbuf.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmmsgbuf.h @@ -4,14 +4,14 @@ * * Definitions subject to change without notice. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: bcmmsgbuf.h 727682 2017-10-23 04:45:57Z $ + * $Id: bcmmsgbuf.h 726968 2017-10-17 10:34:46Z $ */ #ifndef _bcmmsgbuf_h_ #define _bcmmsgbuf_h_ @@ -58,6 +58,8 @@ #define H2DRING_INFO_BUFPOST_ITEMSIZE H2DRING_CTRL_SUB_ITEMSIZE #define D2HRING_INFO_BUFCMPLT_ITEMSIZE D2HRING_CTRL_CMPLT_ITEMSIZE +#define D2HRING_SNAPSHOT_CMPLT_ITEMSIZE 20 + #define H2DRING_TXPOST_MAX_ITEM 512 #define H2DRING_RXPOST_MAX_ITEM 512 #define H2DRING_CTRL_SUB_MAX_ITEM 64 @@ -84,6 +86,10 @@ enum { #define MESSAGE_PAYLOAD(a) (a & MSG_TYPE_INTERNAL_USE_START) ? TRUE : FALSE #define PCIEDEV_FIRMWARE_TSINFO 0x1 +#define PCIEDEV_FIRMWARE_TSINFO_FIRST 0x1 +#define PCIEDEV_FIRMWARE_TSINFO_MIDDLE 0x2 +#define PCIEDEV_BTLOG_POST 0x3 +#define PCIEDEV_BT_SNAPSHOT_POST 0x4 #ifdef PCIE_API_REV1 @@ -168,7 +174,7 @@ typedef enum bcmpcie_msgtype { MSG_TYPE_TX_STATUS = 0x10, MSG_TYPE_RXBUF_POST = 0x11, MSG_TYPE_RX_CMPLT = 0x12, - MSG_TYPE_LPBK_DMAXFER = 0x13, + MSG_TYPE_LPBK_DMAXFER = 0x13, MSG_TYPE_LPBK_DMAXFER_CMPLT = 0x14, MSG_TYPE_FLOW_RING_RESUME = 0x15, MSG_TYPE_FLOW_RING_RESUME_CMPLT = 0x16, @@ -190,6 +196,12 @@ typedef enum bcmpcie_msgtype { MSG_TYPE_HOSTTIMSTAMP = 0x26, MSG_TYPE_HOSTTIMSTAMP_CMPLT = 0x27, MSG_TYPE_FIRMWARE_TIMESTAMP = 0x28, + MSG_TYPE_SNAPSHOT_UPLOAD = 0x29, + MSG_TYPE_SNAPSHOT_CMPLT = 0x2A, + MSG_TYPE_H2D_RING_DELETE = 0x2B, + MSG_TYPE_D2H_RING_DELETE = 0x2C, + MSG_TYPE_H2D_RING_DELETE_CMPLT = 0x2D, + MSG_TYPE_D2H_RING_DELETE_CMPLT = 0x2E, MSG_TYPE_API_MAX_RSVD = 0x3F } bcmpcie_msg_type_t; @@ -203,7 +215,12 @@ typedef enum bcmpcie_msgtype_int { MSG_TYPE_TXMETADATA_PYLD = 0x46, MSG_TYPE_INDX_UPDATE = 0x47, MSG_TYPE_INFO_PYLD = 0x48, - MSG_TYPE_TS_EVENT_PYLD = 0x49 + MSG_TYPE_TS_EVENT_PYLD = 0x49, + MSG_TYPE_PVT_BTLOG_CMPLT = 0x4A, + MSG_TYPE_BTLOG_PYLD = 0x4B, + MSG_TYPE_HMAPTEST_PYLD = 0x4C, + MSG_TYPE_PVT_BT_SNAPSHOT_CMPLT = 0x4D, + MSG_TYPE_BT_SNAPSHOT_PYLD = 0x4E } bcmpcie_msgtype_int_t; typedef enum bcmpcie_msgtype_u { @@ -238,19 +255,22 @@ typedef struct bcmpcie_soft_doorbell { * D2H_RING_CONFIG_SUBTYPE_MSI_DOORBELL */ typedef enum bcmpcie_msi_intr_idx { - MSI_INTR_IDX_CTRL_CMPL_RING, - MSI_INTR_IDX_TXP_CMPL_RING, - MSI_INTR_IDX_RXP_CMPL_RING, - MSI_INTR_IDX_MAILBOX, - MSI_INTR_IDX_MAX + MSI_INTR_IDX_CTRL_CMPL_RING = 0, + MSI_INTR_IDX_TXP_CMPL_RING = 1, + MSI_INTR_IDX_RXP_CMPL_RING = 2, + MSI_INTR_IDX_INFO_CMPL_RING = 3, + MSI_INTR_IDX_MAILBOX = 4, + MSI_INTR_IDX_MAX = 5 } bcmpcie_msi_intr_idx_t; +#define BCMPCIE_D2H_MSI_OFFSET_SINGLE 0 typedef enum bcmpcie_msi_offset_type { - BCMPCIE_D2H_MSI_OFFSET_MB0 = 2, - BCMPCIE_D2H_MSI_OFFSET_MB1, - BCMPCIE_D2H_MSI_OFFSET_DB0, - BCMPCIE_D2H_MSI_OFFSET_DB1, - BCMPCIE_D2H_MSI_OFFSET_MAX + BCMPCIE_D2H_MSI_OFFSET_MB0 = 2, + BCMPCIE_D2H_MSI_OFFSET_MB1 = 3, + BCMPCIE_D2H_MSI_OFFSET_DB0 = 4, + BCMPCIE_D2H_MSI_OFFSET_DB1 = 5, + BCMPCIE_D2H_MSI_OFFSET_H1_DB0 = 6, + BCMPCIE_D2H_MSI_OFFSET_MAX = 7 } bcmpcie_msi_offset_type_t; typedef struct bcmpcie_msi_offset { @@ -265,6 +285,7 @@ typedef struct bcmpcie_msi_offset_config { #define BCMPCIE_D2H_MSI_OFFSET_DEFAULT BCMPCIE_D2H_MSI_OFFSET_DB1 +#define BCMPCIE_D2H_MSI_SINGLE 0xFFFE /* if_id */ #define BCMPCIE_CMNHDR_IFIDX_PHYINTF_SHFT 5 @@ -279,13 +300,14 @@ typedef struct bcmpcie_msi_offset_config { /* flags */ #define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX 0x1 #define BCMPCIE_CMNHDR_FLAGS_DMA_R_IDX_INTR 0x2 +#define BCMPCIE_CMNHDR_FLAGS_TS_SEQNUM_INIT 0x4 #define BCMPCIE_CMNHDR_FLAGS_PHASE_BIT 0x80 #define BCMPCIE_CMNHDR_PHASE_BIT_INIT 0x80 /* IOCTL request message */ typedef struct ioctl_req_msg { /** common message header */ - cmn_msg_hdr_t cmn_hdr; + cmn_msg_hdr_t cmn_hdr; /** ioctl command type */ uint32 cmd; /** ioctl transaction ID, to pair with a ioctl response */ @@ -318,6 +340,9 @@ typedef struct ioctl_resp_evt_buf_post_msg { /* buffer post messages for device to use to return dbg buffers */ typedef ioctl_resp_evt_buf_post_msg_t info_buf_post_msg_t; +#define DHD_INFOBUF_RX_BUFPOST_PKTSZ (2 * 1024) + +#define DHD_BTLOG_RX_BUFPOST_PKTSZ (2 * 1024) /* An infobuf host buffer starts with a 32 bit (LE) version. */ #define PCIE_INFOBUF_V1 1 @@ -342,10 +367,46 @@ typedef struct info_buf_payload_hdr_s { uint16 length; } info_buf_payload_hdr_t; -#define PCIE_DMA_XFER_FLG_D11_LPBK_MASK 3 -#define PCIE_DMA_XFER_FLG_D11_LPBK_SHIFT 0 -#define PCIE_DMA_XFER_FLG_CORE_NUMBER_MASK 1 -#define PCIE_DMA_XFER_FLG_CORE_NUMBER_SHIFT 2 +/* BT logs/memory to DMA directly from BT memory to host */ +typedef struct info_buf_btlog_s { + void (*status_cb)(void *ctx, void *p, int error); /* obsolete - to be removed */ + void *ctx; + dma64addr_t src_addr; + uint32 length; + bool (*pcie_status_cb)(osl_t *osh, void *p, int error); + uint32 bt_intstatus; + int error; +} info_buf_btlog_t; + +/** snapshot upload request message */ +typedef struct snapshot_upload_request_msg { + /** common message header */ + cmn_msg_hdr_t cmn_hdr; + /** length of the snaphost buffer supplied */ + uint32 snapshot_buf_len; + /** type of snapshot */ + uint8 snapshot_type; + /** snapshot param */ + uint8 snapshot_param; + /** to align the host address on 8 byte boundary */ + uint8 reserved[2]; + /** always align on 8 byte boundary */ + bcm_addr64_t host_buf_addr; + uint32 rsvd[4]; +} snapshot_upload_request_msg_t; + +/** snapshot types */ +typedef enum bcmpcie_snapshot_type { + SNAPSHOT_TYPE_BT = 0, /* Bluetooth SRAM and patch RAM */ + SNAPSHOT_TYPE_WLAN_SOCRAM = 1, /* WLAN SOCRAM */ + SNAPSHOT_TYPE_WLAN_HEAP = 2, /* WLAN HEAP */ + SNAPSHOT_TYPE_WLAN_REGISTER = 3 /* WLAN registers */ +} bcmpcie_snapshot_type_t; + +#define PCIE_DMA_XFER_FLG_D11_LPBK_MASK 0xF +#define PCIE_DMA_XFER_FLG_D11_LPBK_SHIFT 2 +#define PCIE_DMA_XFER_FLG_CORE_NUMBER_MASK 3 +#define PCIE_DMA_XFER_FLG_CORE_NUMBER_SHIFT 0 typedef struct pcie_dma_xfer_params { /** common message header */ @@ -374,14 +435,14 @@ typedef struct tx_flowring_create_request { uint8 da[ETHER_ADDR_LEN]; uint8 sa[ETHER_ADDR_LEN]; uint8 tid; - uint8 if_flags; + uint8 if_flags; uint16 flow_ring_id; - uint8 tc; + uint8 tc; /* priority_ifrmmask is to define core mask in ifrm mode. * currently it is not used for priority. so uses solely for ifrm mask */ uint8 priority_ifrmmask; - uint16 int_vector; + uint16 int_vector; uint16 max_items; uint16 len_item; bcm_addr64_t flow_ring_ptr; @@ -390,14 +451,17 @@ typedef struct tx_flowring_create_request { typedef struct tx_flowring_delete_request { cmn_msg_hdr_t msg; uint16 flow_ring_id; - uint16 reason; + uint16 reason; uint32 rsvd[7]; } tx_flowring_delete_request_t; +typedef tx_flowring_delete_request_t d2h_ring_delete_req_t; +typedef tx_flowring_delete_request_t h2d_ring_delete_req_t; + typedef struct tx_flowring_flush_request { cmn_msg_hdr_t msg; uint16 flow_ring_id; - uint16 reason; + uint16 reason; uint32 rsvd[7]; } tx_flowring_flush_request_t; @@ -500,6 +564,8 @@ typedef union ctrl_submit_item { h2d_mailbox_data_t h2d_mailbox_data; host_timestamp_msg_t host_ts; ts_buf_post_msg_t ts_buf_post; + d2h_ring_delete_req_t d2h_delete; + h2d_ring_delete_req_t h2d_delete; unsigned char check[H2DRING_CTRL_SUB_ITEMSIZE]; } ctrl_submit_item_t; @@ -570,6 +636,14 @@ typedef ts_timestamp_t ts_correction_b_t; #define BCMPCIE_RING_TYPE_INVALID 14 #define BCMPCIE_NO_TS_EVENT_BUF 15 #define BCMPCIE_MAX_TS_EVENT_BUF 16 +#define BCMPCIE_PCIE_NO_BTLOG_BUF 17 +#define BCMPCIE_BT_DMA_ERR 18 +#define BCMPCIE_BT_DMA_DESCR_FETCH_ERR 19 +#define BCMPCIE_SNAPSHOT_ERR 20 +#define BCMPCIE_NOT_READY 21 +#define BCMPCIE_INVALID_DATA 22 +#define BCMPCIE_NO_RESPONSE 23 +#define BCMPCIE_NO_CLOCK 24 /** IOCTL completion response */ typedef struct ioctl_compl_resp_msg { @@ -592,7 +666,7 @@ typedef struct ioctl_req_ack_msg { /** common message header */ cmn_msg_hdr_t cmn_hdr; /** completion message header */ - compl_msg_hdr_t compl_hdr; + compl_msg_hdr_t compl_hdr; /** cmd id */ uint32 cmd; uint32 rsvd; @@ -653,7 +727,7 @@ typedef struct pcie_ring_status { typedef struct ring_create_response { cmn_msg_hdr_t cmn_hdr; - compl_msg_hdr_t cmplt; + compl_msg_hdr_t cmplt; uint32 rsvd[2]; /** XOR checksum or a magic number to audit DMA done */ dma_done_t marker; @@ -665,15 +739,19 @@ typedef ring_create_response_t d2h_ring_create_response_t; typedef struct tx_flowring_delete_response { cmn_msg_hdr_t msg; - compl_msg_hdr_t cmplt; - uint32 rsvd[2]; + compl_msg_hdr_t cmplt; + uint16 read_idx; + uint16 rsvd[3]; /** XOR checksum or a magic number to audit DMA done */ dma_done_t marker; } tx_flowring_delete_response_t; +typedef tx_flowring_delete_response_t h2d_ring_delete_response_t; +typedef tx_flowring_delete_response_t d2h_ring_delete_response_t; + typedef struct tx_flowring_flush_response { cmn_msg_hdr_t msg; - compl_msg_hdr_t cmplt; + compl_msg_hdr_t cmplt; uint32 rsvd[2]; /** XOR checksum or a magic number to audit DMA done */ dma_done_t marker; @@ -695,7 +773,8 @@ typedef struct ring_config_resp { cmn_msg_hdr_t cmn_hdr; /** completion message header */ compl_msg_hdr_t compl_hdr; - uint32 rsvd[2]; + uint16 subtype; + uint16 rsvd[3]; /** XOR checksum or a magic number to audit DMA done */ dma_done_t marker; } ring_config_resp_t; @@ -725,6 +804,22 @@ typedef struct info_buf_resp { dma_done_t marker; } info_buf_resp_t; +/* snapshot completion msg: send from device to host */ +typedef struct snapshot_resp { + /* common message header */ + cmn_msg_hdr_t cmn_hdr; + /* completion message header */ + compl_msg_hdr_t compl_hdr; + /* snapshot length uploaded */ + uint32 resp_len; + /* snapshot type */ + uint8 type; + /* rsvd */ + uint8 rsvd[3]; + /* XOR checksum or a magic number to audit DMA done */ + dma_done_t marker; +} snapshot_resp_t; + typedef struct info_ring_cpl_item { info_buf_resp_t info_buf_post; unsigned char check[D2HRING_INFO_BUFCMPLT_ITEMSIZE]; @@ -769,6 +864,8 @@ typedef union ctrl_completion_item { d2h_ring_create_response_t d2h_ring_create_resp; host_timestamp_msg_cpl_t host_ts_cpl; fw_timestamp_event_msg_t fw_ts_event; + h2d_ring_delete_response_t h2d_ring_delete_resp; + d2h_ring_delete_response_t d2h_ring_delete_resp; unsigned char ctrl_response[D2HRING_CTRL_CMPLT_ITEMSIZE]; } ctrl_completion_item_t; @@ -822,7 +919,6 @@ typedef union rxbuf_complete_item { unsigned char check[D2HRING_RXCMPLT_ITEMSIZE]; } rxbuf_complete_item_t; - typedef struct host_txbuf_post { /** common message header */ cmn_msg_hdr_t cmn_hdr; @@ -841,17 +937,32 @@ typedef struct host_txbuf_post { uint16 metadata_buf_len; /** provided data buffer len to receive data */ uint16 data_len; - /** XOR checksum or a magic number to audit DMA done */ - dma_done_t marker; + union { + struct { + /** extended transmit flags */ + uint8 ext_flags; + uint8 rsvd1; + + /** user defined rate */ + uint8 rate; + uint8 rsvd2; + }; + /** XOR checksum or a magic number to audit DMA done */ + dma_done_t marker; + }; } host_txbuf_post_t; #define BCMPCIE_PKT_FLAGS_FRAME_802_3 0x01 #define BCMPCIE_PKT_FLAGS_FRAME_802_11 0x02 +#define BCMPCIE_PKT_FLAGS_FRAME_NORETRY 0x01 /* Disable retry on this frame */ +#define BCMPCIE_PKT_FLAGS_FRAME_NOAGGR 0x02 /* Disable aggregation for this frame */ +#define BCMPCIE_PKT_FLAGS_FRAME_UDR 0x04 /* User defined rate for this frame */ +#define BCMPCIE_PKT_FLAGS_FRAME_ATTR_MASK 0x07 /* Attribute mask */ + #define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_MASK 0x03 /* Exempt uses 2 bits */ #define BCMPCIE_PKT_FLAGS_FRAME_EXEMPT_SHIFT 0x02 /* needs to be shifted past other bits */ - #define BCMPCIE_PKT_FLAGS_PRIO_SHIFT 5 #define BCMPCIE_PKT_FLAGS_PRIO_MASK (7 << BCMPCIE_PKT_FLAGS_PRIO_SHIFT) #define BCMPCIE_PKT_FLAGS_MONITOR_NO_AMSDU 0x00 @@ -867,7 +978,6 @@ typedef struct host_txbuf_post { #define BCMPCIE_TXPOST_FLAGS_PRIO_SHIFT BCMPCIE_PKT_FLAGS_PRIO_SHIFT #define BCMPCIE_TXPOST_FLAGS_PRIO_MASK BCMPCIE_PKT_FLAGS_PRIO_MASK - /* H2D Txpost ring work items */ typedef union txbuf_submit_item { host_txbuf_post_t txpost; @@ -882,8 +992,12 @@ typedef struct host_txbuf_cmpl { compl_msg_hdr_t compl_hdr; union { struct { - /** provided meta data len */ - uint16 metadata_len; + union { + /** provided meta data len */ + uint16 metadata_len; + /** provided extended TX status */ + uint16 tx_status_ext; + }; /** WLAN side txstatus */ uint16 tx_status; }; @@ -910,20 +1024,19 @@ typedef struct ret_buf_ptr { uint32 high_addr; } ret_buf_t; - #ifdef PCIE_API_REV1 /* ioctl specific hdr */ typedef struct ioctl_hdr { - uint16 cmd; + uint16 cmd; uint16 retbuf_len; uint32 cmd_id; } ioctl_hdr_t; typedef struct ioctlptr_hdr { - uint16 cmd; + uint16 cmd; uint16 retbuf_len; - uint16 buflen; + uint16 buflen; uint16 rsvd; uint32 cmd_id; } ioctlptr_hdr_t; @@ -932,16 +1045,15 @@ typedef struct ioctlptr_hdr { typedef struct ioctl_req_hdr { uint32 pkt_id; /**< Packet ID */ - uint32 cmd; /**< IOCTL ID */ + uint32 cmd; /**< IOCTL ID */ uint16 retbuf_len; - uint16 buflen; + uint16 buflen; uint16 xt_id; /**< transaction ID */ uint16 rsvd[1]; } ioctl_req_hdr_t; #endif /* PCIE_API_REV1 */ - /** Complete msgbuf hdr for ioctl from host to dongle */ typedef struct ioct_reqst_hdr { cmn_msg_hdr_t msg; @@ -949,7 +1061,7 @@ typedef struct ioct_reqst_hdr { ioctl_hdr_t ioct_hdr; #else ioctl_req_hdr_t ioct_hdr; -#endif +#endif // endif ret_buf_t ret_buf; } ioct_reqst_hdr_t; @@ -959,7 +1071,7 @@ typedef struct ioctptr_reqst_hdr { ioctlptr_hdr_t ioct_hdr; #else ioctl_req_hdr_t ioct_hdr; -#endif +#endif // endif ret_buf_t ret_buf; ret_buf_t ioct_buf; } ioctptr_reqst_hdr_t; @@ -971,7 +1083,7 @@ typedef struct ioct_resp_hdr { uint32 cmd_id; #else uint32 pkt_id; -#endif +#endif // endif uint32 status; uint32 ret_len; uint32 inline_data; @@ -979,7 +1091,7 @@ typedef struct ioct_resp_hdr { #else uint16 xt_id; /**< transaction ID */ uint16 rsvd[1]; -#endif +#endif // endif } ioct_resp_hdr_t; /* ioct resp header used in dongle */ @@ -1195,11 +1307,17 @@ typedef struct ts_host_timestamping_config { /* time period to capture the device time stamp and toggle WLAN_TIME_SYNC_GPIO */ uint16 period_ms; uint8 flags; - uint8 rsvd; + uint8 post_delay; uint32 reset_cnt; } ts_host_timestamping_config_t; /* Flags in host timestamping config TLV */ #define FLAG_HOST_RESET (1 << 0) +#define IS_HOST_RESET(x) ((x) & FLAG_HOST_RESET) +#define CLEAR_HOST_RESET(x) ((x) & ~FLAG_HOST_RESET) + +#define FLAG_CONFIG_NODROP (1 << 1) +#define IS_CONFIG_NODROP(x) ((x) & FLAG_CONFIG_NODROP) +#define CLEAR_CONFIG_NODROP(x) ((x) & ~FLAG_CONFIG_NODROP) #endif /* _bcmmsgbuf_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmpcie.h b/drivers/net/wireless/bcmdhd_oo/include/bcmpcie.h index 114924cc9fec07786e9da52837d58c2ac352fbcc..e51ec48054974aba9ce941ca22dbecafb7ef5fa1 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmpcie.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmpcie.h @@ -3,14 +3,14 @@ * Software-specific definitions shared between device and host side * Explains the shared area between host and dongle * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,10 +26,9 @@ * * <> * - * $Id: bcmpcie.h 678914 2017-01-11 15:34:26Z $ + * $Id: bcmpcie.h 737203 2017-12-20 05:55:03Z $ */ - #ifndef _bcmpcie_h_ #define _bcmpcie_h_ @@ -44,7 +43,6 @@ typedef struct { uint32 high_addr; } sh_addr_t; - /* May be overridden by 43xxxxx-roml.mk */ #if !defined(BCMPCIE_MAX_TX_FLOWS) #define BCMPCIE_MAX_TX_FLOWS 40 @@ -57,7 +55,6 @@ typedef struct { * Feature flags enabled in dongle. Advertised by dongle to DHD via the PCIe Shared structure that * is located in device memory. */ -#define PCIE_SHARED_VERSION PCIE_SHARED_VERSION_7 #define PCIE_SHARED_VERSION_MASK 0x000FF #define PCIE_SHARED_ASSERT_BUILT 0x00100 #define PCIE_SHARED_ASSERT 0x00200 @@ -69,10 +66,6 @@ typedef struct { #define PCIE_SHARED_EVT_SEQNUM 0x08000 #define PCIE_SHARED_DMA_INDEX 0x10000 -/* WAR: D11 txstatus through unused status field of PCIe completion header */ -#define PCIE_SHARED_D2H_D11_TX_STATUS 0x40000000 /* using flags2 in shared area */ -#define PCIE_SHARED_H2D_D11_TX_STATUS 0x80000000 /* using flags2 in shared area */ - /** * There are host types where a device interrupt can 'race ahead' of data written by the device into * host memory. The dongle can avoid this condition using a variety of techniques (read barrier, @@ -89,9 +82,17 @@ typedef struct { #define PCIE_SHARED_2BYTE_INDICES 0x100000 #define PCIE_SHARED2_EXTENDED_TRAP_DATA 0x00000001 /* using flags2 in shared area */ +#define PCIE_SHARED2_TXSTATUS_METADATA 0x00000002 +#define PCIE_SHARED2_BT_LOGGING 0x00000004 /* BT logging support */ +#define PCIE_SHARED2_SNAPSHOT_UPLOAD 0x00000008 /* BT/WLAN snapshot upload support */ +#define PCIE_SHARED2_SUBMIT_COUNT_WAR 0x00000010 /* submission count WAR */ +#define PCIE_SHARED2_FW_SMALL_MEMDUMP 0x00000200 /* FW small memdump */ +#define PCIE_SHARED_FAST_DELETE_RING 0x00000020 /* Fast Delete Ring */ +#define PCIE_SHARED_EVENT_BUF_POOL_MAX 0x000000c0 /* event buffer pool max bits */ +#define PCIE_SHARED_EVENT_BUF_POOL_MAX_POS 6 /* event buffer pool max bit position */ /* dongle supports fatal buf log collection */ -#define PCIE_SHARED_FATAL_LOGBUG_VALID 0x200000 +#define PCIE_SHARED_FATAL_LOGBUG_VALID 0x200000 /* Implicit DMA with corerev 19 and after */ #define PCIE_SHARED_IDMA 0x400000 @@ -120,17 +121,46 @@ typedef struct { #define PCIE_SHARED_HOSTRDY_SUPPORT 0x10000000 /* When set, Firmwar does not support OOB Device Wake based DS protocol */ -#define PCIE_SHARED_NO_OOB_DW 0x20000000 +#define PCIE_SHARED_NO_OOB_DW 0x20000000 /* When set, Firmwar supports Inband DS protocol */ -#define PCIE_SHARED_INBAND_DS 0x40000000 +#define PCIE_SHARED_INBAND_DS 0x40000000 + +/* use DAR registers */ +#define PCIE_SHARED_DAR 0x80000000 + +/** + * Following are the shared2 flags. All bits in flags have been used. A flags2 + * field got added and the definition for these flags come here: + */ +/* WAR: D11 txstatus through unused status field of PCIe completion header */ +#define PCIE_SHARED2_D2H_D11_TX_STATUS 0x40000000 +#define PCIE_SHARED2_H2D_D11_TX_STATUS 0x80000000 + +#define PCIE_SHARED2_EXTENDED_TRAP_DATA 0x00000001 + +#define PCIE_SHARED2_TXSTATUS_METADATA 0x00000002 -/* Implicit DMA WAR for 4347B0 PCIe memory retention */ -#define PCIE_SHARED_IDMA_RETENTION_DS 0x80000000 +/* BT logging support */ +#define PCIE_SHARED2_BT_LOGGING 0x00000004 +/* BT/WLAN snapshot upload support */ +#define PCIE_SHARED2_SNAPSHOT_UPLOAD 0x00000008 +/* submission count WAR */ +#define PCIE_SHARED2_SUBMIT_COUNT_WAR 0x00000010 + +/* Fast Delete ring support */ +#define PCIE_SHARED2_FAST_DELETE_RING 0x00000020 + +/* Host SCB support */ +#define PCIE_SHARED2_HSCB 0x00000800 #define PCIE_SHARED_D2H_MAGIC 0xFEDCBA09 #define PCIE_SHARED_H2D_MAGIC 0x12345678 +#define PCIE_SHARED2_PKT_TX_STATUS 0x00000100 /* using flags2 to indicate + firmware support added to reuse + timesync to update PKT txstatus + */ /** * Message rings convey messages between host and device. They are unidirectional, and are located * in host memory. @@ -157,12 +187,14 @@ typedef struct { #define BCMPCIE_H2D_RING_TYPE_RXBUFPOST 0x3 #define BCMPCIE_H2D_RING_TYPE_TXSUBMIT 0x4 #define BCMPCIE_H2D_RING_TYPE_DBGBUF_SUBMIT 0x5 +#define BCMPCIE_H2D_RING_TYPE_BTLOG_SUBMIT 0x6 #define BCMPCIE_D2H_RING_TYPE_CTRL_CPL 0x1 #define BCMPCIE_D2H_RING_TYPE_TX_CPL 0x2 #define BCMPCIE_D2H_RING_TYPE_RX_CPL 0x3 #define BCMPCIE_D2H_RING_TYPE_DBGBUF_CPL 0x4 #define BCMPCIE_D2H_RING_TYPE_AC_RX_COMPLETE 0x5 +#define BCMPCIE_D2H_RING_TYPE_BTLOG_CPL 0x6 /** * H2D and D2H, WR and RD index, are maintained in the following arrays: @@ -231,6 +263,8 @@ enum d2hring_idx { #define BCMPCIE_D2H_RW_INDEX_ARRAY_SZ(rw_index_sz) \ ((rw_index_sz) * BCMPCIE_D2H_COMMON_MSGRINGS) +#define HOFFLOAD_MODULES_ENAB(shmem) (0) + /** * This type is used by a 'message buffer' (which is a FIFO for messages). Message buffers are used * for host<->device communication and are instantiated on both sides. ring_mem_t is instantiated @@ -245,6 +279,7 @@ typedef struct ring_mem { sh_addr_t base_addr; /* 64 bits address, either in host or device memory */ } ring_mem_t; +#define HOSTCAP_PKT_TXSTATUS 0x00400000 /** * Per flow ring, information is maintained in device memory, eg at what address the ringmem and @@ -319,11 +354,19 @@ typedef struct { uint32 host_dma_scratch_buffer_len; sh_addr_t host_dma_scratch_buffer; - /** block of host memory for the dongle to push the status into */ - uint32 device_rings_stsblk_len; - sh_addr_t device_rings_stsblk; + /* location in host memory for scb host offload structures */ + sh_addr_t host_scb_addr; + uint32 host_scb_size; - uint32 buzz_dbg_ptr; /* BUZZZ state format strings and trace buffer */ + /* anonymous union for overloading fields in structure */ + union { + uint32 buzz_dbg_ptr; /* BUZZZ state format strings and trace buffer */ + struct { + /* Host provided trap buffer length in words */ + uint16 device_trap_debug_buffer_len; + uint16 rsvd2; + }; + }; /* rev6 compatible changes */ uint32 flags2; @@ -332,6 +375,7 @@ typedef struct { /* location in the host address space to write trap indication. * At this point for the current rev of the spec, firmware will * support only indications to 32 bit host addresses. + * This essentially is device_trap_debug_buffer_addr */ sh_addr_t host_trap_addr; @@ -339,10 +383,12 @@ typedef struct { uint32 device_fatal_logbuf_start; /* location in host memory for offloaded modules */ - sh_addr_t hoffload_addr; + sh_addr_t hoffload_addr; } pciedev_shared_t; -extern pciedev_shared_t pciedev_shared; +/* Device F/W provides the following access function: + * pciedev_shared_t *hnd_get_pciedev_shared(void); + */ /* host capabilities */ #define HOSTCAP_PCIEAPI_VERSION_MASK 0x000000FF @@ -357,6 +403,19 @@ extern pciedev_shared_t pciedev_shared; #define HOSTCAP_H2D_DAR 0x00010000 #define HOSTCAP_EXTENDED_TRAP_DATA 0x00020000 #define HOSTCAP_TXSTATUS_METADATA 0x00040000 +#define HOSTCAP_BT_LOGGING 0x00080000 +#define HOSTCAP_SNAPSHOT_UPLOAD 0x00100000 +#define HOSTCAP_FAST_DELETE_RING 0x00200000 +#define HOSTCAP_UR_FW_NO_TRAP 0x00800000 /* Don't trap on UR */ +#define HOSTCAP_HSCB 0x02000000 +/* Host support for extended device trap debug buffer */ +#define HOSTCAP_EXT_TRAP_DBGBUF 0x04000000 + +/* extended trap debug buffer allocation sizes. Note that this buffer can be used for + * other trap related purposes also. + */ +#define BCMPCIE_HOST_EXT_TRAP_DBGBUF_LEN_MIN (64u * 1024u) +#define BCMPCIE_HOST_EXT_TRAP_DBGBUF_LEN_MAX (256u * 1024u) /** * Mailboxes notify a remote party that an event took place, using interrupts. They use hardware @@ -364,61 +423,69 @@ extern pciedev_shared_t pciedev_shared; */ /* H2D mail box Data */ -#define H2D_HOST_D3_INFORM 0x00000001 +#define H2D_HOST_D3_INFORM 0x00000001 #define H2D_HOST_DS_ACK 0x00000002 #define H2D_HOST_DS_NAK 0x00000004 -#define H2D_HOST_CONS_INT 0x80000000 /**< h2d int for console cmds */ -#define H2D_FW_TRAP 0x20000000 /**< h2d force TRAP */ #define H2D_HOST_D0_INFORM_IN_USE 0x00000008 -#define H2D_HOST_D0_INFORM 0x00000010 +#define H2D_HOST_D0_INFORM 0x00000010 +#define H2DMB_DS_ACTIVE 0x00000020 +#define H2DMB_DS_DEVICE_WAKE 0x00000040 #define H2D_HOST_IDMA_INITED 0x00000080 +#define H2D_HOST_ACK_NOINT 0x00010000 /* d2h_ack interrupt ignore */ +#define H2D_HOST_CONS_INT 0x80000000 /**< h2d int for console cmds */ +#define H2D_FW_TRAP 0x20000000 /**< h2d force TRAP */ #define H2DMB_DS_HOST_SLEEP_INFORM H2D_HOST_D3_INFORM #define H2DMB_DS_DEVICE_SLEEP_ACK H2D_HOST_DS_ACK #define H2DMB_DS_DEVICE_SLEEP_NAK H2D_HOST_DS_NAK #define H2DMB_D0_INFORM_IN_USE H2D_HOST_D0_INFORM_IN_USE #define H2DMB_D0_INFORM H2D_HOST_D0_INFORM -#define H2DMB_DS_ACTIVE 0x00000020 -#define H2DMB_DS_DEVICE_WAKE 0x00000040 #define H2DMB_FW_TRAP H2D_FW_TRAP #define H2DMB_HOST_CONS_INT H2D_HOST_CONS_INT #define H2DMB_DS_DEVICE_WAKE_ASSERT H2DMB_DS_DEVICE_WAKE #define H2DMB_DS_DEVICE_WAKE_DEASSERT H2DMB_DS_ACTIVE /* D2H mail box Data */ -#define D2H_DEV_D3_ACK 0x00000001 -#define D2H_DEV_DS_ENTER_REQ 0x00000002 -#define D2H_DEV_DS_EXIT_NOTE 0x00000004 -#define D2H_DEV_FWHALT 0x10000000 -#define D2H_DEV_EXT_TRAP_DATA 0x20000000 -#define D2H_DEV_IDMA_INITED 0x00000010 -#define D2H_FWTRAP_MASK 0x0000001F /* Adding maskbits for TRAP information */ +#define D2H_DEV_D3_ACK 0x00000001 +#define D2H_DEV_DS_ENTER_REQ 0x00000002 +#define D2H_DEV_DS_EXIT_NOTE 0x00000004 +#define D2HMB_DS_HOST_SLEEP_EXIT_ACK 0x00000008 +#define D2H_DEV_IDMA_INITED 0x00000010 +#define D2H_DEV_FWHALT 0x10000000 +#define D2H_DEV_EXT_TRAP_DATA 0x20000000 +#define D2H_DEV_TRAP_IN_TRAP 0x40000000 +#define D2H_DEV_TRAP_DUE_TO_BT 0x01000000 #define D2HMB_DS_HOST_SLEEP_ACK D2H_DEV_D3_ACK #define D2HMB_DS_DEVICE_SLEEP_ENTER_REQ D2H_DEV_DS_ENTER_REQ #define D2HMB_DS_DEVICE_SLEEP_EXIT D2H_DEV_DS_EXIT_NOTE -#define D2HMB_DS_HOST_SLEEP_EXIT_ACK 0x00000008 #define D2HMB_FWHALT D2H_DEV_FWHALT +#define D2HMB_TRAP_IN_TRAP D2H_DEV_TRAP_IN_TRAP +#define D2HMB_EXT_TRAP_DATA D2H_DEV_EXT_TRAP_DATA +#define D2H_FWTRAP_MASK 0x0000001F /* Adding maskbits for TRAP information */ #define D2H_DEV_MB_MASK (D2H_DEV_D3_ACK | D2H_DEV_DS_ENTER_REQ | \ D2H_DEV_DS_EXIT_NOTE | D2H_DEV_IDMA_INITED | D2H_DEV_FWHALT | \ - D2H_FWTRAP_MASK | D2H_DEV_EXT_TRAP_DATA) + D2H_FWTRAP_MASK | D2H_DEV_EXT_TRAP_DATA | D2H_DEV_TRAP_IN_TRAP) #define D2H_DEV_MB_INVALIDATED(x) ((!x) || (x & ~D2H_DEV_MB_MASK)) +/* Size of Extended Trap data Buffer */ +#define BCMPCIE_EXT_TRAP_DATA_MAXLEN 4096 /** These macro's operate on type 'inuse_lclbuf_pool_t' and are used by firmware only */ +#define PREVTXP(i, d) (((i) == 0) ? ((d) - 1) : ((i) - 1)) #define NEXTTXP(i, d) ((((i)+1) >= (d)) ? 0 : ((i)+1)) +#define NEXTNTXP(i, n, d) ((((i)+(n)) >= (d)) ? 0 : ((i)+(n))) #define NTXPACTIVE(r, w, d) (((r) <= (w)) ? ((w)-(r)) : ((d)-(r)+(w))) #define NTXPAVAIL(r, w, d) (((d) - NTXPACTIVE((r), (w), (d))) > 1) /* Function can be used to notify host of FW halt */ -#define READ_AVAIL_SPACE(w, r, d) \ - ((w >= r) ? (w - r) : (d - r)) - -#define WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d) ((w >= r) ? (d - w) : (r - w)) -#define WRITE_SPACE_AVAIL(r, w, d) (d - (NTXPACTIVE(r, w, d)) - 1) -#define CHECK_WRITE_SPACE(r, w, d) \ - ((r) > (w)) ? ((r) - (w) - 1) : ((r) == 0 || (w) == 0) ? ((d) - (w) - 1) : ((d) - (w)) -#define CHECK_NOWRITE_SPACE(r, w, d) \ - (((r) == (w) + 1) || (((r) == 0) && ((w) == ((d) - 1)))) +#define READ_AVAIL_SPACE(w, r, d) ((w >= r) ? (uint32)(w - r) : (uint32)(d - r)) +#define WRITE_SPACE_AVAIL_CONTINUOUS(r, w, d) ((w >= r) ? (d - w) : (r - w)) +#define WRITE_SPACE_AVAIL(r, w, d) (d - (NTXPACTIVE(r, w, d)) - 1) +#define CHECK_WRITE_SPACE(r, w, d) ((r) > (w)) ? \ + (uint32)((r) - (w) - 1) : ((r) == 0 || (w) == 0) ? \ + (uint32)((d) - (w) - 1) : (uint32)((d) - (w)) +#define CHECK_NOWRITE_SPACE(r, w, d) \ + (((uint32)(r) == (uint32)((w) + 1)) || (((r) == 0) && ((w) == ((d) - 1)))) #define WRT_PEND(x) ((x)->wr_pending) #define DNGL_RING_WPTR(msgbuf) (*((msgbuf)->tcm_rs_w_ptr)) /**< advanced by producer */ @@ -437,4 +504,9 @@ extern pciedev_shared_t pciedev_shared; #define HOST_RING_BASE(x) ((x)->dma_buf.va) #define HOST_RING_END(x) ((uint8 *)HOST_RING_BASE((x)) + \ ((RING_MAX_ITEM((x))-1)*RING_LEN_ITEMS((x)))) + +/* Trap types copied in the pciedev_shared.trap_addr */ +#define FW_INITIATED_TRAP_TYPE (0x1 << 7) +#define HEALTHCHECK_NODS_TRAP_TYPE (0x1 << 6) + #endif /* _bcmpcie_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd_oo/include/bcmsdbus.h index 03a05c2ee8e43a4e9e0e09e62e1ae6362ba38e5d..c4cef93c7e91284721da82fb9e344605597a55b6 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmsdbus.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmsdbus.h @@ -2,14 +2,14 @@ * Definitions for API from sdio common code (bcmsdh) to individual * host controller drivers. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: bcmsdbus.h 644725 2016-06-21 12:26:04Z $ + * $Id: bcmsdbus.h 689948 2017-03-14 05:21:03Z $ */ #ifndef _sdio_api_h_ @@ -35,7 +35,6 @@ #include #endif /* defined (BT_OVER_SDIO) */ - #define SDIOH_API_RC_SUCCESS (0x00) #define SDIOH_API_RC_FAIL (0x01) #define SDIOH_API_SUCCESS(status) (status == 0) @@ -73,7 +72,7 @@ #warning "SDPCM_DEFGLOM_SIZE cannot be higher than SDPCM_MAXGLOM_SIZE!!" #undef SDPCM_DEFGLOM_SIZE #define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE -#endif +#endif // endif typedef int SDIOH_API_RC; @@ -98,7 +97,7 @@ extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable); #if defined(DHD_DEBUG) extern bool sdioh_interrupt_pending(sdioh_info_t *si); -#endif +#endif // endif /* read or write one byte using cmd52 */ extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte); @@ -138,7 +137,6 @@ extern int sdioh_waitlockfree(sdioh_info_t *si); /* Reset and re-initialize the device */ extern int sdioh_sdio_reset(sdioh_info_t *si); - #ifdef BCMSPI /* Function to pass gSPI specific device-status bits to dhd. */ extern uint32 sdioh_get_dstatus(sdioh_info_t *si); @@ -150,7 +148,7 @@ extern void sdioh_dwordmode(sdioh_info_t *si, bool set); #if defined(BCMSDIOH_STD) #define SDIOH_SLEEP_ENABLED -#endif +#endif // endif extern SDIOH_API_RC sdioh_sleep(sdioh_info_t *si, bool enab); /* GPIO support */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmsdh.h b/drivers/net/wireless/bcmdhd_oo/include/bcmsdh.h index d8cd2919292d4b81d588fc6f4b4aed15243c874c..9deaff26508d5065b8bf6480283b1999f382cb33 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmsdh.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmsdh.h @@ -3,14 +3,14 @@ * export functions to client drivers * abstract OS and BUS specific details of SDIO * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,7 +26,7 @@ * * <> * - * $Id: bcmsdh.h 698895 2017-05-11 02:55:17Z $ + * $Id: bcmsdh.h 727623 2017-10-21 01:00:32Z $ */ /** @@ -52,14 +52,13 @@ extern const uint bcmsdh_msglevel; typedef struct bcmsdh_info bcmsdh_info_t; typedef void (*bcmsdh_cb_fn_t)(void *); - #if defined(BT_OVER_SDIO) typedef enum { NO_HANG_STATE = 0, HANG_START_STATE = 1, HANG_RECOVERY_STATE = 2 } dhd_hang_state_t; -#endif +#endif // endif extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *sdioh, ulong *regsva); /** @@ -75,10 +74,6 @@ struct bcmsdh_info uint32 sbwad; /* Save backplane window address */ void *os_cxt; /* Pointer to per-OS private data */ bool force_sbwad_calc; /* forces calculation of sbwad instead of using cached value */ -#ifdef DHD_WAKE_STATUS - unsigned int total_wake_count; - int pkt_wake; -#endif /* DHD_WAKE_STATUS */ }; /* Detach - freeup resources allocated in attach */ @@ -100,7 +95,7 @@ extern void bcmsdh_intr_forward(void *sdh, bool pass); #if defined(DHD_DEBUG) /* Query pending interrupt status from the host controller */ extern bool bcmsdh_intr_pending(void *sdh); -#endif +#endif // endif /* Register a callback to be called if and when bcmsdh detects * device removal. No-op in the case of non-removable/hardwired devices. @@ -205,7 +200,7 @@ extern uint bcmsdh_query_iofnum(void *sdh); /* Miscellaneous knob tweaker. */ extern int bcmsdh_iovar_op(void *sdh, const char *name, - void *params, int plen, void *arg, int len, bool set); + void *params, uint plen, void *arg, uint len, bool set); /* Reset and reinitialize the device */ extern int bcmsdh_reset(bcmsdh_info_t *sdh); diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd_oo/include/bcmsdh_sdmmc.h index d9305e509464ed4a98c9403b806abbe9cd603e65..32160b1c0c6a9f6f35959cba22a6a88312c8d76e 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmsdh_sdmmc.h @@ -1,14 +1,14 @@ /* * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmsdh_sdmmc.h 687253 2017-02-28 09:33:36Z $ + * $Id: bcmsdh_sdmmc.h 690294 2017-03-15 12:33:14Z $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -59,7 +59,7 @@ /* private bus modes */ #define SDIOH_MODE_SD4 2 #define CLIENT_INTR 0x100 /* Get rid of this! */ -#define SDIOH_SDMMC_MAX_SG_ENTRIES (SDPCM_MAXGLOM_SIZE + 2) +#define SDIOH_SDMMC_MAX_SG_ENTRIES 32 struct sdioh_info { osl_t *osh; /* osh handler */ @@ -101,7 +101,6 @@ extern bool check_client_intr(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); - /************************************************************** * Internal interfaces: bcmsdh_sdmmc.c references to per-port code */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd_oo/include/bcmsdpcm.h index 6230047f4f3aa437a9463875ac1c09d079a99b6e..c5665f1ad7673c3eca114705d659cdf12505b142 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmsdpcm.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmsdpcm.h @@ -2,14 +2,14 @@ * Broadcom SDIO/PCMCIA * Software-specific definitions shared between device and host side * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: bcmsdpcm.h 614070 2016-01-21 00:55:57Z $ + * $Id: bcmsdpcm.h 700076 2017-05-17 14:42:22Z $ */ #ifndef _bcmsdpcm_h_ @@ -58,6 +58,8 @@ #define SMB_DATA_DSACK 0x200 /* host acking a deepsleep request */ #define SMB_DATA_DSNACK 0x400 /* host nacking a deepsleep request */ #endif /* DS_PROT */ +/* force a trap */ +#define SMB_DATA_TRAP 0x800 /* host forcing trap */ #define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ #define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ @@ -97,7 +99,6 @@ #define HMB_DATA_DSPROT_MASK 0xf00 #endif /* DS_PROT */ - #define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ #define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ @@ -131,7 +132,7 @@ /* Data Offset from SOF (HW Tag, SW Tag, Pad) */ #define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ -#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) +#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) #define SDPCM_DOFFSET_MASK 0xff000000 #define SDPCM_DOFFSET_SHIFT 24 @@ -296,6 +297,8 @@ typedef struct { uint32 device_fatal_logbuf_start; } sdpcm_shared_t; -extern sdpcm_shared_t sdpcm_shared; +/* Device F/W provides the following access function: + * sdpcm_shared_t *hnd_get_sdpcm_shared(void); + */ #endif /* _bcmsdpcm_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd_oo/include/bcmsdstd.h index ff3b0d1f2750c4cae75d1916edc9731c43678800..009535c16b8bdb2e858a2c34b8b76d5581bc1f30 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmsdstd.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmsdstd.h @@ -1,14 +1,14 @@ /* * 'Standard' SDIO HOST CONTROLLER driver * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: bcmsdstd.h 514727 2014-11-12 03:02:48Z $ + * $Id: bcmsdstd.h 663318 2016-10-04 19:02:16Z $ */ #ifndef _BCM_SD_STD_H #define _BCM_SD_STD_H @@ -84,7 +84,6 @@ extern void sdstd_osfree(sdioh_info_t *sd); #define sdstd_os_yield(sd) do {} while (0) #define RETRIES_SMALL 100 - #define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ #define USE_MULTIBLOCK 0x4 @@ -94,7 +93,6 @@ extern void sdstd_osfree(sdioh_info_t *sd); #define HC_INTR_RETUNING 0x1000 - #ifdef BCMSDIOH_TXGLOM /* Total glom pkt can not exceed 64K * need one more slot for glom padding packet @@ -107,7 +105,7 @@ typedef struct glom_buf { ulong dma_phys_arr[SDIOH_MAXGLOM_SIZE]; /* DMA_MAPed address of frames */ uint16 nbytes[SDIOH_MAXGLOM_SIZE]; /* Size of each frame */ } glom_buf_t; -#endif +#endif // endif struct sdioh_info { uint cfg_bar; /* pci cfg address for bar */ @@ -182,7 +180,7 @@ struct sdioh_info { #ifdef BCMSDIOH_TXGLOM glom_buf_t glom_info; /* pkt information used for glomming */ uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */ -#endif +#endif // endif }; #define DMA_MODE_NONE 0 @@ -206,12 +204,10 @@ struct sdioh_info { #define CHECK_TUNING_PRE_DATA 1 #define CHECK_TUNING_POST_DATA 2 - #ifdef DHD_DEBUG #define SD_DHD_DISABLE_PERIODIC_TUNING 0x01 #define SD_DHD_ENABLE_PERIODIC_TUNING 0x00 -#endif - +#endif // endif /************************************************************ * Internal interfaces: per-port references into bcmsdstd.c @@ -234,7 +230,6 @@ extern void sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err); /* Wait for specified interrupt and error bits to be set */ extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err); - /************************************************************** * Internal interfaces: bcmsdstd.c references to per-port code */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmtcp.h b/drivers/net/wireless/bcmdhd_oo/include/bcmtcp.h index 4d40948759d63bd0fbf5c6ae519e3ccb97fe6d57..dd8b9c970b764c132d99cb1ee3f87e43770f8a09 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmtcp.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmtcp.h @@ -1,14 +1,14 @@ /* * Fundamental constants relating to TCP Protocol * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,12 +32,11 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include - #define TCP_SRC_PORT_OFFSET 0 /* TCP source port offset */ #define TCP_DEST_PORT_OFFSET 2 /* TCP dest port offset */ #define TCP_SEQ_NUM_OFFSET 4 /* TCP sequence number offset */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmtlv.h b/drivers/net/wireless/bcmdhd_oo/include/bcmtlv.h new file mode 100644 index 0000000000000000000000000000000000000000..7f8cb99e320e7eaec15565099cfeb7d45c1c67bd --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmtlv.h @@ -0,0 +1,334 @@ +/* + * TLV and XTLV support + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: $ + */ + +#ifndef _bcmtlv_h_ +#define _bcmtlv_h_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* begin tlvs - used in 802.11 IEs etc. */ + +/* type(aka id)/length/value buffer triple */ +typedef struct bcm_tlv { + uint8 id; + uint8 len; + uint8 data[1]; +} bcm_tlv_t; + +/* size of tlv including data */ +#define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0) + +/* get next tlv - no length checks */ +#define BCM_TLV_NEXT(_tlv) (bcm_tlv_t *)((uint8 *)(_tlv)+ BCM_TLV_SIZE(_tlv)) + +/* tlv length is restricted to 1 byte */ +#define BCM_TLV_MAX_DATA_SIZE (255) + +/* tlv header - two bytes */ +#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data)) + +/* Check that bcm_tlv_t fits into the given buffer len */ +#define bcm_valid_tlv(elt, buflen) (\ + ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \ + ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len))) + +/* type(aka id)/length/ext/value buffer */ +typedef struct bcm_tlv_ext { + uint8 id; + uint8 len; + uint8 ext; + uint8 data[1]; +} bcm_tlv_ext_t; + +/* get next tlv_ext - no length checks */ +#define BCM_TLV_EXT_NEXT(_tlv_ext) \ + (bcm_tlv_ext_t *)((uint8 *)(_tlv_ext)+ BCM_TLV_EXT_SIZE(_tlv_ext)) + +/* tlv_ext length is restricted to 1 byte */ +#define BCM_TLV_EXT_MAX_DATA_SIZE (254) + +/* tlv_ext header - three bytes */ +#define BCM_TLV_EXT_HDR_SIZE (OFFSETOF(bcm_tlv_ext_t, data)) + +/* size of tlv_ext including data */ +#define BCM_TLV_EXT_SIZE(_tlv_ext) (BCM_TLV_EXT_HDR_SIZE + (_tlv_ext)->len) + +/* find the next tlv */ +bcm_tlv_t *bcm_next_tlv(const bcm_tlv_t *elt, int *buflen); + +/* find the tlv for a given id */ +bcm_tlv_t *bcm_parse_tlvs(const void *buf, int buflen, uint key); + +/* + * Traverse tlvs and return pointer to the first tlv that + * matches the key. Return NULL if not found or tlv len < min_bodylen + */ +bcm_tlv_t *bcm_parse_tlvs_min_bodylen(const void *buf, int buflen, uint key, int min_bodylen); + +/* parse tlvs for dot11 - same as parse_tlvs but supports 802.11 id extension */ +bcm_tlv_t *bcm_parse_tlvs_dot11(const void *buf, int buflen, uint key, bool id_ext); + +/* same as parse_tlvs, but stops when found id > key */ +const bcm_tlv_t *bcm_parse_ordered_tlvs(const void *buf, int buflen, uint key); + +/* find a tlv with DOT11_MNG_PROPR_ID as id, and the given oui and type */ + bcm_tlv_t *bcm_find_vendor_ie(const void *tlvs, int tlvs_len, const char *voui, + uint8 *type, int type_len); + +/* write tlv at dst and return next tlv ptr */ +uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst); + +/* write tlv_ext at dst and return next tlv ptr */ +uint8 *bcm_write_tlv_ext(uint8 type, uint8 ext, const void *data, uint8 datalen, uint8 *dst); + +/* write tlv at dst if space permits and return next tlv ptr */ +uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, + int dst_maxlen); + +/* copy a tlv and return next tlv ptr */ +uint8 *bcm_copy_tlv(const void *src, uint8 *dst); + +/* copy a tlv if space permits and return next tlv ptr */ +uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen); + +/* end tlvs */ + +/* begin xtlv - used for iovars, nan attributes etc. */ + +/* bcm type(id), length, value with w/16 bit id/len. The structure below + * is nominal, and is used to support variable length id and type. See + * xtlv options below. + */ +typedef struct bcm_xtlv { + uint16 id; + uint16 len; + uint8 data[1]; +} bcm_xtlv_t; + +/* xtlv options */ +#define BCM_XTLV_OPTION_NONE 0x0000 +#define BCM_XTLV_OPTION_ALIGN32 0x0001 /* 32bit alignment of type.len.data */ +#define BCM_XTLV_OPTION_IDU8 0x0002 /* shorter id */ +#define BCM_XTLV_OPTION_LENU8 0x0004 /* shorted length */ +typedef uint16 bcm_xtlv_opts_t; + +/* header size. depends on options. Macros names ending w/ _EX are where + * options are explcitly specified that may be less common. The ones + * without use default values that correspond to ...OPTION_NONE + */ + +/* xtlv header size depends on options */ +#define BCM_XTLV_HDR_SIZE 4 +#define BCM_XTLV_HDR_SIZE_EX(_opts) bcm_xtlv_hdr_size(_opts) + +/* note: xtlv len only stores the value's length without padding */ +#define BCM_XTLV_LEN(_elt) ltoh16_ua(&(_elt)->len) +#define BCM_XTLV_LEN_EX(_elt, _opts) bcm_xtlv_len(_elt, _opts) + +#define BCM_XTLV_ID(_elt) ltoh16_ua(&(_elt)->id) +#define BCM_XTLV_ID_EX(_elt, _opts) bcm_xtlv_id(_elt, _opts) + +/* entire size of the XTLV including header, data, and optional padding */ +#define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts) +#define BCM_XTLV_SIZE_EX(_elt, _opts) bcm_xtlv_size(_elt, _opts) + +/* max xtlv data size */ +#define BCM_XTLV_MAX_DATA_SIZE 65535 +#define BCM_XTLV_MAX_DATA_SIZE_EX(_opts) ((_opts & BCM_XTLV_OPTION_LENU8) ? \ + 255 : 65535) + +/* descriptor of xtlv data, packing(src) and unpacking(dst) support */ +typedef struct { + uint16 type; + uint16 len; + void *ptr; /* ptr to memory location */ +} xtlv_desc_t; + +/* xtlv buffer - packing/unpacking support */ +struct bcm_xtlvbuf { + bcm_xtlv_opts_t opts; + uint16 size; + uint8 *head; /* point to head of buffer */ + uint8 *buf; /* current position of buffer */ + /* allocated buffer may follow, but not necessarily */ +}; +typedef struct bcm_xtlvbuf bcm_xtlvbuf_t; + +/* valid xtlv ? */ +bool bcm_valid_xtlv(const bcm_xtlv_t *elt, int buf_len, bcm_xtlv_opts_t opts); + +/* return the next xtlv element, and update buffer len (remaining). Buffer length + * updated includes padding as specified by options + */ +bcm_xtlv_t *bcm_next_xtlv(const bcm_xtlv_t *elt, int *buf_len, bcm_xtlv_opts_t opts); + +/* initialize an xtlv buffer. Use options specified for packing/unpacking using + * the buffer. Caller is responsible for allocating both buffers. + */ +int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, + bcm_xtlv_opts_t opts); + +/* length of data in the xtlv buffer */ +uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf); + +/* remaining space in the xtlv buffer */ +uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf); + +/* write ptr */ +uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf); + +/* head */ +uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf); + +/* put a data buffer into xtlv */ +int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const uint8 *data, int n); + +/* put one or more u16 elts into xtlv */ +int bcm_xtlv_put16(bcm_xtlvbuf_t *tbuf, uint16 type, const uint16 *data, int n); + +/* put one or more u32 elts into xtlv */ +int bcm_xtlv_put32(bcm_xtlvbuf_t *tbuf, uint16 type, const uint32 *data, int n); + +/* put one or more u64 elts into xtlv */ +int bcm_xtlv_put64(bcm_xtlvbuf_t *tbuf, uint16 type, const uint64 *data, int n); + +/* note: there are no get equivalent of integer unpacking, becasuse bcmendian.h + * can be used directly using pointers returned in the buffer being processed. + */ + +/* unpack a single xtlv entry, advances buffer and copies data to dst_data on match + * type and length match must be exact + */ +int bcm_unpack_xtlv_entry(const uint8 **buf, uint16 expected_type, uint16 expected_len, + uint8 *dst_data, bcm_xtlv_opts_t opts); + +/* packs an xtlv into buffer, and advances buffer, decreements buffer length. + * buffer length is checked and must be >= size of xtlv - otherwise BCME_BADLEN + */ +int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len, + const uint8 *src_data, bcm_xtlv_opts_t opts); + +/* accessors and lengths for element given options */ +int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); +int bcm_xtlv_hdr_size(bcm_xtlv_opts_t opts); +int bcm_xtlv_len(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); +int bcm_xtlv_id(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); +int bcm_xtlv_size_for_data(int dlen, bcm_xtlv_opts_t opts); + +/* compute size needed for number of tlvs whose total data len is given */ +#define BCM_XTLV_SIZE_FOR_TLVS(_data_len, _num_tlvs, _opts) (\ + bcm_xtlv_size_for_data(_data_len, _opts) + (\ + (_num_tlvs) * BCM_XTLV_HDR_SIZE_EX(_opts))) + +/* unsafe copy xtlv */ +#define BCM_XTLV_BCOPY(_src, _dst, _opts) \ + bcm_xtlv_bcopy(_src, _dst, BCM_XTLV_MAX_DATA_SIZE_EX(_opts), \ + BCM_XTLV_MAX_DATA_SIZE_EX(_opts), _opts) + +/* copy xtlv - note: src->dst bcopy order - to be compatible w/ tlv version */ +bcm_xtlv_t* bcm_xtlv_bcopy(const bcm_xtlv_t *src, bcm_xtlv_t *dst, + int src_buf_len, int dst_buf_len, bcm_xtlv_opts_t opts); + +/* callback for unpacking xtlv from a buffer into context. */ +typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, const uint8 *buf, + uint16 type, uint16 len); + +/* unpack a tlv buffer using buffer, options, and callback */ +int bcm_unpack_xtlv_buf(void *ctx, const uint8 *buf, uint16 buflen, + bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn); + +/* unpack a set of tlvs from the buffer using provided xtlv descriptors */ +int bcm_unpack_xtlv_buf_to_mem(uint8 *buf, int *buflen, xtlv_desc_t *items, + bcm_xtlv_opts_t opts); + +/* pack a set of tlvs into buffer using provided xtlv descriptors */ +int bcm_pack_xtlv_buf_from_mem(uint8 **buf, uint16 *buflen, + const xtlv_desc_t *items, bcm_xtlv_opts_t opts); + +/* return data pointer and data length of a given id from xtlv buffer + * data_len may be NULL + */ +const uint8* bcm_get_data_from_xtlv_buf(const uint8 *tlv_buf, uint16 buflen, + uint16 id, uint16 *datalen, bcm_xtlv_opts_t opts); + +/* callback to return next tlv id and len to pack, if there is more tlvs to come and + * options e.g. alignment + */ +typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len); + +/* callback to pack the tlv into length validated buffer */ +typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx, + uint16 tlv_id, uint16 tlv_len, uint8* buf); + +/* pack a set of tlvs into buffer using get_next to interate */ +int bcm_pack_xtlv_buf(void *ctx, uint8 *tlv_buf, uint16 buflen, + bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next, + bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen); + +/* pack an xtlv. does not do any error checking. if data is not NULL + * data of given length is copied to buffer (xtlv) + */ +void bcm_xtlv_pack_xtlv(bcm_xtlv_t *xtlv, uint16 type, uint16 len, + const uint8 *data, bcm_xtlv_opts_t opts); + +/* unpack an xtlv and return ptr to data, and data length */ +void bcm_xtlv_unpack_xtlv(const bcm_xtlv_t *xtlv, uint16 *type, uint16 *len, + const uint8 **data, bcm_xtlv_opts_t opts); + +/* end xtlvs */ + +/* length value pairs */ +struct bcm_xlv { + uint16 len; + uint8 data[1]; +}; +typedef struct bcm_xlv bcm_xlv_t; + +struct bcm_xlvp { + uint16 len; + uint8 *data; +}; +typedef struct bcm_xlvp bcm_xlvp_t; + +struct bcm_const_xlvp { + uint16 len; + const uint8 *data; +}; +typedef struct bcm_const_xlvp bcm_const_xlvp_t; + +/* end length value pairs */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _bcmtlv_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/bcmutils.h b/drivers/net/wireless/bcmdhd_oo/include/bcmutils.h index ba6ee957d160b634e0b674190d5364cbb86b092b..5e437e65bf4aaf27445ec67088222e760ebf0c46 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd_oo/include/bcmutils.h @@ -1,14 +1,14 @@ /* * Misc useful os-independent macros and functions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,20 +24,24 @@ * * <> * - * $Id: bcmutils.h 735359 2017-12-08 10:56:04Z $ + * $Id: bcmutils.h 738149 2017-12-27 07:54:37Z $ */ #ifndef _bcmutils_h_ #define _bcmutils_h_ +#include #ifdef __cplusplus extern "C" { -#endif - +#endif // endif #define bcm_strncpy_s(dst, noOfElements, src, count) strncpy((dst), (src), (count)) +#ifdef FREEBSD +#define bcm_strncat_s(dst, noOfElements, src, count) strcat((dst), (src)) +#else #define bcm_strncat_s(dst, noOfElements, src, count) strncat((dst), (src), (count)) +#endif /* FREEBSD */ #define bcm_snprintf_s snprintf #define bcm_sprintf_s snprintf @@ -110,12 +114,12 @@ struct bcmstrbuf { * and take appropriate error action if 'exp' is still true. */ #ifndef SPINWAIT_POLL_PERIOD -#define SPINWAIT_POLL_PERIOD 10 -#endif +#define SPINWAIT_POLL_PERIOD 10U +#endif // endif #define SPINWAIT(exp, us) { \ - uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1); \ - while ((exp) && (countdown >= SPINWAIT_POLL_PERIOD)) { \ + uint countdown = (us) + (SPINWAIT_POLL_PERIOD - 1U); \ + while (((exp) != 0) && (uint)(countdown >= SPINWAIT_POLL_PERIOD)) { \ OSL_DELAY(SPINWAIT_POLL_PERIOD); \ countdown -= SPINWAIT_POLL_PERIOD; \ } \ @@ -129,6 +133,10 @@ extern int ether_isbcast(const void *ea); extern int ether_isnulladdr(const void *ea); #define UP_TABLE_MAX ((IPV4_TOS_DSCP_MASK >> IPV4_TOS_DSCP_SHIFT) + 1) /* 64 max */ +#define CORE_SLAVE_PORT_0 0 +#define CORE_SLAVE_PORT_1 1 +#define CORE_BASE_ADDR_0 0 +#define CORE_BASE_ADDR_1 1 /* externs */ /* packet */ @@ -137,7 +145,6 @@ extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); 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 *pktdataoffset(osl_t *osh, void *p, uint offset); extern void *pktoffset(osl_t *osh, void *p, uint offset); @@ -181,8 +188,10 @@ extern int bcm_atoipv4(const char *p, struct ipv4_addr *ip); extern void bcm_mdelay(uint ms); /* variable access */ #if defined(BCM_RECLAIM) +extern bool _nvram_reclaim_enb; +#define NVRAM_RECLAIM_ENAB() (_nvram_reclaim_enb) #define NVRAM_RECLAIM_CHECK(name) \ - if (bcm_attach_part_reclaimed == TRUE) { \ + if (NVRAM_RECLAIM_ENAB() && (bcm_attach_part_reclaimed == TRUE)) { \ *(char*) 0 = 0; /* TRAP */ \ return NULL; \ } @@ -194,6 +203,16 @@ extern char *getvar(char *vars, const char *name); extern int getintvar(char *vars, const char *name); extern int getintvararray(char *vars, const char *name, int index); extern int getintvararraysize(char *vars, const char *name); + +/* Read an array of values from a possibly slice-specific nvram string */ +extern int get_uint8_vararray_slicespecific(osl_t *osh, char *vars, char *vars_table_accessor, + const char* name, uint8* dest_array, uint dest_size); +extern int get_int16_vararray_slicespecific(osl_t *osh, char *vars, char *vars_table_accessor, + const char* name, int16* dest_array, uint dest_size); +/* Prepend a slice-specific accessor to an nvram string name */ +extern int get_slicespecific_var_name(osl_t *osh, char *vars_table_accessor, + const char *name, char **name_out); + extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); #define bcm_perf_enable() #define bcmstats(fmt) @@ -257,12 +276,13 @@ typedef struct wlc_ioctl_cmd { #if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); -#endif +#endif // endif #endif /* BCMDRIVER */ /* string */ extern int bcm_atoi(const char *s); extern ulong bcm_strtoul(const char *cp, char **endp, uint base); +extern uint64 bcm_strtoull(const char *cp, char **endp, uint base); extern char *bcmstrstr(const char *haystack, const char *needle); extern char *bcmstrnstr(const char *s, uint s_len, const char *substr, uint substr_len); extern char *bcmstrcat(char *dest, const char *src); @@ -308,9 +328,15 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); /* ** driver/apps-shared section ** */ -#define BCME_STRLEN 64 /* Max string length for BCM errors */ -#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) +#define BCME_STRLEN 64 /* Max string length for BCM errors */ +#define VALID_BCMERROR(e) valid_bcmerror(e) +#ifdef DBG_BUS +/** tracks non typical execution paths, use gdb with arm sim + firmware dump to read counters */ +#define DBG_BUS_INC(s, cnt) ((s)->dbg_bus->cnt++) +#else +#define DBG_BUS_INC(s, cnt) +#endif /* DBG_BUS */ /* * error codes could be added but the defined ones shouldn't be changed/deleted @@ -362,7 +388,7 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); #define BCME_RXFAIL -39 /* RX failure */ #define BCME_NODEVICE -40 /* Device not present */ #define BCME_NMODE_DISABLED -41 /* NMODE disabled */ -#define BCME_NONRESIDENT -42 /* access to nonresident overlay */ +#define BCME_HOFFLOAD_RESIDENT -42 /* offload resident */ #define BCME_SCANREJECT -43 /* reject scan request */ #define BCME_USAGE_ERROR -44 /* WLCMD usage error */ #define BCME_IOCTL_ERROR -45 /* WLCMD ioctl error */ @@ -381,7 +407,14 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); #define BCME_FRAG_Q_FAILED -58 /* queueing 80211 frag failedi */ #define BCME_GET_AF_FAILED -59 /* Get p2p AF pkt failed */ #define BCME_MSCH_NOTREADY -60 /* scheduler not ready */ -#define BCME_LAST BCME_MSCH_NOTREADY +#define BCME_IOV_LAST_CMD -61 /* last batched iov sub-command */ +#define BCME_MINIPMU_CAL_FAIL -62 /* MiniPMU cal failed */ +#define BCME_RCAL_FAIL -63 /* Rcal failed */ +#define BCME_LPF_RCCAL_FAIL -64 /* RCCAL failed */ +#define BCME_DACBUF_RCCAL_FAIL -65 /* RCCAL failed */ +#define BCME_VCOCAL_FAIL -66 /* VCOCAL failed */ +#define BCME_BANDLOCKED -67 /* interface is restricted to a band */ +#define BCME_LAST BCME_BANDLOCKED #define BCME_NOTENABLED BCME_DISABLED @@ -393,7 +426,7 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); #define BCME_IOCTL_PATCH_UNSUPPORTED -9999 #if (BCME_LAST <= BCME_IOCTL_PATCH_UNSUPPORTED) #error "BCME_LAST <= BCME_IOCTL_PATCH_UNSUPPORTED" -#endif +#endif // endif /* These are collection of BCME Error strings */ #define BCMERRSTRINGTABLE { \ @@ -439,7 +472,7 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); "RX Failure", \ "Device Not Present", \ "NMODE Disabled", \ - "Nonresident overlay access", \ + "Host Offload in device", \ "Scan Rejected", \ "WLCMD usage error", \ "WLCMD ioctl error", \ @@ -458,6 +491,13 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); "FRAG Q FAILED", \ "GET ActionFrame failed", \ "scheduler not ready", \ + "Last IOV batched sub-cmd", \ + "Mini PMU Cal failed", \ + "R-cal failed", \ + "LPF RC Cal failed", \ + "DAC buf RC Cal failed", \ + "VCO Cal failed", \ + "band locked", \ } #ifndef ABS @@ -526,13 +566,25 @@ int bcmstrnicmp(const char* s1, const char* s2, int cnt); #define CONTAINEROF(ptr, type, member) ((type *)((char *)(ptr) - OFFSETOF(type, member))) #endif /* CONTAINEROF */ +/* substruct size up to and including a member of the struct */ +#ifndef STRUCT_SIZE_THROUGH +#define STRUCT_SIZE_THROUGH(sptr, fname) \ + (((uint8*)&((sptr)->fname) - (uint8*)(sptr)) + sizeof((sptr)->fname)) +#endif // endif + +/* Extracting the size of element in a structure */ +#define SIZE_OF(type, field) sizeof(((type *)0)->field) + #ifndef ARRAYSIZE #define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0])) -#endif +#endif // endif #ifndef ARRAYLAST /* returns pointer to last array element */ #define ARRAYLAST(a) (&a[ARRAYSIZE(a)-1]) -#endif +#endif // endif + +/* Calculates the required pad size. This is mainly used in register structures */ +#define PADSZ(start, end) ((((end) - (start)) / 4) + 1) /* Reference a function; used to prevent a static function from being optimized out */ extern void *_bcmutils_dummy_fn; @@ -553,9 +605,23 @@ extern bool isclr(const void *array, uint bit); #define clrbit(a, i) (((uint8 *)a)[(i) / NBBY] &= ~(1 << ((i) % NBBY))) #define isset(a, i) (((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) #define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) -#endif +#endif // endif #endif /* setbit */ + +/* read/write/clear field in a consecutive bits in an octet array. + * 'addr' is the octet array's start byte address + * 'size' is the octet array's byte size + * 'stbit' is the value's start bit offset + * 'nbits' is the value's bit size + * This set of utilities are for convenience. Don't use them + * in time critical/data path as there's a great overhead in them. + */ +void setbits(uint8 *addr, uint size, uint stbit, uint nbits, uint32 val); +uint32 getbits(const uint8 *addr, uint size, uint stbit, uint nbits); +#define clrbits(addr, size, stbit, nbits) setbits(addr, size, stbit, nbits, 0) + extern void set_bitrange(void *array, uint start, uint end, uint maxbit); +extern int bcm_find_fsb(uint32 num); #define isbitset(a, i) (((a) & (1 << (i))) != 0) @@ -658,6 +724,9 @@ DECLARE_MAP_API(8, 2, 3, 3U, 0x00FF) /* setbit8() and getbit8() */ #define MACOUIDBG "%02x:%x:%02x" #define MACOUI2STRDBG(ea) (ea)[0], (ea)[1] & 0xf, (ea)[2] +#define MACOUI "%02x:%02x:%02x" +#define MACOUI2STR(ea) (ea)[0], (ea)[1], (ea)[2] + /* bcm_format_flags() bit description structure */ typedef struct bcm_bit_desc { uint32 bit; @@ -691,7 +760,7 @@ xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) if ( #ifdef __i386__ 1 || -#endif +#endif // endif (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { /* ARM CM3 rel time: 1229 (727 if alignment check could be omitted) */ /* x86 supports unaligned. This version runs 6x-9x faster on x86. */ @@ -709,9 +778,9 @@ xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) /* externs */ /* crc */ -extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); -extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); -extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); +uint8 hndcrc8(const uint8 *p, uint nbytes, uint8 crc); +uint16 hndcrc16(const uint8 *p, uint nbytes, uint16 crc); +uint32 hndcrc32(const uint8 *p, uint nbytes, uint32 crc); /* format/print */ #if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ @@ -720,7 +789,10 @@ extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len); /* print out which bits in flags are set */ extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); -#endif +/* print out whcih bits in octet array 'addr' are set. bcm_bit_desc_t:bit is a bit offset. */ +int bcm_format_octets(const bcm_bit_desc_t *bd, uint bdsz, + const uint8 *addr, uint size, char *buf, int len); +#endif // endif extern int bcm_format_hex(char *str, const void *bytes, int len); @@ -728,149 +800,7 @@ extern const char *bcm_crypto_algo_name(uint algo); extern char *bcm_chipname(uint chipid, char *buf, uint len); extern char *bcm_brev_str(uint32 brev, char *buf); extern void printbig(char *buf); -extern void prhex(const char *msg, volatile uchar *buf, uint len); - -/* IE parsing */ - -/* packing is required if struct is passed across the bus */ -#include -/* tag_ID/length/value_buffer tuple */ -typedef struct bcm_tlv { - uint8 id; - uint8 len; - uint8 data[1]; -} bcm_tlv_t; - -#define BCM_TLV_SIZE(_tlv) ((_tlv) ? (OFFSETOF(bcm_tlv_t, data) + (_tlv)->len) : 0) - -#define BCM_XTLV_TAG_LEN_SIZE 4 - -/* bcm tlv w/ 16 bit id/len */ -typedef BWL_PRE_PACKED_STRUCT struct bcm_xtlv { - uint16 id; - uint16 len; - uint8 data[1]; -} BWL_POST_PACKED_STRUCT bcm_xtlv_t; -#include - - -/* descriptor of xtlv data src or dst */ -typedef struct { - uint16 type; - uint16 len; - void *ptr; /* ptr to memory location */ -} xtlv_desc_t; - -/* xtlv options */ -#define BCM_XTLV_OPTION_NONE 0x0000 -#define BCM_XTLV_OPTION_ALIGN32 0x0001 - -typedef uint16 bcm_xtlv_opts_t; -struct bcm_xtlvbuf { - bcm_xtlv_opts_t opts; - uint16 size; - uint8 *head; /* point to head of buffer */ - uint8 *buf; /* current position of buffer */ - /* allocated buffer may follow, but not necessarily */ -}; -typedef struct bcm_xtlvbuf bcm_xtlvbuf_t; - -#define BCM_TLV_MAX_DATA_SIZE (255) -#define BCM_XTLV_MAX_DATA_SIZE (65535) -#define BCM_TLV_HDR_SIZE (OFFSETOF(bcm_tlv_t, data)) - -#define BCM_XTLV_HDR_SIZE (OFFSETOF(bcm_xtlv_t, data)) -/* LEN only stores the value's length without padding */ -#define BCM_XTLV_LEN(elt) ltoh16_ua(&(elt->len)) -#define BCM_XTLV_ID(elt) ltoh16_ua(&(elt->id)) -/* entire size of the XTLV including header, data, and optional padding */ -#define BCM_XTLV_SIZE(elt, opts) bcm_xtlv_size(elt, opts) -#define bcm_valid_xtlv(elt, buflen, opts) (elt && ((int)(buflen) >= (int)BCM_XTLV_SIZE(elt, opts))) - -/* Check that bcm_tlv_t fits into the given buflen */ -#define bcm_valid_tlv(elt, buflen) (\ - ((int)(buflen) >= (int)BCM_TLV_HDR_SIZE) && \ - ((int)(buflen) >= (int)(BCM_TLV_HDR_SIZE + (elt)->len))) - - -extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); -extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); -extern bcm_tlv_t *bcm_parse_tlvs_min_bodylen(void *buf, int buflen, uint key, int min_bodylen); -extern bcm_tlv_t *bcm_parse_tlvs_dot11(void *buf, int buflen, uint key, bool id_ext); - -extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); - -extern bcm_tlv_t *bcm_find_vendor_ie(void *tlvs, int tlvs_len, const char *voui, uint8 *type, - int type_len); - -extern uint8 *bcm_write_tlv(int type, const void *data, int datalen, uint8 *dst); -extern uint8 *bcm_write_tlv_safe(int type, const void *data, int datalen, uint8 *dst, - int dst_maxlen); - -extern uint8 *bcm_copy_tlv(const void *src, uint8 *dst); -extern uint8 *bcm_copy_tlv_safe(const void *src, uint8 *dst, int dst_maxlen); - -/* xtlv */ - -/* return the next xtlv element, and update buffer len (remaining). Buffer length - * updated includes padding as specified by options - */ -extern bcm_xtlv_t *bcm_next_xtlv(bcm_xtlv_t *elt, int *buflen, bcm_xtlv_opts_t opts); - -/* initialize an xtlv buffer. Use options specified for packing/unpacking using - * the buffer. Caller is responsible for allocating both buffers. - */ -extern int bcm_xtlv_buf_init(bcm_xtlvbuf_t *tlv_buf, uint8 *buf, uint16 len, - bcm_xtlv_opts_t opts); - -extern uint16 bcm_xtlv_buf_len(struct bcm_xtlvbuf *tbuf); -extern uint16 bcm_xtlv_buf_rlen(struct bcm_xtlvbuf *tbuf); -extern uint8 *bcm_xtlv_buf(struct bcm_xtlvbuf *tbuf); -extern uint8 *bcm_xtlv_head(struct bcm_xtlvbuf *tbuf); -extern int bcm_xtlv_put_data(bcm_xtlvbuf_t *tbuf, uint16 type, const void *data, uint16 dlen); -extern int bcm_xtlv_put_8(bcm_xtlvbuf_t *tbuf, uint16 type, const int8 data); -extern int bcm_xtlv_put_16(bcm_xtlvbuf_t *tbuf, uint16 type, const int16 data); -extern int bcm_xtlv_put_32(bcm_xtlvbuf_t *tbuf, uint16 type, const int32 data); -extern int bcm_unpack_xtlv_entry(uint8 **buf, uint16 xpct_type, uint16 xpct_len, - void *dst, bcm_xtlv_opts_t opts); -extern int bcm_pack_xtlv_entry(uint8 **buf, uint16 *buflen, uint16 type, uint16 len, - void *src, bcm_xtlv_opts_t opts); -extern int bcm_xtlv_size(const bcm_xtlv_t *elt, bcm_xtlv_opts_t opts); - -/* callback for unpacking xtlv from a buffer into context. */ -typedef int (bcm_xtlv_unpack_cbfn_t)(void *ctx, uint8 *buf, uint16 type, uint16 len); - -/* unpack a tlv buffer using buffer, options, and callback */ -extern int bcm_unpack_xtlv_buf(void *ctx, uint8 *buf, uint16 buflen, - bcm_xtlv_opts_t opts, bcm_xtlv_unpack_cbfn_t *cbfn); - -/* unpack a set of tlvs from the buffer using provided xtlv desc */ -extern int bcm_unpack_xtlv_buf_to_mem(void *buf, int *buflen, xtlv_desc_t *items, - bcm_xtlv_opts_t opts); - -/* pack a set of tlvs into buffer using provided xtlv desc */ -extern int bcm_pack_xtlv_buf_from_mem(void **buf, uint16 *buflen, xtlv_desc_t *items, - bcm_xtlv_opts_t opts); - -/* return data pointer of a given ID from xtlv buffer - * xtlv data length is given to *datalen_out, if the pointer is valid - */ -extern void *bcm_get_data_from_xtlv_buf(uint8 *tlv_buf, uint16 buflen, uint16 id, - uint16 *datalen_out, bcm_xtlv_opts_t opts); - -/* callback to return next tlv id and len to pack, if there is more tlvs to come and - * options e.g. alignment - */ -typedef bool (*bcm_pack_xtlv_next_info_cbfn_t)(void *ctx, uint16 *tlv_id, uint16 *tlv_len); - -/* callback to pack the tlv into length validated buffer */ -typedef void (*bcm_pack_xtlv_pack_next_cbfn_t)(void *ctx, - uint16 tlv_id, uint16 tlv_len, uint8* buf); - -/* pack a set of tlvs into buffer using get_next to interate */ -int bcm_pack_xtlv_buf(void *ctx, void *tlv_buf, uint16 buflen, - bcm_xtlv_opts_t opts, bcm_pack_xtlv_next_info_cbfn_t get_next, - bcm_pack_xtlv_pack_next_cbfn_t pack_next, int *outlen); +extern void prhex(const char *msg, const uchar *buf, uint len); /* bcmerror */ extern const char *bcmerrorstr(int bcmerror); @@ -957,12 +887,6 @@ extern void bcm_object_trace_deinit(void); #define bcm_object_trace_deinit() #endif /* BCM_OBJECT_TRACE */ -/* calculate a * b + c */ -extern void bcm_uint64_multiple_add(uint32* r_high, uint32* r_low, uint32 a, uint32 b, uint32 c); -/* calculate a / b */ -extern void bcm_uint64_divide(uint32* r, uint32 a_high, uint32 a_low, uint32 b); - - /* Public domain bit twiddling hacks/utilities: Sean Eron Anderson */ /* Table driven count set bits. */ @@ -983,7 +907,6 @@ bcm_cntsetbits(const uint32 u32arg) return (_CSBTBL[p[0]] + _CSBTBL[p[1]] + _CSBTBL[p[2]] + _CSBTBL[p[3]]); } - static INLINE int /* C equivalent count of leading 0's in a u32 */ C_bcm_count_leading_zeros(uint32 u32arg) { @@ -994,17 +917,37 @@ C_bcm_count_leading_zeros(uint32 u32arg) return (32U - shifts); } -#ifdef BCM_ASLR_HEAP +/* the format of current TCM layout during boot + * + * Code Unused memory Random numbers Random number Magic number NVRAM NVRAM + * byte Count 0xFEEDC0DE Size + * |<-----Variable---->|<---Variable--->|<-----4 bytes-->|<---4 bytes---->|<---V--->|<--4B--->| + * |<------------- BCM_ENTROPY_HOST_MAXSIZE --------->| + */ + +/* The HOST need to provided 64 bytes (512 bits) entropy for the bcm SW RNG */ +#define BCM_ENTROPY_MAGIC_SIZE 4u +#define BCM_ENTROPY_COUNT_SIZE 4u +#define BCM_ENTROPY_SEED_NBYTES 64u +#define BCM_ENTROPY_NONCE_NBYTES 16u +#define BCM_ENTROPY_HOST_NBYTES (BCM_ENTROPY_SEED_NBYTES + BCM_ENTROPY_NONCE_NBYTES) +#define BCM_ENTROPY_HOST_MAXSIZE \ + (BCM_ENTROPY_MAGIC_SIZE + BCM_ENTROPY_COUNT_SIZE + BCM_ENTROPY_HOST_NBYTES) + +/* Keep BCM MAX_RAND NUMBERS definition for the current dongle image. It will be + * removed after the dongle image is updated to use the bcm RNG. + */ +#define BCM_MAX_RAND_NUMBERS 2u -#define BCM_NVRAM_OFFSET_TCM 4 -#define BCM_NVRAM_IMG_COMPRS_FACTOR 4 -#define BCM_RNG_SIGNATURE 0xFEEDC0DE +/* Constant for calculate the location of host entropy input */ +#define BCM_NVRAM_OFFSET_TCM 4u +#define BCM_NVRAM_IMG_COMPRS_FACTOR 4u +#define BCM_NVRAM_RNG_SIGNATURE 0xFEEDC0DEu typedef struct bcm_rand_metadata { uint32 signature; /* host fills it in, FW verfies before reading rand */ - uint32 count; /* number of 4byte wide random numbers */ + uint32 count; /* number of random numbers in bytes */ } bcm_rand_metadata_t; -#endif /* BCM_ASLR_HEAP */ #ifdef BCMDRIVER /* @@ -1081,7 +1024,6 @@ extern void bcm_mwbmap_show(struct bcm_mwbmap * mwbmap_hdl); extern void bcm_mwbmap_audit(struct bcm_mwbmap * mwbmap_hdl); /* End - Multiword bitmap based small Id allocator. */ - /* INTERFACE: Simple unique 16bit Id Allocator using a stack implementation. */ #define ID8_INVALID 0xFFu @@ -1113,23 +1055,6 @@ extern bool id16_map_audit(void * id16_map_hndl); /* End - Simple 16bit Id Allocator. */ #endif /* BCMDRIVER */ -extern void bcm_uint64_right_shift(uint32* r, uint32 a_high, uint32 a_low, uint32 b); - -void bcm_add_64(uint32* r_hi, uint32* r_lo, uint32 offset); -void bcm_sub_64(uint32* r_hi, uint32* r_lo, uint32 offset); - -uint64 fp_mult_64(uint64 val1, uint64 val2, uint8 nf1, uint8 nf2, uint8 nf_res); -uint8 fp_div_64(uint64 num, uint32 den, uint8 nf_num, uint8 nf_den, uint32 *div_out); -uint8 fp_calc_head_room_64(uint64 num); -uint8 fp_calc_head_room_32(uint32 num); -uint32 fp_round_64(uint64 num, uint8 rnd_pos); -uint32 fp_round_32(uint32 num, uint8 rnd_pos); -uint32 fp_floor_64(uint64 num, uint8 floor_pos); -uint32 fp_floor_32(uint32 num, uint8 floor_pos); -uint32 fp_ceil_64(uint64 num, uint8 ceil_pos); -uint64 bcm_shl_64(uint64 input, uint8 shift_amt); -uint64 bcm_shr_64(uint64 input, uint8 shift_amt); - #define MASK_32_BITS (~0) #define MASK_8_BITS ((1 << 8) - 1) @@ -1212,42 +1137,36 @@ dll_head_p(dll_t *list_p) return list_p->next_p; } - static INLINE dll_t * dll_tail_p(dll_t *list_p) { return (list_p)->prev_p; } - static INLINE dll_t * dll_next_p(dll_t *node_p) { return (node_p)->next_p; } - static INLINE dll_t * dll_prev_p(dll_t *node_p) { return (node_p)->prev_p; } - static INLINE bool dll_empty(dll_t *list_p) { return ((list_p)->next_p == (list_p)); } - static INLINE bool dll_end(dll_t *list_p, dll_t * node_p) { return (list_p == node_p); } - /* inserts the node new_p "after" the node at_p */ static INLINE void dll_insert(dll_t *new_p, dll_t * at_p) @@ -1270,7 +1189,6 @@ dll_prepend(dll_t *list_p, dll_t *node_p) dll_insert(node_p, list_p); } - /* deletes a node from any list that it "may" be in, if at all. */ static INLINE void dll_delete(dll_t *node_p) @@ -1297,6 +1215,8 @@ void dll_pool_free_tail(dll_pool_t * dll_pool_p, void * elem_p); typedef void (* dll_elem_dump)(void * elem_p); void dll_pool_detach(void * osh, dll_pool_t * pool, uint16 elems_max, uint16 elem_size); +int valid_bcmerror(int e); + /* calculate IPv4 header checksum * - input ip points to IP header in network order * - output cksum is in network order @@ -1317,7 +1237,7 @@ uint16 ipv6_tcp_hdr_cksum(uint8 *ipv6, uint8 *tcp, uint16 tcp_len); #ifdef __cplusplus } -#endif +#endif // endif /* #define DEBUG_COUNTER */ #ifdef DEBUG_COUNTER @@ -1331,7 +1251,6 @@ typedef struct _counter_tbl_t { bool enabled; /* Whether to enable printing log */ } counter_tbl_t; - void counter_printlog(counter_tbl_t *ctr_tbl); #endif /* DEBUG_COUNTER */ @@ -1339,9 +1258,9 @@ void counter_printlog(counter_tbl_t *ctr_tbl); #define CALL_SITE __builtin_return_address(0) #else #define CALL_SITE ((void*) 0) -#endif +#endif // endif #ifdef SHOW_LOGTRACE -#define TRACE_LOG_BUF_MAX_SIZE 1500 +#define TRACE_LOG_BUF_MAX_SIZE 1700 #define BUF_NOT_AVAILABLE 0 #define NEXT_BUF_NOT_AVAIL 1 #define NEXT_BUF_AVAIL 2 @@ -1353,4 +1272,52 @@ typedef struct trace_buf_info { } trace_buf_info_t; #endif /* SHOW_LOGTRACE */ +enum dump_dongle_e { + DUMP_DONGLE_COREREG = 0, + DUMP_DONGLE_D11MEM +}; + +typedef struct { + uint32 type; /**< specifies e.g dump of d11 memory, use enum dump_dongle_e */ + uint32 index; /**< iterator1, specifies core index or d11 memory index */ + uint32 offset; /**< iterator2, byte offset within register set or memory */ +} dump_dongle_in_t; + +typedef struct { + uint32 address; /**< e.g. backplane address of register */ + uint32 id; /**< id, e.g. core id */ + uint32 rev; /**< rev, e.g. core rev */ + uint32 n_bytes; /**< nbytes in array val[] */ + uint32 val[1]; /**< out: values that were read out of registers or memory */ +} dump_dongle_out_t; + +extern uint32 sqrt_int(uint32 value); + +#ifdef BCMDRIVER +/* structures and routines to process variable sized data */ +typedef struct var_len_data { + uint32 vlen; + uint8 *vdata; +} var_len_data_t; + +int bcm_vdata_alloc(osl_t *osh, var_len_data_t *vld, uint32 size); +int bcm_vdata_free(osl_t *osh, var_len_data_t *vld); +#endif /* BCMDRIVER */ + +/* Count the number of elements in an array that do not match the given value */ +extern int array_value_mismatch_count(uint8 value, uint8 *array, int array_size); +/* Count the number of non-zero elements in an uint8 array */ +extern int array_nonzero_count(uint8 *array, int array_size); +/* Count the number of non-zero elements in an int16 array */ +extern int array_nonzero_count_int16(int16 *array, int array_size); +/* Count the number of zero elements in an uint8 array */ +extern int array_zero_count(uint8 *array, int array_size); +/* Validate a uint8 ordered array. Assert if invalid. */ +extern int verify_ordered_array_uint8(uint8 *array, int array_size, uint8 range_lo, uint8 range_hi); +/* Validate a int16 configuration array that need not be zero-terminated. Assert if invalid. */ +extern int verify_ordered_array_int16(int16 *array, int array_size, int16 range_lo, int16 range_hi); +/* Validate all values in an array are in range */ +extern int verify_array_values(uint8 *array, int array_size, + int range_lo, int range_hi, bool zero_terminated); + #endif /* _bcmutils_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/brcm_nl80211.h b/drivers/net/wireless/bcmdhd_oo/include/brcm_nl80211.h index 84bfddabffddffec12c8856021ef2b4a359678b0..4f40db0247a99315cd4e80efb16990f4c98dbccd 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/brcm_nl80211.h +++ b/drivers/net/wireless/bcmdhd_oo/include/brcm_nl80211.h @@ -1,14 +1,14 @@ /* * Definitions for nl80211 vendor command/event access to host driver * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -40,7 +40,6 @@ enum wl_vendor_subcmd { BRCM_VENDOR_SCMD_BCM_STR }; - struct bcm_nlmsg_hdr { uint cmd; /* common ioctl definition */ int len; /* expected return buffer length */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/dhd_daemon.h b/drivers/net/wireless/bcmdhd_oo/include/dhd_daemon.h index 3a5141ab20947108191d337e5559af2f7213d303..06aa182bfbe0c6a875d10a17f498979bb765b0bc 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/dhd_daemon.h +++ b/drivers/net/wireless/bcmdhd_oo/include/dhd_daemon.h @@ -1,14 +1,14 @@ /* * Header file for DHD daemon to handle timeouts * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: dhd_daemon.h 671464 2016-11-22 06:15:32Z $ + * $Id: dhd_daemon.h 671442 2016-11-22 05:16:18Z $ */ #ifndef __BCM_DHDD_H__ diff --git a/drivers/net/wireless/bcmdhd_oo/include/dhdioctl.h b/drivers/net/wireless/bcmdhd_oo/include/dhdioctl.h index bcace743159e7c478f0b1762d874279814dad8fe..9aa35764e15ce9c0804d8ca66c32ddf65c0a74dd 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd_oo/include/dhdioctl.h @@ -5,14 +5,14 @@ * * Definitions subject to change without notice. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -20,7 +20,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. @@ -28,7 +28,7 @@ * * <> * - * $Id: dhdioctl.h 727682 2017-10-23 04:45:57Z $ + * $Id: dhdioctl.h 735118 2017-12-07 10:59:35Z $ */ #ifndef _dhdioctl_h_ @@ -36,7 +36,6 @@ #include - /* Linux network driver ioctl encoding */ typedef struct dhd_ioctl { uint32 cmd; /* common ioctl definition */ @@ -61,6 +60,36 @@ typedef enum { DMA_XFER_FAILED } dma_xfer_status_t; +typedef struct tput_test { + uint16 version; + uint16 length; + uint8 direction; + uint8 tput_test_running; + uint8 mac_sta[6]; + uint8 mac_ap[6]; + uint8 PAD[2]; + uint32 payload_size; + uint32 num_pkts; + uint32 timeout_ms; + uint32 flags; + + uint32 pkts_good; + uint32 pkts_bad; + uint32 pkts_cmpl; + uint64 time_ms; + uint64 tput_bps; +} tput_test_t; + +typedef enum { + TPUT_DIR_TX = 0, + TPUT_DIR_RX +} tput_dir_t; + +#define TPUT_TEST_T_VER 1 +#define TPUT_TEST_T_LEN 68 +#define TPUT_TEST_MIN_PAYLOAD_SIZE 16 +#define TPUT_TEST_USE_ETHERNET_HDR 0x1 +#define TPUT_TEST_USE_802_11_HDR 0x2 /* per-driver magic numbers */ #define DHD_IOCTL_MAGIC 0x00444944 @@ -119,7 +148,8 @@ typedef enum { #define DHD_ERROR_MEM_VAL 0x8000000 #define DHD_DNGL_IOVAR_SET_VAL 0x10000000 /**< logs the setting of dongle iovars */ #define DHD_LPBKDTDUMP_VAL 0x20000000 -#define DHD_ECNTR_VAL 0x40000000 +#define DHD_EVENT_MEM_VAL 0x40000000 +#define DHD_IOVAR_MEM_VAL 0x80000000 #ifdef SDTEST /* For pktgen iovar */ @@ -155,6 +185,49 @@ typedef struct dhd_pktgen { #define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change when idle */ #define DHD_IDLE_STOP (-1) /* Request SD clock be stopped (and use SD1 mode) */ +enum dhd_maclist_xtlv_type { + DHD_MACLIST_XTLV_R = 0x1, + DHD_MACLIST_XTLV_X = 0x2, + DHD_SVMPLIST_XTLV = 0x3 +}; +typedef struct _dhd_maclist_t { + uint16 version; /* Version */ + uint16 bytes_len; /* Total bytes length of lists, XTLV headers and paddings */ + uint8 plist[1]; /* Pointer to the first list */ +} dhd_maclist_t; + +typedef struct _dhd_pd11regs_param { + uint16 start_idx; + uint8 verbose; + uint8 pad; + uint8 plist[1]; +} dhd_pd11regs_param; + +typedef struct _dhd_pd11regs_buf { + uint16 idx; + uint8 pad[2]; + uint8 pbuf[1]; +} dhd_pd11regs_buf; + +/* BT logging and memory dump */ + +#define BT_LOG_BUF_MAX_SIZE (DHD_IOCTL_MAXLEN - (2 * sizeof(int))) +#define BT_LOG_BUF_NOT_AVAILABLE 0 +#define BT_LOG_NEXT_BUF_NOT_AVAIL 1 +#define BT_LOG_NEXT_BUF_AVAIL 2 +#define BT_LOG_NOT_READY 3 + +typedef struct bt_log_buf_info { + int availability; + int size; + char buf[BT_LOG_BUF_MAX_SIZE]; +} bt_log_buf_info_t; + +/* request BT memory in chunks */ +typedef struct bt_mem_req { + int offset; /* offset from BT memory start */ + int buf_size; /* buffer size per chunk */ +} bt_mem_req_t; #endif /* _dhdioctl_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/dnglevent.h b/drivers/net/wireless/bcmdhd_oo/include/dnglevent.h index 40a0047a6781c91964000f566ea35f852414b0bc..4919af769b15271accdba8c957a372c257eebc58 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/dnglevent.h +++ b/drivers/net/wireless/bcmdhd_oo/include/dnglevent.h @@ -1,14 +1,14 @@ /* * Broadcom Event protocol definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -41,7 +41,7 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif #include #include @@ -73,8 +73,11 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_dngl_socramind { } BWL_POST_PACKED_STRUCT bcm_dngl_socramind_t; /* SOCRAM_IND type tags */ -#define SOCRAM_IND_ASSERT_TAG 0x1 -#define SOCRAM_IND_TAG_HEALTH_CHECK 0x2 +typedef enum socram_ind_tag { + SOCRAM_IND_ASSERT_TAG = 1, + SOCRAM_IND_TAG_HEALTH_CHECK = 2 +} socram_ind_tag_t; + /* Health check top level module tags */ typedef BWL_PRE_PACKED_STRUCT struct bcm_dngl_healthcheck { uint16 top_module_tag; /* top level module tag */ @@ -90,11 +93,13 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_dngl_healthcheck { #define HEALTH_CHECK_PCIEDEV_FLAG_LINKDOWN_SHIFT 2 #define HEALTH_CHECK_PCIEDEV_FLAG_MSI_INT_SHIFT 3 #define HEALTH_CHECK_PCIEDEV_FLAG_NODS_SHIFT 4 +#define HEALTH_CHECK_PCIEDEV_FLAG_NO_HOST_WAKE_SHIFT 5 #define HEALTH_CHECK_PCIEDEV_FLAG_IN_D3 1 << HEALTH_CHECK_PCIEDEV_FLAG_IN_D3_SHIFT #define HEALTH_CHECK_PCIEDEV_FLAG_AER 1 << HEALTH_CHECK_PCIEDEV_FLAG_AER_SHIFT #define HEALTH_CHECK_PCIEDEV_FLAG_LINKDOWN 1 << HEALTH_CHECK_PCIEDEV_FLAG_LINKDOWN_SHIFT #define HEALTH_CHECK_PCIEDEV_FLAG_MSI_INT 1 << HEALTH_CHECK_PCIEDEV_FLAG_MSI_INT_SHIFT #define HEALTH_CHECK_PCIEDEV_FLAG_NODS 1 << HEALTH_CHECK_PCIEDEV_FLAG_NODS_SHIFT +#define HEALTH_CHECK_PCIEDEV_FLAG_NO_HOST_WAKE 1 << HEALTH_CHECK_PCIEDEV_FLAG_NO_HOST_WAKE_SHIFT /* PCIE Module TAGs */ #define HEALTH_CHECK_PCIEDEV_INDUCED_IND 0x1 #define HEALTH_CHECK_PCIEDEV_H2D_DMA_IND 0x2 @@ -114,6 +119,20 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_dngl_pcie_hc { uint32 pcie_config_regs[HC_PCIEDEV_CONFIG_REGLIST_MAX]; } BWL_POST_PACKED_STRUCT bcm_dngl_pcie_hc_t; +#ifdef HCHK_COMMON_SW_EVENT +/* Enumerating top level SW entities for use by health check */ +typedef enum { + HCHK_SW_ENTITY_UNDEFINED = 0, + HCHK_SW_ENTITY_PCIE = 1, + HCHK_SW_ENTITY_SDIO = 2, + HCHK_SW_ENTITY_USB = 3, + HCHK_SW_ENTITY_RTE = 4, + HCHK_SW_ENTITY_WL_PRIMARY = 5, /* WL instance 0 */ + HCHK_SW_ENTITY_WL_SECONDARY = 6, /* WL instance 1 */ + HCHK_SW_ENTITY_MAX +} hchk_sw_entity_t; +#endif /* HCHK_COMMON_SW_EVENT */ + /* This marks the end of a packed structure section. */ #include diff --git a/drivers/net/wireless/bcmdhd_oo/include/eapol.h b/drivers/net/wireless/bcmdhd_oo/include/eapol.h new file mode 100644 index 0000000000000000000000000000000000000000..fbe0c6c832ed8cfb03702e5b9015f8d9c17e9de3 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/eapol.h @@ -0,0 +1,218 @@ +/* + * 802.1x EAPOL definitions + * + * See + * IEEE Std 802.1X-2001 + * IEEE 802.1X RADIUS Usage Guidelines + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: eapol.h 716595 2017-08-18 21:43:55Z $ + */ + +#ifndef _eapol_h_ +#define _eapol_h_ + +#ifndef _TYPEDEFS_H_ +#include +#endif // endif + +/* This marks the start of a packed structure section. */ +#include + +#if !defined(BCMCRYPTO_COMPONENT) +#include +#endif /* !BCMCRYPTO_COMPONENT */ + +/* EAPOL for 802.3/Ethernet */ +typedef BWL_PRE_PACKED_STRUCT struct { + struct ether_header eth; /* 802.3/Ethernet header */ + unsigned char version; /* EAPOL protocol version */ + unsigned char type; /* EAPOL type */ + unsigned short length; /* Length of body */ + unsigned char body[1]; /* Body (optional) */ +} BWL_POST_PACKED_STRUCT eapol_header_t; + +#define EAPOL_HEADER_LEN 18 + +typedef struct { + unsigned char version; /* EAPOL protocol version */ + unsigned char type; /* EAPOL type */ + unsigned short length; /* Length of body */ +} eapol_hdr_t; + +#define EAPOL_HDR_LEN 4 + +/* EAPOL version */ +#define WPA2_EAPOL_VERSION 2 +#define WPA_EAPOL_VERSION 1 +#define LEAP_EAPOL_VERSION 1 +#define SES_EAPOL_VERSION 1 + +/* EAPOL types */ +#define EAP_PACKET 0 +#define EAPOL_START 1 +#define EAPOL_LOGOFF 2 +#define EAPOL_KEY 3 +#define EAPOL_ASF 4 + +/* EAPOL-Key types */ +#define EAPOL_RC4_KEY 1 +#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */ +#define EAPOL_WPA_KEY 254 /* WPA */ + +/* RC4 EAPOL-Key header field sizes */ +#define EAPOL_KEY_REPLAY_LEN 8 +#define EAPOL_KEY_IV_LEN 16 +#define EAPOL_KEY_SIG_LEN 16 + +/* RC4 EAPOL-Key */ +typedef BWL_PRE_PACKED_STRUCT struct { + unsigned char type; /* Key Descriptor Type */ + unsigned short length; /* Key Length (unaligned) */ + unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */ + unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */ + unsigned char index; /* Key Flags & Index */ + unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */ + unsigned char key[1]; /* Key (optional) */ +} BWL_POST_PACKED_STRUCT eapol_key_header_t; + +#define EAPOL_KEY_HEADER_LEN 44 + +/* RC4 EAPOL-Key flags */ +#define EAPOL_KEY_FLAGS_MASK 0x80 +#define EAPOL_KEY_BROADCAST 0 +#define EAPOL_KEY_UNICAST 0x80 + +/* RC4 EAPOL-Key index */ +#define EAPOL_KEY_INDEX_MASK 0x7f + +/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */ +#define EAPOL_AKW_BLOCK_LEN 8 +#define EAPOL_WPA_KEY_REPLAY_LEN 8 +#define EAPOL_WPA_KEY_NONCE_LEN 32 +#define EAPOL_WPA_KEY_IV_LEN 16 +#define EAPOL_WPA_KEY_RSC_LEN 8 +#define EAPOL_WPA_KEY_ID_LEN 8 +#define EAPOL_WPA_KEY_MIC_LEN 16 +#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + EAPOL_AKW_BLOCK_LEN) +#define EAPOL_WPA_MAX_KEY_SIZE 32 + +/* WPA EAPOL-Key */ +typedef BWL_PRE_PACKED_STRUCT struct { + unsigned char type; /* Key Descriptor Type */ + unsigned short key_info; /* Key Information (unaligned) */ + unsigned short key_len; /* Key Length (unaligned) */ + unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ + unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ + unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ + unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ + unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ + unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ + unsigned short data_len; /* Key Data Length */ + unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */ +} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t; + +#define EAPOL_WPA_KEY_LEN 95 + +/* WPA/802.11i/WPA2 KEY KEY_INFO bits */ +#define WPA_KEY_DESC_OSEN 0x0 +#define WPA_KEY_DESC_V1 0x01 +#define WPA_KEY_DESC_V2 0x02 +#define WPA_KEY_DESC_V3 0x03 +#define WPA_KEY_PAIRWISE 0x08 +#define WPA_KEY_INSTALL 0x40 +#define WPA_KEY_ACK 0x80 +#define WPA_KEY_MIC 0x100 +#define WPA_KEY_SECURE 0x200 +#define WPA_KEY_ERROR 0x400 +#define WPA_KEY_REQ 0x800 +#define WPA_KEY_DESC_VER(_ki) ((_ki) & 0x03u) + +#define WPA_KEY_DESC_V2_OR_V3 WPA_KEY_DESC_V2 + +/* WPA-only KEY KEY_INFO bits */ +#define WPA_KEY_INDEX_0 0x00 +#define WPA_KEY_INDEX_1 0x10 +#define WPA_KEY_INDEX_2 0x20 +#define WPA_KEY_INDEX_3 0x30 +#define WPA_KEY_INDEX_MASK 0x30 +#define WPA_KEY_INDEX_SHIFT 0x04 + +/* 802.11i/WPA2-only KEY KEY_INFO bits */ +#define WPA_KEY_ENCRYPTED_DATA 0x1000 + +/* Key Data encapsulation */ +typedef BWL_PRE_PACKED_STRUCT struct { + uint8 type; + uint8 length; + uint8 oui[3]; + uint8 subtype; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t; + +#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6 + +#define WPA2_KEY_DATA_SUBTYPE_GTK 1 +#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2 +#define WPA2_KEY_DATA_SUBTYPE_MAC 3 +#define WPA2_KEY_DATA_SUBTYPE_PMKID 4 +#define WPA2_KEY_DATA_SUBTYPE_IGTK 9 + +/* GTK encapsulation */ +typedef BWL_PRE_PACKED_STRUCT struct { + uint8 flags; + uint8 reserved; + uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE]; +} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t; + +#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2 + +#define WPA2_GTK_INDEX_MASK 0x03 +#define WPA2_GTK_INDEX_SHIFT 0x00 + +#define WPA2_GTK_TRANSMIT 0x04 + +/* IGTK encapsulation */ +typedef BWL_PRE_PACKED_STRUCT struct { + uint16 key_id; + uint8 ipn[6]; + uint8 key[EAPOL_WPA_MAX_KEY_SIZE]; +} BWL_POST_PACKED_STRUCT eapol_wpa2_key_igtk_encap_t; + +#define EAPOL_WPA2_KEY_IGTK_ENCAP_HDR_LEN 8 + +/* STAKey encapsulation */ +typedef BWL_PRE_PACKED_STRUCT struct { + uint8 reserved[2]; + uint8 mac[ETHER_ADDR_LEN]; + uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE]; +} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t; + +#define WPA2_KEY_DATA_PAD 0xdd + +/* This marks the end of a packed structure section. */ +#include + +#endif /* _eapol_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/epivers.h b/drivers/net/wireless/bcmdhd_oo/include/epivers.h index 3149f09a3c65af3863d2761203d6dbcc347ad871..59b58e35eb877c5a97b2da66b45010cfd00d8780 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/epivers.h +++ b/drivers/net/wireless/bcmdhd_oo/include/epivers.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -14,7 +14,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. @@ -29,23 +29,23 @@ #ifndef _epivers_h_ #define _epivers_h_ -#define EPI_MAJOR_VERSION 1 +#define EPI_MAJOR_VERSION 100 -#define EPI_MINOR_VERSION 77 +#define EPI_MINOR_VERSION 11 -#define EPI_RC_NUMBER 59 +#define EPI_RC_NUMBER 3 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 77, 59, 0 +#define EPI_VERSION 100, 11, 3, 0 -#define EPI_VERSION_NUM 0x014d3b00 +#define EPI_VERSION_NUM 0x640b0300 -#define EPI_VERSION_DEV 1.77.59 +#define EPI_VERSION_DEV 100.11.3 /* Driver Version String, ASCII, 32 chars max */ -#define EPI_VERSION_STR "1.77.59 (r)" +#define EPI_VERSION_STR "100.11.3 (r)" #endif /* _epivers_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/etd.h b/drivers/net/wireless/bcmdhd_oo/include/etd.h new file mode 100644 index 0000000000000000000000000000000000000000..2dfa10be495f44bcf3b3de5bc4347fb513720c25 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/etd.h @@ -0,0 +1,468 @@ +/* + * Extended Trap data component interface file. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: etd.h 730252 2017-11-06 12:25:27Z $ + */ + +#ifndef _ETD_H_ +#define _ETD_H_ + +#if defined(ETD) && !defined(WLETD) +#include +#endif // endif +#include +/* Tags for structures being used by etd info iovar. + * Related structures are defined in wlioctl.h. + */ +#define ETD_TAG_JOIN_CLASSIFICATION_INFO 10 /* general information about join request */ +#define ETD_TAG_JOIN_TARGET_CLASSIFICATION_INFO 11 /* per target (AP) join information */ +#define ETD_TAG_ASSOC_STATE 12 /* current state of the Device association state machine */ +#define ETD_TAG_CHANNEL 13 /* current channel on which the association was performed */ +#define ETD_TAG_TOTAL_NUM_OF_JOIN_ATTEMPTS 14 /* number of join attempts (bss_retries) */ + +#define PSMDBG_REG_READ_CNT_FOR_PSMWDTRAP_V1 3 +#define PSMDBG_REG_READ_CNT_FOR_PSMWDTRAP_V2 6 + +#ifndef _LANGUAGE_ASSEMBLY + +#define HND_EXTENDED_TRAP_VERSION 1 +#define HND_EXTENDED_TRAP_BUFLEN 512 + +typedef struct hnd_ext_trap_hdr { + uint8 version; /* Extended trap version info */ + uint8 reserved; /* currently unused */ + uint16 len; /* Length of data excluding this header */ + uint8 data[]; /* TLV data */ +} hnd_ext_trap_hdr_t; + +typedef enum { + TAG_TRAP_SIGNATURE = 1, /* Processor register dumps */ + TAG_TRAP_STACK = 2, /* Processor stack dump (possible code locations) */ + TAG_TRAP_MEMORY = 3, /* Memory subsystem dump */ + TAG_TRAP_DEEPSLEEP = 4, /* Deep sleep health check failures */ + TAG_TRAP_PSM_WD = 5, /* PSM watchdog information */ + TAG_TRAP_PHY = 6, /* Phy related issues */ + TAG_TRAP_BUS = 7, /* Bus level issues */ + TAG_TRAP_MAC_SUSP = 8, /* Mac level suspend issues */ + TAG_TRAP_BACKPLANE = 9, /* Backplane related errors */ + /* Values 10 through 14 are in use by etd_data info iovar */ + TAG_TRAP_PCIE_Q = 15, /* PCIE Queue state during memory trap */ + TAG_TRAP_WLC_STATE = 16, /* WLAN state during memory trap */ + TAG_TRAP_MAC_WAKE = 17, /* Mac level wake issues */ + TAG_TRAP_PHYTXERR_THRESH = 18, /* Phy Tx Err */ + TAG_TRAP_HC_DATA = 19, /* Data collected by HC module */ + TAG_TRAP_LOG_DATA = 20, + TAG_TRAP_LAST /* This must be the last entry */ +} hnd_ext_tag_trap_t; + +typedef struct hnd_ext_trap_bp_err +{ + uint32 error; + uint32 coreid; + uint32 baseaddr; + uint32 ioctrl; + uint32 iostatus; + uint32 resetctrl; + uint32 resetstatus; + uint32 resetreadid; + uint32 resetwriteid; + uint32 errlogctrl; + uint32 errlogdone; + uint32 errlogstatus; + uint32 errlogaddrlo; + uint32 errlogaddrhi; + uint32 errlogid; + uint32 errloguser; + uint32 errlogflags; + uint32 itipoobaout; + uint32 itipoobbout; + uint32 itipoobcout; + uint32 itipoobdout; +} hnd_ext_trap_bp_err_t; + +#define HND_EXT_TRAP_PSMWD_INFO_VER 1 +typedef struct hnd_ext_trap_psmwd_v1 { + uint16 xtag; + uint16 version; /* version of the information following this */ + uint32 i32_maccontrol; + uint32 i32_maccommand; + uint32 i32_macintstatus; + uint32 i32_phydebug; + uint32 i32_clk_ctl_st; + uint32 i32_psmdebug[PSMDBG_REG_READ_CNT_FOR_PSMWDTRAP_V1]; + uint16 i16_0x1a8; /* gated clock en */ + uint16 i16_0x406; /* Rcv Fifo Ctrl */ + uint16 i16_0x408; /* Rx ctrl 1 */ + uint16 i16_0x41a; /* Rxe Status 1 */ + uint16 i16_0x41c; /* Rxe Status 2 */ + uint16 i16_0x424; /* rcv wrd count 0 */ + uint16 i16_0x426; /* rcv wrd count 1 */ + uint16 i16_0x456; /* RCV_LFIFO_STS */ + uint16 i16_0x480; /* PSM_SLP_TMR */ + uint16 i16_0x490; /* PSM BRC */ + uint16 i16_0x500; /* TXE CTRL */ + uint16 i16_0x50e; /* TXE Status */ + uint16 i16_0x55e; /* TXE_xmtdmabusy */ + uint16 i16_0x566; /* TXE_XMTfifosuspflush */ + uint16 i16_0x690; /* IFS Stat */ + uint16 i16_0x692; /* IFS_MEDBUSY_CTR */ + uint16 i16_0x694; /* IFS_TX_DUR */ + uint16 i16_0x6a0; /* SLow_CTL */ + uint16 i16_0x838; /* TXE_AQM fifo Ready */ + uint16 i16_0x8c0; /* Dagg ctrl */ + uint16 shm_prewds_cnt; + uint16 shm_txtplufl_cnt; + uint16 shm_txphyerr_cnt; + uint16 pad; +} hnd_ext_trap_psmwd_v1_t; + +typedef struct hnd_ext_trap_psmwd { + uint16 xtag; + uint16 version; /* version of the information following this */ + uint32 i32_maccontrol; + uint32 i32_maccommand; + uint32 i32_macintstatus; + uint32 i32_phydebug; + uint32 i32_clk_ctl_st; + uint32 i32_psmdebug[PSMDBG_REG_READ_CNT_FOR_PSMWDTRAP_V2]; + uint16 i16_0x4b8; /* psm_brwk_0 */ + uint16 i16_0x4ba; /* psm_brwk_1 */ + uint16 i16_0x4bc; /* psm_brwk_2 */ + uint16 i16_0x4be; /* psm_brwk_2 */ + uint16 i16_0x1a8; /* gated clock en */ + uint16 i16_0x406; /* Rcv Fifo Ctrl */ + uint16 i16_0x408; /* Rx ctrl 1 */ + uint16 i16_0x41a; /* Rxe Status 1 */ + uint16 i16_0x41c; /* Rxe Status 2 */ + uint16 i16_0x424; /* rcv wrd count 0 */ + uint16 i16_0x426; /* rcv wrd count 1 */ + uint16 i16_0x456; /* RCV_LFIFO_STS */ + uint16 i16_0x480; /* PSM_SLP_TMR */ + uint16 i16_0x500; /* TXE CTRL */ + uint16 i16_0x50e; /* TXE Status */ + uint16 i16_0x55e; /* TXE_xmtdmabusy */ + uint16 i16_0x566; /* TXE_XMTfifosuspflush */ + uint16 i16_0x690; /* IFS Stat */ + uint16 i16_0x692; /* IFS_MEDBUSY_CTR */ + uint16 i16_0x694; /* IFS_TX_DUR */ + uint16 i16_0x6a0; /* SLow_CTL */ + uint16 i16_0x490; /* psm_brc */ + uint16 i16_0x4da; /* psm_brc_1 */ + uint16 i16_0x838; /* TXE_AQM fifo Ready */ + uint16 i16_0x8c0; /* Dagg ctrl */ + uint16 shm_prewds_cnt; + uint16 shm_txtplufl_cnt; + uint16 shm_txphyerr_cnt; +} hnd_ext_trap_psmwd_t; + +#define HEAP_HISTOGRAM_DUMP_LEN 6 +#define HEAP_MAX_SZ_BLKS_LEN 2 + +/* Ignore chunks for which there are fewer than this many instances, irrespective of size */ +#define HEAP_HISTOGRAM_INSTANCE_MIN 4 + +/* + * Use the last two length values for chunks larger than this, or when we run out of + * histogram entries (because we have too many different sized chunks) to store "other" + */ +#define HEAP_HISTOGRAM_SPECIAL 0xfffeu + +#define HEAP_HISTOGRAM_GRTR256K 0xffffu + +typedef struct hnd_ext_trap_heap_err { + uint32 arena_total; + uint32 heap_free; + uint32 heap_inuse; + uint32 mf_count; + uint32 stack_lwm; + uint16 heap_histogm[HEAP_HISTOGRAM_DUMP_LEN * 2]; /* size/number */ + uint16 max_sz_free_blk[HEAP_MAX_SZ_BLKS_LEN]; +} hnd_ext_trap_heap_err_t; + +#define MEM_TRAP_NUM_WLC_TX_QUEUES 6 +#define HND_EXT_TRAP_WLC_MEM_ERR_VER_V2 2 + +typedef struct hnd_ext_trap_wlc_mem_err { + uint8 instance; + uint8 associated; + uint8 soft_ap_client_cnt; + uint8 peer_cnt; + uint16 txqueue_len[MEM_TRAP_NUM_WLC_TX_QUEUES]; +} hnd_ext_trap_wlc_mem_err_t; + +typedef struct hnd_ext_trap_wlc_mem_err_v2 { + uint16 version; + uint16 pad; + uint8 instance; + uint8 stas_associated; + uint8 aps_associated; + uint8 soft_ap_client_cnt; + uint16 txqueue_len[MEM_TRAP_NUM_WLC_TX_QUEUES]; +} hnd_ext_trap_wlc_mem_err_v2_t; + +typedef struct hnd_ext_trap_pcie_mem_err { + uint16 d2h_queue_len; + uint16 d2h_req_queue_len; +} hnd_ext_trap_pcie_mem_err_t; + +#define HND_EXT_TRAP_MACSUSP_INFO_VER 1 +typedef struct hnd_ext_trap_macsusp { + uint16 xtag; + uint8 version; /* version of the information following this */ + uint8 trap_reason; + uint32 i32_maccontrol; + uint32 i32_maccommand; + uint32 i32_macintstatus; + uint32 i32_phydebug[4]; + uint32 i32_psmdebug[8]; + uint16 i16_0x41a; /* Rxe Status 1 */ + uint16 i16_0x41c; /* Rxe Status 2 */ + uint16 i16_0x490; /* PSM BRC */ + uint16 i16_0x50e; /* TXE Status */ + uint16 i16_0x55e; /* TXE_xmtdmabusy */ + uint16 i16_0x566; /* TXE_XMTfifosuspflush */ + uint16 i16_0x690; /* IFS Stat */ + uint16 i16_0x692; /* IFS_MEDBUSY_CTR */ + uint16 i16_0x694; /* IFS_TX_DUR */ + uint16 i16_0x7c0; /* WEP CTL */ + uint16 i16_0x838; /* TXE_AQM fifo Ready */ + uint16 i16_0x880; /* MHP_status */ + uint16 shm_prewds_cnt; + uint16 shm_ucode_dbgst; +} hnd_ext_trap_macsusp_t; + +#define HND_EXT_TRAP_MACENAB_INFO_VER 1 +typedef struct hnd_ext_trap_macenab { + uint16 xtag; + uint8 version; /* version of the information following this */ + uint8 trap_reason; + uint32 i32_maccontrol; + uint32 i32_maccommand; + uint32 i32_macintstatus; + uint32 i32_psmdebug[8]; + uint32 i32_clk_ctl_st; + uint32 i32_powerctl; + uint16 i16_0x1a8; /* gated clock en */ + uint16 i16_0x480; /* PSM_SLP_TMR */ + uint16 i16_0x490; /* PSM BRC */ + uint16 i16_0x600; /* TSF CTL */ + uint16 i16_0x690; /* IFS Stat */ + uint16 i16_0x692; /* IFS_MEDBUSY_CTR */ + uint16 i16_0x6a0; /* SLow_CTL */ + uint16 i16_0x6a6; /* SLow_FRAC */ + uint16 i16_0x6a8; /* fast power up delay */ + uint16 i16_0x6aa; /* SLow_PER */ + uint16 shm_ucode_dbgst; + uint16 PAD; +} hnd_ext_trap_macenab_t; + +typedef struct hnd_ext_trap_phydbg { + uint16 err; + uint16 RxFeStatus; + uint16 TxFIFOStatus0; + uint16 TxFIFOStatus1; + uint16 RfseqMode; + uint16 RfseqStatus0; + uint16 RfseqStatus1; + uint16 RfseqStatus_Ocl; + uint16 RfseqStatus_Ocl1; + uint16 OCLControl1; + uint16 TxError; + uint16 bphyTxError; + uint16 TxCCKError; + uint16 TxCtrlWrd0; + uint16 TxCtrlWrd1; + uint16 TxCtrlWrd2; + uint16 TxLsig0; + uint16 TxLsig1; + uint16 TxVhtSigA10; + uint16 TxVhtSigA11; + uint16 TxVhtSigA20; + uint16 TxVhtSigA21; + uint16 txPktLength; + uint16 txPsdulengthCtr; + uint16 gpioClkControl; + uint16 gpioSel; + uint16 pktprocdebug; + uint16 PAD; + uint32 gpioOut[3]; +} hnd_ext_trap_phydbg_t; + +/* unique IDs for separate cores in SI */ +#define REGDUMP_MASK_MAC0 BCM_BIT(1) +#define REGDUMP_MASK_ARM BCM_BIT(2) +#define REGDUMP_MASK_PCIE BCM_BIT(3) +#define REGDUMP_MASK_MAC1 BCM_BIT(4) +#define REGDUMP_MASK_PMU BCM_BIT(5) + +typedef struct { + uint16 reg_offset; + uint16 core_mask; +} reg_dump_config_t; + +#define HND_EXT_TRAP_PHY_INFO_VER 2 +typedef struct hnd_ext_trap_phydbg_v2 { + uint8 version; + uint8 len; + uint16 err; + uint16 RxFeStatus; + uint16 TxFIFOStatus0; + uint16 TxFIFOStatus1; + uint16 RfseqMode; + uint16 RfseqStatus0; + uint16 RfseqStatus1; + uint16 RfseqStatus_Ocl; + uint16 RfseqStatus_Ocl1; + uint16 OCLControl1; + uint16 TxError; + uint16 bphyTxError; + uint16 TxCCKError; + uint16 TxCtrlWrd0; + uint16 TxCtrlWrd1; + uint16 TxCtrlWrd2; + uint16 TxLsig0; + uint16 TxLsig1; + uint16 TxVhtSigA10; + uint16 TxVhtSigA11; + uint16 TxVhtSigA20; + uint16 TxVhtSigA21; + uint16 txPktLength; + uint16 txPsdulengthCtr; + uint16 gpioClkControl; + uint16 gpioSel; + uint16 pktprocdebug; + uint32 gpioOut[3]; + uint32 additional_regs[1]; +} hnd_ext_trap_phydbg_v2_t; + +/* Phy TxErr Dump Structure */ +#define HND_EXT_TRAP_PHYTXERR_INFO_VER 1 +#define HND_EXT_TRAP_PHYTXERR_INFO_VER_V2 2 +typedef struct hnd_ext_trap_macphytxerr { + uint8 version; /* version of the information following this */ + uint8 trap_reason; + uint16 i16_0x63E; /* tsf_tmr_rx_ts */ + uint16 i16_0x640; /* tsf_tmr_tx_ts */ + uint16 i16_0x642; /* tsf_tmr_rx_end_ts */ + uint16 i16_0x846; /* TDC_FrmLen0 */ + uint16 i16_0x848; /* TDC_FrmLen1 */ + uint16 i16_0x84a; /* TDC_Txtime */ + uint16 i16_0xa5a; /* TXE_BytCntInTxFrmLo */ + uint16 i16_0xa5c; /* TXE_BytCntInTxFrmHi */ + uint16 i16_0x856; /* TDC_VhtPsduLen0 */ + uint16 i16_0x858; /* TDC_VhtPsduLen1 */ + uint16 i16_0x490; /* psm_brc */ + uint16 i16_0x4d8; /* psm_brc_1 */ + uint16 shm_txerr_reason; + uint16 shm_pctl0; + uint16 shm_pctl1; + uint16 shm_pctl2; + uint16 shm_lsig0; + uint16 shm_lsig1; + uint16 shm_plcp0; + uint16 shm_plcp1; + uint16 shm_plcp2; + uint16 shm_vht_sigb0; + uint16 shm_vht_sigb1; + uint16 shm_tx_tst; + uint16 shm_txerr_tm; + uint16 shm_curchannel; + uint16 shm_crx_rxtsf_pos; + uint16 shm_lasttx_tsf; + uint16 shm_s_rxtsftmrval; + uint16 i16_0x29; /* Phy indirect address */ + uint16 i16_0x2a; /* Phy indirect address */ +} hnd_ext_trap_macphytxerr_t; + +typedef struct hnd_ext_trap_macphytxerr_v2 { + uint8 version; /* version of the information following this */ + uint8 trap_reason; + uint16 i16_0x63E; /* tsf_tmr_rx_ts */ + uint16 i16_0x640; /* tsf_tmr_tx_ts */ + uint16 i16_0x642; /* tsf_tmr_rx_end_ts */ + uint16 i16_0x846; /* TDC_FrmLen0 */ + uint16 i16_0x848; /* TDC_FrmLen1 */ + uint16 i16_0x84a; /* TDC_Txtime */ + uint16 i16_0xa5a; /* TXE_BytCntInTxFrmLo */ + uint16 i16_0xa5c; /* TXE_BytCntInTxFrmHi */ + uint16 i16_0x856; /* TDC_VhtPsduLen0 */ + uint16 i16_0x858; /* TDC_VhtPsduLen1 */ + uint16 i16_0x490; /* psm_brc */ + uint16 i16_0x4d8; /* psm_brc_1 */ + uint16 shm_txerr_reason; + uint16 shm_pctl0; + uint16 shm_pctl1; + uint16 shm_pctl2; + uint16 shm_lsig0; + uint16 shm_lsig1; + uint16 shm_plcp0; + uint16 shm_plcp1; + uint16 shm_plcp2; + uint16 shm_vht_sigb0; + uint16 shm_vht_sigb1; + uint16 shm_tx_tst; + uint16 shm_txerr_tm; + uint16 shm_curchannel; + uint16 shm_crx_rxtsf_pos; + uint16 shm_lasttx_tsf; + uint16 shm_s_rxtsftmrval; + uint16 i16_0x29; /* Phy indirect address */ + uint16 i16_0x2a; /* Phy indirect address */ + uint8 phyerr_bmac_cnt; /* number of times bmac raised phy tx err */ + uint8 phyerr_bmac_rsn; /* bmac reason for phy tx error */ + uint16 pad; + uint32 recv_fifo_status[3][2]; /* Rcv Status0 & Rcv Status1 for 3 Rx fifos */ +} hnd_ext_trap_macphytxerr_v2_t; + +#define MAX_EVENTLOG_BUFFERS 48 +typedef struct eventlog_trapdata_info { + uint32 num_elements; + uint32 seq_num; + uint32 log_arr_addr; +} eventlog_trapdata_info_t; + +typedef struct eventlog_trap_buf_info { + uint32 len; + uint32 buf_addr; +} eventlog_trap_buf_info_t; + +#if defined(ETD) && !defined(WLETD) +#define ETD_SW_FLAG_MEM 0x00000001 + +void etd_init(osl_t *osh); +int etd_register_trap_ext_callback(void *cb, void *arg); +int (etd_register_trap_ext_callback_late)(void *cb, void *arg); +uint32 *etd_get_trap_ext_data(void); +uint32 etd_get_trap_ext_swflags(void); +void etd_set_trap_ext_swflag(uint32 flag); +void etd_notify_trap_ext_callback(trap_t *tr); +reg_dump_config_t *etd_get_reg_dump_config_tbl(void); +uint etd_get_reg_dump_config_len(void); +#endif /* WLETD */ + +#endif /* !LANGUAGE_ASSEMBLY */ + +#endif /* _ETD_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/ethernet.h b/drivers/net/wireless/bcmdhd_oo/include/ethernet.h index 2e338676a9ebe88f2cb5daa48b555941b45aabb9..565fc70744fabdf89bec8cd48f373a5aebe6a6d5 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/ethernet.h +++ b/drivers/net/wireless/bcmdhd_oo/include/ethernet.h @@ -1,14 +1,14 @@ /* * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,12 +32,11 @@ #ifndef _TYPEDEFS_H_ #include "typedefs.h" -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include - /* * The number of bytes in an ethernet (MAC) address. */ @@ -154,7 +153,6 @@ BWL_PRE_PACKED_STRUCT struct ether_addr { */ #define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) - /* compare two ethernet addresses - assumes the pointers can be referenced as shorts */ #define eacmp(a, b) ((((const uint16 *)(a))[0] ^ ((const uint16 *)(b))[0]) | \ (((const uint16 *)(a))[1] ^ ((const uint16 *)(b))[1]) | \ @@ -189,7 +187,6 @@ do { \ ((uint16 *)(d))[6] = ((const uint16 *)(s))[6]; \ } while (0) - 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}}; diff --git a/drivers/net/wireless/bcmdhd_oo/include/event_log.h b/drivers/net/wireless/bcmdhd_oo/include/event_log.h index 0c2120e19be3653fad792c3ce66a15a6a771cdd2..f0516020bfb172cba55376a9551b8fdc9e57a1e1 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/event_log.h +++ b/drivers/net/wireless/bcmdhd_oo/include/event_log.h @@ -1,14 +1,14 @@ /* * EVENT_LOG system definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: event_log.h 711908 2017-07-20 10:37:34Z $ + * $Id: event_log.h 717896 2017-08-28 21:56:11Z $ */ #ifndef _EVENT_LOG_H_ @@ -43,13 +43,17 @@ /* We make sure that the block size will fit in a single packet * (allowing for a bit of overhead on each packet */ +#if defined(BCMPCIEDEV) +#define EVENT_LOG_MAX_BLOCK_SIZE 1648 +#else #define EVENT_LOG_MAX_BLOCK_SIZE 1400 +#endif // endif #define EVENT_LOG_WL_BLOCK_SIZE 0x200 #define EVENT_LOG_PSM_BLOCK_SIZE 0x200 #define EVENT_LOG_BUS_BLOCK_SIZE 0x200 #define EVENT_LOG_ERROR_BLOCK_SIZE 0x200 -/* Maximum event log record payload size = 1024 bytes or 256 words. */ -#define EVENT_LOG_MAX_RECORD_PAYLOAD_SIZE 256 +/* Maximum event log record payload size = 1016 bytes or 254 words. */ +#define EVENT_LOG_MAX_RECORD_PAYLOAD_SIZE 254 /* * There are multiple levels of objects define here: @@ -98,7 +102,8 @@ typedef struct event_log_block { uint32 event_logs; } event_log_block_t; #define EVENT_LOG_BLOCK_HDRLEN 8 /* pktlen 2 + count 2 + extra_hdr_info 4 */ -#define NAN_EVENT_LOG_MIN_LENGTH 2 /* Minimum length of Nan event */ + +#define EVENT_LOG_BLOCK_LEN 12 typedef enum { SET_DESTINATION_INVALID = -1, @@ -125,6 +130,9 @@ typedef struct event_log_set { uint16 size; /* same size for all buffers in one set */ } event_log_set_t; +/* logstr_hdr_flags */ +#define LOGSTRS_ENCRYPTED 0x1 + /* Top data structure for access to everything else */ typedef struct event_log_top { uint32 magic; @@ -135,10 +143,29 @@ typedef struct event_log_top { uint32 logstrs_size; /* Size of lognums + logstrs area */ uint32 timestamp; /* Last timestamp event */ uint32 cyclecount; /* Cycles at last timestamp event */ - _EL_SET_PTR sets; /* Ptr to array of set ptrs */ + _EL_SET_PTR sets; /* Ptr to array of set ptrs */ } event_log_top_t; +/* structure of the trailing 3 words in logstrs.bin */ +typedef struct { + uint32 fw_id; /* FWID will be written by tool later */ + uint32 flags; /* 0th bit indicates whether encrypted or not */ + /* Keep version and magic last since "header" is appended to the end of logstrs file. */ + uint32 version; /* Header version */ + uint32 log_magic; /* MAGIC number for verification 'LOGS' */ +} logstr_trailer_t; + /* Data structure of Keeping the Header from logstrs.bin */ +typedef struct { + uint32 logstrs_size; /* Size of the file */ + uint32 rom_lognums_offset; /* Offset to the ROM lognum */ + uint32 ram_lognums_offset; /* Offset to the RAM lognum */ + uint32 rom_logstrs_offset; /* Offset to the ROM logstr */ + uint32 ram_logstrs_offset; /* Offset to the RAM logstr */ + logstr_trailer_t trailer; +} logstr_header_t; + +/* Ver 1 Header from logstrs.bin */ typedef struct { uint32 logstrs_size; /* Size of the file */ uint32 rom_lognums_offset; /* Offset to the ROM lognum */ @@ -148,7 +175,7 @@ typedef struct { /* Keep version and magic last since "header" is appended to the end of logstrs file. */ uint32 version; /* Header version */ uint32 log_magic; /* MAGIC number for verification 'LOGS' */ -} logstr_header_t; +} logstr_header_v1_t; /* * Use the following macros for generating log events. @@ -180,7 +207,7 @@ typedef struct { * */ -#if !defined(EVENT_LOG_DUMPER) && !defined(DHD_EFI) +#if !defined(EVENT_LOG_DUMPER) #ifndef EVENT_LOG_COMPILE @@ -232,7 +259,6 @@ typedef struct { #define _EVENT_LOGE(tag, fmt_num, ...) event_logn(14, tag, fmt_num, __VA_ARGS__) #define _EVENT_LOGF(tag, fmt_num, ...) event_logn(15, tag, fmt_num, __VA_ARGS__) - /* Casting low level macros */ #define _EVENT_LOG_CAST0(tag, fmt_num) \ event_log0(tag, fmt_num) @@ -281,7 +307,6 @@ typedef struct { 7, 6, 5, 4, 3, 2, 1, 0) \ (tag, (int) &fmtnum , ## __VA_ARGS__) - #define EVENT_LOG_FAST(tag, fmt, ...) \ do { \ if (event_log_tag_sets != NULL) { \ @@ -313,7 +338,6 @@ typedef struct { _EVENT_LOG(_EVENT_LOG_CAST, tag, fmt , ## __VA_ARGS__); \ } while (0) - #define EVENT_LOG(tag, fmt, ...) EVENT_LOG_COMPACT(tag, fmt , ## __VA_ARGS__) #define EVENT_LOG_CAST(tag, fmt, ...) EVENT_LOG_COMPACT_CAST(tag, fmt , ## __VA_ARGS__) @@ -343,8 +367,10 @@ typedef struct { event_log_caller_return_address(tag); \ } while (0) +#define EVENT_LOG_IS_ON(tag) (*(event_log_tag_sets + (tag)) & ~EVENT_LOG_TAG_FLAG_SET_MASK) #define EVENT_LOG_IS_LOG_ON(tag) (*(event_log_tag_sets + (tag)) & EVENT_LOG_TAG_FLAG_LOG) +#define EVENT_LOG_BUFFER(tag, buf, size) event_log_buffer(tag, buf, size) #define EVENT_DUMP event_log_buffer extern uint8 *event_log_tag_sets; @@ -355,6 +381,7 @@ extern int event_log_set_expand(osl_t *osh, int set_num, int size); extern int event_log_set_shrink(osl_t *osh, int set_num, int size); extern int event_log_tag_start(int tag, int set_num, int flags); +extern int event_log_tag_set_retrieve(int tag); extern int event_log_tag_stop(int tag); typedef void (*event_log_logtrace_trigger_fn_t)(void *ctx); @@ -378,6 +405,13 @@ extern void event_log_buffer(int tag, uint8 *buf, int size); extern void event_log_caller_return_address(int tag); extern int event_log_set_destination_set(int set, event_log_set_destination_t dest); extern event_log_set_destination_t event_log_set_destination_get(int set); +extern int event_log_flush_log_buffer(int set); +extern uint16 event_log_get_available_space(int set); +extern bool event_log_is_set_configured(int set_num); +extern bool event_log_is_tag_valid(int tag); +/* returns number of blocks available for writing */ +extern int event_log_free_blocks_get(int set); +extern bool event_log_is_ready(void); #endif /* EVENT_LOG_DUMPER */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/event_log_payload.h b/drivers/net/wireless/bcmdhd_oo/include/event_log_payload.h index d01264c5b8f2a053756f15e4a3e1173ab05339f2..60274a0a44e877bb2d8ec9a3b9bb807f143ca0ca 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/event_log_payload.h +++ b/drivers/net/wireless/bcmdhd_oo/include/event_log_payload.h @@ -4,14 +4,14 @@ * This file describes the payloads of event log entries that are data buffers * rather than formatted string entries. The contents are generally XTLVs. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: event_log_payload.h 700076 2017-05-17 14:42:22Z $ + * $Id: event_log_payload.h 738285 2017-12-28 01:28:18Z $ */ #ifndef _EVENT_LOG_PAYLOAD_H_ @@ -125,7 +125,6 @@ typedef struct scb_subq_summary { #define SCBDATA_APPS_F_OFF_BLOCKED 0x00000200 #define SCBDATA_APPS_F_OFF_IN_PROG 0x00000400 - /** * Summary for tx datapath AMPDU SCB cubby * This is a specific data structure to describe the AMPDU datapath state for an SCB @@ -281,48 +280,61 @@ typedef struct wl_chansw_event_log_record { int32 dwell_time; } wl_chansw_event_log_record_t; -/* Sub-block type for EVENT_LOG_TAG_AMPDU_DUMP */ -#define WL_AMPDU_STATS_TYPE_RXMCSx1 0 /* RX MCS rate (Nss = 1) */ -#define WL_AMPDU_STATS_TYPE_RXMCSx2 1 -#define WL_AMPDU_STATS_TYPE_RXMCSx3 2 -#define WL_AMPDU_STATS_TYPE_RXMCSx4 3 -#define WL_AMPDU_STATS_TYPE_RXVHTx1 4 /* RX VHT rate (Nss = 1) */ -#define WL_AMPDU_STATS_TYPE_RXVHTx2 5 -#define WL_AMPDU_STATS_TYPE_RXVHTx3 6 -#define WL_AMPDU_STATS_TYPE_RXVHTx4 7 -#define WL_AMPDU_STATS_TYPE_TXMCSx1 8 /* TX MCS rate (Nss = 1) */ -#define WL_AMPDU_STATS_TYPE_TXMCSx2 9 -#define WL_AMPDU_STATS_TYPE_TXMCSx3 10 -#define WL_AMPDU_STATS_TYPE_TXMCSx4 11 -#define WL_AMPDU_STATS_TYPE_TXVHTx1 12 /* TX VHT rate (Nss = 1) */ -#define WL_AMPDU_STATS_TYPE_TXVHTx2 13 -#define WL_AMPDU_STATS_TYPE_TXVHTx3 14 -#define WL_AMPDU_STATS_TYPE_TXVHTx4 15 -#define WL_AMPDU_STATS_TYPE_RXMCSSGI 16 /* RX SGI usage (for all MCS rates) */ -#define WL_AMPDU_STATS_TYPE_TXMCSSGI 17 /* TX SGI usage (for all MCS rates) */ -#define WL_AMPDU_STATS_TYPE_RXVHTSGI 18 /* RX SGI usage (for all VHT rates) */ -#define WL_AMPDU_STATS_TYPE_TXVHTSGI 19 /* TX SGI usage (for all VHT rates) */ -#define WL_AMPDU_STATS_TYPE_RXMCSPER 20 /* RX PER (for all MCS rates) */ -#define WL_AMPDU_STATS_TYPE_TXMCSPER 21 /* TX PER (for all MCS rates) */ -#define WL_AMPDU_STATS_TYPE_RXVHTPER 22 /* RX PER (for all VHT rates) */ -#define WL_AMPDU_STATS_TYPE_TXVHTPER 23 /* TX PER (for all VHT rates) */ -#define WL_AMPDU_STATS_TYPE_RXDENS 24 /* RX AMPDU density */ -#define WL_AMPDU_STATS_TYPE_TXDENS 25 /* TX AMPDU density */ -#define WL_AMPDU_STATS_TYPE_RXMCSOK 26 /* RX all MCS rates */ -#define WL_AMPDU_STATS_TYPE_RXVHTOK 27 /* RX all VHT rates */ -#define WL_AMPDU_STATS_TYPE_TXMCSALL 28 /* TX all MCS rates */ -#define WL_AMPDU_STATS_TYPE_TXVHTALL 29 /* TX all VHT rates */ -#define WL_AMPDU_STATS_TYPE_TXMCSOK 30 /* TX all MCS rates */ -#define WL_AMPDU_STATS_TYPE_TXVHTOK 31 /* TX all VHT rates */ - -#define WL_AMPDU_STATS_MAX_CNTS 64 +typedef struct wl_chansw_event_log_record_v2 { + uint32 time; /* Time in us */ + uint32 old_chanspec; /* Old channel spec */ + uint32 new_chanspec; /* New channel spec */ + uint32 chansw_reason; /* Reason for channel change */ + int32 dwell_time; + uint32 core; + int32 phychanswtime; /* channel switch time */ +} wl_chansw_event_log_record_v2_t; +/* Sub-block type for EVENT_LOG_TAG_AMPDU_DUMP */ +typedef enum { + WL_AMPDU_STATS_TYPE_RXMCSx1 = 0, /* RX MCS rate (Nss = 1) */ + WL_AMPDU_STATS_TYPE_RXMCSx2 = 1, + WL_AMPDU_STATS_TYPE_RXMCSx3 = 2, + WL_AMPDU_STATS_TYPE_RXMCSx4 = 3, + WL_AMPDU_STATS_TYPE_RXVHTx1 = 4, /* RX VHT rate (Nss = 1) */ + WL_AMPDU_STATS_TYPE_RXVHTx2 = 5, + WL_AMPDU_STATS_TYPE_RXVHTx3 = 6, + WL_AMPDU_STATS_TYPE_RXVHTx4 = 7, + WL_AMPDU_STATS_TYPE_TXMCSx1 = 8, /* TX MCS rate (Nss = 1) */ + WL_AMPDU_STATS_TYPE_TXMCSx2 = 9, + WL_AMPDU_STATS_TYPE_TXMCSx3 = 10, + WL_AMPDU_STATS_TYPE_TXMCSx4 = 11, + WL_AMPDU_STATS_TYPE_TXVHTx1 = 12, /* TX VHT rate (Nss = 1) */ + WL_AMPDU_STATS_TYPE_TXVHTx2 = 13, + WL_AMPDU_STATS_TYPE_TXVHTx3 = 14, + WL_AMPDU_STATS_TYPE_TXVHTx4 = 15, + WL_AMPDU_STATS_TYPE_RXMCSSGI = 16, /* RX SGI usage (for all MCS rates) */ + WL_AMPDU_STATS_TYPE_TXMCSSGI = 17, /* TX SGI usage (for all MCS rates) */ + WL_AMPDU_STATS_TYPE_RXVHTSGI = 18, /* RX SGI usage (for all VHT rates) */ + WL_AMPDU_STATS_TYPE_TXVHTSGI = 19, /* TX SGI usage (for all VHT rates) */ + WL_AMPDU_STATS_TYPE_RXMCSPER = 20, /* RX PER (for all MCS rates) */ + WL_AMPDU_STATS_TYPE_TXMCSPER = 21, /* TX PER (for all MCS rates) */ + WL_AMPDU_STATS_TYPE_RXVHTPER = 22, /* RX PER (for all VHT rates) */ + WL_AMPDU_STATS_TYPE_TXVHTPER = 23, /* TX PER (for all VHT rates) */ + WL_AMPDU_STATS_TYPE_RXDENS = 24, /* RX AMPDU density */ + WL_AMPDU_STATS_TYPE_TXDENS = 25, /* TX AMPDU density */ + WL_AMPDU_STATS_TYPE_RXMCSOK = 26, /* RX all MCS rates */ + WL_AMPDU_STATS_TYPE_RXVHTOK = 27, /* RX all VHT rates */ + WL_AMPDU_STATS_TYPE_TXMCSALL = 28, /* TX all MCS rates */ + WL_AMPDU_STATS_TYPE_TXVHTALL = 29, /* TX all VHT rates */ + WL_AMPDU_STATS_TYPE_TXMCSOK = 30, /* TX all MCS rates */ + WL_AMPDU_STATS_TYPE_TXVHTOK = 31, /* TX all VHT rates */ + WL_AMPDU_STATS_MAX_CNTS = 64 +} wl_ampdu_stat_enum_t; typedef struct { uint16 type; /* AMPDU statistics sub-type */ uint16 len; /* Number of 32-bit counters */ uint32 counters[WL_AMPDU_STATS_MAX_CNTS]; } wl_ampdu_stats_generic_t; +typedef wl_ampdu_stats_generic_t wl_ampdu_stats_rx_t; +typedef wl_ampdu_stats_generic_t wl_ampdu_stats_tx_t; + typedef struct { uint16 type; /* AMPDU statistics sub-type */ uint16 len; /* Number of 32-bit counters + 2 */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/event_log_set.h b/drivers/net/wireless/bcmdhd_oo/include/event_log_set.h index db28360ea26551e02b7e0c228a1cf3ad6cf7c98e..660bcd714c94aaca3f8adbacb01db6ec248f81e0 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/event_log_set.h +++ b/drivers/net/wireless/bcmdhd_oo/include/event_log_set.h @@ -1,14 +1,14 @@ /* * EVENT_LOG system definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,16 +24,37 @@ * * <> * - * $Id: event_log_set.h 700076 2017-05-17 14:42:22Z $ + * $Id: event_log_set.h 711987 2017-07-20 22:04:29Z $ */ #ifndef _EVENT_LOG_SET_H_ #define _EVENT_LOG_SET_H_ +#ifndef NUM_EVENT_LOG_SETS /* Set a maximum number of sets here. It is not dynamic for - * efficiency of the EVENT_LOG calls. + * efficiency of the EVENT_LOG calls. Old branches could define + * this to an appropriat enumber in their makefiles to reduce + * ROM invalidation + */ +#define NUM_EVENT_LOG_SETS 10 +#endif // endif + +/* Legacy implementation does not have these sets. So make them 0. */ +#if (NUM_EVENT_LOG_SETS <= 8) +#define NUM_EVENT_LOG_DBG_SETS 0 +#elif (NUM_EVENT_LOG_SETS == 9) +#define NUM_EVENT_LOG_DBG_SETS 1 +#else +#define NUM_EVENT_LOG_DBG_SETS 2 +#endif // endif + +/* Debug log sets start from this log set and are always the last few ones */ +/* Note that these log sets are not reserved for debug builds. They can be used + * for other purpose as well. If used for other purpose, the debug log set + * allocation code will check if there is a free one available out of + * NUM_EVENT_LOG_DBG_SETS starting from EVENT_LOG_DBG_START_SET */ -#define NUM_EVENT_LOG_SETS 8 +#define EVENT_LOG_DBG_START_SET (NUM_EVENT_LOG_SETS - NUM_EVENT_LOG_DBG_SETS) /* Define new event log sets here */ #define EVENT_LOG_SET_BUS 0 @@ -50,4 +71,12 @@ #define EVENT_LOG_SET_6 6 /* Instantiated by host for channel switch logs */ #define EVENT_LOG_SET_7 7 /* Instantiated by host for AMPDU stats */ +/* The following ones could be used for debug builds. Always the last few ones */ +#define EVENT_LOG_SET_8 8 +#define EVENT_LOG_SET_9 9 + +#define EVENT_LOG_SET_PRSRV 7 /* The logtag set flushed only on error. Share with 7 to avoid + * abandons. + */ + #endif /* _EVENT_LOG_SET_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/event_log_tag.h b/drivers/net/wireless/bcmdhd_oo/include/event_log_tag.h index 41332e7aa7a38f09e7aaf238ab8eaef57612c54e..6dda422d9a72205b19efe5fd9edc1cba1186bace 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/event_log_tag.h +++ b/drivers/net/wireless/bcmdhd_oo/include/event_log_tag.h @@ -1,14 +1,14 @@ /* * EVENT_LOG system definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: event_log_tag.h 700681 2017-05-20 16:37:38Z $ + * $Id: event_log_tag.h 736348 2017-12-14 20:10:24Z $ */ #ifndef _EVENT_LOG_TAG_H_ @@ -35,6 +35,9 @@ /* Define new event log tags here */ #define EVENT_LOG_TAG_NULL 0 /* Special null tag */ #define EVENT_LOG_TAG_TS 1 /* Special timestamp tag */ + +/* HSIC Legacy support */ +/* Possible candidates for reuse */ #define EVENT_LOG_TAG_BUS_OOB 2 #define EVENT_LOG_TAG_BUS_STATE 3 #define EVENT_LOG_TAG_BUS_PROTO 4 @@ -45,10 +48,14 @@ #define EVENT_LOG_TAG_BUS_DESC 9 #define EVENT_LOG_TAG_BUS_SETUP 10 #define EVENT_LOG_TAG_BUS_MISC 11 + #define EVENT_LOG_TAG_SRSCAN 22 #define EVENT_LOG_TAG_PWRSTATS_INFO 23 -#define EVENT_LOG_TAG_UCODE_WATCHDOG 26 -#define EVENT_LOG_TAG_UCODE_FIFO 27 + +/* Possible candidates for reuse */ +#define EVENT_LOG_TAG_UCODE_WATCHDOG 26 +#define EVENT_LOG_TAG_UCODE_FIFO 27 + #define EVENT_LOG_TAG_SCAN_TRACE_LOW 28 #define EVENT_LOG_TAG_SCAN_TRACE_HIGH 29 #define EVENT_LOG_TAG_SCAN_ERROR 30 @@ -188,13 +195,88 @@ #define EVENT_LOG_TAG_RANDMAC_DBG 160 #define EVENT_LOG_TAG_RANDMAC_ERR 161 #define EVENT_LOG_TAG_AWDL_DFSP_DBG 162 -#define EVENT_LOG_TAG_TPA_ERR 163 -#define EVENT_LOG_TAG_TPA_INFO 164 +#define EVENT_LOG_TAG_MSCH_CAL 163 +#define EVENT_LOG_TAG_MSCH_OPP_CAL 164 +#define EVENT_LOG_TAG_MSCH 165 +#define EVENT_LOG_TAG_NAN_SYNC 166 +#define EVENT_LOG_TAG_NAN_DPE 167 +#define EVENT_LOG_TAG_NAN_SCHED 168 +#define EVENT_LOG_TAG_NAN_RNG 169 +#define EVENT_LOG_TAG_NAN_DAM 170 +#define EVENT_LOG_TAG_NAN_NA 171 +#define EVENT_LOG_TAG_NAN_NDL 172 +#define EVENT_LOG_TAG_NAN_NDP 173 +#define EVENT_LOG_TAG_NAN_SEC 174 +#define EVENT_LOG_TAG_NAN_MAC 175 +#define EVENT_LOG_TAG_NAN_FSM 176 + +#define EVENT_LOG_TAG_TPA_ERR 192 +#define EVENT_LOG_TAG_TPA_INFO 193 +#define EVENT_LOG_TAG_OCE_DBG 194 +#define EVENT_LOG_TAG_OCE_INFO 195 +#define EVENT_LOG_TAG_OCE_ERR 196 +#define EVENT_LOG_TAG_WL_WARN 197 +#define EVENT_LOG_TAG_SB_ERR 198 +#define EVENT_LOG_TAG_SB_INFO 199 +#define EVENT_LOG_TAG_SB_SCHED 200 +#define EVENT_LOG_TAG_ADPS_INFO 201 +#define EVENT_LOG_TAG_SB_CMN_SYNC_INFO 202 +#define EVENT_LOG_TAG_PHY_CAL_INFO 203 /* PHY CALs scheduler info */ +#define EVENT_LOG_TAG_EVT_NOTIF_INFO 204 +#define EVENT_LOG_TAG_PHY_HC_ERROR 205 +#define EVENT_LOG_TAG_PHY_TXPWR_WARN 206 +#define EVENT_LOG_TAG_PHY_TXPWR_INFO 207 +#define EVENT_LOG_TAG_PHY_ACI_INFO 208 + +#define EVENT_LOG_TAG_WL_COUNTERS_AUX 209 +#define EVENT_LOG_TAG_AMPDU_DUMP_AUX 210 +#define EVENT_LOG_TAG_PWRSTATS_AWDL_AUX 211 +#define EVENT_LOG_TAG_PWRSTATS_PHY_AUX 212 +#define EVENT_LOG_TAG_PWRSTATS_SCAN_AUX 213 +#define EVENT_LOG_TAG_PWRSTATS_WAKE_V2_AUX 214 + +#define EVENT_LOG_TAG_SVT_TESTING 215 /* SVT testing/verification */ + +/* Debug tags for making debug builds */ +#define EVENT_LOG_TAG_DBG1 251 +#define EVENT_LOG_TAG_DBG2 252 +#define EVENT_LOG_TAG_DBG3 253 +#define EVENT_LOG_TAG_DBG4 254 +#define EVENT_LOG_TAG_DBG5 255 + +/* Insert new tags here for Koala onwards */ /* EVENT_LOG_TAG_MAX = Set to the same value of last tag, not last tag + 1 */ -#define EVENT_LOG_TAG_MAX 164 +#define EVENT_LOG_TAG_MAX 255 +#define EVENT_LOG_TAG_MAX_LEGACY_FORMAT 255 /* Note: New event should be added/reserved in trunk before adding it to branches */ +typedef enum wl_el_set_type_def { + EVENT_LOG_SET_TYPE_DEFAULT = 0, + EVENT_LOG_SET_TYPE_PRSRV = 1 +} wl_el_set_type_def_t; + +#define EVENT_LOG_TAG_FLUSH_NONE 0x00 /* No flush */ +#define EVENT_LOG_TAG_FLUSH_ALL 0x40 /* Flush all preserved sets */ +#define EVENT_LOG_TAG_FLUSH_SETNUM 0x80 /* Flush preserved set */ +#define EVENT_LOG_TAG_FLUSH_MASK 0x3f /* SetNum Mask */ + +typedef enum wl_el_flush_type { + EL_TAG_PRSRV_FLUSH_NONE = 0, /* No flush of preserve buf on this tag */ + EL_TAG_PRSRV_FLUSH_SETNUM, /* Flush the buffer set specifid on this tag */ + EL_TAG_PRSRV_FLUSH_ALL /* Flush all preserved buffer set on this tag */ +} wl_el_flush_type_t; + +#define EVENT_LOG_FLUSH_CURRENT_VERSION 0 +typedef struct wl_el_set_flush_prsrv_s { + uint16 version; + uint16 len; + uint16 tag; /* Tag for which preserve flush should be done */ + uint8 flush_type; /* Check wl_el_flush_type_t */ + uint8 set_num; /* Log set num to flush. Max is NUM_EVENT_LOG_SETS. Valid only when + * action is EVENT_LOG_TAG_FLUSH_SETNUM + */ +} wl_el_set_flush_prsrv_t; #define SD_PRHDRS(i, s, h, p, n, l) #define SD_PRPKT(m, b, n) @@ -219,4 +301,26 @@ typedef union event_log_hdr { uint32 t; /* Type cheat */ } event_log_hdr_t; +/* + * The position of the extended header in the event log stream will be as follows: + * + * Extended header could be due to count > 255 or tag > 255. + * + * Extended count: 6 bits long. 8 bits (existing) + 6 bits => + * 2^14 words = 65536 bytes payload max + * Extended count field is currently reserved + * Extended tag: 8 (existing) + 4 bits = 12 bits =>2^12 = 4096 tags + * bits[7..4] of extended tags are reserved. + * MSB 16 bits of the extended header are reserved for future use. + */ + +typedef union event_log_extended_hdr { + struct { + uint8 extended_tag; /* Extended tag, bits[7..4] are reserved */ + uint8 extended_count; /* Extended count. Reserved for now. */ + uint16 rsvd; /* Reserved */ + }; + + uint32 t; /* Type cheat */ +} event_log_extended_hdr_t; #endif /* _EVENT_LOG_TAG_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/event_trace.h b/drivers/net/wireless/bcmdhd_oo/include/event_trace.h index cd24bdf28eab117f8eddd9eceb5cc526e6d1faff..da346999966d9348bc41955e0fb00fac5fac23b3 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/event_trace.h +++ b/drivers/net/wireless/bcmdhd_oo/include/event_trace.h @@ -1,14 +1,14 @@ /* * Trace log blocks sent over HBUS * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: event_trace.h 645268 2016-06-23 08:39:17Z $ + * $Id: event_trace.h 693870 2017-04-05 09:03:17Z $ */ /** diff --git a/drivers/net/wireless/bcmdhd_oo/include/fils.h b/drivers/net/wireless/bcmdhd_oo/include/fils.h new file mode 100644 index 0000000000000000000000000000000000000000..1906e64e4fb70be5742763f6cc200ea4f35d0562 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/fils.h @@ -0,0 +1,251 @@ +/* + * Fundamental types and constants relating to FILS AUTHENTICATION + * Copyright (C) 1999-2018, Broadcom. + * + * 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$ + */ + +#ifndef _FILSAUTH_H_ +#define _FILSAUTH_H_ + +/* This marks the start of a packed structure section. */ +#include + +/* 11ai D6.0 8.6.8.36 FILS Discovery frame format + category + action + fils_discovery_info_field_t + fils_rnr_element_t + fils_indication_element_t + fils_vendor_specific_element_t +*/ + +/* 11revmc D4.0 8.4.2.25 Vendor Specific element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_vendor_specific_element { + uint8 elementid; + uint8 length; + /* variable len info */ + uint8 orgid_vendorspecific_content[]; +} BWL_POST_PACKED_STRUCT fils_vendor_specific_element_t; + +#define FILS_VS_ELEM_HDR_LEN (sizeof(fils_vendor_specific_element_t)) + +/* 11ai D6.0 8.4.2.178 FILS Indication element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_indication_element { + uint8 elementid; + uint8 length; + uint16 fils_info; + /* variable len info */ + uint8 cache_domain_publickey_id[]; +} BWL_POST_PACKED_STRUCT fils_indication_element_t; + +#define FILS_INDICATION_ELEM_HDR_LEN (sizeof(fils_indication_element_t)) + +#define FILS_INDICATION_IE_TAG_FIXED_LEN 2 + +#define FI_INFO_CACHE_IND_SUBFIELD_SIZE 2 + +/* FILS Indication Information field */ +#define FI_INFO_PUB_KEY_IDENTS_MASK (0x0007) +#define FI_INFO_REALM_IDENTS_MASK (0x0038) +#define FI_INFO_IP_ADDR_CFG_MASK (0x0040) +#define FI_INFO_CACHE_IDENT_MASK (0x0080) +#define FI_INFO_HESSID_MASK (0x0100) +#define FI_INFO_SHRKEY_AUTH_WOPFS_MASK (0x0200) +#define FI_INFO_SHRKEY_AUTH_WPFS_MASK (0x0400) +#define FI_INFO_PUBKEY_AUTH_MASK (0x0800) + +#define FI_INFO_CACHE_IDENT(fc) ((fc & FI_INFO_CACHE_IDENT_MASK)) +#define FI_INFO_HESSID(fc) ((fc & FI_INFO_HESSID_MASK)) +#define FI_INFO_SHRKEY_AUTH_WOPFS(fc) ((fc & FI_INFO_SHRKEY_AUTH_WOPFS_MASK)) +#define FI_INFO_SHRKEY_AUTH_WPFS(fc) ((fc & FI_INFO_SHRKEY_AUTH_WPFS_MASK)) + +/* 11ai D11.0 9.4.2.171.1 TBTT Information field */ +typedef BWL_PRE_PACKED_STRUCT struct tbtt_info_field { + uint8 tbtt_offset; + uint8 bssid[ETHER_ADDR_LEN]; + uint32 short_ssid; +} BWL_POST_PACKED_STRUCT tbtt_info_field_t; + +#define TBTT_INFO_FIELD_HDR_LEN (sizeof(tbtt_info_field_t)) + +/* 11ai D11.0 9.4.2.171.1 Neighbor AP Information field */ +typedef BWL_PRE_PACKED_STRUCT struct neighbor_ap_info_field { + uint16 tbtt_info_header; + uint8 op_class; + uint8 channel; + /* variable len info */ + uint8 tbtt_info_field[]; +} BWL_POST_PACKED_STRUCT neighbor_ap_info_field_t; + +#define NEIGHBOR_AP_INFO_FIELD_HDR_LEN (sizeof(neighbor_ap_info_field_t)) + +/* 11ai D11.0 9.4.2.171 Reduced Neighbor Report element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_rnr_element { + uint8 elementid; + uint8 length; + /* variable len info */ + uint8 neighbor_ap_info[]; +} BWL_POST_PACKED_STRUCT fils_rnr_element_t; + +#define FILS_RNR_ELEM_HDR_LEN (sizeof(fils_rnr_element_t)) + +/* TBTT Info Header macros */ +#define TBTT_INFO_HDR_FIELD_TYPE_MASK (0x001f) +#define TBTT_INFO_HDR_FN_AP_MASK (0x0004) +#define TBTT_INFO_HDR_COUNT_MASK (0x00f0) +#define TBTT_INFO_HDR_LENGTH_MASK (0xff00) + +#define TBTT_INFO_HDR_FIELD_TYPE(hdr)\ + ((hdr) & TBTT_INFO_HDR_FIELD_TYPE_MASK) +#define TBTT_INFO_HDR_FN_AP(hdr)\ + (((hdr) & TBTT_INFO_HDR_FN_AP_MASK) >> 2) +#define TBTT_INFO_HDR_COUNT(hdr)\ + (((hdr) & TBTT_INFO_HDR_COUNT_MASK) >> 4) +#define TBTT_INFO_HDR_LENGTH(hdr)\ + (((hdr) & TBTT_INFO_HDR_LENGTH_MASK) >> 8) + +/* 8.4.2.175 FILS Session element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_session_element { + uint8 elementid; + uint8 length; + uint8 element_id_ext; + uint32 fils_session[2]; +} BWL_POST_PACKED_STRUCT fils_session_element_t; + +#define FILS_SESSION_ELEM_LEN (sizeof(fils_session_element_t)) + +/* 8.4.2.174 FILS Key Confirmation element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_key_confirm_element { + uint8 elementid; + uint8 length; + uint8 element_id_ext; + /* variable len info */ + uint8 keyauth[]; +} BWL_POST_PACKED_STRUCT fils_key_confirm_element_t; + +#define FILS_CONFIRM_ELEM_HDR_LEN (sizeof(fils_key_confirm_element_t)) + +/* 11ai D6.0 8.6.8.36 FILS Discovery frame format */ +typedef BWL_PRE_PACKED_STRUCT struct fils_discovery_info_field { + uint16 framecontrol; + uint32 timestamp[2]; + uint16 bcninterval; + /* variable len info */ + uint8 disc_info[]; +} BWL_POST_PACKED_STRUCT fils_discovery_info_field_t; + +#define FD_INFO_FIELD_HDR_LEN (sizeof(fils_discovery_info_field_t)) + +#define FD_INFO_CAP_SUBFIELD_SIZE 2 +#define FD_INFO_LENGTH_FIELD_SIZE 2 + +/* FILS Discovery Information field */ +#define FD_INFO_SSID_LENGTH_MASK (0x001f) +#define FD_INFO_CAP_IND_MASK (0x0020) +#define FD_INFO_SHORT_SSID_IND_MASK (0x0040) +#define FD_INFO_APCSN_IND_MASK (0x0080) +#define FD_INFO_ANO_IND_MASK (0x0100) +#define FD_INFO_CH_CENTER_FR_IND_MASK (0x0200) +#define FD_INFO_PRIMARY_CH_IND_MASK (0x0400) +#define FD_INFO_RSN_IND_MASK (0x0800) +#define FD_INFO_LENGTH_IND_MASK (0x1000) +#define FD_INFO_MD_IND_MASK (0x2000) + +#define FD_INFO_SET_SSID_LENGTH(fc, len) (fc |= ((uint16)(len) & FD_INFO_SSID_LENGTH_MASK)) +#define FD_INFO_SET_CAP_PRESENT(fc) (fc |= FD_INFO_CAP_IND_MASK) +#define FD_INFO_SET_SHORT_SSID_PRESENT(fc) (fc |= FD_INFO_SHORT_SSID_IND_MASK) +#define FD_INFO_SET_APCSN_PRESENT(fc) ((fc |= FD_INFO_APCSN_IND_MASK) +#define FD_INFO_SET_ANO_PRESENT(fc) (fc |= FD_INFO_ANO_IND_MASK) +#define FD_INFO_SET_CH_CENTER_FR_PRESENT(fc) (fc |= FD_INFO_CH_CENTER_FR_IND_MASK) +#define FD_INFO_SET_PRIMARY_CH_PRESENT(fc) (fc |= FD_INFO_PRIMARY_CH_IND_MASK) +#define FD_INFO_SET_RSN_PRESENT(fc) (fc |= FD_INFO_RSN_IND_MASK) +#define FD_INFO_SET_LENGTH_PRESENT(fc) (fc |= FD_INFO_LENGTH_IND_MASK) +#define FD_INFO_SET_MD_PRESENT(fc) (fc |= FD_INFO_MD_IND_MASK) + +#define FD_INFO_SSID_LENGTH(fc) ((fc & FD_INFO_SSID_LENGTH_MASK)) +#define FD_INFO_IS_CAP_PRESENT(fc) ((fc & FD_INFO_CAP_IND_MASK) >> 5) +#define FD_INFO_IS_SHORT_SSID_PRESENT(fc) ((fc & FD_INFO_SHORT_SSID_IND_MASK) >> 6) +#define FD_INFO_IS_APCSN_PRESENT(fc) ((fc & FD_INFO_APCSN_IND_MASK) >> 7) +#define FD_INFO_IS_ANO_PRESENT(fc) ((fc & FD_INFO_ANO_IND_MASK) >> 8) +#define FD_INFO_IS_CH_CENTER_FR_PRESENT(fc) ((fc & FD_INFO_CH_CENTER_FR_IND_MASK) >> 9) +#define FD_INFO_IS_PRIMARY_CH_PRESENT(fc) ((fc & FD_INFO_PRIMARY_CH_IND_MASK) >> 10) +#define FD_INFO_IS_RSN_PRESENT(fc) ((fc & FD_INFO_RSN_IND_MASK) >> 11) +#define FD_INFO_IS_LENGTH_PRESENT(fc) ((fc & FD_INFO_LENGTH_IND_MASK) >> 12) +#define FD_INFO_IS_MD_PRESENT(fc) ((fc & FD_INFO_MD_IND_MASK) >> 13) + +/* FILS Discovery Capability subfield */ +#define FD_CAP_ESS_MASK (0x0001) +#define FD_CAP_PRIVACY_MASK (0x0002) +#define FD_CAP_BSS_CH_WIDTH_MASK (0x001c) +#define FD_CAP_MAX_NSS_MASK (0x00e0) +#define FD_CAP_MULTI_BSS_MASK (0x0200) +#define FD_CAP_PHY_INDEX_MASK (0x1c00) +#define FD_CAP_FILS_MIN_RATE_MASK (0xe000) + +#define FD_CAP_ESS(cap) ((cap & FD_CAP_ESS_MASK)) +#define FD_CAP_PRIVACY(cap) ((cap & FD_CAP_PRIVACY_MASK) >> 1) +#define FD_CAP_BSS_CH_WIDTH(cap) ((cap & FD_CAP_BSS_CH_WIDTH_MASK) >> 2) +#define FD_CAP_MAX_NSS(cap) ((cap & FD_CAP_MAX_NSS_MASK) >> 5) +#define FD_CAP_MULTI_BSS(cap) ((cap & FD_CAP_MULTI_BSS_MASK) >> 9) +#define FD_CAP_PHY_INDEX(cap) ((cap & FD_CAP_PHY_INDEX_MASK) >> 10) +#define FD_CAP_FILS_MIN_RATE(cap) ((cap & FD_CAP_FILS_MIN_RATE_MASK) >> 13) + +#define FD_CAP_SET_ESS(cap) ((cap |= FD_CAP_ESS_MASK)) +#define FD_CAP_SET_PRIVACY(cap) ((cap & FD_CAP_PRIVACY_MASK) >> 1) +#define FD_CAP_SET_BSS_CH_WIDTH(cap) ((cap & FD_CAP_BSS_CH_WIDTH_MASK) >> 2) +#define FD_CAP_SET_MAX_NSS(cap) ((cap & FD_CAP_MAX_NSS_MASK) >> 5) +#define FD_CAP_SET_MULTI_BSS(cap) ((cap & FD_CAP_MULTI_BSS_MASK) >> 9) +#define FD_CAP_SET_PHY_INDEX(cap) ((cap & FD_CAP_PHY_INDEX_MASK) >> 10) +#define FD_CAP_SET_FILS_MIN_RATE(cap) ((cap & FD_CAP_FILS_MIN_RATE_MASK) >> 13) + +/* 11ai D6.0 8.4.2.173 FILS Request Parameters element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_request_parameters_element { + uint8 elementid; + uint8 length; + uint8 element_id_ext; + uint8 params_bitmap; + /* variable len info */ + uint8 params_fields[]; +} BWL_POST_PACKED_STRUCT fils_request_parameters_element_t; + +#define FILS_PARAM_MAX_CHANNEL_TIME (1 << 2) + +/* 11ai 9.4.2.184 FILS HLP Container element */ +typedef BWL_PRE_PACKED_STRUCT struct fils_hlp_container_element { + uint8 elementid; + uint8 length; + uint8 element_id_ext; + uint8 dest_addr[ETHER_ADDR_LEN]; + uint8 src_addr[ETHER_ADDR_LEN]; + /* variable len hlp packet */ + uint8 hlp[]; +} BWL_POST_PACKED_STRUCT fils_hlp_container_element_t; + +#define FILS_HLP_CONTAINER_ELEM_LEN (sizeof(fils_hlp_container_element_t)) + +/* This marks the end of a packed structure section. */ +#include + +#endif /* __FILSAUTH_H__ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_armtrap.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_armtrap.h index e7c005c6f1b3537cd89730f4f2dda13212b35250..622fa4392d1f9607564cbef16af269ec347a71b1 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hnd_armtrap.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_armtrap.h @@ -1,14 +1,14 @@ /* * HND arm trap handling. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -30,7 +30,6 @@ #ifndef _hnd_armtrap_h_ #define _hnd_armtrap_h_ - /* ARM trap handling */ /* Trap types defined by ARM (see arminc.h) */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_cons.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_cons.h index 3470d6a91307852669b4a3eeb007d8fd64c658fa..c76414295e004c7aded4573c1c5340f64f0ce54c 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hnd_cons.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_cons.h @@ -1,14 +1,14 @@ /* * Console support for RTE - for host use only. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_cons.h 568961 2015-07-06 18:14:49Z $ + * $Id: hnd_cons.h 624181 2016-03-10 18:58:22Z $ */ #ifndef _hnd_cons_h_ #define _hnd_cons_h_ @@ -34,11 +34,13 @@ #define CBUF_LEN (128) +#ifndef LOG_BUF_LEN #if defined(BCM_BIG_LOG) #define LOG_BUF_LEN (16 * 1024) #else #define LOG_BUF_LEN 1024 -#endif +#endif // endif +#endif /* LOG_BUF_LEN */ #ifdef BOOTLOADER_CONSOLE_OUTPUT #undef RWL_MAX_DATA_LEN @@ -47,7 +49,7 @@ #define RWL_MAX_DATA_LEN (4 * 1024 + 8) #define CBUF_LEN (RWL_MAX_DATA_LEN + 64) #define LOG_BUF_LEN (16 * 1024) -#endif +#endif // endif typedef struct { uint32 buf; /* Can't be pointer on (64-bit) hosts */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_debug.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_debug.h index 239e596e96af76775182550ebc3a10cd13b02f17..ad191fbfc7316d5d82412a9cfcb31cb6cb5d4df2 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hnd_debug.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_debug.h @@ -1,14 +1,14 @@ /* * HND Run Time Environment debug info area * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_debug.h 678890 2017-01-11 11:48:36Z $ + * $Id: hnd_debug.h 726313 2017-10-12 06:07:22Z $ */ #ifndef _HND_DEBUG_H @@ -40,7 +40,6 @@ /* Includes only when building dongle code */ - /* We use explicit sizes here since this gets included from different * systems. The sizes must be the size of the creating system * (currently 32 bit ARM) since this is gleaned from dump. @@ -48,7 +47,7 @@ #ifdef FWID extern uint32 gFWID; -#endif +#endif // endif /* Define pointers for use on other systems */ #define _HD_EVLOG_P uint32 @@ -121,7 +120,6 @@ typedef struct { /* Time value with microsecond resolution */ uint32 tv_usec; /* Microseconds */ } timeval_t; - /* Linux/ARM 32 prstatus for notes section */ typedef struct prstatus { int32 si_signo; /* Signal number */ @@ -165,42 +163,6 @@ typedef struct prstatus { #define RAMSIZE_PTR_PTR_LIST RAMSIZE_PTR_PTR_0, \ RAMSIZE_PTR_PTR_END -typedef struct hnd_ext_trap_hdr { - uint8 version; /* Extended trap version info */ - uint8 reserved; /* currently unused */ - uint16 len; /* Length of data excluding this header */ - uint8 data[]; /* TLV data */ -} hnd_ext_trap_hdr_t; - -#define TAG_TRAP_SIGNATURE 1 /* Processor register dumps */ -#define TAG_TRAP_STACK 2 /* Processor stack dump (possible code locations) */ -#define TAG_TRAP_MEMORY 3 /* Memory subsystem dump */ -#define TAG_TRAP_DEEPSLEEP 4 /* Deep sleep health check failures */ -#define TAG_TRAP_PSM_WD 5 /* PSM watchdog information */ -#define TAG_TRAP_PHY 6 /* Phy related issues */ -#define TAG_TRAP_BUS 7 /* Bus level issues */ -#define TAG_TRAP_MAC 8 /* Mac level issues */ -#define TAG_TRAP_BACKPLANE 9 /* Backplane related errors */ - -typedef struct hnd_ext_trap_bp_err -{ - uint32 error; - uint32 coreid; - uint32 baseaddr; - uint32 ioctrl; - uint32 iostatus; - uint32 resetctrl; - uint32 resetstatus; - uint32 errlogctrl; - uint32 errlogdone; - uint32 errlogstatus; - uint32 errlogaddrlo; - uint32 errlogaddrhi; - uint32 errlogid; - uint32 errloguser; - uint32 errlogflags; -} hnd_ext_trap_bp_err_t; - #endif /* !LANGUAGE_ASSEMBLY */ #endif /* _HND_DEBUG_H */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_pktpool.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_pktpool.h index e5d0eaa650fe9f55fde84e35c6bfa802d099cb56..2d9eaf5fe663664121374e53bf9081354c3833e8 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hnd_pktpool.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_pktpool.h @@ -1,14 +1,14 @@ /* * HND generic packet pool operation primitives * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_pktpool.h 613891 2016-01-20 10:05:44Z $ + * $Id: hnd_pktpool.h 633941 2016-04-26 07:04:26Z $ */ #ifndef _hnd_pktpool_h_ @@ -34,14 +34,14 @@ #ifdef __cplusplus extern "C" { -#endif +#endif // endif /* mutex macros for thread safe */ #ifdef HND_PKTPOOL_THREAD_SAFE #define HND_PKTPOOL_MUTEX_DECL(mutex) OSL_EXT_MUTEX_DECL(mutex) #else #define HND_PKTPOOL_MUTEX_DECL(mutex) -#endif +#endif // endif #ifdef BCMPKTPOOL #define POOL_ENAB(pool) ((pool) && (pool)->inited) @@ -55,6 +55,10 @@ extern "C" { #define PKTPOOL_CB_MAX 3 #define PKTPOOL_CB_MAX_AVL 4 +/* REMOVE_RXCPLID is an arg for pktpool callback function for removing rxcplID + * and host addr associated with the rxfrag or shared pool buffer during pktpool_reclaim(). + */ +#define REMOVE_RXCPLID 2 /* forward declaration */ struct pktpool; @@ -63,16 +67,16 @@ typedef void (*pktpool_cb_t)(struct pktpool *pool, void *arg); typedef struct { pktpool_cb_t cb; void *arg; + uint8 refcnt; } pktpool_cbinfo_t; /** PCIe SPLITRX related: call back fn extension to populate host address in pool pkt */ -typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, bool arg2); +typedef int (*pktpool_cb_extn_t)(struct pktpool *pool, void *arg1, void* pkt, int arg2); typedef struct { pktpool_cb_extn_t cb; void *arg; } pktpool_cbextn_info_t; - #ifdef BCMDBG_POOL /* pkt pool debug states */ #define POOL_IDLE 0 @@ -110,9 +114,9 @@ typedef struct pktpool { void * freelist; /**< free list: see PKTNEXTFREE(), PKTSETNEXTFREE() */ uint16 avail; /**< number of packets in pool's free list */ - uint16 len; /**< number of packets managed by pool */ + uint16 n_pkts; /**< number of packets managed by pool */ uint16 maxlen; /**< maximum size of pool <= PKTPOOL_LEN_MAX */ - uint16 plen; /**< size of pkt buffer in [bytes], excluding lbuf|lbuf_frag */ + uint16 max_pkt_bytes; /**< size of pkt buffer in [bytes], excluding lbuf|lbuf_frag */ bool empty; uint8 cbtoggle; @@ -129,29 +133,32 @@ typedef struct pktpool { pktpool_cbinfo_t dbg_cbs[PKTPOOL_CB_MAX]; uint16 dbg_qlen; pktpool_dbg_t dbg_q[PKTPOOL_LEN_MAX + 1]; -#endif +#endif // endif pktpool_cbinfo_t dmarxfill; } pktpool_t; - pktpool_t *get_pktpools_registry(int id); /* Incarnate a pktpool registry. On success returns total_pools. */ extern int pktpool_attach(osl_t *osh, uint32 total_pools); extern int pktpool_dettach(osl_t *osh); /* Relinquish registry */ -extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *pktplen, int plen, bool istx, uint8 type); +extern int pktpool_init(osl_t *osh, pktpool_t *pktp, int *n_pkts, int max_pkt_bytes, bool istx, + uint8 type); extern int pktpool_deinit(osl_t *osh, pktpool_t *pktp); extern int pktpool_fill(osl_t *osh, pktpool_t *pktp, bool minimal); +extern int pktpool_empty(osl_t *osh, pktpool_t *pktp); +extern uint16 pktpool_reclaim(osl_t *osh, pktpool_t *pktp, uint16 free_cnt); extern void* pktpool_get(pktpool_t *pktp); extern void pktpool_free(pktpool_t *pktp, void *p); extern int pktpool_add(pktpool_t *pktp, void *p); extern int pktpool_avail_notify_normal(osl_t *osh, pktpool_t *pktp); extern int pktpool_avail_notify_exclusive(osl_t *osh, pktpool_t *pktp, pktpool_cb_t cb); extern int pktpool_avail_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); +extern int pktpool_avail_deregister(pktpool_t *pktp, pktpool_cb_t cb, void *arg); extern int pktpool_empty_register(pktpool_t *pktp, pktpool_cb_t cb, void *arg); -extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 maxlen); -extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 maxlen); +extern int pktpool_setmaxlen(pktpool_t *pktp, uint16 max_pkts); +extern int pktpool_setmaxlen_strict(osl_t *osh, pktpool_t *pktp, uint16 max_pkts); extern void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); extern bool pktpool_emptycb_disabled(pktpool_t *pktp); extern int pktpool_hostaddr_fill_register(pktpool_t *pktp, pktpool_cb_extn_t cb, void *arg1); @@ -164,11 +171,10 @@ extern int pkpool_haddr_avail_register_cb(pktpool_t *pktp, pktpool_cb_t cb, void #define POOLSETID(pp, ppid) (POOLPTR(pp)->id = (ppid)) -#define pktpool_len(pp) (POOLPTR(pp)->len) /**< returns packet length in [bytes] */ +#define pktpool_tot_pkts(pp) (POOLPTR(pp)->n_pkts) /**< n_pkts = avail + in_use <= max_pkts */ #define pktpool_avail(pp) (POOLPTR(pp)->avail) -#define pktpool_plen(pp) (POOLPTR(pp)->plen) -#define pktpool_maxlen(pp) (POOLPTR(pp)->maxlen) - +#define pktpool_max_pkt_bytes(pp) (POOLPTR(pp)->max_pkt_bytes) +#define pktpool_max_pkts(pp) (POOLPTR(pp)->maxlen) /* * ---------------------------------------------------------------------------- @@ -205,7 +211,15 @@ extern pktpool_t *pktpool_shared; #ifdef BCMFRAGPOOL #define SHARED_FRAG_POOL (pktpool_shared_lfrag) extern pktpool_t *pktpool_shared_lfrag; -#endif +#endif // endif + +#ifdef BCMRESVFRAGPOOL +#define RESV_FRAG_POOL (pktpool_resv_lfrag) +#define RESV_POOL_INFO (resv_pool_info) +#else +#define RESV_FRAG_POOL ((struct pktpool *)NULL) +#define RESV_POOL_INFO (NULL) +#endif /* BCMRESVFRAGPOOL */ /** PCIe SPLITRX related */ #define SHARED_RXFRAG_POOL (pktpool_shared_rxlfrag) @@ -214,12 +228,16 @@ extern pktpool_t *pktpool_shared_rxlfrag; int hnd_pktpool_init(osl_t *osh); int hnd_pktpool_fill(pktpool_t *pktpool, bool minimal); void hnd_pktpool_refill(bool minimal); +#ifdef BCMRESVFRAGPOOL +extern pktpool_t *pktpool_resv_lfrag; +extern struct resv_info *resv_pool_info; +#endif /* BCMRESVFRAGPOOL */ #else /* BCMPKTPOOL */ #define SHARED_POOL ((struct pktpool *)NULL) #endif /* BCMPKTPOOL */ #ifdef __cplusplus } -#endif +#endif // endif #endif /* _hnd_pktpool_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_pktq.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_pktq.h index ad778da896e7f709674bc975b8ecfd82eba3c58a..24a3e423570a390d54469c7ec966d090492725fc 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hnd_pktq.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_pktq.h @@ -1,14 +1,14 @@ /* * HND generic pktq operation primitives * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hnd_pktq.h 641285 2016-06-02 02:33:55Z $ + * $Id: hnd_pktq.h 698847 2017-05-11 00:10:48Z $ */ #ifndef _hnd_pktq_h_ @@ -34,29 +34,32 @@ #ifdef __cplusplus extern "C" { -#endif +#endif // endif /* mutex macros for thread safe */ #ifdef HND_PKTQ_THREAD_SAFE #define HND_PKTQ_MUTEX_DECL(mutex) OSL_EXT_MUTEX_DECL(mutex) #else #define HND_PKTQ_MUTEX_DECL(mutex) -#endif +#endif // endif /* osl multi-precedence packet queue */ #define PKTQ_LEN_MAX 0xFFFF /* Max uint16 65535 packets */ #ifndef PKTQ_LEN_DEFAULT #define PKTQ_LEN_DEFAULT 128 /* Max 128 packets */ -#endif +#endif // endif #ifndef PKTQ_MAX_PREC #define PKTQ_MAX_PREC 16 /* Maximum precedence levels */ -#endif +#endif // endif +/** Queue for a single precedence level */ typedef struct pktq_prec { void *head; /**< first packet to dequeue */ void *tail; /**< last packet to dequeue */ - uint16 len; /**< number of queued packets */ - uint16 max; /**< maximum number of queued packets */ + uint16 n_pkts; /**< number of queued packets */ + uint16 max_pkts; /**< maximum number of queued packets */ + uint16 stall_count; /**< # seconds since no packets are dequeued */ + uint16 dequeue_count; /**< # of packets dequeued in last 1 second */ } pktq_prec_t; #ifdef PKTQ_LOG @@ -109,27 +112,25 @@ typedef struct { typedef struct pktq_log pktq_log_t; #endif /* PKTQ_LOG */ - #define PKTQ_COMMON \ HND_PKTQ_MUTEX_DECL(mutex) \ pktq_log_t *pktqlog; \ uint16 num_prec; /**< number of precedences in use */ \ uint16 hi_prec; /**< rapid dequeue hint (>= highest non-empty prec) */ \ - uint16 max; /**< total max packets */ \ - uint16 len; /**< total number of packets */ + uint16 max_pkts; /**< max packets */ \ + uint16 n_pkts_tot; /**< total (cummulative over all precedences) number of packets */ -/* multi-priority pkt queue */ +/** multi-priority packet queue */ struct pktq { PKTQ_COMMON /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ struct pktq_prec q[PKTQ_MAX_PREC]; }; -/* simple, non-priority pkt queue */ +/** simple, non-priority packet queue */ struct spktq { - PKTQ_COMMON - /* q array must be last since # of elements can be either PKTQ_MAX_PREC or 1 */ - struct pktq_prec q[1]; + HND_PKTQ_MUTEX_DECL(mutex) + struct pktq_prec q; }; #define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) @@ -141,7 +142,7 @@ typedef bool (*ifpkt_cb_t)(void*, int); * pktq filter support */ -/* filter function return values */ +/** filter function return values */ typedef enum { PKT_FILTER_NOACTION = 0, /**< restore the pkt to its position in the queue */ PKT_FILTER_DELETE = 1, /**< delete the pkt */ @@ -172,58 +173,77 @@ typedef enum { * WARNING: pkts inserted by the user (in pkt_filter and/or flush callbacks * and chains) in the prec queue will not be seen by the filter, and the prec * queue will be temporarily be removed from the queue hence there're side - * effects including pktq_len() on the queue won't reflect the correct number + * effects including pktq_n_pkts_tot() on the queue won't reflect the correct number * of packets in the queue. */ + typedef pktq_filter_result_t (*pktq_filter_t)(void* ctx, void* pkt); -/* The defer_free_pkt callback is invoked when the the pktq_filter callback +/** + * The defer_free_pkt callback is invoked when the the pktq_filter callback * returns PKT_FILTER_DELETE decision, which allows the user to deposite * the packet appropriately based on the situation (free the packet or * save it in a temporary queue etc.). */ typedef void (*defer_free_pkt_fn_t)(void *ctx, void *pkt); -/* The flush_free_pkt callback is invoked when all packets in the pktq +/** + * The flush_free_pkt callback is invoked when all packets in the pktq * are processed. */ typedef void (*flush_free_pkt_fn_t)(void *ctx); -/* filter a pktq, using the caller supplied filter/deposition/flush functions */ +#if defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) +/* this callback will be invoked when in low_txq_scb flush() + * two back-to-back pkts has same epoch value. + */ +typedef void (*flip_epoch_t)(void *ctx, void *pkt, uint8 *flipEpoch, uint8 *lastEpoch); +#endif /* defined(WLAMPDU_MAC) && defined(PROP_TXSTATUS) */ + +/** filter a pktq, using the caller supplied filter/deposition/flush functions */ extern void pktq_filter(struct pktq *pq, pktq_filter_t fn, void* arg, defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx); -/* filter a particular precedence in pktq, using the caller supplied filter function */ +/** filter a particular precedence in pktq, using the caller supplied filter function */ extern void pktq_pfilter(struct pktq *pq, int prec, pktq_filter_t fn, void* arg, defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx); +/** filter a simple non-precedence in spktq, using the caller supplied filter function */ +extern void spktq_filter(struct spktq *spq, pktq_filter_t fltr, void* fltr_ctx, + defer_free_pkt_fn_t defer, void *defer_ctx, flush_free_pkt_fn_t flush, void *flush_ctx); /* operations on a specific precedence in packet queue */ - -#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) -#define pktq_pmax(pq, prec) ((pq)->q[prec].max) -#define pktq_plen(pq, prec) ((pq)->q[prec].len) -#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) -#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) -#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) +#define pktqprec_max_pkts(pq, prec) ((pq)->q[prec].max_pkts) +#define pktqprec_n_pkts(pq, prec) ((pq)->q[prec].n_pkts) +#define pktqprec_empty(pq, prec) ((pq)->q[prec].n_pkts == 0) +#define pktqprec_peek(pq, prec) ((pq)->q[prec].head) +#define pktqprec_peek_tail(pq, prec) ((pq)->q[prec].tail) +#define spktq_peek_tail(pq) ((pq)->q.tail) #ifdef HND_PKTQ_THREAD_SAFE -extern int pktq_pavail(struct pktq *pq, int prec); -extern bool pktq_pfull(struct pktq *pq, int prec); +extern int pktqprec_avail_pkts(struct pktq *pq, int prec); +extern bool pktqprec_full(struct pktq *pq, int prec); #else -#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) -#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) +#define pktqprec_avail_pkts(pq, prec) ((pq)->q[prec].max_pkts - (pq)->q[prec].n_pkts) +#define pktqprec_full(pq, prec) ((pq)->q[prec].n_pkts >= (pq)->q[prec].max_pkts) #endif /* HND_PKTQ_THREAD_SAFE */ extern void pktq_append(struct pktq *pq, int prec, struct spktq *list); +extern void spktq_append(struct spktq *spq, struct spktq *list); extern void pktq_prepend(struct pktq *pq, int prec, struct spktq *list); - +extern void spktq_prepend(struct spktq *spq, struct spktq *list); 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); -/* Remove a specified packet from its queue */ +/** Remove a specified packet from its queue */ extern bool pktq_pdel(struct pktq *pq, void *p, int prec); +/* For single precedence queues */ +extern void *spktq_enq(struct spktq *spq, void *p); +extern void *spktq_enq_head(struct spktq *spq, void *p); +extern void *spktq_deq(struct spktq *spq); +extern void *spktq_deq_tail(struct spktq *spq); + /* operations on a set of precedences in packet queue */ extern int pktq_mlen(struct pktq *pq, uint prec_bmp); @@ -232,53 +252,74 @@ extern void *pktq_mpeek(struct pktq *pq, uint prec_bmp, int *prec_out); /* operations on packet queue as a whole */ -#define pktq_len(pq) ((int)(pq)->len) -#define pktq_max(pq) ((int)(pq)->max) -#define pktq_empty(pq) ((pq)->len == 0) +#define pktq_n_pkts_tot(pq) ((int)(pq)->n_pkts_tot) +#define pktq_max(pq) ((int)(pq)->max_pkts) +#define pktq_empty(pq) ((pq)->n_pkts_tot == 0) +#define spktq_n_pkts(spq) ((int)(spq)->q.n_pkts) +#define spktq_empty(spq) ((spq)->q.n_pkts == 0) + +#define spktq_max(spq) ((int)(spq)->q.max_pkts) +#define spktq_empty(spq) ((spq)->q.n_pkts == 0) #ifdef HND_PKTQ_THREAD_SAFE extern int pktq_avail(struct pktq *pq); extern bool pktq_full(struct pktq *pq); +extern int spktq_avail(struct spktq *spq); +extern bool spktq_full(struct spktq *spq); #else -#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) -#define pktq_full(pq) ((pq)->len >= (pq)->max) +#define pktq_avail(pq) ((int)((pq)->max_pkts - (pq)->n_pkts_tot)) +#define pktq_full(pq) ((pq)->n_pkts_tot >= (pq)->max_pkts) +#define spktq_avail(spq) ((int)((spq)->q.max_pkts - (spq)->q.n_pkts)) +#define spktq_full(spq) ((spq)->q.n_pkts >= (spq)->q.max_pkts) #endif /* HND_PKTQ_THREAD_SAFE */ /* operations for single precedence queues */ -#define pktenq(pq, p) pktq_penq(((struct pktq *)(void *)pq), 0, (p)) -#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)(void *)pq), 0, (p)) -#define pktdeq(pq) pktq_pdeq(((struct pktq *)(void *)pq), 0) -#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)(void *)pq), 0) -#define pktqflush(osh, pq, dir) pktq_pflush(osh, ((struct pktq *)(void *)pq), 0, dir) -#define pktqinit(pq, len) pktq_init(((struct pktq *)(void *)pq), 1, len) -#define pktqdeinit(pq) pktq_deinit((struct pktq *)(void *)pq) -#define pktqavail(pq) pktq_avail((struct pktq *)(void *)pq) -#define pktqfull(pq) pktq_full((struct pktq *)(void *)pq) +#define pktenq(pq, p) pktq_penq((pq), 0, (p)) +#define pktenq_head(pq, p) pktq_penq_head((pq), 0, (p)) +#define pktdeq(pq) pktq_pdeq((pq), 0) +#define pktdeq_tail(pq) pktq_pdeq_tail((pq), 0) +#define pktqflush(osh, pq, dir) pktq_pflush(osh, (pq), 0, (dir)) +#define pktqinit(pq, max_pkts) pktq_init((pq), 1, (max_pkts)) +#define pktqdeinit(pq) pktq_deinit((pq)) +#define pktqavail(pq) pktq_avail((pq)) +#define pktqfull(pq) pktq_full((pq)) #define pktqfilter(pq, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) \ - pktq_pfilter((struct pktq *)pq, 0, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) - -/* wrap macros for modules in components use */ -#define spktqinit(pq, max_pkts) pktqinit(pq, max_pkts) -#define spktenq(pq, p) pktenq(pq, p) -#define spktdeq(pq) pktdeq(pq) - -extern bool pktq_init(struct pktq *pq, int num_prec, int max_len); + pktq_pfilter((pq), 0, (fltr), (fltr_ctx), (defer), (defer_ctx), (flush), (flush_ctx)) + +/* operations for simple non-precedence queues */ +#define spktenq(spq, p) spktq_enq((spq), (p)) +#define spktenq_head(spq, p) spktq_enq_head((spq), (p)) +#define spktdeq(spq) spktq_deq((spq)) +#define spktdeq_tail(spq) spktq_deq_tail((spq)) +#define spktqflush(osh, spq, dir) spktq_flush((osh), (spq), (dir)) +#define spktqinit(spq, max_pkts) spktq_init((spq), (max_pkts)) +#define spktqdeinit(spq) spktq_deinit((spq)) +#define spktqavail(spq) spktq_avail((spq)) +#define spktqfull(spq) spktq_full((spq)) + +#define spktqfilter(spq, fltr, fltr_ctx, defer, defer_ctx, flush, flush_ctx) \ + spktq_filter((spq), (fltr), (fltr_ctx), (defer), (defer_ctx), (flush), (flush_ctx)) +extern bool pktq_init(struct pktq *pq, int num_prec, int max_pkts); extern bool pktq_deinit(struct pktq *pq); +extern bool spktq_init(struct spktq *spq, int max_pkts); +extern bool spktq_deinit(struct spktq *spq); -extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_len); +extern void pktq_set_max_plen(struct pktq *pq, int prec, int max_pkts); /* prec_out may be NULL if caller is not interested in return value */ extern void *pktq_deq(struct pktq *pq, int *prec_out); extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); extern void *pktq_peek(struct pktq *pq, int *prec_out); +extern void *spktq_peek(struct spktq *spq); extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); -/* flush pktq */ +/** flush pktq */ extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir); -/* Empty the queue at particular precedence level */ +extern void spktq_flush(osl_t *osh, struct spktq *spq, bool dir); +/** Empty the queue at particular precedence level */ extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir); #ifdef __cplusplus } -#endif +#endif // endif #endif /* _hnd_pktq_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hnd_trap.h b/drivers/net/wireless/bcmdhd_oo/include/hnd_trap.h new file mode 100644 index 0000000000000000000000000000000000000000..1e2a4a63c8e79397aee4c500e4f8394c1985cb49 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/hnd_trap.h @@ -0,0 +1,39 @@ +/* + * HND Trap handling. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: hnd_trap.h 514727 2014-11-12 03:02:48Z $ + */ + +#ifndef _hnd_trap_h_ +#define _hnd_trap_h_ + +#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) +#include +#else +#error "unsupported CPU architecture" +#endif // endif + +#endif /* _hnd_trap_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hndchipc.h b/drivers/net/wireless/bcmdhd_oo/include/hndchipc.h new file mode 100644 index 0000000000000000000000000000000000000000..71f26b096b4e84c12394a7e411a1631d440567d8 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/hndchipc.h @@ -0,0 +1,53 @@ +/* + * HND SiliconBackplane chipcommon support - OS independent. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: hndchipc.h 689775 2017-03-13 12:37:05Z $ + */ + +#ifndef _hndchipc_h_ +#define _hndchipc_h_ + +#include +#include + +#ifdef RTE_UART +typedef void (*si_serial_init_fn)(si_t *sih, void *regs, uint irq, uint baud_base, uint reg_shift); +#else +typedef void (*si_serial_init_fn)(void *regs, uint irq, uint baud_base, uint reg_shift); +#endif // endif +extern void si_serial_init(si_t *sih, si_serial_init_fn add); + +extern volatile void *hnd_jtagm_init(si_t *sih, uint clkd, bool exttap); +extern void hnd_jtagm_disable(si_t *sih, volatile void *h); +extern uint32 jtag_scan(si_t *sih, volatile void *h, uint irsz, uint32 ir0, uint32 ir1, + uint drsz, uint32 dr0, uint32 *dr1, bool rti); +extern uint32 jtag_read_128(si_t *sih, volatile void *h, uint irsz, uint32 ir0, uint drsz, + uint32 dr0, uint32 *dr1, uint32 *dr2, uint32 *dr3); +extern uint32 jtag_write_128(si_t *sih, volatile void *h, uint irsz, uint32 ir0, uint drsz, + uint32 dr0, uint32 *dr1, uint32 *dr2, uint32 *dr3); +extern int jtag_setbit_128(si_t *sih, uint32 jtagureg_addr, uint8 bit_pos, uint8 bit_val); + +#endif /* _hndchipc_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hndlhl.h b/drivers/net/wireless/bcmdhd_oo/include/hndlhl.h new file mode 100644 index 0000000000000000000000000000000000000000..3fd9563b38428e12c4267c9d0e75037bf7caedd4 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/hndlhl.h @@ -0,0 +1,61 @@ +/* + * HND SiliconBackplane PMU support. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: hndpmu.h 546588 2015-04-13 09:24:52Z $ + */ + +#ifndef _hndlhl_h_ +#define _hndlhl_h_ + +enum { + LHL_MAC_TIMER = 0, + LHL_ARM_TIMER = 1 +}; + +typedef struct { + uint16 offset; + uint32 mask; + uint32 val; +} lhl_reg_set_t; + +#define LHL_REG_OFF(reg) OFFSETOF(gciregs_t, reg) + +extern void si_lhl_timer_config(si_t *sih, osl_t *osh, int timer_type); +extern void si_lhl_timer_enable(si_t *sih); + +extern void si_lhl_setup(si_t *sih, osl_t *osh); +extern void si_lhl_enable(si_t *sih, osl_t *osh, bool enable); +extern void si_lhl_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period); +extern void si_lhl_enable_sdio_wakeup(si_t *sih, osl_t *osh); +extern void si_lhl_disable_sdio_wakeup(si_t *sih); +extern int si_lhl_set_lpoclk(si_t *sih, osl_t *osh, uint32 lpo_force); +extern void si_set_lv_sleep_mode_lhl_config_4369(si_t *sih); + +#define HIB_EXT_WAKEUP_CAP(sih) (BCM4347_CHIP(sih->chip)) + +#define LHL_IS_PSMODE_0(sih) (si_lhl_ps_mode(sih) == LHL_PS_MODE_0) +#define LHL_IS_PSMODE_1(sih) (si_lhl_ps_mode(sih) == LHL_PS_MODE_1) +#endif /* _hndlhl_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hndpmu.h b/drivers/net/wireless/bcmdhd_oo/include/hndpmu.h index bfc916693e1f3f0ce4950d064d6431bceceb5bda..025f7a624092e79a64f54c4c8f7b8df91bd65a65 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hndpmu.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hndpmu.h @@ -1,14 +1,14 @@ /* * HND SiliconBackplane PMU support. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hndpmu.h 657872 2016-09-02 22:17:34Z $ + * $Id: hndpmu.h 700376 2017-05-18 22:55:43Z $ */ #ifndef _hndpmu_h_ @@ -35,22 +35,45 @@ #include #include +extern uint32 si_pmu_rsrc_macphy_clk_deps(si_t *sih, osl_t *osh, int maccore_index); +extern uint32 si_pmu_rsrc_ht_avail_clk_deps(si_t *sih, osl_t *osh); extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on, uint32* min_res_mask); extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); -extern void si_pmu_minresmask_htavail_set(si_t *sih, osl_t *osh, bool set_clear); extern void si_pmu_slow_clk_reinit(si_t *sih, osl_t *osh); extern void si_pmu_avbtimer_enable(si_t *sih, osl_t *osh, bool set_flag); extern uint32 si_pmu_dump_pmucap_binary(si_t *sih, uchar *p); extern uint32 si_pmu_dump_buf_size_pmucap(si_t *sih); extern int si_pmu_wait_for_steady_state(si_t *sih, osl_t *osh, pmuregs_t *pmu); +extern uint32 si_pmu_wake_bit_offset(si_t *sih); #if defined(BCMULP) int si_pmu_ulp_register(si_t *sih); +extern void si_pmu_ulp_chipconfig(si_t *sih, osl_t *osh); extern void si_pmu_ulp_ilp_config(si_t *sih, osl_t *osh, uint32 ilp_period); +extern void si_pmu_ds1_res_init(si_t *sih, osl_t *osh); #endif /* BCMULP */ extern uint32 si_pmu_get_pmutimer(si_t *sih); +extern void si_switch_pmu_dependency(si_t *sih, uint mode); extern void si_pmu_set_min_res_mask(si_t *sih, osl_t *osh, uint min_res_mask); +extern void si_pmu_set_mac_rsrc_req(si_t *sih, int macunit); +extern bool si_pmu_fast_lpo_enable_pcie(si_t *sih); +extern bool si_pmu_fast_lpo_enable_pmu(si_t *sih); +extern void si_pmu_chipcontrol_xtal_settings_4369(si_t *sih); +extern uint32 si_cur_pmu_time(si_t *sih); extern bool si_pmu_cap_fast_lpo(si_t *sih); extern int si_pmu_fast_lpo_disable(si_t *sih); +#ifdef BCMPMU_STATS +extern void si_pmustatstimer_init(si_t *sih); +extern void si_pmustatstimer_dump(si_t *sih); +extern void si_pmustatstimer_start(si_t *sih, uint8 timerid); +extern void si_pmustatstimer_stop(si_t *sih, uint8 timerid); +extern void si_pmustatstimer_clear(si_t *sih, uint8 timerid); +extern void si_pmustatstimer_clear_overflow(si_t *sih); +extern uint32 si_pmustatstimer_read(si_t *sih, uint8 timerid); +extern void si_pmustatstimer_cfg_src_num(si_t *sih, uint8 src_num, uint8 timerid); +extern void si_pmustatstimer_cfg_cnt_mode(si_t *sih, uint8 cnt_mode, uint8 timerid); +extern void si_pmustatstimer_int_enable(si_t *sih); +extern void si_pmustatstimer_int_disable(si_t *sih); +#endif /* BCMPMU_STATS */ #endif /* _hndpmu_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/hndsoc.h b/drivers/net/wireless/bcmdhd_oo/include/hndsoc.h index b35380ad57bf1de4e7d79be2b21318f8a15959c2..46f5acce83660ca349bc755b97000dac8e4ab5d9 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/hndsoc.h +++ b/drivers/net/wireless/bcmdhd_oo/include/hndsoc.h @@ -1,14 +1,14 @@ /* * Broadcom HND chip & on-chip-interconnect-related definitions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: hndsoc.h 613129 2016-01-17 09:25:52Z $ + * $Id: hndsoc.h 672520 2016-11-28 23:30:55Z $ */ #ifndef _HNDSOC_H @@ -45,10 +45,32 @@ #define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ #define SI_SDRAM_R2 0x80000000 /* Region 2 for sdram (512 MB) */ -#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -#define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ +#ifdef STB_SOC_WIFI +#define SI_REG_BASE_SIZE 0xB000 /* size from 0xf1800000 to 0xf180AFFF (44KB) */ +#define SI_ENUM_BASE_DEFAULT 0xF1800000 /* Enumeration space base */ +#define SI_WRAP_BASE_DEFAULT 0xF1900000 /* Wrapper space base */ +#endif /* STB_SOC_WIFI */ + +#ifndef SI_ENUM_BASE_DEFAULT +#define SI_ENUM_BASE_DEFAULT 0x18000000 /* Enumeration space base */ +#endif // endif + +#ifndef SI_WRAP_BASE_DEFAULT +#define SI_WRAP_BASE_DEFAULT 0x18100000 /* Wrapper space base */ +#endif // endif + +/** new(er) chips started locating their chipc core at a different BP address than 0x1800_0000 */ +// NIC and DHD driver binaries should support both old(er) and new(er) chips at the same time +#define SI_ENUM_BASE(sih) ((sih)->enum_base) +#define SI_WRAP_BASE(sih) (SI_ENUM_BASE(sih) + 0x00100000) + #define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ +#define SI_NIC400_GPV_BASE 0x18200000 /* NIC-400 Global Programmers View (GPV) */ +#define SI_GPV_WR_CAP_ADDR 0x4008 /* WR-CAP offset */ +#define SI_GPV_RD_CAP_EN 0x1 /* issue read */ +#define SI_GPV_WR_CAP_EN 0x2 /* issue write */ + #ifndef SI_MAXCORES #define SI_MAXCORES 32 /* NorthStar has more cores */ #endif /* SI_MAXCORES */ @@ -78,7 +100,9 @@ #define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ #define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ #define SI_ARMCA7_ROM 0x00000000 /* ARM Cortex-A7 ROM */ +#ifndef SI_ARMCA7_RAM #define SI_ARMCA7_RAM 0x00200000 /* ARM Cortex-A7 RAM */ +#endif // endif #define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ #define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ @@ -182,10 +206,12 @@ #define USB30D_CORE_ID 0x83d /* usb 3.0 device core */ #define ARMCR4_CORE_ID 0x83e /* ARM CR4 CPU */ #define GCI_CORE_ID 0x840 /* GCI Core */ +#define SR_CORE_ID 0x841 /* SR_CORE ID */ #define M2MDMA_CORE_ID 0x844 /* memory to memory dma */ #define CMEM_CORE_ID 0x846 /* CNDS DDR2/3 memory controller */ #define ARMCA7_CORE_ID 0x847 /* ARM CA7 CPU */ #define SYSMEM_CORE_ID 0x849 /* System memory core */ +#define HUB_CORE_ID 0x84b /* Hub core ID */ #define APB_BRIDGE_CORE_ID 0x135 /* APB bridge core ID */ #define AXI_CORE_ID 0x301 /* AXI/GPV core ID */ #define EROM_CORE_ID 0x366 /* EROM core ID */ @@ -194,7 +220,6 @@ * unused address ranges */ -#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 */ @@ -206,12 +231,9 @@ #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 NS_SOCRAM_CORE_ID 0x50e /* internal memory core */ #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 */ #define ALTA_CORE_ID 0x534 /* I2S core */ #define DDR23_PHY_CORE_ID 0x5dd @@ -221,12 +243,9 @@ #define SI_PCIE1_DMA_H32 0xc0000000 /* PCIE Client Mode sb2pcitranslation2 * (2 ZettaBytes), high 32 bits */ -#define CC_4706B0_CORE_REV 0x8000001f /* chipcommon core */ -#define SOCRAM_4706B0_CORE_REV 0x80000005 /* internal memory core */ -#define GMAC_4706B0_CORE_REV 0x80000000 /* Gigabit MAC core */ #define NS_PCIEG2_CORE_REV_B0 0x7 /* NS-B0 PCIE Gen 2 core rev */ -/* There are TWO constants on all HND chips: SI_ENUM_BASE above, +/* There are TWO constants on all HND chips: SI_ENUM_BASE_DEFAULT above, * and chipcommon being the first core: */ #define SI_CC_IDX 0 @@ -235,6 +254,7 @@ #define SOCI_AI 1 #define SOCI_UBUS 2 #define SOCI_NAI 3 +#define SOCI_DVTBUS 4 /* BCM7XXX Digital Video Tech bus */ /* Common core control flags */ #define SICF_BIST_EN 0x8000 @@ -258,6 +278,10 @@ #define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ #define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ +/* dot11 core-specific status flags */ +#define SISF_MINORREV_D11_SHIFT 16 +#define SISF_MINORREV_D11_MASK 0xF /**< minor corerev (corerev == 61) */ + /* A register that is common to all cores to * communicate w/PMU regarding clock control. */ @@ -275,6 +299,7 @@ #define CCS_USBCLKREQ 0x00000100 /* USB Clock Req */ #define CCS_SECICLKREQ 0x00000100 /* SECI Clock Req */ #define CCS_ARMFASTCLOCKREQ 0x00000100 /* ARM CR4/CA7 fast clock request */ +#define CCS_SFLASH_CLKREQ 0x00000200 /* Sflash clk request */ #define CCS_AVBCLKREQ 0x00000400 /* AVB Clock enable request */ #define CCS_ERSRC_REQ_MASK 0x00000700 /* external resource requests */ #define CCS_ERSRC_REQ_SHIFT 8 @@ -287,9 +312,6 @@ #define CCS_ERSRC_STS_SHIFT 24 #define CCS_SECI_AVAIL 0x01000000 /* RO: SECI is available */ -#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ -#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ - /* Not really related to SOC Interconnect, but a couple of software * conventions for the use the flash space: */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/linux_osl.h b/drivers/net/wireless/bcmdhd_oo/include/linux_osl.h index 59905b6ad4b7c24c40893525283cdc597cad3ad5..e86b3b77a7e17cb0f7e0798d84325a5183ce5383 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/linux_osl.h +++ b/drivers/net/wireless/bcmdhd_oo/include/linux_osl.h @@ -1,14 +1,14 @@ /* * Linux OS Independent Layer * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: linux_osl.h 672413 2016-11-28 11:13:23Z $ + * $Id: linux_osl.h 737888 2017-12-23 13:20:41Z $ */ #ifndef _linux_osl_h_ @@ -50,6 +50,9 @@ extern int osl_static_mem_init(osl_t *osh, void *adapter); extern int osl_static_mem_deinit(osl_t *osh, void *adapter); extern void osl_set_bus_handle(osl_t *osh, void *bus_handle); extern void* osl_get_bus_handle(osl_t *osh); +#ifdef DHD_MAP_LOGGING +extern void osl_dma_map_dump(void); +#endif /* DHD_MAP_LOGGING */ /* Global ASSERT type */ extern uint32 g_assert_type; @@ -66,6 +69,7 @@ extern uint32 g_assert_type; #define PRI_FMT_d "d" #endif /* CONFIG_PHYS_ADDR_T_64BIT */ /* ASSERT */ +#ifndef ASSERT #if defined(BCMASSERT_LOG) #define ASSERT(exp) \ do { if (!(exp)) osl_assert(#exp, __FILE__, __LINE__); } while (0) @@ -81,7 +85,8 @@ extern void osl_assert(const char *exp, const char *file, int line); #define ASSERT(exp) #endif /* GCC_VERSION > 30100 */ #endif /* __GNUC__ */ -#endif +#endif // endif +#endif /* ASSERT */ /* bcm_prefetch_32B */ static inline void bcm_prefetch_32B(const uint8 *addr, const int cachelines_32B) @@ -93,7 +98,7 @@ static inline void bcm_prefetch_32B(const uint8 *addr, const int cachelines_32B) case 2: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 32) : "cc"); case 1: __asm__ __volatile__("pld\t%a0" :: "p"(addr + 0) : "cc"); } -#endif +#endif // endif } /* microsecond delay */ @@ -139,6 +144,8 @@ typedef struct { pktfree_cb_fn_t tx_fn; /**< Callback function for PKTFREE */ void *tx_ctx; /**< Context to the callback function */ void *unused[3]; + void (*rx_fn)(void *rx_ctx, void *p); + void *rx_ctx; } osl_pubinfo_t; extern void osl_flag_set(osl_t *osh, uint32 mask); @@ -151,6 +158,11 @@ extern bool osl_is_flag_set(osl_t *osh, uint32 mask); ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ } while (0) +#define PKTFREESETRXCB(osh, _rx_fn, _rx_ctx) \ + do { \ + ((osl_pubinfo_t*)osh)->rx_fn = _rx_fn; \ + ((osl_pubinfo_t*)osh)->rx_ctx = _rx_ctx; \ + } while (0) /* host/bus architecture-specific byte swap */ #define BUS_SWAP32(v) (v) @@ -199,10 +211,21 @@ extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t p /* map/unmap shared (dma-able) memory */ #define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ osl_dma_unmap((osh), (pa), (size), (direction)) +extern void osl_dma_flush(osl_t *osh, void *va, uint size, int direction, void *p, + hnddma_seg_map_t *txp_dmah); extern dmaaddr_t 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, dmaaddr_t pa, uint size, int direction); +#ifndef PHYS_TO_VIRT +#define PHYS_TO_VIRT(pa) osl_phys_to_virt(pa) +#endif // endif +#ifndef VIRT_TO_PHYS +#define VIRT_TO_PHYS(va) osl_virt_to_phys(va) +#endif // endif +extern void * osl_phys_to_virt(void * pa); +extern void * osl_virt_to_phys(void * va); + /* API for DMA addressing capability */ #define OSL_DMADDRWIDTH(osh, addrwidth) ({BCM_REFERENCE(osh); BCM_REFERENCE(addrwidth);}) @@ -218,14 +241,14 @@ extern void osl_preempt_enable(osl_t *osh); #define OSL_ENABLE_PREEMPTION(osh) osl_preempt_enable(osh) #if (!defined(DHD_USE_COHERENT_MEM_FOR_RING) && defined(__ARM_ARCH_7A__)) || \ - (defined(STBLINUX) && defined(__ARM_ARCH_7A__)) + defined(STB_SOC_WIFI) extern void osl_cache_flush(void *va, uint size); extern void osl_cache_inv(void *va, uint size); extern void osl_prefetch(const void *ptr); #define OSL_CACHE_FLUSH(va, len) osl_cache_flush((void *)(va), len) #define OSL_CACHE_INV(va, len) osl_cache_inv((void *)(va), len) #define OSL_PREFETCH(ptr) osl_prefetch(ptr) -#if defined(__ARM_ARCH_7A__) +#if defined(__ARM_ARCH_7A__) || defined(STB_SOC_WIFI) extern int osl_arch_is_coherent(void); #define OSL_ARCH_IS_COHERENT() osl_arch_is_coherent() extern int osl_acp_war_enab(void); @@ -241,7 +264,16 @@ extern void osl_preempt_enable(osl_t *osh); #define OSL_ARCH_IS_COHERENT() NULL #define OSL_ACP_WAR_ENAB() NULL -#endif +#endif // endif + +#ifdef BCM_BACKPLANE_TIMEOUT +extern void osl_set_bpt_cb(osl_t *osh, void *bpt_cb, void *bpt_ctx); +extern void osl_bpt_rreg(osl_t *osh, ulong addr, volatile void *v, uint size); +#endif /* BCM_BACKPLANE_TIMEOUT */ + +#if (defined(STB) && defined(__arm__)) +extern void osl_pcie_rreg(osl_t *osh, ulong addr, volatile void *v, uint size); +#endif // endif /* register access macros */ #if defined(BCMSDIO) @@ -250,21 +282,26 @@ extern void osl_preempt_enable(osl_t *osh); (uintptr)(r), sizeof(*(r)), (v))) #define OSL_READ_REG(osh, r) (bcmsdh_reg_read(osl_get_bus_handle(osh), \ (uintptr)(r), sizeof(*(r)))) +#elif defined(BCM_BACKPLANE_TIMEOUT) +#define OSL_READ_REG(osh, r) \ + ({\ + __typeof(*(r)) __osl_v; \ + osl_bpt_rreg(osh, (uintptr)(r), &__osl_v, sizeof(*(r))); \ + __osl_v; \ + }) #elif (defined(STB) && defined(__arm__)) -extern void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size); - #define OSL_READ_REG(osh, r) \ ({\ __typeof(*(r)) __osl_v; \ - osl_pcie_rreg(osh, (uintptr)(r), (void *)&__osl_v, sizeof(*(r))); \ + osl_pcie_rreg(osh, (uintptr)(r), &__osl_v, sizeof(*(r))); \ __osl_v; \ }) -#endif +#endif // endif -#if (defined(STB) && defined(__arm__)) +#if defined(BCM_BACKPLANE_TIMEOUT) || (defined(STB) && defined(__arm__)) #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;}) #define SELECT_BUS_READ(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); bus_op;}) -#else /* !BCM47XX_CA9 */ +#else /* !BCM47XX_CA9 && !BCM_BACKPLANE_TIMEOUT && !(STB && __arm__) */ #if defined(BCMSDIO) #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \ mmap_op else bus_op @@ -273,8 +310,8 @@ extern void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size); #else #define SELECT_BUS_WRITE(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;}) #define SELECT_BUS_READ(osh, mmap_op, bus_op) ({BCM_REFERENCE(osh); mmap_op;}) -#endif -#endif +#endif // endif +#endif // endif #define OSL_ERROR(bcmerror) osl_error(bcmerror) extern int osl_error(int bcmerror); @@ -303,6 +340,9 @@ extern uint64 osl_sysuptime_us(void); #include /* for vsn/printf's */ #include /* for mem*, str* */ /* bcopy's: Linux kernel doesn't provide these (anymore) */ +#define bcopy_hw(src, dst, len) memcpy((dst), (src), (len)) +#define bcopy_hw_async(src, dst, len) memcpy((dst), (src), (len)) +#define bcopy_hw_poll_for_completion() #define bcopy(src, dst, len) memcpy((dst), (src), (len)) #define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) #define bzero(b, len) memset((b), '\0', (len)) @@ -315,6 +355,7 @@ extern uint64 osl_sysuptime_us(void); SELECT_BUS_READ(osh, \ ({ \ __typeof(*(r)) __osl_v = 0; \ + BCM_REFERENCE(osh); \ switch (sizeof(*(r))) { \ case sizeof(uint8): __osl_v = \ readb((volatile uint8*)(r)); break; \ @@ -393,7 +434,7 @@ extern uint64 osl_sysuptime_us(void); #define OSL_GETCYCLES(x) rdtscl((x)) #else #define OSL_GETCYCLES(x) ((x) = 0) -#endif +#endif // endif /* dereference an address that may cause a bus exception */ #define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) @@ -416,283 +457,18 @@ extern uint64 osl_sysuptime_us(void); */ #include /* use current 2.4.x calling conventions */ -/* packet primitives */ -#ifdef BCM_OBJECT_TRACE -#define PKTGET(osh, len, send) osl_pktget((osh), (len), __LINE__, __FUNCTION__) -#define PKTDUP(osh, skb) osl_pktdup((osh), (skb), __LINE__, __FUNCTION__) -#else -#define PKTGET(osh, len, send) osl_pktget((osh), (len)) -#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) -#endif /* BCM_OBJECT_TRACE */ -#define PKTLIST_DUMP(osh, buf) BCM_REFERENCE(osh) -#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh) -#if defined(BCM_OBJECT_TRACE) -#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send), __LINE__, __FUNCTION__) -#else -#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -#endif /* BCM_OBJECT_TRACE */ -#ifdef CONFIG_DHD_USE_STATIC_BUF -#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) -#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) -#else -#define PKTGET_STATIC PKTGET -#define PKTFREE_STATIC PKTFREE -#endif /* CONFIG_DHD_USE_STATIC_BUF */ -#define PKTDATA(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->data);}) -#define PKTLEN(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->len);}) -#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) -#define PKTEXPHEADROOM(osh, skb, b) \ - ({ \ - BCM_REFERENCE(osh); \ - skb_realloc_headroom((struct sk_buff*)(skb), (b)); \ - }) -#define PKTTAILROOM(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - skb_tailroom((struct sk_buff*)(skb)); \ - }) -#define PKTPADTAILROOM(osh, skb, padlen) \ - ({ \ - BCM_REFERENCE(osh); \ - skb_pad((struct sk_buff*)(skb), (padlen)); \ - }) -#define PKTNEXT(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->next);}) -#define PKTSETNEXT(osh, skb, x) \ - ({ \ - BCM_REFERENCE(osh); \ - (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)); \ - }) -#define PKTSETLEN(osh, skb, len) \ - ({ \ - BCM_REFERENCE(osh); \ - __skb_trim((struct sk_buff*)(skb), (len)); \ - }) -#define PKTPUSH(osh, skb, bytes) \ - ({ \ - BCM_REFERENCE(osh); \ - skb_push((struct sk_buff*)(skb), (bytes)); \ - }) -#define PKTPULL(osh, skb, bytes) \ - ({ \ - BCM_REFERENCE(osh); \ - skb_pull((struct sk_buff*)(skb), (bytes)); \ - }) -#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) -#define PKTSETPOOL(osh, skb, x, y) BCM_REFERENCE(osh) -#define PKTPOOL(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) -#define PKTFREELIST(skb) PKTLINK(skb) -#define PKTSETFREELIST(skb, x) PKTSETLINK((skb), (x)) -#define PKTPTR(skb) (skb) -#define PKTID(skb) ({BCM_REFERENCE(skb); 0;}) -#define PKTSETID(skb, id) ({BCM_REFERENCE(skb); BCM_REFERENCE(id);}) -#define PKTSHRINK(osh, m) ({BCM_REFERENCE(osh); m;}) -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && defined(TSQ_MULTIPLIER) -#define PKTORPHAN(skb) osl_pkt_orphan_partial(skb) -extern void osl_pkt_orphan_partial(struct sk_buff *skb); -#else -#define PKTORPHAN(skb) ({BCM_REFERENCE(skb); 0;}) -#endif /* LINUX VERSION >= 3.6 */ - - - -#ifdef CTFPOOL -#define CTFPOOL_REFILL_THRESH 3 -typedef struct ctfpool { - void *head; - spinlock_t lock; - osl_t *osh; - uint max_obj; - uint curr_obj; - uint obj_size; - uint refills; - uint fast_allocs; - uint fast_frees; - uint slow_allocs; -} ctfpool_t; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) -#define FASTBUF (1 << 0) -#define PKTSETFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF); \ - }) -#define PKTCLRFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)); \ - }) -#define PKTISFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF); \ - }) -#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -#define FASTBUF (1 << 16) -#define PKTSETFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF); \ - }) -#define PKTCLRFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->mac_len) &= (~FASTBUF)); \ - }) -#define PKTISFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->mac_len) & FASTBUF); \ - }) -#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) -#else -#define FASTBUF (1 << 0) -#define PKTSETFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->__unused) |= FASTBUF); \ - }) -#define PKTCLRFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->__unused) &= (~FASTBUF)); \ - }) -#define PKTISFAST(osh, skb) \ - ({ \ - BCM_REFERENCE(osh); \ - ((((struct sk_buff*)(skb))->__unused) & FASTBUF); \ - }) -#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) -#endif /* 2.6.22 */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) -#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); -extern int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size); -extern void osl_ctfpool_cleanup(osl_t *osh); -extern void osl_ctfpool_stats(osl_t *osh, void *b); -#else /* CTFPOOL */ -#define PKTSETFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTCLRFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTISFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) -#endif /* CTFPOOL */ - -#define PKTSETCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTCLRCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTISCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) - -#define PKTSETSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTCLRSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define CTF_MARK(m) ({BCM_REFERENCE(m); 0;}) - - -#define PKTSETFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); }) -#define PKTCLRFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); }) -#define PKTISFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) - - -#define PKTSETTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTCLRTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) -#define PKTISTOBR(skb) ({BCM_REFERENCE(skb); FALSE;}) - - -#ifdef BCMFA -#ifdef BCMFA_HW_HASH -#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) -#else -#define PKTSETFAHIDX(skb, idx) ({BCM_REFERENCE(skb); BCM_REFERENCE(idx);}) -#endif /* BCMFA_SW_HASH */ -#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) -#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) -#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) - -#define AUX_TCP_FIN_RST (1 << 0) -#define AUX_FREED (1 << 1) -#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) -#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) -#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) -#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) -#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) -#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) -#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) -#else -#define PKTISFAAUX(skb) ({BCM_REFERENCE(skb); FALSE;}) -#define PKTISFABRIDGED(skb) ({BCM_REFERENCE(skb); FALSE;}) -#define PKTISFAFREED(skb) ({BCM_REFERENCE(skb); FALSE;}) - -#define PKTCLRFAAUX(skb) BCM_REFERENCE(skb) -#define PKTSETFAFREED(skb) BCM_REFERENCE(skb) -#define PKTCLRFAFREED(skb) BCM_REFERENCE(skb) -#endif /* BCMFA */ - -#if defined(BCM_OBJECT_TRACE) -extern void osl_pktfree(osl_t *osh, void *skb, bool send, int line, const char *caller); -#else -extern void osl_pktfree(osl_t *osh, void *skb, bool send); -#endif /* BCM_OBJECT_TRACE */ -extern void *osl_pktget_static(osl_t *osh, uint len); -extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); -extern void osl_pktclone(osl_t *osh, void **pkt); - -#ifdef BCM_OBJECT_TRACE -extern void *osl_pktget(osl_t *osh, uint len, int line, const char *caller); -extern void *osl_pktdup(osl_t *osh, void *skb, int line, const char *caller); -#else -extern void *osl_pktget(osl_t *osh, uint len); -extern void *osl_pktdup(osl_t *osh, void *skb); -#endif /* BCM_OBJECT_TRACE */ -extern void *osl_pkt_frmnative(osl_t *osh, void *skb); -extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); -#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) -#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) - -#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) -#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) -#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) -#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) -#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) -#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ - ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) -/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ -#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 /* !2.6.0 */ -#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) -#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) -#endif /* 2.6.0 */ -#else /* CONFIG_NF_CONNTRACK_MARK */ -#define PKTMARK(p) 0 -#define PKTSETMARK(p, m) -#endif /* CONFIG_NF_CONNTRACK_MARK */ - -#define PKTALLOCED(osh) osl_pktalloced(osh) -extern uint osl_pktalloced(osl_t *osh); - #define OSL_RAND() osl_rand() extern uint32 osl_rand(void); +#define DMA_FLUSH(osh, va, size, direction, p, dmah) \ + osl_dma_flush((osh), (va), (size), (direction), (p), (dmah)) #if !defined(BCM_SECURE_DMA) #define DMA_MAP(osh, va, size, direction, p, dmah) \ osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) #endif /* !(defined(BCM_SECURE_DMA)) */ - #else /* ! BCMDRIVER */ - /* ASSERT */ #define ASSERT(exp) do {} while (0) @@ -717,15 +493,6 @@ extern void bzero(void *b, size_t len); * Adding these dummy values for build apss only * When we revisit need to change these. */ -#if defined(STBLINUX) - -#if defined(__ARM_ARCH_7A__) -#define ACP_WAR_ENAB() 0 -#define ACP_WIN_LIMIT 1 -#define arch_is_coherent() 0 -#endif /* __ARM_ARCH_7A__ */ - -#endif /* STBLINUX */ #ifdef BCM_SECURE_DMA diff --git a/drivers/net/wireless/bcmdhd_oo/include/linux_pkt.h b/drivers/net/wireless/bcmdhd_oo/include/linux_pkt.h new file mode 100644 index 0000000000000000000000000000000000000000..a21954e1b3cf691c3ba10eaed963d19f9891b391 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/linux_pkt.h @@ -0,0 +1,233 @@ +/* + * Linux Packet (skb) interface + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: linux_pkt.h 701430 2017-05-25 00:03:02Z $ + */ + +#ifndef _linux_pkt_h_ +#define _linux_pkt_h_ + +#include + +#ifdef __ARM_ARCH_7A__ +#define PKT_HEADROOM_DEFAULT NET_SKB_PAD /**< NET_SKB_PAD is defined in a linux kernel header */ +#else +#define PKT_HEADROOM_DEFAULT 16 +#endif /* __ARM_ARCH_7A__ */ + +#ifdef BCMDRIVER +/* + * BINOSL selects the slightly slower function-call-based binary compatible osl. + * Macros expand to calls to functions defined in linux_osl.c . + */ +/* Because the non BINOSL implemenation of the PKT OSL routines are macros (for + * performance reasons), we need the Linux headers. + */ +#include + +/* packet primitives */ +#ifdef BCM_OBJECT_TRACE +#define PKTGET(osh, len, send) linux_pktget((osh), (len), __LINE__, __FUNCTION__) +#define PKTDUP(osh, skb) osl_pktdup((osh), (skb), __LINE__, __FUNCTION__) +#else +#define PKTGET(osh, len, send) linux_pktget((osh), (len)) +#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) +#endif /* BCM_OBJECT_TRACE */ +#define PKTLIST_DUMP(osh, buf) BCM_REFERENCE(osh) +#define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh) +#if defined(BCM_OBJECT_TRACE) +#define PKTFREE(osh, skb, send) linux_pktfree((osh), (skb), (send), __LINE__, __FUNCTION__) +#else +#define PKTFREE(osh, skb, send) linux_pktfree((osh), (skb), (send)) +#endif /* BCM_OBJECT_TRACE */ +#ifdef CONFIG_DHD_USE_STATIC_BUF +#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) +#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) +#else +#define PKTGET_STATIC PKTGET +#define PKTFREE_STATIC PKTFREE +#endif /* CONFIG_DHD_USE_STATIC_BUF */ +#define PKTDATA(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->data);}) +#define PKTLEN(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->len);}) +#define PKTHEAD(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->head);}) +#define PKTSETHEAD(osh, skb, h) ({BCM_REFERENCE(osh); \ + (((struct sk_buff *)(skb))->head = (h));}) +#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) +#define PKTEXPHEADROOM(osh, skb, b) \ + ({ \ + BCM_REFERENCE(osh); \ + skb_realloc_headroom((struct sk_buff*)(skb), (b)); \ + }) +#define PKTTAILROOM(osh, skb) \ + ({ \ + BCM_REFERENCE(osh); \ + skb_tailroom((struct sk_buff*)(skb)); \ + }) +#define PKTPADTAILROOM(osh, skb, padlen) \ + ({ \ + BCM_REFERENCE(osh); \ + skb_pad((struct sk_buff*)(skb), (padlen)); \ + }) +#define PKTNEXT(osh, skb) ({BCM_REFERENCE(osh); (((struct sk_buff*)(skb))->next);}) +#define PKTSETNEXT(osh, skb, x) \ + ({ \ + BCM_REFERENCE(osh); \ + (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)); \ + }) +#define PKTSETLEN(osh, skb, len) \ + ({ \ + BCM_REFERENCE(osh); \ + __skb_trim((struct sk_buff*)(skb), (len)); \ + }) +#define PKTPUSH(osh, skb, bytes) \ + ({ \ + BCM_REFERENCE(osh); \ + skb_push((struct sk_buff*)(skb), (bytes)); \ + }) +#define PKTPULL(osh, skb, bytes) \ + ({ \ + BCM_REFERENCE(osh); \ + skb_pull((struct sk_buff*)(skb), (bytes)); \ + }) +#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) +#define PKTSETPOOL(osh, skb, x, y) BCM_REFERENCE(osh) +#define PKTPOOL(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) +#define PKTFREELIST(skb) PKTLINK(skb) +#define PKTSETFREELIST(skb, x) PKTSETLINK((skb), (x)) +#define PKTPTR(skb) (skb) +#define PKTID(skb) ({BCM_REFERENCE(skb); 0;}) +#define PKTSETID(skb, id) ({BCM_REFERENCE(skb); BCM_REFERENCE(id);}) +#define PKTSHRINK(osh, m) ({BCM_REFERENCE(osh); m;}) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && defined(TSQ_MULTIPLIER) +#define PKTORPHAN(skb) osl_pkt_orphan_partial(skb) +extern void osl_pkt_orphan_partial(struct sk_buff *skb); +#else +#define PKTORPHAN(skb) ({BCM_REFERENCE(skb); 0;}) +#endif /* LINUX VERSION >= 3.6 */ + +#define PKTSETFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTCLRFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTISFAST(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) + +#define PKTSETCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTCLRCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTISCTF(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) + +#define PKTSETSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTCLRSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTSKIPCT(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define CTF_MARK(m) ({BCM_REFERENCE(m); 0;}) + +#define PKTFRAGLEN(osh, lb, ix) (0) +#define PKTSETFRAGLEN(osh, lb, ix, len) BCM_REFERENCE(osh) + +#define PKTSETFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); }) +#define PKTCLRFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); }) +#define PKTISFWDERBUF(osh, skb) ({ BCM_REFERENCE(osh); BCM_REFERENCE(skb); FALSE;}) + +#define PKTSETTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTCLRTOBR(osh, skb) ({BCM_REFERENCE(osh); BCM_REFERENCE(skb);}) +#define PKTISTOBR(skb) ({BCM_REFERENCE(skb); FALSE;}) + +#ifdef BCMFA +#ifdef BCMFA_HW_HASH +#define PKTSETFAHIDX(skb, idx) (((struct sk_buff*)(skb))->napt_idx = idx) +#else +#define PKTSETFAHIDX(skb, idx) ({BCM_REFERENCE(skb); BCM_REFERENCE(idx);}) +#endif /* BCMFA_SW_HASH */ +#define PKTGETFAHIDX(skb) (((struct sk_buff*)(skb))->napt_idx) +#define PKTSETFADEV(skb, imp) (((struct sk_buff*)(skb))->dev = imp) +#define PKTSETRXDEV(skb) (((struct sk_buff*)(skb))->rxdev = ((struct sk_buff*)(skb))->dev) + +#define AUX_TCP_FIN_RST (1 << 0) +#define AUX_FREED (1 << 1) +#define PKTSETFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_TCP_FIN_RST) +#define PKTCLRFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_TCP_FIN_RST)) +#define PKTISFAAUX(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_TCP_FIN_RST) +#define PKTSETFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags |= AUX_FREED) +#define PKTCLRFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags &= (~AUX_FREED)) +#define PKTISFAFREED(skb) (((struct sk_buff*)(skb))->napt_flags & AUX_FREED) +#define PKTISFABRIDGED(skb) PKTISFAAUX(skb) +#else +#define PKTISFAAUX(skb) ({BCM_REFERENCE(skb); FALSE;}) +#define PKTISFABRIDGED(skb) ({BCM_REFERENCE(skb); FALSE;}) +#define PKTISFAFREED(skb) ({BCM_REFERENCE(skb); FALSE;}) + +#define PKTCLRFAAUX(skb) BCM_REFERENCE(skb) +#define PKTSETFAFREED(skb) BCM_REFERENCE(skb) +#define PKTCLRFAFREED(skb) BCM_REFERENCE(skb) +#endif /* BCMFA */ + +#if defined(BCM_OBJECT_TRACE) +extern void linux_pktfree(osl_t *osh, void *skb, bool send, int line, const char *caller); +#else +extern void linux_pktfree(osl_t *osh, void *skb, bool send); +#endif /* BCM_OBJECT_TRACE */ +extern void *osl_pktget_static(osl_t *osh, uint len); +extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); +extern void osl_pktclone(osl_t *osh, void **pkt); + +#ifdef BCM_OBJECT_TRACE +extern void *linux_pktget(osl_t *osh, uint len, int line, const char *caller); +extern void *osl_pktdup(osl_t *osh, void *skb, int line, const char *caller); +#else +extern void *linux_pktget(osl_t *osh, uint len); +extern void *osl_pktdup(osl_t *osh, void *skb); +#endif /* BCM_OBJECT_TRACE */ +extern void *osl_pkt_frmnative(osl_t *osh, void *skb); +extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); +#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_t *)osh), (struct sk_buff*)(skb)) +#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_t *)(osh), (pkt)) + +#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) +#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) +#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) +#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) +#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) +#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ + ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) +/* PKTSETSUMNEEDED and PKTSUMGOOD are not possible because skb->ip_summed is overloaded */ +#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 /* !2.6.0 */ +#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) +#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) +#endif /* 2.6.0 */ +#else /* CONFIG_NF_CONNTRACK_MARK */ +#define PKTMARK(p) 0 +#define PKTSETMARK(p, m) +#endif /* CONFIG_NF_CONNTRACK_MARK */ + +#define PKTALLOCED(osh) osl_pktalloced(osh) +extern uint osl_pktalloced(osl_t *osh); + +#endif /* BCMDRIVER */ + +#endif /* _linux_pkt_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/linuxver.h b/drivers/net/wireless/bcmdhd_oo/include/linuxver.h index 271fe2fee96c7214bfb145953214c7a5d831346c..8ef791d6a0a5fdfd96b855c74f4050c2f712fb39 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd_oo/include/linuxver.h @@ -2,14 +2,14 @@ * Linux-specific abstractions to gain some independence from linux kernel versions. * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: linuxver.h 646721 2016-06-30 12:36:41Z $ + * $Id: linuxver.h 646730 2016-06-30 13:01:49Z $ */ #ifndef _linuxver_h_ @@ -35,7 +35,7 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" -#endif +#endif // endif #include #include @@ -46,12 +46,12 @@ #include #else #include -#endif +#endif // endif #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)) #include -#endif +#endif // endif #include #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) @@ -60,21 +60,21 @@ #undef __NO_VERSION__ #else #define __NO_VERSION__ -#endif +#endif // endif #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0) */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) #define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") #define module_param_string(_name_, _string_, _size_, _perm_) \ MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) -#endif +#endif // endif /* linux/malloc.h is deprecated, use linux/slab.h instead. */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) #include #else #include -#endif +#endif // endif #include #include @@ -100,16 +100,16 @@ #include #ifndef work_struct #define work_struct tq_struct -#endif +#endif // endif #ifndef INIT_WORK #define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) -#endif +#endif // endif #ifndef schedule_work #define schedule_work(_work) schedule_task((_work)) -#endif +#endif // endif #ifndef flush_scheduled_work #define flush_scheduled_work() flush_scheduled_tasks() -#endif +#endif // endif #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) @@ -139,7 +139,7 @@ (RHEL_MAJOR == 5)) /* Exclude RHEL 5 */ typedef void (*work_func_t)(void *work); -#endif +#endif // endif #endif /* >= 2.6.20 */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) @@ -149,7 +149,7 @@ typedef void irqreturn_t; #define IRQ_NONE #define IRQ_HANDLED #define IRQ_RETVAL(x) -#endif +#endif // endif #else typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) */ @@ -161,7 +161,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) #ifdef CONFIG_NET_RADIO #define CONFIG_WIRELESS_EXT -#endif +#endif // endif #endif /* < 2.6.17 */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) @@ -179,22 +179,21 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) #include -#endif +#endif // endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29) #include #else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) #include -#endif +#endif // endif #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30) */ - #ifndef __exit #define __exit -#endif +#endif // endif #ifndef __devexit #define __devexit -#endif +#endif // endif #ifndef __devinit # if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0)) # define __devinit __init @@ -205,10 +204,10 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); #endif /* !__devinit */ #ifndef __devinitdata #define __devinitdata -#endif +#endif // endif #ifndef __devexit_p #define __devexit_p(x) x -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) @@ -251,7 +250,7 @@ extern void pci_unregister_driver(struct pci_driver *drv); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) #define pci_module_init pci_register_driver -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) #ifdef MODULE @@ -260,39 +259,39 @@ extern void pci_unregister_driver(struct pci_driver *drv); #else #define module_init(x) __initcall(x); #define module_exit(x) __exitcall(x); -#endif +#endif // endif #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18) */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) #define WL_USE_NETDEV_OPS #else #undef WL_USE_NETDEV_OPS -#endif +#endif // endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) && defined(CONFIG_RFKILL) #define WL_CONFIG_RFKILL #else #undef WL_CONFIG_RFKILL -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) #define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) #elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) #define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) #define pci_enable_device(dev) do { } while (0) -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) #define net_device device -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) @@ -305,7 +304,7 @@ extern void pci_unregister_driver(struct pci_driver *drv); #ifndef PCI_DMA_TODEVICE #define PCI_DMA_TODEVICE 1 #define PCI_DMA_FROMDEVICE 2 -#endif +#endif // endif typedef u32 dma_addr_t; @@ -444,7 +443,7 @@ static inline void tasklet_init(struct tasklet_struct *tasklet, #else #define PCI_SAVE_STATE(a, b) pci_save_state(a, b) #define PCI_RESTORE_STATE(a, b) pci_restore_state(a, b) -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) static inline int @@ -487,7 +486,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer) /* Old cp0 access macros deprecated in 2.4.19 */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) #define read_c0_count() read_32bit_cp0_register(CP0_COUNT) -#endif +#endif // endif /* Module refcount handled internally in 2.6.x */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) @@ -498,46 +497,46 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer) #else #define OLD_MOD_INC_USE_COUNT do {} while (0) #define OLD_MOD_DEC_USE_COUNT do {} while (0) -#endif +#endif // endif #else /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ #ifndef SET_MODULE_OWNER #define SET_MODULE_OWNER(dev) do {} while (0) -#endif +#endif // endif #ifndef MOD_INC_USE_COUNT #define MOD_INC_USE_COUNT do {} while (0) -#endif +#endif // endif #ifndef MOD_DEC_USE_COUNT #define MOD_DEC_USE_COUNT do {} while (0) -#endif +#endif // endif #define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT #define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) */ #ifndef SET_NETDEV_DEV #define SET_NETDEV_DEV(net, pdev) do {} while (0) -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0)) #ifndef HAVE_FREE_NETDEV #define free_netdev(dev) kfree(dev) -#endif +#endif // endif #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) */ #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) /* struct packet_type redefined in 2.6.x */ #define af_packet_priv data -#endif +#endif // endif /* suspend args */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) #define DRV_SUSPEND_STATE_TYPE pm_message_t #else #define DRV_SUSPEND_STATE_TYPE uint32 -#endif +#endif // endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) #define CHECKSUM_HW CHECKSUM_PARTIAL -#endif +#endif // endif typedef struct { void *parent; /* some external entity that the thread supposed to work for */ @@ -552,14 +551,13 @@ typedef struct { int up_cnt; } tsk_ctl_t; - /* requires tsk_ctl_t tsk argument, the caller's priv data is passed in owner ptr */ /* note this macro assumes there may be only one context waiting on thread's completion */ #ifdef DHD_DEBUG #define DBG_THR(x) printk x #else #define DBG_THR(x) -#endif +#endif // endif static inline bool binary_sema_down(tsk_ctl_t *tsk) { @@ -603,7 +601,7 @@ static inline bool binary_sema_up(tsk_ctl_t *tsk) #define SMP_RD_BARRIER_DEPENDS(x) smp_read_barrier_depends(x) #else #define SMP_RD_BARRIER_DEPENDS(x) smp_rmb(x) -#endif +#endif // endif #define PROC_START(thread_func, owner, tsk_ctl, flags, name) \ { \ @@ -614,9 +612,9 @@ static inline bool binary_sema_up(tsk_ctl_t *tsk) (tsk_ctl)->terminated = FALSE; \ (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \ if (IS_ERR((tsk_ctl)->p_task)) { \ - (tsk_ctl)->thr_pid = DHD_PID_KT_INVALID; \ - DBG_THR(("%s(): thread:%s:%lx failed\n", __FUNCTION__, \ - (tsk_ctl)->proc_name, (tsk_ctl)->thr_pid)); \ + (tsk_ctl)->thr_pid = -1; \ + DBG_THR(("%s(): thread:%s create failed\n", __FUNCTION__, \ + (tsk_ctl)->proc_name)); \ } else { \ (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \ spin_lock_init(&((tsk_ctl)->spinlock)); \ @@ -661,7 +659,7 @@ if (tsk) send_sig(sig, tsk, 1); \ { \ kill_proc(pid, sig, 1); \ } -#endif +#endif // endif #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) @@ -713,7 +711,7 @@ not match our unaligned address for < 2.6.24 #define DEV_PRIV(dev) (dev->priv) #else #define DEV_PRIV(dev) netdev_priv(dev) -#endif +#endif // endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) #define WL_ISR(i, d, p) wl_isr((i), (d)) @@ -729,7 +727,7 @@ not match our unaligned address for < 2.6.24 #define CAN_SLEEP() ((!in_atomic() && !irqs_disabled())) #else #define CAN_SLEEP() (FALSE) -#endif +#endif // endif #define KMALLOC_FLAG (CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC) @@ -762,7 +760,7 @@ not match our unaligned address for < 2.6.24 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) #pragma GCC diagnostic pop -#endif +#endif // endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0)) static inline struct inode *file_inode(const struct file *f) diff --git a/drivers/net/wireless/bcmdhd_oo/include/lpflags.h b/drivers/net/wireless/bcmdhd_oo/include/lpflags.h new file mode 100644 index 0000000000000000000000000000000000000000..dad31c5123cb6cb823f90fa6400339a4a3b49f17 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/lpflags.h @@ -0,0 +1,45 @@ +/* + * Chip related low power flags + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: lpflags.h 592839 2015-10-14 14:19:09Z $ + */ +#ifndef _lpflags_h_ +#define _lpflags_h_ + +/* Chip related low power flags (lpflags) */ +#define LPFLAGS_SI_GLOBAL_DISABLE (1 << 0) +#define LPFLAGS_SI_MEM_STDBY_DISABLE (1 << 1) +#define LPFLAGS_SI_SFLASH_DISABLE (1 << 2) +#define LPFLAGS_SI_BTLDO3P3_DISABLE (1 << 3) +#define LPFLAGS_SI_GCI_FORCE_REGCLK_DISABLE (1 << 4) +#define LPFLAGS_SI_FORCE_PWM_WHEN_RADIO_ON (1 << 5) +#define LPFLAGS_SI_DS0_SLEEP_PDA_DISABLE (1 << 6) +#define LPFLAGS_SI_DS1_SLEEP_PDA_DISABLE (1 << 7) +#define LPFLAGS_PHY_GLOBAL_DISABLE (1 << 16) +#define LPFLAGS_PHY_LP_DISABLE (1 << 17) +#define LPFLAGS_PSM_PHY_CTL (1 << 18) + +#endif /* _lpflags_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/msgtrace.h b/drivers/net/wireless/bcmdhd_oo/include/msgtrace.h index a2da1d3c7967a9d176d08e93eb14d1d367f9965b..3e143c5c5e8c45501e473e988019ecc2bdaf207e 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/msgtrace.h +++ b/drivers/net/wireless/bcmdhd_oo/include/msgtrace.h @@ -1,14 +1,14 @@ /* * Trace messages sent over HBUS * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,7 +32,7 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include diff --git a/drivers/net/wireless/bcmdhd_oo/include/nan.h b/drivers/net/wireless/bcmdhd_oo/include/nan.h index 4534414fbc38938d46e585d352b626830fdb82ea..4cb2a4396574723872744035203c63e290b3fbeb 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/nan.h +++ b/drivers/net/wireless/bcmdhd_oo/include/nan.h @@ -2,14 +2,14 @@ * Fundamental types and constants relating to WFA NAN * (Neighbor Awareness Networking) * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: nan.h 700076 2017-05-17 14:42:22Z $ + * $Id: nan.h 736626 2017-12-17 10:08:43Z $ */ #ifndef _NAN_H_ #define _NAN_H_ @@ -33,7 +33,6 @@ #include #include <802.11.h> - /* This marks the start of a packed structure section. */ #include @@ -88,6 +87,10 @@ #define NAN_OPERATING_CLASS_LEN 1 /* operating class field length from NAN FAM */ #define NAN_CHANNEL_NUM_LEN 1 /* channel number field length 1 byte */ +/* generic nan attribute total length */ +#define NAN_ATTR_TOT_LEN(_nan_attr) (ltoh16_ua(((const uint8 *)(_nan_attr)) + \ + NAN_ATTR_ID_LEN) + NAN_ATTR_HDR_LEN) + /* NAN slot duration / period */ #define NAN_MIN_TU 16 #define NAN_TU_PER_DW 512 @@ -106,9 +109,9 @@ #define NAN_SLOT_DUR_4096TU 4096 #define NAN_SLOT_DUR_8192TU 8192 -#define NAN_MAP_ID_2G 2 /* NAN Further Avail Map ID for band 2.4G */ -#define NAN_MAP_ID_5G 5 /* NAN Further Avail Map ID for band 5G */ -#define NAN_MAP_NUM_IDS 2 /* Max number of NAN Further Avail Map IDs supported */ +#define NAN_SOC_CHAN_2G 6 /* NAN 2.4G discovery channel */ +#define NAN_SOC_CHAN_5G_CH149 149 /* NAN 5G discovery channel if upper band allowed */ +#define NAN_SOC_CHAN_5G_CH44 44 /* NAN 5G discovery channel if only lower band allowed */ /* size of ndc id */ #define NAN_DATA_NDC_ID_SIZE 6 @@ -315,7 +318,8 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_avail_entry_s { #define NAN_VENDOR_TYPE_RTT 0 #define NAN_VENDOR_TYPE_P2P 1 -/* Vendor Specific Attribute */ +/* Vendor Specific Attribute - old definition */ +/* TODO remove */ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_vendor_attr_s { uint8 id; /* 0xDD */ uint16 len; /* IE length */ @@ -326,6 +330,14 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_vendor_attr_s { #define NAN_VENDOR_HDR_SIZE (OFFSETOF(wifi_nan_vendor_attr_t, attr)) +/* vendor specific attribute */ +typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_vndr_attr_s { + uint8 id; /* 0xDD */ + uint16 len; /* length of following fields */ + uint8 oui[DOT11_OUI_LEN]; /* vendor specific OUI */ + uint8 body[]; +} BWL_POST_PACKED_STRUCT wifi_nan_vndr_attr_t; + /* p2p operation attribute */ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_p2p_op_attr_s { /* Attribute ID - 0x06. */ @@ -625,6 +637,7 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_channel_entry_s { (*(uint8 *)(((wifi_nan_avail_entry_attr_t *)avail_entry)->var + 2)) #define NAN_AVAIL_CHAN_LIST_HDR_LEN 1 +#define NAN_AVAIL_CHAN_LIST_TYPE_BAND 0x00 #define NAN_AVAIL_CHAN_LIST_TYPE_CHANNEL 0x01 #define NAN_AVAIL_CHAN_LIST_NON_CONTIG_BW 0x02 #define NAN_AVAIL_CHAN_LIST_NUM_ENTRIES_MASK 0xF0 @@ -800,7 +813,6 @@ enum #define NAN_NDL_CONFIRM(_ndl) (((_ndl)->type_status & NAN_NDL_TYPE_MASK) == \ NDL_ATTR_TYPE_STATUS_CONFIRM) - #define NAN_NDL_STATUS_SHIFT 4 #define NAN_NDL_STATUS_MASK 0xF0 #define NAN_NDL_CONT(_ndl) (((_ndl)->type_status & NAN_NDL_STATUS_MASK) == \ @@ -863,6 +875,15 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_dev_cap_s { uint8 capabilities; /* DFS Master, Extended key id etc */ } BWL_POST_PACKED_STRUCT wifi_nan_dev_cap_t; +/* map id related */ + +/* all maps */ +#define NAN_DEV_CAP_ALL_MAPS_FLAG_MASK 0x1 /* nan default map control */ +#define NAN_DEV_CAP_ALL_MAPS_FLAG_SHIFT 0 +/* map id */ +#define NAN_DEV_CAP_MAPID_MASK 0x1E +#define NAN_DEV_CAP_MAPID_SHIFT 1 + /* Awake DW Info field format */ /* 2.4GHz DW */ @@ -900,9 +921,13 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_dev_cap_s { #define NAN_DEV_CAP_OP_PAGING_NDL 0x08 #define NAN_DEV_CAP_OP_MODE_VHT_MASK 0x01 -#define NAN_DEV_CAP_OP_MODE_VHT8080_MASK 0x03 -#define NAN_DEV_CAP_OP_MODE_VHT160_MASK 0x05 +#define NAN_DEV_CAP_OP_MODE_VHT_SHIFT 0 +#define NAN_DEV_CAP_OP_MODE_VHT8080_MASK 0x02 +#define NAN_DEV_CAP_OP_MODE_VHT8080_SHIFT 1 +#define NAN_DEV_CAP_OP_MODE_VHT160_MASK 0x04 +#define NAN_DEV_CAP_OP_MODE_VHT160_SHIFT 2 #define NAN_DEV_CAP_OP_MODE_PAGING_NDL_MASK 0x08 +#define NAN_DEV_CAP_OP_MODE_PAGING_NDL_SHIFT 3 #define NAN_DEV_CAP_RX_ANT_SHIFT 4 #define NAN_DEV_CAP_TX_ANT_MASK 0x0F @@ -1119,6 +1144,7 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_sched_entry_s { uint8 tbmp[]; /* time bitmap - Optional */ } BWL_POST_PACKED_STRUCT wifi_nan_sched_entry_t; +#define NAN_SCHED_ENTRY_MAPID_MASK 0x0F #define NAN_SCHED_ENTRY_MIN_SIZE OFFSETOF(wifi_nan_sched_entry_t, tbmp) #define NAN_SCHED_ENTRY_SIZE(_entry) (NAN_SCHED_ENTRY_MIN_SIZE + (_entry)->tbmp_len) @@ -1201,6 +1227,16 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_desc_ext_attr_s { } BWL_POST_PACKED_STRUCT wifi_nan_svc_desc_ext_attr_t; #define NAN_SDE_ATTR_MIN_LEN OFFSETOF(wifi_nan_svc_desc_ext_attr_t, var) +#define NAN_SDE_ATTR_RANGE_LEN 4 +#define NAN_SDE_ATTR_SUI_LEN 1 +#define NAN_SDE_ATTR_INFO_LEN_PARAM_LEN 2 +#define NAN_SDE_ATTR_RANGE_INGRESS_LEN 2 +#define NAN_SDE_ATTR_RANGE_EGRESS_LEN 2 +#define NAN_SDE_ATTR_CTRL_LEN 2 +/* max length of variable length field (matching filter, service response filter, + * or service info) in service descriptor attribute + */ +#define NAN_DISC_SDA_FIELD_MAX_LEN 255 /* SDEA control field bit definitions and access macros */ #define NAN_SDE_CF_FSD_REQUIRED (1 << 0) @@ -1213,6 +1249,8 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_desc_ext_attr_s { #define NAN_SDE_CF_RANGING_REQUIRED (1 << 7) #define NAN_SDE_CF_RANGE_PRESENT (1 << 8) #define NAN_SDE_CF_SVC_UPD_IND_PRESENT (1 << 9) +/* Using Reserved Bits as per Spec */ +#define NAN_SDE_CF_LIFE_CNT_PUB_RX (1 << 15) #define NAN_SDE_FSD_REQUIRED(_sde) ((_sde)->control & NAN_SDE_CF_FSD_REQUIRED) #define NAN_SDE_FSD_GAS(_sde) ((_sde)->control & NAN_SDE_CF_FSD_GAS) #define NAN_SDE_DP_REQUIRED(_sde) ((_sde)->control & NAN_SDE_CF_DP_REQUIRED) @@ -1223,6 +1261,7 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_svc_desc_ext_attr_s { #define NAN_SDE_RANGING_REQUIRED(_sde) ((_sde)->control & NAN_SDE_CF_RANGING_REQUIRED) #define NAN_SDE_RANGE_PRESENT(_sde) ((_sde)->control & NAN_SDE_CF_RANGE_PRESENT) #define NAN_SDE_SVC_UPD_IND_PRESENT(_sde) ((_sde)->control & NAN_SDE_CF_SVC_UPD_IND_PRESENT) +#define NAN_SDE_LIFE_COUNT_FOR_PUB_RX(_sde) (_sde & NAN_SDE_CF_LIFE_CNT_PUB_RX) /* nan2 security */ @@ -1445,7 +1484,6 @@ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_mcast_sched_attr_s { uint8 var[]; /* multicast sched entry list (schedule_entry_list) */ } BWL_POST_PACKED_STRUCT wifi_nan_mcast_sched_attr_t; - /* FAC Channel Entry (section 10.7.19.1.5) */ typedef BWL_PRE_PACKED_STRUCT struct wifi_nan_fac_chan_entry_s { uint8 oper_class; /* Operating Class */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/osl.h b/drivers/net/wireless/bcmdhd_oo/include/osl.h index abdcf4518833f3c0deb058005506945685dc4c3c..a883665596c9d0ce4c5f7ac0c3bd6454d8e2e18d 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/osl.h +++ b/drivers/net/wireless/bcmdhd_oo/include/osl.h @@ -1,14 +1,14 @@ /* * OS Abstraction Layer * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: osl.h 642189 2016-06-07 21:12:50Z $ + * $Id: osl.h 729333 2017-10-31 12:16:35Z $ */ #ifndef _osl_h_ @@ -32,6 +32,12 @@ #include +enum { + TAIL_BYTES_TYPE_FCS = 1, + TAIL_BYTES_TYPE_ICV = 2, + TAIL_BYTES_TYPE_MIC = 3 +}; + #define OSL_PKTTAG_SZ 32 /* Size of PktTag */ /* Drivers use PKTFREESETCB to register a callback function when a packet is freed by OSL */ @@ -41,16 +47,16 @@ typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); typedef unsigned int (*osl_rreg_fn_t)(void *ctx, volatile void *reg, unsigned int size); typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, unsigned int size); - #if defined(WL_UNITTEST) #include #else #include -#endif +#include +#endif // endif #ifndef PKTDBG_TRACE #define PKTDBG_TRACE(osh, pkt, bit) BCM_REFERENCE(osh) -#endif +#endif // endif #define PKTCTFMAP(osh, p) BCM_REFERENCE(osh) @@ -70,24 +76,35 @@ typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, #if !defined(OSL_SYSUPTIME) #define OSL_SYSUPTIME() (0) -#define OSL_SYSUPTIME_SUPPORT FALSE -#else -#define OSL_SYSUPTIME_SUPPORT TRUE -#endif /* OSL_SYSUPTIME */ +#define OSL_SYSUPTIME_NOT_DEFINED 1 +#endif /* !defined(OSL_SYSUPTIME) */ #if !defined(OSL_SYSUPTIME_US) #define OSL_SYSUPTIME_US() (0) +#define OSL_SYSUPTIME_US_NOT_DEFINED 1 +#endif /* !defined(OSL_SYSUPTIME) */ + +#if defined(OSL_SYSUPTIME_NOT_DEFINED) && defined(OSL_SYSUPTIME_US_NOT_DEFINED) +#define OSL_SYSUPTIME_SUPPORT FALSE +#else +#define OSL_SYSUPTIME_SUPPORT TRUE #endif /* OSL_SYSUPTIME */ #ifndef OSL_SYS_HALT #define OSL_SYS_HALT() do {} while (0) -#endif +#endif // endif + +#ifndef DMB +#if defined(STB) +#define DMB() mb(); +#else /* STB */ +#define DMB() do {} while (0) +#endif /* STB */ +#endif /* DMB */ #ifndef OSL_MEM_AVAIL #define OSL_MEM_AVAIL() (0xffffffff) -#endif - -#if !defined(PKTC_DONGLE) +#endif // endif #ifndef OSL_OBFUSCATE_BUF /* For security reasons printing pointers is not allowed. @@ -98,6 +115,8 @@ typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, #define OSL_OBFUSCATE_BUF(x) (x) #endif /* OSL_OBFUSCATE_BUF */ +#if !defined(PKTC_DONGLE) + #define PKTCGETATTR(skb) (0) #define PKTCSETATTR(skb, f, p, b) BCM_REFERENCE(skb) #define PKTCCLRATTR(skb) BCM_REFERENCE(skb) @@ -125,109 +144,146 @@ do { \ (h) = (t) = (p); \ } \ } while (0) -#endif +#endif // endif +#ifndef PKTSETCHAINED #define PKTSETCHAINED(osh, skb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTCLRCHAINED #define PKTCLRCHAINED(osh, skb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTISCHAINED #define PKTISCHAINED(skb) FALSE +#endif // endif /* Lbuf with fraglist */ #ifndef PKTFRAGPKTID #define PKTFRAGPKTID(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETFRAGPKTID #define PKTSETFRAGPKTID(osh, lb, id) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTFRAGTOTNUM #define PKTFRAGTOTNUM(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETFRAGTOTNUM #define PKTSETFRAGTOTNUM(osh, lb, tot) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTFRAGTOTLEN #define PKTFRAGTOTLEN(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETFRAGTOTLEN #define PKTSETFRAGTOTLEN(osh, lb, len) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTIFINDEX #define PKTIFINDEX(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETIFINDEX #define PKTSETIFINDEX(osh, lb, idx) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTGETLF #define PKTGETLF(osh, len, send, lbuf_type) (0) -#endif +#endif // endif /* in rx path, reuse totlen as used len */ #ifndef PKTFRAGUSEDLEN #define PKTFRAGUSEDLEN(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETFRAGUSEDLEN #define PKTSETFRAGUSEDLEN(osh, lb, len) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTFRAGLEN #define PKTFRAGLEN(osh, lb, ix) (0) -#endif +#endif // endif #ifndef PKTSETFRAGLEN #define PKTSETFRAGLEN(osh, lb, ix, len) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTFRAGDATA_LO #define PKTFRAGDATA_LO(osh, lb, ix) (0) -#endif +#endif // endif #ifndef PKTSETFRAGDATA_LO #define PKTSETFRAGDATA_LO(osh, lb, ix, addr) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTFRAGDATA_HI #define PKTFRAGDATA_HI(osh, lb, ix) (0) -#endif +#endif // endif #ifndef PKTSETFRAGDATA_HI #define PKTSETFRAGDATA_HI(osh, lb, ix, addr) BCM_REFERENCE(osh) -#endif +#endif // endif /* RX FRAG */ #ifndef PKTISRXFRAG #define PKTISRXFRAG(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETRXFRAG #define PKTSETRXFRAG(osh, lb) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTRESETRXFRAG #define PKTRESETRXFRAG(osh, lb) BCM_REFERENCE(osh) -#endif +#endif // endif /* TX FRAG */ #ifndef PKTISTXFRAG #define PKTISTXFRAG(osh, lb) (0) -#endif +#endif // endif #ifndef PKTSETTXFRAG #define PKTSETTXFRAG(osh, lb) BCM_REFERENCE(osh) -#endif +#endif // endif /* Need Rx completion used for AMPDU reordering */ #ifndef PKTNEEDRXCPL #define PKTNEEDRXCPL(osh, lb) (TRUE) -#endif +#endif // endif #ifndef PKTSETNORXCPL #define PKTSETNORXCPL(osh, lb) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTRESETNORXCPL #define PKTRESETNORXCPL(osh, lb) BCM_REFERENCE(osh) -#endif +#endif // endif #ifndef PKTISFRAG #define PKTISFRAG(osh, lb) (0) -#endif +#endif // endif #ifndef PKTFRAGISCHAINED #define PKTFRAGISCHAINED(osh, i) (0) -#endif +#endif // endif /* TRIM Tail bytes from lfrag */ #ifndef PKTFRAG_TRIM_TAILBYTES #define PKTFRAG_TRIM_TAILBYTES(osh, p, len, type) PKTSETLEN(osh, p, PKTLEN(osh, p) - len) -#endif +#endif // endif #ifndef PKTISHDRCONVTD #define PKTISHDRCONVTD(osh, lb) (0) -#endif +#endif // endif + +/* Forwarded pkt indication */ +#ifndef PKTISFRWDPKT +#define PKTISFRWDPKT(osh, lb) 0 +#endif // endif +#ifndef PKTSETFRWDPKT +#define PKTSETFRWDPKT(osh, lb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTRESETFRWDPKT +#define PKTRESETFRWDPKT(osh, lb) BCM_REFERENCE(osh) +#endif // endif + +/* SFD Frame */ +#ifndef PKTISSFDFRAME +#define PKTISSFDFRAME(osh, lb) (0) +#endif // endif +#ifndef PKTSETSFDFRAME +#define PKTSETSFDFRAME(osh, lb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTRESETSFDFRAME +#define PKTRESETSFDFRAME(osh, lb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTISSFDTXC +#define PKTISSFDTXC(osh, lb) (0) +#endif // endif +#ifndef PKTSETSFDTXC +#define PKTSETSFDTXC(osh, lb) BCM_REFERENCE(osh) +#endif // endif +#ifndef PKTRESETSFDTXC +#define PKTRESETSFDTXC(osh, lb) BCM_REFERENCE(osh) +#endif // endif #ifdef BCM_SECURE_DMA #define SECURE_DMA_ENAB(osh) (1) @@ -237,22 +293,69 @@ do { \ #ifndef BCMDMA64OSL #define SECURE_DMA_MAP(osh, va, size, direction, p, dmah, pcma, offset) ((dmaaddr_t) ((0))) #else -#define SECURE_DMA_MAP(osh, va, size, direction, p, dmah, pcma, offset) ((dmaaddr_t) {(0)}) -#endif +#define SECURE_DMA_MAP(osh, va, size, direction, p, dmah, pcma, offset) \ + ((dmaaddr_t) {.hiaddr = 0, .loaddr = 0}) +#endif // endif #define SECURE_DMA_DD_MAP(osh, va, size, direction, p, dmah) 0 #ifndef BCMDMA64OSL #define SECURE_DMA_MAP_TXMETA(osh, va, size, direction, p, dmah, pcma) ((dmaaddr_t) ((0))) #else -#define SECURE_DMA_MAP_TXMETA(osh, va, size, direction, p, dmah, pcma) ((dmaaddr_t) {(0)}) -#endif +#define SECURE_DMA_MAP_TXMETA(osh, va, size, direction, p, dmah, pcma) \ + ((dmaaddr_t) {.hiaddr = 0, .loaddr = 0}) +#endif // endif #define SECURE_DMA_UNMAP(osh, pa, size, direction, p, dmah, pcma, offset) #define SECURE_DMA_UNMAP_ALL(osh, pcma) #endif /* BCMDMA64OSL */ - #ifndef ROMMABLE_ASSERT #define ROMMABLE_ASSERT(exp) ASSERT(exp) #endif /* ROMMABLE_ASSERT */ +#ifndef MALLOC_NOPERSIST + #define MALLOC_NOPERSIST MALLOC +#endif /* !MALLOC_NOPERSIST */ + +#ifndef MALLOC_PERSIST + #define MALLOC_PERSIST MALLOC +#endif /* !MALLOC_PERSIST */ + +#ifndef MALLOC_NOPERSIST + #define MALLOC_NOPERSIST MALLOC +#endif /* !MALLOC_NOPERSIST */ + +#ifndef MALLOC_PERSIST_ATTACH + #define MALLOC_PERSIST_ATTACH MALLOC +#endif /* !MALLOC_PERSIST_ATTACH */ + +#ifndef MALLOCZ_PERSIST_ATTACH + #define MALLOCZ_PERSIST_ATTACH MALLOCZ +#endif /* !MALLOCZ_PERSIST_ATTACH */ + +#ifndef MALLOCZ_NOPERSIST + #define MALLOCZ_NOPERSIST MALLOCZ +#endif /* !MALLOCZ_NOPERSIST */ + +#ifndef MALLOCZ_PERSIST + #define MALLOCZ_PERSIST MALLOCZ +#endif /* !MALLOCZ_PERSIST */ + +#ifndef MFREE_PERSIST + #define MFREE_PERSIST MFREE +#endif /* !MFREE_PERSIST */ + +#ifndef MALLOC_SET_NOPERSIST + #define MALLOC_SET_NOPERSIST(osh) do { } while (0) +#endif /* !MALLOC_SET_NOPERSIST */ + +#ifndef MALLOC_CLEAR_NOPERSIST + #define MALLOC_CLEAR_NOPERSIST(osh) do { } while (0) +#endif /* !MALLOC_CLEAR_NOPERSIST */ + +#if defined(OSL_MEMCHECK) +#define MEMCHECK(f, l) osl_memcheck(f, l) +#else +#define MEMCHECK(f, l) +#endif /* OSL_MEMCHECK */ + #endif /* _osl_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/osl_decl.h b/drivers/net/wireless/bcmdhd_oo/include/osl_decl.h index 977a1ca46073e23193001c213f703e05584f5d54..8b487de0a613de74c43d7257f2d61ea8dd577bee 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/osl_decl.h +++ b/drivers/net/wireless/bcmdhd_oo/include/osl_decl.h @@ -1,14 +1,14 @@ /* * osl forward declarations * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -34,4 +34,4 @@ typedef struct osl_info osl_t; typedef struct osl_dmainfo osldma_t; extern unsigned int lmtest; /* low memory test */ -#endif +#endif // endif diff --git a/drivers/net/wireless/bcmdhd_oo/include/osl_ext.h b/drivers/net/wireless/bcmdhd_oo/include/osl_ext.h index 2503f6a37a02fb18ca3d87e51a4173143c37fadb..1d81985736a1b14d377cd645c89024a00b4976b7 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/osl_ext.h +++ b/drivers/net/wireless/bcmdhd_oo/include/osl_ext.h @@ -2,14 +2,14 @@ * OS Abstraction Layer Extension - the APIs defined by the "extension" API * are only supported by a subset of all operating systems. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,13 +25,12 @@ * * <> * - * $Id: osl_ext.h 611959 2016-01-12 15:23:56Z $ + * $Id: osl_ext.h 627993 2016-03-29 10:07:29Z $ */ #ifndef _osl_ext_h_ #define _osl_ext_h_ - /* ---- Include Files ---------------------------------------------------- */ #if defined(TARGETOS_symbian) @@ -41,14 +40,14 @@ #include #else #define OSL_EXT_DISABLED -#endif +#endif // endif /* Include base operating system abstraction. */ #include #ifdef __cplusplus extern "C" { -#endif +#endif // endif /* ---- Constants and Types ---------------------------------------------- */ @@ -66,6 +65,7 @@ typedef enum osl_ext_status_t #define OSL_EXT_TIME_FOREVER ((osl_ext_time_ms_t)(-1)) typedef unsigned int osl_ext_time_ms_t; +typedef unsigned int osl_ext_time_us_t; typedef unsigned int osl_ext_event_bits_t; @@ -88,7 +88,6 @@ typedef enum typedef void* osl_ext_timer_arg_t; typedef void (*osl_ext_timer_callback)(osl_ext_timer_arg_t arg); - /* ----------------------------------------------------------------------- * Tasks. */ @@ -114,13 +113,11 @@ typedef enum OSL_EXT_TASK_NUM_PRIORITES } osl_ext_task_priority_t; - #ifndef OSL_EXT_DISABLED /* ---- Variable Externs ------------------------------------------------- */ /* ---- Function Prototypes ---------------------------------------------- */ - /* -------------------------------------------------------------------------- ** Semaphore */ @@ -188,7 +185,6 @@ osl_ext_status_t osl_ext_sem_give(osl_ext_sem_t *sem); */ osl_ext_status_t osl_ext_sem_take(osl_ext_sem_t *sem, osl_ext_time_ms_t timeout_msec); - /* -------------------------------------------------------------------------- ** Mutex */ @@ -251,7 +247,6 @@ osl_ext_status_t osl_ext_mutex_acquire(osl_ext_mutex_t *mutex, osl_ext_time_ms_t */ osl_ext_status_t osl_ext_mutex_release(osl_ext_mutex_t *mutex); - /* -------------------------------------------------------------------------- ** Timers */ @@ -309,6 +304,23 @@ osl_ext_status_t osl_ext_timer_start(osl_ext_timer_t *timer, osl_ext_time_ms_t timeout_msec, osl_ext_timer_mode_t mode); +/**************************************************************************** +* Function: osl_ext_timer_start +* +* Purpose: Start a previously created timer object. +* +* Parameters: timer (in) Timer object. +* timeout_usec (in) Invoke callback after this number of micro-seconds. +* mode (in) One-shot or periodic timer. +* +* Returns: OSL_EXT_SUCCESS if the timer was created successfully, or an +* error code if the timer could not be created. +***************************************************************************** +*/ +osl_ext_status_t +osl_ext_timer_start_us(osl_ext_timer_t *timer, + osl_ext_time_us_t timeout_usec, osl_ext_timer_mode_t mode); + /**************************************************************************** * Function: osl_ext_timer_stop * @@ -359,12 +371,31 @@ osl_ext_time_ms_t osl_ext_time_get(void); #define osl_ext_task_create(name, stack, stack_size, priority, func, arg, task) \ osl_ext_task_create_ex((name), (stack), (stack_size), (priority), 0, (func), \ - (arg), (task)) + (arg), TRUE, (task)) + +/**************************************************************************** +* Function: osl_ext_task_create_ex +* +* Purpose: Create a task with autostart option. +* +* Parameters: name (in) Pointer to task string descriptor. +* stack (in) Pointer to stack. NULL to allocate. +* stack_size (in) Stack size - in bytes. +* priority (in) Abstract task priority. +* func (in) A pointer to the task entry point function. +* arg (in) Value passed into task entry point function. +* autostart (in) TRUE to start task after creation. +* task (out) Task to create. +* +* Returns: OSL_EXT_SUCCESS if the task was created successfully, or an +* error code if the task could not be created. +***************************************************************************** +*/ osl_ext_status_t osl_ext_task_create_ex(char* name, void *stack, unsigned int stack_size, osl_ext_task_priority_t priority, osl_ext_time_ms_t timslice_msec, osl_ext_task_entry func, osl_ext_task_arg_t arg, - osl_ext_task_t *task); + bool autostart, osl_ext_task_t *task); /**************************************************************************** * Function: osl_ext_task_delete @@ -379,7 +410,6 @@ osl_ext_status_t osl_ext_task_create_ex(char* name, */ osl_ext_status_t osl_ext_task_delete(osl_ext_task_t *task); - /**************************************************************************** * Function: osl_ext_task_is_running * @@ -392,6 +422,18 @@ osl_ext_status_t osl_ext_task_delete(osl_ext_task_t *task); */ osl_ext_task_t *osl_ext_task_current(void); +/**************************************************************************** +* Function: osl_ext_task_yield +* +* Purpose: Yield the CPU to other tasks of the same priority that are +* ready-to-run. +* +* Parameters: None. +* +* Returns: OSL_EXT_SUCCESS if successful, else error code. +***************************************************************************** +*/ +osl_ext_status_t osl_ext_task_yield(void); /**************************************************************************** * Function: osl_ext_task_yield @@ -406,6 +448,31 @@ osl_ext_task_t *osl_ext_task_current(void); */ osl_ext_status_t osl_ext_task_yield(void); +/**************************************************************************** +* Function: osl_ext_task_suspend +* +* Purpose: Suspend a task. +* +* Parameters: task (mod) Task to suspend. +* +* Returns: OSL_EXT_SUCCESS if the task was suspended successfully, or an +* error code if the task could not be suspended. +***************************************************************************** +*/ +osl_ext_status_t osl_ext_task_suspend(osl_ext_task_t *task); + +/**************************************************************************** +* Function: osl_ext_task_resume +* +* Purpose: Resume a task. +* +* Parameters: task (mod) Task to resume. +* +* Returns: OSL_EXT_SUCCESS if the task was resumed successfully, or an +* error code if the task could not be resumed. +***************************************************************************** +*/ +osl_ext_status_t osl_ext_task_resume(osl_ext_task_t *task); /**************************************************************************** * Function: osl_ext_task_enable_stack_check @@ -419,7 +486,6 @@ osl_ext_status_t osl_ext_task_yield(void); */ osl_ext_status_t osl_ext_task_enable_stack_check(void); - /* -------------------------------------------------------------------------- ** Queue */ @@ -518,7 +584,6 @@ osl_ext_status_t osl_ext_queue_receive(osl_ext_queue_t *queue, */ osl_ext_status_t osl_ext_queue_count(osl_ext_queue_t *queue, int *count); - /* -------------------------------------------------------------------------- ** Event */ @@ -584,7 +649,6 @@ osl_ext_status_t osl_ext_event_get(osl_ext_event_t *event, osl_ext_status_t osl_ext_event_set(osl_ext_event_t *event, osl_ext_event_bits_t event_bits); - /* -------------------------------------------------------------------------- ** Interrupt */ @@ -601,7 +665,6 @@ osl_ext_status_t osl_ext_event_set(osl_ext_event_t *event, */ osl_ext_interrupt_state_t osl_ext_interrupt_disable(void); - /**************************************************************************** * Function: osl_ext_interrupt_restore * @@ -619,6 +682,11 @@ void osl_ext_interrupt_restore(osl_ext_interrupt_state_t state); /* ---- Constants and Types ---------------------------------------------- */ +/* Interrupt control */ +#define OSL_INTERRUPT_SAVE_AREA +#define OSL_DISABLE +#define OSL_RESTORE + /* Semaphore. */ #define osl_ext_sem_t #define OSL_EXT_SEM_DECL(sem) @@ -692,6 +760,6 @@ void osl_ext_interrupt_restore(osl_ext_interrupt_state_t state); #ifdef __cplusplus } -#endif +#endif // endif #endif /* _osl_ext_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/p2p.h b/drivers/net/wireless/bcmdhd_oo/include/p2p.h index cc7aa686e861120cb4f78b2a59e59fef14fb8055..e9b023e914bce5343ad9ca678bb1b149d47ac2b8 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/p2p.h +++ b/drivers/net/wireless/bcmdhd_oo/include/p2p.h @@ -1,14 +1,14 @@ /* * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,14 +32,13 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif #include #include <802.11.h> /* This marks the start of a packed structure section. */ #include - /* WiFi P2P OUI values */ #define P2P_OUI WFA_OUI /* WiFi P2P OUI */ #define P2P_VER WFA_OUI_TYPE_P2P /* P2P version: 9=WiFi P2P v1.0 */ @@ -102,7 +101,6 @@ typedef struct wifi_p2p_ie wifi_p2p_ie_t; #define P2P_SE_VS_ID_SERVICES 0x1b - /* WiFi P2P IE subelement: P2P Capability (capabilities info) */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_info_se_s { uint8 eltId; /* SE ID: P2P_SEID_P2P_INFO */ @@ -129,7 +127,6 @@ typedef struct wifi_p2p_info_se_s wifi_p2p_info_se_t; #define P2P_CAPSE_GRP_PERSISTENT 0x20 /* Persistent Reconnect */ #define P2P_CAPSE_GRP_FORMATION 0x40 /* Group Formation */ - /* WiFi P2P IE subelement: Group Owner Intent */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_intent_se_s { uint8 eltId; /* SE ID: P2P_SEID_INTENT */ @@ -250,7 +247,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_channel_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_channel_se_s wifi_p2p_channel_se_t; - /* Channel Entry structure within the Channel List SE */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_chanlist_entry_s { uint8 band; /* Regulatory Class (band) */ @@ -396,7 +392,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_serv_inst_data_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_serv_inst_data_se_s wifi_p2p_serv_inst_data_se_t; - /* WiFi P2P IE subelement: Connection capability */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_conn_cap_data_se_s { uint8 eltId; /* SE ID: P2P_SEID_CONNECT_CAP */ @@ -407,7 +402,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_conn_cap_data_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_conn_cap_data_se_s wifi_p2p_conn_cap_data_se_t; - /* WiFi P2P IE subelement: Advertisement ID */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_id_se_s { uint8 eltId; /* SE ID: P2P_SEID_ADVERTISE_ID */ @@ -419,7 +413,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_id_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_advt_id_se_s wifi_p2p_advt_id_se_t; - /* WiFi P2P IE subelement: Advertise Service Hash */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_adv_serv_info_s { uint8 advt_id[4]; /* SE Advertise ID for the service */ @@ -429,7 +422,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_adv_serv_info_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_adv_serv_info_s wifi_p2p_adv_serv_info_t; - /* WiFi P2P IE subelement: Advertise Service Hash */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_serv_se_s { uint8 eltId; /* SE ID: P2P_SEID_ADVERTISE_SERVICE */ @@ -443,7 +435,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_advt_serv_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_advt_serv_se_s wifi_p2p_advt_serv_se_t; - /* WiFi P2P IE subelement: Session ID */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_ssn_id_se_s { uint8 eltId; /* SE ID: P2P_SEID_SESSION_ID */ @@ -455,7 +446,6 @@ BWL_PRE_PACKED_STRUCT struct wifi_p2p_ssn_id_se_s { } BWL_POST_PACKED_STRUCT; typedef struct wifi_p2p_ssn_id_se_s wifi_p2p_ssn_id_se_t; - #define P2P_ADVT_SERV_SE_FIXED_LEN 3 /* Includes only the element ID and len */ #define P2P_ADVT_SERV_INFO_FIXED_LEN 7 /* Per ADV Service Instance advt_id + * nw_config_method + serv_name_len @@ -483,7 +473,6 @@ typedef struct wifi_p2p_action_frame wifi_p2p_action_frame_t; #define P2P_AF_PRESENCE_RSP 2 /* P2P Presence Response */ #define P2P_AF_GO_DISC_REQ 3 /* GO Discoverability Request */ - /* WiFi P2P Public Action Frame */ BWL_PRE_PACKED_STRUCT struct wifi_p2p_pub_act_frame { uint8 category; /* P2P_PUB_AF_CATEGORY */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/packed_section_end.h b/drivers/net/wireless/bcmdhd_oo/include/packed_section_end.h index 4827c709af263dc06c9b20e3a879c94733c443bf..886f9670abd39647ed2ac138a8a7963faa34ec88 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/packed_section_end.h +++ b/drivers/net/wireless/bcmdhd_oo/include/packed_section_end.h @@ -15,14 +15,14 @@ * #include * * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -30,7 +30,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. @@ -38,10 +38,9 @@ * * <> * - * $Id: packed_section_end.h 514727 2014-11-12 03:02:48Z $ + * $Id: packed_section_end.h 666738 2016-10-24 12:16:37Z $ */ - /* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h * and undefined in packed_section_end.h. If it is NOT defined at this * point, then there is a missing include of packed_section_start.h. @@ -50,10 +49,7 @@ #undef BWL_PACKED_SECTION #else #error "BWL_PACKED_SECTION is NOT defined!" -#endif - - - +#endif // endif /* Compiler-specific directives for structure packing are declared in * packed_section_start.h. This marks the end of the structure packing section, diff --git a/drivers/net/wireless/bcmdhd_oo/include/packed_section_start.h b/drivers/net/wireless/bcmdhd_oo/include/packed_section_start.h index 9beb45d5e0822cd3b8dd71c635e8bdbcdf30c862..955cf687f76fa0abaa2395d56f8bc32795733e62 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/packed_section_start.h +++ b/drivers/net/wireless/bcmdhd_oo/include/packed_section_start.h @@ -15,14 +15,14 @@ * #include * * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -30,7 +30,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. @@ -38,9 +38,44 @@ * * <> * - * $Id: packed_section_start.h 514727 2014-11-12 03:02:48Z $ + * $Id: packed_section_start.h 666738 2016-10-24 12:16:37Z $ */ +#ifndef _alignment_test_ +#define _alignment_test_ + +/* ASSERT default packing */ +typedef struct T4 { + uint8 a; + uint32 b; + uint16 c; + uint8 d; +} T4_t; + +/* 4 byte alignment support */ +/* +* a . . . +* b b b b +* c c d . +*/ + +/* + * Below function is meant to verify that this file is compiled with the default alignment of 4. + * Function will fail to compile if the condition is not met. + */ +#ifdef __GNUC__ +#define VARIABLE_IS_NOT_USED __attribute__ ((unused)) +#else +#define VARIABLE_IS_NOT_USED +#endif // endif +static void alignment_test(void); +static void +VARIABLE_IS_NOT_USED alignment_test(void) +{ + /* verify 4 byte alignment support */ + STATIC_ASSERT(sizeof(T4_t) == 12); +} +#endif /* _alignment_test_ */ /* Error check - BWL_PACKED_SECTION is defined in packed_section_start.h * and undefined in packed_section_end.h. If it is already defined at this @@ -50,10 +85,12 @@ #error "BWL_PACKED_SECTION is already defined!" #else #define BWL_PACKED_SECTION -#endif - - +#endif // endif +#if defined(BWL_DEFAULT_PACKING) + /* generate an error if BWL_DEFAULT_PACKING is defined */ + #error "BWL_DEFAULT_PACKING not supported any more." +#endif /* BWL_PACKED_SECTION */ /* Declare compiler-specific directives for structure packing. */ #if defined(__GNUC__) || defined(__lint) @@ -64,4 +101,4 @@ #define BWL_POST_PACKED_STRUCT #else #error "Unknown compiler!" -#endif +#endif // endif diff --git a/drivers/net/wireless/bcmdhd_oo/include/pcicfg.h b/drivers/net/wireless/bcmdhd_oo/include/pcicfg.h index 98f22c3df918f5bca27e1ec2e325899eb55286d9..1435921e376e3740bbb82501a69238b30ac8b48c 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/pcicfg.h +++ b/drivers/net/wireless/bcmdhd_oo/include/pcicfg.h @@ -1,14 +1,14 @@ /* * pcicfg.h: PCI configuration constants and structures. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,13 +24,12 @@ * * <> * - * $Id: pcicfg.h 621340 2016-02-25 12:26:40Z $ + * $Id: pcicfg.h 722942 2017-09-22 03:49:44Z $ */ #ifndef _h_pcicfg_ #define _h_pcicfg_ - /* pci config status reg has a bit to indicate that capability ptr is present */ #define PCI_CAPPTR_PRESENT 0x0010 @@ -57,11 +56,7 @@ * 0x18 as per the PCIe full dongle spec. Need to modify the values below * correctly at a later point of time */ -#ifdef DHD_EFI -#define PCI_CFG_BAR1 0x18 -#else #define PCI_CFG_BAR1 0x14 -#endif /* DHD_EFI */ #define PCI_CFG_BAR2 0x18 #define PCI_CFG_BAR3 0x1c #define PCI_CFG_BAR4 0x20 @@ -78,7 +73,6 @@ #define PCI_CFG_DEVCTRL 0xd8 #define PCI_CFG_TLCNTRL_5 0x814 - /* PCI CAPABILITY DEFINES */ #define PCI_CAP_POWERMGMTCAP_ID 0x01 #define PCI_CAP_MSICAP_ID 0x05 @@ -159,6 +153,9 @@ typedef struct _pciconfig_cap_pcie { /* PCIE Root Capability Register bits (Host mode only) */ #define PCIE_RC_CRS_VISIBILITY 0x0001 +/* PCIe PMCSR Register bits */ +#define PCIE_PMCSR_PMESTAT 0x8000 + /* Header to define the PCIE specific capabilities in the extended config space */ typedef struct _pcie_enhanced_caphdr { uint16 capID; @@ -166,10 +163,11 @@ typedef struct _pcie_enhanced_caphdr { uint16 next_ptr : 12; } pcie_enhanced_caphdr; - +#define PCIE_CFG_PMCSR 0x4C #define PCI_BAR0_WIN 0x80 /* backplane addres space accessed by BAR0 */ #define PCI_BAR1_WIN 0x84 /* backplane addres space accessed by BAR1 */ #define PCI_SPROM_CONTROL 0x88 /* sprom property control */ +#define PCIE_CFG_SUBSYSTEM_CONTROL 0x88 /* used as subsystem control in PCIE devices */ #define PCI_BAR1_CONTROL 0x8c /* BAR1 region burst control */ #define PCI_INT_STATUS 0x90 /* PCI and other cores interrupts */ #define PCI_INT_MASK 0x94 /* mask of PCI and other cores interrupts */ @@ -179,6 +177,7 @@ typedef struct _pcie_enhanced_caphdr { #define PCI_CLK_CTL_ST 0xa8 /* pci config space clock control/status (>=rev14) */ #define PCI_BAR0_WIN2 0xac /* backplane addres space accessed by second 4KB of BAR0 */ #define PCI_GPIO_IN 0xb0 /* pci config space gpio input (>=rev3) */ +#define PCIE_CFG_DEVICE_CAPABILITY 0xb0 /* used as device capability in PCIE devices */ #define PCI_GPIO_OUT 0xb4 /* pci config space gpio output (>=rev3) */ #define PCIE_CFG_DEVICE_CONTROL 0xb4 /* 0xb4 is used as device control in PCIE devices */ #define PCIE_DC_AER_CORR_EN (1u << 0u) @@ -216,12 +215,71 @@ typedef struct _pcie_enhanced_caphdr { #define PCI_CONFIG_EXT_CLK_MIN_TIME_MASK (1u << 31u) #define PCI_CONFIG_EXT_CLK_MIN_TIME_SHIFT (31) +#define PCI_ADV_ERR_CAP 0x100 +#define PCI_UC_ERR_STATUS 0x104 +#define PCI_UNCORR_ERR_MASK 0x108 +#define PCI_UCORR_ERR_SEVR 0x10c +#define PCI_CORR_ERR_STATUS 0x110 +#define PCI_CORR_ERR_MASK 0x114 +#define PCI_ERR_CAP_CTRL 0x118 +#define PCI_TLP_HDR_LOG1 0x11c +#define PCI_TLP_HDR_LOG2 0x120 +#define PCI_TLP_HDR_LOG3 0x124 +#define PCI_TLP_HDR_LOG4 0x128 +#define PCI_TL_CTRL_5 0x814 +#define PCI_TL_HDR_FC_ST 0x980 +#define PCI_TL_TGT_CRDT_ST 0x990 +#define PCI_TL_SMLOGIC_ST 0x998 +#define PCI_DL_ATTN_VEC 0x1040 +#define PCI_DL_STATUS 0x1048 + +#define PCI_PHY_CTL_0 0x1800 +#define PCI_SLOW_PMCLK_EXT_RLOCK (1 << 7) + +#define PCI_LINK_STATE_DEBUG 0x1c24 +#define PCI_RECOVERY_HIST 0x1ce4 +#define PCI_PHY_LTSSM_HIST_0 0x1cec +#define PCI_PHY_LTSSM_HIST_1 0x1cf0 +#define PCI_PHY_LTSSM_HIST_2 0x1cf4 +#define PCI_PHY_LTSSM_HIST_3 0x1cf8 +#define PCI_PHY_DBG_CLKREG_0 0x1e10 +#define PCI_PHY_DBG_CLKREG_1 0x1e14 +#define PCI_PHY_DBG_CLKREG_2 0x1e18 +#define PCI_PHY_DBG_CLKREG_3 0x1e1c + +/* Bit settings for PCI_UC_ERR_STATUS register */ +#define PCI_UC_ERR_URES (1 << 20) /* Unsupported Request Error Status */ +#define PCI_UC_ERR_ECRCS (1 << 19) /* ECRC Error Status */ +#define PCI_UC_ERR_MTLPS (1 << 18) /* Malformed TLP Status */ +#define PCI_UC_ERR_ROS (1 << 17) /* Receiver Overflow Status */ +#define PCI_UC_ERR_UCS (1 << 16) /* Unexpected Completion Status */ +#define PCI_UC_ERR_CAS (1 << 15) /* Completer Abort Status */ +#define PCI_UC_ERR_CTS (1 << 14) /* Completer Timeout Status */ +#define PCI_UC_ERR_FCPES (1 << 13) /* Flow Control Protocol Error Status */ +#define PCI_UC_ERR_PTLPS (1 << 12) /* Poisoned TLP Status */ +#define PCI_UC_ERR_DLPES (1 << 4) /* Data Link Protocol Error Status */ + +#define PCI_DL_STATUS_PHY_LINKUP (1 << 13) /* Status of LINK */ + #define PCI_PMCR_REFUP 0x1814 /* Trefup time */ +#define PCI_PMCR_TREFUP_LO_MASK 0x3f +#define PCI_PMCR_TREFUP_LO_SHIFT 24 +#define PCI_PMCR_TREFUP_LO_BITS 6 +#define PCI_PMCR_TREFUP_HI_MASK 0xf +#define PCI_PMCR_TREFUP_HI_SHIFT 5 +#define PCI_PMCR_TREFUP_HI_BITS 4 +#define PCI_PMCR_TREFUP_MAX 0x400 +#define PCI_PMCR_TREFUP_MAX_SCALE 0x2000 + #define PCI_PMCR_REFUP_EXT 0x1818 /* Trefup extend Max */ +#define PCI_PMCR_TREFUP_EXT_SHIFT 22 +#define PCI_PMCR_TREFUP_EXT_SCALE 3 +#define PCI_PMCR_TREFUP_EXT_ON 1 +#define PCI_PMCR_TREFUP_EXT_OFF 0 + #define PCI_TPOWER_SCALE_MASK 0x3 #define PCI_TPOWER_SCALE_SHIFT 3 /* 0:1 is scale and 2 is rsvd */ - #define PCI_BAR0_SHADOW_OFFSET (2 * 1024) /* bar0 + 2K accesses sprom shadow (in pci core) */ #define PCI_BAR0_SPROM_OFFSET (4 * 1024) /* bar0 + 4K accesses external sprom */ #define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) /* bar0 + 6K accesses pci core registers */ @@ -237,6 +295,7 @@ typedef struct _pcie_enhanced_caphdr { #define PCIE2_BAR0_WIN2 0x70 /* backplane addres space accessed by second 4KB of BAR0 */ #define PCIE2_BAR0_CORE2_WIN 0x74 /* backplane addres space accessed by second 4KB of BAR0 */ #define PCIE2_BAR0_CORE2_WIN2 0x78 /* backplane addres space accessed by second 4KB of BAR0 */ +#define PCIE2_BAR0_WINSZ 0x8000 #define PCI_BAR0_WIN2_OFFSET 0x1000u #define PCI_CORE_ENUM_OFFSET 0x2000u diff --git a/drivers/net/wireless/bcmdhd_oo/include/pcie_core.h b/drivers/net/wireless/bcmdhd_oo/include/pcie_core.h index 463561d08440bc593e2c046991eb5471bc9f80dc..12486132b2806e0457c5eb608ae0c049ff863593 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/pcie_core.h +++ b/drivers/net/wireless/bcmdhd_oo/include/pcie_core.h @@ -1,14 +1,14 @@ /* * BCM43XX PCIE core hardware definitions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: pcie_core.h 673814 2016-12-05 06:10:24Z $ + * $Id: pcie_core.h 732527 2017-11-17 19:09:04Z $ */ #ifndef _PCIE_CORE_H #define _PCIE_CORE_H @@ -32,12 +32,14 @@ #include #include +#define REV_GE_64(rev) (rev >= 64) + /* cpp contortions to concatenate w/arg prescan */ #ifndef PAD #define _PADLINE(line) pad ## line #define _XSTR(line) _PADLINE(line) #define PAD _XSTR(__LINE__) -#endif +#endif // endif /* PCIE Enumeration space offsets */ #define PCIE_CORE_CONFIG_OFFSET 0x0 @@ -48,7 +50,6 @@ #define PCIE_SPROM_SHADOW_OFFSET 0x800 #define PCIE_SBCONFIG_OFFSET 0xE00 - #define PCIEDEV_MAX_DMAS 4 /* PCIE Bar0 Address Mapping. Each function maps 16KB config space */ @@ -136,6 +137,9 @@ typedef struct pcie_doorbell { #define IFRM_VECSTAT_MASK 0x3 #define IFRM_VEC_MASK 0xff +/* HMAP Windows */ +#define HMAP_MAX_WINDOWS 8 + /* idma frm array */ typedef struct pcie_ifrm_array { uint32 addr; @@ -156,6 +160,20 @@ typedef struct pcie_ifrm_intr { uint32 intmask; } pcie_ifrm_intr_t; +/* HMAP window register set */ +typedef volatile struct pcie_hmapwindow { + uint32 baseaddr_lo; /* BaseAddrLower */ + uint32 baseaddr_hi; /* BaseAddrUpper */ + uint32 windowlength; /* Window Length */ + uint32 PAD[1]; +} pcie_hmapwindow_t; + +typedef volatile struct pcie_hmapviolation { + uint32 hmap_violationaddr_lo; /* violating address lo */ + uint32 hmap_violationaddr_hi; /* violating addr hi */ + uint32 hmap_violation_info; /* violation info */ + uint32 PAD[1]; +} pcie_hmapviolation_t; /* SB side: PCIE core and host control registers */ typedef volatile struct sbpcieregs { uint32 control; /* host mode only */ @@ -164,7 +182,8 @@ typedef volatile struct sbpcieregs { uint32 biststatus; /* bist Status: 0x00C */ uint32 gpiosel; /* PCIE gpio sel: 0x010 */ uint32 gpioouten; /* PCIE gpio outen: 0x14 */ - uint32 PAD[2]; + uint32 gpioout; /* PCIE gpio out: 0x18 */ + uint32 PAD; uint32 intstatus; /* Interrupt status: 0x20 */ uint32 intmask; /* Interrupt mask: 0x24 */ uint32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ @@ -185,7 +204,9 @@ typedef volatile struct sbpcieregs { uint32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ uint32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ uint32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ - uint32 PAD[5]; + uint32 sbtopcie0upper; /* sb to pcie translation 0: 0x10C */ + uint32 sbtopcie1upper; /* sb to pcie translation 1: 0x110 */ + uint32 PAD[3]; /* pcie core supports in direct access to config space */ uint32 configaddr; /* pcie config space access: Address field: 0x120 */ @@ -228,7 +249,10 @@ typedef volatile struct sbpcieregs { uint32 err_hdr_logreg3; /* 0x1B8 */ uint32 err_hdr_logreg4; /* 0x1BC */ uint32 err_code_logreg; /* 0x1C0 */ - uint32 PAD[7]; /* 0x1C4 - 0x1DF */ + uint32 axi_dbg_ctl; /* 0x1C4 */ + uint32 axi_dbg_data0; /* 0x1C8 */ + uint32 axi_dbg_data1; /* 0x1CC */ + uint32 PAD[4]; /* 0x1D0 - 0x1DF */ uint32 clk_ctl_st; /* 0x1E0 */ uint32 PAD[1]; /* 0x1E4 */ uint32 powerctl; /* 0x1E8 */ @@ -264,20 +288,71 @@ typedef volatile struct sbpcieregs { /* 0x480 - 0x4FF */ pcie_ifrm_intr_t ifrm_intr[IFRM_FR_DEV_MAX]; /* 0x500 - 0x53F */ - uint32 PAD[48]; /* 0x540 - 0x5FF */ + /* HMAP regs for PCIE corerev >= 24 [0x540 - 0x5DF] */ + pcie_hmapwindow_t hmapwindow[HMAP_MAX_WINDOWS]; /* 0x540 - 0x5BF */ + pcie_hmapviolation_t hmapviolation; /* 0x5C0 - 0x5CF */ + uint32 hmap_window_config; /* 0x5D0 */ + uint32 PAD[3]; /* 0x5D4 - 0x5DF */ + + uint32 PAD[8]; /* 0x5E0 - 0x5FF */ uint32 PAD[2][64]; /* 0x600 - 0x7FF */ } pcie2; } u; uint16 sprom[64]; /* SPROM shadow Area : 0x800 - 0x880 */ uint32 PAD[96]; /* 0x880 - 0x9FF */ /* direct memory access (pcie2 rev19 and after) : 0xA00 - 0xAFF */ - uint32 PAD[16]; /* 0xA00 - 0xA3F */ - uint32 dm_errlog; /* 0xA40 */ - uint32 dm_erraddr; /* 0xA44 */ - uint32 PAD[37]; /* 0xA48 - 0xADC */ - uint32 dm_clk_ctl_st; /* 0xAE0 */ - uint32 PAD[1]; /* 0xAE4 */ - uint32 dm_powerctl; /* 0xAE8 */ + union { + /* corerev < 64 */ + struct { + uint32 dar_ctrl; /* 0xA00 */ + uint32 PAD[7]; /* 0xA04-0xA1F */ + uint32 intstatus; /* 0xA20 */ + uint32 PAD[1]; /* 0xA24 */ + uint32 h2d_db_0_0; /* 0xA28 */ + uint32 h2d_db_0_1; /* 0xA2C */ + uint32 h2d_db_1_0; /* 0xA30 */ + uint32 h2d_db_1_1; /* 0xA34 */ + uint32 h2d_db_2_0; /* 0xA38 */ + uint32 h2d_db_2_1; /* 0xA3C */ + uint32 errlog; /* 0xA40 */ + uint32 erraddr; /* 0xA44 */ + uint32 mbox_int; /* 0xA48 */ + uint32 fis_ctrl; /* 0xA4C */ + uint32 PAD[36]; /* 0xA50 - 0xADC */ + uint32 clk_ctl_st; /* 0xAE0 */ + uint32 PAD[1]; /* 0xAE4 */ + uint32 powerctl; /* 0xAE8 */ + } dar; + /* corerev > = 64 */ + struct { + uint32 dar_ctrl; /* 0xA00 */ + uint32 dar_cap; /* 0xA04 */ + uint32 clk_ctl_st; /* 0xA08 */ + uint32 powerctl; /* 0xA0C */ + uint32 intstatus; /* 0xA10 */ + uint32 PAD[3]; /* 0xA14-0xA1F */ + uint32 h2d_db_0_0; /* 0xA20 */ + uint32 h2d_db_0_1; /* 0xA24 */ + uint32 h2d_db_1_0; /* 0xA28 */ + uint32 h2d_db_1_1; /* 0xA2C */ + uint32 h2d_db_2_0; /* 0xA30 */ + uint32 h2d_db_2_1; /* 0xA34 */ + uint32 h2d_db_3_0; /* 0xA38 */ + uint32 h2d_db_3_1; /* 0xA3C */ + uint32 h2d_db_4_0; /* 0xA40 */ + uint32 h2d_db_4_1; /* 0xA44 */ + uint32 h2d_db_5_0; /* 0xA48 */ + uint32 h2d_db_5_1; /* 0xA4C */ + uint32 h2d_db_6_0; /* 0xA50 */ + uint32 h2d_db_6_1; /* 0xA54 */ + uint32 h2d_db_7_0; /* 0xA58 */ + uint32 h2d_db_7_1; /* 0xA5C */ + uint32 errlog; /* 0xA60 */ + uint32 erraddr; /* 0xA64 */ + uint32 mbox_int; /* 0xA68 */ + uint32 fis_ctrl; /* 0xA6C */ + } dar_64; + } u1; } sbpcieregs_t; #define PCIE_CFG_DA_OFFSET 0x400 /* direct access register offset for configuration space */ @@ -294,9 +369,11 @@ typedef volatile struct sbpcieregs { #define PCIE_MULTIMSI_EN 0x2000 /* enable multi-vector MSI messages */ #define PCIE_PipeIddqDisable0 0x8000 /* Disable assertion of pcie_pipe_iddq during L1.2 and L2 */ #define PCIE_PipeIddqDisable1 0x10000 /* Disable assertion of pcie_pipe_iddq during L2 */ +#define PCIE_EN_MDIO_IN_PERST 0x20000 /* enable access to internal registers when PERST */ #define PCIE_MSI_B2B_EN 0x100000 /* enable back-to-back MSI messages */ #define PCIE_MSI_FIFO_CLEAR 0x200000 /* reset MSI FIFO */ -#define PCIE_IDMA_MODE_EN 0x800000 /* implicit M2M DMA mode */ +#define PCIE_IDMA_MODE_EN(rev) (REV_GE_64(rev) ? 0x1 : 0x800000) /* implicit M2M DMA mode */ +#define PCIE_TL_CLK_DETCT 0x4000000 /* enable TL clk detection */ #define PCIE_CFGADDR 0x120 /* offsetof(configaddr) */ #define PCIE_CFGDATA 0x124 /* offsetof(configdata) */ @@ -328,36 +405,49 @@ typedef volatile struct sbpcieregs { #define MSIVEC_D2H0_DB1 (0x1 << 4) /* MSI Vector offset for interface0 door bell 1 is 5 */ /* PCIE MailboxInt/MailboxIntMask register */ -#define PCIE_MB_TOSB_FN0_0 0x0001 /* write to assert PCIEtoSB Mailbox interrupt */ -#define PCIE_MB_TOSB_FN0_1 0x0002 -#define PCIE_MB_TOSB_FN1_0 0x0004 -#define PCIE_MB_TOSB_FN1_1 0x0008 -#define PCIE_MB_TOSB_FN2_0 0x0010 -#define PCIE_MB_TOSB_FN2_1 0x0020 -#define PCIE_MB_TOSB_FN3_0 0x0040 -#define PCIE_MB_TOSB_FN3_1 0x0080 -#define PCIE_MB_TOPCIE_FN0_0 0x0100 /* int status/mask for SBtoPCIE Mailbox interrupts */ -#define PCIE_MB_TOPCIE_FN0_1 0x0200 -#define PCIE_MB_TOPCIE_FN1_0 0x0400 -#define PCIE_MB_TOPCIE_FN1_1 0x0800 -#define PCIE_MB_TOPCIE_FN2_0 0x1000 -#define PCIE_MB_TOPCIE_FN2_1 0x2000 -#define PCIE_MB_TOPCIE_FN3_0 0x4000 -#define PCIE_MB_TOPCIE_FN3_1 0x8000 -#define PCIE_MB_TOPCIE_D2H0_DB0 0x10000 -#define PCIE_MB_TOPCIE_D2H0_DB1 0x20000 -#define PCIE_MB_TOPCIE_D2H1_DB0 0x40000 -#define PCIE_MB_TOPCIE_D2H1_DB1 0x80000 -#define PCIE_MB_TOPCIE_D2H2_DB0 0x100000 -#define PCIE_MB_TOPCIE_D2H2_DB1 0x200000 -#define PCIE_MB_TOPCIE_D2H3_DB0 0x400000 -#define PCIE_MB_TOPCIE_D2H3_DB1 0x800000 - -#define PCIE_MB_D2H_MB_MASK \ - (PCIE_MB_TOPCIE_D2H0_DB0 | PCIE_MB_TOPCIE_D2H0_DB1 | \ - PCIE_MB_TOPCIE_D2H1_DB0 | PCIE_MB_TOPCIE_D2H1_DB1 | \ - PCIE_MB_TOPCIE_D2H2_DB0 | PCIE_MB_TOPCIE_D2H2_DB1 | \ - PCIE_MB_TOPCIE_D2H3_DB0 | PCIE_MB_TOPCIE_D2H3_DB1) +#define PCIE_MB_TOSB_FN0_0 0x0001 /* write to assert PCIEtoSB Mailbox interrupt */ +#define PCIE_MB_TOSB_FN0_1 0x0002 +#define PCIE_MB_TOSB_FN1_0 0x0004 +#define PCIE_MB_TOSB_FN1_1 0x0008 +#define PCIE_MB_TOSB_FN2_0 0x0010 +#define PCIE_MB_TOSB_FN2_1 0x0020 +#define PCIE_MB_TOSB_FN3_0 0x0040 +#define PCIE_MB_TOSB_FN3_1 0x0080 +#define PCIE_MB_TOPCIE_FN0_0 0x0100 /* int status/mask for SBtoPCIE Mailbox interrupts */ +#define PCIE_MB_TOPCIE_FN0_1 0x0200 +#define PCIE_MB_TOPCIE_FN1_0 0x0400 +#define PCIE_MB_TOPCIE_FN1_1 0x0800 +#define PCIE_MB_TOPCIE_FN2_0 0x1000 +#define PCIE_MB_TOPCIE_FN2_1 0x2000 +#define PCIE_MB_TOPCIE_FN3_0 0x4000 +#define PCIE_MB_TOPCIE_FN3_1 0x8000 + +#define PCIE_MB_TOPCIE_DB0_D2H0(rev) (REV_GE_64(rev) ? 0x0001 : 0x010000) +#define PCIE_MB_TOPCIE_DB0_D2H1(rev) (REV_GE_64(rev) ? 0x0002 : 0x020000) +#define PCIE_MB_TOPCIE_DB1_D2H0(rev) (REV_GE_64(rev) ? 0x0004 : 0x040000) +#define PCIE_MB_TOPCIE_DB1_D2H1(rev) (REV_GE_64(rev) ? 0x0008 : 0x080000) +#define PCIE_MB_TOPCIE_DB2_D2H0(rev) (REV_GE_64(rev) ? 0x0010 : 0x100000) +#define PCIE_MB_TOPCIE_DB2_D2H1(rev) (REV_GE_64(rev) ? 0x0020 : 0x200000) +#define PCIE_MB_TOPCIE_DB3_D2H0(rev) (REV_GE_64(rev) ? 0x0040 : 0x400000) +#define PCIE_MB_TOPCIE_DB3_D2H1(rev) (REV_GE_64(rev) ? 0x0080 : 0x800000) +#define PCIE_MB_TOPCIE_DB4_D2H0(rev) (REV_GE_64(rev) ? 0x0100 : 0x0) +#define PCIE_MB_TOPCIE_DB4_D2H1(rev) (REV_GE_64(rev) ? 0x0200 : 0x0) +#define PCIE_MB_TOPCIE_DB5_D2H0(rev) (REV_GE_64(rev) ? 0x0400 : 0x0) +#define PCIE_MB_TOPCIE_DB5_D2H1(rev) (REV_GE_64(rev) ? 0x0800 : 0x0) +#define PCIE_MB_TOPCIE_DB6_D2H0(rev) (REV_GE_64(rev) ? 0x1000 : 0x0) +#define PCIE_MB_TOPCIE_DB6_D2H1(rev) (REV_GE_64(rev) ? 0x2000 : 0x0) +#define PCIE_MB_TOPCIE_DB7_D2H0(rev) (REV_GE_64(rev) ? 0x4000 : 0x0) +#define PCIE_MB_TOPCIE_DB7_D2H1(rev) (REV_GE_64(rev) ? 0x8000 : 0x0) + +#define PCIE_MB_D2H_MB_MASK(rev) \ + (PCIE_MB_TOPCIE_DB0_D2H0(rev) | PCIE_MB_TOPCIE_DB0_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB1_D2H0(rev) | PCIE_MB_TOPCIE_DB1_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB2_D2H0(rev) | PCIE_MB_TOPCIE_DB2_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB3_D2H0(rev) | PCIE_MB_TOPCIE_DB3_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB4_D2H0(rev) | PCIE_MB_TOPCIE_DB4_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB5_D2H0(rev) | PCIE_MB_TOPCIE_DB5_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB6_D2H0(rev) | PCIE_MB_TOPCIE_DB6_D2H1(rev) | \ + PCIE_MB_TOPCIE_DB7_D2H0(rev) | PCIE_MB_TOPCIE_DB7_D2H1(rev)) #define SBTOPCIE0_BASE 0x08000000 #define SBTOPCIE1_BASE 0x0c000000 @@ -517,7 +607,6 @@ typedef volatile struct sbpcieregs { #define PCIE2_MDIO_WR_DATA 0x12C #define PCIE2_MDIO_RD_DATA 0x130 - /* MDIO control */ #define MDIOCTL_DIVISOR_MASK 0x7fu /* clock to be used on MDIO */ #define MDIOCTL_DIVISOR_VAL 0x2u @@ -556,7 +645,6 @@ typedef volatile struct sbpcieregs { #define MDIODATA2_MASK 0x7FFFFFFF /* rd/wr transaction data */ #define MDIODATA2_DEVADDR_SHF 4 /* Physmedia devaddr shift */ - /* MDIO devices (SERDES modules) * unlike old pcie cores (rev < 10), rev10 pcie serde organizes registers into a few blocks. * two layers mapping (blockidx, register offset) is required @@ -573,7 +661,6 @@ typedef volatile struct sbpcieregs { #define MDIO_DEV_SERDESID 0x831 #define MDIO_DEV_RXCTRL0 0x840 - /* XgxsBlk1_A Register Offsets */ #define BLK1_PWR_MGMT0 0x16 #define BLK1_PWR_MGMT1 0x17 @@ -664,7 +751,6 @@ typedef volatile struct sbpcieregs { * #define PCIE_CAP_RTSTA 32 // Root Status */ - /* Linkcapability reg offset in PCIE Cap */ #define PCIE_CAP_LINKCAP_OFFSET 12 /* linkcap offset in pcie cap */ #define PCIE_CAP_LINKCAP_LNKSPEED_MASK 0xf /* Supported Link Speeds */ @@ -725,11 +811,15 @@ typedef volatile struct sbpcieregs { #define PCIE_LTR0_REG_DEFAULT_150 0x88968896u /* active latency default to 150usec */ #define PCIE_LTR1_REG_DEFAULT 0x88648864u /* idle latency default to 100usec */ #define PCIE_LTR2_REG_DEFAULT 0x90039003u /* sleep latency default to 3msec */ +#define PCIE_LTR_LAT_VALUE_MASK 0x3FF /* LTR Latency mask */ +#define PCIE_LTR_LAT_SCALE_SHIFT 10 /* LTR Scale shift */ +#define PCIE_LTR_LAT_SCALE_MASK 0x1C00 /* LTR Scale mask */ +#define PCIE_LTR_SNOOP_REQ_SHIFT 15 /* LTR SNOOP REQ shift */ +#define PCIE_LTR_SNOOP_REQ_MASK 0x8000 /* LTR SNOOP REQ mask */ /* Status reg PCIE_PLP_STATUSREG */ #define PCIE_PLP_POLARITYINV_STAT 0x10 - /* PCIE BRCM Vendor CAP REVID reg bits */ #define BRCMCAP_PCIEREV_CT_MASK 0xF00u #define BRCMCAP_PCIEREV_CT_SHIFT 8u @@ -765,10 +855,11 @@ typedef volatile struct sbpcieregs { #define PCIECFGREG_MSI_ADDR_L 0x5C #define PCIECFGREG_MSI_ADDR_H 0x60 #define PCIECFGREG_MSI_DATA 0x64 +#define PCIECFGREG_SPROM_CTRL 0x88 #define PCIECFGREG_LINK_STATUS_CTRL 0xBCu +#define PCIECFGREG_LINK_STATUS_CTRL2 0xDCu #define PCIECFGREG_DEV_STATUS_CTRL 0xB4u #define PCIECFGGEN_DEV_STATUS_CTRL2 0xD4 -#define PCIECFGREG_LINK_STATUS_CTRL2 0xDCu #define PCIECFGREG_RBAR_CTRL 0x228 #define PCIECFGREG_PML1_SUB_CTRL1 0x248 #define PCIECFGREG_PML1_SUB_CTRL2 0x24C @@ -808,16 +899,31 @@ typedef volatile struct sbpcieregs { #define PCIH2D_MailBox_2 0x160 /* for dma channel2 which will be used for Implicit DMA */ #define PCIH2D_DB1_2 0x164 #define PCID2H_MailBox_2 0x168 +#define PCIE_PWR_CTRL 0x1E8 + +#define PCIControl(rev) (REV_GE_64(rev) ? 0xC00 : 0x00) +/* for corerev < 64 idma_en is in PCIControl regsiter */ +#define IDMAControl(rev) (REV_GE_64(rev) ? 0x480 : 0x00) +#define PCIMailBoxInt(rev) (REV_GE_64(rev) ? 0xC30 : 0x48) +#define PCIMailBoxMask(rev) (REV_GE_64(rev) ? 0xC34 : 0x4C) -#define PCIMailBoxInt 0x48 -#define PCIMailBoxMask 0x4C #define PCIMSIVecAssign 0x58 +/* HMAP Registers */ +#define PCI_HMAP_WINDOW_BASE 0x540 /* base of all HMAP window registers */ +#define PCI_HMAP_VIOLATION_ADDR_L 0x5C0 +#define PCI_HMAP_VIOLATION_ADDR_U 0x5C4 +#define PCI_HMAP_VIOLATION_INFO 0x5C8 +#define PCI_HMAP_WINDOW_CONFIG 0x5D0 +#define PCI_HMAP_NWINDOWS_SHIFT 8 +#define PCI_HMAP_NWINDOWS_MASK 0x0000ff00 /* bits 8:15 */ + #define I_F0_B0 (0x1 << 8) /* Mail box interrupt Function 0 interrupt, bit 0 */ #define I_F0_B1 (0x1 << 9) /* Mail box interrupt Function 0 interrupt, bit 1 */ #define PCIECFGREG_DEVCONTROL 0xB4 #define PCIECFGREG_BASEADDR0 0x10 +#define PCIECFGREG_BASEADDR1 0x18 #define PCIECFGREG_DEVCONTROL_MRRS_SHFT 12 #define PCIECFGREG_DEVCONTROL_MRRS_MASK (0x7 << PCIECFGREG_DEVCONTROL_MRRS_SHFT) #define PCIECFGREG_DEVCTRL_MPS_SHFT 5 @@ -829,6 +935,47 @@ typedef volatile struct sbpcieregs { #define PCIECFGREG_PM_CSR_STATE_D3_HOT 3 #define PCIECFGREG_PM_CSR_STATE_D3_COLD 4 +/* Direct Access regs */ +#define DAR_ERRLOG(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.errlog) : \ + OFFSETOF(sbpcieregs_t, u1.dar.errlog)) +#define DAR_PCIH2D_DB0_0(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_0_0) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_0_0)) +#define DAR_PCIH2D_DB0_1(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_0_1) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_0_1)) +#define DAR_PCIH2D_DB1_0(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_1_0) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_1_0)) +#define DAR_PCIH2D_DB1_1(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_1_1) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_1_1)) +#define DAR_PCIH2D_DB2_0(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_2_0) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_2_0)) +#define DAR_PCIH2D_DB2_1(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_2_1) : \ + OFFSETOF(sbpcieregs_t, u1.dar.h2d_db_2_1)) +#define DAR_PCIH2D_DB3_0(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_3_0) +#define DAR_PCIH2D_DB3_1(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_3_1) +#define DAR_PCIH2D_DB4_0(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_4_0) +#define DAR_PCIH2D_DB4_1(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_4_1) +#define DAR_PCIH2D_DB5_0(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_5_0) +#define DAR_PCIH2D_DB5_1(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_5_1) +#define DAR_PCIH2D_DB6_0(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_6_0) +#define DAR_PCIH2D_DB6_1(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_6_1) +#define DAR_PCIH2D_DB7_0(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_7_0) +#define DAR_PCIH2D_DB7_1(rev) OFFSETOF(sbpcieregs_t, u1.dar_64.h2d_db_7_1) + +#define DAR_PCIMailBoxInt(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.mbox_int) : \ + OFFSETOF(sbpcieregs_t, u1.dar.mbox_int)) +#define DAR_PCIE_PWR_CTRL(rev) (REV_GE_64(rev) ? \ + OFFSETOF(sbpcieregs_t, u1.dar_64.powerctl) : \ + OFFSETOF(sbpcieregs_t, u1.dar.powerctl)) + +#define PCIE_PWR_REQ_PCIE (0x1 << 8) /* SROM hardware region */ #define SROM_OFFSET_BAR1_CTRL 52 @@ -895,6 +1042,7 @@ typedef volatile struct sbpcieregs { #define PCIEGEN2_IOC_L1_LINK_SHIFT 13 #define PCIEGEN2_IOC_L1L2_LINK_SHIFT 14 #define PCIEGEN2_IOC_L2_L3_LINK_SHIFT 15 +#define PCIEGEN2_IOC_BME_SHIFT 20 #define PCIEGEN2_IOC_D0_STATE_MASK (1 << PCIEGEN2_IOC_D0_STATE_SHIFT) #define PCIEGEN2_IOC_D1_STATE_MASK (1 << PCIEGEN2_IOC_D1_STATE_SHIFT) @@ -904,6 +1052,7 @@ typedef volatile struct sbpcieregs { #define PCIEGEN2_IOC_L1_LINK_MASK (1 << PCIEGEN2_IOC_L1_LINK_SHIFT) #define PCIEGEN2_IOC_L1L2_LINK_MASK (1 << PCIEGEN2_IOC_L1L2_LINK_SHIFT) #define PCIEGEN2_IOC_L2_L3_LINK_MASK (1 << PCIEGEN2_IOC_L2_L3_LINK_SHIFT) +#define PCIEGEN2_IOC_BME_MASK (1 << PCIEGEN2_IOC_BME_SHIFT) /* stat_ctrl */ #define PCIE_STAT_CTRL_RESET 0x1 @@ -911,6 +1060,10 @@ typedef volatile struct sbpcieregs { #define PCIE_STAT_CTRL_INTENABLE 0x4 #define PCIE_STAT_CTRL_INTSTATUS 0x8 +/* SPROMControl */ +#define PCIE_BAR1COHERENTACCEN (1 << 8) +#define PCIE_BAR2COHERENTACCEN (1 << 9) + /* cpl_timeout_ctrl_reg */ #define PCIE_CTO_TO_THRESHOLD_SHIFT 0 #define PCIE_CTO_TO_THRESHHOLD_MASK (0xfffff << PCIE_CTO_TO_THRESHOLD_SHIFT) @@ -941,7 +1094,7 @@ typedef volatile struct sbpcieregs { #define PCIE_BP_IN_RESET_ERR_MASK (0x1 << PCIE_BP_IN_RESET_ERR_SHIFT) #ifdef BCMDRIVER -void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs); +void pcie_watchdog_reset(osl_t *osh, si_t *sih, uint32 wd_mask, uint32 wd_val); void pcie_serdes_iddqdisable(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs); void pcie_set_trefup_time_100us(si_t *sih); #endif /* BCMDRIVER */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/rte_ioctl.h b/drivers/net/wireless/bcmdhd_oo/include/rte_ioctl.h new file mode 100644 index 0000000000000000000000000000000000000000..cbeef7d4fe44240fe2880ee8de3437988afa7412 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/include/rte_ioctl.h @@ -0,0 +1,103 @@ +/* + * HND Run Time Environment ioctl. + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: rte_ioctl.h 699094 2017-05-11 22:41:10Z $ + */ + +#ifndef _rte_ioctl_h_ +#define _rte_ioctl_h_ + +/* RTE IOCTL definitions for generic ether devices */ +#define RTEGHWADDR 0x8901 +#define RTESHWADDR 0x8902 +#define RTEGMTU 0x8903 +#define RTEGSTATS 0x8904 +#define RTEGALLMULTI 0x8905 +#define RTESALLMULTI 0x8906 +#define RTEGPROMISC 0x8907 +#define RTESPROMISC 0x8908 +#define RTESMULTILIST 0x8909 +#define RTEGUP 0x890A +#define RTEGPERMADDR 0x890B +#define RTEDEVPWRSTCHG 0x890C /* Device pwr state change for PCIedev */ +#define RTEDEVPMETOGGLE 0x890D /* Toggle PME# to wake up the host */ +#define RTEDEVTIMESYNC 0x890E /* Device TimeSync */ +#define RTEDEVDSNOTIFY 0x890F /* Bus DS state notification */ +#define RTED11DMALPBK_INIT 0x8910 /* D11 DMA loopback init */ +#define RTED11DMALPBK_UNINIT 0x8911 /* D11 DMA loopback uninit */ +#define RTED11DMALPBK_RUN 0x8912 /* D11 DMA loopback run */ +#define RTEDEVTSBUFPOST 0x8913 /* Async interface for tsync buffer post */ + +#define RTE_IOCTL_QUERY 0x00 +#define RTE_IOCTL_SET 0x01 +#define RTE_IOCTL_OVL_IDX_MASK 0x1e +#define RTE_IOCTL_OVL_RSV 0x20 +#define RTE_IOCTL_OVL 0x40 +#define RTE_IOCTL_OVL_IDX_SHIFT 1 + +enum hnd_ioctl_cmd { + HND_RTE_DNGL_IS_SS = 1, /* true if device connected at super speed */ + + /* PCIEDEV specific wl <--> bus ioctls */ + BUS_GET_VAR = 2, + BUS_SET_VAR = 3, + BUS_FLUSH_RXREORDER_Q = 4, + BUS_SET_LTR_STATE = 5, + BUS_FLUSH_CHAINED_PKTS = 6, + BUS_SET_COPY_COUNT = 7, + BUS_UPDATE_FLOW_PKTS_MAX = 8, + BUS_UPDATE_EXTRA_TXLFRAGS = 9, + BUS_UPDATE_FRWD_RESRV_BUFCNT = 10, + BUS_PCIE_CONFIG_ACCESS = 11 +}; + +#define SDPCMDEV_SET_MAXTXPKTGLOM 1 +#define RTE_MEMUSEINFO_VER 0x00 + +typedef struct memuse_info { + uint16 ver; /* version of this struct */ + uint16 len; /* length in bytes of this structure */ + uint32 tot; /* Total memory */ + uint32 text_len; /* Size of Text segment memory */ + uint32 data_len; /* Size of Data segment memory */ + uint32 bss_len; /* Size of BSS segment memory */ + + uint32 arena_size; /* Total Heap size */ + uint32 arena_free; /* Heap memory available or free */ + uint32 inuse_size; /* Heap memory currently in use */ + uint32 inuse_hwm; /* High watermark of memory - reclaimed memory */ + uint32 inuse_overhead; /* tally of allocated mem_t blocks */ + uint32 inuse_total; /* Heap in-use + Heap overhead memory */ + uint32 free_lwm; /* Least free size since reclaim */ + uint32 mf_count; /* Malloc failure count */ +} memuse_info_t; + +/* For D11 DMA loopback test */ +typedef struct d11_dmalpbk_args { + uint8 *buf; + int32 len; +} d11_dmalpbk_args_t; +#endif /* _rte_ioctl_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbchipc.h b/drivers/net/wireless/bcmdhd_oo/include/sbchipc.h index ffec624c53dcca8eaa4f6f93b952a86dddf1975f..b4952b3427922a7b83dbf211c5f7ba4db102f748 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbchipc.h @@ -5,16 +5,16 @@ * 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 657872 2016-09-02 22:17:34Z $ + * $Id: sbchipc.h 732401 2017-11-17 01:38:44Z $ + * + * Copyright (C) 1999-2018, Broadcom. * - * Copyright (C) 1999-2017, 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 @@ -22,7 +22,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. @@ -43,6 +43,8 @@ #define PAD _XSTR(__LINE__) #endif /* PAD */ +#define BCM_MASK32(msb, lsb) ((~0u >> (32u - (msb) - 1u)) & (~0u << (lsb))) + /** * In chipcommon rev 49 the pmu registers have been moved from chipc to the pmu core if the * 'AOBPresent' bit of 'CoreCapabilitiesExt' is set. If this field is set, the traditional chipc to @@ -52,62 +54,71 @@ */ typedef volatile struct { uint32 PAD[384]; - uint32 pmucontrol; /* 0x600 */ - uint32 pmucapabilities; /* 0x604 */ - uint32 pmustatus; /* 0x608 */ - uint32 res_state; /* 0x60C */ - uint32 res_pending; /* 0x610 */ - uint32 pmutimer; /* 0x614 */ - uint32 min_res_mask; /* 0x618 */ - uint32 max_res_mask; /* 0x61C */ - uint32 res_table_sel; /* 0x620 */ - uint32 res_dep_mask; - uint32 res_updn_timer; - uint32 res_timer; - uint32 clkstretch; - uint32 pmuwatchdog; - uint32 gpiosel; /* 0x638, rev >= 1 */ - uint32 gpioenable; /* 0x63c, rev >= 1 */ - uint32 res_req_timer_sel; /* 0x640 */ - uint32 res_req_timer; /* 0x644 */ - uint32 res_req_mask; /* 0x648 */ - uint32 core_cap_ext; /* 0x64C */ - uint32 chipcontrol_addr; /* 0x650 */ - uint32 chipcontrol_data; /* 0x654 */ - uint32 regcontrol_addr; - uint32 regcontrol_data; - uint32 pllcontrol_addr; - uint32 pllcontrol_data; - uint32 pmustrapopt; /* 0x668, corerev >= 28 */ - uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ - uint32 retention_ctl; /* 0x670 */ - uint32 ILPPeriod; /* 0x674 */ + uint32 pmucontrol; /* 0x600 */ + uint32 pmucapabilities; /* 0x604 */ + uint32 pmustatus; /* 0x608 */ + uint32 res_state; /* 0x60C */ + uint32 res_pending; /* 0x610 */ + uint32 pmutimer; /* 0x614 */ + uint32 min_res_mask; /* 0x618 */ + uint32 max_res_mask; /* 0x61C */ + uint32 res_table_sel; /* 0x620 */ + uint32 res_dep_mask; + uint32 res_updn_timer; + uint32 res_timer; + uint32 clkstretch; + uint32 pmuwatchdog; + uint32 gpiosel; /* 0x638, rev >= 1 */ + uint32 gpioenable; /* 0x63c, rev >= 1 */ + uint32 res_req_timer_sel; /* 0x640 */ + uint32 res_req_timer; /* 0x644 */ + uint32 res_req_mask; /* 0x648 */ + uint32 core_cap_ext; /* 0x64C */ + uint32 chipcontrol_addr; /* 0x650 */ + uint32 chipcontrol_data; /* 0x654 */ + uint32 regcontrol_addr; + uint32 regcontrol_data; + uint32 pllcontrol_addr; + uint32 pllcontrol_data; + uint32 pmustrapopt; /* 0x668, corerev >= 28 */ + uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ + uint32 retention_ctl; /* 0x670 */ + uint32 ILPPeriod; /* 0x674 */ uint32 PAD[2]; - uint32 retention_grpidx; /* 0x680 */ - uint32 retention_grpctl; /* 0x684 */ - uint32 mac_res_req_timer; /* 0x688 */ - uint32 mac_res_req_mask; /* 0x68c */ + uint32 retention_grpidx; /* 0x680 */ + uint32 retention_grpctl; /* 0x684 */ + uint32 mac_res_req_timer; /* 0x688 */ + uint32 mac_res_req_mask; /* 0x68c */ uint32 PAD[18]; - uint32 pmucontrol_ext; /* 0x6d8 */ - uint32 slowclkperiod; /* 0x6dc */ - uint32 PAD[8]; - uint32 pmuintmask0; /* 0x700 */ - uint32 pmuintmask1; /* 0x704 */ - uint32 PAD[14]; - uint32 pmuintstatus; /* 0x740 */ - uint32 extwakeupstatus; /* 0x744 */ - uint32 watchdog_res_mask; /* 0x748 */ - uint32 PAD[1]; /* 0x74C */ - uint32 swscratch; /* 0x750 */ - uint32 PAD[3]; /* 0x754-0x75C */ - uint32 extwakemask[2]; /* 0x760-0x764 */ - uint32 PAD[2]; /* 0x768-0x76C */ - uint32 extwakereqmask[2]; /* 0x770-0x774 */ - uint32 PAD[2]; /* 0x778-0x77C */ - uint32 pmuintctrl0; /* 0x780 */ - uint32 pmuintctrl1; /* 0x784 */ + uint32 pmucontrol_ext; /* 0x6d8 */ + uint32 slowclkperiod; /* 0x6dc */ + uint32 pmu_statstimer_addr; /* 0x6e0 */ + uint32 pmu_statstimer_ctrl; /* 0x6e4 */ + uint32 pmu_statstimer_N; /* 0x6e8 */ + uint32 PAD[1]; + uint32 mac_res_req_timer1; /* 0x6f0 */ + uint32 mac_res_req_mask1; /* 0x6f4 */ uint32 PAD[2]; - uint32 extwakectrl[2] ; /* 0x790 */ + uint32 pmuintmask0; /* 0x700 */ + uint32 pmuintmask1; /* 0x704 */ + uint32 PAD[14]; + uint32 pmuintstatus; /* 0x740 */ + uint32 extwakeupstatus; /* 0x744 */ + uint32 watchdog_res_mask; /* 0x748 */ + uint32 PAD[1]; /* 0x74C */ + uint32 swscratch; /* 0x750 */ + uint32 PAD[3]; /* 0x754-0x75C */ + uint32 extwakemask0; /* 0x760 */ + uint32 extwakemask1; /* 0x764 */ + uint32 PAD[2]; /* 0x768-0x76C */ + uint32 extwakereqmask[2]; /* 0x770-0x774 */ + uint32 PAD[2]; /* 0x778-0x77C */ + uint32 pmuintctrl0; /* 0x780 */ + uint32 pmuintctrl1; /* 0x784 */ + uint32 PAD[2]; + uint32 extwakectrl[2]; /* 0x790 */ + uint32 PAD[10]; + uint32 PrecisionTmrCtrlStatus; /* 0x7c0 */ } pmuregs_t; typedef struct eci_prerev35 { @@ -328,7 +339,10 @@ typedef volatile struct { uint8 uart1lsr; uint8 uart1msr; uint8 uart1scratch; /* 0x407 */ - uint32 PAD[62]; + uint32 PAD[50]; + uint32 sr_memrw_addr; /* 0x4d0 */ + uint32 sr_memrw_data; /* 0x4d4 */ + uint32 PAD[10]; /* save/restore, corerev >= 48 */ uint32 sr_capability; /* 0x500 */ @@ -373,20 +387,37 @@ typedef volatile struct { uint32 pmustrapopt; /* 0x668, corerev >= 28 */ uint32 pmu_xtalfreq; /* 0x66C, pmurev >= 10 */ uint32 retention_ctl; /* 0x670 */ - uint32 PAD[3]; + uint32 ILPPeriod; /* 0x674 */ + uint32 PAD[2]; uint32 retention_grpidx; /* 0x680 */ uint32 retention_grpctl; /* 0x684 */ - uint32 PAD[20]; + uint32 mac_res_req_timer; /* 0x688 */ + uint32 mac_res_req_mask; /* 0x68c */ + uint32 PAD[18]; uint32 pmucontrol_ext; /* 0x6d8 */ uint32 slowclkperiod; /* 0x6dc */ - uint32 PAD[8]; + uint32 pmu_statstimer_addr; /* 0x6e0 */ + uint32 pmu_statstimer_ctrl; /* 0x6e4 */ + uint32 pmu_statstimer_N; /* 0x6e8 */ + uint32 PAD[1]; + uint32 mac_res_req_timer1; /* 0x6f0 */ + uint32 mac_res_req_mask1; /* 0x6f4 */ + uint32 PAD[2]; uint32 pmuintmask0; /* 0x700 */ uint32 pmuintmask1; /* 0x704 */ uint32 PAD[14]; uint32 pmuintstatus; /* 0x740 */ - uint32 PAD[15]; + uint32 extwakeupstatus; /* 0x744 */ + uint32 PAD[6]; + uint32 extwakemask0; /* 0x760 */ + uint32 extwakemask1; /* 0x764 */ + uint32 PAD[2]; /* 0x768-0x76C */ + uint32 extwakereqmask[2]; /* 0x770-0x774 */ + uint32 PAD[2]; /* 0x778-0x77C */ uint32 pmuintctrl0; /* 0x780 */ - uint32 PAD[31]; + uint32 PAD[3]; /* 0x784 - 0x78c */ + uint32 extwakectrl[1]; /* 0x790 */ + uint32 PAD[27]; uint16 sromotp[512]; /* 0x800 */ #ifdef CCNFLASH_SUPPORT /* Nand flash MLC controller registers (corerev >= 38) */ @@ -467,7 +498,7 @@ typedef volatile struct { uint32 gci_gpioctl; /* 0xC44 */ uint32 gci_gpiostatus; uint32 gci_gpiomask; /* 0xC4C */ - uint32 PAD; + uint32 gci_eventsummary; /* 0xC50 */ uint32 gci_miscctl; /* 0xC54 */ uint32 gci_gpiointmask; uint32 gci_gpiowakemask; @@ -526,7 +557,6 @@ typedef volatile struct { #endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */ - #define CC_CHIPID 0 #define CC_CAPABILITIES 4 #define CC_CHIPST 0x2c @@ -581,7 +611,7 @@ typedef volatile struct { #define CC_SROM_OTP 0xa000 /* SROM/OTP address space */ #else #define CC_SROM_OTP 0x0800 -#endif +#endif // endif #define CC_GCI_INDIRECT_ADDR_REG 0xC40 #define CC_GCI_CHIP_CTRL_REG 0xE00 #define CC_GCI_CC_OFFSET_2 2 @@ -589,6 +619,10 @@ typedef volatile struct { #define CC_SWD_CTRL 0x380 #define CC_SWD_REQACK 0x384 #define CC_SWD_DATA 0x388 +#define GPIO_SEL_0 0x00001111 +#define GPIO_SEL_1 0x11110000 +#define GPIO_SEL_8 0x00001111 +#define GPIO_SEL_9 0x11110000 #define CHIPCTRLREG0 0x0 #define CHIPCTRLREG1 0x1 @@ -631,6 +665,44 @@ typedef volatile struct { #define CC_BP_IND_ACCESS_ERROR_SHIFT 10 #define CC_BP_IND_ACCESS_ERROR_MASK (1 << CC_BP_IND_ACCESS_ERROR_SHIFT) +#define LPO_SEL_TIMEOUT 1000 + +#define LPO_FINAL_SEL_SHIFT 18 + +#define LHL_LPO1_SEL 0 +#define LHL_LPO2_SEL 0x1 +#define LHL_32k_SEL 0x2 +#define LHL_EXT_SEL 0x3 + +#define EXTLPO_BUF_PD 0x40 +#define LPO1_PD_EN 0x1 +#define LPO1_PD_SEL 0x6 +#define LPO1_PD_SEL_VAL 0x4 +#define LPO2_PD_EN 0x8 +#define LPO2_PD_SEL 0x30 +#define LPO2_PD_SEL_VAL 0x20 +#define OSC_32k_PD 0x80 + +#define LHL_CLK_DET_CTL_AD_CNTR_CLK_SEL 0x3 + +#define LHL_LPO_AUTO 0x0 +#define LHL_LPO1_ENAB 0x1 +#define LHL_LPO2_ENAB 0x2 +#define LHL_OSC_32k_ENAB 0x3 +#define LHL_EXT_LPO_ENAB 0x4 +#define RADIO_LPO_ENAB 0x5 + +#define LHL_CLK_DET_CTL_ADR_LHL_CNTR_EN 0x4 +#define LHL_CLK_DET_CTL_ADR_LHL_CNTR_CLR 0x8 +#define LHL_CLK_DET_CNT 0xF0 +#define LHL_CLK_DET_CNT_SHIFT 4 +#define LPO_SEL_SHIFT 9 + +#define LHL_MAIN_CTL_ADR_FINAL_CLK_SEL 0x3C0000 +#define LHL_MAIN_CTL_ADR_LHL_WLCLK_SEL 0x600 + +#define CLK_DET_CNT_THRESH 8 + #ifdef SR_DEBUG #define SUBCORE_POWER_ON 0x0001 #define PHY_POWER_ON 0x0010 @@ -707,6 +779,14 @@ typedef volatile struct { #define GCI_WL_CHN_INFO_MASK (0xFF00) /* WL indication of MCHAN enabled/disabled to BT in awdl mode- bit 36 */ #define GCI_WL_MCHAN_BIT_MASK (0x0010) + +#ifdef WLC_SW_DIVERSITY +/* WL indication of SWDIV enabled/disabled to BT - bit 33 */ +#define GCI_WL_SWDIV_ANT_VALID_BIT_MASK (0x0002) +#define GCI_SWDIV_ANT_VALID_SHIFT 0x1 +#define GCI_SWDIV_ANT_VALID_DISABLE 0x0 +#endif // endif + /* WL Strobe to BT */ #define GCI_WL_STROBE_BIT_MASK (0x0020) /* bits [51:48] - reserved for wlan TX pwr index */ @@ -769,8 +849,6 @@ typedef volatile struct { #define RCTL_MEM_RET_SLEEP_LOG_MASK (1 << RCTL_MEM_RET_SLEEP_LOG_SHIFT) /* 4321 chipcontrol */ -#define CHIPCTRL_4321A0_DEFAULT 0x3a4 -#define CHIPCTRL_4321A1_DEFAULT 0x0a4 #define CHIPCTRL_4321_PLL_DOWN 0x800000 /**< serdes PLL down override */ /* Fields in the otpstatus register in rev >= 21 */ @@ -928,7 +1006,6 @@ typedef volatile struct { /* Fields in otplayoutextension */ #define OTPLAYOUTEXT_FUSE_MASK 0x3FF - /* Jtagm characteristics that appeared at a given corerev */ #define JTAGM_CREV_OLD 10 /**< Old command set, 16bit max IR */ #define JTAGM_CREV_IRP 22 /**< Able to do pause-ir */ @@ -985,7 +1062,15 @@ typedef volatile struct { #define CLKD_JTAG_SHIFT 8 #define CLKD_UART 0x000000ff -#define CLKD2_SROM 0x00000003 +#define CLKD2_SROM 0x00000007 +#define CLKD2_SROMDIV_32 0 +#define CLKD2_SROMDIV_64 1 +#define CLKD2_SROMDIV_96 2 +#define CLKD2_SROMDIV_128 3 +#define CLKD2_SROMDIV_192 4 +#define CLKD2_SROMDIV_256 5 +#define CLKD2_SROMDIV_384 6 +#define CLKD2_SROMDIV_512 7 #define CLKD2_SWD 0xf8000000 #define CLKD2_SWD_SHIFT 27 @@ -997,6 +1082,7 @@ typedef volatile struct { #define CI_ECI 0x00000010 /**< eci intr (corerev >= 21) */ #define CI_PMU 0x00000020 /**< pmu intr (corerev >= 21) */ #define CI_UART 0x00000040 /**< uart intr (corerev >= 21) */ +#define CI_WECI 0x00000080 /* eci wakeup intr (corerev >= 21) */ #define CI_WDRESET 0x80000000 /**< watchdog reset occurred */ /* slow_clk_ctl */ @@ -1030,6 +1116,17 @@ typedef volatile struct { #define SYCC_CD_MASK 0xffff0000 /**< ClkDiv (ILP = 1/(4 * (divisor + 1)) */ #define SYCC_CD_SHIFT 16 +/* watchdogcounter */ +#define SSRESET_PCIE_F0 0x10000000 +#define SSRESET_PCIE_F1 0x20000000 +#define SSRESET_PCIE_F2 0x40000000 +#define WD_RESET_EN 0x80000000 +#define WD_COUNTER_MASK 0x0fffffff +#define WD_SSRESET_PCIE_F0_EN (WD_RESET_EN | SSRESET_PCIE_F0) +#define WD_SSRESET_PCIE_F1_EN (WD_RESET_EN | SSRESET_PCIE_F1) +#define WD_ENABLE_MASK \ + (WD_RESET_EN | SSRESET_PCIE_F0 | SSRESET_PCIE_F1 | SSRESET_PCIE_F2) + /* Indirect backplane access */ #define BPIA_BYTEEN 0x0000000f #define BPIA_SZ1 0x00000001 @@ -1140,8 +1237,10 @@ typedef volatile struct { #define PCTL_LPO_SEL 0x00000001 /* Fields in pmucontrol_ext */ -#define PCTL_EXT_FASTLPO_ENAB 0x00000080 +#define PCTL_EXT_USE_LHL_TIMER 0x00000010 +#define PCTL_EXT_FASTLPO_ENAB 0x00000080 #define PCTL_EXT_FASTLPO_SWENAB 0x00000200 +#define PCTL_EXT_FASTSEQ_ENAB 0x00001000 #define PCTL_EXT_FASTLPO_PCIE_SWENAB 0x00004000 /**< rev33 for FLL1M */ #define DEFAULT_43012_MIN_RES_MASK 0x0f8bfe77 @@ -1166,16 +1265,11 @@ typedef volatile struct { #define PMU_RCTLGRP_DFT_ENABLE_MASK (1 << 15) #define PMU_RCTLGRP_NSRST_DISABLE_SHIFT 16 #define PMU_RCTLGRP_NSRST_DISABLE_MASK (1 << 16) -/* Retention Group Control special for 4334 */ -#define PMU4334_RCTLGRP_CHAIN_LEN_GRP0 338 -#define PMU4334_RCTLGRP_CHAIN_LEN_GRP1 315 -/* Retention Group Control special for 43341 */ -#define PMU43341_RCTLGRP_CHAIN_LEN_GRP0 366 -#define PMU43341_RCTLGRP_CHAIN_LEN_GRP1 330 /* Fields in clkstretch */ #define CSTRETCH_HT 0xffff0000 #define CSTRETCH_ALP 0x0000ffff +#define CSTRETCH_REDUCE_8 0x00080008 /* gpiotimerval */ #define GPIO_ONTIME_SHIFT 16 @@ -1267,7 +1361,6 @@ typedef volatile struct { #define CC_EB_PCMCIA1_CFG 0x1ac00000 /**< PCMCIA 1 config base address */ #define CC_EB_PROGIF 0x1b000000 /**< ProgIF Async/Sync base address */ - /* Start/busy bit in flashcontrol */ #define SFLASH_OPCODE 0x000000ff #define SFLASH_ACTION 0x00000700 @@ -1346,6 +1439,12 @@ typedef volatile struct { #define GSIO_START 0x80000000 #define GSIO_BUSY GSIO_START +/* GCI UART Function sel related */ +#define MUXENAB_GCI_UART_MASK (0x00000f00) +#define MUXENAB_GCI_UART_SHIFT 8 +#define MUXENAB_GCI_UART_FNSEL_MASK (0x00003000) +#define MUXENAB_GCI_UART_FNSEL_SHIFT 12 + /* * These are the UART port assignments, expressed as offsets from the base * register. These assignments should hold for any serial port based on @@ -1428,6 +1527,26 @@ typedef volatile struct { #define PCAP5_CC_MASK 0xf8000000 #define PCAP5_CC_SHIFT 27 +/* pmucapabilities ext */ +#define PCAP_EXT_ST_NUM_SHIFT (8) /* stat timer number */ +#define PCAP_EXT_ST_NUM_MASK (0xf << PCAP_EXT_ST_NUM_SHIFT) +#define PCAP_EXT_ST_SRC_NUM_SHIFT (12) /* stat timer source number */ +#define PCAP_EXT_ST_SRC_NUM_MASK (0xf << PCAP_EXT_ST_SRC_NUM_SHIFT) + +/* pmustattimer ctrl */ +#define PMU_ST_SRC_SHIFT (0) /* stat timer source number */ +#define PMU_ST_SRC_MASK (0xff << PMU_ST_SRC_SHIFT) +#define PMU_ST_CNT_MODE_SHIFT (10) /* stat timer count mode */ +#define PMU_ST_CNT_MODE_MASK (0x3 << PMU_ST_CNT_MODE_SHIFT) +#define PMU_ST_EN_SHIFT (8) /* stat timer enable */ +#define PMU_ST_EN_MASK (0x1 << PMU_ST_EN_SHIFT) +#define PMU_ST_ENAB 1 +#define PMU_ST_DISAB 0 +#define PMU_ST_INT_EN_SHIFT (9) /* stat timer enable */ +#define PMU_ST_INT_EN_MASK (0x1 << PMU_ST_INT_EN_SHIFT) +#define PMU_ST_INT_ENAB 1 +#define PMU_ST_INT_DISAB 0 + /* CoreCapabilitiesExtension */ #define PCAP_EXT_USE_MUXED_ILP_CLK_MASK 0x04000000 @@ -1435,7 +1554,12 @@ typedef volatile struct { /* This is based on PmuRev0 */ #define PRRT_TIME_MASK 0x03ff #define PRRT_INTEN 0x0400 -#define PRRT_REQ_ACTIVE 0x0800 +/* ReqActive 25 + * The hardware sets this field to 1 when the timer expires. + * Software writes this field to 1 to make immediate resource requests. + */ +#define PRRT_REQ_ACTIVE 0x0800 /* To check h/w status */ +#define PRRT_IMMEDIATE_RES_REQ 0x0800 /* macro for sw immediate res req */ #define PRRT_ALP_REQ 0x1000 #define PRRT_HT_REQ 0x2000 #define PRRT_HQ_REQ 0x4000 @@ -1447,6 +1571,11 @@ typedef volatile struct { /* bit 0 of the PMU interrupt vector is asserted if this mask is enabled */ #define RSRC_INTR_MASK_TIMER_INT_0 1 +#define PMU_INTR_MASK_EXTWAKE_REQ_ACTIVE_0 (1 << 20) + +/* bit 16 of the PMU interrupt vector - Stats Timer Interrupt */ +#define PMU_INT_STAT_TIMER_INT_SHIFT 16 +#define PMU_INT_STAT_TIMER_INT_MASK (1 << PMU_INT_STAT_TIMER_INT_SHIFT) /* PMU resource bit position */ #define PMURES_BIT(bit) (1 << (bit)) @@ -1456,7 +1585,15 @@ typedef volatile struct { /* PMU chip control0 register */ #define PMU_CHIPCTL0 0 -#define PMU43143_CC0_SDIO_DRSTR_OVR (1 << 31) /* sdio drive strength override enable */ + +#define PMU_CC0_4369_XTALCORESIZE_BIAS_ADJ_START_VAL (0x20 << 0) +#define PMU_CC0_4369_XTALCORESIZE_BIAS_ADJ_START_MASK (0x3F << 0) +#define PMU_CC0_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL (0xF << 6) +#define PMU_CC0_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK (0x3F << 6) +#define PMU_CC0_4369_XTAL_RES_BYPASS_START_VAL (0 << 12) +#define PMU_CC0_4369_XTAL_RES_BYPASS_START_MASK (0x7 << 12) +#define PMU_CC0_4369_XTAL_RES_BYPASS_NORMAL_VAL (0x1 << 15) +#define PMU_CC0_4369_XTAL_RES_BYPASS_NORMAL_MASK (0x7 << 15) /* clock req types */ #define PMU_CC1_CLKREQ_TYPE_SHIFT 19 @@ -1465,6 +1602,10 @@ typedef volatile struct { #define CLKREQ_TYPE_CONFIG_OPENDRAIN 0 #define CLKREQ_TYPE_CONFIG_PUSHPULL 1 +/* Power Control */ +#define PWRCTL_ENAB_MEM_CLK_GATE_SHIFT 5 +#define PWRCTL_AUTO_MEM_STBYRET 28 + /* PMU chip control1 register */ #define PMU_CHIPCTL1 1 #define PMU_CC1_RXC_DLL_BYPASS 0x00010000 @@ -1484,6 +1625,9 @@ typedef volatile struct { #define PMU_CC1_ENABLE_CLOSED_LOOP_MASK 0x00000080 #define PMU_CC1_ENABLE_CLOSED_LOOP 0x00000000 +#define PMU_CC1_PWRSW_CLKSTRSTP_DELAY_MASK 0x00003F00u +#define PMU_CC1_PWRSW_CLKSTRSTP_DELAY 0x00000400u + /* PMU chip control2 register */ #define PMU_CC2_RFLDO3P3_PU_FORCE_ON (1 << 15) #define PMU_CC2_RFLDO3P3_PU_CLEAR 0x00000000 @@ -1498,12 +1642,30 @@ typedef volatile struct { #define PMU_CC2_INV_GPIO_POLARITY_PMU_WAKE (1 << 25) #define PMU_CC2_GCI2_WAKE (1 << 31) +#define PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_START_VAL (0x3 << 26) +#define PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_START_MASK (0x3 << 26) +#define PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_VAL (0x0 << 28) +#define PMU_CC2_4369_XTALCORESIZE_BIAS_ADJ_NORMAL_MASK (0x3 << 28) + /* PMU chip control3 register */ #define PMU_CHIPCTL3 3 #define PMU_CC3_ENABLE_SDIO_WAKEUP_SHIFT 19 #define PMU_CC3_ENABLE_RF_SHIFT 22 #define PMU_CC3_RF_DISABLE_IVALUE_SHIFT 23 +#define PMU_CC3_4369_XTALCORESIZE_PMOS_START_VAL (0x3F << 0) +#define PMU_CC3_4369_XTALCORESIZE_PMOS_START_MASK (0x3F << 0) +#define PMU_CC3_4369_XTALCORESIZE_PMOS_NORMAL_VAL (0x3F << 15) +#define PMU_CC3_4369_XTALCORESIZE_PMOS_NORMAL_MASK (0x3F << 15) +#define PMU_CC3_4369_XTALCORESIZE_NMOS_START_VAL (0x3F << 6) +#define PMU_CC3_4369_XTALCORESIZE_NMOS_START_MASK (0x3F << 6) +#define PMU_CC3_4369_XTALCORESIZE_NMOS_NORMAL_VAL (0x3F << 21) +#define PMU_CC3_4369_XTALCORESIZE_NMOS_NORMAL_MASK (0x3F << 21) +#define PMU_CC3_4369_XTALSEL_BIAS_RES_START_VAL (0x2 << 12) +#define PMU_CC3_4369_XTALSEL_BIAS_RES_START_MASK (0x7 << 12) +#define PMU_CC3_4369_XTALSEL_BIAS_RES_NORMAL_VAL (0x6 << 27) +#define PMU_CC3_4369_XTALSEL_BIAS_RES_NORMAL_MASK (0x7 << 27) + /* PMU chip control4 register */ #define PMU_CHIPCTL4 4 @@ -1520,13 +1682,31 @@ typedef volatile struct { #define PMU_CC4_SW_TYPE_RGMII 0x0000c000 #define PMU_CC4_DISABLE_LQ_AVAIL (1<<27) +#define PMU_CC4_4369_MAIN_PD_CBUCK2VDDB_ON (1u << 15u) +#define PMU_CC4_4369_MAIN_PD_CBUCK2VDDRET_ON (1u << 16u) +#define PMU_CC4_4369_MAIN_PD_MEMLPLDO2VDDB_ON (1u << 17u) +#define PMU_CC4_4369_MAIN_PD_MEMLPDLO2VDDRET_ON (1u << 18u) + +#define PMU_CC4_4369_AUX_PD_CBUCK2VDDB_ON (1u << 21u) +#define PMU_CC4_4369_AUX_PD_CBUCK2VDDRET_ON (1u << 22u) +#define PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDB_ON (1u << 23u) +#define PMU_CC4_4369_AUX_PD_MEMLPLDO2VDDRET_ON (1u << 24u) + /* PMU chip control5 register */ #define PMU_CHIPCTL5 5 +#define PMU_CC5_4369_SUBCORE_CBUCK2VDDB_ON (1u << 9u) +#define PMU_CC5_4369_SUBCORE_CBUCK2VDDRET_ON (1u << 10u) +#define PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDB_ON (1u << 11u) +#define PMU_CC5_4369_SUBCORE_MEMLPLDO2VDDRET_ON (1u << 12u) + /* PMU chip control6 register */ #define PMU_CHIPCTL6 6 #define PMU_CC6_ENABLE_CLKREQ_WAKEUP (1 << 4) #define PMU_CC6_ENABLE_PMU_WAKEUP_ALP (1 << 6) +#define PMU_CC6_ENABLE_PCIE_RETENTION (1 << 12) +#define PMU_CC6_ENABLE_PMU_EXT_PERST (1 << 13) +#define PMU_CC6_ENABLE_PMU_WAKEUP_PERST (1 << 14) /* PMU chip control7 register */ #define PMU_CHIPCTL7 7 @@ -1541,6 +1721,61 @@ typedef volatile struct { #define PMU_CHIPCTL8 8 #define PMU_CHIPCTL9 9 +#define PMU_CHIPCTL10 10 +#define PMU_CC10_PCIE_PWRSW_RESET0_CNT_SHIFT 0 +#define PMU_CC10_PCIE_PWRSW_RESET0_CNT_MASK 0x000000ff +#define PMU_CC10_PCIE_PWRSW_RESET1_CNT_SHIFT 8 +#define PMU_CC10_PCIE_PWRSW_RESET1_CNT_MASK 0x0000ff00 +#define PMU_CC10_PCIE_PWRSW_UP_DLY_SHIFT 16 +#define PMU_CC10_PCIE_PWRSW_UP_DLY_MASK 0x000f0000 +#define PMU_CC10_PCIE_PWRSW_FORCE_PWROK_DLY_SHIFT 20 +#define PMU_CC10_PCIE_PWRSW_FORCE_PWROK_DLY_MASK 0x00f00000 +#define PMU_CC10_FORCE_PCIE_ON (1 << 24) +#define PMU_CC10_FORCE_PCIE_SW_ON (1 << 25) +#define PMU_CC10_FORCE_PCIE_RETNT_ON (1 << 26) + +#define PMU_CC10_PCIE_PWRSW_RESET_CNT_4US 1 +#define PMU_CC10_PCIE_PWRSW_RESET_CNT_8US 2 + +#define PMU_CC10_PCIE_PWRSW_UP_DLY_0US 0 + +#define PMU_CC10_PCIE_PWRSW_FORCE_PWROK_DLY_4US 1 + +#define PMU_CHIPCTL11 11 +#define PMU_CHIPCTL12 12 + +/* PMU chip control13 register */ +#define PMU_CHIPCTL13 13 + +#define PMU_CC13_SUBCORE_CBUCK2VDDB_OFF (1u << 0u) +#define PMU_CC13_SUBCORE_CBUCK2VDDRET_OFF (1u << 1u) +#define PMU_CC13_SUBCORE_MEMLPLDO2VDDB_OFF (1u << 2u) +#define PMU_CC13_SUBCORE_MEMLPLDO2VDDRET_OFF (1u << 3u) + +#define PMU_CC13_MAIN_CBUCK2VDDB_OFF (1u << 4u) +#define PMU_CC13_MAIN_CBUCK2VDDRET_OFF (1u << 5u) +#define PMU_CC13_MAIN_MEMLPLDO2VDDB_OFF (1u << 6u) +#define PMU_CC13_MAIN_MEMLPLDO2VDDRET_OFF (1u << 7u) + +#define PMU_CC13_AUX_CBUCK2VDDB_OFF (1u << 8u) +#define PMU_CC13_AUX_MEMLPLDO2VDDB_OFF (1u << 10u) +#define PMU_CC13_AUX_MEMLPLDO2VDDRET_OFF (1u << 11u) +#define PMU_CC13_AUX_CBUCK2VDDRET_OFF (1u << 12u) + +#define PMU_CHIPCTL14 14 +#define PMU_CHIPCTL15 15 +#define PMU_CHIPCTL16 16 +#define PMU_CC16_CLK4M_DIS (1 << 4) +#define PMU_CC16_FF_ZERO_ADJ (4 << 5) + +/* PMU chip control14 register */ +#define PMU_CC14_MAIN_VDDB2VDDRET_UP_DLY_MASK (0xF) +#define PMU_CC14_MAIN_VDDB2VDD_UP_DLY_MASK (0xF << 4) +#define PMU_CC14_AUX_VDDB2VDDRET_UP_DLY_MASK (0xF << 8) +#define PMU_CC14_AUX_VDDB2VDD_UP_DLY_MASK (0xF << 12) +#define PMU_CC14_PCIE_VDDB2VDDRET_UP_DLY_MASK (0xF << 16) +#define PMU_CC14_PCIE_VDDB2VDD_UP_DLY_MASK (0xF << 20) + /* PMU corerev and chip specific PLL controls. * PMU_PLL_XX where is PMU corerev and is an arbitrary number * to differentiate different PLLs controlled by the same PMU rev. @@ -1599,7 +1834,8 @@ typedef volatile struct { #define PMU1_PLL0_PC1_M4DIV_BY_18 0x12 #define PMU1_PLL0_PC1_M4DIV_BY_36 0x24 #define PMU1_PLL0_PC1_M4DIV_BY_60 0x3C - +#define PMU1_PLL0_PC1_M2_M4DIV_MASK 0xff00ff00 +#define PMU1_PLL0_PC1_HOLD_LOAD_CH 0x28 #define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 #define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) #define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) @@ -1744,18 +1980,6 @@ typedef volatile struct { #define PMU5_MAINPLL_MEM 2 #define PMU5_MAINPLL_SI 3 -/* 4706 PMU */ -#define PMU4706_MAINPLL_PLL0 0 -#define PMU6_4706_PROCPLL_OFF 4 /**< The CPU PLL */ -#define PMU6_4706_PROC_P2DIV_MASK 0x000f0000 -#define PMU6_4706_PROC_P2DIV_SHIFT 16 -#define PMU6_4706_PROC_P1DIV_MASK 0x0000f000 -#define PMU6_4706_PROC_P1DIV_SHIFT 12 -#define PMU6_4706_PROC_NDIV_INT_MASK 0x00000ff8 -#define PMU6_4706_PROC_NDIV_INT_SHIFT 3 -#define PMU6_4706_PROC_NDIV_MODE_MASK 0x00000007 -#define PMU6_4706_PROC_NDIV_MODE_SHIFT 0 - #define PMU7_PLL_PLLCTL7 7 #define PMU7_PLL_CTL7_M4DIV_MASK 0xff000000 #define PMU7_PLL_CTL7_M4DIV_SHIFT 24 @@ -1883,7 +2107,6 @@ typedef volatile struct { #define PMU15_ARM_98MHZ 98400000 /**< 98.4 Mhz */ #define PMU15_ARM_97MHZ 97000000 /**< 97 Mhz */ - #define PMU17_PLLCTL2_NDIVTYPE_MASK 0x00000070 #define PMU17_PLLCTL2_NDIVTYPE_SHIFT 4 @@ -1923,228 +2146,33 @@ typedef volatile struct { #define PMU4347_PLL1_PC6_NDIV_FRAC_MASK 0xfffff000 #define PMU4347_PLL1_PC6_NDIV_FRAC_SHIFT 12 -/* PLL usage in 5356/5357 */ -#define PMU5356_MAINPLL_PLL0 0 -#define PMU5357_MAINPLL_PLL0 0 - -/* 4716/47162 resources */ -#define RES4716_PROC_PLL_ON 0x00000040 -#define RES4716_PROC_HT_AVAIL 0x00000080 - -/* 4716/4717/4718 Chip specific ChipControl register bits */ -#define CCTRL_471X_I2S_PINS_ENABLE 0x0080 /* I2S pins off by default, shared w/ pflash */ - -/* 5357 Chip specific ChipControl register bits */ -/* 2nd - 32-bit reg */ -#define CCTRL_5357_I2S_PINS_ENABLE 0x00040000 /* I2S pins enable */ -#define CCTRL_5357_I2CSPI_PINS_ENABLE 0x00080000 /* I2C/SPI pins enable */ - -/* 5354 resources */ -#define RES5354_EXT_SWITCHER_PWM 0 /**< 0x00001 */ -#define RES5354_BB_SWITCHER_PWM 1 /**< 0x00002 */ -#define RES5354_BB_SWITCHER_BURST 2 /**< 0x00004 */ -#define RES5354_BB_EXT_SWITCHER_BURST 3 /**< 0x00008 */ -#define RES5354_ILP_REQUEST 4 /**< 0x00010 */ -#define RES5354_RADIO_SWITCHER_PWM 5 /**< 0x00020 */ -#define RES5354_RADIO_SWITCHER_BURST 6 /**< 0x00040 */ -#define RES5354_ROM_SWITCH 7 /**< 0x00080 */ -#define RES5354_PA_REF_LDO 8 /**< 0x00100 */ -#define RES5354_RADIO_LDO 9 /**< 0x00200 */ -#define RES5354_AFE_LDO 10 /**< 0x00400 */ -#define RES5354_PLL_LDO 11 /**< 0x00800 */ -#define RES5354_BG_FILTBYP 12 /**< 0x01000 */ -#define RES5354_TX_FILTBYP 13 /**< 0x02000 */ -#define RES5354_RX_FILTBYP 14 /**< 0x04000 */ -#define RES5354_XTAL_PU 15 /**< 0x08000 */ -#define RES5354_XTAL_EN 16 /**< 0x10000 */ -#define RES5354_BB_PLL_FILTBYP 17 /**< 0x20000 */ -#define RES5354_RF_PLL_FILTBYP 18 /**< 0x40000 */ -#define RES5354_BB_PLL_PU 19 /**< 0x80000 */ +/* Even though the masks are same as 4347, separate macros are +created for 4369 +*/ +/* PLL usage in 4369 */ +#define PMU4369_PLL0_PC2_PDIV_MASK 0x000f0000 +#define PMU4369_PLL0_PC2_PDIV_SHIFT 16 +#define PMU4369_PLL0_PC2_NDIV_INT_MASK 0x3ff00000 +#define PMU4369_PLL0_PC2_NDIV_INT_SHIFT 20 +#define PMU4369_PLL0_PC3_NDIV_FRAC_MASK 0x000fffff +#define PMU4369_PLL0_PC3_NDIV_FRAC_SHIFT 0 +#define PMU4369_PLL1_PC5_P1DIV_MASK 0xc0000000 +#define PMU4369_PLL1_PC5_P1DIV_SHIFT 30 +#define PMU4369_PLL1_PC6_P1DIV_MASK 0x00000003 +#define PMU4369_PLL1_PC6_P1DIV_SHIFT 0 +#define PMU4369_PLL1_PC6_NDIV_INT_MASK 0x00000ffc +#define PMU4369_PLL1_PC6_NDIV_INT_SHIFT 2 +#define PMU4369_PLL1_PC6_NDIV_FRAC_MASK 0xfffff000 +#define PMU4369_PLL1_PC6_NDIV_FRAC_SHIFT 12 /* 5357 Chip specific ChipControl register bits */ #define CCTRL5357_EXTPA (1<<14) /* extPA in ChipControl 1, bit 14 */ #define CCTRL5357_ANT_MUX_2o3 (1<<15) /* 2o3 in ChipControl 1, bit 15 */ #define CCTRL5357_NFLASH (1<<16) /* Nandflash in ChipControl 1, bit 16 */ - /* 43217 Chip specific ChipControl register bits */ #define CCTRL43217_EXTPA_C0 (1<<13) /* core0 extPA in ChipControl 1, bit 13 */ #define CCTRL43217_EXTPA_C1 (1<<8) /* core1 extPA in ChipControl 1, bit 8 */ -/* 43228 Chip specific ChipControl register bits */ -#define CCTRL43228_EXTPA_C0 (1<<14) /* core1 extPA in ChipControl 1, bit 14 */ -#define CCTRL43228_EXTPA_C1 (1<<9) /* core0 extPA in ChipControl 1, bit 1 */ - -/* 4328 resources */ -#define RES4328_EXT_SWITCHER_PWM 0 /**< 0x00001 */ -#define RES4328_BB_SWITCHER_PWM 1 /**< 0x00002 */ -#define RES4328_BB_SWITCHER_BURST 2 /**< 0x00004 */ -#define RES4328_BB_EXT_SWITCHER_BURST 3 /**< 0x00008 */ -#define RES4328_ILP_REQUEST 4 /**< 0x00010 */ -#define RES4328_RADIO_SWITCHER_PWM 5 /**< 0x00020 */ -#define RES4328_RADIO_SWITCHER_BURST 6 /**< 0x00040 */ -#define RES4328_ROM_SWITCH 7 /**< 0x00080 */ -#define RES4328_PA_REF_LDO 8 /**< 0x00100 */ -#define RES4328_RADIO_LDO 9 /**< 0x00200 */ -#define RES4328_AFE_LDO 10 /**< 0x00400 */ -#define RES4328_PLL_LDO 11 /**< 0x00800 */ -#define RES4328_BG_FILTBYP 12 /**< 0x01000 */ -#define RES4328_TX_FILTBYP 13 /**< 0x02000 */ -#define RES4328_RX_FILTBYP 14 /**< 0x04000 */ -#define RES4328_XTAL_PU 15 /**< 0x08000 */ -#define RES4328_XTAL_EN 16 /**< 0x10000 */ -#define RES4328_BB_PLL_FILTBYP 17 /**< 0x20000 */ -#define RES4328_RF_PLL_FILTBYP 18 /**< 0x40000 */ -#define RES4328_BB_PLL_PU 19 /**< 0x80000 */ - -/* 4325 A0/A1 resources */ -#define RES4325_BUCK_BOOST_BURST 0 /**< 0x00000001 */ -#define RES4325_CBUCK_BURST 1 /**< 0x00000002 */ -#define RES4325_CBUCK_PWM 2 /**< 0x00000004 */ -#define RES4325_CLDO_CBUCK_BURST 3 /**< 0x00000008 */ -#define RES4325_CLDO_CBUCK_PWM 4 /**< 0x00000010 */ -#define RES4325_BUCK_BOOST_PWM 5 /**< 0x00000020 */ -#define RES4325_ILP_REQUEST 6 /**< 0x00000040 */ -#define RES4325_ABUCK_BURST 7 /**< 0x00000080 */ -#define RES4325_ABUCK_PWM 8 /**< 0x00000100 */ -#define RES4325_LNLDO1_PU 9 /**< 0x00000200 */ -#define RES4325_OTP_PU 10 /**< 0x00000400 */ -#define RES4325_LNLDO3_PU 11 /**< 0x00000800 */ -#define RES4325_LNLDO4_PU 12 /**< 0x00001000 */ -#define RES4325_XTAL_PU 13 /**< 0x00002000 */ -#define RES4325_ALP_AVAIL 14 /**< 0x00004000 */ -#define RES4325_RX_PWRSW_PU 15 /**< 0x00008000 */ -#define RES4325_TX_PWRSW_PU 16 /**< 0x00010000 */ -#define RES4325_RFPLL_PWRSW_PU 17 /**< 0x00020000 */ -#define RES4325_LOGEN_PWRSW_PU 18 /**< 0x00040000 */ -#define RES4325_AFE_PWRSW_PU 19 /**< 0x00080000 */ -#define RES4325_BBPLL_PWRSW_PU 20 /**< 0x00100000 */ -#define RES4325_HT_AVAIL 21 /**< 0x00200000 */ - -/* 4325 B0/C0 resources */ -#define RES4325B0_CBUCK_LPOM 1 /**< 0x00000002 */ -#define RES4325B0_CBUCK_BURST 2 /**< 0x00000004 */ -#define RES4325B0_CBUCK_PWM 3 /**< 0x00000008 */ -#define RES4325B0_CLDO_PU 4 /**< 0x00000010 */ - -/* 4325 C1 resources */ -#define RES4325C1_LNLDO2_PU 12 /**< 0x00001000 */ - -/* 4325 chip-specific ChipStatus register bits */ -#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4325_DEFCIS_SEL 0 /**< OTP is powered up, use def. CIS, no SPROM */ -#define CST4325_SPROM_SEL 1 /**< OTP is powered up, SPROM is present */ -#define CST4325_OTP_SEL 2 /**< OTP is powered up, no SPROM */ -#define CST4325_OTP_PWRDN 3 /**< OTP is powered down, SPROM is present */ -#define CST4325_SDIO_USB_MODE_MASK 0x00000004 -#define CST4325_SDIO_USB_MODE_SHIFT 2 -#define CST4325_RCAL_VALID_MASK 0x00000008 -#define CST4325_RCAL_VALID_SHIFT 3 -#define CST4325_RCAL_VALUE_MASK 0x000001f0 -#define CST4325_RCAL_VALUE_SHIFT 4 -#define CST4325_PMUTOP_2B_MASK 0x00000200 /**< 1 for 2b, 0 for to 2a */ -#define CST4325_PMUTOP_2B_SHIFT 9 - -#define RES4329_RESERVED0 0 /**< 0x00000001 */ -#define RES4329_CBUCK_LPOM 1 /**< 0x00000002 */ -#define RES4329_CBUCK_BURST 2 /**< 0x00000004 */ -#define RES4329_CBUCK_PWM 3 /**< 0x00000008 */ -#define RES4329_CLDO_PU 4 /**< 0x00000010 */ -#define RES4329_PALDO_PU 5 /**< 0x00000020 */ -#define RES4329_ILP_REQUEST 6 /**< 0x00000040 */ -#define RES4329_RESERVED7 7 /**< 0x00000080 */ -#define RES4329_RESERVED8 8 /**< 0x00000100 */ -#define RES4329_LNLDO1_PU 9 /**< 0x00000200 */ -#define RES4329_OTP_PU 10 /**< 0x00000400 */ -#define RES4329_RESERVED11 11 /**< 0x00000800 */ -#define RES4329_LNLDO2_PU 12 /**< 0x00001000 */ -#define RES4329_XTAL_PU 13 /**< 0x00002000 */ -#define RES4329_ALP_AVAIL 14 /**< 0x00004000 */ -#define RES4329_RX_PWRSW_PU 15 /**< 0x00008000 */ -#define RES4329_TX_PWRSW_PU 16 /**< 0x00010000 */ -#define RES4329_RFPLL_PWRSW_PU 17 /**< 0x00020000 */ -#define RES4329_LOGEN_PWRSW_PU 18 /**< 0x00040000 */ -#define RES4329_AFE_PWRSW_PU 19 /**< 0x00080000 */ -#define RES4329_BBPLL_PWRSW_PU 20 /**< 0x00100000 */ -#define RES4329_HT_AVAIL 21 /**< 0x00200000 */ - -#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4329_DEFCIS_SEL 0 /**< OTP is powered up, use def. CIS, no SPROM */ -#define CST4329_SPROM_SEL 1 /**< OTP is powered up, SPROM is present */ -#define CST4329_OTP_SEL 2 /**< OTP is powered up, no SPROM */ -#define CST4329_OTP_PWRDN 3 /**< OTP is powered down, SPROM is present */ -#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 -#define CST4329_SPI_SDIO_MODE_SHIFT 2 - -/* 4312 chip-specific ChipStatus register bits */ -#define CST4312_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4312_DEFCIS_SEL 0 /**< OTP is powered up, use def. CIS, no SPROM */ -#define CST4312_SPROM_SEL 1 /**< OTP is powered up, SPROM is present */ -#define CST4312_OTP_SEL 2 /**< OTP is powered up, no SPROM */ -#define CST4312_OTP_BAD 3 /**< OTP is broken, SPROM is present */ - -/* 4312 resources (all PMU chips with little memory constraint) */ -#define RES4312_SWITCHER_BURST 0 /**< 0x00000001 */ -#define RES4312_SWITCHER_PWM 1 /**< 0x00000002 */ -#define RES4312_PA_REF_LDO 2 /**< 0x00000004 */ -#define RES4312_CORE_LDO_BURST 3 /**< 0x00000008 */ -#define RES4312_CORE_LDO_PWM 4 /**< 0x00000010 */ -#define RES4312_RADIO_LDO 5 /**< 0x00000020 */ -#define RES4312_ILP_REQUEST 6 /**< 0x00000040 */ -#define RES4312_BG_FILTBYP 7 /**< 0x00000080 */ -#define RES4312_TX_FILTBYP 8 /**< 0x00000100 */ -#define RES4312_RX_FILTBYP 9 /**< 0x00000200 */ -#define RES4312_XTAL_PU 10 /**< 0x00000400 */ -#define RES4312_ALP_AVAIL 11 /**< 0x00000800 */ -#define RES4312_BB_PLL_FILTBYP 12 /**< 0x00001000 */ -#define RES4312_RF_PLL_FILTBYP 13 /**< 0x00002000 */ -#define RES4312_HT_AVAIL 14 /**< 0x00004000 */ - -/* 4322 resources */ -#define RES4322_RF_LDO 0 -#define RES4322_ILP_REQUEST 1 -#define RES4322_XTAL_PU 2 -#define RES4322_ALP_AVAIL 3 -#define RES4322_SI_PLL_ON 4 -#define RES4322_HT_SI_AVAIL 5 -#define RES4322_PHY_PLL_ON 6 -#define RES4322_HT_PHY_AVAIL 7 -#define RES4322_OTP_PU 8 - -/* 4322 chip-specific ChipStatus register bits */ -#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 -#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 -#define CST4322_SPROM_OTP_SEL_SHIFT 6 -#define CST4322_NO_SPROM_OTP 0 /**< no OTP, no SPROM */ -#define CST4322_SPROM_PRESENT 1 /**< SPROM is present */ -#define CST4322_OTP_PRESENT 2 /**< OTP is present */ -#define CST4322_PCI_OR_USB 0x00000100 -#define CST4322_BOOT_MASK 0x00000600 -#define CST4322_BOOT_SHIFT 9 -#define CST4322_BOOT_FROM_SRAM 0 /**< boot from SRAM, ARM in reset */ -#define CST4322_BOOT_FROM_ROM 1 /**< boot from ROM */ -#define CST4322_BOOT_FROM_FLASH 2 /**< boot from FLASH */ -#define CST4322_BOOT_FROM_INVALID 3 -#define CST4322_ILP_DIV_EN 0x00000800 -#define CST4322_FLASH_TYPE_MASK 0x00001000 -#define CST4322_FLASH_TYPE_SHIFT 12 -#define CST4322_FLASH_TYPE_SHIFT_ST 0 /**< ST serial FLASH */ -#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 /**< ATMEL flash */ -#define CST4322_ARM_TAP_SEL 0x00002000 -#define CST4322_RES_INIT_MODE_MASK 0x0000c000 -#define CST4322_RES_INIT_MODE_SHIFT 14 -#define CST4322_RES_INIT_MODE_ILPAVAIL 0 /**< resinitmode: ILP available */ -#define CST4322_RES_INIT_MODE_ILPREQ 1 /**< resinitmode: ILP request */ -#define CST4322_RES_INIT_MODE_ALPAVAIL 2 /**< resinitmode: ALP available */ -#define CST4322_RES_INIT_MODE_HTAVAIL 3 /**< resinitmode: HT available */ -#define CST4322_PCIPLLCLK_GATING 0x00010000 -#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 -#define CST4322_PCI_CARDBUS_MODE 0x00040000 - -/* 43224 chip-specific ChipControl register bits */ -#define CCTRL43224_GPIO_TOGGLE 0x8000 /* gpio[3:0] pins as btcoex or s/w gpio */ -#define CCTRL_43224A0_12MA_LED_DRIVE 0x00F000F0 /* 12 mA drive strength */ -#define CCTRL_43224B0_12MA_LED_DRIVE 0xF0 /* 12 mA drive strength for later 43224s */ - /* 43236 resources */ #define RES43236_REGULATOR 0 #define RES43236_ILP_REQUEST 1 @@ -2173,327 +2201,13 @@ typedef volatile struct { #define CST43236_BOOT_FROM_FLASH 2 /**< boot from FLASH */ #define CST43236_BOOT_FROM_INVALID 3 -/* 43237 resources */ -#define RES43237_REGULATOR 0 -#define RES43237_ILP_REQUEST 1 -#define RES43237_XTAL_PU 2 -#define RES43237_ALP_AVAIL 3 -#define RES43237_SI_PLL_ON 4 -#define RES43237_HT_SI_AVAIL 5 - -/* 43237 chip-specific ChipControl register bits */ -#define CCTRL43237_BT_COEXIST (1<<0) /**< 0 disable */ -#define CCTRL43237_SECI (1<<1) /**< 0 SECI is disabled (JATG functional) */ -#define CCTRL43237_EXT_LNA (1<<2) /**< 0 disable */ -#define CCTRL43237_ANT_MUX_2o3 (1<<3) /**< 2o3 mux, chipcontrol bit 3 */ -#define CCTRL43237_GSIO (1<<4) /**< 0 disable */ - -/* 43237 Chip specific ChipStatus register bits */ -#define CST43237_SFLASH_MASK 0x00000040 -#define CST43237_OTP_SEL_MASK 0x00000080 -#define CST43237_OTP_SEL_SHIFT 7 -#define CST43237_HSIC_MASK 0x00000100 /**< USB/HSIC */ -#define CST43237_BP_CLK 0x00000200 /**< 120/96Mbps */ -#define CST43237_BOOT_MASK 0x00001800 -#define CST43237_BOOT_SHIFT 11 -#define CST43237_BOOT_FROM_SRAM 0 /**< boot from SRAM, ARM in reset */ -#define CST43237_BOOT_FROM_ROM 1 /**< boot from ROM */ -#define CST43237_BOOT_FROM_FLASH 2 /**< boot from FLASH */ -#define CST43237_BOOT_FROM_INVALID 3 - -/* 43239 resources */ -#define RES43239_OTP_PU 9 -#define RES43239_MACPHY_CLKAVAIL 23 -#define RES43239_HT_AVAIL 24 - -/* 43239 Chip specific ChipStatus register bits */ -#define CST43239_SPROM_MASK 0x00000002 -#define CST43239_SFLASH_MASK 0x00000004 -#define CST43239_RES_INIT_MODE_SHIFT 7 -#define CST43239_RES_INIT_MODE_MASK 0x000001f0 -#define CST43239_CHIPMODE_SDIOD(cs) ((cs) & (1 << 15)) /**< SDIO || gSPI */ -#define CST43239_CHIPMODE_USB20D(cs) (~(cs) & (1 << 15)) /**< USB || USBDA */ -#define CST43239_CHIPMODE_SDIO(cs) (((cs) & (1 << 0)) == 0) /**< SDIO */ -#define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) /**< gSPI */ - -/* 4324 resources */ -/* 43242 use same PMU as 4324 */ -#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 - -/* 4324 Chip specific ChipStatus register bits */ -#define CST4324_SPROM_MASK 0x00000080 -#define CST4324_SFLASH_MASK 0x00400000 -#define CST4324_RES_INIT_MODE_SHIFT 10 -#define CST4324_RES_INIT_MODE_MASK 0x00000c00 -#define CST4324_CHIPMODE_MASK 0x7 -#define CST4324_CHIPMODE_SDIOD(cs) ((~(cs)) & (1 << 2)) /**< SDIO || gSPI */ -#define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) /**< USB || USBDA */ - -/* 43242 Chip specific ChipStatus register bits */ -#define CST43242_SFLASH_MASK 0x00000008 -#define CST43242_SR_HALT (1<<25) -#define CST43242_SR_CHIP_STATUS_2 27 /* bit 27 */ - -/* 4331 resources */ -#define RES4331_REGULATOR 0 -#define RES4331_ILP_REQUEST 1 -#define RES4331_XTAL_PU 2 -#define RES4331_ALP_AVAIL 3 -#define RES4331_SI_PLL_ON 4 -#define RES4331_HT_SI_AVAIL 5 - -/* 4331 chip-specific ChipControl register bits */ -#define CCTRL4331_BT_COEXIST (1<<0) /**< 0 disable */ -#define CCTRL4331_SECI (1<<1) /**< 0 SECI is disabled (JATG functional) */ -#define CCTRL4331_EXT_LNA_G (1<<2) /**< 0 disable */ -#define CCTRL4331_SPROM_GPIO13_15 (1<<3) /**< sprom/gpio13-15 mux */ -#define CCTRL4331_EXTPA_EN (1<<4) /**< 0 ext pa disable, 1 ext pa enabled */ -#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) /**< set drive out GPIO_CLK on sprom_cs pin */ -#define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) /**< use sprom_cs pin as PCIE mdio interface */ -#define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) /* aband extpa will be at gpio2/5 and sprom_dout */ -#define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) /**< override core control on pipe_AuxClkEnable */ -#define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) /**< override core control on pipe_AuxPowerDown */ -#define CCTRL4331_PCIE_AUXCLKEN (1<<10) /**< pcie_auxclkenable */ -#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) /**< pcie_pipe_pllpowerdown */ -#define CCTRL4331_EXTPA_EN2 (1<<12) /**< 0 ext pa disable, 1 ext pa enabled */ -#define CCTRL4331_EXT_LNA_A (1<<13) /**< 0 disable */ -#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) /**< enable bt_shd0 at gpio4 */ -#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) /**< enable bt_shd1 at gpio5 */ -#define CCTRL4331_EXTPA_ANA_EN (1<<24) /**< 0 ext pa disable, 1 ext pa enabled */ - -/* 4331 Chip specific ChipStatus register bits */ -#define CST4331_XTAL_FREQ 0x00000001 /**< crystal frequency 20/40Mhz */ -#define CST4331_SPROM_OTP_SEL_MASK 0x00000006 -#define CST4331_SPROM_OTP_SEL_SHIFT 1 -#define CST4331_SPROM_PRESENT 0x00000002 -#define CST4331_OTP_PRESENT 0x00000004 -#define CST4331_LDO_RF 0x00000008 -#define CST4331_LDO_PAR 0x00000010 - -/* 4315 resource */ -#define RES4315_CBUCK_LPOM 1 /**< 0x00000002 */ -#define RES4315_CBUCK_BURST 2 /**< 0x00000004 */ -#define RES4315_CBUCK_PWM 3 /**< 0x00000008 */ -#define RES4315_CLDO_PU 4 /**< 0x00000010 */ -#define RES4315_PALDO_PU 5 /**< 0x00000020 */ -#define RES4315_ILP_REQUEST 6 /**< 0x00000040 */ -#define RES4315_LNLDO1_PU 9 /**< 0x00000200 */ -#define RES4315_OTP_PU 10 /**< 0x00000400 */ -#define RES4315_LNLDO2_PU 12 /**< 0x00001000 */ -#define RES4315_XTAL_PU 13 /**< 0x00002000 */ -#define RES4315_ALP_AVAIL 14 /**< 0x00004000 */ -#define RES4315_RX_PWRSW_PU 15 /**< 0x00008000 */ -#define RES4315_TX_PWRSW_PU 16 /**< 0x00010000 */ -#define RES4315_RFPLL_PWRSW_PU 17 /**< 0x00020000 */ -#define RES4315_LOGEN_PWRSW_PU 18 /**< 0x00040000 */ -#define RES4315_AFE_PWRSW_PU 19 /**< 0x00080000 */ -#define RES4315_BBPLL_PWRSW_PU 20 /**< 0x00100000 */ -#define RES4315_HT_AVAIL 21 /**< 0x00200000 */ - -/* 4315 chip-specific ChipStatus register bits */ -#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 /**< gpio [7:6], SDIO CIS selection */ -#define CST4315_DEFCIS_SEL 0x00000000 /**< use default CIS, OTP is powered up */ -#define CST4315_SPROM_SEL 0x00000001 /**< use SPROM, OTP is powered up */ -#define CST4315_OTP_SEL 0x00000002 /**< use OTP, OTP is powered up */ -#define CST4315_OTP_PWRDN 0x00000003 /**< use SPROM, OTP is powered down */ -#define CST4315_SDIO_MODE 0x00000004 /**< gpio [8], sdio/usb mode */ -#define CST4315_RCAL_VALID 0x00000008 -#define CST4315_RCAL_VALUE_MASK 0x000001f0 -#define CST4315_RCAL_VALUE_SHIFT 4 -#define CST4315_PALDO_EXTPNP 0x00000200 /**< PALDO is configured with external PNP */ -#define CST4315_CBUCK_MODE_MASK 0x00000c00 -#define CST4315_CBUCK_MODE_BURST 0x00000400 -#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 - -/* 4319 resources */ -#define RES4319_CBUCK_LPOM 1 /**< 0x00000002 */ -#define RES4319_CBUCK_BURST 2 /**< 0x00000004 */ -#define RES4319_CBUCK_PWM 3 /**< 0x00000008 */ -#define RES4319_CLDO_PU 4 /**< 0x00000010 */ -#define RES4319_PALDO_PU 5 /**< 0x00000020 */ -#define RES4319_ILP_REQUEST 6 /**< 0x00000040 */ -#define RES4319_LNLDO1_PU 9 /**< 0x00000200 */ -#define RES4319_OTP_PU 10 /**< 0x00000400 */ -#define RES4319_LNLDO2_PU 12 /**< 0x00001000 */ -#define RES4319_XTAL_PU 13 /**< 0x00002000 */ -#define RES4319_ALP_AVAIL 14 /**< 0x00004000 */ -#define RES4319_RX_PWRSW_PU 15 /**< 0x00008000 */ -#define RES4319_TX_PWRSW_PU 16 /**< 0x00010000 */ -#define RES4319_RFPLL_PWRSW_PU 17 /**< 0x00020000 */ -#define RES4319_LOGEN_PWRSW_PU 18 /**< 0x00040000 */ -#define RES4319_AFE_PWRSW_PU 19 /**< 0x00080000 */ -#define RES4319_BBPLL_PWRSW_PU 20 /**< 0x00100000 */ -#define RES4319_HT_AVAIL 21 /**< 0x00200000 */ - -/* 4319 chip-specific ChipStatus register bits */ -#define CST4319_SPI_CPULESSUSB 0x00000001 -#define CST4319_SPI_CLK_POL 0x00000002 -#define CST4319_SPI_CLK_PH 0x00000008 -#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 /**< gpio [7:6], SDIO CIS selection */ -#define CST4319_SPROM_OTP_SEL_SHIFT 6 -#define CST4319_DEFCIS_SEL 0x00000000 /**< use default CIS, OTP is powered up */ -#define CST4319_SPROM_SEL 0x00000040 /**< use SPROM, OTP is powered up */ -#define CST4319_OTP_SEL 0x00000080 /* use OTP, OTP is powered up */ -#define CST4319_OTP_PWRDN 0x000000c0 /* use SPROM, OTP is powered down */ -#define CST4319_SDIO_USB_MODE 0x00000100 /**< gpio [8], sdio/usb mode */ -#define CST4319_REMAP_SEL_MASK 0x00000600 -#define CST4319_ILPDIV_EN 0x00000800 -#define CST4319_XTAL_PD_POL 0x00001000 -#define CST4319_LPO_SEL 0x00002000 -#define CST4319_RES_INIT_MODE 0x0000c000 -#define CST4319_PALDO_EXTPNP 0x00010000 /**< PALDO is configured with external PNP */ -#define CST4319_CBUCK_MODE_MASK 0x00060000 -#define CST4319_CBUCK_MODE_BURST 0x00020000 -#define CST4319_CBUCK_MODE_LPBURST 0x00060000 -#define CST4319_RCAL_VALID 0x01000000 -#define CST4319_RCAL_VALUE_MASK 0x3e000000 -#define CST4319_RCAL_VALUE_SHIFT 25 - #define PMU1_PLL0_CHIPCTL0 0 #define PMU1_PLL0_CHIPCTL1 1 #define PMU1_PLL0_CHIPCTL2 2 -#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 -#define CCTL_4319USB_XTAL_SEL_SHIFT 19 -#define CCTL_4319USB_48MHZ_PLL_SEL 1 -#define CCTL_4319USB_24MHZ_PLL_SEL 2 - -/* PMU resources for 4336 */ -#define RES4336_CBUCK_LPOM 0 -#define RES4336_CBUCK_BURST 1 -#define RES4336_CBUCK_LP_PWM 2 -#define RES4336_CBUCK_PWM 3 -#define RES4336_CLDO_PU 4 -#define RES4336_DIS_INT_RESET_PD 5 -#define RES4336_ILP_REQUEST 6 -#define RES4336_LNLDO_PU 7 -#define RES4336_LDO3P3_PU 8 -#define RES4336_OTP_PU 9 -#define RES4336_XTAL_PU 10 -#define RES4336_ALP_AVAIL 11 -#define RES4336_RADIO_PU 12 -#define RES4336_BG_PU 13 -#define RES4336_VREG1p4_PU_PU 14 -#define RES4336_AFE_PWRSW_PU 15 -#define RES4336_RX_PWRSW_PU 16 -#define RES4336_TX_PWRSW_PU 17 -#define RES4336_BB_PWRSW_PU 18 -#define RES4336_SYNTH_PWRSW_PU 19 -#define RES4336_MISC_PWRSW_PU 20 -#define RES4336_LOGEN_PWRSW_PU 21 -#define RES4336_BBPLL_PWRSW_PU 22 -#define RES4336_MACPHY_CLKAVAIL 23 -#define RES4336_HT_AVAIL 24 -#define RES4336_RSVD 25 - -/* 4336 chip-specific ChipStatus register bits */ -#define CST4336_SPI_MODE_MASK 0x00000001 -#define CST4336_SPROM_PRESENT 0x00000002 -#define CST4336_OTP_PRESENT 0x00000004 -#define CST4336_ARMREMAP_0 0x00000008 -#define CST4336_ILPDIV_EN_MASK 0x00000010 -#define CST4336_ILPDIV_EN_SHIFT 4 -#define CST4336_XTAL_PD_POL_MASK 0x00000020 -#define CST4336_XTAL_PD_POL_SHIFT 5 -#define CST4336_LPO_SEL_MASK 0x00000040 -#define CST4336_LPO_SEL_SHIFT 6 -#define CST4336_RES_INIT_MODE_MASK 0x00000180 -#define CST4336_RES_INIT_MODE_SHIFT 7 -#define CST4336_CBUCK_MODE_MASK 0x00000600 -#define CST4336_CBUCK_MODE_SHIFT 9 - -/* 4336 Chip specific PMU ChipControl register bits */ -#define PCTL_4336_SERIAL_ENAB (1 << 24) - -/* 4330 resources */ -#define RES4330_CBUCK_LPOM 0 -#define RES4330_CBUCK_BURST 1 -#define RES4330_CBUCK_LP_PWM 2 -#define RES4330_CBUCK_PWM 3 -#define RES4330_CLDO_PU 4 -#define RES4330_DIS_INT_RESET_PD 5 -#define RES4330_ILP_REQUEST 6 -#define RES4330_LNLDO_PU 7 -#define RES4330_LDO3P3_PU 8 -#define RES4330_OTP_PU 9 -#define RES4330_XTAL_PU 10 -#define RES4330_ALP_AVAIL 11 -#define RES4330_RADIO_PU 12 -#define RES4330_BG_PU 13 -#define RES4330_VREG1p4_PU_PU 14 -#define RES4330_AFE_PWRSW_PU 15 -#define RES4330_RX_PWRSW_PU 16 -#define RES4330_TX_PWRSW_PU 17 -#define RES4330_BB_PWRSW_PU 18 -#define RES4330_SYNTH_PWRSW_PU 19 -#define RES4330_MISC_PWRSW_PU 20 -#define RES4330_LOGEN_PWRSW_PU 21 -#define RES4330_BBPLL_PWRSW_PU 22 -#define RES4330_MACPHY_CLKAVAIL 23 -#define RES4330_HT_AVAIL 24 -#define RES4330_5gRX_PWRSW_PU 25 -#define RES4330_5gTX_PWRSW_PU 26 -#define RES4330_5g_LOGEN_PWRSW_PU 27 - -/* 4330 chip-specific ChipStatus register bits */ -#define CST4330_CHIPMODE_SDIOD(cs) (((cs) & 0x7) < 6) /**< SDIO || gSPI */ -#define CST4330_CHIPMODE_USB20D(cs) (((cs) & 0x7) >= 6) /**< USB || USBDA */ -#define CST4330_CHIPMODE_SDIO(cs) (((cs) & 0x4) == 0) /**< SDIO */ -#define CST4330_CHIPMODE_GSPI(cs) (((cs) & 0x6) == 4) /**< gSPI */ -#define CST4330_CHIPMODE_USB(cs) (((cs) & 0x7) == 6) /**< USB packet-oriented */ -#define CST4330_CHIPMODE_USBDA(cs) (((cs) & 0x7) == 7) /**< USB Direct Access */ -#define CST4330_OTP_PRESENT 0x00000010 -#define CST4330_LPO_AUTODET_EN 0x00000020 -#define CST4330_ARMREMAP_0 0x00000040 -#define CST4330_SPROM_PRESENT 0x00000080 /**< takes priority over OTP if both set */ -#define CST4330_ILPDIV_EN 0x00000100 -#define CST4330_LPO_SEL 0x00000200 -#define CST4330_RES_INIT_MODE_SHIFT 10 -#define CST4330_RES_INIT_MODE_MASK 0x00000c00 -#define CST4330_CBUCK_MODE_SHIFT 12 -#define CST4330_CBUCK_MODE_MASK 0x00003000 -#define CST4330_CBUCK_POWER_OK 0x00004000 -#define CST4330_BB_PLL_LOCKED 0x00008000 + #define SOCDEVRAM_BP_ADDR 0x1E000000 #define SOCDEVRAM_ARM_ADDR 0x00800000 -/* 4330 Chip specific PMU ChipControl register bits */ -#define PCTL_4330_SERIAL_ENAB (1 << 24) - -/* 4330 Chip specific ChipControl register bits */ -#define CCTRL_4330_GPIO_SEL 0x00000001 /* 1=select GPIOs to be muxed out */ -#define CCTRL_4330_ERCX_SEL 0x00000002 /* 1=select ERCX BT coex to be muxed out */ -#define CCTRL_4330_SDIO_HOST_WAKE 0x00000004 /* SDIO: 1=configure GPIO0 for host wake */ -#define CCTRL_4330_JTAG_DISABLE 0x00000008 /* 1=disable JTAG interface on mux'd pins */ - -#define PMU_VREG0_ADDR 0 #define PMU_VREG0_I_SR_CNTL_EN_SHIFT 0 #define PMU_VREG0_DISABLE_PULLD_BT_SHIFT 2 #define PMU_VREG0_DISABLE_PULLD_WL_SHIFT 3 @@ -2550,233 +2264,8 @@ typedef volatile struct { #define PMU_VREG5_HSICDVDD_PD_SHIFT 11 #define PMU_VREG5_HSICDVDD_PD_MASK 0x1 -/* 4334 resources */ -#define RES4334_LPLDO_PU 0 -#define RES4334_RESET_PULLDN_DIS 1 -#define RES4334_PMU_BG_PU 2 -#define RES4334_HSIC_LDO_PU 3 -#define RES4334_CBUCK_LPOM_PU 4 -#define RES4334_CBUCK_PFM_PU 5 -#define RES4334_CLDO_PU 6 -#define RES4334_LPLDO2_LVM 7 -#define RES4334_LNLDO_PU 8 -#define RES4334_LDO3P3_PU 9 -#define RES4334_OTP_PU 10 -#define RES4334_XTAL_PU 11 -#define RES4334_WL_PWRSW_PU 12 -#define RES4334_LQ_AVAIL 13 -#define RES4334_LOGIC_RET 14 -#define RES4334_MEM_SLEEP 15 -#define RES4334_MACPHY_RET 16 -#define RES4334_WL_CORE_READY 17 -#define RES4334_ILP_REQ 18 -#define RES4334_ALP_AVAIL 19 -#define RES4334_MISC_PWRSW_PU 20 -#define RES4334_SYNTH_PWRSW_PU 21 -#define RES4334_RX_PWRSW_PU 22 -#define RES4334_RADIO_PU 23 -#define RES4334_WL_PMU_PU 24 -#define RES4334_VCO_LDO_PU 25 -#define RES4334_AFE_LDO_PU 26 -#define RES4334_RX_LDO_PU 27 -#define RES4334_TX_LDO_PU 28 -#define RES4334_HT_AVAIL 29 -#define RES4334_MACPHY_CLK_AVAIL 30 - -/* 4334 chip-specific ChipStatus register bits */ -#define CST4334_CHIPMODE_MASK 7 -#define CST4334_SDIO_MODE 0x00000000 -#define CST4334_SPI_MODE 0x00000004 -#define CST4334_HSIC_MODE 0x00000006 -#define CST4334_BLUSB_MODE 0x00000007 -#define CST4334_CHIPMODE_HSIC(cs) (((cs) & CST4334_CHIPMODE_MASK) == CST4334_HSIC_MODE) -#define CST4334_OTP_PRESENT 0x00000010 -#define CST4334_LPO_AUTODET_EN 0x00000020 -#define CST4334_ARMREMAP_0 0x00000040 -#define CST4334_SPROM_PRESENT 0x00000080 -#define CST4334_ILPDIV_EN_MASK 0x00000100 -#define CST4334_ILPDIV_EN_SHIFT 8 -#define CST4334_LPO_SEL_MASK 0x00000200 -#define CST4334_LPO_SEL_SHIFT 9 -#define CST4334_RES_INIT_MODE_MASK 0x00000C00 -#define CST4334_RES_INIT_MODE_SHIFT 10 - -/* 4334 Chip specific PMU ChipControl register bits */ -#define PCTL_4334_GPIO3_ENAB (1 << 3) - -/* 4334 Chip control */ -#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) - -/* 4334 Chip control 3 */ -#define CCTRL4334_BLOCK_EXTRNL_WAKE (1 << 4) -#define CCTRL4334_SAVERESTORE_FIX (1 << 5) - -/* 43341 Chip control 3 */ -#define CCTRL43341_BLOCK_EXTRNL_WAKE (1 << 13) -#define CCTRL43341_SAVERESTORE_FIX (1 << 14) -#define CCTRL43341_BT_ISO_SEL (1 << 16) - -/* 4334 Chip specific ChipControl1 register bits */ -#define CCTRL1_4334_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ -#define CCTRL1_4334_ERCX_SEL (1 << 1) /* 1=select ERCX BT coex to be muxed out */ -#define CCTRL1_4334_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ -#define CCTRL1_4334_JTAG_DISABLE (1 << 3) /* 1=disable JTAG interface on mux'd pins */ -#define CCTRL1_4334_UART_ON_4_5 (1 << 28) /**< 1=UART_TX/UART_RX muxed on GPIO_4/5 (4334B0/1) */ - -/* 4324 Chip specific ChipControl1 register bits */ -#define CCTRL1_4324_GPIO_SEL (1 << 0) /* 1=select GPIOs to be muxed out */ -#define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) /* SDIO: 1=configure GPIO0 for host wake */ - -/* 43143 chip-specific ChipStatus register bits based on Confluence documentation */ -/* register contains strap values sampled during POR */ -#define CST43143_REMAP_TO_ROM (3 << 0) /* 00=Boot SRAM, 01=Boot ROM, 10=Boot SFLASH */ -#define CST43143_SDIO_EN (1 << 2) /* 0 = USB Enab, SDIO pins are GPIO or I2S */ -#define CST43143_SDIO_ISO (1 << 3) /* 1 = SDIO isolated */ -#define CST43143_USB_CPU_LESS (1 << 4) /* 1 = CPULess mode Enabled */ -#define CST43143_CBUCK_MODE (3 << 6) /* Indicates what controller mode CBUCK is in */ -#define CST43143_POK_CBUCK (1 << 8) /* 1 = 1.2V CBUCK voltage ready */ -#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) /* SDIO */ - -/* 43143 Chip specific ChipControl register bits */ -/* 00: SECI is disabled (JATG functional), 01: 2 wire, 10: 4 wire */ -#define CCTRL_43143_SECI (1<<0) -#define CCTRL_43143_BT_LEGACY (1<<1) -#define CCTRL_43143_I2S_MODE (1<<2) /**< 0: SDIO enabled */ -#define CCTRL_43143_I2S_MASTER (1<<3) /**< 0: I2S MCLK input disabled */ -#define CCTRL_43143_I2S_FULL (1<<4) /**< 0: I2S SDIN and SPDIF_TX inputs disabled */ -#define CCTRL_43143_GSIO (1<<5) /**< 0: sFlash enabled */ -#define CCTRL_43143_RF_SWCTRL_MASK (7<<6) /**< 0: disabled */ -#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) /**< 0: UART enabled */ -#define CCTRL_43143_HOST_WAKE0 (1<<11) /**< 1: SDIO separate interrupt output from GPIO4 */ -#define CCTRL_43143_HOST_WAKE1 (1<<12) /* 1: SDIO separate interrupt output from GPIO16 */ - -/* 43143 resources, based on pmu_params.xls V1.19 */ -#define RES43143_EXT_SWITCHER_PWM 0 /**< 0x00001 */ -#define RES43143_XTAL_PU 1 /**< 0x00002 */ -#define RES43143_ILP_REQUEST 2 /**< 0x00004 */ -#define RES43143_ALP_AVAIL 3 /**< 0x00008 */ -#define RES43143_WL_CORE_READY 4 /**< 0x00010 */ -#define RES43143_BBPLL_PWRSW_PU 5 /**< 0x00020 */ -#define RES43143_HT_AVAIL 6 /**< 0x00040 */ -#define RES43143_RADIO_PU 7 /**< 0x00080 */ -#define RES43143_MACPHY_CLK_AVAIL 8 /**< 0x00100 */ -#define RES43143_OTP_PU 9 /**< 0x00200 */ -#define RES43143_LQ_AVAIL 10 /**< 0x00400 */ - -#define PMU43143_XTAL_CORE_SIZE_MASK 0x3F - -/* 4313 resources */ -#define RES4313_BB_PU_RSRC 0 -#define RES4313_ILP_REQ_RSRC 1 -#define RES4313_XTAL_PU_RSRC 2 -#define RES4313_ALP_AVAIL_RSRC 3 -#define RES4313_RADIO_PU_RSRC 4 -#define RES4313_BG_PU_RSRC 5 -#define RES4313_VREG1P4_PU_RSRC 6 -#define RES4313_AFE_PWRSW_RSRC 7 -#define RES4313_RX_PWRSW_RSRC 8 -#define RES4313_TX_PWRSW_RSRC 9 -#define RES4313_BB_PWRSW_RSRC 10 -#define RES4313_SYNTH_PWRSW_RSRC 11 -#define RES4313_MISC_PWRSW_RSRC 12 -#define RES4313_BB_PLL_PWRSW_RSRC 13 -#define RES4313_HT_AVAIL_RSRC 14 -#define RES4313_MACPHY_CLK_AVAIL_RSRC 15 - -/* 4313 chip-specific ChipStatus register bits */ -#define CST4313_SPROM_PRESENT 1 -#define CST4313_OTP_PRESENT 2 -#define CST4313_SPROM_OTP_SEL_MASK 0x00000002 -#define CST4313_SPROM_OTP_SEL_SHIFT 0 - -/* 4313 Chip specific ChipControl register bits */ -#define CCTRL_4313_12MA_LED_DRIVE 0x00000007 /* 12 mA drive strengh for later 4313 */ - -/* PMU respources for 4314 */ -#define RES4314_LPLDO_PU 0 -#define RES4314_PMU_SLEEP_DIS 1 -#define RES4314_PMU_BG_PU 2 -#define RES4314_CBUCK_LPOM_PU 3 -#define RES4314_CBUCK_PFM_PU 4 -#define RES4314_CLDO_PU 5 -#define RES4314_LPLDO2_LVM 6 -#define RES4314_WL_PMU_PU 7 -#define RES4314_LNLDO_PU 8 -#define RES4314_LDO3P3_PU 9 -#define RES4314_OTP_PU 10 -#define RES4314_XTAL_PU 11 -#define RES4314_WL_PWRSW_PU 12 -#define RES4314_LQ_AVAIL 13 -#define RES4314_LOGIC_RET 14 -#define RES4314_MEM_SLEEP 15 -#define RES4314_MACPHY_RET 16 -#define RES4314_WL_CORE_READY 17 -#define RES4314_ILP_REQ 18 -#define RES4314_ALP_AVAIL 19 -#define RES4314_MISC_PWRSW_PU 20 -#define RES4314_SYNTH_PWRSW_PU 21 -#define RES4314_RX_PWRSW_PU 22 -#define RES4314_RADIO_PU 23 -#define RES4314_VCO_LDO_PU 24 -#define RES4314_AFE_LDO_PU 25 -#define RES4314_RX_LDO_PU 26 -#define RES4314_TX_LDO_PU 27 -#define RES4314_HT_AVAIL 28 -#define RES4314_MACPHY_CLK_AVAIL 29 - -/* 4314 chip-specific ChipStatus register bits */ -#define CST4314_OTP_ENABLED 0x00200000 - -/* 43228 resources */ -#define RES43228_NOT_USED 0 -#define RES43228_ILP_REQUEST 1 -#define RES43228_XTAL_PU 2 -#define RES43228_ALP_AVAIL 3 -#define RES43228_PLL_EN 4 -#define RES43228_HT_PHY_AVAIL 5 - /* 43228 chipstatus reg bits */ -#define CST43228_ILP_DIV_EN 0x1 #define CST43228_OTP_PRESENT 0x2 -#define CST43228_SERDES_REFCLK_PADSEL 0x4 -#define CST43228_SDIO_MODE 0x8 -#define CST43228_SDIO_OTP_PRESENT 0x10 -#define CST43228_SDIO_RESET 0x20 - -/* 4706 chipstatus reg bits */ -#define CST4706_PKG_OPTION (1<<0) /* 0: full-featured package 1: low-cost package */ -#define CST4706_SFLASH_PRESENT (1<<1) /* 0: parallel, 1: serial flash is present */ -#define CST4706_SFLASH_TYPE (1<<2) /* 0: 8b-p/ST-s flash, 1: 16b-p/Atmal-s flash */ -#define CST4706_MIPS_BENDIAN (1<<3) /* 0: little, 1: big endian */ -#define CST4706_PCIE1_DISABLE (1<<5) /* PCIE1 enable strap pin */ - -/* 4706 flashstrconfig reg bits */ -#define FLSTRCF4706_MASK 0x000000ff -#define FLSTRCF4706_SF1 0x00000001 /**< 2nd serial flash present */ -#define FLSTRCF4706_PF1 0x00000002 /**< 2nd parallel flash present */ -#define FLSTRCF4706_SF1_TYPE 0x00000004 /**< 2nd serial flash type : 0 : ST, 1 : Atmel */ -#define FLSTRCF4706_NF1 0x00000008 /**< 2nd NAND flash present */ -#define FLSTRCF4706_1ST_MADDR_SEG_MASK 0x000000f0 /**< Valid value mask */ -#define FLSTRCF4706_1ST_MADDR_SEG_4MB 0x00000010 /**< 4MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_8MB 0x00000020 /**< 8MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_16MB 0x00000030 /**< 16MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_32MB 0x00000040 /**< 32MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_64MB 0x00000050 /**< 64MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_128MB 0x00000060 /**< 128MB */ -#define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 /**< 256MB */ /* 4360 Chip specific ChipControl register bits */ #define CCTRL4360_I2C_MODE (1 << 0) @@ -2824,15 +2313,15 @@ typedef volatile struct { #define CST4360_AVBBPLL_LOCK 0x00001000 #define CST4360_USBBBPLL_LOCK 0x00002000 #define CST4360_RSRC_INIT_MODE(cs) ((cs & CST4360_RSRC_INIT_MODE_MASK) >> \ - CST4360_RSRC_INIT_MODE_SHIFT) + CST4360_RSRC_INIT_MODE_SHIFT) + +#define CCTRL_4360_UART_SEL 0x2 -#define CCTRL_4360_UART_SEL 0x2 #define CST4360_RSRC_INIT_MODE(cs) ((cs & CST4360_RSRC_INIT_MODE_MASK) >> \ - CST4360_RSRC_INIT_MODE_SHIFT) + CST4360_RSRC_INIT_MODE_SHIFT) #define PMU4360_CC1_GPIO7_OVRD (1<<23) /* GPIO7 override */ - /* 43602 PMU resources based on pmu_params.xls version v0.95 */ #define RES43602_LPLDO_PU 0 #define RES43602_REGULATOR 1 @@ -2902,6 +2391,35 @@ typedef volatile struct { #define RES4365_RADIO_PU 12 #define RES4365_MACPHY_CLK_AVAIL 13 +/* 43684 PMU resources */ +#define RES43684_REGULATOR_PU 0 +#define RES43684_PCIE_LDO_BG_PU 1 +#define RES43684_XTAL_LDO_PU 2 +#define RES43684_XTAL_PU 3 +#define RES43684_CPU_PLL_LDO_PU 4 +#define RES43684_CPU_PLL_PU 5 +#define RES43684_WL_CORE_RDY 6 +#define RES43684_ILP_REQ 7 +#define RES43684_ALP_AVAIL 8 +#define RES43684_HT_AVAIL 9 +#define RES43684_BB_PLL_LDO_PU 10 +#define RES43684_BB_PLL_PU 11 +#define RES43684_MINI_PMU_PU 12 +#define RES43684_RADIO_PU 13 +#define RES43684_MACPHY_CLK_AVAIL 14 +#define RES43684_PCIE_LDO_PU 15 + +/* 7271 PMU resources */ +#define RES7271_REGULATOR_PU 0 +#define RES7271_WL_CORE_RDY 1 +#define RES7271_ILP_REQ 2 +#define RES7271_ALP_AVAIL 3 +#define RES7271_HT_AVAIL 4 +#define RES7271_BB_PLL_PU 5 +#define RES7271_MINIPMU_PU 6 +#define RES7271_RADIO_PU 7 +#define RES7271_MACPHY_CLK_AVAIL 8 + /* 4349 related */ #define RES4349_LPLDO_PU 0 #define RES4349_BG_PU 1 @@ -2935,8 +2453,40 @@ typedef volatile struct { #define RES4349_HT_AVAIL 29 #define RES4349_MACPHY_CLKAVAIL 30 +/* 4373 PMU resources */ +#define RES4373_LPLDO_PU 0 +#define RES4373_BG_PU 1 +#define RES4373_PMU_SLEEP 2 +#define RES4373_PALDO3P3_PU 3 +#define RES4373_CBUCK_LPOM_PU 4 +#define RES4373_CBUCK_PFM_PU 5 +#define RES4373_COLD_START_WAIT 6 +#define RES4373_RSVD_7 7 +#define RES4373_LNLDO_PU 8 +#define RES4373_XTALLDO_PU 9 +#define RES4373_LDO3P3_PU 10 +#define RES4373_OTP_PU 11 +#define RES4373_XTAL_PU 12 +#define RES4373_SR_CLK_START 13 +#define RES4373_LQ_AVAIL 14 +#define RES4373_LQ_START 15 +#define RES4373_PERST_OVR 16 +#define RES4373_WL_CORE_RDY 17 +#define RES4373_ILP_REQ 18 +#define RES4373_ALP_AVAIL 19 +#define RES4373_MINI_PMU 20 +#define RES4373_RADIO_PU 21 +#define RES4373_SR_CLK_STABLE 22 +#define RES4373_SR_SAVE_RESTORE 23 +#define RES4373_SR_PHY_PWRSW 24 +#define RES4373_SR_VDDM_PWRSW 25 +#define RES4373_SR_SUBCORE_PWRSW 26 +#define RES4373_SR_SLEEP 27 +#define RES4373_HT_START 28 +#define RES4373_HT_AVAIL 29 +#define RES4373_MACPHY_CLKAVAIL 30 /* SR Control0 bits */ -#define CC_SR0_4349_SR_ENG_EN_MASK 0x1 +#define CC_SR0_4349_SR_ENG_EN_MASK 0x1 #define CC_SR0_4349_SR_ENG_EN_SHIFT 0 #define CC_SR0_4349_SR_ENG_CLK_EN (1 << 1) #define CC_SR0_4349_SR_RSRC_TRIGGER (0xC << 2) @@ -2948,9 +2498,8 @@ typedef volatile struct { #define CC_SR0_4349_SR_ENABLE_HT (1 << 19) #define CC_SR0_4349_SR_ALLOW_PIC (3 << 20) #define CC_SR0_4349_SR_PMU_MEM_DISABLE (1 << 30) - /* SR Control0 bits */ -#define CC_SR0_4349_SR_ENG_EN_MASK 0x1 +#define CC_SR0_4349_SR_ENG_EN_MASK 0x1 #define CC_SR0_4349_SR_ENG_EN_SHIFT 0 #define CC_SR0_4349_SR_ENG_CLK_EN (1 << 1) #define CC_SR0_4349_SR_RSRC_TRIGGER (0xC << 2) @@ -2964,12 +2513,16 @@ typedef volatile struct { /* SR binary offset is at 8K */ #define CC_SR1_4349_SR_ASM_ADDR (0x10) - #define CST4349_CHIPMODE_SDIOD(cs) (((cs) & (1 << 6)) != 0) /* SDIO */ #define CST4349_CHIPMODE_PCIE(cs) (((cs) & (1 << 7)) != 0) /* PCIE */ - #define CST4349_SPROM_PRESENT 0x00000010 +/* 4373 related */ +#define CST4373_CHIPMODE_USB20D(cs) (((cs) & (1 << 8)) != 0) /* USB */ +#define CST4373_CHIPMODE_SDIOD(cs) (((cs) & (1 << 7)) != 0) /* SDIO */ +#define CST4373_CHIPMODE_PCIE(cs) (((cs) & (1 << 6)) != 0) /* PCIE */ +#define CST4373_SFLASH_PRESENT 0x00000010 + #define VREG4_4349_MEMLPLDO_PWRUP_MASK (1 << 31) #define VREG4_4349_MEMLPLDO_PWRUP_SHIFT (31) #define VREG4_4349_LPLDO1_OUTPUT_VOLT_ADJ_MASK (0x7 << 15) @@ -2998,7 +2551,6 @@ typedef volatile struct { #define CC6_4349_PMU_EN_MDIO_MASK (1 << 16) #define CC6_4349_PMU_EN_ASSERT_L2_MASK (1 << 25) - /* 4349 GCI function sel values */ /* * Reference @@ -3098,6 +2650,7 @@ typedef volatile struct { #define CC_SR0_4364_SR_ENABLE_ILP (1 << 17) #define CC_SR0_4364_SR_ENABLE_ALP (1 << 18) #define CC_SR0_4364_SR_ENABLE_HT (1 << 19) +#define CC_SR0_4364_SR_INVERT_CLK (1 << 11) #define CC_SR0_4364_SR_ALLOW_PIC (3 << 20) #define CC_SR0_4364_SR_PMU_MEM_DISABLE (1 << 30) @@ -3119,7 +2672,6 @@ typedef volatile struct { #define PMU_4364_CC3_MEMLPLDO3x3_PWRSW_FORCE_OFF (0) #define PMU_4364_CC3_MEMLPLDO1x1_PWRSW_FORCE_OFF (0) - #define PMU_4364_CC5_DISABLE_BBPLL_CLKOUT6_DIV2_MASK (1 << 26) #define PMU_4364_CC5_ENABLE_ARMCR4_DEBUG_CLK_MASK (1 << 4) #define PMU_4364_CC5_DISABLE_BBPLL_CLKOUT6_DIV2 (1 << 26) @@ -3140,13 +2692,74 @@ typedef volatile struct { #define PMU_4364_VREG0_DISABLE_BT_PULL_DOWN (1 << 2) #define PMU_4364_VREG1_DISABLE_WL_PULL_DOWN (1 << 2) -#define PMU_VREG_0 (0x0) -#define PMU_VREG_1 (0x1) -#define PMU_VREG_3 (0x3) -#define PMU_VREG_4 (0x4) -#define PMU_VREG_5 (0x5) -#define PMU_VREG_6 (0x6) - +/* Indices of PMU voltage regulator registers */ +#define PMU_VREG_0 (0u) +#define PMU_VREG_1 (1u) +#define PMU_VREG_2 (2u) +#define PMU_VREG_3 (3u) +#define PMU_VREG_4 (4u) +#define PMU_VREG_5 (5u) +#define PMU_VREG_6 (6u) +#define PMU_VREG_7 (7u) +#define PMU_VREG_8 (8u) +#define PMU_VREG_9 (9u) +#define PMU_VREG_10 (10u) +#define PMU_VREG_11 (11u) +#define PMU_VREG_12 (12u) +#define PMU_VREG_13 (13u) +#define PMU_VREG_14 (14u) +#define PMU_VREG_15 (15u) +#define PMU_VREG_16 (16u) + +/* 43012 Chipcommon ChipStatus bits */ +#define CST43012_FLL_LOCK (1 << 13) +/* 43012 resources - End */ + +/* 43012 related Cbuck modes */ +#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE0 0x00001c03 +#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE0 0x00492490 +#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE1 0x00001c03 +#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE1 0x00490410 + +/* 43012 related dynamic cbuck mode mask */ +#define PMU_43012_VREG8_DYNAMIC_CBUCK_MODE_MASK 0xFFFFFC07 +#define PMU_43012_VREG9_DYNAMIC_CBUCK_MODE_MASK 0xFFFFFFFF + +/* 4369 related VREG masks */ +#define PMU_4369_VREG_5_MISCLDO_POWER_UP_MASK (1u << 11u) +#define PMU_4369_VREG_5_MISCLDO_POWER_UP_SHIFT 11u +#define PMU_4369_VREG_5_LPLDO_POWER_UP_MASK (1u << 27u) +#define PMU_4369_VREG_5_LPLDO_POWER_UP_SHIFT 27u +#define PMU_4369_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_MASK BCM_MASK32(31, 28) +#define PMU_4369_VREG_5_MEMLPLDO_OP_VLT_ADJ_CTRL_SHIFT 28u + +#define PMU_4369_VREG_6_MEMLPLDO_POWER_UP_MASK (1u << 3u) +#define PMU_4369_VREG_6_MEMLPLDO_POWER_UP_SHIFT 3u + +#define PMU_4369_VREG_7_PMU_FORCE_HP_MODE_MASK (1u << 27u) +#define PMU_4369_VREG_7_PMU_FORCE_HP_MODE_SHIFT 27u +#define PMU_4369_VREG_7_WL_PMU_LP_MODE_MASK (1u << 28u) +#define PMU_4369_VREG_7_WL_PMU_LP_MODE_SHIFT 28u +#define PMU_4369_VREG_7_WL_PMU_LV_MODE_MASK (1u << 29u) +#define PMU_4369_VREG_7_WL_PMU_LV_MODE_SHIFT 29u + +#define PMU_4369_VREG8_ASR_OVADJ_LPPFM_MASK BCM_MASK32(4, 0) +#define PMU_4369_VREG8_ASR_OVADJ_LPPFM_SHIFT 0u + +#define PMU_4369_VREG13_RSRC_EN_ASR_MASK4_MASK BCM_MASK32(10, 9) +#define PMU_4369_VREG13_RSRC_EN_ASR_MASK4_SHIFT 9u + +#define PMU_4369_VREG14_RSRC_EN_CSR_MASK0_MASK (1u << 23u) +#define PMU_4369_VREG14_RSRC_EN_CSR_MASK0_SHIFT 23u + +#define PMU_4369_VREG16_RSRC0_CBUCK_MODE_MASK BCM_MASK32(2, 0) +#define PMU_4369_VREG16_RSRC0_CBUCK_MODE_SHIFT 0u +#define PMU_4369_VREG16_RSRC0_ABUCK_MODE_MASK BCM_MASK32(17, 15) +#define PMU_4369_VREG16_RSRC0_ABUCK_MODE_SHIFT 15u +#define PMU_4369_VREG16_RSRC1_ABUCK_MODE_MASK BCM_MASK32(20, 18) +#define PMU_4369_VREG16_RSRC1_ABUCK_MODE_SHIFT 18u + +/* 4364 related VREG masks */ #define PMU_4364_VREG3_DISABLE_WPT_REG_ON_PULL_DOWN (1 << 11) #define PMU_4364_VREG4_MEMLPLDO_PU_ON (1 << 31) @@ -3187,6 +2800,19 @@ typedef volatile struct { #define PMU_4364_MACCORE_0_RES_REQ_MASK 0x3FCBF7FF #define PMU_4364_MACCORE_1_RES_REQ_MASK 0x7FFB3647 +#define PMU_4364_RSDB_MODE (0) +#define PMU_4364_1x1_MODE (1) +#define PMU_4364_3x3_MODE (2) + +#define PMU_4364_MAX_MASK_1x1 (0x7FFF3E47) +#define PMU_4364_MAX_MASK_RSDB (0x7FFFFFFF) +#define PMU_4364_MAX_MASK_3x3 (0x3FCFFFFF) + +#define PMU_4364_SAVE_RESTORE_UPDNTIME_1x1 (0xC000C) +#define PMU_4364_SAVE_RESTORE_UPDNTIME_3x3 (0xF000F) + +#define FORCE_CLK_ON 1 +#define FORCE_CLK_OFF 0 #define PMU1_PLL0_SWITCH_MACCLOCK_120MHZ (0) #define PMU1_PLL0_SWITCH_MACCLOCK_160MHZ (1) @@ -3197,10 +2823,346 @@ typedef volatile struct { #define PMU1_PLL0_PC1_M2DIV_VALUE_120MHZ 8 #define PMU1_PLL0_PC1_M2DIV_VALUE_160MHZ 6 +/* 4347/4369 Related */ + +/* + * PMU VREG Definitions: + * http://confluence.broadcom.com/display/WLAN/BCM4347+PMU+Vreg+Control+Register + * http://confluence.broadcom.com/display/WLAN/BCM4369+PMU+Vreg+Control+Register + */ +/* PMU VREG4 */ +#define PMU_28NM_VREG4_WL_LDO_CNTL_EN (0x1 << 10) + +/* PMU VREG6 */ +#define PMU_28NM_VREG6_BTLDO3P3_PU (0x1 << 12) + +/* PMU resources */ +#define RES4347_MEMLPLDO_PU 0 +#define RES4347_AAON 1 +#define RES4347_PMU_SLEEP 2 +#define RES4347_RESERVED_3 3 +#define RES4347_LDO3P3_PU 4 +#define RES4347_FAST_LPO_AVAIL 5 +#define RES4347_XTAL_PU 6 +#define RES4347_XTAL_STABLE 7 +#define RES4347_PWRSW_DIG 8 +#define RES4347_SR_DIG 9 +#define RES4347_SLEEP_DIG 10 +#define RES4347_PWRSW_AUX 11 +#define RES4347_SR_AUX 12 +#define RES4347_SLEEP_AUX 13 +#define RES4347_PWRSW_MAIN 14 +#define RES4347_SR_MAIN 15 +#define RES4347_SLEEP_MAIN 16 +#define RES4347_CORE_RDY_DIG 17 +#define RES4347_CORE_RDY_AUX 18 +#define RES4347_ALP_AVAIL 19 +#define RES4347_RADIO_AUX_PU 20 +#define RES4347_MINIPMU_AUX_PU 21 +#define RES4347_CORE_RDY_MAIN 22 +#define RES4347_RADIO_MAIN_PU 23 +#define RES4347_MINIPMU_MAIN_PU 24 +#define RES4347_PCIE_EP_PU 25 +#define RES4347_COLD_START_WAIT 26 +#define RES4347_ARMHTAVAIL 27 +#define RES4347_HT_AVAIL 28 +#define RES4347_MACPHY_AUX_CLK_AVAIL 29 +#define RES4347_MACPHY_MAIN_CLK_AVAIL 30 +#define RES4347_RESERVED_31 31 + +/* 4369 PMU Resources */ +#define RES4369_DUMMY 0 +#define RES4369_ABUCK 1 +#define RES4369_PMU_SLEEP 2 +#define RES4369_MISCLDO 3 +#define RES4369_LDO3P3 4 +#define RES4369_FAST_LPO_AVAIL 5 +#define RES4369_XTAL_PU 6 +#define RES4369_XTAL_STABLE 7 +#define RES4369_PWRSW_DIG 8 +#define RES4369_SR_DIG 9 +#define RES4369_SLEEP_DIG 10 +#define RES4369_PWRSW_AUX 11 +#define RES4369_SR_AUX 12 +#define RES4369_SLEEP_AUX 13 +#define RES4369_PWRSW_MAIN 14 +#define RES4369_SR_MAIN 15 +#define RES4369_SLEEP_MAIN 16 +#define RES4369_DIG_CORE_RDY 17 +#define RES4369_CORE_RDY_AUX 18 +#define RES4369_ALP_AVAIL 19 +#define RES4369_RADIO_AUX_PU 20 +#define RES4369_MINIPMU_AUX_PU 21 +#define RES4369_CORE_RDY_MAIN 22 +#define RES4369_RADIO_MAIN_PU 23 +#define RES4369_MINIPMU_MAIN_PU 24 +#define RES4369_PCIE_EP_PU 25 +#define RES4369_COLD_START_WAIT 26 +#define RES4369_ARMHTAVAIL 27 +#define RES4369_HT_AVAIL 28 +#define RES4369_MACPHY_AUX_CLK_AVAIL 29 +#define RES4369_MACPHY_MAIN_CLK_AVAIL 30 + +/* chip status */ #define CST4347_CHIPMODE_SDIOD(cs) (((cs) & (1 << 6)) != 0) /* SDIO */ #define CST4347_CHIPMODE_PCIE(cs) (((cs) & (1 << 7)) != 0) /* PCIE */ +#define CST4347_JTAG_STRAP_ENABLED(cs) (((cs) & (1 << 20)) != 0) /* JTAG strap st */ #define CST4347_SPROM_PRESENT 0x00000010 +/* GCI chip status */ +#define GCI_CS_4347_FLL1MHZ_LOCK_MASK (1 << 1) + +/* GCI chip control registers */ +#define GCI_CC7_AAON_BYPASS_PWRSW_SEL 13 +#define GCI_CC7_AAON_BYPASS_PWRSW_SEQ_ON 14 + +/* PMU chip control registers */ +#define CC2_4347_VASIP_MEMLPLDO_VDDB_OFF_MASK (1 << 11) +#define CC2_4347_VASIP_MEMLPLDO_VDDB_OFF_SHIFT 11 +#define CC2_4347_MAIN_MEMLPLDO_VDDB_OFF_MASK (1 << 12) +#define CC2_4347_MAIN_MEMLPLDO_VDDB_OFF_SHIFT 12 +#define CC2_4347_AUX_MEMLPLDO_VDDB_OFF_MASK (1 << 13) +#define CC2_4347_AUX_MEMLPLDO_VDDB_OFF_SHIFT 13 +#define CC2_4347_VASIP_VDDRET_ON_MASK (1 << 14) +#define CC2_4347_VASIP_VDDRET_ON_SHIFT 14 +#define CC2_4347_MAIN_VDDRET_ON_MASK (1 << 15) +#define CC2_4347_MAIN_VDDRET_ON_SHIFT 15 +#define CC2_4347_AUX_VDDRET_ON_MASK (1 << 16) +#define CC2_4347_AUX_VDDRET_ON_SHIFT 16 +#define CC2_4347_GCI2WAKE_MASK (1 << 31) +#define CC2_4347_GCI2WAKE_SHIFT 31 + +#define CC2_4347_SDIO_AOS_WAKEUP_MASK (1 << 24) +#define CC2_4347_SDIO_AOS_WAKEUP_SHIFT 24 + +#define CC4_4347_LHL_TIMER_SELECT (1 << 0) + +#define CC6_4347_PWROK_WDT_EN_IN_MASK (1 << 6) +#define CC6_4347_PWROK_WDT_EN_IN_SHIFT 6 + +#define CC6_4347_SDIO_AOS_CHIP_WAKEUP_MASK (1 << 24) +#define CC6_4347_SDIO_AOS_CHIP_WAKEUP_SHIFT 24 + +#define PCIE_GPIO1_GPIO_PIN CC_GCI_GPIO_0 +#define PCIE_PERST_GPIO_PIN CC_GCI_GPIO_1 +#define PCIE_CLKREQ_GPIO_PIN CC_GCI_GPIO_2 + +#define VREG5_4347_MEMLPLDO_ADJ_MASK 0xF0000000 +#define VREG5_4347_MEMLPLDO_ADJ_SHIFT 28 +#define VREG5_4347_LPLDO_ADJ_MASK 0x00F00000 +#define VREG5_4347_LPLDO_ADJ_SHIFT 20 + +/* lpldo/memlpldo voltage */ +#define PMU_VREG5_LPLDO_VOLT_0_88 0xf /* 0.88v */ +#define PMU_VREG5_LPLDO_VOLT_0_86 0xe /* 0.86v */ +#define PMU_VREG5_LPLDO_VOLT_0_84 0xd /* 0.84v */ +#define PMU_VREG5_LPLDO_VOLT_0_82 0xc /* 0.82v */ +#define PMU_VREG5_LPLDO_VOLT_0_80 0xb /* 0.80v */ +#define PMU_VREG5_LPLDO_VOLT_0_78 0xa /* 0.78v */ +#define PMU_VREG5_LPLDO_VOLT_0_76 0x9 /* 0.76v */ +#define PMU_VREG5_LPLDO_VOLT_0_74 0x8 /* 0.74v */ +#define PMU_VREG5_LPLDO_VOLT_0_72 0x7 /* 0.72v */ +#define PMU_VREG5_LPLDO_VOLT_1_10 0x6 /* 1.10v */ +#define PMU_VREG5_LPLDO_VOLT_1_00 0x5 /* 1.00v */ +#define PMU_VREG5_LPLDO_VOLT_0_98 0x4 /* 0.98v */ +#define PMU_VREG5_LPLDO_VOLT_0_96 0x3 /* 0.96v */ +#define PMU_VREG5_LPLDO_VOLT_0_94 0x2 /* 0.94v */ +#define PMU_VREG5_LPLDO_VOLT_0_92 0x1 /* 0.92v */ +#define PMU_VREG5_LPLDO_VOLT_0_90 0x0 /* 0.90v */ + +/* Save/Restore engine */ + +#define BM_ADDR_TO_SR_ADDR(bmaddr) ((bmaddr) >> 9) + +/* Txfifo is 512KB for main core and 128KB for aux core + * We use first 12kB (0x3000) in BMC buffer for template in main core and + * 6.5kB (0x1A00) in aux core, followed by ASM code + */ +#define SR_ASM_ADDR_MAIN_4347 (0x18) +#define SR_ASM_ADDR_AUX_4347 (0xd) +#define SR_ASM_ADDR_DIG_4347 (0x0) + +#define SR_ASM_ADDR_MAIN_4369 BM_ADDR_TO_SR_ADDR(0xC00) +#define SR_ASM_ADDR_AUX_4369 BM_ADDR_TO_SR_ADDR(0xC00) +#define SR_ASM_ADDR_DIG_4369 (0x0) + +/* 512 bytes block */ +#define SR_ASM_ADDR_BLK_SIZE_SHIFT 9 + +/* SR Control0 bits */ +#define SR0_SR_ENG_EN_MASK 0x1 +#define SR0_SR_ENG_EN_SHIFT 0 +#define SR0_SR_ENG_CLK_EN (1 << 1) +#define SR0_RSRC_TRIGGER (0xC << 2) +#define SR0_WD_MEM_MIN_DIV (0x3 << 6) +#define SR0_INVERT_SR_CLK (1 << 11) +#define SR0_MEM_STBY_ALLOW (1 << 16) +#define SR0_ENABLE_SR_ILP (1 << 17) +#define SR0_ENABLE_SR_ALP (1 << 18) +#define SR0_ENABLE_SR_HT (1 << 19) +#define SR0_ALLOW_PIC (3 << 20) +#define SR0_ENB_PMU_MEM_DISABLE (1 << 30) + +/* SR Control0 bits for 4369 */ +#define SR0_4369_SR_ENG_EN_MASK 0x1 +#define SR0_4369_SR_ENG_EN_SHIFT 0 +#define SR0_4369_SR_ENG_CLK_EN (1 << 1) +#define SR0_4369_RSRC_TRIGGER (0xC << 2) +#define SR0_4369_WD_MEM_MIN_DIV (0x2 << 6) +#define SR0_4369_INVERT_SR_CLK (1 << 11) +#define SR0_4369_MEM_STBY_ALLOW (1 << 16) +#define SR0_4369_ENABLE_SR_ILP (1 << 17) +#define SR0_4369_ENABLE_SR_ALP (1 << 18) +#define SR0_4369_ENABLE_SR_HT (1 << 19) +#define SR0_4369_ALLOW_PIC (3 << 20) +#define SR0_4369_ENB_PMU_MEM_DISABLE (1 << 30) +/* =========== LHL regs =========== */ +/* 4369 LHL register settings */ +#define LHL4369_UP_CNT 0 +#define LHL4369_DN_CNT 2 +#define LHL4369_PWRSW_EN_DWN_CNT (LHL4369_DN_CNT + 2) +#define LHL4369_ISO_EN_DWN_CNT (LHL4369_PWRSW_EN_DWN_CNT + 3) +#define LHL4369_SLB_EN_DWN_CNT (LHL4369_ISO_EN_DWN_CNT + 1) +#define LHL4369_ASR_CLK4M_DIS_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_LPPFM_MODE_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_MODE_SEL_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_MANUAL_MODE_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_ADJ_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_OVERI_DIS_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_ASR_TRIM_ADJ_DWN_CNT (LHL4369_DN_CNT) +#define LHL4369_VDDC_SW_DIS_DWN_CNT (LHL4369_SLB_EN_DWN_CNT + 1) +#define LHL4369_VMUX_ASR_SEL_DWN_CNT (LHL4369_VDDC_SW_DIS_DWN_CNT + 1) +#define LHL4369_CSR_ADJ_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_CSR_MODE_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_CSR_OVERI_DIS_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_HPBG_CHOP_DIS_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_SRBG_REF_SEL_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_PFM_PWR_SLICE_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_CSR_TRIM_ADJ_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_CSR_VOLTAGE_DWN_CNT (LHL4369_VMUX_ASR_SEL_DWN_CNT + 1) +#define LHL4369_HPBG_PU_EN_DWN_CNT (LHL4369_CSR_MODE_DWN_CNT + 1) + +#define LHL4369_HPBG_PU_EN_UP_CNT (LHL4369_UP_CNT + 1) +#define LHL4369_CSR_ADJ_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_CSR_MODE_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_CSR_OVERI_DIS_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_HPBG_CHOP_DIS_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_SRBG_REF_SEL_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_PFM_PWR_SLICE_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_CSR_TRIM_ADJ_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_CSR_VOLTAGE_UP_CNT (LHL4369_HPBG_PU_EN_UP_CNT + 1) +#define LHL4369_VMUX_ASR_SEL_UP_CNT (LHL4369_CSR_MODE_UP_CNT + 1) +#define LHL4369_VDDC_SW_DIS_UP_CNT (LHL4369_VMUX_ASR_SEL_UP_CNT + 1) +#define LHL4369_SLB_EN_UP_CNT (LHL4369_VDDC_SW_DIS_UP_CNT + 8) +#define LHL4369_ISO_EN_UP_CNT (LHL4369_SLB_EN_UP_CNT + 1) +#define LHL4369_PWRSW_EN_UP_CNT (LHL4369_ISO_EN_UP_CNT + 3) +#define LHL4369_ASR_ADJ_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_CLK4M_DIS_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_LPPFM_MODE_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_MODE_SEL_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_MANUAL_MODE_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_OVERI_DIS_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) +#define LHL4369_ASR_TRIM_ADJ_UP_CNT (LHL4369_PWRSW_EN_UP_CNT + 1) + +/* MacResourceReqTimer0/1 */ +#define MAC_RSRC_REQ_TIMER_INT_ENAB_SHIFT 24 +#define MAC_RSRC_REQ_TIMER_FORCE_ALP_SHIFT 26 +#define MAC_RSRC_REQ_TIMER_FORCE_HT_SHIFT 27 +#define MAC_RSRC_REQ_TIMER_FORCE_HQ_SHIFT 28 +#define MAC_RSRC_REQ_TIMER_CLKREQ_GRP_SEL_SHIFT 29 + +/* for pmu rev32 and higher */ +#define PMU32_MAC_MAIN_RSRC_REQ_TIMER ((1 << MAC_RSRC_REQ_TIMER_INT_ENAB_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_ALP_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_HT_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_HQ_SHIFT) | \ + (0 << MAC_RSRC_REQ_TIMER_CLKREQ_GRP_SEL_SHIFT)) + +#define PMU32_MAC_AUX_RSRC_REQ_TIMER ((1 << MAC_RSRC_REQ_TIMER_INT_ENAB_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_ALP_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_HT_SHIFT) | \ + (1 << MAC_RSRC_REQ_TIMER_FORCE_HQ_SHIFT) | \ + (0 << MAC_RSRC_REQ_TIMER_CLKREQ_GRP_SEL_SHIFT)) + +/* 4369 related: 4369 parameters + * http://www.sj.broadcom.com/projects/BCM4369/gallery_backend.RC6.0/design/backplane/pmu_params.xls + */ +#define RES4369_DUMMY 0 +#define RES4369_ABUCK 1 +#define RES4369_PMU_SLEEP 2 +#define RES4369_MISCLDO_PU 3 +#define RES4369_LDO3P3_PU 4 +#define RES4369_FAST_LPO_AVAIL 5 +#define RES4369_XTAL_PU 6 +#define RES4369_XTAL_STABLE 7 +#define RES4369_PWRSW_DIG 8 +#define RES4369_SR_DIG 9 +#define RES4369_SLEEP_DIG 10 +#define RES4369_PWRSW_AUX 11 +#define RES4369_SR_AUX 12 +#define RES4369_SLEEP_AUX 13 +#define RES4369_PWRSW_MAIN 14 +#define RES4369_SR_MAIN 15 +#define RES4369_SLEEP_MAIN 16 +#define RES4369_DIG_CORE_RDY 17 +#define RES4369_CORE_RDY_AUX 18 +#define RES4369_ALP_AVAIL 19 +#define RES4369_RADIO_AUX_PU 20 +#define RES4369_MINIPMU_AUX_PU 21 +#define RES4369_CORE_RDY_MAIN 22 +#define RES4369_RADIO_MAIN_PU 23 +#define RES4369_MINIPMU_MAIN_PU 24 +#define RES4369_PCIE_EP_PU 25 +#define RES4369_COLD_START_WAIT 26 +#define RES4369_ARMHTAVAIL 27 +#define RES4369_HT_AVAIL 28 +#define RES4369_MACPHY_AUX_CLK_AVAIL 29 +#define RES4369_MACPHY_MAIN_CLK_AVAIL 30 +#define RES4369_RESERVED_31 31 + +#define CST4369_CHIPMODE_SDIOD(cs) (((cs) & (1 << 6)) != 0) /* SDIO */ +#define CST4369_CHIPMODE_PCIE(cs) (((cs) & (1 << 7)) != 0) /* PCIE */ +#define CST4369_SPROM_PRESENT 0x00000010 + +#define PMU_4369_MACCORE_0_RES_REQ_MASK 0x3FCBF7FF +#define PMU_4369_MACCORE_1_RES_REQ_MASK 0x7FFB3647 + +/* 4367 related */ +#define RES4367_ABUCK 0 +#define RES4367_CBUCK 1 +#define RES4367_MISCLDO_PU 2 +#define RES4367_VBOOST 3 +#define RES4367_LDO3P3_PU 4 +#define RES4367_LAST_LPO_AVAIL 5 +#define RES4367_XTAL_PU 6 +#define RES4367_XTAL_STABLE 7 +#define RES4367_PWRSW_DIG 8 +#define RES4367_SR_DIG 9 +#define RES4367_SPARE10 10 +#define RES4367_PWRSW_AUX 11 +#define RES4367_SR_AUX 12 +#define RES4367_SPARE2 13 +#define RES4367_PWRSW_MAIN 14 +#define RES4367_SR_MAIN 15 +#define RES4367_ARMPLL_PWRUP 16 +#define RES4367_DIG_CORE_RDY 17 +#define RES4367_CORE_RDY_AUX 18 +#define RES4367_ALP_AVAIL 19 +#define RES4367_RADIO_AUX_PU 20 +#define RES4367_MINIPMU_AUX_PU 21 +#define RES4367_CORE_RDY_MAIN 22 +#define RES4367_RADIO_MAIN_PU 23 +#define RES4367_MINIPMU_MAIN_PU 24 +#define RES4367_PCIE_RET 25 +#define RES4367_COLD_START_WAIT 26 +#define RES4367_ARMPLL_HTAVAIL 27 +#define RES4367_HT_AVAIL 28 +#define RES4367_MACPHY_AUX_CLK_AVAIL 29 +#define RES4367_MACPHY_MAIN_CLK_AVAIL 30 +#define RES4367_RESERVED_31 31 + +#define CST4367_SPROM_PRESENT (1 << 17) + /* 43430 PMU resources based on pmu_params.xls */ #define RES43430_LPLDO_PU 0 #define RES43430_BG_PU 1 @@ -3265,10 +3227,12 @@ typedef volatile struct { #define CC2_43430_SDIO_AOS_WAKEUP_MASK (1 << 24) #define CC2_43430_SDIO_AOS_WAKEUP_SHIFT (24) - #define PMU_MACCORE_0_RES_REQ_TIMER 0x1d000000 #define PMU_MACCORE_0_RES_REQ_MASK 0x5FF2364F +#define PMU43012_MAC_RES_REQ_TIMER 0x1D000000 +#define PMU43012_MAC_RES_REQ_MASK 0x3FBBF7FF + #define PMU_MACCORE_1_RES_REQ_TIMER 0x1d000000 #define PMU_MACCORE_1_RES_REQ_MASK 0x5FF2364F @@ -3343,6 +3307,11 @@ typedef volatile struct { #define CA7_4365_RAM_BASE (0x200000) #define CR4_4347_RAM_BASE (0x170000) +#define CR4_4362_RAM_BASE (0x170000) +#define CR4_4369_RAM_BASE (0x170000) +#define CR4_4377_RAM_BASE (0x170000) +#define CA7_4367_RAM_BASE (0x200000) +#define CR4_4378_RAM_BASE (0x352000) /* 4335 chip OTP present & OTP select bits. */ #define SPROM4335_OTP_SELECT 0x00000010 @@ -3364,7 +3333,6 @@ typedef volatile struct { #define CC4335_SROM_OTP_SFLASH_CLKDIV_MASK 0x003C #define CC4335_SROM_OTP_SFLASH_CLKDIV_SHIFT 2 - /* 4335 chip OTP present & OTP select bits. */ #define SPROM4335_OTP_SELECT 0x00000010 #define SPROM4335_OTP_PRESENT 0x00000020 @@ -3405,22 +3373,44 @@ typedef volatile struct { #define RES43012_XTAL_STABLE 14 #define RES43012_FCBS 15 #define RES43012_CBUCK_MODE 16 -#define RES43012_WL_CORE_RDY 17 +#define RES43012_CORE_READY 17 #define RES43012_ILP_REQ 18 #define RES43012_ALP_AVAIL 19 -#define RES43012_RADIO_LDO 20 +#define RES43012_RADIOLDO_1P8 20 #define RES43012_MINI_PMU 21 -#define RES43012_DUMMY 22 +#define RES43012_UNUSED 22 #define RES43012_SR_SAVE_RESTORE 23 -#define RES43012_SR_PHY_PWRSW 24 -#define RES43012_SR_VDDB_CLDO 25 -#define RES43012_SR_SUBCORE_PWRSW 26 +#define RES43012_PHY_PWRSW 24 +#define RES43012_VDDB_CLDO 25 +#define RES43012_SUBCORE_PWRSW 26 #define RES43012_SR_SLEEP 27 #define RES43012_HT_START 28 #define RES43012_HT_AVAIL 29 #define RES43012_MACPHY_CLK_AVAIL 30 #define CST43012_SPROM_PRESENT 0x00000010 +/* SR Control0 bits */ +#define SR0_43012_SR_ENG_EN_MASK 0x1 +#define SR0_43012_SR_ENG_EN_SHIFT 0 +#define SR0_43012_SR_ENG_CLK_EN (1 << 1) +#define SR0_43012_SR_RSRC_TRIGGER (0xC << 2) +#define SR0_43012_SR_WD_MEM_MIN_DIV (0x3 << 6) +#define SR0_43012_SR_MEM_STBY_ALLOW_MSK (1 << 16) +#define SR0_43012_SR_MEM_STBY_ALLOW_SHIFT 16 +#define SR0_43012_SR_ENABLE_ILP (1 << 17) +#define SR0_43012_SR_ENABLE_ALP (1 << 18) +#define SR0_43012_SR_ENABLE_HT (1 << 19) +#define SR0_43012_SR_ALLOW_PIC (3 << 20) +#define SR0_43012_SR_PMU_MEM_DISABLE (1 << 30) +#define CC_43012_VDDM_PWRSW_EN_MASK (1 << 20) +#define CC_43012_VDDM_PWRSW_EN_SHIFT (20) +#define CC_43012_SDIO_AOS_WAKEUP_MASK (1 << 24) +#define CC_43012_SDIO_AOS_WAKEUP_SHIFT (24) + +/* 43012 - offset at 5K */ +#define SR1_43012_SR_INIT_ADDR_MASK 0x3ff +#define SR1_43012_SR_ASM_ADDR 0xA + /* PLL usage in 43012 */ #define PMU43012_PLL0_PC0_NDIV_INT_MASK 0x0000003f #define PMU43012_PLL0_PC0_NDIV_INT_SHIFT 0 @@ -3439,12 +3429,15 @@ typedef volatile struct { /* PMU Rev >= 30 */ #define PMU30_ALPCLK_ONEMHZ_ENAB 0x80000000 +#define BCM7271_PMU30_ALPCLK_ONEMHZ_ENAB 0x00010000 + /* 43012 PMU Chip Control Registers */ #define PMUCCTL02_43012_SUBCORE_PWRSW_FORCE_ON 0x00000010 #define PMUCCTL02_43012_PHY_PWRSW_FORCE_ON 0x00000040 #define PMUCCTL02_43012_LHL_TIMER_SELECT 0x00000800 #define PMUCCTL02_43012_RFLDO3P3_PU_FORCE_ON 0x00008000 #define PMUCCTL02_43012_WL2CDIG_I_PMU_SLEEP_ENAB 0x00010000 +#define PMUCCTL02_43012_BTLDO3P3_PU_FORCE_OFF (1 << 12) #define PMUCCTL04_43012_BBPLL_ENABLE_PWRDN 0x00100000 #define PMUCCTL04_43012_BBPLL_ENABLE_PWROFF 0x00200000 @@ -3458,6 +3451,9 @@ typedef volatile struct { #define PMUCCTL04_43012_USE_LOCK 0x20000000 #define PMUCCTL04_43012_OPEN_LOOP_ENABLE 0x40000000 #define PMUCCTL04_43012_FORCE_OPEN_LOOP 0x80000000 +#define PMUCCTL05_43012_DISABLE_SPM_CLK (1 << 8) +#define PMUCCTL05_43012_RADIO_DIG_CLK_GATING_EN (1 << 14) +#define PMUCCTL06_43012_GCI2RDIG_USE_ASYNCAPB (1 << 31) #define PMUCCTL08_43012_XTAL_CORE_SIZE_PMOS_NORMAL_MASK 0x00000FC0 #define PMUCCTL08_43012_XTAL_CORE_SIZE_PMOS_NORMAL_SHIFT 6 #define PMUCCTL08_43012_XTAL_CORE_SIZE_NMOS_NORMAL_MASK 0x00FC0000 @@ -3468,16 +3464,53 @@ typedef volatile struct { #define PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_NORMAL_SHIFT 12 #define PMUCCTL09_43012_XTAL_CORESIZE_RES_BYPASS_NORMAL_MASK 0x00000038 #define PMUCCTL09_43012_XTAL_CORESIZE_RES_BYPASS_NORMAL_SHIFT 3 -#define PMUCCTL13_43012_FCBS_UP_TRIG_EN 0x00000400 -#define PMUCCTL14_43012_ARMCM3_RESET_INITVAL 0x00000001 -#define PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL 0x00000020 -#define PMUCCTL14_43012_SDIOD_RESET_INIVAL 0x00000400 -#define PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL 0x00001000 -#define PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL 0x00004000 -#define PMUCCTL14_43012_M2MDMA_RESET_INITVAL 0x00008000 -#define PMUCCTL14_43012_DISABLE_LQ_AVAIL 0x08000000 +#define PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_MASK 0x00000FC0 +#define PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_SHIFT 6 +/* during normal operation normal value is reduced for optimized power */ +#define PMUCCTL09_43012_XTAL_CORESIZE_BIAS_ADJ_STARTUP_VAL 0x1F + +#define PMUCCTL13_43012_FCBS_UP_TRIG_EN 0x00000400 + +#define PMUCCTL14_43012_ARMCM3_RESET_INITVAL 0x00000001 +#define PMUCCTL14_43012_DOT11MAC_CLKEN_INITVAL 0x00000020 +#define PMUCCTL14_43012_DOT11MAC_PHY_CLK_EN_INITVAL 0x00000080 +#define PMUCCTL14_43012_DOT11MAC_PHY_CNTL_EN_INITVAL 0x00000200 +#define PMUCCTL14_43012_SDIOD_RESET_INIVAL 0x00000400 +#define PMUCCTL14_43012_SDIO_CLK_DMN_RESET_INITVAL 0x00001000 +#define PMUCCTL14_43012_SOCRAM_CLKEN_INITVAL 0x00004000 +#define PMUCCTL14_43012_M2MDMA_RESET_INITVAL 0x00008000 +#define PMUCCTL14_43012_DISABLE_LQ_AVAIL 0x08000000 + +#define VREG6_43012_MEMLPLDO_ADJ_MASK 0x0000F000 +#define VREG6_43012_MEMLPLDO_ADJ_SHIFT 12 + +#define VREG6_43012_LPLDO_ADJ_MASK 0x000000F0 +#define VREG6_43012_LPLDO_ADJ_SHIFT 4 + +#define VREG7_43012_PWRSW_1P8_PU_MASK 0x00400000 +#define VREG7_43012_PWRSW_1P8_PU_SHIFT 22 +/* 4347 PMU Chip Control Registers */ +#define PMUCCTL03_4347_XTAL_CORESIZE_PMOS_NORMAL_MASK 0x001F8000 +#define PMUCCTL03_4347_XTAL_CORESIZE_PMOS_NORMAL_SHIFT 15 +#define PMUCCTL03_4347_XTAL_CORESIZE_PMOS_NORMAL_VAL 0x3F + +#define PMUCCTL03_4347_XTAL_CORESIZE_NMOS_NORMAL_MASK 0x07E00000 +#define PMUCCTL03_4347_XTAL_CORESIZE_NMOS_NORMAL_SHIFT 21 +#define PMUCCTL03_4347_XTAL_CORESIZE_NMOS_NORMAL_VAL 0x3F + +#define PMUCCTL03_4347_XTAL_SEL_BIAS_RES_NORMAL_MASK 0x38000000 +#define PMUCCTL03_4347_XTAL_SEL_BIAS_RES_NORMAL_SHIFT 27 +#define PMUCCTL03_4347_XTAL_SEL_BIAS_RES_NORMAL_VAL 0x0 + +#define PMUCCTL00_4347_XTAL_CORESIZE_BIAS_ADJ_NORMAL_MASK 0x00000FC0 +#define PMUCCTL00_4347_XTAL_CORESIZE_BIAS_ADJ_NORMAL_SHIFT 6 +#define PMUCCTL00_4347_XTAL_CORESIZE_BIAS_ADJ_NORMAL_VAL 0x5 + +#define PMUCCTL00_4347_XTAL_RES_BYPASS_NORMAL_MASK 0x00038000 +#define PMUCCTL00_4347_XTAL_RES_BYPASS_NORMAL_SHIFT 15 +#define PMUCCTL00_4347_XTAL_RES_BYPASS_NORMAL_VAL 0x7 /* 4345 Chip specific ChipStatus register bits */ #define CST4345_SPROM_MASK 0x00000020 @@ -3604,7 +3637,6 @@ typedef volatile struct { #define MUXENAB4350_HOSTWAKE_SHIFT 4 #define MUXENAB4349_UART_MASK (0xf) - #define CC4350_GPIO_COUNT 16 /* 4350 GCI function sel values */ @@ -3625,7 +3657,6 @@ typedef volatile struct { #define CC4350_FNSEL_TRISTATE (15) #define CC4350C_FNSEL_UART (3) - /* 4350 GPIO */ #define CC4350_PIN_GPIO_00 (0) #define CC4350_PIN_GPIO_01 (1) @@ -3758,6 +3789,37 @@ typedef volatile struct { #define CC6_4345_PMU_EN_MDIO_MASK (1 << 24) #define CC6_4345_PMU_EN_MDIO_SHIFT (24) +/* 4347 GCI function sel values */ +#define CC4347_FNSEL_HWDEF (0) +#define CC4347_FNSEL_SAMEASPIN (1) +#define CC4347_FNSEL_GPIO0 (2) +#define CC4347_FNSEL_FUART (3) +#define CC4347_FNSEL_GCI0 (4) +#define CC4347_FNSEL_GCI1 (5) +#define CC4347_FNSEL_DBG_UART (6) +#define CC4347_FNSEL_SPI (7) +#define CC4347_FNSEL_SPROM (8) +#define CC4347_FNSEL_MISC0 (9) +#define CC4347_FNSEL_MISC1 (10) +#define CC4347_FNSEL_MISC2 (11) +#define CC4347_FNSEL_IND (12) +#define CC4347_FNSEL_PDN (13) +#define CC4347_FNSEL_PUP (14) +#define CC4347_FNSEL_TRISTATE (15) + +/* 4347 GPIO */ +#define CC4347_PIN_GPIO_02 (2) +#define CC4347_PIN_GPIO_03 (3) +#define CC4347_PIN_GPIO_04 (4) +#define CC4347_PIN_GPIO_05 (5) +#define CC4347_PIN_GPIO_06 (6) +#define CC4347_PIN_GPIO_07 (7) +#define CC4347_PIN_GPIO_08 (8) +#define CC4347_PIN_GPIO_09 (9) +#define CC4347_PIN_GPIO_10 (10) +#define CC4347_PIN_GPIO_11 (11) +#define CC4347_PIN_GPIO_12 (12) +#define CC4347_PIN_GPIO_13 (13) /* GCI chipcontrol register indices */ #define CC_GCI_CHIPCTRL_00 (0) #define CC_GCI_CHIPCTRL_01 (1) @@ -3774,11 +3836,23 @@ typedef volatile struct { #define CC_GCI_CHIPCTRL_11 (11) #define CC_GCI_XTAL_BUFSTRG_NFC (0xff << 12) +#define CC_GCI_04_SDIO_DRVSTR_SHIFT 15 +#define CC_GCI_04_SDIO_DRVSTR_MASK (0x0f << CC_GCI_04_SDIO_DRVSTR_SHIFT) /* 0x00078000 */ +#define CC_GCI_04_SDIO_DRVSTR_OVERRIDE_BIT (1 << 18) +#define CC_GCI_04_SDIO_DRVSTR_DEFAULT_MA 14 +#define CC_GCI_04_SDIO_DRVSTR_MIN_MA 2 +#define CC_GCI_04_SDIO_DRVSTR_MAX_MA 16 + #define CC_GCI_06_JTAG_SEL_SHIFT 4 #define CC_GCI_06_JTAG_SEL_MASK (1 << 4) #define CC_GCI_NUMCHIPCTRLREGS(cap1) ((cap1 & 0xF00) >> 8) +#define CC_GCI_03_LPFLAGS_SFLASH_MASK (0xFFFFFF << 8) +#define CC_GCI_03_LPFLAGS_SFLASH_VAL (0xCCCCCC << 8) +#define GPIO_CTRL_REG_DISABLE_INTERRUPT (3 << 9) +#define GPIO_CTRL_REG_COUNT 40 + /* GCI chipstatus register indices */ #define GCI_CHIPSTATUS_00 (0) #define GCI_CHIPSTATUS_01 (1) @@ -3789,6 +3863,11 @@ typedef volatile struct { #define GCI_CHIPSTATUS_06 (6) #define GCI_CHIPSTATUS_07 (7) #define GCI_CHIPSTATUS_08 (8) +#define GCI_CHIPSTATUS_09 (9) +#define GCI_CHIPSTATUS_10 (10) +#define GCI_CHIPSTATUS_11 (11) +#define GCI_CHIPSTATUS_12 (12) +#define GCI_CHIPSTATUS_13 (13) /* 43021 GCI chipstatus registers */ #define GCI43012_CHIPSTATUS_07_BBPLL_LOCK_MASK (1 << 3) @@ -3923,6 +4002,7 @@ typedef volatile struct { #define GCI_CORECTRL_SOM_MASK (7 << 4) /**< SECI Op Mode */ #define GCI_CORECTRL_US_MASK (1 << 7) /**< Update SECI */ #define GCI_CORECTRL_BOS_MASK (1 << 8) /**< Break On Sleep */ +#define GCI_CORECTRL_FORCEREGCLK_MASK (1 << 18) /* ForceRegClk */ /* 4345 pins * note: only the values set as default/used are added here. @@ -4035,7 +4115,6 @@ typedef volatile struct { #define CC_GCI_GPIO_14 (14) #define CC_GCI_GPIO_15 (15) - /* indicates Invalid GPIO, e.g. when PAD GPIO doesn't map to GCI GPIO */ #define CC_GCI_GPIO_INVALID 0xFF @@ -4046,7 +4125,6 @@ typedef volatile struct { /* Extract nibble from a given position */ #define GCIGETNBL(val, pos) ((val >> pos) & 0xF) - /* find the 8 bit mask given the bit position */ #define GCIMASK_8B(pos) (((uint32)0xFF) << pos) /* get the value which can be used to directly OR with chipcontrol reg */ @@ -4061,7 +4139,6 @@ typedef volatile struct { /* Extract nibble from a given position */ #define GCIGETNBL_4B(val, pos) ((val >> pos) & 0xF) - /* 4335 GCI Intstatus(Mask)/WakeMask Register bits. */ #define GCI_INTSTATUS_RBI (1 << 0) /**< Rx Break Interrupt */ #define GCI_INTSTATUS_UB (1 << 1) /**< UART Break Interrupt */ @@ -4073,8 +4150,12 @@ typedef volatile struct { #define GCI_INTSTATUS_SRFAF (1 << 12) /**< SECI Rx FIFO Almost Full */ #define GCI_INTSTATUS_SRFNE (1 << 14) /**< SECI Rx FIFO Not Empty */ #define GCI_INTSTATUS_SRFOF (1 << 15) /**< SECI Rx FIFO Not Empty Timeout */ +#define GCI_INTSTATUS_EVENT (1 << 21) /* GCI Event Interrupt */ +#define GCI_INTSTATUS_LEVELWAKE (1 << 22) /* GCI Wake Level Interrupt */ +#define GCI_INTSTATUS_EVENTWAKE (1 << 23) /* GCI Wake Event Interrupt */ #define GCI_INTSTATUS_GPIOINT (1 << 25) /**< GCIGpioInt */ #define GCI_INTSTATUS_GPIOWAKE (1 << 26) /**< GCIGpioWake */ +#define GCI_INTSTATUS_LHLWLWAKE (1 << 30) /* LHL WL wake */ /* 4335 GCI IntMask Register bits. */ #define GCI_INTMASK_RBI (1 << 0) /**< Rx Break Interrupt */ @@ -4087,8 +4168,12 @@ typedef volatile struct { #define GCI_INTMASK_SRFAF (1 << 12) /**< SECI Rx FIFO Almost Full */ #define GCI_INTMASK_SRFNE (1 << 14) /**< SECI Rx FIFO Not Empty */ #define GCI_INTMASK_SRFOF (1 << 15) /**< SECI Rx FIFO Not Empty Timeout */ +#define GCI_INTMASK_EVENT (1 << 21) /* GCI Event Interrupt */ +#define GCI_INTMASK_LEVELWAKE (1 << 22) /* GCI Wake Level Interrupt */ +#define GCI_INTMASK_EVENTWAKE (1 << 23) /* GCI Wake Event Interrupt */ #define GCI_INTMASK_GPIOINT (1 << 25) /**< GCIGpioInt */ #define GCI_INTMASK_GPIOWAKE (1 << 26) /**< GCIGpioWake */ +#define GCI_INTMASK_LHLWLWAKE (1 << 30) /* LHL WL wake */ /* 4335 GCI WakeMask Register bits. */ #define GCI_WAKEMASK_RBI (1 << 0) /**< Rx Break Interrupt */ @@ -4101,8 +4186,12 @@ typedef volatile struct { #define GCI_WAKEMASK_SRFAF (1 << 12) /**< SECI Rx FIFO Almost Full */ #define GCI_WAKEMASK_SRFNE (1 << 14) /**< SECI Rx FIFO Not Empty */ #define GCI_WAKEMASK_SRFOF (1 << 15) /**< SECI Rx FIFO Not Empty Timeout */ +#define GCI_WAKEMASK_EVENT (1 << 21) /* GCI Event Interrupt */ +#define GCI_WAKEMASK_LEVELWAKE (1 << 22) /* GCI Wake Level Interrupt */ +#define GCI_WAKEMASK_EVENTWAKE (1 << 23) /* GCI Wake Event Interrupt */ #define GCI_WAKEMASK_GPIOINT (1 << 25) /**< GCIGpioInt */ #define GCI_WAKEMASK_GPIOWAKE (1 << 26) /**< GCIGpioWake */ +#define GCI_WAKEMASK_LHLWLWAKE (1 << 30) /* LHL WL wake */ #define GCI_WAKE_ON_GCI_GPIO1 1 #define GCI_WAKE_ON_GCI_GPIO2 2 @@ -4114,12 +4203,130 @@ typedef volatile struct { #define GCI_WAKE_ON_GCI_GPIO8 8 #define GCI_WAKE_ON_GCI_SECI_IN 9 -/* 43012 ULB dividers */ -#define PMU43012_CC0_ULB_DIVMASK 0xfffffc00 -#define PMU43012_10MHZ_ULB_DIV ((1 << 0) | (1 << 5)) -#define PMU43012_5MHZ_ULB_DIV ((3 << 0) | (3 << 5)) -#define PMU43012_2P5MHZ_ULB_DIV ((7 << 0) | (7 << 5)) -#define PMU43012_ULB_NO_DIV 0 +#define PMU_EXT_WAKE_MASK_0_SDIO (1 << 2) + +/* =========== LHL regs =========== */ +#define LHL_PWRSEQCTL_SLEEP_EN (1 << 0) +#define LHL_PWRSEQCTL_PMU_SLEEP_MODE (1 << 1) +#define LHL_PWRSEQCTL_PMU_FINAL_PMU_SLEEP_EN (1 << 2) +#define LHL_PWRSEQCTL_PMU_TOP_ISO_EN (1 << 3) +#define LHL_PWRSEQCTL_PMU_TOP_SLB_EN (1 << 4) +#define LHL_PWRSEQCTL_PMU_TOP_PWRSW_EN (1 << 5) +#define LHL_PWRSEQCTL_PMU_CLDO_PD (1 << 6) +#define LHL_PWRSEQCTL_PMU_LPLDO_PD (1 << 7) +#define LHL_PWRSEQCTL_PMU_RSRC6_EN (1 << 8) + +#define PMU_SLEEP_MODE_0 (LHL_PWRSEQCTL_SLEEP_EN |\ + LHL_PWRSEQCTL_PMU_FINAL_PMU_SLEEP_EN) + +#define PMU_SLEEP_MODE_1 (LHL_PWRSEQCTL_SLEEP_EN |\ + LHL_PWRSEQCTL_PMU_SLEEP_MODE |\ + LHL_PWRSEQCTL_PMU_FINAL_PMU_SLEEP_EN |\ + LHL_PWRSEQCTL_PMU_TOP_ISO_EN |\ + LHL_PWRSEQCTL_PMU_TOP_SLB_EN |\ + LHL_PWRSEQCTL_PMU_TOP_PWRSW_EN |\ + LHL_PWRSEQCTL_PMU_CLDO_PD |\ + LHL_PWRSEQCTL_PMU_RSRC6_EN) + +#define PMU_SLEEP_MODE_2 (LHL_PWRSEQCTL_SLEEP_EN |\ + LHL_PWRSEQCTL_PMU_SLEEP_MODE |\ + LHL_PWRSEQCTL_PMU_FINAL_PMU_SLEEP_EN |\ + LHL_PWRSEQCTL_PMU_TOP_ISO_EN |\ + LHL_PWRSEQCTL_PMU_TOP_SLB_EN |\ + LHL_PWRSEQCTL_PMU_TOP_PWRSW_EN |\ + LHL_PWRSEQCTL_PMU_CLDO_PD |\ + LHL_PWRSEQCTL_PMU_LPLDO_PD |\ + LHL_PWRSEQCTL_PMU_RSRC6_EN) + +#define LHL_PWRSEQ_CTL (0x000000ff) + +/* LHL Top Level Power Up Control Register (lhl_top_pwrup_ctl_adr, Offset 0xE78) +* Top Level Counter values for isolation, retention, Power Switch control +*/ +#define LHL_PWRUP_ISOLATION_CNT (0x6 << 8) +#define LHL_PWRUP_RETENTION_CNT (0x5 << 16) +#define LHL_PWRUP_PWRSW_CNT (0x7 << 24) +/* Mask is taken only for isolation 8:13 , Retention 16:21 , +* Power Switch control 24:29 +*/ +#define LHL_PWRUP_CTL_MASK (0x3F3F3F00) +#define LHL_PWRUP_CTL (LHL_PWRUP_ISOLATION_CNT |\ + LHL_PWRUP_RETENTION_CNT |\ + LHL_PWRUP_PWRSW_CNT) + +#define LHL_PWRUP_ISOLATION_CNT_4347 (0x7 << 8) +#define LHL_PWRUP_RETENTION_CNT_4347 (0x5 << 16) +#define LHL_PWRUP_PWRSW_CNT_4347 (0x7 << 24) + +#define LHL_PWRUP_CTL_4347 (LHL_PWRUP_ISOLATION_CNT_4347 |\ + LHL_PWRUP_RETENTION_CNT_4347 |\ + LHL_PWRUP_PWRSW_CNT_4347) + +#define LHL_PWRUP2_CLDO_DN_CNT (0x0) +#define LHL_PWRUP2_LPLDO_DN_CNT (0x0 << 8) +#define LHL_PWRUP2_RSRC6_DN_CN (0x4 << 16) +#define LHL_PWRUP2_RSRC7_DN_CN (0x0 << 24) +#define LHL_PWRUP2_CTL_MASK (0x3F3F3F3F) +#define LHL_PWRUP2_CTL (LHL_PWRUP2_CLDO_DN_CNT |\ + LHL_PWRUP2_LPLDO_DN_CNT |\ + LHL_PWRUP2_RSRC6_DN_CN |\ + LHL_PWRUP2_RSRC7_DN_CN) + +/* LHL Top Level Power Down Control Register (lhl_top_pwrdn_ctl_adr, Offset 0xE74) */ +#define LHL_PWRDN_SLEEP_CNT (0x4) +#define LHL_PWRDN_CTL_MASK (0x3F) + +/* LHL Top Level Power Down Control 2 Register (lhl_top_pwrdn2_ctl_adr, Offset 0xE80) */ +#define LHL_PWRDN2_CLDO_DN_CNT (0x4) +#define LHL_PWRDN2_LPLDO_DN_CNT (0x4 << 8) +#define LHL_PWRDN2_RSRC6_DN_CN (0x3 << 16) +#define LHL_PWRDN2_RSRC7_DN_CN (0x0 << 24) +#define LHL_PWRDN2_CTL (LHL_PWRDN2_CLDO_DN_CNT |\ + LHL_PWRDN2_LPLDO_DN_CNT |\ + LHL_PWRDN2_RSRC6_DN_CN |\ + LHL_PWRDN2_RSRC7_DN_CN) +#define LHL_PWRDN2_CTL_MASK (0x3F3F3F3F) + +#define LHL_FAST_WRITE_EN (1 << 14) + +/* WL ARM Timer0 Interrupt Mask (lhl_wl_armtim0_intrp_adr) */ +#define LHL_WL_ARMTIM0_INTRP_EN 0x00000001 +#define LHL_WL_ARMTIM0_INTRP_EDGE_TRIGGER 0x00000002 + +/* WL MAC Timer0 Interrupt Mask (lhl_wl_mactim0_intrp_adr) */ +#define LHL_WL_MACTIM0_INTRP_EN 0x00000001 +#define LHL_WL_MACTIM0_INTRP_EDGE_TRIGGER 0x00000002 + +/* LHL Wakeup Status (lhl_wkup_status_adr) */ +#define LHL_WKUP_STATUS_WR_PENDING_ARMTIM0 0x00100000 + +/* WL ARM Timer0 Interrupt Status (lhl_wl_armtim0_st_adr) */ +#define LHL_WL_ARMTIM0_ST_WL_ARMTIM_INT_ST 0x00000001 + +#define LHL_PS_MODE_0 0 +#define LHL_PS_MODE_1 1 + +/* GCI EventIntMask Register SW bits */ +#define GCI_MAILBOXDATA_TOWLAN (1 << 0) +#define GCI_MAILBOXDATA_TOBT (1 << 1) +#define GCI_MAILBOXDATA_TONFC (1 << 2) +#define GCI_MAILBOXDATA_TOGPS (1 << 3) +#define GCI_MAILBOXDATA_TOLTE (1 << 4) +#define GCI_MAILBOXACK_TOWLAN (1 << 8) +#define GCI_MAILBOXACK_TOBT (1 << 9) +#define GCI_MAILBOXACK_TONFC (1 << 10) +#define GCI_MAILBOXACK_TOGPS (1 << 11) +#define GCI_MAILBOXACK_TOLTE (1 << 12) +#define GCI_WAKE_TOWLAN (1 << 16) +#define GCI_WAKE_TOBT (1 << 17) +#define GCI_WAKE_TONFC (1 << 18) +#define GCI_WAKE_TOGPS (1 << 19) +#define GCI_WAKE_TOLTE (1 << 20) +#define GCI_SWREADY (1 << 24) + +/* 4349 Group (4349, 4355, 4359) GCI SECI_OUT TX Status Regiser bits */ +#define GCI_SECIOUT_TXSTATUS_TXHALT (1 << 0) +#define GCI_SECIOUT_TXSTATUS_TI (1 << 16) /* 4335 MUX options. each nibble belongs to a setting. Non-zero value specifies a logic * for now only UART for bootloader. @@ -4197,7 +4404,6 @@ typedef volatile struct { #define CST53573_CHIPMODE_PCIE(cs) FALSE - /* SECI Status (0x134) & Mask (0x138) bits - Rev 35 */ #define SECI_STAT_BI (1 << 0) /* Break Interrupt */ #define SECI_STAT_SPE (1 << 1) /* Parity Error */ @@ -4228,6 +4434,7 @@ typedef volatile struct { #define SECI_MODE_SHIFT 4 /* (bits 5, 6, 7) */ #define SECI_UPD_SECI (1 << 7) +#define SECI_AUX_TX_START (1 << 31) #define SECI_SLIP_ESC_CHAR 0xDB #define SECI_SIGNOFF_0 SECI_SLIP_ESC_CHAR #define SECI_SIGNOFF_1 0 @@ -4319,7 +4526,6 @@ typedef volatile struct { #define LTECX_MUX_MODE_WCI2 0x0 #define LTECX_MUX_MODE_GPIO 0x1 - /* LTECX GPIO Information Index */ #define LTECX_NVRAM_FSYNC_IDX 0 #define LTECX_NVRAM_LTERX_IDX 1 @@ -4389,6 +4595,11 @@ typedef volatile struct { #define GCI_GPIO_STS_FAST_EDGE_BIT 3 #define GCI_GPIO_STS_CLEAR 0xF +#define GCI_GPIO_STS_EDGE_TRIG_BIT 0 +#define GCI_GPIO_STS_NEG_EDGE_TRIG_BIT 1 +#define GCI_GPIO_STS_DUAL_EDGE_TRIG_BIT 2 +#define GCI_GPIO_STS_WL_DIN_SELECT 6 + #define GCI_GPIO_STS_VALUE (1 << GCI_GPIO_STS_VALUE_BIT) /* SR Power Control */ @@ -4413,4 +4624,7 @@ typedef volatile struct { #define SRPWR_DMN_SHIFT (28) /* PowerDomain[31:28], RO */ #define SRPWR_DMN_MASK (SRPWR_DMN_ALL_MASK << SRPWR_DMN_SHIFT) +/* PMU Precision Usec Timer */ +#define PMU_PREC_USEC_TIMER_ENABLE 0x1 + #endif /* _SBCHIPC_H */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbconfig.h b/drivers/net/wireless/bcmdhd_oo/include/sbconfig.h index ad9c408cd3448f7a00c97d8f665b5b8578a287bb..d38364e90ddb3b53b7899c1a6d3211ebaf7717d0 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbconfig.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbconfig.h @@ -1,14 +1,14 @@ /* * Broadcom SiliconBackplane hardware register definitions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: sbconfig.h 530150 2015-01-29 08:43:40Z $ + * $Id: sbconfig.h 654158 2016-08-11 09:30:01Z $ */ #ifndef _SBCONFIG_H @@ -35,13 +35,13 @@ #define _PADLINE(line) pad ## line #define _XSTR(line) _PADLINE(line) #define PAD _XSTR(__LINE__) -#endif +#endif // endif -/* enumeration in SB is based on the premise that cores are contiguos in the +/* enumeration in SB is based on the premise that cores are contiguous in the * enumeration space. */ #define SB_BUS_SIZE 0x10000 /**< Each bus gets 64Kbytes for cores */ -#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) +#define SB_BUS_BASE(sih, b) (SI_ENUM_BASE(sih) + (b) * SB_BUS_SIZE) #define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) /**< Max cores per bus */ /* diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbgci.h b/drivers/net/wireless/bcmdhd_oo/include/sbgci.h index f04232daca1a6dbca93b8ffb98c9a5ad64a449bc..121f04ad468a119dfeae8bb0d0f957784b176f0c 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbgci.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbgci.h @@ -1,14 +1,14 @@ /* * SiliconBackplane GCI core hardware definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,12 +24,14 @@ * * <> * - * $Id: sbgci.h 612498 2016-01-14 05:09:09Z $ + * $Id: sbgci.h 696881 2017-04-28 17:20:35Z $ */ #ifndef _SBGCI_H #define _SBGCI_H +#include + #if !defined(_LANGUAGE_ASSEMBLY) && !defined(__ASSEMBLY__) /* cpp contortions to concatenate w/arg prescan */ @@ -44,124 +46,127 @@ #define GCI_CORE_IDX(sih) (AOB_ENAB(sih) ? si_findcoreidx(sih, GCI_CORE_ID, 0) : SI_CC_IDX) typedef volatile struct { - uint32 gci_corecaps0; /* 0x000 */ - uint32 gci_corecaps1; /* 0x004 */ - uint32 gci_corecaps2; /* 0x008 */ - uint32 gci_corectrl; /* 0x00c */ - uint32 gci_corestat; /* 0x010 */ - uint32 gci_intstat; /* 0x014 */ - uint32 gci_intmask; /* 0x018 */ - uint32 gci_wakemask; /* 0x01c */ - uint32 gci_levelintstat; /* 0x020 */ - uint32 gci_eventintstat; /* 0x024 */ - uint32 gci_wakelevelintstat; /* 0x028 */ - uint32 gci_wakeeventintstat; /* 0x02c */ - uint32 semaphoreintstatus; /* 0x030 */ - uint32 semaphoreintmask; /* 0x034 */ - uint32 semaphorerequest; /* 0x038 */ - uint32 semaphorereserve; /* 0x03c */ - uint32 gci_indirect_addr; /* 0x040 */ - uint32 gci_gpioctl; /* 0x044 */ - uint32 gci_gpiostatus; /* 0x048 */ - uint32 gci_gpiomask; /* 0x04c */ - uint32 eventsummary; /* 0x050 */ - uint32 gci_miscctl; /* 0x054 */ - uint32 gci_gpiointmask; /* 0x058 */ - uint32 gci_gpiowakemask; /* 0x05c */ - uint32 gci_input[32]; /* 0x060 */ - uint32 gci_event[32]; /* 0x0e0 */ - uint32 gci_output[4]; /* 0x160 */ - uint32 gci_control_0; /* 0x170 */ - uint32 gci_control_1; /* 0x174 */ - uint32 gci_intpolreg; /* 0x178 */ - uint32 gci_levelintmask; /* 0x17c */ - uint32 gci_eventintmask; /* 0x180 */ - uint32 wakelevelintmask; /* 0x184 */ - uint32 wakeeventintmask; /* 0x188 */ - uint32 hwmask; /* 0x18c */ - uint32 PAD; - uint32 gci_inbandeventintmask; /* 0x194 */ - uint32 PAD; - uint32 gci_inbandeventstatus; /* 0x19c */ - uint32 gci_seciauxtx; /* 0x1a0 */ - uint32 gci_seciauxrx; /* 0x1a4 */ - uint32 gci_secitx_datatag; /* 0x1a8 */ - uint32 gci_secirx_datatag; /* 0x1ac */ - uint32 gci_secitx_datamask; /* 0x1b0 */ - uint32 gci_seciusef0tx_reg; /* 0x1b4 */ - uint32 gci_secif0tx_offset; /* 0x1b8 */ - uint32 gci_secif0rx_offset; /* 0x1bc */ - uint32 gci_secif1tx_offset; /* 0x1c0 */ - uint32 gci_rxfifo_common_ctrl; /* 0x1c4 */ - uint32 gci_rxfifoctrl; /* 0x1c8 */ - uint32 gci_hw_sema_status; /* 0x1cc */ - uint32 gci_seciuartescval; /* 0x1d0 */ - uint32 gic_seciuartautobaudctr; /* 0x1d4 */ - uint32 gci_secififolevel; /* 0x1d8 */ - uint32 gci_seciuartdata; /* 0x1dc */ - uint32 gci_secibauddiv; /* 0x1e0 */ - uint32 gci_secifcr; /* 0x1e4 */ - uint32 gci_secilcr; /* 0x1e8 */ - uint32 gci_secimcr; /* 0x1ec */ - uint32 gci_secilsr; /* 0x1f0 */ - uint32 gci_secimsr; /* 0x1f4 */ - uint32 gci_baudadj; /* 0x1f8 */ - uint32 gci_inbandintmask; /* 0x1fc */ - uint32 gci_chipctrl; /* 0x200 */ - uint32 gci_chipsts; /* 0x204 */ - uint32 gci_gpioout; /* 0x208 */ - uint32 gci_gpioout_read; /* 0x20C */ - uint32 gci_mpwaketx; /* 0x210 */ - uint32 gci_mpwakedetect; /* 0x214 */ - uint32 gci_seciin_ctrl; /* 0x218 */ - uint32 gci_seciout_ctrl; /* 0x21C */ - uint32 gci_seciin_auxfifo_en; /* 0x220 */ - uint32 gci_seciout_txen_txbr; /* 0x224 */ - uint32 gci_seciin_rxbrstatus; /* 0x228 */ - uint32 gci_seciin_rxerrstatus; /* 0x22C */ - uint32 gci_seciin_fcstatus; /* 0x230 */ - uint32 gci_seciout_txstatus; /* 0x234 */ - uint32 gci_seciout_txbrstatus; /* 0x238 */ - uint32 wlan_mem_info; /* 0x23C */ - uint32 wlan_bankxinfo; /* 0x240 */ - uint32 bt_smem_select; /* 0x244 */ - uint32 bt_smem_stby; /* 0x248 */ - uint32 bt_smem_status; /* 0x24C */ - uint32 wlan_bankxactivepda; /* 0x250 */ - uint32 wlan_bankxsleeppda; /* 0x254 */ - uint32 wlan_bankxkill; /* 0x258 */ - uint32 PAD[41]; - uint32 gci_chipid; /* 0x300 */ - uint32 PAD[3]; - uint32 otpstatus; /* 0x310 */ - uint32 otpcontrol; /* 0x314 */ - uint32 otpprog; /* 0x318 */ - uint32 otplayout; /* 0x31c */ - uint32 otplayoutextension; /* 0x320 */ - uint32 otpcontrol1; /* 0x324 */ - uint32 otpprogdata; /* 0x328 */ - uint32 PAD[52]; - uint32 otpECCstatus; /* 0x3FC */ - uint32 PAD[512]; - uint32 lhl_core_capab_adr; /* 0xC00 */ - uint32 lhl_main_ctl_adr; /* 0xC04 */ - uint32 lhl_pmu_ctl_adr; /* 0xC08 */ - uint32 lhl_extlpo_ctl_adr; /* 0xC0C */ - uint32 lpo_ctl_adr; /* 0xC10 */ - uint32 lhl_lpo2_ctl_adr; /* 0xC14 */ - uint32 lhl_osc32k_ctl_adr; /* 0xC18 */ - uint32 lhl_clk_status_adr; /* 0xC1C */ - uint32 lhl_clk_det_ctl_adr; /* 0xC20 */ - uint32 lhl_clk_sel_adr; /* 0xC24 */ - uint32 hidoff_cnt_adr[2]; /* 0xC28-0xC2C */ - uint32 lhl_autoclk_ctl_adr; /* 0xC30 */ - uint32 PAD; /* reserved */ - uint32 lhl_hibtim_adr; /* 0xC38 */ - uint32 lhl_wl_ilp_val_adr; /* 0xC3C */ - uint32 lhl_wl_armtim0_intrp_adr; /* 0xC40 */ - uint32 lhl_wl_armtim0_st_adr; /* 0xC44 */ - uint32 lhl_wl_armtim0_adr; /* 0xC48 */ - uint32 PAD[9]; /* 0xC4C-0xC6C */ + uint32 gci_corecaps0; /* 0x000 */ + uint32 gci_corecaps1; /* 0x004 */ + uint32 gci_corecaps2; /* 0x008 */ + uint32 gci_corectrl; /* 0x00c */ + uint32 gci_corestat; /* 0x010 */ + uint32 gci_intstat; /* 0x014 */ + uint32 gci_intmask; /* 0x018 */ + uint32 gci_wakemask; /* 0x01c */ + uint32 gci_levelintstat; /* 0x020 */ + uint32 gci_eventintstat; /* 0x024 */ + uint32 gci_wakelevelintstat; /* 0x028 */ + uint32 gci_wakeeventintstat; /* 0x02c */ + uint32 semaphoreintstatus; /* 0x030 */ + uint32 semaphoreintmask; /* 0x034 */ + uint32 semaphorerequest; /* 0x038 */ + uint32 semaphorereserve; /* 0x03c */ + uint32 gci_indirect_addr; /* 0x040 */ + uint32 gci_gpioctl; /* 0x044 */ + uint32 gci_gpiostatus; /* 0x048 */ + uint32 gci_gpiomask; /* 0x04c */ + uint32 gci_eventsummary; /* 0x050 */ + uint32 gci_miscctl; /* 0x054 */ + uint32 gci_gpiointmask; /* 0x058 */ + uint32 gci_gpiowakemask; /* 0x05c */ + uint32 gci_input[32]; /* 0x060 */ + uint32 gci_event[32]; /* 0x0e0 */ + uint32 gci_output[4]; /* 0x160 */ + uint32 gci_control_0; /* 0x170 */ + uint32 gci_control_1; /* 0x174 */ + uint32 gci_intpolreg; /* 0x178 */ + uint32 gci_levelintmask; /* 0x17c */ + uint32 gci_eventintmask; /* 0x180 */ + uint32 wakelevelintmask; /* 0x184 */ + uint32 wakeeventintmask; /* 0x188 */ + uint32 hwmask; /* 0x18c */ + uint32 PAD; + uint32 gci_inbandeventintmask; /* 0x194 */ + uint32 PAD; + uint32 gci_inbandeventstatus; /* 0x19c */ + uint32 gci_seciauxtx; /* 0x1a0 */ + uint32 gci_seciauxrx; /* 0x1a4 */ + uint32 gci_secitx_datatag; /* 0x1a8 */ + uint32 gci_secirx_datatag; /* 0x1ac */ + uint32 gci_secitx_datamask; /* 0x1b0 */ + uint32 gci_seciusef0tx_reg; /* 0x1b4 */ + uint32 gci_secif0tx_offset; /* 0x1b8 */ + uint32 gci_secif0rx_offset; /* 0x1bc */ + uint32 gci_secif1tx_offset; /* 0x1c0 */ + uint32 gci_rxfifo_common_ctrl; /* 0x1c4 */ + uint32 gci_rxfifoctrl; /* 0x1c8 */ + uint32 gci_hw_sema_status; /* 0x1cc */ + uint32 gci_seciuartescval; /* 0x1d0 */ + uint32 gic_seciuartautobaudctr; /* 0x1d4 */ + uint32 gci_secififolevel; /* 0x1d8 */ + uint32 gci_seciuartdata; /* 0x1dc */ + uint32 gci_secibauddiv; /* 0x1e0 */ + uint32 gci_secifcr; /* 0x1e4 */ + uint32 gci_secilcr; /* 0x1e8 */ + uint32 gci_secimcr; /* 0x1ec */ + uint32 gci_secilsr; /* 0x1f0 */ + uint32 gci_secimsr; /* 0x1f4 */ + uint32 gci_baudadj; /* 0x1f8 */ + uint32 gci_inbandintmask; /* 0x1fc */ + uint32 gci_chipctrl; /* 0x200 */ + uint32 gci_chipsts; /* 0x204 */ + uint32 gci_gpioout; /* 0x208 */ + uint32 gci_gpioout_read; /* 0x20C */ + uint32 gci_mpwaketx; /* 0x210 */ + uint32 gci_mpwakedetect; /* 0x214 */ + uint32 gci_seciin_ctrl; /* 0x218 */ + uint32 gci_seciout_ctrl; /* 0x21C */ + uint32 gci_seciin_auxfifo_en; /* 0x220 */ + uint32 gci_seciout_txen_txbr; /* 0x224 */ + uint32 gci_seciin_rxbrstatus; /* 0x228 */ + uint32 gci_seciin_rxerrstatus; /* 0x22C */ + uint32 gci_seciin_fcstatus; /* 0x230 */ + uint32 gci_seciout_txstatus; /* 0x234 */ + uint32 gci_seciout_txbrstatus; /* 0x238 */ + uint32 wlan_mem_info; /* 0x23C */ + uint32 wlan_bankxinfo; /* 0x240 */ + uint32 bt_smem_select; /* 0x244 */ + uint32 bt_smem_stby; /* 0x248 */ + uint32 bt_smem_status; /* 0x24C */ + uint32 wlan_bankxactivepda; /* 0x250 */ + uint32 wlan_bankxsleeppda; /* 0x254 */ + uint32 wlan_bankxkill; /* 0x258 */ + uint32 PAD[PADSZ(0x25c, 0x268)]; /* 0x25c-0x268 */ + uint32 bt_smem_control0; /* 0x26C */ + uint32 bt_smem_control1; /* 0x270 */ + uint32 PAD[PADSZ(0x274, 0x2fc)]; /* 0x274-0x2fc */ + uint32 gci_chipid; /* 0x300 */ + uint32 PAD[PADSZ(0x304, 0x30c)]; /* 0x304-0x30c */ + uint32 otpstatus; /* 0x310 */ + uint32 otpcontrol; /* 0x314 */ + uint32 otpprog; /* 0x318 */ + uint32 otplayout; /* 0x31c */ + uint32 otplayoutextension; /* 0x320 */ + uint32 otpcontrol1; /* 0x324 */ + uint32 otpprogdata; /* 0x328 */ + uint32 PAD[PADSZ(0x32c, 0x3f8)]; /* 0x32c-0x3f8 */ + uint32 otpECCstatus; /* 0x3FC */ + uint32 PAD[PADSZ(0x400, 0xbfc)]; /* 0x400-0xbfc */ + uint32 lhl_core_capab_adr; /* 0xC00 */ + uint32 lhl_main_ctl_adr; /* 0xC04 */ + uint32 lhl_pmu_ctl_adr; /* 0xC08 */ + uint32 lhl_extlpo_ctl_adr; /* 0xC0C */ + uint32 lpo_ctl_adr; /* 0xC10 */ + uint32 lhl_lpo2_ctl_adr; /* 0xC14 */ + uint32 lhl_osc32k_ctl_adr; /* 0xC18 */ + uint32 lhl_clk_status_adr; /* 0xC1C */ + uint32 lhl_clk_det_ctl_adr; /* 0xC20 */ + uint32 lhl_clk_sel_adr; /* 0xC24 */ + uint32 hidoff_cnt_adr[2]; /* 0xC28-0xC2C */ + uint32 lhl_autoclk_ctl_adr; /* 0xC30 */ + uint32 PAD; /* reserved */ + uint32 lhl_hibtim_adr; /* 0xC38 */ + uint32 lhl_wl_ilp_val_adr; /* 0xC3C */ + uint32 lhl_wl_armtim0_intrp_adr; /* 0xC40 */ + uint32 lhl_wl_armtim0_st_adr; /* 0xC44 */ + uint32 lhl_wl_armtim0_adr; /* 0xC48 */ + uint32 PAD[PADSZ(0xc4c, 0xc6c)]; /* 0xC4C-0xC6C */ uint32 lhl_wl_mactim0_intrp_adr; /* 0xC70 */ uint32 lhl_wl_mactim0_st_adr; /* 0xC74 */ uint32 lhl_wl_mactim_int0_adr; /* 0xC78 */ @@ -170,43 +175,65 @@ typedef volatile struct { uint32 lhl_wl_mactim1_st_adr; /* 0xC84 */ uint32 lhl_wl_mactim_int1_adr; /* 0xC88 */ uint32 lhl_wl_mactim_frac1_adr; /* 0xC8C */ - uint32 PAD[8]; /* 0xC90-0xCAC */ - uint32 gpio_int_en_port_adr[4]; /* 0xCB0-0xCBC */ - uint32 gpio_int_st_port_adr[4]; /* 0xCC0-0xCCC */ - uint32 gpio_ctrl_iocfg_p_adr[64]; /* 0xCD0-0xDCC */ - uint32 gpio_gctrl_iocfg_p0_p39_adr; /* 0xDD0 */ - uint32 gpio_gdsctrl_iocfg_p0_p25_p30_p39_adr; /* 0xDD4 */ - uint32 gpio_gdsctrl_iocfg_p26_p29_adr; /* 0xDD8 */ - uint32 PAD[8]; /* 0xDDC-0xDF8 */ - uint32 lhl_gpio_din0_adr; /* 0xDFC */ - uint32 lhl_gpio_din1_adr; /* 0xE00 */ - uint32 lhl_wkup_status_adr; /* 0xE04 */ - uint32 lhl_ctl_adr; /* 0xE08 */ - uint32 lhl_adc_ctl_adr; /* 0xE0C */ - uint32 lhl_qdxyz_in_dly_adr; /* 0xE10 */ - uint32 lhl_optctl_adr; /* 0xE14 */ - uint32 lhl_optct2_adr; /* 0xE18 */ - uint32 lhl_scanp_cntr_init_val_adr; /* 0xE1C */ - uint32 lhl_opt_togg_val_adr[6]; /* 0xE20-0xE34 */ - uint32 lhl_optx_smp_val_adr; /* 0xE38 */ - uint32 lhl_opty_smp_val_adr; /* 0xE3C */ - uint32 lhl_optz_smp_val_adr; /* 0xE40 */ - uint32 lhl_hidoff_keepstate_adr[3]; /* 0xE44-0xE4C */ - uint32 lhl_bt_slmboot_ctl0_adr[4]; /* 0xE50-0xE5C */ - uint32 lhl_wl_fw_ctl; /* 0xE60 */ - uint32 lhl_wl_hw_ctl_adr[2]; /* 0xE64-0xE68 */ - uint32 lhl_bt_hw_ctl_adr; /* 0xE6C */ - uint32 lhl_top_pwrseq_en_adr; /* 0xE70 */ - uint32 lhl_top_pwrdn_ctl_adr; /* 0xE74 */ - uint32 lhl_top_pwrup_ctl_adr; /* 0xE78 */ - uint32 lhl_top_pwrseq_ctl_adr; /* 0xE7C */ - uint32 lhl_top_pwrdn2_ctl_adr; /* 0xE80 */ - uint32 lhl_top_pwrup2_ctl_adr; /* 0xE84 */ - uint32 wpt_regon_intrp_cfg_adr; /* 0xE88 */ - uint32 bt_regon_intrp_cfg_adr; /* 0xE8C */ - uint32 wl_regon_intrp_cfg_adr; /* 0xE90 */ - uint32 regon_intrp_st_adr; /* 0xE94 */ - uint32 regon_intrp_en_adr; /* 0xE98 */ + uint32 PAD[PADSZ(0xc90, 0xcac)]; /* 0xC90-0xCAC */ + uint32 gpio_int_en_port_adr[4]; /* 0xCB0-0xCBC */ + uint32 gpio_int_st_port_adr[4]; /* 0xCC0-0xCCC */ + uint32 gpio_ctrl_iocfg_p_adr[40]; /* 0xCD0-0xD6C */ + uint32 lhl_lp_up_ctl1_adr; /* 0xd70 */ + uint32 lhl_lp_dn_ctl1_adr; /* 0xd74 */ + uint32 PAD[PADSZ(0xd78, 0xdb4)]; /* 0xd78-0xdb4 */ + uint32 lhl_sleep_timer_adr; /* 0xDB8 */ + uint32 lhl_sleep_timer_ctl_adr; /* 0xDBC */ + uint32 lhl_sleep_timer_load_val_adr; /* 0xDC0 */ + uint32 lhl_lp_main_ctl_adr; /* 0xDC4 */ + uint32 lhl_lp_up_ctl_adr; /* 0xDC8 */ + uint32 lhl_lp_dn_ctl_adr; /* 0xDCC */ + uint32 gpio_gctrl_iocfg_p0_p39_adr; /* 0xDD0 */ + uint32 gpio_gdsctrl_iocfg_p0_p25_p30_p39_adr; /* 0xDD4 */ + uint32 gpio_gdsctrl_iocfg_p26_p29_adr; /* 0xDD8 */ + uint32 PAD[PADSZ(0xddc, 0xdf8)]; /* 0xDDC-0xDF8 */ + uint32 lhl_gpio_din0_adr; /* 0xDFC */ + uint32 lhl_gpio_din1_adr; /* 0xE00 */ + uint32 lhl_wkup_status_adr; /* 0xE04 */ + uint32 lhl_ctl_adr; /* 0xE08 */ + uint32 lhl_adc_ctl_adr; /* 0xE0C */ + uint32 lhl_qdxyz_in_dly_adr; /* 0xE10 */ + uint32 lhl_optctl_adr; /* 0xE14 */ + uint32 lhl_optct2_adr; /* 0xE18 */ + uint32 lhl_scanp_cntr_init_val_adr; /* 0xE1C */ + uint32 lhl_opt_togg_val_adr[6]; /* 0xE20-0xE34 */ + uint32 lhl_optx_smp_val_adr; /* 0xE38 */ + uint32 lhl_opty_smp_val_adr; /* 0xE3C */ + uint32 lhl_optz_smp_val_adr; /* 0xE40 */ + uint32 lhl_hidoff_keepstate_adr[3]; /* 0xE44-0xE4C */ + uint32 lhl_bt_slmboot_ctl0_adr[4]; /* 0xE50-0xE5C */ + uint32 lhl_wl_fw_ctl; /* 0xE60 */ + uint32 lhl_wl_hw_ctl_adr[2]; /* 0xE64-0xE68 */ + uint32 lhl_bt_hw_ctl_adr; /* 0xE6C */ + uint32 lhl_top_pwrseq_en_adr; /* 0xE70 */ + uint32 lhl_top_pwrdn_ctl_adr; /* 0xE74 */ + uint32 lhl_top_pwrup_ctl_adr; /* 0xE78 */ + uint32 lhl_top_pwrseq_ctl_adr; /* 0xE7C */ + uint32 lhl_top_pwrdn2_ctl_adr; /* 0xE80 */ + uint32 lhl_top_pwrup2_ctl_adr; /* 0xE84 */ + uint32 wpt_regon_intrp_cfg_adr; /* 0xE88 */ + uint32 bt_regon_intrp_cfg_adr; /* 0xE8C */ + uint32 wl_regon_intrp_cfg_adr; /* 0xE90 */ + uint32 regon_intrp_st_adr; /* 0xE94 */ + uint32 regon_intrp_en_adr; /* 0xE98 */ + uint32 PAD[PADSZ(0xe9c, 0xeb4)]; /* 0xe9c-0xeb4 */ + uint32 lhl_lp_main_ctl1_adr; /* 0xeb8 */ + uint32 lhl_lp_up_ctl2_adr; /* 0xebc */ + uint32 lhl_lp_dn_ctl2_adr; /* 0xec0 */ + uint32 lhl_lp_up_ctl3_adr; /* 0xec4 */ + uint32 lhl_lp_dn_ctl3_adr; /* 0xec8 */ + uint32 PAD[PADSZ(0xecc, 0xed8)]; /* 0xecc-0xed8 */ + uint32 lhl_lp_main_ctl2_adr; /* 0xedc */ + uint32 lhl_lp_up_ctl4_adr; /* 0xee0 */ + uint32 lhl_lp_dn_ctl4_adr; /* 0xee4 */ + uint32 lhl_lp_up_ctl5_adr; /* 0xee8 */ + uint32 lhl_lp_dn_ctl5_adr; /* 0xeec */ + } gciregs_t; #define GCI_CAP0_REV_MASK 0x000000ff @@ -241,8 +268,6 @@ typedef volatile struct { #define WLAN_MEM_INFO_REG_NUMD11MACSHM_MASK 0xFF000000 #define WLAN_MEM_INFO_REG_NUMD11MACSHM_SHIFT 24 - #endif /* !_LANGUAGE_ASSEMBLY && !__ASSEMBLY__ */ - #endif /* _SBGCI_H */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbhnddma.h b/drivers/net/wireless/bcmdhd_oo/include/sbhnddma.h index 6d10d6ad3940aac1b5842ccbcc8ba1c31cd3b85f..88a8844cc8d2ca1899e7430dde9f163616939119 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbhnddma.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbhnddma.h @@ -2,14 +2,14 @@ * Generic Broadcom Home Networking Division (HND) DMA engine HW interface * This supports the following chips: BCM42xx, 44xx, 47xx . * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: sbhnddma.h 615537 2016-01-28 00:46:34Z $ + * $Id: sbhnddma.h 694506 2017-04-13 05:10:05Z $ */ #ifndef _sbhnddma_h_ @@ -37,7 +37,6 @@ * a pair of channels is defined for convenience */ - /* 32 bits addressing */ /** dma registers per channel(xmt or rcv) */ @@ -117,6 +116,7 @@ typedef volatile struct { #define DMA_PC_4 1 #define DMA_PC_8 2 #define DMA_PC_16 3 +#define DMA_PC_32 4 /* others: reserved */ /** Prefetch threshold */ @@ -278,13 +278,12 @@ typedef volatile struct { #define D64_DEF_USBBURSTLEN 2 #define D64_DEF_SDIOBURSTLEN 1 - #ifndef D64_USBBURSTLEN #define D64_USBBURSTLEN DMA_BL_64 -#endif +#endif // endif #ifndef D64_SDIOBURSTLEN #define D64_SDIOBURSTLEN DMA_BL_32 -#endif +#endif // endif /* transmit channel control */ #define D64_XC_XE 0x00000001 /**< transmit enable */ @@ -304,6 +303,8 @@ typedef volatile struct { #define D64_XC_PC_SHIFT 21 #define D64_XC_PT_MASK 0x03000000 /**< Prefetch threshold */ #define D64_XC_PT_SHIFT 24 +#define D64_XC_CO_MASK 0x04000000 /**< coherent transactions for descriptors */ +#define D64_XC_CO_SHIFT 26 /* transmit descriptor table pointer */ #define D64_XP_LD_MASK 0x00001fff /**< last valid descriptor */ @@ -337,6 +338,8 @@ typedef volatile struct { #define D64_RC_SHIFT 9 /**< separate rx header descriptor enable */ #define D64_RC_OC 0x00000400 /**< overflow continue */ #define D64_RC_PD 0x00000800 /**< parity check disable */ +#define D64_RC_WAITCMP_MASK 0x00001000 +#define D64_RC_WAITCMP_SHIFT 12 #define D64_RC_SA 0x00002000 /**< select active */ #define D64_RC_GE 0x00004000 /**< Glom enable */ #define D64_RC_AE 0x00030000 /**< address extension bits */ @@ -347,8 +350,10 @@ typedef volatile struct { #define D64_RC_PC_SHIFT 21 #define D64_RC_PT_MASK 0x03000000 /**< Prefetch threshold */ #define D64_RC_PT_SHIFT 24 -#define D64_RC_WAITCMP_MASK 0x00001000 -#define D64_RC_WAITCMP_SHIFT 12 +#define D64_RC_CO_MASK 0x04000000 /**< coherent transactions for descriptors */ +#define D64_RC_CO_SHIFT 26 +#define D64_RC_ROEXT_MASK 0x08000000 /**< receive frame offset extension bit */ +#define D64_RC_ROEXT_SHIFT 27 /* flags for dma controller */ #define DMA_CTRL_PEN (1 << 0) /**< partity enable */ @@ -359,6 +364,15 @@ typedef volatile struct { #define DMA_CTRL_DMA_AVOIDANCE_WAR (1 << 5) /**< DMA avoidance WAR for 4331 */ #define DMA_CTRL_RXSINGLE (1 << 6) /**< always single buffer */ #define DMA_CTRL_SDIO_RXGLOM (1 << 7) /**< DMA Rx glome is enabled */ +#define DMA_CTRL_DESC_ONLY_FLAG (1 << 8) /**< For DMA which posts only descriptors, + * no packets + */ +#define DMA_CTRL_DESC_CD_WAR (1 << 9) /**< WAR for descriptor only DMA's CD not being + * updated correctly by HW in CT mode. + */ +#define DMA_CTRL_CS (1 << 10) /* channel switch enable */ +#define DMA_CTRL_ROEXT (1 << 11) /* receive frame offset extension support */ +#define DMA_CTRL_RX_ALIGN_8BYTE (1 << 12) /* RXDMA address 8-byte aligned for 43684A0 */ /* receive descriptor table pointer */ #define D64_RP_LD_MASK 0x00001fff /**< last valid descriptor */ @@ -400,6 +414,7 @@ typedef volatile struct { /* descriptor control flags 1 */ #define D64_CTRL_COREFLAGS 0x0ff00000 /**< core specific flags */ +#define D64_CTRL1_COHERENT ((uint32)1 << 17) /* cache coherent per transaction */ #define D64_CTRL1_NOTPCIE ((uint32)1 << 18) /**< buirst size control */ #define D64_CTRL1_EOT ((uint32)1 << 28) /**< end of descriptor table */ #define D64_CTRL1_IOC ((uint32)1 << 29) /**< interrupt on completion */ @@ -407,7 +422,8 @@ typedef volatile struct { #define D64_CTRL1_SOF ((uint32)1 << 31) /**< start of frame */ /* descriptor control flags 2 */ -#define D64_CTRL2_BC_MASK 0x00007fff /**< buffer byte count. real data len must <= 16KB */ +#define D64_CTRL2_MAX_LEN 0x0000fff7 /* Max transfer length (buffer byte count) <= 65527 */ +#define D64_CTRL2_BC_MASK 0x0000ffff /**< mask for buffer byte count */ #define D64_CTRL2_AE 0x00030000 /**< address extension bits */ #define D64_CTRL2_AE_SHIFT 16 #define D64_CTRL2_PARITY 0x00040000 /* parity bit */ @@ -418,8 +434,12 @@ typedef volatile struct { #define D64_RX_FRM_STS_LEN 0x0000ffff /**< frame length mask */ #define D64_RX_FRM_STS_OVFL 0x00800000 /**< RxOverFlow */ #define D64_RX_FRM_STS_DSCRCNT 0x0f000000 /**< no. of descriptors used - 1, d11corerev >= 22 */ +#define D64_RX_FRM_STS_DSCRCNT_SHIFT 24 /* Shift for no .of dma descriptor field */ #define D64_RX_FRM_STS_DATATYPE 0xf0000000 /**< core-dependent data type */ +#define BCM_D64_CTRL2_BOUND_DMA_LENGTH(len) \ +(((len) > D64_CTRL2_MAX_LEN) ? D64_CTRL2_MAX_LEN : (len)) + /** receive frame status */ typedef volatile struct { uint16 len; diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbpcmcia.h b/drivers/net/wireless/bcmdhd_oo/include/sbpcmcia.h index 0ffc97be1a488dcf3e74e445efaa4ca7bee0a360..9dec294e63c346c717a4058a72150c3f97f35ce0 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbpcmcia.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbpcmcia.h @@ -1,14 +1,14 @@ /* * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: sbpcmcia.h 616054 2016-01-29 13:22:24Z $ + * $Id: sbpcmcia.h 647676 2016-07-07 02:59:05Z $ */ #ifndef _SBPCMCIA_H @@ -60,13 +60,11 @@ #define COR_BLREN 0x01 #define COR_FUNEN 0x01 - #define PCICIA_FCSR (2 / 2) #define PCICIA_PRR (4 / 2) #define PCICIA_SCR (6 / 2) #define PCICIA_ESR (8 / 2) - #define PCM_MEMOFF 0x0000 #define F0_MEMOFF 0x1000 #define F1_MEMOFF 0x2000 @@ -105,31 +103,31 @@ #define SRI_BLANK 0x04 #define SRI_OTP 0x80 - #define SROM16K_BANK_SEL_MASK (3 << 11) #define SROM16K_BANK_SHFT_MASK 11 #define SROM16K_ADDR_SEL_MASK ((1 << SROM16K_BANK_SHFT_MASK) - 1) - - +#define SROM_PRSNT_MASK 0x1 +#define SROM_SUPPORT_SHIFT_MASK 30 +#define SROM_SUPPORTED (0x1 << SROM_SUPPORT_SHIFT_MASK) +#define SROM_SIZE_MASK 0x00000006 +#define SROM_SIZE_2K 2 +#define SROM_SIZE_512 1 +#define SROM_SIZE_128 0 +#define SROM_SIZE_SHFT_MASK 1 /* Standard tuples we know about */ #define CISTPL_NULL 0x00 #define CISTPL_END 0xff /* End of the CIS tuple chain */ - #define CISTPL_BRCM_HNBU 0x80 - #define HNBU_BOARDREV 0x02 /* One byte board revision */ - #define HNBU_BOARDTYPE 0x1b /* 2 bytes; boardtype */ - #define HNBU_HNBUCIS 0x1d /* what follows is proprietary HNBU CIS format */ - /* sbtmstatelow */ #define SBTML_INT_ACK 0x40000 /* ack the sb interrupt */ #define SBTML_INT_EN 0x20000 /* enable sb interrupt */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbsdio.h b/drivers/net/wireless/bcmdhd_oo/include/sbsdio.h index ede8b5e2104087f4f39b1c0dddfb494ace31025f..942fc4bbf6747ab51955b9a33566c14af956fd55 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbsdio.h @@ -4,14 +4,14 @@ * * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,7 +27,7 @@ * * <> * - * $Id: sbsdio.h 514727 2014-11-12 03:02:48Z $ + * $Id: sbsdio.h 665717 2016-10-18 23:29:25Z $ */ #ifndef _SBSDIO_H @@ -89,11 +89,6 @@ #define SROM_BLANK 0x04 /* depreciated in corerev 6 */ #define SROM_OTP 0x80 /* OTP present */ -/* SBSDIO_CHIP_CTRL */ -#define SBSDIO_CHIP_CTRL_XTAL 0x01 /* or'd with onchip xtal_pu, - * 1: power on oscillator - * (for 4318 only) - */ /* SBSDIO_WATERMARK */ #define SBSDIO_WATERMARK_MASK 0x7f /* number of words - 1 for sd device * to wait before sending data to host diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd_oo/include/sbsdpcmdev.h index 8607d63579101eda22da45aa708175e4585329c9..78bd979a4606b449f3f89f567a26959556be53c0 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbsdpcmdev.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbsdpcmdev.h @@ -2,14 +2,14 @@ * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific * device core support * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: sbsdpcmdev.h 610395 2016-01-06 22:52:57Z $ + * $Id: sbsdpcmdev.h 616398 2016-02-01 09:37:52Z $ */ #ifndef _sbsdpcmdev_h_ @@ -38,7 +38,6 @@ #define PAD _XSTR(__LINE__) #endif /* PAD */ - typedef volatile struct { dma64regs_t xmt; /* dma tx */ uint32 PAD[2]; @@ -99,7 +98,9 @@ typedef volatile struct { /* synchronized access to registers in SDIO clock domain */ uint32 sdioaccess; /* SdioAccess, 0x050, rev8 */ - uint32 PAD[3]; + uint32 PAD[1]; + uint32 MiscHostAccessIntEn; + uint32 PAD[1]; /* PCMCIA frame control */ uint8 pcmciaframectrl; /* pcmciaFrameCtrl, 0x060, rev8 */ @@ -235,6 +236,7 @@ typedef volatile struct { #define SDA_F1_FBR_SPACE 0x100 /* sdioAccess F1 FBR register space */ #define SDA_F2_FBR_SPACE 0x200 /* sdioAccess F2 FBR register space */ #define SDA_F1_REG_SPACE 0x300 /* sdioAccess F1 core-specific register space */ +#define SDA_F3_FBR_SPACE 0x400 /* sdioAccess F3 FBR register space */ /* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */ #define SDA_CHIPCONTROLDATA 0x006 /* ChipControlData */ @@ -251,6 +253,13 @@ typedef volatile struct { #define SDA_SDIOWRFRAMEBCHIGH 0x01a /* SdioWrFrameBCHigh */ #define SDA_SDIORDFRAMEBCLOW 0x01b /* SdioRdFrameBCLow */ #define SDA_SDIORDFRAMEBCHIGH 0x01c /* SdioRdFrameBCHigh */ +#define SDA_MESBUSYCNTRL 0x01d /* mesBusyCntrl */ +#define SDA_WAKEUPCTRL 0x01e /* WakeupCtrl */ +#define SDA_SLEEPCSR 0x01f /* sleepCSR */ + +/* SDA_F1_REG_SPACE register bits */ +/* sleepCSR register */ +#define SDA_SLEEPCSR_KEEP_SDIO_ON 0x1 /* SDA_F2WATERMARK */ #define SDA_F2WATERMARK_MASK 0x7f /* F2Watermark Mask */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbsocram.h b/drivers/net/wireless/bcmdhd_oo/include/sbsocram.h index b2c018839788572315fdb884babb931669652e89..c78479eb8737bcb77beca22d212271e6a5886be6 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbsocram.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbsocram.h @@ -1,14 +1,14 @@ /* * BCM47XX Sonics SiliconBackplane embedded ram core * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: sbsocram.h 604712 2015-12-08 08:05:42Z $ + * $Id: sbsocram.h 619629 2016-02-17 18:37:56Z $ */ #ifndef _SBSOCRAM_H @@ -171,7 +171,7 @@ typedef volatile struct sbsocramregs { #define SOCRAM_BANKIDX_MEMTYPE_SHIFT 8 /* socram bankinfo memtype */ #define SOCRAM_MEMTYPE_RAM 0 -#define SOCRAM_MEMTYPE_R0M 1 +#define SOCRAM_MEMTYPE_ROM 1 #define SOCRAM_MEMTYPE_DEVRAM 2 #define SOCRAM_BANKINFO_REG 0x40 @@ -201,5 +201,4 @@ typedef volatile struct sbsocramregs { #define SOCRAM_BANKINFO_SZBASE 8192 #define SOCRAM_BANKSIZE_SHIFT 13 /* SOCRAM_BANKINFO_SZBASE */ - #endif /* _SBSOCRAM_H */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sbsysmem.h b/drivers/net/wireless/bcmdhd_oo/include/sbsysmem.h index df26399b2d6111a6f95f914929acded82bf6ba0c..7c5ad99859ddac1320174cd6cf44eb64949c1907 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sbsysmem.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sbsysmem.h @@ -1,14 +1,14 @@ /* * SiliconBackplane System Memory core * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. diff --git a/drivers/net/wireless/bcmdhd_oo/include/sdio.h b/drivers/net/wireless/bcmdhd_oo/include/sdio.h index 8f77e4150e76ebe5309753c8755da8d5c1696227..d26c45bcc7c1e6ae008e470f70ad4883e2149e55 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sdio.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sdio.h @@ -2,14 +2,14 @@ * SDIO spec header file * Protocol and standard (common) device definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: sdio.h 644725 2016-06-21 12:26:04Z $ + * $Id: sdio.h 689948 2017-03-14 05:21:03Z $ */ #ifndef _SDIO_H @@ -284,8 +284,6 @@ typedef volatile struct { #define CARDREG_STATUS_BIT_IOCURRENTSTATE0 9 #define CARDREG_STATUS_BIT_FUN_NUM_ERROR 4 - - #define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */ #define SD_CMD_SEND_OPCOND 1 #define SD_CMD_MMC_SET_RCA 3 @@ -378,7 +376,6 @@ typedef volatile struct { #define SD_RSP_R5_ERRBITS 0xCB - /* ------------------------------------------------ * SDIO Commands and responses * @@ -450,7 +447,6 @@ typedef volatile struct { #define CMD52_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */ #define CMD52_RW_FLAG_S 31 - #define CMD53_BYTE_BLK_CNT_M BITFIELD_MASK(9) /* Bits [8:0] - Byte/Block Count of CMD53 */ #define CMD53_BYTE_BLK_CNT_S 0 #define CMD53_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */ @@ -541,7 +537,6 @@ typedef volatile struct { #define RSP1_OUT_OF_RANGE_M BITFIELD_MASK(1) /* Bit 31 - Cmd arg was out of range */ #define RSP1_OUT_OF_RANGE_S 31 - #define RSP5_DATA_M BITFIELD_MASK(8) /* Bits [0:7] - data */ #define RSP5_DATA_S 0 #define RSP5_FLAGS_M BITFIELD_MASK(8) /* Bit [15:8] - Rsp flags */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/sdioh.h b/drivers/net/wireless/bcmdhd_oo/include/sdioh.h index f37c5f62aef7056b6e264604849687c43501c5a2..6229af9819d6060ed1312ec785502fd914bb3225 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sdioh.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sdioh.h @@ -2,14 +2,14 @@ * SDIO Host Controller Spec header file * Register map and definitions for the Standard Host Controller * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -96,7 +96,6 @@ #define SD3_Tuning_Info_Register 0x0EC #define SD3_WL_BT_reset_register 0x0F0 - /* preset value indices */ #define SD3_PRESETVAL_INITIAL_IX 0 #define SD3_PRESETVAL_DESPEED_IX 1 @@ -140,7 +139,6 @@ #define SDIO_OCR_READ_FAIL (2) - #define CAP_ASYNCINT_SUP_M BITFIELD_MASK(1) #define CAP_ASYNCINT_SUP_S 29 diff --git a/drivers/net/wireless/bcmdhd_oo/include/sdiovar.h b/drivers/net/wireless/bcmdhd_oo/include/sdiovar.h index 09be5c6df78945eb033d93cc4a9e98f4dfdcbc3f..c28eccfb1731bf4fa4f9a25383f70c1f5ab53b19 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/sdiovar.h +++ b/drivers/net/wireless/bcmdhd_oo/include/sdiovar.h @@ -2,14 +2,14 @@ * Structure used by apps whose drivers access SDIO drivers. * Pulled out separately so dhdu and wlu can both use it. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: sdiovar.h 610006 2016-01-06 01:38:47Z $ + * $Id: sdiovar.h 660496 2016-09-20 19:28:50Z $ */ #ifndef _sdiovar_h_ @@ -33,10 +33,6 @@ #include -/* require default structure packing */ -#define BWL_DEFAULT_PACKING -#include - typedef struct sdreg { int func; int offset; @@ -124,6 +120,4 @@ typedef struct wl_pwr_sdio_stats { sdio_bus_metrics_t sdio; /* stats from SDIO bus driver */ } wl_pwr_sdio_stats_t; -#include - #endif /* _sdiovar_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/siutils.h b/drivers/net/wireless/bcmdhd_oo/include/siutils.h index 2afca25492509c901e5899598202885cb2b6aa8c..547998c228edcd26d606a6311d7024760294d7e1 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/siutils.h +++ b/drivers/net/wireless/bcmdhd_oo/include/siutils.h @@ -2,14 +2,14 @@ * Misc utility routines for accessing the SOC Interconnects * of Broadcom HNBU chips. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: siutils.h 668442 2016-11-03 08:42:43Z $ + * $Id: siutils.h 729061 2017-10-30 08:41:27Z $ */ #ifndef _siutils_h_ @@ -35,7 +35,6 @@ #include "wlioctl.h" #endif /* SR_DEBUG */ - #define WARM_BOOT 0xA0B0C0D0 #ifdef BCM_BACKPLANE_TIMEOUT @@ -80,6 +79,7 @@ struct si_pub { uint boardvendor; /**< board vendor */ uint boardflags; /**< board flags */ uint boardflags2; /**< board flags2 */ + uint boardflags4; /**< board flags4 */ uint chip; /**< chip number */ uint chiprev; /**< chip revision */ uint chippkg; /**< chip package option */ @@ -88,6 +88,9 @@ struct si_pub { uint socirev; /**< SOC interconnect rev */ bool pci_pr32414; int gcirev; /**< gci core rev */ + int lpflags; /**< low power flags */ + uint32 enum_base; /**< backplane address where the chipcommon core resides */ + #ifdef BCM_BACKPLANE_TIMEOUT si_axi_error_info_t * err_info; #endif /* BCM_BACKPLANE_TIMEOUT */ @@ -96,7 +99,7 @@ struct si_pub { /* for HIGH_ONLY driver, the si_t must be writable to allow states sync from BMAC to HIGH driver * for monolithic driver, it is readonly to prevent accident change */ -typedef const struct si_pub si_t; +typedef struct si_pub si_t; /* * Many of the routines below take an 'sih' handle as their first arg. @@ -163,7 +166,7 @@ typedef const struct si_pub si_t; #define PMUCTL_ENAB(sih) (BCMPMUCTL) #else #define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) -#endif +#endif // endif #if defined(BCMAOBENAB) #define AOB_ENAB(sih) (BCMAOBENAB) @@ -179,7 +182,7 @@ typedef const struct si_pub si_t; #else #define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) #define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) -#endif +#endif // endif typedef void (*gci_gpio_handler_t)(uint32 stat, void *arg); @@ -192,8 +195,6 @@ typedef void (*gci_gpio_handler_t)(uint32 stat, void *arg); #define GPIO_CTRL_7_6_EN_MASK 0xC0 #define GPIO_OUT_7_EN_MASK 0x80 - - /* CR4 specific defines used by the host driver */ #define SI_CR4_CAP (0x04) #define SI_CR4_BANKIDX (0x40) @@ -211,13 +212,19 @@ typedef void (*gci_gpio_handler_t)(uint32 stat, void *arg); #define SI_BPIND_1BYTE 0x1 #define SI_BPIND_2BYTE 0x3 #define SI_BPIND_4BYTE 0xF + +#define GET_GCI_OFFSET(sih, gci_reg) \ + (AOB_ENAB(sih)? OFFSETOF(gciregs_t, gci_reg) : OFFSETOF(chipcregs_t, gci_reg)) + +#define GET_GCI_CORE(sih) \ + (AOB_ENAB(sih)? si_findcoreidx(sih, GCI_CORE_ID, 0) : SI_CC_IDX) + #include /* === exported functions === */ extern si_t *si_attach(uint pcidev, osl_t *osh, volatile void *regs, uint bustype, void *sdh, char **vars, uint *varsz); extern si_t *si_kattach(osl_t *osh); extern void si_detach(si_t *sih); -extern bool si_pci_war16165(si_t *sih); extern volatile void * si_d11_switch_addrbase(si_t *sih, uint coreunit); extern uint si_corelist(si_t *sih, uint coreid[]); @@ -229,9 +236,10 @@ extern uint si_coreidx(si_t *sih); extern uint si_coreunit(si_t *sih); extern uint si_corevendor(si_t *sih); extern uint si_corerev(si_t *sih); +extern uint si_corerev_minor(si_t *sih); extern void *si_osh(si_t *sih); extern void si_setosh(si_t *sih, osl_t *osh); -extern uint si_backplane_access(si_t *sih, uint addr, uint size, +extern int si_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read); extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); extern uint si_pmu_corereg(si_t *sih, uint32 idx, uint regoff, uint mask, uint val); @@ -253,15 +261,14 @@ extern volatile void *si_setcore(si_t *sih, uint coreid, uint coreunit); extern volatile void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); extern int si_numaddrspaces(si_t *sih); -extern uint32 si_addrspace(si_t *sih, uint asidx); -extern uint32 si_addrspacesize(si_t *sih, uint asidx); +extern uint32 si_addrspace(si_t *sih, uint spidx, uint baidx); +extern uint32 si_addrspacesize(si_t *sih, uint spidx, uint baidx); extern void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); extern int si_corebist(si_t *sih); extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); extern void si_core_disable(si_t *sih, uint32 bits); extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); extern uint si_chip_hostif(si_t *sih); -extern bool si_read_pmu_autopll(si_t *sih); extern uint32 si_clock(si_t *sih); extern uint32 si_alp_clock(si_t *sih); /* returns [Hz] units */ extern uint32 si_ilp_clock(si_t *sih); /* returns [Hz] units */ @@ -310,18 +317,31 @@ extern uint32 si_gpio_int_enable(si_t *sih, bool enable); extern void si_gci_uart_init(si_t *sih, osl_t *osh, uint8 seci_mode); extern void si_gci_enable_gpio(si_t *sih, uint8 gpio, uint32 mask, uint32 value); extern uint8 si_gci_host_wake_gpio_init(si_t *sih); +extern uint8 si_gci_time_sync_gpio_init(si_t *sih); extern void si_gci_host_wake_gpio_enable(si_t *sih, uint8 gpio, bool state); +extern void si_gci_time_sync_gpio_enable(si_t *sih, uint8 gpio, bool state); extern void si_invalidate_second_bar0win(si_t *sih); +extern void si_gci_shif_config_wake_pin(si_t *sih, uint8 gpio_n, + uint8 wake_events, bool gci_gpio); +extern void si_shif_int_enable(si_t *sih, uint8 gpio_n, uint8 wake_events, bool enable); + /* GCI interrupt handlers */ extern void si_gci_handler_process(si_t *sih); +extern void si_enable_gpio_wake(si_t *sih, uint8 *wake_mask, uint8 *cur_status, uint8 gci_gpio, + uint32 pmu_cc2_mask, uint32 pmu_cc2_value); + /* GCI GPIO event handlers */ extern void *si_gci_gpioint_handler_register(si_t *sih, uint8 gpio, uint8 sts, gci_gpio_handler_t cb, void *arg); extern void si_gci_gpioint_handler_unregister(si_t *sih, void* gci_i); + extern uint8 si_gci_gpio_status(si_t *sih, uint8 gci_gpio, uint8 mask, uint8 value); +extern void si_gci_config_wake_pin(si_t *sih, uint8 gpio_n, uint8 wake_events, + bool gci_gpio); +extern void si_gci_free_wake_pin(si_t *sih, uint8 gpio_n); /* Wake-on-wireless-LAN (WOWL) */ extern bool si_pci_pmecap(si_t *sih); @@ -334,10 +354,9 @@ extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset); extern uint si_pcie_writereg(void *sih, uint addrtype, uint offset, uint val); extern void si_deepsleep_count(si_t *sih, bool arm_wakeup); - #ifdef BCMSDIO extern void si_sdio_init(si_t *sih); -#endif +#endif // endif extern uint16 si_d11_devid(si_t *sih); extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice, @@ -377,7 +396,6 @@ extern int si_cis_source(si_t *sih); #define TSMC_FAB12 0x2 /**< TSMC Fab12/Fab14 chip */ #define SMIC_FAB4 0x3 /**< SMIC Fab4 chip */ -extern int si_otp_fabid(si_t *sih, uint16 *fabid, bool rw); extern uint16 si_fabid(si_t *sih); extern uint16 si_chipid(si_t *sih); @@ -393,7 +411,6 @@ extern char *si_getdevpathvar(si_t *sih, const char *name); extern int si_getdevpathintvar(si_t *sih, const char *name); extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const char *name); - 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); @@ -415,23 +432,12 @@ extern int si_pci_fixcfg(si_t *sih); extern void si_chippkg_set(si_t *sih, uint); extern bool si_is_warmboot(void); -extern void si_chipcontrl_btshd0_4331(si_t *sih, bool on); extern void si_chipcontrl_restore(si_t *sih, uint32 val); extern uint32 si_chipcontrl_read(si_t *sih); -extern void si_chipcontrl_epa4331(si_t *sih, bool on); -extern void si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl); extern void si_chipcontrl_srom4360(si_t *sih, bool on); -extern void si_clk_srom4365(si_t *sih); -/* Enable BT-COEX & Ex-PA for 4313 */ -extern void si_epa_4313war(si_t *sih); +extern void si_srom_clk_set(si_t *sih); /**< for chips with fast BP clock */ extern void si_btc_enable_chipcontrol(si_t *sih); -/* BT/WL selection for 4313 bt combo >= P250 boards */ -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_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag); -extern void si_pmu_synth_pwrsw_4313_war(si_t *sih); -extern uint si_pll_reset(si_t *sih); /* === debug routines === */ extern bool si_taclear(si_t *sih, bool details); @@ -441,11 +447,11 @@ struct bcmstrbuf; extern int si_dump_pcieinfo(si_t *sih, struct bcmstrbuf *b); extern void si_dump_pmuregs(si_t *sih, struct bcmstrbuf *b); extern int si_dump_pcieregs(si_t *sih, struct bcmstrbuf *b); -#endif +#endif // endif #if defined(BCMDBG_PHYDUMP) extern void si_dumpregs(si_t *sih, struct bcmstrbuf *b); -#endif +#endif // endif extern uint32 si_ccreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint type); @@ -469,12 +475,13 @@ extern int si_pcie_configspace_cache(si_t *sih); extern int si_pcie_configspace_restore(si_t *sih); extern int si_pcie_configspace_get(si_t *sih, uint8 *buf, uint size); - #ifdef BCM_BACKPLANE_TIMEOUT extern const si_axi_error_info_t * si_get_axi_errlog_info(si_t *sih); extern void si_reset_axi_errlog_info(si_t * sih); #endif /* BCM_BACKPLANE_TIMEOUT */ +extern void si_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout, uint32 cid); + extern uint32 si_tcm_size(si_t *sih); extern bool si_has_flops(si_t *sih); @@ -488,12 +495,12 @@ extern uint32 si_gci_input(si_t *sih, uint reg); extern uint32 si_gci_int_enable(si_t *sih, bool enable); extern void si_gci_reset(si_t *sih); #ifdef BCMLTECOEX -extern void si_gci_seci_init(si_t *sih); extern void si_ercx_init(si_t *sih, uint32 ltecx_mux, uint32 ltecx_padnum, uint32 ltecx_fnsel, uint32 ltecx_gcigpio); #endif /* BCMLTECOEX */ +extern void si_gci_seci_init(si_t *sih); extern void si_wci2_init(si_t *sih, uint8 baudrate, uint32 ltecx_mux, uint32 ltecx_padnum, - uint32 ltecx_fnsel, uint32 ltecx_gcigpio); + uint32 ltecx_fnsel, uint32 ltecx_gcigpio, uint32 xtalfreq); extern bool si_btcx_wci2_init(si_t *sih); @@ -504,6 +511,7 @@ 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); extern uint32 si_gci_chipstatus(si_t *sih, uint reg); extern uint8 si_enable_device_wake(si_t *sih, uint8 *wake_status, uint8 *cur_status); +extern uint8 si_get_device_wake_opt(si_t *sih); extern void si_swdenable(si_t *sih, uint32 swdflag); extern uint8 si_enable_perst_wake(si_t *sih, uint8 *perst_wake_mask, uint8 *perst_cur_status); @@ -525,7 +533,6 @@ void si_update_masks(si_t *sih); void si_force_islanding(si_t *sih, bool enable); extern uint32 si_pmu_res_req_timer_clr(si_t *sih); extern void si_pmu_rfldo(si_t *sih, bool on); -extern void si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 spert_val); extern uint32 si_pcie_set_ctrlreg(si_t *sih, uint32 sperst_mask, uint32 spert_val); extern void si_pcie_ltr_war(si_t *sih); extern void si_pcie_hw_LTR_war(si_t *sih); @@ -541,9 +548,8 @@ extern uint32 si_raw_reg(si_t *sih, uint32 reg, uint32 val, uint32 wrire_req); #ifdef WLRSDB extern void si_d11rsdb_core_disable(si_t *sih, uint32 bits); extern void si_d11rsdb_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); -#endif - +extern void set_secondary_d11_core(si_t *sih, volatile void **secmap, volatile void **secwrap); +#endif // endif /* Macro to enable clock gating changes in different cores */ #define MEM_CLK_GATE_BIT 5 @@ -576,6 +582,22 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); OFFSETOF(pmuregs_t, member), mask, val): \ si_corereg(si, SI_CC_IDX, OFFSETOF(chipcregs_t, member), mask, val)) +/* Used only for the regs present in the pmu core and not present in the old cc core */ +#define PMU_REG_NEW(si, member, mask, val) \ + si_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \ + OFFSETOF(pmuregs_t, member), mask, val) + +#define GCI_REG(si, offset, mask, val) \ + (AOB_ENAB(si) ? \ + si_corereg(si, si_findcoreidx(si, GCI_CORE_ID, 0), \ + offset, mask, val): \ + si_corereg(si, SI_CC_IDX, offset, mask, val)) + +/* Used only for the regs present in the gci core and not present in the old cc core */ +#define GCI_REG_NEW(si, member, mask, val) \ + si_corereg(si, si_findcoreidx(si, GCI_CORE_ID, 0), \ + OFFSETOF(gciregs_t, member), mask, val) + #define LHL_REG(si, member, mask, val) \ si_corereg(si, si_findcoreidx(si, GCI_CORE_ID, 0), \ OFFSETOF(gciregs_t, member), mask, val) @@ -602,6 +624,7 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); #define GCI_CCTL_FGCA_OFFSET 20 /**< ForceGciClkAvail */ #define GCI_CCTL_FGCAV_OFFSET 21 /**< ForceGciClkAvailValue */ #define GCI_CCTL_SCS_OFFSET 24 /**< SeciClkStretch, 31:24 */ +#define GCI_CCTL_SCS 25 /* SeciClkStretch */ #define GCI_MODE_UART 0x0 #define GCI_MODE_SECI 0x1 @@ -622,11 +645,20 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); #define GCI_SECIIN_GCIGPIO_OFFSET 4 #define GCI_SECIIN_RXID2IP_OFFSET 8 +#define GCI_SECIIN_MODE_MASK 0x7 +#define GCI_SECIIN_GCIGPIO_MASK 0xF + #define GCI_SECIOUT_MODE_OFFSET 0 #define GCI_SECIOUT_GCIGPIO_OFFSET 4 #define GCI_SECIOUT_LOOPBACK_OFFSET 8 #define GCI_SECIOUT_SECIINRELATED_OFFSET 16 +#define GCI_SECIOUT_MODE_MASK 0x7 +#define GCI_SECIOUT_GCIGPIO_MASK 0xF +#define GCI_SECIOUT_SECIINRELATED_MASK 0x1 + +#define GCI_SECIOUT_SECIINRELATED 0x1 + #define GCI_SECIAUX_RXENABLE_OFFSET 0 #define GCI_SECIFIFO_RXENABLE_OFFSET 16 @@ -639,10 +671,27 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); #define GCI_GPIOIDX_OFFSET 16 #define GCI_LTECX_SECI_ID 0 /**< SECI port for LTECX */ +#define GCI_LTECX_TXCONF_EN_OFFSET 2 +#define GCI_LTECX_PRISEL_EN_OFFSET 3 /* To access per GCI bit registers */ #define GCI_REG_WIDTH 32 +/* number of event summary bits */ +#define GCI_EVENT_NUM_BITS 32 + +/* gci event bits per core */ +#define GCI_EVENT_BITS_PER_CORE 4 +#define GCI_EVENT_HWBIT_1 1 +#define GCI_EVENT_HWBIT_2 2 +#define GCI_EVENT_SWBIT_1 3 +#define GCI_EVENT_SWBIT_2 4 + +#define GCI_MBDATA_TOWLAN_POS 96 +#define GCI_MBACK_TOWLAN_POS 104 +#define GCI_WAKE_TOWLAN_PO 112 +#define GCI_SWREADY_POS 120 + /* GCI bit positions */ /* GCI [127:000] = WLAN [127:0] */ #define GCI_WLAN_IP_ID 0 @@ -650,6 +699,14 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); #define GCI_WLAN_PRIO_POS (GCI_WLAN_BEGIN + 4) #define GCI_WLAN_PERST_POS (GCI_WLAN_BEGIN + 15) +/* GCI [255:128] = BT [127:0] */ +#define GCI_BT_IP_ID 1 +#define GCI_BT_BEGIN 128 +#define GCI_BT_MBDATA_TOWLAN_POS (GCI_BT_BEGIN + GCI_MBDATA_TOWLAN_POS) +#define GCI_BT_MBACK_TOWLAN_POS (GCI_BT_BEGIN + GCI_MBACK_TOWLAN_POS) +#define GCI_BT_WAKE_TOWLAN_POS (GCI_BT_BEGIN + GCI_WAKE_TOWLAN_PO) +#define GCI_BT_SWREADY_POS (GCI_BT_BEGIN + GCI_SWREADY_POS) + /* GCI [639:512] = LTE [127:0] */ #define GCI_LTE_IP_ID 4 #define GCI_LTE_BEGIN 512 @@ -665,40 +722,34 @@ extern void set_secondary_d11_core(si_t *sih, void **secmap, void **secwrap); /* Bit offset of ECI bit no x in 32-bit words */ #define GCI_BITOFFSET(x) ((x)%GCI_REG_WIDTH) -/* End - GCI Macros */ +/* BT SMEM Control Register 0 */ +#define GCI_BT_SMEM_CTRL0_SUBCORE_ENABLE_PKILL (1 << 28) -#ifdef REROUTE_OOBINT -#define CC_OOB 0x0 -#define M2MDMA_OOB 0x1 -#define PMU_OOB 0x2 -#define D11_OOB 0x3 -#define SDIOD_OOB 0x4 -#define WLAN_OOB 0x5 -#define PMU_OOB_BIT 0x12 -#endif /* REROUTE_OOBINT */ +/* End - GCI Macros */ -#define GCI_REG(si, offset, mask, val) \ - (AOB_ENAB(si) ? \ - si_corereg(si, si_findcoreidx(si, GCI_CORE_ID, 0), \ - offset, mask, val): \ - si_corereg(si, SI_CC_IDX, offset, mask, val)) +#define AXI_OOB 0x7 extern void si_pll_sr_reinit(si_t *sih); extern void si_pll_closeloop(si_t *sih); void si_config_4364_d11_oob(si_t *sih, uint coreid); -extern void si_update_macclk_mul_fact(si_t *sih, uint mul_fact); -extern uint32 si_get_macclk_mul_fact(si_t *sih); extern void si_gci_set_femctrl(si_t *sih, osl_t *osh, bool set); extern void si_gci_set_femctrl_mask_ant01(si_t *sih, osl_t *osh, bool set); extern uint si_num_slaveports(si_t *sih, uint coreid); -extern uint32 si_get_slaveport_addr(si_t *sih, uint asidx, uint core_id, uint coreunit); -extern uint32 si_get_d11_slaveport_addr(si_t *sih, uint asidx, uint coreunit); +extern uint32 si_get_slaveport_addr(si_t *sih, uint spidx, uint baidx, + uint core_id, uint coreunit); +extern uint32 si_get_d11_slaveport_addr(si_t *sih, uint spidx, + uint baidx, uint coreunit); uint si_introff(si_t *sih); void si_intrrestore(si_t *sih, uint intr_val); void si_nvram_res_masks(si_t *sih, uint32 *min_mask, uint32 *max_mask); -uint32 si_xtalfreq(si_t *sih); +extern uint32 si_xtalfreq(si_t *sih); +extern uint8 si_getspurmode(si_t *sih); +extern uint32 si_get_openloop_dco_code(si_t *sih); +extern void si_set_openloop_dco_code(si_t *sih, uint32 openloop_dco_code); extern uint32 si_wrapper_dump_buf_size(si_t *sih); extern uint32 si_wrapper_dump_binary(si_t *sih, uchar *p); +extern uint32 si_wrapper_dump_last_timeout(si_t *sih, uint32 *error, uint32 *core, uint32 *ba, + uchar *p); /* SR Power Control */ extern uint32 si_srpwr_request(si_t *sih, uint32 mask, uint32 val); @@ -707,14 +758,12 @@ extern uint32 si_srpwr_stat(si_t *sih); extern uint32 si_srpwr_domain(si_t *sih); /* SR Power Control */ -#ifdef BCMSRPWR /* No capabilities bit so using chipid for now */ - #define SRPWR_CAP(sih) (\ - (CHIPID(sih->chip) == BCM4347_CHIP_ID) || \ - (0)) +#define SRPWR_CAP(sih) (BCM4347_CHIP(sih->chip) || BCM4369_CHIP(sih->chip)) +#ifdef BCMSRPWR extern bool _bcmsrpwr; - #if defined(WL_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) + #if defined(ROM_ENAB_RUNTIME_CHECK) || !defined(DONGLEBUILD) #define SRPWR_ENAB() (_bcmsrpwr) #elif defined(BCMSRPWR_DISABLED) #define SRPWR_ENAB() (0) @@ -722,8 +771,17 @@ extern uint32 si_srpwr_domain(si_t *sih); #define SRPWR_ENAB() (1) #endif #else - #define SRPWR_CAP(sih) (0) #define SRPWR_ENAB() (0) #endif /* BCMSRPWR */ +uint32 si_enum_base(uint devid); + +extern uint8 si_lhl_ps_mode(si_t *sih); + +#ifdef UART_TRAP_DBG +void ai_dump_APB_Bridge_registers(si_t *sih); +#endif /* UART_TRAP_DBG */ + +void si_clrirq_idx(si_t *sih, uint core_idx); + #endif /* _siutils_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/typedefs.h b/drivers/net/wireless/bcmdhd_oo/include/typedefs.h index aed3ace9155305d5fbd94f95fa019c3e5c954ca3..47062d73a0fdb9b1316b6c71285d49b560ecee8c 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/typedefs.h +++ b/drivers/net/wireless/bcmdhd_oo/include/typedefs.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -14,7 +14,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. @@ -22,7 +22,7 @@ * * <> * - * $Id: typedefs.h 639587 2016-05-24 06:44:44Z $ + * $Id: typedefs.h 672943 2016-11-30 08:54:06Z $ */ #ifndef _TYPEDEFS_H_ @@ -62,23 +62,21 @@ #define TYPEDEF_BOOL #ifndef FALSE #define FALSE false -#endif +#endif // endif #ifndef TRUE #define TRUE true -#endif +#endif // endif #else /* ! __cplusplus */ - #endif /* ! __cplusplus */ +#if !defined(TYPEDEF_UINTPTR) #if defined(__LP64__) #define TYPEDEF_UINTPTR typedef unsigned long long int uintptr; -#endif - - - +#endif // endif +#endif /* TYPEDEF_UINTPTR */ /* float_t types conflict with the same typedefs from the standard ANSI-C ** math.h header file. Don't re-typedef them here. @@ -86,15 +84,11 @@ typedef unsigned long long int uintptr; #if defined(_NEED_SIZE_T_) typedef long unsigned int size_t; -#endif - - - - +#endif // endif #if defined(__sparc__) #define TYPEDEF_ULONG -#endif +#endif // endif /* * If this is either a Linux hybrid build or the per-port code of a hybrid build @@ -118,11 +112,10 @@ typedef long unsigned int size_t; #include #ifdef noinline_for_stack #define TYPEDEF_BOOL -#endif +#endif // endif #endif /* == 2.6.18 */ #endif /* __KERNEL__ */ - /* Do not support the (u)int64 types with strict ansi for GNU C */ #if defined(__GNUC__) && defined(__STRICT_ANSI__) #define TYPEDEF_INT64 @@ -138,7 +131,7 @@ typedef long unsigned int size_t; #if defined(__STDC__) #define TYPEDEF_UINT64 -#endif +#endif // endif #endif /* __ICL */ @@ -156,15 +149,13 @@ typedef long unsigned int size_t; #endif /* linux && __KERNEL__ */ -#endif - +#endif // endif /* use the default typedefs in the next section of this file */ #define USE_TYPEDEF_DEFAULTS #endif /* SITE_TYPEDEFS */ - /* * Default Typedefs */ @@ -180,67 +171,67 @@ typedef /* @abstract@ */ unsigned char bool; #ifndef TYPEDEF_UCHAR typedef unsigned char uchar; -#endif +#endif // endif #ifndef TYPEDEF_USHORT typedef unsigned short ushort; -#endif +#endif // endif #ifndef TYPEDEF_UINT typedef unsigned int uint; -#endif +#endif // endif #ifndef TYPEDEF_ULONG typedef unsigned long ulong; -#endif +#endif // endif /* define [u]int8/16/32/64, uintptr */ #ifndef TYPEDEF_UINT8 typedef unsigned char uint8; -#endif +#endif // endif #ifndef TYPEDEF_UINT16 typedef unsigned short uint16; -#endif +#endif // endif #ifndef TYPEDEF_UINT32 typedef unsigned int uint32; -#endif +#endif // endif #ifndef TYPEDEF_UINT64 typedef unsigned long long uint64; -#endif +#endif // endif #ifndef TYPEDEF_UINTPTR typedef unsigned int uintptr; -#endif +#endif // endif #ifndef TYPEDEF_INT8 typedef signed char int8; -#endif +#endif // endif #ifndef TYPEDEF_INT16 typedef signed short int16; -#endif +#endif // endif #ifndef TYPEDEF_INT32 typedef signed int int32; -#endif +#endif // endif #ifndef TYPEDEF_INT64 typedef signed long long int64; -#endif +#endif // endif /* define float32/64, float_t */ #ifndef TYPEDEF_FLOAT32 typedef float float32; -#endif +#endif // endif #ifndef TYPEDEF_FLOAT64 typedef double float64; -#endif +#endif // endif /* * abstracted floating point type allows for compile time selection of @@ -254,7 +245,7 @@ typedef double float64; typedef float32 float_t; #else /* default to double precision floating point */ typedef float64 float_t; -#endif +#endif // endif #endif /* TYPEDEF_FLOAT_T */ @@ -262,23 +253,23 @@ typedef float64 float_t; #ifndef FALSE #define FALSE 0 -#endif +#endif // endif #ifndef TRUE #define TRUE 1 /* TRUE */ -#endif +#endif // endif #ifndef NULL #define NULL 0 -#endif +#endif // endif #ifndef OFF #define OFF 0 -#endif +#endif // endif #ifndef ON #define ON 1 /* ON = 1 */ -#endif +#endif // endif #define AUTO (-1) /* Auto = -1 */ @@ -286,8 +277,7 @@ typedef float64 float_t; #ifndef PTRSZ #define PTRSZ sizeof(char*) -#endif - +#endif // endif /* Detect compiler type. */ #if defined(__GNUC__) || defined(__lint) @@ -296,8 +286,7 @@ typedef float64 float_t; #define BWL_COMPILER_ARMCC #else #error "Unknown compiler!" -#endif - +#endif // endif #ifndef INLINE #if defined(BWL_COMPILER_MICROSOFT) @@ -308,7 +297,7 @@ typedef float64 float_t; #define INLINE __inline #else #define INLINE - #endif + #endif #endif /* INLINE */ #undef TYPEDEF_BOOL @@ -337,7 +326,7 @@ typedef float64 float_t; /* Avoid warning for discarded const or volatile qualifier in special cases (-Wcast-qual) */ #define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) -#else +#else /* !EDK_RELEASE_VERSION || (EDK_RELEASE_VERSION < 0x00020000) */ #include #include @@ -346,11 +335,8 @@ typedef float64 float_t; #ifdef stderr #undef stderr #define stderr stdout -#endif +#endif // endif -typedef UINT32 uint; -typedef UINT64 ulong; -typedef UINT16 ushort; typedef UINT8 uint8; typedef UINT16 uint16; typedef UINT32 uint32; @@ -364,11 +350,6 @@ typedef BOOLEAN bool; typedef unsigned char uchar; typedef UINTN uintptr; -typedef UINT8 u_char; -typedef UINT16 u_short; -typedef UINTN u_int; -typedef ULONGN u_long; - #define UNUSED_PARAMETER(x) (void)(x) #define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) #define INLINE diff --git a/drivers/net/wireless/bcmdhd_oo/include/vlan.h b/drivers/net/wireless/bcmdhd_oo/include/vlan.h index 4879eae5852825eff688cf44827a6cee2653f5c8..9f5fcdd63c6f5d69ba82b78097fe21ec08ca892b 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/vlan.h +++ b/drivers/net/wireless/bcmdhd_oo/include/vlan.h @@ -1,14 +1,14 @@ /* * 802.1Q VLAN protocol definitions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -32,14 +32,14 @@ #ifndef _TYPEDEFS_H_ #include -#endif +#endif // endif /* This marks the start of a packed structure section. */ #include #ifndef VLAN_VID_MASK #define VLAN_VID_MASK 0xfff /* low 12 bits are vlan id */ -#endif +#endif // endif #define VLAN_CFI_SHIFT 12 /* canonical format indicator bit */ #define VLAN_PRI_SHIFT 13 /* user priority */ @@ -84,7 +84,6 @@ struct dot3_mac_llc_snapvlan_header { #define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) - /* This marks the end of a packed structure section. */ #include diff --git a/drivers/net/wireless/bcmdhd_oo/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd_oo/include/wlfc_proto.h index b5ab529d4ae8ac79ebb48eed2e210f3107df4659..46846340cf9fdb69b4053b31e5a3e426f5dad8bf 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/wlfc_proto.h +++ b/drivers/net/wireless/bcmdhd_oo/include/wlfc_proto.h @@ -1,12 +1,12 @@ /* - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -14,7 +14,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. @@ -22,13 +22,12 @@ * * <> * - * $Id: wlfc_proto.h 735359 2017-12-08 10:56:04Z $ + * $Id: wlfc_proto.h 735303 2017-12-08 06:20:29Z $ * */ /** WL flow control for PROP_TXSTATUS. Related to host AMPDU reordering. */ - #ifndef __wlfc_proto_definitions_h__ #define __wlfc_proto_definitions_h__ @@ -81,37 +80,47 @@ --------------------------------------------------------------------------- */ -#define WLFC_CTL_TYPE_MAC_OPEN 1 -#define WLFC_CTL_TYPE_MAC_CLOSE 2 -#define WLFC_CTL_TYPE_MAC_REQUEST_CREDIT 3 -#define WLFC_CTL_TYPE_TXSTATUS 4 -#define WLFC_CTL_TYPE_PKTTAG 5 /** host<->dongle */ +typedef enum { + WLFC_CTL_TYPE_MAC_OPEN = 1, + WLFC_CTL_TYPE_MAC_CLOSE = 2, + WLFC_CTL_TYPE_MAC_REQUEST_CREDIT = 3, + WLFC_CTL_TYPE_TXSTATUS = 4, + WLFC_CTL_TYPE_PKTTAG = 5, /** host<->dongle */ + + WLFC_CTL_TYPE_MACDESC_ADD = 6, + WLFC_CTL_TYPE_MACDESC_DEL = 7, + WLFC_CTL_TYPE_RSSI = 8, -#define WLFC_CTL_TYPE_MACDESC_ADD 6 -#define WLFC_CTL_TYPE_MACDESC_DEL 7 -#define WLFC_CTL_TYPE_RSSI 8 + WLFC_CTL_TYPE_INTERFACE_OPEN = 9, + WLFC_CTL_TYPE_INTERFACE_CLOSE = 10, -#define WLFC_CTL_TYPE_INTERFACE_OPEN 9 -#define WLFC_CTL_TYPE_INTERFACE_CLOSE 10 + WLFC_CTL_TYPE_FIFO_CREDITBACK = 11, -#define WLFC_CTL_TYPE_FIFO_CREDITBACK 11 + WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP = 12, /** host->dongle */ + WLFC_CTL_TYPE_MAC_REQUEST_PACKET = 13, + WLFC_CTL_TYPE_HOST_REORDER_RXPKTS = 14, -#define WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP 12 /** host->dongle */ -#define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13 -#define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS 14 + WLFC_CTL_TYPE_TX_ENTRY_STAMP = 15, + WLFC_CTL_TYPE_RX_STAMP = 16, + WLFC_CTL_TYPE_TX_STATUS_STAMP = 17, /** obsolete */ -#define WLFC_CTL_TYPE_TX_ENTRY_STAMP 15 -#define WLFC_CTL_TYPE_RX_STAMP 16 -#define WLFC_CTL_TYPE_TX_STATUS_STAMP 17 /** obsolete */ + WLFC_CTL_TYPE_TRANS_ID = 18, + WLFC_CTL_TYPE_COMP_TXSTATUS = 19, -#define WLFC_CTL_TYPE_TRANS_ID 18 -#define WLFC_CTL_TYPE_COMP_TXSTATUS 19 + WLFC_CTL_TYPE_TID_OPEN = 20, + WLFC_CTL_TYPE_TID_CLOSE = 21, + WLFC_CTL_TYPE_UPD_FLR_WEIGHT = 22, + WLFC_CTL_TYPE_ENAB_FFSCH = 23, + WLFC_CTL_TYPE_UPDATE_FLAGS = 24, /* clear the flags set in flowring */ + WLFC_CTL_TYPE_CLEAR_SUPPR = 25, /* free the supression info in the flowring */ -#define WLFC_CTL_TYPE_TID_OPEN 20 -#define WLFC_CTL_TYPE_TID_CLOSE 21 + WLFC_CTL_TYPE_FLOWID_OPEN = 26, + WLFC_CTL_TYPE_FLOWID_CLOSE = 27, + WLFC_CTL_TYPE_FILLER = 255 +} wlfc_ctl_type_t; -#define WLFC_CTL_TYPE_FILLER 255 +#define WLFC_CTL_VALUE_LEN_FLOWID 2 #define WLFC_CTL_VALUE_LEN_MACDESC 8 /** handle, interface, MAC */ @@ -127,6 +136,14 @@ #define WLFC_CTL_VALUE_LEN_SEQ 2 +/* Reset the flags set for the corresponding flowring of the SCB which is de-inited */ +/* FLOW_RING_FLAG_LAST_TIM | FLOW_RING_FLAG_INFORM_PKTPEND | FLOW_RING_FLAG_PKT_REQ */ +#define WLFC_RESET_ALL_FLAGS 0 +#define WLFC_CTL_VALUE_LEN_FLAGS 7 /** flags, MAC */ + +/* free the data stored to be used for suppressed packets in future */ +#define WLFC_CTL_VALUE_LEN_SUPR 7 /** tid, MAC */ + /* The high bits of ratespec report in timestamp are used for various status */ #define WLFC_TSFLAGS_RX_RETRY (1 << 31) #define WLFC_TSFLAGS_PM_ENABLED (1 << 30) @@ -138,9 +155,9 @@ #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_PKTFLAG_PKTFROMHOST 0x01 #define WLFC_PKTFLAG_PKT_REQUESTED 0x02 +#define WLFC_PKTFLAG_PKT_SENDTOHOST 0x04 #define WL_TXSTATUS_STATUS_MASK 0xff /* allow 8 bits */ #define WL_TXSTATUS_STATUS_SHIFT 24 @@ -215,6 +232,15 @@ #define WL_SEQ_IS_AMSDU(x) (((x) >> WL_SEQ_AMSDU_SHIFT) & \ WL_SEQ_AMSDU_MASK) +/* indicates last_suppr_seq is valid */ +#define WL_SEQ_VALIDSUPPR_MASK 0x1 /* allow 1 bit */ +#define WL_SEQ_VALIDSUPPR_SHIFT 12 +#define WL_SEQ_SET_VALIDSUPPR(x, val) ((x) = \ + ((x) & ~(WL_SEQ_VALIDSUPPR_MASK << WL_SEQ_VALIDSUPPR_SHIFT)) | \ + (((val) & WL_SEQ_VALIDSUPPR_MASK) << WL_SEQ_VALIDSUPPR_SHIFT)) +#define WL_SEQ_GET_VALIDSUPPR(x) (((x) >> WL_SEQ_VALIDSUPPR_SHIFT) & \ + WL_SEQ_VALIDSUPPR_MASK) + #define WL_SEQ_FROMFW_MASK 0x1 /* allow 1 bit */ #define WL_SEQ_FROMFW_SHIFT 13 #define WL_SEQ_SET_FROMFW(x, val) ((x) = \ @@ -279,7 +305,6 @@ #define WLFC_PKTFLAG_CLR_PKTREQUESTED(x) (x) &= \ ~(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT) - #define WLFC_MAX_PENDING_DATALEN 120 /* host is free to discard the packet */ @@ -296,6 +321,12 @@ #define WLFC_CTL_PKTFLAG_DISCARD_NOACK 4 /* Firmware wrongly reported suppressed previously,now fixing to acked */ #define WLFC_CTL_PKTFLAG_SUPPRESS_ACKED 5 +/* Firmware send this packet expired, lifetime expiration */ +#define WLFC_CTL_PKTFLAG_EXPIRED 6 +/* Firmware drop this packet for any other reason */ +#define WLFC_CTL_PKTFLAG_DROPPED 7 +/* Firmware free this packet */ +#define WLFC_CTL_PKTFLAG_MKTFREE 8 #define WLFC_CTL_PKTFLAG_MASK (0x0f) /* For 4-bit mask with one extra bit */ #ifdef PROP_TXSTATUS_DEBUG @@ -347,8 +378,14 @@ #define WLFC_SET_REUSESEQ(x, val) ((x) = \ ((x) & ~(1 << WLFC_MODE_REUSESEQ_SHIFT)) | \ (((val) & 1) << WLFC_MODE_REUSESEQ_SHIFT)) + /** returns TRUE if 'd11 sequence reuse' has been agreed upon between host and dongle */ +#if defined(BCMPCIEDEV_ENABLED) && !defined(ROM_ENAB_RUNTIME_CHECK) +/* GET_REUSESEQ is always TRUE in pciedev */ +#define WLFC_GET_REUSESEQ(x) (TRUE) +#else #define WLFC_GET_REUSESEQ(x) (((x) >> WLFC_MODE_REUSESEQ_SHIFT) & 1) +#endif /* defined(BCMPCIEDEV_ENABLED) && !defined(ROM_ENAB_RUNTIME_CHECK) */ #define WLFC_MODE_REORDERSUPP_SHIFT 4 /* host reorder suppress pkt bit */ #define WLFC_SET_REORDERSUPP(x, val) ((x) = \ @@ -366,6 +403,9 @@ #define FLOW_RING_TIM_SET 7 #define FLOW_RING_TIM_RESET 8 #define FLOW_RING_FLUSH_TXFIFO 9 +#define FLOW_RING_GET_PKT_MAX 10 +#define FLOW_RING_RESET_WEIGHT 11 +#define FLOW_RING_UPD_PRIOMAP 12 /* bit 7, indicating if is TID(1) or AC(0) mapped info in tid field) */ #define PCIEDEV_IS_AC_TID_MAP_MASK 0x80 diff --git a/drivers/net/wireless/bcmdhd_oo/include/wlioctl.h b/drivers/net/wireless/bcmdhd_oo/include/wlioctl.h index 3eeefebc0c381565eb6ffc27d3ffeec075975b26..21ebcd50c1d4349e4b63a63b962d3bbeee92af68 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd_oo/include/wlioctl.h @@ -6,14 +6,14 @@ * * Definitions subject to change without notice. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -21,13 +21,15 @@ * 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: wlioctl.h 677952 2017-01-05 23:25:28Z $ + * $Id: wlioctl.h 738254 2017-12-27 22:33:17Z $ */ #ifndef _wlioctl_h_ @@ -44,6 +46,9 @@ #include <802.11s.h> #include <802.1d.h> #include +#ifdef WL11AX +#include <802.11ax.h> +#endif /* WL11AX */ #include #include #include @@ -51,6 +56,8 @@ #include #include +/* 11ax trigger frame format - versioning info */ +#define TRIG_FRAME_FORMAT_11AX_DRAFT_1P1 0 typedef struct { uint32 num; @@ -62,7 +69,15 @@ typedef struct { #define TPK_FTM_LEN 16 #ifndef INTF_NAME_SIZ #define INTF_NAME_SIZ 16 -#endif +#endif // endif + +#define WL_ASSOC_START_EVT_DATA_VERSION 1 + +typedef struct assoc_event_data { + uint32 version; + uint32 flags; + chanspec_t join_chspec; +} assoc_event_data_t; /**Used to send ioctls over the transport pipe */ typedef struct remote_ioctl { @@ -111,7 +126,6 @@ typedef struct { #define DFS_SCAN_S_SCAN_MODESW_INPROGRESS 4 #define DFS_SCAN_S_MAX 5 - #define ACTION_FRAME_SIZE 1800 typedef struct wl_action_frame { @@ -257,7 +271,6 @@ typedef struct ulp_shm_info { uint32 m_ulp_wakeind; } ulp_shm_info_t; - /* Legacy structure to help keep backward compatible wl tool and tray app */ #define LEGACY_WL_BSS_INFO_VERSION 107 /**< older version of wl_bss_info struct */ @@ -339,7 +352,6 @@ typedef struct wl_bss_info_108 { /* variable length Information Elements */ } wl_bss_info_108_t; - #define WL_BSS_INFO_VERSION 109 /**< current version of wl_bss_info struct */ /** @@ -387,20 +399,83 @@ typedef struct wl_bss_info { uint16 vht_mcsmap; /**< STA's Associated vhtmcsmap */ uint16 vht_mcsmap_prop; /**< STA's Associated prop vhtmcsmap */ uint16 vht_txmcsmap_prop; /**< prop VHT tx mcs prop */ - /* Add new fields here */ - /* variable length Information Elements */ -} wl_bss_info_t; +} wl_bss_info_v109_t; -#define WL_GSCAN_FULL_RESULT_VERSION 2 /* current version of wl_gscan_result_t struct */ -#define WL_GSCAN_INFO_FIXED_FIELD_SIZE (sizeof(wl_gscan_bss_info_t) - sizeof(wl_bss_info_t)) +/** + * BSS info structure + * Applications MUST CHECK ie_offset field and length field to access IEs and + * next bss_info structure in a vector (in wl_scan_results_t) + */ +typedef struct wl_bss_info_v109_1 { + uint32 version; /**< version field */ + uint32 length; /**< byte length of data in this record, + * starting at version and including IEs + */ + struct ether_addr BSSID; + uint16 beacon_period; /**< units are Kusec */ + uint16 capability; /**< Capability information */ + uint8 SSID_len; + uint8 SSID[32]; + uint8 bcnflags; /* additional flags w.r.t. beacon */ + struct { + uint32 count; /**< # rates in this set */ + uint8 rates[16]; /**< rates in 500kbps units w/hi bit set if basic */ + } rateset; /**< supported rates */ + chanspec_t chanspec; /**< chanspec for bss */ + uint16 atim_window; /**< units are Kusec */ + uint8 dtim_period; /**< DTIM period */ + uint8 accessnet; /* from beacon interwork IE (if bcnflags) */ + int16 RSSI; /**< receive signal strength (in dBm) */ + int8 phy_noise; /**< noise (in dBm) */ + uint8 n_cap; /**< BSS is 802.11N Capable */ + uint8 he_cap; /**< BSS is he capable */ + uint8 freespace1; /* make implicit padding explicit */ + 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 (802.11ac IE, VHT_CAP_MCS_MAP_*) */ + uint16 vht_txmcsmap; /**< VHT tx mcs map (802.11ac IE, VHT_CAP_MCS_MAP_*) */ + uint8 flags; /**< flags */ + uint8 vht_cap; /**< BSS is vht capable */ + uint8 reserved[2]; /**< Reserved for expansion of BSS properties */ + uint8 basic_mcs[MCSSET_LEN]; /**< 802.11N BSS required MCS set */ + + uint16 ie_offset; /**< offset at which IEs start, from beginning */ + uint16 freespace2; /* making implicit padding explicit */ + uint32 ie_length; /**< byte length of Information Elements */ + int16 SNR; /**< average SNR of during frame reception */ + uint16 vht_mcsmap; /**< STA's Associated vhtmcsmap */ + uint16 vht_mcsmap_prop; /**< STA's Associated prop vhtmcsmap */ + uint16 vht_txmcsmap_prop; /**< prop VHT tx mcs prop */ + uint32 he_mcsmap; /**< STA's Associated hemcsmap */ + uint32 he_rxmcsmap; /**< HE rx mcs map (802.11ax IE, HE_CAP_MCS_MAP_*) */ + uint32 he_txmcsmap; /**< HE tx mcs map (802.11ax IE, HE_CAP_MCS_MAP_*) */ +} wl_bss_info_v109_1_t; + +#ifndef WL_BSS_INFO_TYPEDEF_HAS_ALIAS +typedef wl_bss_info_v109_t wl_bss_info_t; +#endif // endif + +#define WL_GSCAN_FULL_RESULT_VERSION 2 /* current version of wl_gscan_result_t struct */ typedef struct wl_gscan_bss_info { uint32 timestamp[2]; - wl_bss_info_t info; + wl_bss_info_v109_t info; + /* Do not add any more members below, fixed */ + /* and variable length Information Elements to follow */ +} wl_gscan_bss_info_v2_t; + +typedef struct wl_gscan_bss_info_v3 { + uint32 timestamp[2]; + uint8 info[]; /* var length wl_bss_info_X structures */ /* Do not add any more members below, fixed */ /* and variable length Information Elements to follow */ -} wl_gscan_bss_info_t; +} wl_gscan_bss_info_v3_t; +#ifndef WL_BSS_INFO_TYPEDEF_HAS_ALIAS +typedef wl_gscan_bss_info_v2_t wl_gscan_bss_info_t; +#define WL_GSCAN_INFO_FIXED_FIELD_SIZE (sizeof(wl_gscan_bss_info_t) - sizeof(wl_bss_info_t)) +#endif // endif typedef struct wl_bsscfg { uint32 bsscfg_idx; @@ -432,6 +507,37 @@ typedef struct wl_bss_config { uint32 chanspec; } wl_bss_config_t; +/* Number of Bsscolor supported per core */ +#ifndef HE_MAX_BSSCOLOR_RES +#define HE_MAX_BSSCOLOR_RES 2 +#endif // endif + +#ifndef HE_MAX_STAID_PER_BSSCOLOR +#define HE_MAX_STAID_PER_BSSCOLOR 4 +#endif // endif + +/* BSSColor indices */ +#define BSSCOLOR0_IDX 0 +#define BSSCOLOR1_IDX 1 +#define HE_BSSCOLOR_MAX_VAL 63 + +/* STAID indices */ +#define STAID0_IDX 0 +#define STAID1_IDX 1 +#define STAID2_IDX 2 +#define STAID3_IDX 3 +#define HE_STAID_MAX_VAL 2047 + +typedef struct wl_bsscolor_info { + uint16 version; /**< structure version */ + uint16 length; /**< length of the bsscolor info */ + uint8 bsscolor_index; /**< bsscolor index 0-1 */ + uint8 bsscolor; /** 1 bit */ #define OCL_COREDOWN 0x80 /* Set if core is currently down */ +#define WL_OPS_CFG_VERSION_1 1 +/* Common IOVAR struct */ +typedef struct wl_ops_cfg_v1 { + uint16 version; + uint16 len; /* total length includes fixed fields and variable data[] */ + uint16 subcmd_id; /* subcommand id */ + uint16 padding; /* reserved / padding for 4 byte align */ + uint8 data[]; /* subcommand data; could be empty */ +} wl_ops_cfg_v1_t; + +/* subcommands ids */ +enum { + WL_OPS_CFG_SUBCMD_ENABLE = 0, /* OPS enable/disable mybss and obss + * for nav and plcp options + */ + WL_OPS_CFG_SUBCMD_MAX_SLEEP_DUR = 1, /* Max sleep duration used for OPS */ + WL_OPS_CFG_SUBCMD_RESET_STATS = 2 /* Reset stats part of ops_status + * on both slices + */ +}; + +#define WL_OPS_CFG_MASK 0xffff +#define WL_OPS_CFG_CAP_MASK 0xffff0000 +#define WL_OPS_CFG_CAP_SHIFT 16 /* Shift bits to locate the OPS CAP */ +#define WL_OPS_MAX_SLEEP_DUR 12500 /* max ops duration in us */ +#define WL_OPS_MINOF_MAX_SLEEP_DUR 512 /* minof max ops duration in us */ +#define WL_OPS_SUPPORTED_CFG (WL_OPS_MYBSS_PLCP_DUR | WL_OPS_MYBSS_NAV_DUR \ + | WL_OPS_OBSS_PLCP_DUR | WL_OPS_OBSS_NAV_DUR) +#define WL_OPS_DEFAULT_CFG WL_OPS_SUPPORTED_CFG + +/* WL_OPS_CFG_SUBCMD_ENABLE */ +typedef struct wl_ops_cfg_enable { + uint32 bits; /* selectively enable ops for mybss and obss */ +} wl_ops_cfg_enable_t; +/* Bits for WL_OPS_CFG_SUBCMD_ENABLE Parameter */ +#define WL_OPS_MYBSS_PLCP_DUR 0x1 /* OPS based on mybss 11b & 11n mixed HT frames + * PLCP header duration + */ +#define WL_OPS_MYBSS_NAV_DUR 0x2 /* OPS based on mybss RTS-CTS duration */ +#define WL_OPS_OBSS_PLCP_DUR 0x4 /* OPS based on obss 11b & 11n mixed HT frames + * PLCP header duration + */ +#define WL_OPS_OBSS_NAV_DUR 0x8 /* OPS based on obss RTS-CTS duration */ + +/* WL_OPS_CFG_SUBCMD_MAX_SLEEP_DUR */ +typedef struct wl_ops_cfg_max_sleep_dur { + uint32 val; /* maximum sleep duration (us) used for OPS */ +} wl_ops_cfg_max_sleep_dur_t; + +/* WL_OPS_CFG_SUBCMD_RESET_STATS */ +typedef struct wl_ops_cfg_reset_stats { + uint32 val; /* bitmap of slices, 0 means all slices */ +} wl_ops_cfg_reset_stats_t; + +#define WL_OPS_STATUS_VERSION_1 1 +#define OPS_DUR_HIST_BINS 5 /* number of bins used, 0-1, 1-2, 2-4, 4-8, >8 msec */ +typedef struct wl_ops_status_v1 { + uint16 version; + uint16 len; /* Total length including all fixed fields */ + uint8 slice_index; /* Slice for which status is reported */ + uint8 disable_obss; /* indicate if obss cfg is disabled */ + uint8 pad[2]; /* 4-byte alignment */ + uint32 disable_reasons; /* FW disable reasons */ + uint32 disable_duration; /* ops disable time(ms) due to disable reasons */ + uint32 applied_ops_config; /* currently applied ops config */ + uint32 partial_ops_dur; /* Total time (in usec) of partial ops duration */ + uint32 full_ops_dur; /* Total time (in usec) of full ops duration */ + uint32 count_dur_hist[OPS_DUR_HIST_BINS]; /* ops occurrence histogram */ + uint32 nav_cnt; /* number of times ops triggered based NAV duration */ + uint32 plcp_cnt; /* number of times ops triggered based PLCP duration */ + uint32 mybss_cnt; /* number of times mybss ops trigger */ + uint32 obss_cnt; /* number of times obss ops trigger */ + uint32 miss_dur_cnt; /* number of times ops couldn't happen + * due to insufficient duration + */ + uint32 miss_premt_cnt; /* number of times ops couldn't happen due + * to not meeting Phy preemption thresh + */ + uint32 max_dur_cnt; /* number of times ops did not trigger due to + * frames exceeding max sleep duration + */ + uint32 wake_cnt; /* number of ops miss due to wake reason */ + uint32 bcn_wait_cnt; /* number of ops miss due to waiting for bcn */ +} wl_ops_status_v1_t; +/* Bits for disable_reasons */ +#define OPS_DISABLED_HOST 0x01 /* Host has disabled through ops_cfg */ +#define OPS_DISABLED_UNASSOC 0x02 /* Disabled because the slice is in unassociated state */ +#define OPS_DISABLED_SCAN 0x04 /* Disabled because the slice is in scan state */ +#define OPS_DISABLED_BCN_MISS 0x08 /* Disabled because beacon missed for a duration */ /* * Join preference iovar value is an array of tuples. Each tuple has a one-byte type, @@ -2514,13 +2902,17 @@ typedef struct wl_bsstrans_roamthrottle { #define NFIFO 6 /**< # tx/rx fifopairs */ -#if defined(BCM_DMA_CT) && !defined(BCM_DMA_CT_DISABLED) +#if defined(BCM_AQM_DMA_DESC) && !defined(BCM_AQM_DMA_DESC_DISABLED) +#if defined(WL_MU_TX) && !defined(WL_MU_TX_DISABLED) #define NFIFO_EXT 32 /* 6 traditional FIFOs + 2 rsvd + 24 MU FIFOs */ +#else +#define NFIFO_EXT 10 /* 4EDCA + 4 TWT + 1 Mcast/Bcast + 1 Spare */ +#endif // endif #elif defined(WL11AX) && defined(WL11AX_TRIGGERQ_ENABLED) #define NFIFO_EXT 10 #else #define NFIFO_EXT NFIFO -#endif +#endif /* BCM_AQM_DMA_DESC && !BCM_AQM_DMA_DESC_DISABLED */ /* Reinit reason codes */ enum { @@ -2579,6 +2971,7 @@ enum { WL_REINIT_RC_TX_FIFO_SUSP = 51, WL_REINIT_RC_MAC_ENABLE = 52, WL_REINIT_RC_SCAN_STALLED = 53, + WL_REINIT_RC_PHY_HC = 54, WL_REINIT_RC_LAST /* This must be the last entry */ }; @@ -2588,6 +2981,7 @@ enum { #define WL_CNT_T_VERSION 30 /**< current version of wl_cnt_t struct */ #define WL_CNT_VERSION_6 6 +#define WL_CNT_VERSION_7 7 #define WL_CNT_VERSION_11 11 #define WL_CNT_VERSION_XTLV 30 @@ -2598,6 +2992,10 @@ enum { #define WLC_WITH_XTLV_CNT +/* Number of xtlv info as required to calculate subcounter offsets */ +#define WL_CNT_XTLV_ID_NUM 10 +#define WL_TLV_IOV_VER 1 + /** * tlv IDs uniquely identifies counter component * packed into wl_cmd_t container @@ -2606,10 +3004,149 @@ enum wl_cnt_xtlv_id { WL_CNT_XTLV_SLICE_IDX = 0x1, /**< Slice index */ WL_CNT_XTLV_WLC = 0x100, /**< WLC layer counters */ WL_CNT_XTLV_WLC_RINIT_RSN = 0x101, /**< WLC layer reinitreason extension */ + WL_CNT_XTLV_WLC_HE = 0x102, /* he counters */ WL_CNT_XTLV_CNTV_LE10_UCODE = 0x200, /**< wl counter ver < 11 UCODE MACSTAT */ WL_CNT_XTLV_LT40_UCODE_V1 = 0x300, /**< corerev < 40 UCODE MACSTAT */ WL_CNT_XTLV_GE40_UCODE_V1 = 0x400, /**< corerev >= 40 UCODE MACSTAT */ - WL_CNT_XTLV_GE64_UCODEX_V1 = 0x800 /* corerev >= 64 UCODEX MACSTAT */ + WL_CNT_XTLV_GE64_UCODEX_V1 = 0x800, /* corerev >= 64 UCODEX MACSTAT */ + WL_CNT_XTLV_GE80_UCODE_V1 = 0x900, /* corerev >= 80 UCODEX MACSTAT */ + WL_CNT_XTLV_GE80_TXFUNFL_UCODE_V1 = 0x1000 /* corerev >= 80 UCODEX MACSTAT */ +}; + +/* tlv IDs uniquely identifies periodic state component */ +enum wl_periodic_slice_state_xtlv_id { + WL_STATE_COMPACT_COUNTERS = 0x1, + WL_STATE_TXBF_COUNTERS = 0x2 +}; + +/* tlv IDs uniquely identifies periodic state component */ +enum wl_periodic_if_state_xtlv_id { + WL_STATE_IF_COMPACT_STATE = 0x1, + WL_STATE_IF_ADPS_STATE = 0x02 +}; + +#define TDMTX_CNT_VERSION_V1 1 +#define TDMTX_CNT_VERSION_V2 2 + +/* structure holding tdm counters that interface to iovar */ +typedef struct tdmtx_cnt_v1 { + uint16 ver; + uint16 length; /* length of this structure */ + uint16 wlc_idx; /* index for wlc */ + uint16 enabled; /* tdmtx is enabled on slice */ + uint32 tdmtx_txa_on; /* TXA on requests */ + uint32 tdmtx_txa_tmcnt; /* Total number of TXA timeout */ + uint32 tdmtx_por_on; /* TXA POR requests */ + uint32 tdmtx_txpuen; /* Path enable requests */ + uint32 tdmtx_txpudis; /* Total number of times Tx path is muted on the slice */ + uint32 tdmtx_txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint32 tdmtx_txdefer; /* Total number of times Tx was deferred on the slice */ + uint32 tdmtx_txmute; /* Total number of times active Tx muted on the slice */ + uint32 tdmtx_actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint32 tdmtx_txa_dur; /* Total time txa on */ + uint32 tdmtx_txpri_dur; /* Total time TXPri */ + uint32 tdmtx_txdefer_dur; /* Total time txdefer */ + /* TDMTX input fields */ + uint32 tdmtx_txpri; + uint32 tdmtx_defer; + uint32 tdmtx_threshold; + uint32 tdmtx_rssi_threshold; + uint32 tdmtx_txpwrboff; + uint32 tdmtx_txpwrboff_dt; +} tdmtx_cnt_v1_t; + +typedef struct { + uint16 ver; + uint16 length; /* length of the data portion */ + uint16 cnt; + uint16 pad; /* pad to align to 32 bit */ + uint8 data[]; /* array of tdmtx_cnt_v1_t */ +} tdmtx_status_t; + +/* structure holding counters that match exactly shm field sizes */ +typedef struct tdmtx_cnt_shm_v1 { + uint16 tdmtx_txa_on; /* TXA on requests */ + uint16 tdmtx_tmcnt; /* TXA on requests */ + uint16 tdmtx_por_on; /* TXA POR requests */ + uint16 tdmtx_txpuen; /* Path enable requests */ + uint16 tdmtx_txpudis; /* Total number of times Tx path is muted on the slice */ + uint16 tdmtx_txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint16 tdmtx_txdefer; /* Total number of times Tx was defered by the slice */ + uint16 tdmtx_txmute; /* Total number of times active Tx muted on the slice */ + uint16 tdmtx_actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint16 tdmtx_txa_dur_l; /* Total time (low 16 bits) txa on */ + uint16 tdmtx_txa_dur_h; /* Total time (low 16 bits) txa on */ + uint16 tdmtx_txpri_dur_l; /* Total time (low 16 bits) TXPri */ + uint16 tdmtx_txpri_dur_h; /* Total time (high 16 bits) TXPri */ + uint16 tdmtx_txdefer_dur_l; /* Total time (low 16 bits) txdefer */ + uint16 tdmtx_txdefer_dur_h; /* Total time (high 16 bits) txdefer */ +} tdmtx_cnt_shm_v1_t; + +/* structure holding tdm counters that interface to iovar for version 2 */ +typedef struct tdmtx_cnt_v2 { + uint16 ver; + uint16 length; /* length of this structure */ + uint16 wlc_idx; /* index for wlc */ + uint16 enabled; /* tdmtx is enabled on slice */ + uint32 tdmtx_txa_on; /* TXA on requests */ + uint32 tdmtx_txa_tmcnt; /* Total number of TXA timeout */ + uint32 tdmtx_porhi_on; /* TXA PORHI requests */ + uint32 tdmtx_porlo_on; /* TXA PORLO requests */ + uint32 tdmtx_txpuen; /* Path enable requests */ + uint32 tdmtx_txpudis; /* Total number of times Tx path is muted on the slice */ + uint32 tdmtx_txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint32 tdmtx_txdefer; /* Total number of times Tx was deferred on the slice */ + uint32 tdmtx_txmute; /* Total number of times active Tx muted on the slice */ + uint32 tdmtx_actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint32 tdmtx_txa_dur; /* Total time txa on */ + uint32 tdmtx_txpri_dur; /* Total time TXPri */ + uint32 tdmtx_txdefer_dur; /* Total time txdefer */ + /* TDMTX input fields */ + uint32 tdmtx_txpri; + uint32 tdmtx_defer; + uint32 tdmtx_threshold; + uint32 tdmtx_rssi_threshold; + uint32 tdmtx_txpwrboff; + uint32 tdmtx_txpwrboff_dt; +} tdmtx_cnt_v2_t; + +/* structure holding counters that match exactly shm field sizes */ +typedef struct tdmtx_cnt_shm_v2 { + uint16 tdmtx_txa_on; /* TXA on requests */ + uint16 tdmtx_tmcnt; /* TXA on requests */ + uint16 tdmtx_porhi_on; /* TXA PORHI requests */ + uint16 tdmtx_porlo_on; /* TXA PORLO requests */ + uint16 tdmtx_txpuen; /* Path enable requests */ + uint16 tdmtx_txpudis; /* Total number of times Tx path is muted on the slice */ + uint16 tdmtx_txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint16 tdmtx_txdefer; /* Total number of times Tx was defered by the slice */ + uint16 tdmtx_txmute; /* Total number of times active Tx muted on the slice */ + uint16 tdmtx_actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint16 tdmtx_txa_dur_l; /* Total time (low 16 bits) txa on */ + uint16 tdmtx_txa_dur_h; /* Total time (low 16 bits) txa on */ + uint16 tdmtx_txpri_dur_l; /* Total time (low 16 bits) TXPri */ + uint16 tdmtx_txpri_dur_h; /* Total time (high 16 bits) TXPri */ + uint16 tdmtx_txdefer_dur_l; /* Total time (low 16 bits) txdefer */ + uint16 tdmtx_txdefer_dur_h; /* Total time (high 16 bits) txdefer */ +} tdmtx_cnt_shm_v2_t; + +typedef struct wl_tdmtx_ioc { + uint16 id; /* ID of the sub-command */ + uint16 len; /* total length of all data[] */ + uint8 data[]; /* var len payload */ +} wl_tdmtx_ioc_t; + +/* + * iovar subcommand ids + */ +enum { + IOV_TDMTX_ENB = 1, + IOV_TDMTX_STATUS = 2, + IOV_TDMTX_TXPRI = 3, + IOV_TDMTX_DEFER = 4, + IOV_TDMTX_TXA = 5, + IOV_TDMTX_CFG = 6, + IOV_TDMTX_LAST }; /** @@ -2619,8 +3156,17 @@ enum wl_cnt_xtlv_id { #define WL_CNT_MCST_VAR_NUM 64 /* sizeof(wl_cnt_ge40mcst_v1_t), sizeof(wl_cnt_lt40mcst_v1_t), and sizeof(wl_cnt_v_le10_mcst_t) */ #define WL_CNT_MCST_STRUCT_SZ ((uint32)sizeof(uint32) * WL_CNT_MCST_VAR_NUM) +#define WL_CNT_REV80_MCST_STRUCT_SZ ((uint32)sizeof(wl_cnt_ge80mcst_v1_t)) +#define WL_CNT_REV80_MCST_TXFUNFlW_STRUCT_FIXED_SZ \ + ((uint32)OFFSETOF(wl_cnt_ge80_txfunfl_v1_t, txfunfl)) +#define WL_CNT_REV80_MCST_TXFUNFl_STRUCT_SZ(fcnt) \ + (WL_CNT_REV80_MCST_TXFUNFlW_STRUCT_FIXED_SZ + (fcnt * sizeof(uint32))) +#define WL_CNT_REV80_MCST_TXFUNFlW_STRUCT_SZ (WL_CNT_REV80_MCST_TXFUNFl_STRUCT_SZ(NFIFO_EXT)) #define WL_CNT_MCXST_STRUCT_SZ ((uint32)sizeof(wl_cnt_ge64mcxst_v1_t)) + +#define WL_CNT_HE_STRUCT_SZ ((uint32)sizeof(wl_he_cnt_wlc_v1_t)) + #define INVALID_CNT_VAL (uint32)(-1) #define WL_XTLV_CNTBUF_MAX_SIZE ((uint32)(OFFSETOF(wl_cnt_info_t, data)) + \ @@ -2630,7 +3176,6 @@ enum wl_cnt_xtlv_id { #define WL_CNTBUF_MAX_SIZE MAX(WL_XTLV_CNTBUF_MAX_SIZE, (uint32)sizeof(wl_cnt_ver_11_t)) - /** Top structure of counters IOVar buffer */ typedef struct { uint16 version; /**< see definition of WL_CNT_T_VERSION */ @@ -2670,6 +3215,30 @@ typedef struct { */ } wl_subcnt_info_t; +/* Top structure of counters TLV version IOVar buffer + * The structure definition should remain consistant b/w + * FW and wl/WLM app. + */ +typedef struct { + uint16 version; /* Version of IOVAR structure. Added for backward + * compatibility feature. If any changes are done, + * WL_TLV_IOV_VER need to be updated. + */ + uint16 length; /* total len in bytes of this structure + payload */ + uint16 counters_version; /* See definition of WL_CNT_VERSION_XTLV + * wl app will update counter tlv version to be used + * so to calculate offset of supported TLVs. + * If there is a mismatch in the version, FW will update an error + */ + uint16 num_tlv; /* Max number of TLV info passed by FW to WL app. + * and vice-versa + */ + uint32 data[]; /* variable length payload: + * This stores the tlv as supported by F/W to the wl app. + * This table is required to compute subcounter offsets at WLapp end. + */ +} wl_cntr_tlv_info_t; + /** wlc layer counters */ typedef struct { /* transmit stat counters */ @@ -2883,8 +3452,41 @@ typedef struct { uint32 txdropped; /* tx dropped pkts */ uint32 rxbcast; /* BroadcastReceivedFrameCount */ uint32 rxdropped; /* rx dropped pkts (derived: sum of others) */ + uint32 txq_end_assoccb; /* forced txqueue_end callback fired in assoc */ + uint32 tx_toss_cnt; /* number of tx packets tossed */ + uint32 rx_toss_cnt; /* number of rx packets tossed */ + uint32 last_tx_toss_rsn; /* reason because of which last tx pkt tossed */ + uint32 last_rx_toss_rsn; /* reason because of which last rx pkt tossed */ + + /* counters for security vulnerabilities */ + uint32 ie_unknown; /* number of unknown IEs */ + uint32 ie_invalid_length; /* number of IEs with invalid length */ + uint32 ie_invalid_data; /* number of IEs with invalid data */ + uint32 ipv6_invalid_length; /* number of IPv6 packets with invalid payload length */ } wl_cnt_wlc_t; +/* he counters */ +typedef struct { + uint32 he_rxtrig_myaid; + uint32 he_rxtrig_rand; + uint32 he_colormiss_cnt; + uint32 he_txmampdu; + uint32 he_rxmampdu; + uint32 he_txmtid_back; + uint32 he_rxmtid_back; + uint32 he_rxmsta_back; + uint32 he_txfrag; + uint32 he_rxdefrag; + uint32 he_txtrig; + uint32 he_rxtrig_basic; + uint32 he_rxtrig_murts; + uint32 he_rxtrig_bsrp; + uint32 he_rxdlmu; + uint32 he_physu_rx; + uint32 he_phyru_rx; + uint32 he_txtbppdu; +} wl_he_cnt_wlc_v1_t; + /* Reinit reasons - do not put anything else other than reinit reasons here */ typedef struct { uint32 rsn[WL_REINIT_RC_LAST]; @@ -3070,9 +3672,10 @@ typedef struct { uint32 bphy_badplcp; /**< number of bad PLCP reception on BPHY rate */ } wl_cnt_lt40mcst_v1_t; -/** MACSTAT counters for "wl counter" version <= 10 */ +/** MACSTAT counters for ucode (corerev >= 80) */ typedef struct { /* MAC counters: 32-bit version of d11.h's macstat_t */ + /* Start of PSM2HOST stats(72) block */ uint32 txallfrm; /**< total number of frames sent, incl. Data, ACK, RTS, CTS, * Control Management (includes retransmissions) */ @@ -3081,9 +3684,8 @@ typedef struct { uint32 txackfrm; /**< number of ACK frames sent out */ uint32 txdnlfrm; /**< number of Null-Data transmission generated from template */ uint32 txbcnfrm; /**< beacons transmitted */ - uint32 txfunfl[6]; /**< per-fifo tx underflows */ - uint32 txfbw; /**< transmit at fallback bw (dynamic bw) */ - uint32 PAD0; /**< number of MPDUs transmitted */ + uint32 txampdu; /**< number of AMPDUs transmitted */ + uint32 txmpdu; /**< number of MPDUs transmitted */ uint32 txtplunfl; /**< Template underflows (mac was too slow to transmit ACK/CTS * or BCN) */ @@ -3094,24 +3696,135 @@ typedef struct { uint32 pktengrxdmcast; /**< multicast frames rxed by the pkteng code */ uint32 rxfrmtoolong; /**< Received frame longer than legal limit (2346 bytes) */ uint32 rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */ - uint32 rxinvmachdr; /**< Either the protocol version != 0 or frame type not - * data/control/management - */ + uint32 rxanyerr; /**< Any RX error that is not counted by other counters. */ uint32 rxbadfcs; /**< number of frames for which the CRC check failed in the MAC */ uint32 rxbadplcp; /**< parity check of the PLCP header failed */ uint32 rxcrsglitch; /**< PHY was able to correlate the preamble but not the header */ uint32 rxstrt; /**< Number of received frames with a good PLCP * (i.e. passing parity check) */ - uint32 rxdfrmucastmbss; /* number of received DATA frames with good FCS and matching RA */ - uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ - uint32 rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */ - uint32 rxrtsucast; /**< number of unicast RTS addressed to the MAC (good FCS) */ - uint32 rxctsucast; /**< number of unicast CTS addressed to the MAC (good FCS) */ + uint32 rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */ + uint32 rxmgucastmbss; /**< number of received mgmt frames with good FCS and matching RA */ + uint32 rxctlucast; /**< number of received CNTRL frames with good FCS and matching RA */ + uint32 rxrtsucast; /**< number of unicast RTS addressed to the MAC (good FCS) */ + uint32 rxctsucast; /**< number of unicast CTS addressed to the MAC (good FCS) */ uint32 rxackucast; /**< number of ucast ACKS received (good FCS) */ - uint32 rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */ - uint32 rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */ - uint32 rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */ + uint32 rxdtocast; /**< number of received DATA frames (good FCS and not matching RA) */ + uint32 rxmgocast; /**< number of received MGMT frames (good FCS and not matching RA) */ + uint32 rxctlocast; /**< number of received CNTRL frame (good FCS and not matching RA) */ + uint32 rxrtsocast; /**< number of received RTS not addressed to the MAC */ + uint32 rxctsocast; /**< number of received CTS not addressed to the MAC */ + uint32 rxdtmcast; /**< number of RX Data multicast frames received by the MAC */ + uint32 rxmgmcast; /**< number of RX Management multicast frames received by the MAC */ + uint32 rxctlmcast; /**< number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32 rxbeaconmbss; /**< beacons received from member of BSS */ + uint32 rxdtucastobss; /**< number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32 rxbeaconobss; /**< beacons received from other BSS */ + uint32 rxrsptmout; /**< number of response timeouts for transmitted frames + * expecting a response + */ + uint32 bcntxcancl; /**< transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32 rxnodelim; /**< number of no valid delimiter detected by ampdu parser */ + uint32 missbcn_dbg; /**< number of beacon missed to receive */ + uint32 pmqovfl; /**< number of PMQ overflows */ + uint32 rxcgprqfrm; /**< number of received Probe requests that made it into + * the PRQ fifo + */ + uint32 rxcgprsqovfl; /**< Rx Probe Request Que overflow in the AP */ + uint32 txcgprsfail; /**< Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32 txcgprssuc; /**< Tx Probe Response Success (ACK was received) */ + uint32 prs_timeout; /**< number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32 txrtsfail; /**< number of rts transmission failure that reach retry limit */ + uint32 txucast; /**< number of unicast tx expecting response other than cts/cwcts */ + uint32 txinrtstxop; /**< number of data frame transmissions during rts txop */ + uint32 rxback; /**< blockack rxcnt */ + uint32 txback; /**< blockack txcnt */ + uint32 bphy_rxcrsglitch; /**< PHY count of bphy glitches */ + uint32 rxdrop20s; /**< drop secondary cnt */ + uint32 rxtoolate; /**< receive too late */ + uint32 bphy_badplcp; /**< number of bad PLCP reception on BPHY rate */ + uint32 rxtrig_myaid; /* New counters added in corerev 80 */ + uint32 rxtrig_rand; + uint32 goodfcs; + uint32 colormiss; + uint32 txmampdu; + uint32 rxmtidback; + uint32 rxmstaback; + uint32 txfrag; + /* End of PSM2HOST stats block */ + /* start of rxerror overflow counter(24) block which are modified/added in corerev 80 */ + uint32 phyovfl; + uint32 rxf0ovfl; /**< number of receive fifo 0 overflows */ + uint32 rxf1ovfl; /**< number of receive fifo 1 overflows */ + uint32 lenfovfl; + uint32 weppeof; + uint32 badplcp; + uint32 msduthresh; + uint32 strmeof; + uint32 stsfifofull; + uint32 stsfifoerr; + uint32 PAD[6]; + uint32 rxerr_stat; + uint32 ctx_fifo_full; + uint32 PAD[38]; /* PAD added for counter elements to be added soon */ +} wl_cnt_ge80mcst_v1_t; + +typedef struct { + uint32 fifocount; + uint32 txfunfl[]; +} wl_cnt_ge80_txfunfl_v1_t; + +/** MACSTAT counters for "wl counter" version <= 10 */ +typedef struct { + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32 txallfrm; /**< total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32 txrtsfrm; /**< number of RTS sent out by the MAC */ + uint32 txctsfrm; /**< number of CTS sent out by the MAC */ + uint32 txackfrm; /**< number of ACK frames sent out */ + uint32 txdnlfrm; /**< number of Null-Data transmission generated from template */ + uint32 txbcnfrm; /**< beacons transmitted */ + uint32 txfunfl[6]; /**< per-fifo tx underflows */ + uint32 txfbw; /**< transmit at fallback bw (dynamic bw) */ + uint32 PAD0; /**< number of MPDUs transmitted */ + uint32 txtplunfl; /**< Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32 txphyerror; /**< Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32 pktengrxducast; /**< unicast frames rxed by the pkteng code */ + uint32 pktengrxdmcast; /**< multicast frames rxed by the pkteng code */ + uint32 rxfrmtoolong; /**< Received frame longer than legal limit (2346 bytes) */ + uint32 rxfrmtooshrt; /**< Received frame did not contain enough bytes for its frame type */ + uint32 rxinvmachdr; /**< Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32 rxbadfcs; /**< number of frames for which the CRC check failed in the MAC */ + uint32 rxbadplcp; /**< parity check of the PLCP header failed */ + uint32 rxcrsglitch; /**< PHY was able to correlate the preamble but not the header */ + uint32 rxstrt; /**< Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32 rxdfrmucastmbss; /* number of received DATA frames with good FCS and matching RA */ + uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32 rxcfrmucast; /**< number of received CNTRL frames with good FCS and matching RA */ + uint32 rxrtsucast; /**< number of unicast RTS addressed to the MAC (good FCS) */ + uint32 rxctsucast; /**< number of unicast CTS addressed to the MAC (good FCS) */ + uint32 rxackucast; /**< number of ucast ACKS received (good FCS) */ + uint32 rxdfrmocast; /**< number of received DATA frames (good FCS and not matching RA) */ + uint32 rxmfrmocast; /**< number of received MGMT frames (good FCS and not matching RA) */ + uint32 rxcfrmocast; /**< number of received CNTRL frame (good FCS and not matching RA) */ uint32 rxrtsocast; /**< number of received RTS not addressed to the MAC */ uint32 rxctsocast; /**< number of received CTS not addressed to the MAC */ uint32 rxdfrmmcast; /**< number of RX Data multicast frames received by the MAC */ @@ -3467,6 +4180,239 @@ typedef struct { } wl_cnt_ver_11_t; +typedef struct { + uint16 version; /* see definition of WL_CNT_T_VERSION */ + uint16 length; /* length of entire structure */ + + /* transmit stat counters */ + uint32 txframe; /* tx data frames */ + uint32 txbyte; /* tx data bytes */ + uint32 txretrans; /* tx mac retransmits */ + uint32 txerror; /* tx data errors (derived: sum of others) */ + uint32 txctl; /* tx management frames */ + uint32 txprshort; /* tx short preamble frames */ + uint32 txserr; /* tx status errors */ + uint32 txnobuf; /* tx out of buffers errors */ + uint32 txnoassoc; /* tx discard because we're not associated */ + uint32 txrunt; /* tx runt frames */ + uint32 txchit; /* tx header cache hit (fastpath) */ + uint32 txcmiss; /* tx header cache miss (slowpath) */ + + /* transmit chip error counters */ + uint32 txuflo; /* tx fifo underflows */ + uint32 txphyerr; /* tx phy errors (indicated in tx status) */ + uint32 txphycrs; + + /* receive stat counters */ + uint32 rxframe; /* rx data frames */ + uint32 rxbyte; /* rx data bytes */ + uint32 rxerror; /* rx data errors (derived: sum of others) */ + uint32 rxctl; /* rx management frames */ + uint32 rxnobuf; /* rx out of buffers errors */ + uint32 rxnondata; /* rx non data frames in the data channel errors */ + uint32 rxbadds; /* rx bad DS errors */ + uint32 rxbadcm; /* rx bad control or management frames */ + uint32 rxfragerr; /* rx fragmentation errors */ + uint32 rxrunt; /* rx runt frames */ + uint32 rxgiant; /* rx giant frames */ + uint32 rxnoscb; /* rx no scb error */ + uint32 rxbadproto; /* rx invalid frames */ + uint32 rxbadsrcmac; /* rx frames with Invalid Src Mac */ + uint32 rxbadda; /* rx frames tossed for invalid da */ + uint32 rxfilter; /* rx frames filtered out */ + + /* receive chip error counters */ + uint32 rxoflo; /* rx fifo overflow errors */ + uint32 rxuflo[NFIFO]; /* rx dma descriptor underflow errors */ + + uint32 d11cnt_txrts_off; /* d11cnt txrts value when reset d11cnt */ + uint32 d11cnt_rxcrc_off; /* d11cnt rxcrc value when reset d11cnt */ + uint32 d11cnt_txnocts_off; /* d11cnt txnocts value when reset d11cnt */ + + /* misc counters */ + uint32 dmade; /* tx/rx dma descriptor errors */ + uint32 dmada; /* tx/rx dma data errors */ + uint32 dmape; /* tx/rx dma descriptor protocol errors */ + uint32 reset; /* reset count */ + uint32 tbtt; /* cnts the TBTT int's */ + uint32 txdmawar; + uint32 pkt_callback_reg_fail; /* callbacks register failure */ + + /* MAC counters: 32-bit version of d11.h's macstat_t */ + uint32 txallfrm; /* total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32 txrtsfrm; /* number of RTS sent out by the MAC */ + uint32 txctsfrm; /* number of CTS sent out by the MAC */ + uint32 txackfrm; /* number of ACK frames sent out */ + uint32 txdnlfrm; /* Not used */ + uint32 txbcnfrm; /* beacons transmitted */ + uint32 txfunfl[8]; /* per-fifo tx underflows */ + uint32 txtplunfl; /* Template underflows (mac was too slow to transmit ACK/CTS + * or BCN) + */ + uint32 txphyerror; /* Transmit phy error, type of error is reported in tx-status for + * driver enqueued frames + */ + uint32 rxfrmtoolong; /* Received frame longer than legal limit (2346 bytes) */ + uint32 rxfrmtooshrt; /* Received frame did not contain enough bytes for its frame type */ + uint32 rxinvmachdr; /* Either the protocol version != 0 or frame type not + * data/control/management + */ + uint32 rxbadfcs; /* number of frames for which the CRC check failed in the MAC */ + uint32 rxbadplcp; /* parity check of the PLCP header failed */ + uint32 rxcrsglitch; /* PHY was able to correlate the preamble but not the header */ + uint32 rxstrt; /* Number of received frames with a good PLCP + * (i.e. passing parity check) + */ + uint32 rxdfrmucastmbss; /* Number of received DATA frames with good FCS and matching RA */ + uint32 rxmfrmucastmbss; /* number of received mgmt frames with good FCS and matching RA */ + uint32 rxcfrmucast; /* number of received CNTRL frames with good FCS and matching RA */ + uint32 rxrtsucast; /* number of unicast RTS addressed to the MAC (good FCS) */ + uint32 rxctsucast; /* number of unicast CTS addressed to the MAC (good FCS) */ + uint32 rxackucast; /* number of ucast ACKS received (good FCS) */ + uint32 rxdfrmocast; /* number of received DATA frames (good FCS and not matching RA) */ + uint32 rxmfrmocast; /* number of received MGMT frames (good FCS and not matching RA) */ + uint32 rxcfrmocast; /* number of received CNTRL frame (good FCS and not matching RA) */ + uint32 rxrtsocast; /* number of received RTS not addressed to the MAC */ + uint32 rxctsocast; /* number of received CTS not addressed to the MAC */ + uint32 rxdfrmmcast; /* number of RX Data multicast frames received by the MAC */ + uint32 rxmfrmmcast; /* number of RX Management multicast frames received by the MAC */ + uint32 rxcfrmmcast; /* number of RX Control multicast frames received by the MAC + * (unlikely to see these) + */ + uint32 rxbeaconmbss; /* beacons received from member of BSS */ + uint32 rxdfrmucastobss; /* number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32 rxbeaconobss; /* beacons received from other BSS */ + uint32 rxrsptmout; /* Number of response timeouts for transmitted frames + * expecting a response + */ + uint32 bcntxcancl; /* transmit beacons canceled due to receipt of beacon (IBSS) */ + uint32 rxf0ovfl; /* Number of receive fifo 0 overflows */ + uint32 rxf1ovfl; /* Number of receive fifo 1 overflows (obsolete) */ + uint32 rxf2ovfl; /* Number of receive fifo 2 overflows (obsolete) */ + uint32 txsfovfl; /* Number of transmit status fifo overflows (obsolete) */ + uint32 pmqovfl; /* Number of PMQ overflows */ + uint32 rxcgprqfrm; /* Number of received Probe requests that made it into + * the PRQ fifo + */ + uint32 rxcgprsqovfl; /* Rx Probe Request Que overflow in the AP */ + uint32 txcgprsfail; /* Tx Probe Response Fail. AP sent probe response but did + * not get ACK + */ + uint32 txcgprssuc; /* Tx Probe Response Success (ACK was received) */ + uint32 prs_timeout; /* Number of probe requests that were dropped from the PRQ + * fifo because a probe response could not be sent out within + * the time limit defined in M_PRS_MAXTIME + */ + uint32 rxnack; /* obsolete */ + uint32 frmscons; /* obsolete */ + uint32 txnack; /* obsolete */ + uint32 txglitch_nack; /* obsolete */ + uint32 txburst; /* obsolete */ + + /* 802.11 MIB counters, pp. 614 of 802.11 reaff doc. */ + uint32 txfrag; /* dot11TransmittedFragmentCount */ + uint32 txmulti; /* dot11MulticastTransmittedFrameCount */ + uint32 txfail; /* dot11FailedCount */ + uint32 txretry; /* dot11RetryCount */ + uint32 txretrie; /* dot11MultipleRetryCount */ + uint32 rxdup; /* dot11FrameduplicateCount */ + uint32 txrts; /* dot11RTSSuccessCount */ + uint32 txnocts; /* dot11RTSFailureCount */ + uint32 txnoack; /* dot11ACKFailureCount */ + uint32 rxfrag; /* dot11ReceivedFragmentCount */ + uint32 rxmulti; /* dot11MulticastReceivedFrameCount */ + uint32 rxcrc; /* dot11FCSErrorCount */ + uint32 txfrmsnt; /* dot11TransmittedFrameCount (bogus MIB?) */ + uint32 rxundec; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32 tkipmicfaill; /* TKIPLocalMICFailures */ + uint32 tkipcntrmsr; /* TKIPCounterMeasuresInvoked */ + uint32 tkipreplay; /* TKIPReplays */ + uint32 ccmpfmterr; /* CCMPFormatErrors */ + uint32 ccmpreplay; /* CCMPReplays */ + uint32 ccmpundec; /* CCMPDecryptErrors */ + uint32 fourwayfail; /* FourWayHandshakeFailures */ + uint32 wepundec; /* dot11WEPUndecryptableCount */ + uint32 wepicverr; /* dot11WEPICVErrorCount */ + uint32 decsuccess; /* DecryptSuccessCount */ + uint32 tkipicverr; /* TKIPICVErrorCount */ + uint32 wepexcluded; /* dot11WEPExcludedCount */ + + uint32 txchanrej; /* Tx frames suppressed due to channel rejection */ + uint32 psmwds; /* Count PSM watchdogs */ + uint32 phywatchdog; /* Count Phy watchdogs (triggered by ucode) */ + + /* MBSS counters, AP only */ + uint32 prq_entries_handled; /* PRQ entries read in */ + uint32 prq_undirected_entries; /* which were bcast bss & ssid */ + uint32 prq_bad_entries; /* which could not be translated to info */ + uint32 atim_suppress_count; /* TX suppressions on ATIM fifo */ + uint32 bcn_template_not_ready; /* Template marked in use on send bcn ... */ + uint32 bcn_template_not_ready_done; /* ...but "DMA done" interrupt rcvd */ + uint32 late_tbtt_dpc; /* TBTT DPC did not happen in time */ + + /* per-rate receive stat counters */ + uint32 rx1mbps; /* packets rx at 1Mbps */ + uint32 rx2mbps; /* packets rx at 2Mbps */ + uint32 rx5mbps5; /* packets rx at 5.5Mbps */ + uint32 rx6mbps; /* packets rx at 6Mbps */ + uint32 rx9mbps; /* packets rx at 9Mbps */ + uint32 rx11mbps; /* packets rx at 11Mbps */ + uint32 rx12mbps; /* packets rx at 12Mbps */ + uint32 rx18mbps; /* packets rx at 18Mbps */ + uint32 rx24mbps; /* packets rx at 24Mbps */ + uint32 rx36mbps; /* packets rx at 36Mbps */ + uint32 rx48mbps; /* packets rx at 48Mbps */ + uint32 rx54mbps; /* packets rx at 54Mbps */ + uint32 rx108mbps; /* packets rx at 108mbps */ + uint32 rx162mbps; /* packets rx at 162mbps */ + uint32 rx216mbps; /* packets rx at 216 mbps */ + uint32 rx270mbps; /* packets rx at 270 mbps */ + uint32 rx324mbps; /* packets rx at 324 mbps */ + uint32 rx378mbps; /* packets rx at 378 mbps */ + uint32 rx432mbps; /* packets rx at 432 mbps */ + uint32 rx486mbps; /* packets rx at 486 mbps */ + uint32 rx540mbps; /* packets rx at 540 mbps */ + + /* pkteng rx frame stats */ + uint32 pktengrxducast; /* unicast frames rxed by the pkteng code */ + uint32 pktengrxdmcast; /* multicast frames rxed by the pkteng code */ + + uint32 rfdisable; /* count of radio disables */ + uint32 bphy_rxcrsglitch; /* PHY count of bphy glitches */ + + uint32 txexptime; /* Tx frames suppressed due to timer expiration */ + + uint32 txmpdu_sgi; /* count for sgi transmit */ + uint32 rxmpdu_sgi; /* count for sgi received */ + uint32 txmpdu_stbc; /* count for stbc transmit */ + uint32 rxmpdu_stbc; /* count for stbc received */ + + uint32 rxundec_mcst; /* dot11WEPUndecryptableCount */ + + /* WPA2 counters (see rxundec for DecryptFailureCount) */ + uint32 tkipmicfaill_mcst; /* TKIPLocalMICFailures */ + uint32 tkipcntrmsr_mcst; /* TKIPCounterMeasuresInvoked */ + uint32 tkipreplay_mcst; /* TKIPReplays */ + uint32 ccmpfmterr_mcst; /* CCMPFormatErrors */ + uint32 ccmpreplay_mcst; /* CCMPReplays */ + uint32 ccmpundec_mcst; /* CCMPDecryptErrors */ + uint32 fourwayfail_mcst; /* FourWayHandshakeFailures */ + uint32 wepundec_mcst; /* dot11WEPUndecryptableCount */ + uint32 wepicverr_mcst; /* dot11WEPICVErrorCount */ + uint32 decsuccess_mcst; /* DecryptSuccessCount */ + uint32 tkipicverr_mcst; /* TKIPICVErrorCount */ + uint32 wepexcluded_mcst; /* dot11WEPExcludedCount */ + + uint32 dma_hang; /* count for stbc received */ + uint32 rxrtry; /* number of packets with retry bit set to 1 */ +} wl_cnt_ver_7_t; + typedef struct { uint16 version; /**< see definition of WL_CNT_T_VERSION */ uint16 length; /**< length of entire structure */ @@ -3746,6 +4692,8 @@ typedef struct { uint32 bphy_rxcrsglitch; uint32 bphy_badplcp; + uint32 slice_index; /**< Slice for which stats are reported */ + } wl_delta_stats_t; /* Partial statistics counter report */ @@ -3819,6 +4767,18 @@ struct wl_msglevel2 { uint32 high; }; +/* A versioned structure for setting and retrieving debug message levels. */ +#define WL_MSGLEVEL_STRUCT_VERSION_1 1 + +typedef struct wl_msglevel_v1 { + uint16 version; + uint16 length; + uint32 msglevel1; + uint32 msglevel2; + uint32 msglevel3; + /* add another uint32 when full */ +} wl_msglevel_v1_t; + #define WL_ICMP_IPV6_CFG_VERSION 1 #define WL_ICMP_IPV6_CLEAR_ALL (1 << 0) @@ -3883,7 +4843,6 @@ typedef struct wake_pkt { uint8 packet[]; } wake_pkt_t; - #define WL_MTCPKEEP_ALIVE_VERSION 1 /* #ifdef WLBA */ @@ -3973,8 +4932,7 @@ typedef struct tdls_iovar { uint8 mode; /**< mode: depends on iovar */ uint8 PAD; chanspec_t chanspec; - uint16 PAD; - uint32 pad; /**< future */ + uint8 PAD[6]; } tdls_iovar_t; #define TDLS_WFD_IE_SIZE 512 @@ -4035,7 +4993,6 @@ typedef struct wme_max_bandwidth { #define TSPEC_DEFAULT_DIALOG_TOKEN 42 /**< default dialog token */ #define TSPEC_DEFAULT_SBW_FACTOR 0x3000 /**< default surplus bw */ - #define WL_WOWL_KEEPALIVE_MAX_PACKET_SIZE 80 #define WLC_WOWL_MAX_KEEPALIVE 2 @@ -4292,7 +5249,7 @@ typedef struct wl_pfn_scanresult_v1 { uint32 status; uint32 count; wl_pfn_net_info_v1_t netinfo; - wl_bss_info_t bss_info; + wl_bss_info_v109_t bss_info; } wl_pfn_scanresult_v1_t; typedef struct wl_pfn_scanresult_v2 { @@ -4300,9 +5257,17 @@ typedef struct wl_pfn_scanresult_v2 { uint32 status; uint32 count; wl_pfn_net_info_v2_t netinfo; - wl_bss_info_t bss_info; + wl_bss_info_v109_t bss_info; } wl_pfn_scanresult_v2_t; +typedef struct wl_pfn_scanresult_v2_1 { + uint32 version; + uint32 status; + uint32 count; + wl_pfn_net_info_v2_t netinfo; + uint8 bss_info[]; /* var length wl_bss_info_X structures */ +} wl_pfn_scanresult_v2_1_t; + /**PFN data structure */ typedef struct wl_pfn_param { int32 version; /**< PNO parameters version */ @@ -4502,11 +5467,11 @@ typedef struct wl_pfn_ssid_ext_result { #ifndef BESTN_MAX #define BESTN_MAX 10 -#endif +#endif // endif #ifndef MSCAN_MAX #define MSCAN_MAX 90 -#endif +#endif // endif /* Dynamic scan configuration for motion profiles */ @@ -4656,7 +5621,6 @@ typedef struct wl_p2po_find_config { * 1 means scan for P2P devices plus non-P2P APs. */ - /** For adding a WFDS service to seek */ typedef struct { uint32 seek_hdl; /**< unique id chosen by host */ @@ -4679,7 +5643,6 @@ typedef struct { uint32 seek_hdl; /**< delete service specified by id */ } wl_p2po_wfds_seek_del_t; - /** For adding a WFDS service to advertise */ #include typedef BWL_PRE_PACKED_STRUCT struct { @@ -4750,7 +5713,6 @@ typedef struct { struct ether_addr bssid[]; /**< max ANQPO_MAX_IGNORE_BSSID */ } wl_anqpo_ignore_bssid_list_t; - struct toe_ol_stats_t { /** Num of tx packets that don't need to be checksummed */ uint32 tx_summed; @@ -4883,6 +5845,71 @@ typedef struct rssi_struct { uint8 idx; /**< next rssi location */ } rssi_struct_t; +#ifdef WLDFSP +#define DFSP_EVT_OFFSET OFFSETOF(dfsp_event_data_t, ie) +#define DFSP_EVT_FLAGS_AP_ASSOC (1 << 0) +#define DFSP_EVT_FLAGS_AP_BCNMON (1 << 1) +#define DFSP_EVT_FLAGS_PROXY_BCSA (1 << 2) +#define DFSP_EVT_FLAGS_PROXY_UCSA (1 << 3) +#define DFSP_EVT_FLAGS_PROXY_PCSA (1 << 4) + +typedef struct dfsp_event_data { + uint16 flags; /* indicate what triggers the event */ + uint16 ie_len; + uint8 ie[]; /* variable length */ +} dfsp_event_data_t; + +/* Proxy Channel Switch Announcement is a collection of IEs */ +typedef struct dfsp_pcsa { + dot11_ext_csa_ie_t ecsa; + dot11_mesh_csp_ie_t mcsp; + dot11_wide_bw_chan_switch_ie_t wbcs; +} dfsp_pcsa_t; + +/* DFS Proxy */ +#define DFSP_CFG_VERSION 1 +#define DFSP_FLAGS_ENAB 0x1 +typedef struct dfsp_cfg { + uint16 version; + uint16 len; + uint16 flags; /**< bit 1 to enable/disable the feature */ + uint16 max_bcn_miss_dur; /**< maximum beacon miss duration before ceasing data tx */ + uint8 mcsp_ttl; /**< remaining number of hops allowed for pcsa message */ + uint8 bcsa_cnt; /**< repeat numbers of broadcast CSA */ + chanspec_t mon_chan; /**< passive monitoring channel spec */ + struct ether_addr mon_bssid; /**< broadcast means monitoring all */ + uint16 max_bcn_miss_dur_af; /**< maximum beacon miss duration before ceasing AF tx */ +} dfsp_cfg_t; + +#define DFSP_UCSA_VERSION 1 +typedef struct dfsp_ucsa { + uint16 version; + uint16 len; + struct ether_addr address; + uint8 enable; + uint8 retry_cnt; /**< just in case host needs to control the value */ +} dfsp_ucsa_t; + +typedef struct dfsp_ucsa_tbl { + uint8 tbl_num; + uint8 tbl[]; +} dfsp_ucsa_tbl_t; + +typedef struct dfsp_stats { + uint32 dfsp_csainfra; + uint32 dfsp_csabcnmon; + uint32 dfsp_bcsarx; + uint32 dfsp_ucsarx; + uint32 dfsp_pcsarx; + uint32 dfsp_bcsatx; + uint32 dfsp_ucsatx; + uint32 dfsp_pcsatx; + uint32 dfsp_ucsatxfail; + uint32 dfsp_evtnotif; + uint32 dfsp_evtsuspect; + uint32 dfsp_evtresume; +} dfsp_stats_t; +#endif /* WLDFSP */ /* * ptk_start: iovar to start 4-way handshake for secured ranging @@ -5005,14 +6032,14 @@ typedef struct wl_pkt_filter_pattern_listel { uint16 base_offs; /**< Base for offset (defined below) */ uint16 size_bytes; /**< Size of mask/pattern */ uint16 match_flags; /**< Addition flags controlling the match */ - uint8 mask_and_data[1]; /**< Variable length mask followed by data, each size_bytes */ + uint8 mask_and_data[]; /**< Variable length mask followed by data, each size_bytes */ } wl_pkt_filter_pattern_listel_t; typedef struct wl_pkt_filter_pattern_list { uint8 list_cnt; /**< Number of elements in the list */ uint8 PAD1[1]; /**< Reserved (possible version: reserved) */ uint16 totsize; /**< Total size of this pattern list (includes this struct) */ - wl_pkt_filter_pattern_listel_t patterns[]; /**< Variable number of list elements */ + uint8 patterns[]; /**< Variable number of wl_pkt_filter_pattern_listel_t elements */ } wl_pkt_filter_pattern_list_t; typedef struct wl_apf_program { @@ -5028,7 +6055,7 @@ typedef struct wl_pkt_filter_pattern_timeout { */ uint32 size_bytes; /* Size of the pattern. Bitmask must be the same size. */ uint32 timeout; /* Timeout(seconds) */ - uint8 mask_and_pattern[1]; /* Variable length mask and pattern data. + uint8 mask_and_pattern[]; /* Variable length mask and pattern data. * mask starts at offset 0. Pattern * immediately follows mask. */ @@ -5078,7 +6105,7 @@ typedef struct wl_pkt_filter_enable { /** IOVAR "pkt_filter_list" parameter. Used to retrieve a list of installed filters. */ typedef struct wl_pkt_filter_list { uint32 num; /**< Number of installed packet filters */ - wl_pkt_filter_t filter[1]; /**< Variable array of packet filters. */ + uint8 filter[]; /**< Variable array of packet filters. */ } wl_pkt_filter_list_t; #define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) @@ -5102,7 +6129,11 @@ typedef struct wl_pkt_filter_ports { #define WL_PKT_FILTER_PORTS_FIXED_LEN OFFSETOF(wl_pkt_filter_ports_t, ports) #define WL_PKT_FILTER_PORTS_VERSION 0 -#define WL_PKT_FILTER_PORTS_MAX 128 +#if defined(WL_PKT_FLTR_EXT) && !defined(WL_PKT_FLTR_EXT_DISABLED) +#define WL_PKT_FILTER_PORTS_MAX 256 +#else +#define WL_PKT_FILTER_PORTS_MAX 128 +#endif /* WL_PKT_FLTR_EXT && !WL_PKT_FLTR_EXT_DISABLED */ #define RSN_REPLAY_LEN 8 typedef struct _gtkrefresh { @@ -5130,6 +6161,7 @@ typedef struct wl_seq_cmd_ioctl { ((cmd) == WLC_GET_AP) || \ ((cmd) == WLC_GET_INSTANCE)) +#define MAX_PKTENG_SWEEP_STEPS 40 typedef struct wl_pkteng { uint32 flags; uint32 delay; /**< Inter-packet delay */ @@ -5138,14 +6170,25 @@ typedef struct wl_pkteng { uint8 seqno; /**< Enable/disable sequence no. */ struct ether_addr dest; /**< Destination address */ struct ether_addr src; /**< Source address */ - uint8 PAD[3]; + uint8 sweep_steps; /**< Number of sweep power */ + uint8 PAD[2]; } wl_pkteng_t; +/* IOVAR pkteng_sweep_counters response structure */ +#define WL_PKTENG_SWEEP_COUNTERS_VERSION 1 +typedef struct wl_pkteng_sweep_ctrs { + uint16 version; /**< Version - 1 */ + uint16 size; /**< Complete Size including sweep_counters */ + uint16 sweep_steps; /**< Number of steps */ + uint16 PAD; + uint16 sweep_counter[]; /**< Array of frame counters */ +} wl_pkteng_sweep_ctrs_t; + #define WL_PKTENG_RU_FILL_VER_1 1 // struct for ru packet engine -typedef struct wl_pkteng_ru { - uint16 version; /* ver is 1 */ - uint16 length; /* size of complete structure */ +typedef struct wl_pkteng_ru_v1 { + uint16 version; /* ver is 1 */ + uint16 length; /* size of complete structure */ uint8 bw; /* bandwidth info */ uint8 ru_alloc_val; /* ru allocation index number */ uint8 mcs_val; /* mcs allocated value */ @@ -5155,20 +6198,83 @@ typedef struct wl_pkteng_ru { uint8 he_ltf_symb ; /* num of HE-LTF symbols */ uint8 stbc; /* STBC support */ uint8 coding_val; /* BCC/LDPC coding support */ - uint8 pe_category; /* PE duration 0/8/16usecs */ + uint8 pe_category; /* PE duration 0/8/16usecs */ uint8 dcm; /* dual carrier modulation */ - uint8 mumimo_ltfmode; /* ltf mode */ - uint8 PAD[1]; /* pad bytes to make structure occupy 4 byte aligned */ -} wl_pkteng_ru_fill_t; + uint8 mumimo_ltfmode; /* ltf mode */ + uint8 trig_tx; /* form and transmit the trigger frame */ + uint8 trig_type; /* type of trigger frame */ + uint8 trig_period; /* trigger tx periodicity TBD */ + struct ether_addr dest; /* destination address for un-associated mode */ +} wl_pkteng_ru_v1_t; + +#ifndef WL_PKTENG_RU_VER +/* App uses the latest version - source picks it up from wlc_types.h */ +typedef wl_pkteng_ru_v1_t wl_pkteng_ru_fill_t; +#endif // endif + +typedef struct wl_trig_frame_info { + /* Structure versioning and structure length params */ + uint16 version; + uint16 length; + /* Below params are the fields related to trigger frame contents */ + /* Common Info Params Figure 9-52d - 11ax Draft 1.1 */ + uint16 lsig_len; + uint16 trigger_type; + uint16 cascade_indication; + uint16 cs_req; + uint16 bw; + uint16 cp_ltf_type; + uint16 mu_mimo_ltf_mode; + uint16 num_he_ltf_syms; + uint16 stbc; + uint16 ldpc_extra_symb; + uint16 ap_tx_pwr; + uint16 afactor; + uint16 pe_disambiguity; + uint16 spatial_resuse; + uint16 doppler; + uint16 he_siga_rsvd; + uint16 cmn_info_rsvd; + /* User Info Params Figure 9-52e - 11ax Draft 1.1 */ + uint16 aid12; + uint16 ru_alloc; + uint16 coding_type; + uint16 mcs; + uint16 dcm; + uint16 ss_alloc; + uint16 tgt_rssi; + uint16 usr_info_rsvd; +} wl_trig_frame_info_t; + +/* wl pkteng_stats related definitions */ +#define WL_PKTENG_STATS_V1 (1) +#define WL_PKTENG_STATS_V2 (2) + +typedef struct wl_pkteng_stats_v1 { + uint32 lostfrmcnt; /**< RX PER test: no of frames lost (skip seqno) */ + int32 rssi; /**< RSSI */ + int32 snr; /**< signal to noise ratio */ + uint16 rxpktcnt[NUM_80211_RATES+1]; + uint8 rssi_qdb; /**< qdB portion of the computed rssi */ + uint8 version; +} wl_pkteng_stats_v1_t; -typedef struct wl_pkteng_stats { +typedef struct wl_pkteng_stats_v2 { uint32 lostfrmcnt; /**< RX PER test: no of frames lost (skip seqno) */ int32 rssi; /**< RSSI */ int32 snr; /**< signal to noise ratio */ uint16 rxpktcnt[NUM_80211_RATES+1]; uint8 rssi_qdb; /**< qdB portion of the computed rssi */ - uint8 PAD; -} wl_pkteng_stats_t; + uint8 version; + uint16 length; + uint16 pad; + int32 rssi_per_core[WL_RSSI_ANT_MAX]; + int32 rssi_per_core_qdb[WL_RSSI_ANT_MAX]; +} wl_pkteng_stats_v2_t; + +#ifndef WL_PKTENG_STATS_TYPEDEF_HAS_ALIAS +typedef wl_pkteng_stats_v1_t wl_pkteng_stats_t; +#endif /* WL_PKTENG_STATS_TYPEDEF_HAS_ALIAS */ typedef struct wl_txcal_params { wl_pkteng_t pkteng; @@ -5178,6 +6284,12 @@ typedef struct wl_txcal_params { uint8 PAD; } wl_txcal_params_t; +typedef struct wl_rssilog_params { + uint8 enable; + uint8 rssi_threshold; + uint8 time_threshold; + uint8 pad; +} wl_rssilog_params_t; typedef struct wl_sslpnphy_papd_debug_data { uint8 psat_pwr; @@ -5291,11 +6403,17 @@ typedef struct wl_rssi_monitor_evt { uint16 pad; } wl_rssi_monitor_evt_t; -/* CCA based channel quality event configuration */ +/* CCA based channel quality event configuration (ID values for both config and report) */ #define WL_CHAN_QUAL_CCA 0 #define WL_CHAN_QUAL_NF 1 #define WL_CHAN_QUAL_NF_LTE 2 -#define WL_CHAN_QUAL_TOTAL 3 +#define WL_CHAN_QUAL_TOTAL 3 /* The total IDs supported in both config and report */ +/* Additional channel quality event support in report only (>= 0x100) + * Notice that uint8 is used in configuration struct wl_chan_qual_metric_t, but uint16 is + * used for report in struct cca_chan_qual_event_t. So the ID values beyond 8-bit are used + * for reporting purpose only. + */ +#define WL_CHAN_QUAL_FULL_CCA (0x100 | WL_CHAN_QUAL_CCA) #define MAX_CHAN_QUAL_LEVELS 8 @@ -5321,7 +6439,6 @@ typedef struct wl_action_obss_coex_req { uint8 ch_list[1]; } wl_action_obss_coex_req_t; - /** IOVar parameter block for small MAC address array with type indicator */ #define WL_IOV_MAC_PARAM_LEN 4 @@ -5418,7 +6535,6 @@ typedef struct { char headings[]; } pktq_log_format_v05_t; - typedef struct { uint32 version; wl_iov_mac_params_t params; @@ -5586,6 +6702,8 @@ typedef struct nbr_element { uint8 phytype; uint8 pad; } nbr_element_t; +#define NBR_ADD_STATIC 0 +#define NBR_ADD_DYNAMIC 1 #define WL_RRM_NBR_RPT_VER 1 /** 11k Neighbor Report element */ @@ -5600,7 +6718,7 @@ typedef struct nbr_rpt_elem { uint8 reg; uint8 channel; uint8 phytype; - uint8 pad_2; + uint8 addtype; /* static for manual add or dynamic if auto-learning of neighbors */ wlc_ssid_t ssid; chanspec_t chanspec; uint8 bss_trans_preference; @@ -5648,6 +6766,27 @@ typedef struct pcie_bus_tput_stats { uint32 count; } pcie_bus_tput_stats_t; +#define HOST_WAKEUP_DATA_VER 1 +#include +/* Bus interface host wakeup data */ +typedef BWL_PRE_PACKED_STRUCT struct wl_host_wakeup_data { + uint16 ver; + uint16 len; + uchar data[1]; /* wakeup data */ +} BWL_POST_PACKED_STRUCT wl_host_wakeup_data_t; +#include + +#define HOST_WAKEUP_DATA_VER_2 2 +#include +/* Bus interface host wakeup data */ +typedef BWL_PRE_PACKED_STRUCT struct wl_host_wakeup_data_v2 { + uint16 ver; + uint16 len; + uint32 gpio_toggle_time; /* gpio toggle time in ms */ + uchar data[1]; /* wakeup data */ +} BWL_POST_PACKED_STRUCT wl_host_wakeup_data_v2_t; +#include + typedef struct keepalives_max_idle { uint16 keepalive_count; /**< nmbr of keepalives per bss_max_idle period */ uint8 mkeepalive_index; /**< mkeepalive_index for keepalive frame to be used */ @@ -5658,6 +6797,49 @@ typedef struct keepalives_max_idle { #define PM_IGNORE_BCMC_PROXY_ARP (1 << 0) #define PM_IGNORE_BCMC_ALL_DMS_ACCEPTED (1 << 1) +/* ##### HMAP section ##### */ +#define PCIE_MAX_HMAP_WINDOWS 8 +#define PCIE_HMAPTEST_VERSION 1 +#define HMAPTEST_VAL_INVALIDMASK 1 +#define HMAPTEST_VAL_WRITEMASK 2 +#define HMAPTEST_ACCESS_TYPE_MASK 0b1100 +#define HMAPTEST_ACCESS_TYPE_SHIFT 2 +#define HMAPTEST_ACCESS_ARM 0 +#define HMAPTEST_ACCESS_M2M 1 +#define HMAPTEST_ACCESS_D11 2 +#define HMAPTEST_ACCESS_NONE 3 /* marker to stop HMAPTEST */ + +typedef struct pcie_hmaptest { + uint16 version; /* Version = 1 */ + uint16 length; /* Length of entire structure */ + uint32 xfer_len; + uint32 accesstype; + uint32 is_write; + uint32 is_invalid; + uint32 host_addr_hi; + uint32 host_addr_lo; +} pcie_hmaptest_t; + +/* HMAP window register set */ +typedef struct hmapwindow { + uint32 baseaddr_lo; /* BaseAddrLower */ + uint32 baseaddr_hi; /* BaseAddrUpper */ + uint32 windowlength; /* Window Length */ +} hmapwindow_t; + +#define PCIE_HMAP_VERSION 1 +typedef struct pcie_hmap { + uint16 version; /**< Version = 1 */ + uint16 length; /**< Length of entire structure */ + uint32 enable; /**< status of HMAP enabled/disabled */ + uint32 nwindows; /* no. of HMAP windows enabled */ + uint32 window_config; /* HMAP window_config register */ + uint32 hmap_violationaddr_lo; /* violating address lo */ + uint32 hmap_violationaddr_hi; /* violating addr hi */ + uint32 hmap_violation_info; /* violation info */ + hmapwindow_t hwindows[]; /* Multiple hwindows */ +} pcie_hmap_t; + /* ##### Power Stats section ##### */ #define WL_PWRSTATS_VERSION 2 @@ -5981,6 +7163,12 @@ typedef BWL_PRE_PACKED_STRUCT struct wl_pwr_usb_hsic_stats { } BWL_POST_PACKED_STRUCT wl_pwr_usb_hsic_stats_t; #include +/* PCIe Event counter tlv IDs */ +enum pcie_cnt_xtlv_id { + PCIE_CNT_XTLV_METRICS = 0x1, /**< PCIe Bus Metrics */ + PCIE_CNT_XTLV_BUS_CNT = 0x2 /**< PCIe Bus counters */ +}; + typedef struct pcie_bus_metrics { uint32 d3_suspend_ct; /**< suspend count */ uint32 d0_resume_ct; /**< resume count */ @@ -6016,6 +7204,31 @@ typedef struct pcie_bus_metrics { uint32 ltr_sleep_dur; /**< # of msecs chip was in LTR SLEEP */ } pcie_bus_metrics_t; +typedef struct pcie_cnt { + uint32 ltr_state; /**< Current LTR state */ + uint32 l0_sr_cnt; /**< SR count during L0 */ + uint32 l2l3_sr_cnt; /**< SR count during L2L3 */ + uint32 d3_ack_sr_cnt; /**< srcount during last D3-ACK */ + uint32 d3_sr_cnt; /**< SR count during D3 */ + uint32 d3_info_start; /**< D3 INFORM received time */ + uint32 d3_info_enter_cnt; /**< # of D3 INFORM received */ + uint32 d3_cnt; /**< # of real D3 */ + uint32 d3_ack_sent_cnt; /**< # of D3 ACK sent count */ + uint32 d3_drop_cnt_event; /**< # of events dropped during D3 */ + uint32 d2h_req_q_len; /**< # of Packet pending in D2H request queue */ + uint32 hw_reason; /**< Last Host wake assert reason */ + uint32 hw_assert_cnt; /**< # of times Host wake Asserted */ + uint32 host_ready_cnt; /**< # of Host ready interrupts */ + uint32 hw_assert_reason_0; /**< timestamp when hw_reason is TRAP */ + uint32 hw_assert_reason_1; /**< timestamp when hw_reason is WL_EVENT */ + uint32 hw_assert_reason_2; /**< timestamp when hw_reason is DATA */ + uint32 hw_assert_reason_3; /**< timestamp when hw_reason is DELAYED_WAKE */ + uint32 last_host_ready; /**< Timestamp of last Host ready */ + bool hw_asserted; /**< Flag to indicate if Host wake is Asserted */ + bool event_delivery_pend; /**< No resources to send event */ + uint16 pad; /**< Word alignment for scripts */ +} pcie_cnt_t; + /** Bus interface info for PCIE */ typedef struct wl_pwr_pcie_stats { uint16 type; /**< WL_PWRSTATS_TYPE_PCIE */ @@ -6057,7 +7270,6 @@ typedef struct wl_pwr_phy_stats { uint32 rx_dur; /**< RX Active duration in us */ } wl_pwr_phy_stats_t; - typedef struct wl_mimo_meas_metrics_v1 { uint16 type; uint16 len; @@ -6105,6 +7317,41 @@ typedef struct wl_mimo_meas_metrics { /* Total SIFS idle time in SISO mode */ uint32 total_sifs_time_siso; } wl_mimo_meas_metrics_t; + +typedef struct wl_pwr_slice_index { + uint16 type; /* WL_PWRSTATS_TYPE_SLICE_INDEX */ + uint16 len; + + uint32 slice_index; /* Slice index for which stats are meant for */ +} wl_pwr_slice_index_t; + +typedef struct wl_pwr_tsync_stats { + uint16 type; /**< WL_PWRSTATS_TYPE_TSYNC */ + uint16 len; + uint32 avb_uptime; /**< AVB uptime in msec */ +} wl_pwr_tsync_stats_t; + +typedef struct wl_pwr_ops_stats { + uint16 type; /* WL_PWRSTATS_TYPE_OPS_STATS */ + uint16 len; /* total length includes fixed fields */ + uint32 partial_ops_dur; /* Total time(in usec) partial ops duration */ + uint32 full_ops_dur; /* Total time(in usec) full ops duration */ +} wl_pwr_ops_stats_t; + +typedef struct wl_pwr_bcntrim_stats { + uint16 type; /* WL_PWRSTATS_TYPE_BCNTRIM_STATS */ + uint16 len; /* total length includes fixed fields */ + uint8 associated; /* STA is associated ? */ + uint8 slice_idx; /* on which slice STA is associated */ + uint16 pad; /* padding */ + uint32 slice_beacon_seen; /* number of beacons seen on the Infra + * interface on this slice + */ + uint32 slice_beacon_trimmed; /* number beacons actually trimmed on this slice */ + uint32 total_beacon_seen; /* total number of beacons seen on the Infra interface */ + uint32 total_beacon_trimmed; /* total beacons actually trimmed */ +} wl_pwr_bcntrim_stats_t; + /* ##### End of Power Stats section ##### */ /** IPV4 Arp offloads for ndis context */ @@ -6136,7 +7383,6 @@ typedef struct wl_pfn_roam_thresh { uint32 roam_alert_thresh; /**< time in ms */ } wl_pfn_roam_thresh_t; - /* Reasons for wl_pmalert_t */ #define PM_DUR_EXCEEDED (1<<0) #define MPC_DUR_EXCEEDED (1<<1) @@ -6514,9 +7760,39 @@ typedef BWL_PRE_PACKED_STRUCT struct wlc_ipfo_route_tbl { /* Version of wlc_btc_stats_t structure. * Increment whenever a change is made to wlc_btc_stats_t */ -#define BTCX_STATS_VER 2 +#define BTCX_STATS_VER_3 3 -typedef struct wlc_btc_stats { +typedef struct wlc_btc_stats_v3 { + uint16 version; /* version number of struct */ + uint16 valid; /* Size of this struct */ + uint32 stats_update_timestamp; /* tStamp when data is updated. */ + uint32 btc_status; /* Hybrid/TDM indicator: Bit2:Hybrid, Bit1:TDM,Bit0:CoexEnabled */ + uint32 bt_req_type_map; /* BT Antenna Req types since last stats sample */ + uint32 bt_req_cnt; /* #BT antenna requests since last stats sampl */ + uint32 bt_gnt_cnt; /* #BT antenna grants since last stats sample */ + uint32 bt_gnt_dur; /* usec BT owns antenna since last stats sample */ + uint16 bt_abort_cnt; /* #Times WL was preempted due to BT since WL up */ + uint16 bt_rxf1ovfl_cnt; /* #Time PSNULL retry count exceeded since WL up */ + uint16 bt_latency_cnt; /* #Time ucode high latency detected since WL up */ + uint16 rsvd; /* pad to align struct to 32bit bndry */ + uint16 bt_succ_pm_protect_cnt; /* successful PM protection */ + uint16 bt_succ_cts_cnt; /* successful CTS2A protection */ + uint16 bt_wlan_tx_preempt_cnt; /* WLAN TX Preemption */ + uint16 bt_wlan_rx_preempt_cnt; /* WLAN RX Preemption */ + uint16 bt_ap_tx_after_pm_cnt; /* AP TX even after PM protection */ + uint16 bt_peraud_cumu_gnt_cnt; /* Grant cnt for periodic audio */ + uint16 bt_peraud_cumu_deny_cnt; /* Deny cnt for periodic audio */ + uint16 bt_a2dp_cumu_gnt_cnt; /* Grant cnt for A2DP */ + uint16 bt_a2dp_cumu_deny_cnt; /* Deny cnt for A2DP */ + uint16 bt_sniff_cumu_gnt_cnt; /* Grant cnt for Sniff */ + uint16 bt_sniff_cumu_deny_cnt; /* Deny cnt for Sniff */ + uint8 pad; /* Padding */ + uint8 slice_index; /* Slice to report */ +} wlc_btc_stats_v3_t; + +#define BTCX_STATS_VER_2 2 + +typedef struct wlc_btc_stats_v2 { uint16 version; /* version number of struct */ uint16 valid; /* Size of this struct */ uint32 stats_update_timestamp; /* tStamp when data is updated. */ @@ -6529,7 +7805,7 @@ typedef struct wlc_btc_stats { uint16 bt_rxf1ovfl_cnt; /* #Time PSNULL retry count exceeded since WL up */ uint16 bt_latency_cnt; /* #Time ucode high latency detected since WL up */ uint16 rsvd; /* pad to align struct to 32bit bndry */ -} wlc_btc_stats_t; +} wlc_btc_stats_v2_t; #define WL_IPFO_ROUTE_TBL_FIXED_LEN 4 #define WL_MAX_IPFO_ROUTE_TBL_ENTRY 64 @@ -6564,7 +7840,8 @@ typedef struct wlc_btc_stats { uint8 sta_mac[6]; uint8 reserve_data2[2]; uint8 gsn[IV_LEN]; - uint8 wie[256]; + uint8 wie[TLV_BODY_LEN_MAX + TLV_HDR_LEN]; /* 257 */ + uint8 pad[3]; /* padding for alignment */ }; /* #endif BCMWAPI_WAI */ /* chanim acs record */ @@ -6785,6 +8062,12 @@ typedef struct wl_p2p_wfds_hash { uint8 PAD[3]; } wl_p2p_wfds_hash_t; +typedef struct wl_p2p_config_params { + uint16 enable; /**< 0: disable 1: enable */ + uint16 chanspec; /* GO chanspec */ + wlc_ssid_t ssid; /* SSID */ +} wl_p2p_config_params_t; + typedef struct wl_bcmdcs_data { uint32 reason; chanspec_t chspec; @@ -6851,6 +8134,11 @@ typedef struct { #define MAX_NUM_TXCAL_MEAS 128 #define MAX_NUM_PWR_STEP 40 #define TXCAL_IOVAR_VERSION 0x1 + +/* below are used for bphy/ofdm separated LSC */ +#define TXCAL_PWR_BPHY 0 +#define TXCAL_PWR_OFDM 1 + typedef struct wl_txcal_meas_percore { uint16 tssi[MAX_NUM_TXCAL_MEAS]; int16 pwr[MAX_NUM_TXCAL_MEAS]; @@ -6878,8 +8166,9 @@ typedef struct wl_txcal_power_tssi_ncore { uint8 channel; uint8 num_core; uint8 gen_tbl; - uint16 pad; - wl_txcal_power_tssi_percore_t tssi_percore[1]; + uint8 ofdm; + uint8 pad; + wl_txcal_power_tssi_percore_t tssi_percore[4]; } wl_txcal_power_tssi_ncore_t; typedef struct wl_txcal_meas { @@ -6905,7 +8194,7 @@ typedef struct wl_txcal_power_tssi { uint8 num_entries[WLC_TXCORE_MAX]; uint8 tssi[WLC_TXCORE_MAX][MAX_NUM_PWR_STEP]; uint8 gen_tbl; - uint8 PAD; + uint8 ofdm; } wl_txcal_power_tssi_t; typedef struct wl_txcal_power_tssi_old { @@ -6917,7 +8206,7 @@ typedef struct wl_txcal_power_tssi_old { uint8 num_entries[WLC_TXCORE_MAX_OLD]; uint8 tssi[WLC_TXCORE_MAX_OLD][MAX_NUM_PWR_STEP]; uint8 gen_tbl; - uint8 PAD; + uint8 ofdm; } wl_txcal_power_tssi_old_t; typedef struct wl_olpc_pwr { @@ -6926,9 +8215,17 @@ typedef struct wl_olpc_pwr { uint8 channel; int16 tempsense; uint8 olpc_idx; - uint8 pad; + uint8 ofdm; } wl_olpc_pwr_t; +typedef struct wl_txcal_tempsense { + uint16 version; + uint8 valid_cnt; + uint8 core; + int16 ref_temperature; + int16 meas_temperature; +} wl_txcal_tempsense_t; + /** IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ typedef struct wl_mempool_stats { int32 num; /**< Number of memory pools */ @@ -6941,88 +8238,6 @@ typedef struct { uint32 ipaddr_gateway; } nwoe_ifconfig_t; -/** Traffic management priority classes */ -typedef enum trf_mgmt_priority_class { - 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 */ -typedef struct trf_mgmt_config { - uint32 trf_mgmt_enabled; /**< 0 - disabled, 1 - enabled */ - uint32 flags; /**< See TRF_MGMT_FLAG_xxx defines */ - uint32 host_ip_addr; /**< My IP address to determine subnet */ - uint32 host_subnet_mask; /**< My subnet mask */ - uint32 downlink_bandwidth; /**< In units of kbps */ - uint32 uplink_bandwidth; /**< In units of kbps */ - uint32 min_tx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /**< Minimum guaranteed tx bandwidth */ - uint32 min_rx_bandwidth[TRF_MGMT_MAX_PRIORITIES]; /**< Minimum guaranteed rx bandwidth */ -} trf_mgmt_config_t; - -/** Traffic management filter */ -typedef struct trf_mgmt_filter { - struct ether_addr dst_ether_addr; /**< His L2 address */ - uint8 PAD[2]; - uint32 dst_ip_addr; /**< His IP address */ - uint16 dst_port; /**< His L4 port */ - uint16 src_port; /**< My L4 port */ - uint16 prot; /**< L4 protocol (only TCP or UDP) */ - uint16 flags; /**< TBD. For now, this must be zero. */ - trf_mgmt_priority_class_t priority; /**< Priority for filtered packets */ - uint32 dscp; /**< DSCP */ -} trf_mgmt_filter_t; - -/** Traffic management filter list (variable length) */ -typedef struct trf_mgmt_filter_list { - uint32 num_filters; - trf_mgmt_filter_t filter[1]; -} trf_mgmt_filter_list_t; - -/** Traffic management global info used for all queues */ -typedef struct trf_mgmt_global_info { - uint32 maximum_bytes_per_second; - uint32 maximum_bytes_per_sampling_period; - uint32 total_bytes_consumed_per_second; - uint32 total_bytes_consumed_per_sampling_period; - uint32 total_unused_bytes_per_sampling_period; -} trf_mgmt_global_info_t; - -/** Traffic management shaping info per priority queue */ -typedef struct trf_mgmt_shaping_info { - uint32 gauranteed_bandwidth_percentage; - uint32 guaranteed_bytes_per_second; - uint32 guaranteed_bytes_per_sampling_period; - uint32 num_bytes_produced_per_second; - uint32 num_bytes_consumed_per_second; - uint32 num_queued_packets; /**< Number of packets in queue */ - uint32 num_queued_bytes; /**< Number of bytes in queue */ -} trf_mgmt_shaping_info_t; - -/** Traffic management shaping info array */ -typedef struct trf_mgmt_shaping_info_array { - trf_mgmt_global_info_t tx_global_shaping_info; - trf_mgmt_shaping_info_t tx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; - trf_mgmt_global_info_t rx_global_shaping_info; - trf_mgmt_shaping_info_t rx_queue_shaping_info[TRF_MGMT_MAX_PRIORITIES]; -} trf_mgmt_shaping_info_array_t; - - -/** Traffic management statistical counters */ -typedef struct trf_mgmt_stats { - uint32 num_processed_packets; /**< Number of packets processed */ - uint32 num_processed_bytes; /**< Number of bytes processed */ - uint32 num_discarded_packets; /**< Number of packets discarded from queue */ -} trf_mgmt_stats_t; - -/** Traffic management statistics array */ -typedef struct trf_mgmt_stats_array { - trf_mgmt_stats_t tx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; - trf_mgmt_stats_t rx_queue_stats[TRF_MGMT_MAX_PRIORITIES]; -} trf_mgmt_stats_array_t; - /* Both powersel_params and lpc_params are used by IOVAR lpc_params. * The powersel_params is replaced by lpc_params in later WLC versions. */ @@ -7185,7 +8400,6 @@ typedef struct wl_tfs_term { uint8 tfs_id; /**< ID of a specific set (existing), or nul for all */ } wl_tfs_term_t; - #define DMS_DEP_PROXY_ARP (1 << 0) /* Definitions for WNM/NPS Directed Multicast Service */ @@ -7240,6 +8454,25 @@ typedef struct wl_service_term { } wl_service_term_t; /** Definitions for WNM/NPS BSS Transistion */ +#define WL_BSSTRANS_QUERY_VERSION_1 1 +typedef struct wl_bsstrans_query { + uint16 version; /* structure version */ + uint16 pad0; /* padding for 4-byte allignment */ + wlc_ssid_t ssid; /* SSID of NBR elem to be queried for */ + uint8 reason; /* Reason code of the BTQ */ + uint8 pad1[3]; /* padding for 4-byte allignment */ +} wl_bsstrans_query_t; + +#define BTM_QUERY_NBR_COUNT_MAX 16 + +#define WL_BTQ_NBR_LIST_VERSION_1 1 +typedef struct wl_btq_nbr_list { + uint16 version; /* structure version */ + uint8 count; /* No. of BTQ NBRs returned */ + uint8 pad; /* padding for 4-byte allignment */ + nbr_rpt_elem_t btq_nbt_elem[]; /* BTQ NBR elem in a BTQ NBR list */ +} wl_btq_nbr_list_t; + typedef struct wl_bsstrans_req { uint16 tbtt; /**< time of BSS to end of life, in unit of TBTT */ uint16 dur; /**< time of BSS to keep off, in unit of minute */ @@ -7275,7 +8508,8 @@ typedef enum { WL_BSSTRANS_POLICY_WAIT = 3, /**< Wait for deauth and send Accepted status */ WL_BSSTRANS_POLICY_PRODUCT = 4, /**< Policy for real product use cases (Olympic) */ WL_BSSTRANS_POLICY_PRODUCT_WBTEXT = 5, /**< Policy for real product use cases (SS) */ - WL_BSSTRANS_POLICY_MAX = 6 + WL_BSSTRANS_POLICY_MBO = 6, /**< Policy for MBO certification */ + WL_BSSTRANS_POLICY_MAX = 7 } wnm_bsstrans_policy_type_t; /** Definitions for WNM/NPS TIM Broadcast */ @@ -7470,7 +8704,6 @@ typedef struct wl_rmc_vsie { uint16 payload; /**< IE Data Payload */ } wl_rmc_vsie_t; - /* structures & defines for proximity detection */ enum proxd_method { PROXD_UNDEFINED_METHOD = 0, @@ -7588,8 +8821,10 @@ typedef struct wl_proxd_seq_config } wl_proxd_seq_config_t; #define WL_PROXD_TUNE_VERSION_1 1 +#define WL_PROXD_TUNE_VERSION_2 2 #include -typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune { +/* For legacy ranging target (e.g. 43430, 43342) */ +typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune_v1 { uint32 version; uint32 Ki; /**< h/w delay K factor for initiator */ uint32 Kt; /**< h/w delay K factor for target */ @@ -7619,27 +8854,116 @@ typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune { uint32 acs_gdv_thresh; int8 acs_rssi_thresh; uint8 smooth_win_en; - int32 acs_gdmm_thresh; - int8 acs_delta_rssi_thresh; int32 emu_delay; -} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_t; +} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_v1_t; #include -typedef struct wl_proxd_params_iovar { - uint16 method; /**< Proximity Detection method */ - union { - /* common params for pdsvc */ - wl_proxd_params_common_t cmn_params; /**< common parameters */ - /* method specific */ - wl_proxd_params_rssi_method_t rssi_params; /**< RSSI method parameters */ - wl_proxd_params_tof_method_t tof_params; /**< TOF method parameters */ - /* tune parameters */ - wl_proxd_params_tof_tune_t tof_tune; /**< TOF tune parameters */ - uint8 PAD[sizeof(wl_proxd_params_tof_tune_t)+1]; - } u; /**< Method specific optional parameters */ -} wl_proxd_params_iovar_t; - -#define PROXD_COLLECT_GET_STATUS 0 +#include +/* For legacy ranging initiator (including 4364) */ +typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_params_tof_tune_v2 { + uint32 version; + uint32 Ki; /**< h/w delay K factor for initiator */ + uint32 Kt; /**< h/w delay K factor for target */ + int16 vhtack; /**< enable/disable VHT ACK */ + int16 N_log2[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */ + int16 w_offset[TOF_BW_NUM]; /**< offset of threshold crossing window(per BW) */ + int16 w_len[TOF_BW_NUM]; /**< length of threshold crossing window(per BW) */ + int32 maxDT; /**< max time difference of T4/T1 or T3/T2 */ + int32 minDT; /**< min time difference of T4/T1 or T3/T2 */ + uint8 totalfrmcnt; /**< total count of transfered measurement frames */ + uint16 rsv_media; /**< reserve media value for TOF */ + uint32 flags; /**< flags */ + uint8 core; /**< core to use for tx */ + uint8 setflags; /* set flags of K, N. S values */ + int16 N_scale[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */ + uint8 sw_adj; /**< enable sw assisted timestamp adjustment */ + uint8 hw_adj; /**< enable hw assisted timestamp adjustment */ + uint8 seq_en; /**< enable ranging sequence */ + uint8 ftm_cnt[TOF_BW_SEQ_NUM]; /**< number of ftm frames based on bandwidth */ + int16 N_log2_2g; /**< simple threshold crossing for 2g channel */ + int16 N_scale_2g; /**< simple threshold crossing for 2g channel */ + wl_proxd_seq_config_t seq_5g20; + wl_proxd_seq_config_t seq_2g20; /* Thresh crossing params for 2G Sequence */ + uint16 bitflip_thresh; /* bitflip threshold */ + uint16 snr_thresh; /* SNR threshold */ + int8 recv_2g_thresh; /* 2g recieve sensitivity threshold */ + uint32 acs_gdv_thresh; + int8 acs_rssi_thresh; + uint8 smooth_win_en; + int32 acs_gdmm_thresh; + int8 acs_delta_rssi_thresh; + int32 emu_delay; + uint8 core_mask; /* core mask selection */ +} BWL_POST_PACKED_STRUCT wl_proxd_params_tof_tune_v2_t; +#include + +#define WL_PROXD_TUNE_VERSION_3 3 +/* Future ranging support */ +typedef struct wl_proxd_params_tof_tune_v3 { + uint16 version; + uint16 len; + uint32 Ki; /**< h/w delay K factor for initiator */ + uint32 Kt; /**< h/w delay K factor for target */ + int16 vhtack; /**< enable/disable VHT ACK */ + uint16 PAD; + int16 N_log2[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */ + uint16 PAD; + int16 w_offset[TOF_BW_NUM]; /**< offset of threshold crossing window(per BW) */ + uint16 PAD; + int16 w_len[TOF_BW_NUM]; /**< length of threshold crossing window(per BW) */ + uint16 PAD; + int32 maxDT; /**< max time difference of T4/T1 or T3/T2 */ + int32 minDT; /**< min time difference of T4/T1 or T3/T2 */ + uint8 totalfrmcnt; /**< total count of transfered measurement frames */ + uint8 PAD[3]; + uint16 rsv_media; /**< reserve media value for TOF */ + uint16 PAD; + uint32 flags; /**< flags */ + uint8 core; /**< core to use for tx */ + uint8 setflags; /* set flags of K, N. S values */ + uint16 PAD; + int16 N_scale[TOF_BW_SEQ_NUM]; /**< simple threshold crossing */ + uint8 sw_adj; /**< enable sw assisted timestamp adjustment */ + uint8 hw_adj; /**< enable hw assisted timestamp adjustment */ + uint8 seq_en; /**< enable ranging sequence */ + uint8 PAD[3]; + uint8 ftm_cnt[TOF_BW_SEQ_NUM]; /**< number of ftm frames based on bandwidth */ + uint8 PAD[3]; + int16 N_log2_2g; /**< simple threshold crossing for 2g channel */ + int16 N_scale_2g; /**< simple threshold crossing for 2g channel */ + wl_proxd_seq_config_t seq_5g20; + wl_proxd_seq_config_t seq_2g20; /* Thresh crossing params for 2G Sequence */ + uint16 bitflip_thresh; /* bitflip threshold */ + uint16 snr_thresh; /* SNR threshold */ + int8 recv_2g_thresh; /* 2g recieve sensitivity threshold */ + uint8 PAD[3]; + uint32 acs_gdv_thresh; + int8 acs_rssi_thresh; + uint8 smooth_win_en; + uint16 PAD; + int32 acs_gdmm_thresh; + int8 acs_delta_rssi_thresh; + uint8 PAD[3]; + int32 emu_delay; + uint8 core_mask; /* core mask selection */ + uint8 PAD[3]; +} wl_proxd_params_tof_tune_v3_t; + +typedef struct wl_proxd_params_iovar { + uint16 method; /**< Proximity Detection method */ + uint8 PAD[2]; + union { + /* common params for pdsvc */ + wl_proxd_params_common_t cmn_params; /**< common parameters */ + /* method specific */ + wl_proxd_params_rssi_method_t rssi_params; /**< RSSI method parameters */ + wl_proxd_params_tof_method_t tof_params; /**< TOF method parameters */ + /* tune parameters */ + wl_proxd_params_tof_tune_v3_t tof_tune; /**< TOF tune parameters */ + } u; /**< Method specific optional parameters */ +} wl_proxd_params_iovar_t; + +#define PROXD_COLLECT_GET_STATUS 0 #define PROXD_COLLECT_SET_STATUS 1 #define PROXD_COLLECT_QUERY_HEADER 2 #define PROXD_COLLECT_QUERY_DATA 3 @@ -7689,11 +9013,10 @@ typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_header { uint8 phyver; /**< phy version */ struct ether_addr localMacAddr; /**< local mac address */ struct ether_addr remoteMacAddr; /**< remote mac address */ - wl_proxd_params_tof_tune_t params; + wl_proxd_params_tof_tune_v3_t params; } BWL_POST_PACKED_STRUCT wl_proxd_collect_header_t; #include - /* ifdef WL_NAN */ /* ********************** NAN wl interface struct types and defs ******************** */ /* @@ -7710,35 +9033,81 @@ typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_header { * Bit 0 : If set to 1, means event uses nan bsscfg, * otherwise uses infra bsscfg. Default is using infra bsscfg */ -#define WL_NAN_CTRL_ROUTE_EVENT_VIA_NAN_BSSCFG 0x1 +#define WL_NAN_CTRL_ROUTE_EVENT_VIA_NAN_BSSCFG 0x000001 /* If set, discovery beacons are transmitted on 2G band */ -#define WL_NAN_CTRL_DISC_BEACON_TX_2G 0x2 +#define WL_NAN_CTRL_DISC_BEACON_TX_2G 0x000002 /* If set, sync beacons are transmitted on 2G band */ -#define WL_NAN_CTRL_SYNC_BEACON_TX_2G 0x4 +#define WL_NAN_CTRL_SYNC_BEACON_TX_2G 0x000004 /* If set, discovery beacons are transmitted on 5G band */ -#define WL_NAN_CTRL_DISC_BEACON_TX_5G 0x8 +#define WL_NAN_CTRL_DISC_BEACON_TX_5G 0x000008 /* If set, sync beacons are transmitted on 5G band */ -#define WL_NAN_CTRL_SYNC_BEACON_TX_5G 0x10 +#define WL_NAN_CTRL_SYNC_BEACON_TX_5G 0x000010 /* If set, auto datapath responses will be sent by FW */ -#define WL_NAN_CTRL_AUTO_DPRESP 0x20 +#define WL_NAN_CTRL_AUTO_DPRESP 0x000020 /* If set, auto datapath confirms will be sent by FW */ -#define WL_NAN_CTRL_AUTO_DPCONF 0x40 +#define WL_NAN_CTRL_AUTO_DPCONF 0x000040 +/* If set, auto schedule responses will be sent by FW */ +#define WL_NAN_CTRL_AUTO_SCHEDRESP 0x000080 +/* If set, auto schedule confirms will be sent by FW */ +#define WL_NAN_CTRL_AUTO_SCHEDCONF 0x000100 +/* If set, proprietary rates are supported by FW */ +#define WL_NAN_CTRL_PROP_RATE 0x000200 +/* If set, service awake_dw overrides global dev awake_dw */ +#define WL_NAN_CTRL_SVC_OVERRIDE_DEV_AWAKE_DW 0x000400 +/* If set, merge scan will be disabled */ +#define WL_NAN_CTRL_SCAN_DISABLE 0x000800 +/* If set, power save will be disabled */ +#define WL_NAN_CTRL_POWER_SAVE_DISABLE 0x001000 +/* If set, device will merge to configured CID only */ +#define WL_NAN_CTRL_MERGE_CONF_CID_ONLY 0x002000 +/* If set, 5g core will be brought down in single band NAN */ +#define WL_NAN_CTRL_5G_SLICE_POWER_OPT 0x004000 +#define WL_NAN_CTRL_DUMP_HEAP 0x008000 +/* If set, host generates and assign ndp id for ndp sessions */ +#define WL_NAN_CTRL_HOST_GEN_NDPID 0x010000 +/* If set, nan ndp inactivity watchdog will be activated */ +#define WL_NAN_CTRL_DELETE_INACTIVE_PEERS 0x020000 +/* If set, nan assoc coex will be activated */ +#define WL_NAN_CTRL_INFRA_ASSOC_COEX 0x040000 +/* If set, dam will accept all NDP/RNG request from the peer including counter */ +#define WL_NAN_CTRL_DAM_ACCEPT_ALL 0x080000 +/* If set, nan mac ignores role for tx discovery beacon for periodic config */ +#define WL_NAN_CTRL_FASTDISC_IGNO_ROLE 0x100000 +/* If set, include NA in NAN beacons (disc beacons for now) */ +#define WL_NAN_CTRL_INCL_NA_IN_BCNS 0x200000 +/* If set, host assist will be enabled */ +#define WL_NAN_CTRL_HOST_ASSIST 0x400000 +#define WL_NAN_CTRL_HOST_NDP_INFO 0x800000 /* Value when all host-configurable bits set */ #define WL_NAN_CTRL_MAX_MASK 0xFFFFFF #define WL_NAN_CFG_CTRL_FW_BITS 8 -/* Bit 31: +/* Last 8-bits are firmware controlled bits. + * Bit 31: * If set - indicates that NAN initialization is successful - * NOTE: This is a ready-only bit. All sets to this are masked off + * Bit 30: + * If set - indicates that NAN MAC cfg creation is successful + * + * NOTE: These are only ready-only bits for host. + * All sets to these bits from host are masked off */ -#define WL_NAN_PROTO_INIT_DONE 0x80000000 +#define WL_NAN_PROTO_INIT_DONE (1 << 31) +#define WL_NAN_CFG_CREATE_DONE (1 << 30) + #define WL_NAN_GET_PROTO_INIT_STATUS(x) \ - (((x) >> 31) & 1) + (((x) & WL_NAN_PROTO_INIT_DONE) ? TRUE:FALSE) #define WL_NAN_CLEAR_PROTO_INIT_STATUS(x) \ ((x) &= ~WL_NAN_PROTO_INIT_DONE) #define WL_NAN_SET_PROTO_INIT_STATUS(x) \ - ((x) |= (1 << 31)) + ((x) |= (WL_NAN_PROTO_INIT_DONE)) + +#define WL_NAN_GET_CFG_CREATE_STATUS(x) \ + (((x) & WL_NAN_CFG_CREATE_DONE) ? TRUE:FALSE) +#define WL_NAN_CLEAR_CFG_CREATE_STATUS(x) \ + ((x) &= ~WL_NAN_CFG_CREATE_DONE) +#define WL_NAN_SET_CFG_CREATE_STATUS(x) \ + ((x) |= (WL_NAN_CFG_CREATE_DONE)) #define WL_NAN_IOCTL_VERSION 0x2 /* < some sufficient ioc buff size for our module */ @@ -7814,6 +9183,64 @@ typedef struct wl_nan_event_replied { uint8 attr_list[0]; /* attributes payload */ } wl_nan_event_replied_t; +/* NAN Tx status of transmitted frames */ +#define WL_NAN_TXS_FAILURE 0 +#define WL_NAN_TXS_SUCCESS 1 + +/* NAN frame types */ +enum wl_nan_frame_type { + /* discovery frame types */ + WL_NAN_FRM_TYPE_PUBLISH = 1, + WL_NAN_FRM_TYPE_SUBSCRIBE = 2, + WL_NAN_FRM_TYPE_FOLLOWUP = 3, + + /* datapath frame types */ + WL_NAN_FRM_TYPE_DP_REQ = 4, + WL_NAN_FRM_TYPE_DP_RESP = 5, + WL_NAN_FRM_TYPE_DP_CONF = 6, + WL_NAN_FRM_TYPE_DP_INSTALL = 7, + WL_NAN_FRM_TYPE_DP_END = 8, + + /* schedule frame types */ + WL_NAN_FRM_TYPE_SCHED_REQ = 9, + WL_NAN_FRM_TYPE_SCHED_RESP = 10, + WL_NAN_FRM_TYPE_SCHED_CONF = 11, + WL_NAN_FRM_TYPE_SCHED_UPD = 12, + + /* ranging frame types */ + WL_NAN_FRM_TYPE_RNG_REQ = 13, + WL_NAN_FRM_TYPE_RNG_RESP = 14, + WL_NAN_FRM_TYPE_RNG_TERM = 15, + WL_NAN_FRM_TYPE_RNG_REPORT = 16, + WL_NAN_FRM_TYPE_INVALID +}; +typedef uint8 wl_nan_frame_type_t; + +/* NAN Reason codes for tx status */ +enum wl_nan_txs_reason_codes { + WL_NAN_REASON_SUCCESS = 1, /* NAN status success */ + WL_NAN_REASON_TIME_OUT = 2, /* timeout reached */ + WL_NAN_REASON_DROPPED = 3, /* pkt dropped due to internal failure */ + WL_NAN_REASON_MAX_RETRIES_DONE = 4 /* Max retries exceeded */ +}; + +/* For NAN TX status */ +typedef struct wl_nan_event_txs { + uint8 status; /* For TX status, success or failure */ + uint8 reason_code; /* to identify reason when status is failure */ + uint16 host_seq; /* seq num to keep track of pkts sent by host */ + uint8 type; /* frame type */ + uint8 pad; + uint16 opt_tlvs_len; + uint8 opt_tlvs[]; +} wl_nan_event_txs_t; + +/* SD transmit pkt's event status is sent as optional tlv in wl_nan_event_txs_t */ +typedef struct wl_nan_event_sd_txs { + uint8 inst_id; /* Publish or subscribe instance id */ + uint8 req_id; /* Requestor instance id */ +} wl_nan_event_sd_txs_t; + /* Subscribe or Publish instance Terminated */ /* WL_NAN_EVENT_TERMINATED */ @@ -7827,7 +9254,8 @@ typedef struct wl_nan_ev_terminated { uint8 instance_id; /* publish / subscribe instance id */ uint8 reason; /* 1=timeout, 2=Host/IOVAR, 3=FW Terminated 4=Failure */ uint8 svctype; /* 0 - Publish, 0x1 - Subscribe */ - uint8 pad; /* Align */ + uint8 pad; /* Align */ + uint32 tx_cnt; /* Number of SDFs sent */ } wl_nan_ev_terminated_t; /* Follow up received against a pub / subscr */ @@ -7843,6 +9271,34 @@ typedef struct wl_nan_ev_receive { uint8 attr_list[0]; /* attributes payload */ } wl_nan_ev_receive_t; +/* For NAN event mask extention */ +#define WL_NAN_EVMASK_EXTN_VER 1 +#define WL_NAN_EVMASK_EXTN_LEN 16 /* 16*8 = 128 masks supported */ + +typedef struct wl_nan_event_extn { + uint8 ver; + uint8 pad; + uint16 len; + uint8 evmask[]; +} wl_nan_evmask_extn_t; + +/* WL_NAN_XTLV_DATA_DP_TXS */ + +typedef struct wl_nan_data_dp_txs { + uint8 ndp_id; + uint8 pad; + struct ether_addr indi; /* initiator ndi */ +} wl_nan_data_dp_txs_t; + +/* WL_NAN_XTLV_RNG_TXS */ + +typedef struct wl_nan_range_txs { + uint8 range_id; + uint8 pad[3]; +} wl_nan_range_txs_t; + +#define NAN_MAX_BANDS 2 + /* * TLVs - Below XTLV definitions will be deprecated * in due course (soon as all other branches update @@ -7868,7 +9324,8 @@ enum wl_nan_cmd_xtlv_id { WL_NAN_XTLV_BCN_RX = 0x130, WL_NAN_XTLV_REPLIED = 0x131, /* Publish sent for a subscribe */ WL_NAN_XTLV_RECEIVED = 0x132, /* FUP Received */ - WL_NAN_XTLV_DISC_RESULTS = 0x133 /* Discovery results */ + WL_NAN_XTLV_DISC_RESULTS = 0x133, /* Discovery results */ + WL_NAN_XTLV_TXS = 0x134 /* TX status */ }; #define WL_NAN_CMD_GLOBAL 0x00 @@ -7879,6 +9336,9 @@ enum wl_nan_cmd_xtlv_id { #define WL_NAN_CMD_DATA_COMP_ID 0x05 #define WL_NAN_CMD_DAM_COMP_ID 0x06 #define WL_NAN_CMD_RANGE_COMP_ID 0x07 +#define WL_NAN_CMD_GENERIC_COMP_ID 0x08 +#define WL_NAN_CMD_SCHED_COMP_ID 0x09 +#define WL_NAN_CMD_NSR_COMP_ID 0x0a /* NAN Save Restore */ #define WL_NAN_CMD_DBG_COMP_ID 0x0f #define WL_NAN_CMD_COMP_SHIFT 8 @@ -7899,6 +9359,13 @@ typedef enum wl_nan_tlv { WL_NAN_XTLV_CFG_SEC_CSID = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x08), /* Security CSID */ WL_NAN_XTLV_CFG_SEC_PMK = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x09), /* Security PMK */ WL_NAN_XTLV_CFG_SEC_PMKID = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0A), + WL_NAN_XTLV_CFG_SEC_SCID = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0B), + WL_NAN_XTLV_CFG_VNDR_PAYLOAD = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0C), + WL_NAN_XTLV_CFG_HOST_INDPID = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0D), + /* when host ndpid is used */ + WL_NAN_XTLV_CFG_MAC_ADDR = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0E), + /* fast disc time bitmap config */ + WL_NAN_XTLV_CFG_FDISC_TBMP = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x0F), WL_NAN_XTLV_SD_SVC_INFO = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x01), WL_NAN_XTLV_SD_FOLLOWUP = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x02), @@ -7910,16 +9377,65 @@ typedef enum wl_nan_tlv { WL_NAN_XTLV_SD_REPLIED = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x08), /* Pub sent */ WL_NAN_XTLV_SD_FUP_RECEIVED = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x09), /* FUP Received */ WL_NAN_XTLV_SD_DISC_RESULTS = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0A), /* Pub RX */ + WL_NAN_XTLV_SD_TXS = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0B), /* Tx status */ + WL_NAN_XTLV_SD_SDE_SVC_INFO = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0C), + WL_NAN_XTLV_SD_SDE_SVC_UPD_IND = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0D), + WL_NAN_XTLV_SD_SVC_NDI = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0E), + WL_NAN_XTLV_SD_NDP_SPEC_INFO = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x0F), WL_NAN_XTLV_SYNC_BCN_RX = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x01), + WL_NAN_XTLV_EV_MR_CHANGED = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x02), WL_NAN_XTLV_DATA_DP_END = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x01), WL_NAN_XTLV_DATA_DP_INFO = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x02), WL_NAN_XTLV_DATA_DP_SEC_INST = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x03), - - WL_NAN_XTLV_RANGE_INFO = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x01) + WL_NAN_XTLV_DATA_DP_TXS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x04), /* txs for dp */ + WL_NAN_XTLV_DATA_DP_OPAQUE_INFO = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x05), + WL_NAN_XTLV_RANGE_INFO = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x01), + WL_NAN_XTLV_RNG_TXS = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x02), + + WL_NAN_XTLV_EV_SLOT_INFO = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x01), + WL_NAN_XTLV_EV_GEN_INFO = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x02), + WL_NAN_XTLV_CCA_STATS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x03), + WL_NAN_XTLV_PER_STATS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x04), + WL_NAN_XTLV_CHBOUND_INFO = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x05), + WL_NAN_XTLV_SLOT_STATS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x06), + + WL_NAN_XTLV_DAM_NA_ATTR = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x01), /* na attr */ + WL_NAN_XTLV_HOST_ASSIST_REQ = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x02), /* host assist */ + + WL_NAN_XTLV_GEN_FW_CAP = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x01), /* fw cap */ + + WL_NAN_XTLV_SCHED_INFO = NAN_CMD(WL_NAN_CMD_SCHED_COMP_ID, 0x01), + + /* nan save restore tlvs */ + WL_NAN_XTLV_NSR_PEER = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x01), + WL_NAN_XTLV_NSR_PEER_DEV_CAP = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x02), + WL_NAN_XTLV_NSR_PEER_AVAIL = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x03), + WL_NAN_XTLV_NSR_NDP_PARAMS = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x04), + WL_NAN_XTLV_NSR_QOS = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x05), + WL_NAN_XTLV_NSR_PEER_IES = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x07), + WL_NAN_XTLV_NSR_BLOB = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x020) /* opaque */ } wl_nan_tlv_t; +/* Sub Module ID's for NAN */ +enum { + NAN_MAC = 0, /* nan mac */ + NAN_DISC = 1, /* nan discovery */ + NAN_DBG = 2, /* nan debug */ + NAN_SCHED = 3, /* nan sched */ + NAN_PEER_ENTRY = 4, /* nan peer entry */ + NAN_AVAIL = 5, /* nan avail */ + NAN_DAM = 6, /* nan dam */ + NAN_NDP = 7, /* nan ndp */ + NAN_NDL = 8, /* nan ndl */ + NAN_DP = 9, /* nan dp core */ + NAN_FSM = 10, /* nan fsm registry */ + NAN_RNG = 11, /* nan ranging */ + NAN_SEC = 12, /* nan sec */ + NAN_LAST = 13 +}; + enum wl_nan_sub_cmd_xtlv_id { /* Special command - Tag zero */ @@ -7950,13 +9466,17 @@ enum wl_nan_sub_cmd_xtlv_id { WL_NAN_CMD_CFG_NAN_CONFIG = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x15), WL_NAN_CMD_CFG_NAN_ENAB = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x16), WL_NAN_CMD_CFG_ULW = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x17), - WL_NAN_CMD_CFG_MAX = WL_NAN_CMD_CFG_NAN_ENAB, + WL_NAN_CMD_CFG_VNDR_IE = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x18), /* To be re-used */ + WL_NAN_CMD_CFG_DEV_CAP = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x19), + WL_NAN_CMD_CFG_SCAN_PARAMS = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x1A), + WL_NAN_CMD_CFG_VNDR_PAYLOAD = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x1B), + WL_NAN_CMD_CFG_FASTDISC = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x1C), + WL_NAN_CMD_CFG_MIN_TX_RATE = NAN_CMD(WL_NAN_CMD_CFG_COMP_ID, 0x1D), + WL_NAN_CMD_CFG_MAX = WL_NAN_CMD_CFG_MIN_TX_RATE, + /* Add new commands before and update */ /* nan election sub-commands */ - WL_NAN_CMD_ELECTION_JOIN = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x04), /* Deprecated */ - WL_NAN_CMD_ELECTION_STOP = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x07), /* Deprecate */ - WL_NAN_CMD_ELECTION_HOST_ENABLE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x01), WL_NAN_CMD_ELECTION_METRICS_CONFIG = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x02), WL_NAN_CMD_ELECTION_METRICS_STATE = NAN_CMD(WL_NAN_CMD_ELECTION_COMP_ID, 0x03), @@ -8007,7 +9527,9 @@ enum wl_nan_sub_cmd_xtlv_id { WL_NAN_CMD_DATA_DATACONF = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0E), WL_NAN_CMD_DATA_MIN_TX_RATE = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x0F), WL_NAN_CMD_DATA_MAX_PEERS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x10), - WL_NAN_CMD_DATA_PATH_MAX = WL_NAN_CMD_DATA_MAX_PEERS, /* New ones before and update */ + WL_NAN_CMD_DATA_DP_IDLE_PERIOD = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x11), + WL_NAN_CMD_DATA_DP_OPAQUE_INFO = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x12), + WL_NAN_CMD_DATA_PATH_MAX = WL_NAN_CMD_DATA_DP_OPAQUE_INFO, /* New ones before and update */ /* nan dam sub-commands */ WL_NAN_CMD_DAM_CFG = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x01), @@ -8036,12 +9558,393 @@ enum wl_nan_sub_cmd_xtlv_id { WL_NAN_CMD_DBG_DISC_RESULTS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0D), WL_NAN_CMD_DBG_STATS = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0E), WL_NAN_CMD_DBG_LEVEL = NAN_CMD(WL_NAN_CMD_DBG_COMP_ID, 0x0F), - WL_NAN_CMD_DBG_MAX = WL_NAN_CMD_DBG_LEVEL /* New ones before and update */ + WL_NAN_CMD_DBG_MAX = WL_NAN_CMD_DBG_LEVEL, /* New ones before and update */ + + /* Reinit sub commands */ + WL_NAN_CMD_NSR = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x01), + WL_NAN_CMD_NSR_DP_SESSION = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x02), + WL_NAN_CMD_NSR_SYNC = NAN_CMD(WL_NAN_CMD_NSR_COMP_ID, 0x03), + + /* Generic componenet */ + WL_NAN_CMD_GEN_STATS = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x01), + WL_NAN_CMD_GEN_FW_CAP = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x02), + + WL_NAN_CMD_GEN_MAX = WL_NAN_CMD_GEN_FW_CAP /* New ones before and update */ }; +/* NAN NSR command : NAN Save Restore */ +/* WL_NAN_XTLV_NSR_PEER_ADD */ +typedef struct wl_nan_nsr_peer_add { + struct ether_addr nmi; + uint8 sched_merged; /* peer schedule merged to local device schedule or not */ + uint8 ref_cnt; /* number of references or struct usage count */ + uint ies_len; +} wl_nan_nsr_peer_add_t; + +/* WL_NAN_XTLV_NSR_PEER_DEV_CAP */ +typedef struct wl_nan_peer_stats_dev_cap wl_nan_peer_dev_cap_t; + +/* WL_NAN_XTLV_NSR_PEER_AVAIL */ +/* This TLV is same as WL_NAN_CMD_CFG_AVAIL which is an existing TLV */ + +/* WL_NAN_XTLV_NSR_QOS */ +typedef struct wl_nan_nsr_qos { + uint16 local_max_latency; + uint16 peer_max_latency; + uint8 local_min_slots; + uint8 peer_min_slots; +} wl_nan_nsr_qos_t; + +/* WL_NAN_XTLV_NSR_NDP_PARAMS */ +typedef struct wl_nan_nsr_ndp { + uint8 ndp_id; /* Local ndp id */ + uint8 indp_id; /* Initiator ndp id, (either peer's or local) */ + uint8 lndc_id; /* refers to the selected ndc avail from above */ + uint8 flags; /* FSM role etc */ + struct ether_addr lndi_addr; + struct ether_addr pndi_addr; + uint8 pub_id; /* Publish id */ + uint8 type; /* Unicast or Multicast */ + uint8 ndp_ctrl; /* ndp control field */ + uint8 qos[8]; /* qos for this ndp */ +} wl_nan_nsr_ndp_t; + +typedef struct wl_nan_nsr_dp_session { + uint8 indp_id; /* Initiator ndp id, (either peer's or local) */ + struct ether_addr init_addr; /* Initiator mac address */ + uint8 pad[1]; +} wl_nan_nsr_dp_session_t; + +typedef enum wl_nan_nsr_cmd_type { + WL_NAN_NSR_CMD_FLAG_DP_SESSION = 0x0001, + WL_NAN_NSR_CMD_FLAG_PEER = 0x0002, + WL_NAN_NSR_CMD_FLAG_DAM = 0x0004, + WL_NAN_NSR_CMD_FLAG_SYNC = 0x0008 +} wl_nan_nsr_cmd_type_t; + +typedef struct wl_nan_nsr_cmd { + uint16 cmd; /* Command Flags */ + uint8 pad[2]; + uint8 tlvs[]; +} wl_nan_nsr_cmd_t; + +#define WL_NAN_CMD_NSR_SIZE 1024 + +/* + * Component/Module based NAN TLV IDs for NAN stats + */ +typedef enum wl_nan_stats_tlv { + WL_NAN_XTLV_SYNC_MAC_STATS = NAN_CMD(WL_NAN_CMD_SYNC_COMP_ID, 0x01), + + WL_NAN_XTLV_SD_DISC_STATS = NAN_CMD(WL_NAN_CMD_SD_COMP_ID, 0x01), + + WL_NAN_XTLV_DATA_NDP_STATS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x01), + WL_NAN_XTLV_DATA_NDL_STATS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x02), + WL_NAN_XTLV_DATA_SEC_STATS = NAN_CMD(WL_NAN_CMD_DATA_COMP_ID, 0x03), + + WL_NAN_XTLV_GEN_SCHED_STATS = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x01), + WL_NAN_XTLV_GEN_PEER_STATS = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x02), + WL_NAN_XTLV_GEN_PEER_STATS_DEVCAP = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x03), + WL_NAN_XTLV_GEN_PEER_STATS_NDP = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x04), + WL_NAN_XTLV_GEN_PEER_STATS_SCHED = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x05), + WL_NAN_XTLV_GEN_AVAIL_STATS_SCHED = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x06), + WL_NAN_XTLV_GEN_NDP_STATS = NAN_CMD(WL_NAN_CMD_GENERIC_COMP_ID, 0x07), + + WL_NAN_XTLV_DAM_STATS = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x01), + WL_NAN_XTLV_DAM_AVAIL_STATS = NAN_CMD(WL_NAN_CMD_DAM_COMP_ID, 0x02), + + WL_NAN_XTLV_RANGE_STATS = NAN_CMD(WL_NAN_CMD_RANGE_COMP_ID, 0x01) +} wl_nan_stats_tlv_t; + +/* NAN stats WL_NAN_CMD_GEN_STATS command */ +/* Input data */ +typedef struct wl_nan_cmn_get_stat { + uint32 modules_btmap; /* Bitmap to indicate module stats are needed: + * See NAN Sub Module ID's above + */ + uint8 operation; /* Get, Get and Clear */ + uint8 arg1; /* Submodule control variable1 */ + uint8 arg2; /* Submodule control variable2 */ + uint8 pad; /* May not be needed as TLV's are aligned,add to pass compile chk */ +} wl_nan_cmn_get_stat_t; + +/* Output for Stats container */ +typedef struct wl_nan_cmn_stat { + uint32 n_stats; /* Number of different sub TLV stats present in the container */ + uint32 totlen; /* Total Length of stats data in container */ + uint8 stats_tlvs []; /* Stat TLV's container */ +} wl_nan_cmn_stat_t; + +/* Defines for operation */ +#define WLA_NAN_STATS_GET 0 +#define WLA_NAN_STATS_GET_CLEAR 1 + +#define WL_NAN_STAT_ALL 0xFFFFFFFF + +/* NAN Mac stats */ + +typedef struct wl_nan_mac_band_stats { + uint32 bcn_tx; /* 2g/5g disc/sync beacon tx count */ + uint32 bcn_rx; /* 2g/5g disc/sync beacon rx count */ + uint32 dws; /* Number of 2g/5g DW's */ +} wl_nan_mac_band_stats_t; + +typedef struct wl_nan_mac_stats { + wl_nan_mac_band_stats_t band[NAN_MAX_BANDS]; /* MAC sync band specific stats */ + uint32 naf_tx; /* NAN AF tx */ + uint32 naf_rx; /* NAN AF rx */ + uint32 sdf_tx; /* SDF tx */ + uint32 sdf_rx; /* SDF rx */ +} wl_nan_mac_stats_t; + +/* NAN Sched stats */ +/* Per core Sched stats */ +typedef struct nan_sched_stats_core { + uint32 slotstart; /* slot_start */ + uint32 slotend; /* slot_end */ + uint32 slotskip; /* slot_skip */ + uint32 slotstart_partial; /* slot resume */ + uint32 slotend_partial; /* slot pre-empt */ +} nan_sched_stats_core_t; +/* Common Sched stats */ +typedef struct nan_sched_stats_cmn { + uint32 slot_adj_dw; /* Slot adjusts due to DW changes */ + uint32 slot_dur; /* Total slot duration in TU's */ +} nan_sched_stats_cmn_t; + +typedef struct nan_sched_stats { + nan_sched_stats_cmn_t cmn; + nan_sched_stats_core_t slice[MAX_NUM_D11CORES]; +} nan_sched_stats_t; +/* End NAN Sched stats */ + +/* NAN Discovery stats */ +typedef struct nan_disc_stats { + uint32 pub_tx; /* Publish tx */ + uint32 pub_rx; /* Publish rx */ + uint32 sub_tx; /* Subscribe tx */ + uint32 sub_rx; /* Subscribe rx */ + uint32 fup_tx; /* Followup tx */ + uint32 fup_rx; /* Followup rx */ + uint32 pub_resp_ignored; /* response to incoming publish ignored */ + uint32 sub_resp_ignored; /* response to incoming subscribe ignored */ +} nan_disc_stats_t; +/* NAN Discovery stats end */ + +/* statistics for nan sec */ +typedef struct nan_sec_stats_s { + uint32 mic_fail; /* rx mic fail */ + uint32 replay_fail; /* replay counter */ + uint32 tx_fail; /* tx fail (from txstatus) */ + uint32 key_info_err; /* key info field err */ + uint32 ok_sessions; /* successful mx negotiations */ + uint32 fail_sessions; /* failed sessions */ + uint32 keydesc_err; /* key desc error */ + uint32 invalid_cipher; /* cipher suite not valid */ + uint32 pmk_not_found; /* no pmk found for given service or for any reason */ + uint32 no_pmk_for_pmkid; /* no pmk found for give pmkid */ + uint32 key_install_err; /* failed to install keys */ + uint32 no_keydesc_attr; /* key desc attr missing */ + uint32 nonce_mismatch; /* nonce mismatch */ +} nan_sec_stats_t; + +/* WL_NAN_XTLV_GEN_PEER_STATS */ +typedef struct wl_nan_peer_stats { + struct ether_addr nmi; + uint8 pad[2]; + uint32 pkt_enq; /* counter for queued pkt of peer */ + + /* NDL */ + bool ndl_exist; + uint8 ndl_state; + bool counter_proposed; + uint8 pad1; + + /* NDL QoS */ + uint16 local_max_latency; + uint16 peer_max_latency; + uint8 local_min_slots; + uint8 peer_min_slots; + + /* security association */ + struct ether_addr sec_laddr; /* local mac addr */ + struct ether_addr sec_raddr; /* remote mac addr */ + uint8 sec_csid; + uint8 pad2; +} wl_nan_peer_stats_t; + +/* WL_NAN_XTLV_GEN_PEER_STATS_DEVCAP */ +typedef struct wl_nan_peer_stats_dev_cap { + uint8 mapid; + uint8 awake_dw_2g; + uint8 awake_dw_5g; + uint8 bands_supported; + uint8 op_mode; + uint8 num_antennas; + uint16 chan_switch_time; + uint8 capabilities; + uint8 pad[3]; +} wl_nan_peer_stats_dev_cap_t; + +/* WL_NAN_XTLV_GEN_PEER_STATS_NDP */ +typedef struct wl_nan_peer_stats_ndp { + uint8 peer_role; + uint8 ndp_state; + uint8 indp_id; /* initiator ndp id */ + uint8 ndp_ctrl; /* ndp control field */ + struct ether_addr peer_nmi; + struct ether_addr peer_ndi; + struct ether_addr local_ndi; + + /* peer scb info */ + bool scb_allocated; + bool scb_found; + uint32 scb_flags; + uint32 scb_flags2; + uint32 scb_flags3; +} wl_nan_peer_stats_ndp_t; + +enum { + WL_NAN_SCHED_STAT_SLOT_COMM = 0x01, /* Committed slot */ + WL_NAN_SCHED_STAT_SLOT_COND = 0x02, /* Conditional slot(proposal/counter) */ + WL_NAN_SCHED_STAT_SLOT_NDC = 0x04, /* NDC slot */ + WL_NAN_SCHED_STAT_SLOT_IMMUT = 0x08, /* Immutable slot */ + WL_NAN_SCHED_STAT_SLOT_RANGE = 0x10, /* Ranging slot */ +}; +typedef uint16 wl_nan_stats_sched_slot_info_t; + +typedef struct wl_nan_stats_sched_slot { + wl_nan_stats_sched_slot_info_t info; /* capture slot type and more info */ + chanspec_t chanspec; +} wl_nan_stats_sched_slot_t; + +/* WL_NAN_XTLV_GEN_PEER_STATS_SCHED, WL_NAN_XTLV_GEN_AVAIL_STATS_SCHED */ +typedef struct wl_nan_stats_sched { + uint8 map_id; + uint8 seq_id; /* seq id from NA attr */ + uint8 slot_dur; + uint8 pad; + uint16 period; + uint16 num_slot; + wl_nan_stats_sched_slot_t slot[]; +} wl_nan_stats_sched_t; + +/* WL_NAN_XTLV_GEN_PEER_STATS_SCHED */ +typedef struct wl_nan_peer_stats_sched { + uint8 map_id; + uint8 seq_id; /* seq id from NA attr */ + uint8 slot_dur; + uint8 pad; + uint16 period; + uint16 num_slot; + wl_nan_stats_sched_slot_t slot[]; +} wl_nan_peer_stats_sched_t; + +/* WL_NAN_XTLV_RANGE_STATS */ +typedef struct wl_nan_range_stats { + uint16 rng_ssn_estb; + uint16 rng_ssn_fail; + uint16 rng_sched_start; + uint16 rng_sched_end; + uint16 ftm_ssn_success; /* number of succesfull ftm sessions */ + uint16 ftm_ssn_fail; + uint16 num_meas; /* number of ftm frames */ + uint16 num_valid_meas; /* number of ftm frames with valid timestamp */ +} wl_nan_range_stats_t; + +/* defines for ndp stats flag */ + +#define NAN_NDP_STATS_FLAG_ROLE_MASK 0x01 +#define NAN_NDP_STATS_FLAG_ROLE_INIT 0x00 +#define NAN_NDP_STATS_FLAG_ROLE_RESP 0x01 + +#define NAN_NDP_STATS_STATE_BIT_SHIFT 1 +#define NAN_NDP_STATS_FLAG_STATE_MASK 0x07 +#define NAN_NDP_STATS_FLAG_STATE_IN_PROG 0x00 +#define NAN_NDP_STATS_FLAG_STATE_ESTB 0x01 +#define NAN_NDP_STATS_FLAG_STATE_TEARDOWN_WAIT 0x02 +/* More states can be added here, when needed */ + +/* WL_NAN_XTLV_GEN_NDP_STATS */ +typedef struct wl_nan_ndp_stats_s { + uint8 ndp_id; + uint8 indp_id; + uint8 flags; + uint8 nan_sec_csid; + struct ether_addr lndi_addr; + struct ether_addr pnmi_addr; + struct ether_addr pndi_addr; + uint8 PAD[2]; +} wl_nan_ndp_stats_t; + +/* WL_NAN_XTLV_EV_SLOT_INFO */ +typedef struct wl_nan_slot_info_s { + /* dw slot start expected */ + uint32 dwst_h; + uint32 dwst_l; + /* dw slot start actual */ + uint32 act_dwst_h; + uint32 act_dwst_l; + uint16 cur_chan[MAX_NUM_D11CORES]; /* sdb channels */ + uint16 dw_chan; /* dw channel */ + uint8 dw_no; /* dw number */ + uint8 slot_seq_no; /* slot seq no. */ +} wl_nan_slot_info_t; + +/* WL_NAN_EVENT_MR_CHANGED */ +typedef uint8 wl_nan_mr_changed_t; +#define WL_NAN_AMR_CHANGED 1 +#define WL_NAN_IMR_CHANGED 2 + /** status - TBD BCME_ vs NAN status - range reserved for BCME_ */ enum { /* add new status here... */ + WL_NAN_E_BCMC_PDPA = -2122, /* BCMC NAF PDPA */ + WL_NAN_E_TIMEOUT = -2121, + WL_NAN_E_HOST_CFG = -2120, + WL_NAN_E_NO_ACK = -2119, + WL_NAN_E_SECINST_FAIL = -2118, + WL_NAN_E_REJECT_NDL = -2117, /* generic NDL rejection error */ + WL_NAN_E_INVALID_NDP_ATTR = -2116, + WL_NAN_E_HOST_REJECTED = -2115, + WL_NAN_E_PCB_NORESOURCE = -2114, + WL_NAN_E_NDC_EXISTS = -2113, + WL_NAN_E_NO_NDC_ENTRY_AVAIL = -2112, + WL_NAN_E_INVALID_NDC_ENTRY = -2111, + WL_NAN_E_SD_TX_LIST_FULL = -2110, + WL_NAN_E_SVC_SUB_LIST_FULL = -2109, + WL_NAN_E_SVC_PUB_LIST_FULL = -2108, + WL_NAN_E_SDF_MAX_LEN_EXCEEDED = -2107, + WL_NAN_E_ZERO_CRB = -2106, /* no CRB between local and peer */ + WL_NAN_E_PEER_NDC_NOT_SELECTED = -2105, /* peer ndc not selected */ + WL_NAN_E_DAM_CHAN_CONFLICT = -2104, /* dam schedule channel conflict */ + WL_NAN_E_DAM_SCHED_PERIOD = -2103, /* dam schedule period mismatch */ + WL_NAN_E_LCL_NDC_NOT_SELECTED = -2102, /* local selected ndc not configured */ + WL_NAN_E_NDL_QOS_INVALID_NA = -2101, /* na doesn't comply with ndl qos */ + WL_NAN_E_CLEAR_NAF_WITH_SA_AS_RNDI = -2100, /* rx clear naf with peer rndi */ + WL_NAN_E_SEC_CLEAR_PKT = -2099, /* rx clear pkt from a peer with sec_sa */ + WL_NAN_E_PROT_NON_PDPA_NAF = -2098, /* rx protected non PDPA frame */ + WL_NAN_E_DAM_DOUBLE_REMOVE = -2097, /* remove peer schedule already removed */ + WL_NAN_E_DAM_DOUBLE_MERGE = -2096, /* merge peer schedule already merged */ + WL_NAN_E_DAM_REJECT_INVALID = -2095, /* reject for invalid schedule */ + WL_NAN_E_DAM_REJECT_RANGE = -2094, + WL_NAN_E_DAM_REJECT_QOS = -2093, + WL_NAN_E_DAM_REJECT_NDC = -2092, + WL_NAN_E_DAM_REJECT_PEER_IMMUT = -2091, + WL_NAN_E_DAM_REJECT_LCL_IMMUT = -2090, + WL_NAN_E_DAM_EXCEED_NUM_SCHED = -2089, + WL_NAN_E_DAM_INVALID_SCHED_MAP = -2088, /* invalid schedule map list */ + WL_NAN_E_DAM_INVALID_LCL_SCHED = -2087, + WL_NAN_E_INVALID_MAP_ID = -2086, + WL_NAN_E_CHAN_OVERLAP_ACROSS_MAP = -2085, + WL_NAN_E_INVALID_CHAN_LIST = -2084, + WL_NAN_E_INVALID_RANGE_TBMP = -2083, + WL_NAN_E_INVALID_IMMUT_SCHED = -2082, + WL_NAN_E_INVALID_NDC_ATTR = -2081, + WL_NAN_E_INVALID_TIME_BITMAP = -2080, + WL_NAN_E_INVALID_NA_ATTR = -2079, + WL_NAN_E_NO_NA_ATTR_IN_AVAIL_MAP = -2078, /* no na attr saved in avail map */ + WL_NAN_E_INVALID_MAP_IDX = -2077, WL_NAN_E_SEC_SA_NOTFOUND = -2076, WL_NAN_E_BSSCFG_NOTFOUND = -2075, WL_NAN_E_SCB_NOTFOUND = -2074, @@ -8071,13 +9974,34 @@ enum { WL_NAN_E_INVALID_BAND = -2050, WL_NAN_E_INVALID_MAC = -2049, WL_NAN_E_BAD_INSTANCE = -2048, - WL_NAN_E_NDC_EXISTS = -2047, - WL_NAN_E_NO_NDC_ENTRY_AVAIL = -2046, - WL_NAN_E_INVALID_NDC_ENTRY = -2045, + /* NAN status code reserved from -2048 to -3071 */ WL_NAN_E_ERROR = -1, WL_NAN_E_OK = 0 }; +/* Error codes used in vendor specific attribute in Data Path Termination frames */ +enum { + WL_NAN_DPEND_E_OK = 0, + WL_NAN_DPEND_E_ERROR = 1, + WL_NAN_DPEND_E_HOST_CMD = 2, + WL_NAN_DPEND_E_HOST_REJECTED = 3, /* host rejected rx frame */ + WL_NAN_DPEND_E_RESOURCE_LIMIT = 4, + WL_NAN_DPEND_E_NO_ACK_RCV = 5, + WL_NAN_DPEND_E_TIMEOUT = 6, + WL_NAN_DPEND_E_NO_ELT = 7, /* rx frame missing element container */ + WL_NAN_DPEND_E_NO_NDP_ATTR = 8, + WL_NAN_DPEND_E_NO_AVAIL_ATTR = 9, + WL_NAN_DPEND_E_NO_NDC_ATTR = 10, + WL_NAN_DPEND_E_NO_RANGE_BM = 11, + WL_NAN_DPEND_E_INVALID_NDP_ATTR = 12, + WL_NAN_DPEND_E_INVALID_NDC_ATTR = 13, + WL_NAN_DPEND_E_INVALID_IMMUT = 14, + WL_NAN_DPEND_E_INVALID_NDL_QOS = 15, + WL_NAN_DPEND_E_INVALID_SEC_PARAMS = 16, + WL_NAN_DPEND_E_REJECT_AVAIL = 17, + WL_NAN_DPEND_E_REJECT_NDL = 18 +}; + typedef int32 wl_nan_status_t; /** nan cmd list entry */ @@ -8190,52 +10114,9 @@ typedef struct wl_nan_rssi_thld { typedef uint8 wl_nan_max_peers_t; -#define NAN_MAX_BANDS 2 /* * WL_NAN_CMD_CFG_STATUS */ -/* Deprecated - Begin */ -typedef struct wl_nan_cfg_status { - uint8 enabled; - uint8 inited; - uint8 joined; - uint8 merged; - uint8 role; - uint8 PAD[3]; - uint32 chspec[2]; - uint8 mr[8]; /**< Master Rank */ - uint8 amr[8]; /**< Anchor Master Rank */ - uint32 cnt_pend_txfrm; /**< pending TX frames */ - uint32 cnt_bcn_tx; /**< TX disc/sync beacon count */ - uint32 cnt_bcn_rx; /**< RX disc/sync beacon count */ - uint32 cnt_svc_disc_tx; /**< TX svc disc frame count */ - uint32 cnt_svc_disc_rx; /**< RX svc disc frame count */ - uint32 ambtt; /**< Anchor master beacon target time */ - struct ether_addr cid; /**< Cluster id */ - uint8 hop_count; /**< Hop count */ - uint8 PAD; -} wl_nan_cfg_status_t; - -typedef struct wl_nan_config_status { - struct ether_addr def_cid; /* Default Cluster id */ - uint8 inited; /* NAN Initialized successfully */ - uint8 enabled; /* NAN Enabled */ - struct ether_addr cur_cid; /* Default Cluster id */ - uint8 joined; /* Joined or started own cluster */ - uint8 role; /* Master, Non Master, NM Sync & Non-Sync */ - chanspec_t chspec[NAN_MAX_BANDS]; /* Channel Spec 2.4G followed by 5G */ - uint8 mr[WL_NAN_MASTER_RANK_LEN]; /* Master Rank */ - uint8 amr[WL_NAN_MASTER_RANK_LEN]; /* Anchor Master Rank */ - uint32 cnt_pend_txfrm; /* Pending Tx Frames */ - uint32 cnt_bcn_tx; /* TX disc/sync beacon count */ - uint32 cnt_bcn_rx; /* RX disc/sync beacon count */ - uint32 cnt_svc_disc_tx; /* TX svc disc frame count */ - uint32 cnt_svc_disc_rx; /* RX svc disc frame count */ - uint32 ambtt; /* Anchor master beacon target time */ - uint8 hop_count; /* Hop count */ - uint8 pad[3]; /* Align */ -} wl_nan_config_status_t; -/* Deprecated - End */ typedef enum wl_nan_election_mode { WL_NAN_ELECTION_RUN_BY_HOST = 1, @@ -8248,14 +10129,17 @@ typedef struct wl_nan_conf_status { uint8 role; /* Current nan sync role */ struct ether_addr cid; /* Current Cluster id */ uint8 social_chans[2]; /* Social channels */ - uint8 mr[8]; /* Master Rank */ + uint8 mr[8]; /* Self Master Rank */ uint8 amr[8]; /* Anchor Master Rank */ uint32 ambtt; /* Anchor master beacon target time */ uint32 cluster_tsf_h; /* Current Cluster TSF High */ uint32 cluster_tsf_l; /* Current Cluster TSF Low */ uint8 election_mode; /* Election mode, host or firmware */ uint8 hop_count; /* Current Hop count */ - uint8 pad[2]; + uint8 imr[8]; /* Immediate Master Rank */ + uint8 pad[4]; + uint16 opt_tlvs_len; + uint8 opt_tlvs[]; } wl_nan_conf_status_t; /* @@ -8316,15 +10200,6 @@ typedef struct wl_nan_election_metric_state { */ typedef struct ether_addr wl_nan_cluster_id_t; -/* - * WL_NAN_CMD_ELECTION_JOIN - */ -typedef struct wl_nan_join { - uint8 start_cluster; /* Start a cluster */ - uint8 pad[3]; - wl_nan_cluster_id_t cluster_id; /* Cluster ID to join */ -} wl_nan_join_t; - /* * WL_NAN_CMD_ELECTION_MERGE * 0 - disable cluster merge @@ -8334,21 +10209,27 @@ typedef uint8 wl_nan_merge_enable_t; /* * WL_NAN_CMD_CFG_ROLE - * role = 0 means configuration by firmware; otherwise by host + * role = 0 means configuration by firmware(obsolete); otherwise by host * when host configures role, also need target master address to sync to */ -#define NAN_SYNC_MASTER_SELF 0 -#define NAN_SYNC_MASTER_AM 1 -#define NAN_SYNC_MASTER_INTERMEDIATE 2 -/* ltsf_h, ltsf_l: +#define NAN_SYNC_MASTER_SELF 1 +#define NAN_SYNC_MASTER_USE_TIMING 2 /* Use the tsf timing provided */ +#define NAN_SYNC_MASTER_AMREC_UPD 4 /* provide AM record update */ + +/* + struct ether_addr addr: + when NAN_SYNC_MASTER_USE_TIMING is set, addr is the mac of Rx NAN beacon + providing the timing info + ltsf_h, ltsf_l: The local TSF timestamp filled in by FW in the WL_NAN_EVENT_BCN_RX event; rtsf_h, rtsf_l: The timestamp in the Rx beacon frame, filled in by host uint32 ambtt: the amtt in the cluster ID attribute in the Rx beacon frame */ + typedef struct nan_sync_master { - uint8 flag; /* 0: self, 1: anchor-master, 2: intermediate master */ + uint8 flag; /* 1: self; 2: use TSF timing; 4: AMR update */ uint8 hop_count; struct ether_addr addr; struct ether_addr cluster_id; @@ -8403,6 +10284,10 @@ typedef int8 wl_nan_sd_optional_field_types_t; /* Flag bits for Publish and Subscribe (wl_nan_sd_params_t flags) */ +/* First 8 bits are blocked for mapping + * against svc_control flag bits which goes out + * as part of SDA attribute in air in SDF frames + */ #define WL_NAN_RANGE_LIMITED 0x0040 /* Event generation indicator (default is continuous) */ @@ -8421,6 +10306,7 @@ typedef int8 wl_nan_sd_optional_field_types_t; #define WL_NAN_PUB_SOLICIT_PENDING 0x10000 /* Used for one-time solicited Publish */ #define WL_NAN_FOLLOWUP 0x20000 /* Follow-up frames */ +#define WL_NAN_TX_FOLLOWUP 0x40000 /* host generated transmit Follow-up frames */ /* Bits specific to Subscribe */ @@ -8435,6 +10321,20 @@ typedef int8 wl_nan_sd_optional_field_types_t; */ #define WL_NAN_TTL_FIRST 0 +/* Nan Service Based control Flags */ + +/* If set, dev will take care of dp_resp */ +#define WL_NAN_SVC_CTRL_AUTO_DPRESP 0x1000000 + +/* If set, host wont rec event "receive" */ +#define WL_NAN_SVC_CTRL_SUPPRESS_EVT_RECEIVE 0x2000000 + +/* If set, host wont rec event "replied" */ +#define WL_NAN_SVC_CTRL_SUPPRESS_EVT_REPLIED 0x4000000 + +/* If set, host wont rec event "terminated" */ +#define WL_NAN_SVC_CTRL_SUPPRESS_EVT_TERMINATED 0x8000000 + /* * WL_NAN_CMD_SD_PARAMS */ @@ -8442,7 +10342,7 @@ typedef struct wl_nan_sd_params { uint16 length; /* length including options */ uint8 period; /* period of the unsolicited SDF xmission in DWs */ - uint8 pad; + uint8 awake_dw; /* interval between two DWs where SDF tx/rx are done */ uint8 svc_hash[WL_NAN_SVC_HASH_LEN]; /* Hash for the service name */ uint8 instance_id; /* Instance of the current service */ int8 proximity_rssi; /* RSSI limit to Rx subscribe or pub SDF 0 no effect */ @@ -8563,18 +10463,27 @@ typedef struct wl_nan_sd_stats { uint32 sdmftfail4; } wl_nan_sd_stats_t; +/* Flag bits for sd transmit message (wl_nan_sd_transmit_t flags) */ + +/* If set, host wont rec "tx status" event for tx-followup msg */ +#define WL_NAN_FUP_SUPR_EVT_TXS 0x01 +/* more flags can be added here */ + /* * WL_NAN_CMD_SD_TRANSMIT * WL_NAN_CMD_SD_FUP_TRANSMIT */ typedef struct wl_nan_sd_transmit { - uint8 local_service_id; /* Sender Service ID */ - uint8 requestor_service_id; /* Destination Service ID */ - struct ether_addr destination_addr; /* Destination MAC */ - uint16 token; /* follow_up_token when a follow-up msg is queued successfully */ - uint8 priority; /* requested relative prio */ - uint8 service_info_len; /* size in bytes of the service info payload */ - uint8 service_info[]; /* Service Info payload */ + uint8 local_service_id; /* Sender Service ID */ + uint8 requestor_service_id; /* Destination Service ID */ + struct ether_addr destination_addr; /* Destination MAC */ + uint16 token; /* follow_up_token when a follow-up + * msg is queued successfully + */ + uint8 priority; /* requested relative prio */ + uint8 flags; /* Flags for tx follow-up msg */ + uint16 opt_len; /* total length of optional tlvs */ + uint8 opt_tlv[]; /* optional tlvs in bcm_xtlv_t type */ } wl_nan_sd_transmit_t; /* @@ -8596,14 +10505,18 @@ typedef uint32 wl_nan_ts_bitmap_t; /* nan passive scan params */ #define NAN_SCAN_MAX_CHCNT 8 +/* nan merge scan params */ typedef struct wl_nan_scan_params { - uint16 scan_time; - uint16 home_time; - uint16 ms_intvl; /**< interval between merge scan */ - uint16 ms_dur; /**< duration of merge scan */ - uint16 chspec_num; - uint8 pad[2]; - chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /**< act. used 3, 5 rfu */ + /* dwell time of discovery channel corresponds to band_idx. + * If set to 0 then fw default will be used. + */ + uint16 dwell_time; + /* scan period of discovery channel corresponds to band_idx. + * If set to 0 then fw default will be used. + */ + uint16 scan_period; + /* band index of discovery channel */ + uint8 band_index; } wl_nan_scan_params_t; /* @@ -8658,7 +10571,6 @@ typedef struct wl_nan_debug_params { uint8 PAD[2]; } wl_nan_debug_params_t; - typedef struct wl_nan_sched_svc_timeslot_s { uint32 abitmap; /* availability bitmap */ uint32 chanlist[NAN_MAX_TIMESLOT]; @@ -8667,18 +10579,10 @@ typedef struct wl_nan_sched_svc_timeslot_s { uint8 PAD[2]; } wl_nan_sched_svc_timeslot_t; - -/* nan passive scan params */ -#define NAN_SCAN_MAX_CHCNT 8 -typedef struct nan_scan_params { - uint16 scan_time; - uint16 home_time; - uint16 ms_intvl; /**< interval between merge scan */ - uint16 ms_dur; /**< duration of merge scan */ - uint16 chspec_num; - uint8 pad[2]; - chanspec_t chspec_list[NAN_SCAN_MAX_CHCNT]; /**< act. used 3, 5 rfu */ -} nan_scan_params_t; +/* + * WL_NAN_CMD_DATA_DP_IDLE_PERIOD + */ +typedef uint16 wl_nan_ndp_idle_period_t; /* nan cmd IDs */ enum wl_nan_cmds { @@ -8694,6 +10598,7 @@ enum wl_nan_cmds { WL_NAN_CMD_TSRELEASE = 9, WL_NAN_CMD_OUI = 10, WL_NAN_CMD_OOB_AF = 11, + WL_NAN_CMD_SCAN_PARAMS = 12, WL_NAN_CMD_COUNT = 15, WL_NAN_CMD_CLEARCOUNT = 16, @@ -8708,7 +10613,6 @@ enum wl_nan_cmds { WL_NAN_CMD_SHOW = 26, WL_NAN_CMD_STOP = 27, /* stop nan for a given cluster ID */ /* nan debug iovars & cmds */ - WL_NAN_CMD_SCAN_PARAMS = 46, WL_NAN_CMD_SCAN = 47, WL_NAN_CMD_SCAN_RESULTS = 48, WL_NAN_CMD_EVENT_MASK = 49, @@ -8746,11 +10650,12 @@ enum wl_nan_dp_cmds { #define WL_NAN_DP_MAX_SVC_INFO 0xFF #define WL_NAN_DATA_NDP_INST_SUPPORT 16 -/* Nan flags */ -#define WL_NAN_DP_FLAG_SVC_INFO (1 << 0) -#define WL_NAN_DP_FLAG_CONFIRM (1 << 1) -#define WL_NAN_DP_FLAG_EXPLICIT_CFM (1 << 2) -#define WL_NAN_DP_FLAG_SECURITY (1 << 3) +/* Nan flags (16 bits) */ +#define WL_NAN_DP_FLAG_SVC_INFO 0x0001 +#define WL_NAN_DP_FLAG_CONFIRM 0x0002 +#define WL_NAN_DP_FLAG_EXPLICIT_CFM 0x0004 +#define WL_NAN_DP_FLAG_SECURITY 0x0008 +#define WL_NAN_DP_FLAG_HAST_NDL_COUNTER 0x0010 /* Host assisted NDL counter */ /* NAN Datapath host status */ #define WL_NAN_DP_STATUS_ACCEPTED 1 @@ -8761,7 +10666,6 @@ typedef struct wl_nan_dp_cap { uint8 tbd; } wl_nan_dp_cap_t; - /** The service hash (service id) is exactly this many bytes. */ #define WL_NAN_SVC_HASH_LEN 6 /** Number of hash functions per bloom filter */ @@ -8968,6 +10872,10 @@ typedef struct wl_nan_stats { uint32 cnt_nan_enab; /* no. of times nan feature got enabled */ uint32 cnt_nan_disab; /* no. of times nan feature got disabled */ uint32 cnt_sync_bcn_rx; /* count of sync bcn rx within DW */ + uint32 cnt_sync_bcn_rx_tu[3]; /* Delta bw the tsf in bcn & remote */ + uint32 cnt_bcn_tx_out_dw; /* TX sync beacon outside dw */ + uint32 cnt_role_am_dw; /* anchor master role due to dw */ + uint32 cnt_am_hop_err; /* wrong hopcount set for AM */ } wl_nan_stats_t; #define WL_NAN_MAC_MAX_NAN_PEERS 6 @@ -9027,6 +10935,17 @@ typedef struct wl_nan_dp_qos uint16 mean_rate; uint16 svc_interval; } wl_nan_dp_qos_t; + +#define WL_NAN_NDL_QOS_MAX_LAT_NO_PREF 0xFFFF + +/* nan2 qos */ +typedef struct wl_nan_ndl_qos +{ + uint8 min_slots; /* min slots per dw interval */ + uint8 pad; + uint16 max_latency; /* max latency */ +} wl_nan_ndl_qos_t; + /* ndp config */ typedef struct wl_nan_ndp_config { @@ -9053,13 +10972,17 @@ typedef struct wl_nan_ndp_oper_cfg { typedef uint8 wl_nan_ndp_ndpid_t; typedef uint8 wl_nan_ndp_conn_t; +#define WL_NAN_INVALID_NDPID 0 /* reserved ndp id */ + typedef struct wl_nan_dp_req { uint8 type; /* 0- unicast 1 - multicast */ uint8 pub_id; /* Publisher ID */ uint16 flags; struct ether_addr peer_mac; /* Peer's NMI addr */ struct ether_addr mcast_mac; /* Multicast addr */ + struct ether_addr ndi; wl_nan_dp_qos_t qos; + wl_nan_ndl_qos_t ndl_qos; /* ndl qos */ uint8 tlv_params[]; /* xtlv parameters for command */ } wl_nan_dp_req_t; @@ -9076,11 +10999,13 @@ typedef struct wl_nan_dp_resp { uint8 status; /* Accepted or Rejected */ uint8 reason_code; /* Local NDP ID for unicast, mc_id for multicast, 0 for implicit NMSG */ - uint8 ndp_id; + uint8 ndp_id; /* can be host indp id also */ wl_nan_dp_qos_t qos; /* Initiator data address for unicast or multicast address for multicast */ struct ether_addr mac_addr; + struct ether_addr ndi; uint16 flags; + wl_nan_ndl_qos_t ndl_qos; /* ndl qos */ uint8 tlv_params[]; /* xtlv parameters for command */ } wl_nan_dp_resp_t; @@ -9091,16 +11016,16 @@ typedef struct wl_nan_dp_resp_ret { } wl_nan_dp_resp_ret_t; typedef struct wl_nan_dp_conf { - uint8 lndp_id; - uint8 status; /* Accepted or Rejected */ + uint8 lndp_id; /* can be host ndp id */ + uint8 status; /* Accepted or Rejected */ uint8 pad[2]; } wl_nan_dp_conf_t; typedef struct wl_nan_dp_end { - uint8 lndp_id; + uint8 lndp_id; /* can be host ndp id */ uint8 status; - uint8 pad[2]; + struct ether_addr mac_addr; /* initiator's ndi */ } wl_nan_dp_end_t; typedef struct wl_nan_dp_schedupd { @@ -9108,8 +11033,10 @@ typedef struct wl_nan_dp_schedupd { uint8 flags; struct ether_addr addr; /* peer NMI or multicast addr */ wl_nan_dp_qos_t qos; + wl_nan_ndl_qos_t ndl_qos; /* ndl qos */ uint8 map_id; - uint8 pad[3]; + uint8 pad; + uint16 hostseq; } wl_nan_dp_schedupd_t; /* set: update with notification, unset: NDL setup handshake */ @@ -9133,9 +11060,22 @@ typedef struct wl_nan_ndp_status { struct ether_addr peer_nmi; struct ether_addr peer_ndi; ndp_session_t session; - uint8 pad; + struct ether_addr lndi; + uint8 pad[2]; } wl_nan_ndp_status_t; +#define NAN_DP_OPAQUE_INFO_DP_RESP 0x01 +#define NAN_DP_OPAQUE_INFO_DP_CONF 0x02 + +typedef struct wl_nan_dp_opaque_info { + uint8 frm_mask; /* dp_resp / dp_conf as defined above. */ + struct ether_addr initiator_ndi; /* NDI to match in the dp_req. */ + uint8 pub_id; /* publish id where the opaque data is included. */ + uint8 len; /* len of opaque_info[]. */ + uint8 pad[3]; + uint8 opaque_info[0]; +} wl_nan_dp_opaque_info_t; + /* events */ #define NAN_DP_SESSION_UNICAST 0 #define NAN_DP_SESSION_MULTICAST 1 @@ -9162,11 +11102,12 @@ typedef struct wl_nan_ev_datapath_cmn { /* Following two fields are valid only if type is multicast */ uint8 nmsg_id[WL_NAN_DATA_NMSGID_LEN]; uint8 mc_id; - uint8 pad[1]; + uint8 pad; uint16 opt_tlv_len; uint8 opt_tlvs[]; } wl_nan_ev_datapath_cmn_t; +/* this is obsolete - DON'T USE */ typedef struct wl_nan_ev_datapath_end { uint8 ndp_id; uint8 status; @@ -9175,12 +11116,84 @@ typedef struct wl_nan_ev_datapath_end { struct ether_addr peer_ndi; } wl_nan_ev_datapath_end_t; +typedef struct wl_tsf { + uint32 tsf_l; + uint32 tsf_h; +} wl_tsf_t; + +typedef struct wl_nan_ev_rx_bcn { + wl_tsf_t tsf; + uint16 bcn_len; + uint8 pad[2]; + uint8 bcn[0]; +} wl_nan_ev_rx_bcn_t; + +/* reason of host assist request */ +enum wl_nan_host_assist_reason { + WL_NAN_HAST_REASON_NONE = 0, + + /* reason for host assist request */ + WL_NAN_HAST_REASON_NO_CRB = 1, /* NDL: no common NA */ + WL_NAN_HAST_REASON_NDC = 2, /* NDL: NDC not compliant */ + WL_NAN_HAST_REASON_IMMUT = 3, /* NDL: peer immutable schedule */ + WL_NAN_HAST_REASON_RNG = 4, /* NDL: ranging schedule */ + WL_NAN_HAST_REASON_QOS = 5, /* NDL: QoS not satisfied */ + WL_NAN_HAST_REASON_NDP_SPEC_INFO = 6 /* NDP: NDI & NDP specific info */ +}; +typedef uint8 wl_nan_host_assist_reason_t; + +/* WL_NAN_XTLV_HOST_ASSIST_REQ */ +typedef struct wl_nan_host_assist_req { + struct ether_addr peer_nmi; /* peer nmi */ + struct ether_addr initiator_ndi; /* initiator ndi */ + uint8 indp_id; /* initiator NDP ID */ + wl_nan_frame_type_t frm_type; /* received NAF type */ + wl_nan_host_assist_reason_t reason; /* reason of host assist request */ + uint8 pub_id; /* Publish ID (valid for WL_NAN_FRM_TYPE_DP_REQ) */ + uint8 pad[2]; +} wl_nan_host_assist_req_t; + +/* nan sub-features */ +enum wl_nan_fw_cap_flag1 { + WL_NAN_FW_CAP_FLAG_NONE = 0x00000000, /* dummy */ + WL_NAN_FW_CAP_FLAG1_AVAIL = 0x00000001, + WL_NAN_FW_CAP_FLAG1_DISC = 0x00000002, + WL_NAN_FW_CAP_FLAG1_DATA = 0x00000004, + WL_NAN_FW_CAP_FLAG1_SEC = 0x00000008, + WL_NAN_FW_CAP_FLAG1_RANGE = 0x00000010, + WL_NAN_FW_CAP_FLAG1_WFA_TB = 0x00000020, + WL_NAN_FW_CAP_FLAG1_DAM = 0x00000040, + WL_NAN_FW_CAP_FLAG1_DAM_STRICT = 0x00000080, + WL_NAN_FW_CAP_FLAG1_DAM_AUTO = 0x00000100, + WL_NAN_FW_CAP_FLAG1_DBG = 0x00000200, + WL_NAN_FW_CAP_FLAG1_BCMC_IN_NDC = 0x00000400, + WL_NAN_FW_CAP_FLAG1_CHSTATS = 0x00000800, + WL_NAN_FW_CAP_FLAG1_ASSOC_COEX = 0x00001000, + WL_NAN_FW_CAP_FLAG1_FASTDISC = 0x00002000, + WL_NAN_FW_CAP_FLAG1_NO_ID_GEN = 0x00004000, + WL_NAN_FW_CAP_FLAG1_DP_OPAQUE_DATA = 0x00008000 +}; + +/* WL_NAN_XTLV_GEN_FW_CAP */ +typedef struct wl_nan_fw_cap { + uint32 flags1; /* nan sub-features compiled in firmware */ + uint32 flags2; /* for more sub-features in future */ + uint8 max_svc_publishes; /* max num of service publish */ + uint8 max_svc_subscribes; /* max num of service subscribe */ + uint8 max_lcl_sched_maps; /* max num of local schedule map */ + uint8 max_lcl_ndc_entries; /* max num of local NDC entry */ + uint8 max_lcl_ndi_interfaces; /* max num of local NDI interface */ + uint8 max_peer_entries; /* max num of peer entry */ + uint8 max_ndp_sessions; /* max num of NDP session */ + uint8 pad; +} wl_nan_fw_cap_t; + /* NAN2.0 Ranging definitions */ /* result indication bit map */ #define NAN_RANGE_INDICATION_CONT (1<<0) #define NAN_RANGE_INDICATION_INGRESS (1<<1) -#define NAN_RANGE_INIDICATION_EGRESS (1<<2) +#define NAN_RANGE_INDICATION_EGRESS (1<<2) /* responder flags */ #define NAN_RANGE_FLAG_AUTO_ACCEPT (1 << 0) @@ -9236,19 +11249,95 @@ typedef struct wl_nan_ev_rng_rpt_ind { uint32 dist_mm; /* in millimeter */ struct ether_addr peer_m_addr; uint8 indication; /* indication definitions mentioned above */ - uint8 pad; + uint8 rng_id; } wl_nan_ev_rng_rpt_ind_t; -#define NAN_RNG_RPT_IND_SIZE 11 +#define NAN_RNG_RPT_IND_SIZE 12 typedef struct wl_nan_ev_rng_term_ind { struct ether_addr peer_m_addr; uint8 reason_code; - uint8 pad; + uint8 rng_id; } wl_nan_ev_rng_term_ind_t; -#define NAN_RNG_TERM_IND_SIZE 7 +#define NAN_RNG_TERM_IND_SIZE 8 + +typedef struct wl_nan_ev_rng_resp { + struct ether_addr peer_m_addr; + uint8 status; + uint8 rng_id; +} wl_nan_ev_rng_resp_t; + +/* Used by NDL schedule events - + * WL_NAN_EVENT_PEER_SCHED_UPD_NOTIF, WL_NAN_EVENT_PEER_SCHED_REQ + * WL_NAN_EVENT_PEER_SCHED_RESP, WL_NAN_EVENT_PEER_SCHED_CONF + */ +typedef struct wl_nan_ev_sched_info { + struct ether_addr peer_nmi; + uint8 ndl_status; /* applies only to sched resp/conf */ + uint8 pad; + uint16 opt_tlv_len; + uint8 opt_tlvs[]; +} wl_nan_ev_sched_info_t; + +/* WL_NAN_EVENT_CHAN_BOUNDARY */ +typedef struct wl_nan_chbound_info { + uint32 cluster_tsf_h; /* Current Cluster TSF High */ + uint32 cluster_tsf_l; /* Current Cluster TSF Low */ + uint16 cur_chspec; + uint16 opt_tlvs_len; + uint8 opt_tlvs[]; +} wl_nan_chbound_info_t; + +/* channel stats (includes nan & non-nan) */ + +/* WL_NAN_XTLV_CCA_STATS */ +typedef struct wl_nan_cca_stats { + uint16 chanspec; + uint8 pad[2]; + uint32 sample_dur; + + uint32 congest_ibss; + uint32 congest_obss; + uint32 interference; +} wl_nan_cca_stats_t; + +/* WL_NAN_XTLV_PER_STATS */ +typedef struct wl_nan_per_stats_s { + uint16 chanspec; + uint8 pad[2]; + uint32 sample_dur; + + uint32 txframe; /* tx data frames */ + uint32 txretrans; /* tx mac retransmits */ + uint32 txerror; /* tx data errors */ + uint32 txctl; /* tx management frames */ + uint32 txserr; /* tx status errors */ + + uint32 rxframe; /* rx data frames */ + uint32 rxerror; /* rx data errors */ + uint32 rxctl; /* rx management frames */ + + uint32 txbar; /* tx bar */ + uint32 rxbar; /* rx bar */ + uint32 txaction; /* tx action frame */ + uint32 rxaction; /* rx action frame */ + uint32 txlost; /* lost packets reported in txs */ + uint32 rxback; /* rx block ack */ + uint32 txback; /* tx bloak ack */ +} wl_nan_per_stats_t; + +/* fast discovery beacon config + * WL_NAN_XTLV_CFG_FDISC_TBMP +*/ +typedef struct wl_nan_fastdisc_s { + uint8 id; + uint8 bitmap_len; + uint8 pad[2]; + uint8 bitmap[]; +} wl_nan_fastdisc_t; +#define WL_NAN_FASTDISC_CFG_SIZE 1024 /* arbitrary */ /* ********************* end of NAN section ******************************** */ /* endif WL_NAN */ @@ -9408,10 +11497,19 @@ enum { WL_AVAIL_RESPONSE = 0x0005, WL_AVAIL_COUNTER = 0x0006, WL_AVAIL_RANGING = 0x0007, - WL_AVAIL_TYPE_MAX = WL_AVAIL_RANGING /* New ones before and update */ + WL_AVAIL_UPD_POT = 0x0008, /* modify potential, keep committed/conditional */ + WL_AVAIL_UPD_COM_COND = 0x0009, /* modify committed/conditional, keep potential */ + WL_AVAIL_REMOVE_MAP = 0x000A, /* remove map */ + WL_AVAIL_FRM_TYPE = 0x000B, /* specify frame types containing NA */ + WL_AVAIL_TYPE_MAX = WL_AVAIL_FRM_TYPE /* New ones before and update */ }; -#define WL_AVAIL_TYPE_MASK 0x000F -#define WL_AVAIL_FLAG_RAW_MODE 0x8000 +#define WL_AVAIL_TYPE_MASK 0x000F +#define WL_AVAIL_FLAG_REMOVE 0x2000 /* remove schedule attr of given type & map id */ +#define WL_AVAIL_FLAG_SELECTED_NDC 0x4000 +#define WL_AVAIL_FLAG_RAW_MODE 0x8000 +#define WL_AVAIL_FLAGS_MASK 0xFF00 +#define WL_AVAIL_FLAGS_SHIFT 8 + typedef int16 wl_avail_flags_t; /* availability entry flags */ @@ -9498,7 +11596,8 @@ typedef struct wl_avail_entry { uint32 band; /* defined by WL_BAND enum, 2=2.4GHz, 4=5GHz */ uint8 channel_entry[MAX_CHAN_ENTRY_LEN]; } u; /* band or channel value, 0=all band/channels */ - uint8 pad[2]; + uint8 sched_map_id; /* avail map id associated with sched entry */ + uint8 pad; uint8 period; /* in TUs, defined by WL_AVAIL_PERIOD enum * 1:128, 2:256, 3:512, 4:1024, 5:2048, 6:4096, * 7:8192 @@ -9510,17 +11609,20 @@ typedef struct wl_avail_entry { uint8 bitmap[]; /* time bitmap */ } wl_avail_entry_t; +#define WL_AVAIL_VERSION 1 /* current wl_avail version */ + typedef struct wl_avail { uint16 length; /* total length */ - uint16 flags; /* defined by WL_AVAIL enum - * 1=local, 2=peer, 3=ndc, 4=immutable, - * 5=response, 6=counter + uint16 flags; /* LSB - avail type (defined by WL_AVAIL enum) + * MSB - avail flags */ uint8 id; /* id used for multiple maps/avail */ - uint8 pad[3]; - struct ether_addr addr; /* peer mac address or ndc id */ + uint8 lndc_id; /* ndc id used in multi-ndc case */ + uint8 version; + uint8 pad; + struct ether_addr addr; /* peer mac address or ndc id */ uint8 num_entries; - uint8 entry_offset; + uint8 unused_byte; /* add additional fields above this line */ uint8 entry[]; } wl_avail_t; @@ -9572,10 +11674,55 @@ enum { WL_NAN_WFA_TM_SEC_REJECT_STATUS4M4 = 0x00000080, /* send mgmt frame (for eg. ndp terminate) in clear txt (bypass security) */ WL_NAN_WFA_TM_SEC_SEND_MGMT_CLEAR = 0x00000100, - WL_NAN_WFA_TM_FLAG_MASK = 0x000001ff /* add above & update mask */ + /* validate qos */ + WL_NAN_WFA_TM_NDL_QOS_VALIDATE = 0x00000200, + /* firmware generated schedule update */ + WL_NAN_WFA_TM_GEN_SCHED_UPD = 0x00000400, + /* add lower 4-bytes of TSF to configured start time */ + WL_NAN_WFA_TM_ULW_START_TIME = 0x00000800, + /* enable schedule validation for SDF */ + WL_NAN_WFA_TM_SDF_SCHED_VALIDATE = 0x00001000, + /* by pass faw na iovar */ + WL_NAN_WFA_TM_SKIP_RAW_NA_BLOB = 0x00002000, + /* overwrite local NA with peer NA in received frame */ + WL_NAN_WFA_TM_LOCAL_NA_OVERWRITE = 0x00004000, + /* randomize and self configure ndl qos(needed at responder in auto mode) */ + WL_NAN_WFA_TM_SELF_CFG_NDL_QOS = 0x00008000, + /* send NAF frames only in DW */ + WL_NAN_WFA_TM_SEND_NAF_IN_DW = 0x00010000, + /* restrict channels used for countered slots to Ch 6/149 only */ + WL_NAN_WFA_TM_RESTRICT_COUNTER_SLOTS_CHAN = 0x00020000, + WL_NAN_WFA_TM_FLAG_MASK = 0x0003ffff /* add above & update mask */ }; typedef uint32 wl_nan_wfa_testmode_t; +/* To be removed; replaced by wl_nan_vndr_payload */ +typedef struct wl_nan_vndr_ie { + uint32 flags; /* bitmask indicating which packet(s) contain this IE */ + uint16 body_len; /* length of body (does not include oui field) */ + uint8 pad[2]; + uint8 oui[DOT11_OUI_LEN]; + uint8 pad2; + uint8 body[]; /* vendor IE payload */ +} wl_nan_vndr_ie_t; + +typedef struct wl_nan_vndr_payload { + uint32 flags; /* bitmask indicating which packet(s) contain payload */ + uint16 payload_len; /* length of payload */ + uint8 pad[2]; + uint8 payload[]; /* payload to be appended to NAN frame */ +} wl_nan_vndr_payload_t; + +typedef struct wl_nan_dev_cap { + uint8 bands[NAN_MAX_BANDS]; + uint8 awake_dw[NAN_MAX_BANDS]; + uint8 overwrite_mapid[NAN_MAX_BANDS]; + uint8 mapid; /* dev cap mapid */ + uint8 all_maps; /* applies to device */ + uint8 paging; + uint8 pad[3]; +} wl_nan_dev_cap_t; + #define RSSI_THRESHOLD_SIZE 16 #define MAX_IMP_RESP_SIZE 256 @@ -9650,17 +11797,26 @@ typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_data_v1 { #include #define WL_PROXD_COLLECT_DATA_VERSION_2 2 -typedef struct wl_proxd_collect_data_v2 { +#include +typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_data_v2 { + wl_proxd_collect_info_t info; + uint8 ri_rr[FTM_TPK_RI_RR_LEN_SECURE_2_0]; + /**< raw data read from phy used to adjust timestamps */ + uint32 H[K_TOF_COLLECT_H_SIZE_20MHZ]; +} BWL_POST_PACKED_STRUCT wl_proxd_collect_data_t_v2; +#include + +#define WL_PROXD_COLLECT_DATA_VERSION_3 3 +typedef struct wl_proxd_collect_data_v3 { uint16 version; uint16 len; wl_proxd_collect_info_t info; - uint8 ri_rr[FTM_TPK_RI_RR_LEN]; - uint8 pad[3]; /* should be based on FTM_TPK_RI_RR_LEN */ + uint8 ri_rr[FTM_TPK_RI_RR_LEN_SECURE_2_0]; /**< raw data read from phy used to adjust timestamps */ uint32 H[K_TOF_COLLECT_H_SIZE_20MHZ]; uint32 chan[4 * K_TOF_COLLECT_CHAN_SIZE]; -} wl_proxd_collect_data_t_v2; -#define WL_PROXD_COLLECT_DATA_VERSION_MAX WL_PROXD_COLLECT_DATA_VERSION_2 +} wl_proxd_collect_data_t_v3; +#define WL_PROXD_COLLECT_DATA_VERSION_MAX WL_PROXD_COLLECT_DATA_VERSION_3 typedef struct wl_proxd_debug_data { uint8 count; /**< number of packets */ @@ -9791,6 +11947,7 @@ typedef struct wl_randmac_version { #define WL_RANDMAC_USER_FTM 0x0001 #define WL_RANDMAC_USER_NAN 0x0002 #define WL_RANDMAC_USER_SCAN 0x0004 +#define WL_RANDMAC_USER_ANQP 0x0008 #define WL_RANDMAC_USER_ALL 0xFFFF typedef uint16 wl_randmac_method_t; @@ -9908,6 +12065,23 @@ typedef struct wl_scanmac_config { #define WL_SCANMAC_SCAN_ASSOC_ROAM (0x01 << 1) /**< associated roam scans */ #define WL_SCANMAC_SCAN_ASSOC_PNO (0x01 << 2) /**< associated PNO scans */ #define WL_SCANMAC_SCAN_ASSOC_HOST (0x01 << 3) /**< associated host scans */ + +#define WL_SCAN_EVENT_VERSION 1 + +#define WL_SCAN_TYPE_ASSOC 0x1 /* Assoc scan */ +#define WL_SCAN_TYPE_ROAM 0x2 /* Roam scan */ +#define WL_SCAN_TYPE_FWSCAN 0x4 /* Other FW scan */ +#define WL_SCAN_TYPE_HOSTSCAN 0x8 /* Host scan */ + +typedef struct scan_event_data { + uint32 version; + uint32 flags; + uint16 num_chan_slice0; + uint16 num_chan_slice1; + /* Will contain num_chan_slice0 followed by num_chan_slice1 chanspecs */ + chanspec_t scan_chan_list[]; +} scan_event_data_t; + /* * bonjour dongle offload definitions */ @@ -10256,6 +12430,43 @@ typedef struct statreq { uint16 reps; } statreq_t; +typedef struct txstrmreq { + struct ether_addr da; /* Destination address */ + uint16 random_int; /* Random interval for measurement start */ + uint16 dur; /* Measurement duration */ + uint16 reps; /* number of repetitions */ + struct ether_addr peer; /* Peer MAC address */ + uint8 tid; /* Traffic ID */ + uint8 bin0_range; /* Delay range of the first bin */ +} txstrmreq_t; + +typedef struct lcireq { + struct ether_addr da; /* Destination address */ + uint16 reps; /* number of repetitions */ + uint8 subj; /* Local/Remote/Thid party */ + uint8 lat_res; /* Latitude requested Resolution */ + uint8 lon_res; /* Longitude requested Resolution */ + uint8 alt_res; /* Altitude requested Resolution */ +} lcireq_t; + +typedef struct civicreq { + struct ether_addr da; /* Destination address */ + uint16 reps; /* number of repetitions */ + uint8 subj; /* Local/Remote/Thid party */ + uint8 civloc_type; /* Format of location info */ + uint8 siu; /* Unit of Location service interval */ + uint8 pad; + uint16 si; /* Location service interval */ +} civicreq_t; + +typedef struct locidreq { + struct ether_addr da; /* Destination address */ + uint16 reps; /* number of repetitions */ + uint8 subj; /* Local/Remote/Thid party */ + uint8 siu; /* Unit of Location service interval */ + uint16 si; /* Location service interval */ +} locidreq_t; + typedef struct wl_rrm_config_ioc { uint16 version; /* command version */ uint16 id; /* subiovar cmd ID */ @@ -10270,7 +12481,9 @@ enum { WL_RRM_CONFIG_SET_LCI = 2, /* set LCI */ WL_RRM_CONFIG_GET_CIVIC = 3, /* get civic location */ WL_RRM_CONFIG_SET_CIVIC = 4, /* set civic location */ - WL_RRM_CONFIG_MAX = 5 + WL_RRM_CONFIG_GET_LOCID = 5, /* get location identifier */ + WL_RRM_CONFIG_SET_LOCID = 6, /* set location identifier */ + WL_RRM_CONFIG_MAX = 7 }; #define WL_RRM_CONFIG_NAME "rrm_config" @@ -10385,21 +12598,24 @@ typedef struct wl_el_tag_params_s { uint8 flags; } wl_el_tag_params_t; -/** Video Traffic Interference Monitor config */ -#define INTFER_VERSION 1 -typedef struct wl_intfer_params { - uint16 version; /**< version */ - uint8 period; /**< sample period */ - uint8 cnt; /**< sample cnt */ - uint8 txfail_thresh; /**< non-TCP txfail threshold */ - uint8 tcptxfail_thresh; /**< tcptxfail threshold */ -} wl_intfer_params_t; +#define EVENT_LOG_SET_TYPE_CURRENT_VERSION 0 +typedef struct wl_el_set_type_s { + uint16 version; + uint16 len; + uint8 set; /* Set number */ + uint8 type; /* Type- EVENT_LOG_SET_TYPE_DEFAULT or EVENT_LOG_SET_TYPE_PRSRV */ + uint16 PAD; +} wl_el_set_type_t; typedef struct wl_staprio_cfg { struct ether_addr ea; /**< mac addr */ uint8 prio; /**< scb priority */ } wl_staprio_cfg_t; +#define STAMON_STACONFIG_VER 1 +/* size of struct wlc_stamon_sta_config_t elements */ +#define STAMON_STACONFIG_LENGTH 20 + typedef enum wl_stamon_cfg_cmd_type { STAMON_CFG_CMD_DEL = 0, STAMON_CFG_CMD_ADD = 1, @@ -10407,13 +12623,18 @@ typedef enum wl_stamon_cfg_cmd_type { STAMON_CFG_CMD_DSB = 3, STAMON_CFG_CMD_CNT = 4, STAMON_CFG_CMD_RSTCNT = 5, - STAMON_CFG_CMD_GET_STATS = 6 + STAMON_CFG_CMD_GET_STATS = 6, + STAMON_CFG_CMD_SET_MONTIME = 7 } wl_stamon_cfg_cmd_type_t; typedef struct wlc_stamon_sta_config { - wl_stamon_cfg_cmd_type_t cmd; /**< 0 - delete, 1 - add */ + wl_stamon_cfg_cmd_type_t cmd; /**< 0 - delete, 1 - add */ struct ether_addr ea; - uint8 PAD[2]; + uint16 version; /* Command structure version */ + uint16 length; /* Command structure length */ + uint8 pad[2]; + /* Time (ms) for which STA's are monitored. Value ZERO indicates no time limit */ + uint32 monitor_time; } wlc_stamon_sta_config_t; /* ifdef SR_DEBUG */ @@ -10482,7 +12703,10 @@ typedef enum wl_gpaio_option { GPAIO_OFF, GPAIO_PMU_LOGENLDO, GPAIO_PMU_RXLDO2G, - GPAIO_PMU_RXLDO5G + GPAIO_PMU_RXLDO5G, + GPAIO_PMU_LPFTXLDO, + GPAIO_PMU_LDO1P6, + GPAIO_RCAL } wl_gpaio_option_t; /** IO Var Operations - the Value of iov_op In wlc_ap_doiovar */ @@ -10552,6 +12776,11 @@ typedef struct { uint16 combo4; /* mws ant selection 4 */ } mws_ant_map_t; +/* MWS ANT map 2nd generation */ +typedef struct { + uint16 combo[16]; /* mws ant selection 2nd */ +} mws_ant_map_t_2nd; + /* MWS SCAN_REQ Bitmap */ typedef struct mws_scanreq_params { uint16 idx; @@ -10744,28 +12973,28 @@ typedef struct wl_proxd_intvl { /** commands that can apply to proxd, method or a session */ enum { - WL_PROXD_CMD_NONE = 0, + WL_PROXD_CMD_NONE = 0, WL_PROXD_CMD_GET_VERSION = 1, - WL_PROXD_CMD_ENABLE = 2, - WL_PROXD_CMD_DISABLE = 3, - WL_PROXD_CMD_CONFIG = 4, - WL_PROXD_CMD_START_SESSION = 5, - WL_PROXD_CMD_BURST_REQUEST = 6, - WL_PROXD_CMD_STOP_SESSION = 7, - WL_PROXD_CMD_DELETE_SESSION = 8, - WL_PROXD_CMD_GET_RESULT = 9, - WL_PROXD_CMD_GET_INFO = 10, - WL_PROXD_CMD_GET_STATUS = 11, - WL_PROXD_CMD_GET_SESSIONS = 12, - WL_PROXD_CMD_GET_COUNTERS = 13, - WL_PROXD_CMD_CLEAR_COUNTERS = 14, - WL_PROXD_CMD_COLLECT = 15, /* not supported, see 'wl proxd_collect' */ - WL_PROXD_CMD_TUNE = 16, /* not supported, see 'wl proxd_tune' */ - WL_PROXD_CMD_DUMP = 17, + WL_PROXD_CMD_ENABLE = 2, + WL_PROXD_CMD_DISABLE = 3, + WL_PROXD_CMD_CONFIG = 4, + WL_PROXD_CMD_START_SESSION = 5, + WL_PROXD_CMD_BURST_REQUEST = 6, + WL_PROXD_CMD_STOP_SESSION = 7, + WL_PROXD_CMD_DELETE_SESSION = 8, + WL_PROXD_CMD_GET_RESULT = 9, + WL_PROXD_CMD_GET_INFO = 10, + WL_PROXD_CMD_GET_STATUS = 11, + WL_PROXD_CMD_GET_SESSIONS = 12, + WL_PROXD_CMD_GET_COUNTERS = 13, + WL_PROXD_CMD_CLEAR_COUNTERS = 14, + WL_PROXD_CMD_COLLECT = 15, /* not supported, see 'wl proxd_collect' */ + WL_PROXD_CMD_TUNE = 16, /* not supported, see 'wl proxd_tune' */ + WL_PROXD_CMD_DUMP = 17, WL_PROXD_CMD_START_RANGING = 18, WL_PROXD_CMD_STOP_RANGING = 19, - WL_PROXD_CMD_GET_RANGING_INFO = 20, - WL_PROXD_CMD_IS_TLV_SUPPORTED = 21, + WL_PROXD_CMD_GET_RANGING_INFO = 20, + WL_PROXD_CMD_IS_TLV_SUPPORTED = 21, WL_PROXD_CMD_MAX }; @@ -10804,41 +13033,43 @@ typedef uint16 wl_proxd_session_id_t; /** status - TBD BCME_ vs proxd status - range reserved for BCME_ */ enum { + WL_PROXD_E_LAST = -1056, WL_PROXD_E_NOAVAIL = -1056, WL_PROXD_E_EXT_SCHED = -1055, - WL_PROXD_E_NOT_BCM = -1054, + WL_PROXD_E_NOT_BCM = -1054, WL_PROXD_E_FRAME_TYPE = -1053, WL_PROXD_E_VERNOSUPPORT = -1052, WL_PROXD_E_SEC_NOKEY = -1051, WL_PROXD_E_SEC_POLICY = -1050, WL_PROXD_E_SCAN_INPROCESS = -1049, WL_PROXD_E_BAD_PARTIAL_TSF = -1048, - WL_PROXD_E_SCANFAIL = -1047, - WL_PROXD_E_NOTSF = -1046, - WL_PROXD_E_POLICY = -1045, + WL_PROXD_E_SCANFAIL = -1047, + WL_PROXD_E_NOTSF = -1046, + WL_PROXD_E_POLICY = -1045, WL_PROXD_E_INCOMPLETE = -1044, WL_PROXD_E_OVERRIDDEN = -1043, WL_PROXD_E_ASAP_FAILED = -1042, WL_PROXD_E_NOTSTARTED = -1041, WL_PROXD_E_INVALIDMEAS = -1040, WL_PROXD_E_INCAPABLE = -1039, - WL_PROXD_E_MISMATCH = -1038, + WL_PROXD_E_MISMATCH = -1038, WL_PROXD_E_DUP_SESSION = -1037, WL_PROXD_E_REMOTE_FAIL = -1036, - WL_PROXD_E_REMOTE_INCAPABLE = -1035, + WL_PROXD_E_REMOTE_INCAPABLE = -1035, WL_PROXD_E_SCHED_FAIL = -1034, - WL_PROXD_E_PROTO = -1033, - WL_PROXD_E_EXPIRED = -1032, - WL_PROXD_E_TIMEOUT = -1031, - WL_PROXD_E_NOACK = -1030, - WL_PROXD_E_DEFERRED = -1029, + WL_PROXD_E_PROTO = -1033, + WL_PROXD_E_EXPIRED = -1032, + WL_PROXD_E_TIMEOUT = -1031, + WL_PROXD_E_NOACK = -1030, + WL_PROXD_E_DEFERRED = -1029, WL_PROXD_E_INVALID_SID = -1028, - WL_PROXD_E_REMOTE_CANCEL = -1027, - WL_PROXD_E_CANCELED = -1026, /**< local */ + WL_PROXD_E_REMOTE_CANCEL = -1027, + WL_PROXD_E_CANCELED = -1026, /**< local */ WL_PROXD_E_INVALID_SESSION = -1025, WL_PROXD_E_BAD_STATE = -1024, - WL_PROXD_E_ERROR = -1, - WL_PROXD_E_OK = 0 + WL_PROXD_E_START = -1024, + WL_PROXD_E_ERROR = -1, + WL_PROXD_E_OK = 0 }; typedef int32 wl_proxd_status_t; @@ -10860,7 +13091,7 @@ typedef uint32 wl_proxd_phy_error_t; /** session states */ enum { - WL_PROXD_SESSION_STATE_NONE = 0, + WL_PROXD_SESSION_STATE_NONE = 0, WL_PROXD_SESSION_STATE_CREATED = 1, WL_PROXD_SESSION_STATE_CONFIGURED = 2, WL_PROXD_SESSION_STATE_STARTED = 3, @@ -10877,7 +13108,7 @@ typedef int16 wl_proxd_session_state_t; /** RTT sample flags */ enum { - WL_PROXD_RTT_SAMPLE_NONE = 0x00, + WL_PROXD_RTT_SAMPLE_NONE = 0x00, WL_PROXD_RTT_SAMPLE_DISCARD = 0x01 }; typedef uint8 wl_proxd_rtt_sample_flags_t; @@ -10885,11 +13116,26 @@ typedef int16 wl_proxd_rssi_t; typedef uint16 wl_proxd_snr_t; typedef uint16 wl_proxd_bitflips_t; -typedef struct wl_proxd_rtt_sample { - uint8 id; /**< id for the sample - non-zero */ +/** result flags */ +enum { + WL_PRXOD_RESULT_FLAG_NONE = 0x0000, + WL_PROXD_RESULT_FLAG_NLOS = 0x0001, /**< LOS - if available */ + WL_PROXD_RESULT_FLAG_LOS = 0x0002, /**< NLOS - if available */ + WL_PROXD_RESULT_FLAG_FATAL = 0x0004, /**< Fatal error during burst */ + WL_PROXD_RESULT_FLAG_VHTACK = 0x0008, /* VHTACK or Legacy ACK used */ + WL_PROXD_REQUEST_SENT = 0x0010, /* FTM request was sent */ + WL_PROXD_REQUEST_ACKED = 0x0020, /* FTM request was acked */ + WL_PROXD_LTFSEQ_STARTED = 0x0040, /* LTF sequence started */ + WL_PROXD_RESULT_FLAG_ALL = 0xffff +}; +typedef int16 wl_proxd_result_flags_t; + +#define WL_PROXD_RTT_SAMPLE_VERSION_1 1 +typedef struct wl_proxd_rtt_sample_v1 { + uint8 id; /**< id for the sample - non-zero */ wl_proxd_rtt_sample_flags_t flags; wl_proxd_rssi_t rssi; - wl_proxd_intvl_t rtt; /**< round trip time */ + wl_proxd_intvl_t rtt; /**< round trip time */ uint32 ratespec; wl_proxd_snr_t snr; wl_proxd_bitflips_t bitflips; @@ -10901,34 +13147,68 @@ typedef struct wl_proxd_rtt_sample { wl_proxd_bitflips_t tof_tgt_bitflips; uint8 coreid; uint8 pad[3]; -} wl_proxd_rtt_sample_t; +} wl_proxd_rtt_sample_v1_t; -/** result flags */ -enum { - WL_PRXOD_RESULT_FLAG_NONE = 0x0000, - WL_PROXD_RESULT_FLAG_NLOS = 0x0001, /**< LOS - if available */ - WL_PROXD_RESULT_FLAG_LOS = 0x0002, /**< NLOS - if available */ - WL_PROXD_RESULT_FLAG_FATAL = 0x0004, /**< Fatal error during burst */ - WL_PROXD_RESULT_FLAG_VHTACK = 0x0008, /* VHTACK or Legacy ACK used */ - WL_PROXD_REQUEST_SENT = 0x0010, /* FTM request was sent */ - WL_PROXD_REQUEST_ACKED = 0x0020, /* FTM request was acked */ - WL_PROXD_LTFSEQ_STARTED = 0x0040, /* LTF sequence started */ - WL_PROXD_RESULT_FLAG_ALL = 0xffff -}; -typedef int16 wl_proxd_result_flags_t; +#define WL_PROXD_RTT_RESULT_VERSION_1 1 +/** rtt measurement result */ +typedef struct wl_proxd_rtt_result_v1 { + wl_proxd_session_id_t sid; + wl_proxd_result_flags_t flags; + wl_proxd_status_t status; + struct ether_addr peer; + wl_proxd_session_state_t state; /**< current state */ + union { + wl_proxd_intvl_t retry_after; /* hint for errors */ + wl_proxd_intvl_t burst_duration; /* burst duration */ + } u; + wl_proxd_rtt_sample_v1_t avg_rtt; + uint32 avg_dist; /* 1/256m units */ + uint16 sd_rtt; /* RTT standard deviation */ + uint8 num_valid_rtt; /* valid rtt cnt */ + uint8 num_ftm; /* actual num of ftm cnt (Configured) */ + uint16 burst_num; /* in a session */ + uint16 num_rtt; /* 0 if no detail */ + uint16 num_meas; /* number of ftm frames seen OTA */ + uint8 pad[2]; + wl_proxd_rtt_sample_v1_t rtt[1]; /* variable */ +} wl_proxd_rtt_result_v1_t; + +#define WL_PROXD_RTT_SAMPLE_VERSION_2 2 +typedef struct wl_proxd_rtt_sample_v2 { + uint16 version; + uint16 length; + uint8 id; /**< id for the sample - non-zero */ + wl_proxd_rtt_sample_flags_t flags; + wl_proxd_rssi_t rssi; + wl_proxd_intvl_t rtt; /**< round trip time */ + uint32 ratespec; + wl_proxd_snr_t snr; + wl_proxd_bitflips_t bitflips; + wl_proxd_status_t status; + int32 distance; + wl_proxd_phy_error_t tof_phy_error; + wl_proxd_phy_error_t tof_tgt_phy_error; /* target phy error bit map */ + wl_proxd_snr_t tof_tgt_snr; + wl_proxd_bitflips_t tof_tgt_bitflips; + uint8 coreid; + uint8 pad[3]; + uint32 chanspec; +} wl_proxd_rtt_sample_v2_t; +#define WL_PROXD_RTT_RESULT_VERSION_2 2 /** rtt measurement result */ -typedef struct wl_proxd_rtt_result { +typedef struct wl_proxd_rtt_result_v2 { + uint16 version; + uint16 length; /* up to rtt[] */ wl_proxd_session_id_t sid; wl_proxd_result_flags_t flags; wl_proxd_status_t status; struct ether_addr peer; wl_proxd_session_state_t state; /**< current state */ union { - wl_proxd_intvl_t retry_after; /* hint for errors */ - wl_proxd_intvl_t burst_duration; /* burst duration */ + wl_proxd_intvl_t retry_after; /* hint for errors */ + wl_proxd_intvl_t burst_duration; /* burst duration */ } u; - wl_proxd_rtt_sample_t avg_rtt; uint32 avg_dist; /* 1/256m units */ uint16 sd_rtt; /* RTT standard deviation */ uint8 num_valid_rtt; /* valid rtt cnt */ @@ -10937,48 +13217,48 @@ typedef struct wl_proxd_rtt_result { uint16 num_rtt; /* 0 if no detail */ uint16 num_meas; /* number of ftm frames seen OTA */ uint8 pad[2]; - wl_proxd_rtt_sample_t rtt[1]; /* variable */ -} wl_proxd_rtt_result_t; + wl_proxd_rtt_sample_v2_t rtt[1]; /* variable, first element is avg_rtt */ +} wl_proxd_rtt_result_v2_t; /** aoa measurement result */ typedef struct wl_proxd_aoa_result { - wl_proxd_session_id_t sid; - wl_proxd_result_flags_t flags; - wl_proxd_status_t status; - struct ether_addr peer; - wl_proxd_session_state_t state; - uint16 burst_num; - uint8 pad[2]; + wl_proxd_session_id_t sid; + wl_proxd_result_flags_t flags; + wl_proxd_status_t status; + struct ether_addr peer; + wl_proxd_session_state_t state; + uint16 burst_num; + uint8 pad[2]; /* wl_proxd_aoa_sample_t sample_avg; TBD */ } BWL_POST_PACKED_STRUCT wl_proxd_aoa_result_t; #include /** global stats */ typedef struct wl_proxd_counters { - uint32 tx; /**< tx frame count */ - uint32 rx; /**< rx frame count */ - uint32 burst; /**< total number of burst */ - uint32 sessions; /**< total number of sessions */ - uint32 max_sessions; /**< max concurrency */ - uint32 sched_fail; /**< scheduling failures */ - uint32 timeouts; /**< timeouts */ - uint32 protoerr; /**< protocol errors */ - uint32 noack; /**< tx w/o ack */ - uint32 txfail; /**< any tx falure */ - uint32 lci_req_tx; /**< tx LCI requests */ - uint32 lci_req_rx; /**< rx LCI requests */ - uint32 lci_rep_tx; /**< tx LCI reports */ - uint32 lci_rep_rx; /**< rx LCI reports */ - uint32 civic_req_tx; /**< tx civic requests */ - uint32 civic_req_rx; /**< rx civic requests */ - uint32 civic_rep_tx; /**< tx civic reports */ - uint32 civic_rep_rx; /**< rx civic reports */ - uint32 rctx; /**< ranging contexts created */ - uint32 rctx_done; /**< count of ranging done */ - uint32 publish_err; /**< availability publishing errors */ - uint32 on_chan; /**< count of scheduler onchan */ - uint32 off_chan; /**< count of scheduler offchan */ - uint32 tsf_lo; /* local tsf or session tsf */ + uint32 tx; /* tx frame count */ + uint32 rx; /* rx frame count */ + uint32 burst; /* total number of burst */ + uint32 sessions; /* total number of sessions */ + uint32 max_sessions; /* max concurrency */ + uint32 sched_fail; /* scheduling failures */ + uint32 timeouts; /* timeouts */ + uint32 protoerr; /* protocol errors */ + uint32 noack; /* tx w/o ack */ + uint32 txfail; /* any tx falure */ + uint32 lci_req_tx; /* tx LCI requests */ + uint32 lci_req_rx; /* rx LCI requests */ + uint32 lci_rep_tx; /* tx LCI reports */ + uint32 lci_rep_rx; /* rx LCI reports */ + uint32 civic_req_tx; /* tx civic requests */ + uint32 civic_req_rx; /* rx civic requests */ + uint32 civic_rep_tx; /* tx civic reports */ + uint32 civic_rep_rx; /* rx civic reports */ + uint32 rctx; /* ranging contexts created */ + uint32 rctx_done; /* count of ranging done */ + uint32 publish_err; /* availability publishing errors */ + uint32 on_chan; /* count of scheduler onchan */ + uint32 off_chan; /* count of scheduler offchan */ + uint32 tsf_lo; /* local tsf or session tsf */ uint32 tsf_hi; uint32 num_meas; } wl_proxd_counters_t; @@ -11030,7 +13310,7 @@ typedef struct wl_proxd_ftm_info { } wl_proxd_ftm_info_t; enum { - WL_PROXD_WAIT_NONE = 0x0000, + WL_PROXD_WAIT_NONE = 0x0000, WL_PROXD_WAIT_KEY = 0x0001, WL_PROXD_WAIT_SCHED = 0x0002, WL_PROXD_WAIT_TSF = 0x0004 @@ -11230,6 +13510,7 @@ enum { WL_PROXD_TLV_ID_TPK = 36, /* 32byte TPK */ WL_PROXD_TLV_ID_RI_RR = 36, /* RI_RR */ WL_PROXD_TLV_ID_TUNE = 37, /* wl_proxd_pararms_tof_tune_t */ + WL_PROXD_TLV_ID_CUR_ETHER_ADDR = 38, /* Source Address used for Tx */ /* output - 512 + x */ WL_PROXD_TLV_ID_STATUS = 512, @@ -11240,6 +13521,7 @@ enum { WL_PROXD_TLV_ID_SESSION_INFO = 517, WL_PROXD_TLV_ID_SESSION_STATUS = 518, WL_PROXD_TLV_ID_SESSION_ID_LIST = 519, + WL_PROXD_TLV_ID_RTT_RESULT_V2 = 520, /* debug tlvs can be added starting 1024 */ WL_PROXD_TLV_ID_DEBUG_MASK = 1024, @@ -11250,6 +13532,7 @@ enum { WL_PROXD_TLV_ID_COLLECT_INFO = 1028, /* wl_proxd_collect_info_t */ WL_PROXD_TLV_ID_COLLECT_DATA = 1029, /* wl_proxd_collect_data_t */ WL_PROXD_TLV_ID_COLLECT_CHAN_DATA = 1030, /* wl_proxd_collect_data_t */ + WL_PROXD_TLV_ID_MF_STATS_DATA = 1031, /* mf_stats_buffer */ WL_PROXD_TLV_ID_MAX }; @@ -11296,6 +13579,7 @@ enum { WL_PROXD_EVENT_CIVIC_MEAS_REP = 16, /* civic measurement report */ WL_PROXD_EVENT_COLLECT = 17, WL_PROXD_EVENT_START_WAIT = 18, /* waiting to start */ + WL_PROXD_EVENT_MF_STATS = 19, /* mf stats event */ WL_PROXD_EVENT_MAX }; @@ -11311,13 +13595,13 @@ typedef uint32 wl_proxd_event_mask_t; /** proxd event - applies to proxd, method or session */ typedef struct wl_proxd_event { - uint16 version; - uint16 len; - wl_proxd_event_type_t type; - wl_proxd_method_t method; - wl_proxd_session_id_t sid; - uint8 pad[2]; - wl_proxd_tlv_t tlvs[1]; /**< variable */ + uint16 version; + uint16 len; + wl_proxd_event_type_t type; + wl_proxd_method_t method; + wl_proxd_session_id_t sid; + uint8 pad[2]; + wl_proxd_tlv_t tlvs[1]; /**< variable */ } wl_proxd_event_t; enum { @@ -11346,14 +13630,37 @@ struct wl_proxd_ranging_info { typedef struct wl_proxd_ranging_info wl_proxd_ranging_info_t; #include -typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_event_data { +/* Legacy platform i.e. 43342/43430 */ +#define WL_PROXD_COLLECT_EVENT_DATA_VERSION_1 1 +typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_event_data_v1 { uint32 H_LB[K_TOF_COLLECT_H_SIZE_20MHZ]; uint32 H_RX[K_TOF_COLLECT_H_SIZE_20MHZ]; uint8 ri_rr[FTM_TPK_LEN]; wl_proxd_phy_error_t phy_err_mask; -} BWL_POST_PACKED_STRUCT wl_proxd_collect_event_data_t; +} BWL_POST_PACKED_STRUCT wl_proxd_collect_event_data_v1_t; + +/* Secured 2.0 supoorted devices i.e. 4364 */ +#define WL_PROXD_COLLECT_EVENT_DATA_VERSION_2 2 +typedef BWL_PRE_PACKED_STRUCT struct wl_proxd_collect_event_data_v2 { + uint32 H_LB[K_TOF_COLLECT_H_SIZE_20MHZ]; + uint32 H_RX[K_TOF_COLLECT_H_SIZE_20MHZ]; + uint8 ri_rr[FTM_TPK_RI_RR_LEN_SECURE_2_0]; + wl_proxd_phy_error_t phy_err_mask; +} BWL_POST_PACKED_STRUCT wl_proxd_collect_event_data_v2_t; #include +#define WL_PROXD_COLLECT_EVENT_DATA_VERSION_3 3 +typedef struct wl_proxd_collect_event_data_v3 { + uint16 version; + uint16 length; + uint32 H_LB[K_TOF_COLLECT_H_SIZE_20MHZ]; + uint32 H_RX[K_TOF_COLLECT_H_SIZE_20MHZ]; + uint8 ri_rr[FTM_TPK_RI_RR_LEN_SECURE_2_0]; + wl_proxd_phy_error_t phy_err_mask; +} wl_proxd_collect_event_data_v3_t; + +#define WL_PROXD_COLLECT_EVENT_DATA_VERSION_MAX WL_PROXD_COLLECT_EVENT_DATA_VERSION_3 + /** Data returned by the bssload_report iovar. This is also the WLC_E_BSS_LOAD event data */ #include typedef BWL_PRE_PACKED_STRUCT struct wl_bssload { @@ -11494,6 +13801,22 @@ typedef struct wnm_bss_select_weight_cfg { uint16 weight; /* weightage for each type between 0 to 100 */ } wnm_bss_select_weight_cfg_t; +/* For branches before koala .. wbtext is part + * of wnm need to use below type only + */ +typedef struct wnm_btm_default_score_cfg { + uint32 default_score; /* default score */ + uint8 band; +} wnm_btm_default_score_cfg_t; + +/* For branches from koala and above .. wbtext is + * seperate module..need to use below type only + */ +typedef struct wbtext_btm_default_score_cfg { + uint32 default_score; /* default score */ + uint8 band; +} wbtext_btm_default_score_cfg_t; + #define WNM_BSS_SELECT_TYPE_RSSI 0 #define WNM_BSS_SELECT_TYPE_CU 1 @@ -11544,6 +13867,10 @@ typedef enum wl_interface_type { WL_INTERFACE_TYPE_AP = 1, WL_INTERFACE_TYPE_AWDL = 2, WL_INTERFACE_TYPE_NAN = 3, + WL_INTERFACE_TYPE_P2P_GO = 4, + WL_INTERFACE_TYPE_P2P_GC = 5, + WL_INTERFACE_TYPE_P2P_DISC = 6, + WL_INTERFACE_TYPE_IBSS = 7, WL_INTERFACE_TYPE_MAX } wl_interface_type_t; @@ -11816,15 +14143,21 @@ typedef struct wl_bcntrim_status_v1 { uint32 data[]; /* variable length data containing stats */ } wl_bcntrim_status_v1_t; -#define BCNTRIM_STATS_MAX 10 /* Total stats part of the status data[] */ +#define BCNTRIM_STATS_MAX 10 /* Total stats part of the status data[] */ /* Bits for FW status */ -#define WL_BCNTRIM_DISABLE_HOST 0x1 /* Host disabled bcntrim through bcntrim IOVar */ -#define WL_BCNTRIM_DISABLE_PHY_RATE 0x2 /* bcntrim disabled because beacon rx rate is - higher than phy_rate_thresh - */ -#define WL_BCNTRIM_DISABLE_QUIET_IE 0x4 /* bcntrim disable when Quiet IE present */ - +#define WL_BCNTRIM_DISABLE_HOST 0x1 /* Host disabled bcntrim through bcntrim IOVar */ +#define WL_BCNTRIM_DISABLE_PHY_RATE 0x2 /* bcntrim disabled because beacon rx rate is + * higher than phy_rate_thresh + */ +#define WL_BCNTRIM_DISABLE_QUIET_IE 0x4 /* bcntrim disable when Quiet IE present */ +#define WL_BCNTRIM_DISABLE_QBSSLOAD_IE 0x8 /* bcntrim disable when QBSS Load IE present */ +#define WL_BCNTRIM_DISABLE_OPERMODE_IE 0x10 /* bcntrim dsiable when opermode IE is present */ +#define WL_BCNTRIM_DISABLE_CSA_IE 0x20 /* bcntrim dsiable when CSA IE is present */ + +#define BCNTRIM_DISABLE_THRESHOLD_TIME 1000 * 10 /* enable bcntrim after a threshold (10sec) + * when disabled due to above mentioned IE's + */ #define WL_BCNTRIM_CFG_VERSION_1 1 /* Common IOVAR struct */ typedef struct wl_bcntrim_cfg_v1 { @@ -11846,7 +14179,8 @@ enum { #define BCNTRIM_MAX_PHY_RATE 48 /* in 500Kbps */ #define BCNTRIM_MAX_TSF_DRIFT 65535 /* in usec */ -#define WL_BCNTRIM_OVERRIDE_DISABLE_MASK (WL_BCNTRIM_DISABLE_QUIET_IE) +#define WL_BCNTRIM_OVERRIDE_DISABLE_MASK \ + (WL_BCNTRIM_DISABLE_QUIET_IE | WL_BCNTRIM_DISABLE_QBSSLOAD_IE) /* WL_BCNTRIM_CFG_SUBCMD_PHY_RATE_TRESH */ typedef struct wl_bcntrim_cfg_phy_rate_thresh { @@ -11864,17 +14198,18 @@ typedef struct wl_bcntrim_cfg_tsf_drift_limit { uint8 pad[2]; /* 4-byte alignment */ } wl_bcntrim_cfg_tsf_drift_limit_t; - /* -------------- TX Power Cap --------------- */ #define TXPWRCAP_MAX_NUM_CORES 8 #define TXPWRCAP_MAX_NUM_ANTENNAS (TXPWRCAP_MAX_NUM_CORES * 2) #define TXPWRCAP_NUM_SUBBANDS 5 +#define TXPWRCAP_MAX_NUM_SUBGRPS 10 /* IOVAR txcapconfig enum's */ -#define TXPWRCAPCONFIG_WCI2 0 -#define TXPWRCAPCONFIG_HOST 1 -#define TXPWRCAPCONFIG_WCI2_AND_HOST 2 +#define TXPWRCAPCONFIG_WCI2 0u +#define TXPWRCAPCONFIG_HOST 1u +#define TXPWRCAPCONFIG_WCI2_AND_HOST 2u +#define TXPWRCAPCONFIG_NONE 0xFFu /* IOVAR txcapstate enum's */ #define TXPWRCAPSTATE_LOW_CAP 0 @@ -11886,6 +14221,8 @@ typedef struct wl_bcntrim_cfg_tsf_drift_limit { /* IOVAR txcapconfig and txcapstate structure is shared: SET and GET */ #define TXPWRCAPCTL_VERSION 2 +#define TXPWRCAPCTL_VERSION_3 3 + typedef struct wl_txpwrcap_ctl { uint8 version; uint8 ctl[TXPWRCAP_NUM_SUBBANDS]; @@ -11936,6 +14273,95 @@ typedef struct wl_txpwrcap_dump_v3 { uint8 PAD[2]; } wl_txpwrcap_dump_v3_t; +/* +* Capability flag for wl_txpwrcap_tbl_v2_t and wl_txpwrcap_t +* The index into pwrs will be: 0: onbody-cck, 1: onbody-ofdm, 2:offbody-cck, 3:offbody-ofdm +* +* For 5G power in SDB case as well as for non-SDB case, the value of flag will be: CAP_ONOFF_BODY +* The index into pwrs will be: 0: onbody, 1: offbody-ofdm +*/ + +#define CAP_ONOFF_BODY (0x1) /* on/off body only */ +#define CAP_CCK_OFDM (0x2) /* cck/ofdm capability only */ +#define CAP_LTE_CELL (0x4) /* cell on/off capability; required for iOS builds */ +#define CAP_HEAD_BODY (0x8) /* head/body capability */ +#define CAP_2G_DEPON_5G (0x10) /* 2G pwr caps depend on other slice 5G subband */ +#define CAP_SISO_MIMO (0x20) /* Siso/Mimo Separate Power Caps */ +#define CAP_ANT_TX (0x40) /* Separate Power Caps based on cell ant tx value */ +#define CAP_ONOFF_BODY_CCK_OFDM (CAP_ONOFF_BODY | CAP_CCK_OFDM) +#define CAP_TXPWR_ALL (CAP_ONOFF_BODY|CAP_CCK_OFDM|CAP_LTE_CELL|\ + CAP_SISO_MIMO|CAP_HEAD_BODY|CAP_ANT_TX) + +#define TXHDR_SEC_MAX 5u /* Deprecated. Kept till removed in all branches */ +#define TXPWRCAP_MAX_STATES 4u +#define TXPWRCAP_CCKOFDM_ONOFFBODY_MAX_STATES 4u +#define TXPWRCAP_ONOFFBODY_MAX_STATES 2u +#define TXPWRCAP_ONOFFCELL_MAX_STATES 2u + +#define TXHDR_SEC_NONSDB_MAIN_2G 0 +#define TXHDR_SEC_NONSDB_MAIN_5G 1 +#define TXHDR_SEC_NONSDB_AUX_2G 2 +#define TXHDR_SEC_NONSDB_AUX_5G 3 +#define TXHDR_SEC_SDB_MAIN_2G 4 +#define TXHDR_SEC_SDB_MAIN_5G 5 +#define TXHDR_SEC_SDB_AUX_2G 6 +#define TXHDR_SEC_SDB_AUX_5G 7 +#define TXHDR_MAX_SECTION 8 + +#define WL_TXPWRCAP_MAX_SLICES 2 +#define WL_TXPWRCAPDUMP_VER 4 + +#define WL_TXPWRCAP_VERSION_2 2 +#define WL_TXPWRCAP_VERSION_3 3 + +typedef struct wl_txpwrcap { + uint8 capability; + uint8 num_cap_states; + uint8 section; /* Index from above,eg. TXHDR_SEC_NONSDB */ + int8 pwrs[][TXPWRCAP_NUM_SUBBANDS][TXPWRCAP_MAX_NUM_CORES]; +} wl_txpwrcap_t; + +typedef struct { + uint8 capability; + uint8 num_cap_states; + uint8 num_subgrps; + uint8 section; /* Index from above,eg. TXHDR_SEC_NONSDB */ + int8 pwrs[][TXPWRCAP_MAX_NUM_SUBGRPS][TXPWRCAP_MAX_NUM_ANTENNAS]; +} wl_txpwrcap_v2_t; + +#define TXPWRCAP_DUMP_VERSION_4 4 +#define TXPWRCAP_DUMP_VERSION_5 5 + +typedef struct wl_txpwrcap_dump_v4 { + uint8 version; + uint8 num_pwrcap; + uint8 current_country[2]; + uint32 current_channel; + uint8 download_present; + uint8 num_cores; /* number cores on slice */ + uint8 num_cc_groups; /* number cc groups */ + uint8 current_country_cc_group_info_index; + /* first power cap always exist + * On main,-non-sdb follows by sdb2g and then sdb5g + * On aux slice - aux2g then aux5g. + */ + wl_txpwrcap_t pwrcap; /* first power cap */ +} wl_txpwrcap_dump_v4_t; + +typedef struct wl_txpwrcap_dump_v5 { + uint8 version; + uint8 num_pwrcap; + uint8 current_country[2]; + uint32 current_channel; + uint8 download_present; + uint8 num_ants; /* number antenna slice */ + uint8 num_cc_groups; /* number cc groups */ + uint8 current_country_cc_group_info_index; + uint8 ant_tx; /* current value of ant_tx */ + uint8 cell_status; /* current value of cell status */ + uint8 pwrcap[]; /* variable size power caps (wl_txpwrcap_v2_t) */ +} wl_txpwrcap_dump_v5_t; + typedef struct wl_txpwrcap_tbl { uint8 num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES]; /* Stores values for valid antennas */ @@ -11943,6 +14369,32 @@ typedef struct wl_txpwrcap_tbl { int8 pwrcap_cell_off[TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */ } wl_txpwrcap_tbl_t; +typedef struct wl_txpwrcap_tbl_v2 { + uint8 version; + uint8 length; /* size of entire structure, including the pwrs */ + uint8 capability; /* capability bitmap */ + uint8 num_cores; /* number of cores i.e. entries in each cap state row */ + /* + * pwrs array has TXPWRCAP_MAX_STATES rows - one for each cap state. + * Each row has up to TXPWRCAP_MAX_NUM_CORES entries - one for each core. + */ + uint8 pwrs[][TXPWRCAP_MAX_NUM_CORES]; /* qdBm units */ +} wl_txpwrcap_tbl_v2_t; + +typedef struct wl_txpwrcap_tbl_v3 { + uint8 version; + uint8 length; /* size of entire structure, including the pwrs */ + uint8 capability; /* capability bitmap */ + uint8 num_cores; /* number of cores */ + uint8 num_antennas_per_core[TXPWRCAP_MAX_NUM_CORES]; + /* + * pwrs array has TXPWRCAP_MAX_STATES rows - one for each cap state. + * Each row has up to TXPWRCAP_MAX_NUM_ANTENNAS entries - for each antenna. + * Included in the rows of powers are rows for fail safe. + */ + uint8 pwrs[][TXPWRCAP_MAX_NUM_ANTENNAS]; /* qdBm units */ +} wl_txpwrcap_tbl_v3_t; + /* ##### Ecounters section ##### */ #define ECOUNTERS_VERSION_1 1 @@ -11982,11 +14434,13 @@ typedef struct ecounters_trigger_config { } ecounters_trigger_config_t; #define ECOUNTERS_TRIGGER_REASON_VERSION_1 1 -/* Triggered due to timer based ecounters */ -#define ECOUNTERS_TRIGGER_REASON_TIMER 0 -/* Triggered due to event based configuration */ -#define ECOUNTERS_TRIGGER_REASON_EVENTS 1 -#define ECOUNTERS_TRIGGER_REASON_MAX 1 +typedef enum { + /* Triggered due to timer based ecounters */ + ECOUNTERS_TRIGGER_REASON_TIMER = 0, + /* Triggered due to event based configuration */ + ECOUNTERS_TRIGGER_REASON_EVENTS = 1, + ECOUNTERS_TRIGGER_REASON_MAX = 2 +} ecounters_trigger_reasons_list_t; typedef struct ecounters_trigger_reason { uint16 version; /* version */ @@ -12002,6 +14456,79 @@ typedef struct ecounters_trigger_reason { #define WL_LQM_CURRENT_BSS_VALID 0x1 #define WL_LQM_TARGET_BSS_VALID 0x2 +#define WL_PERIODIC_COMPACT_CNTRS_VER_1 (1) +#define WL_PERIODIC_TXBF_CNTRS_VER_1 (1) +typedef struct { + uint16 version; + uint16 pad; + /* taken from wl_wlc_cnt_t */ + uint32 txfail; + /* taken from wl_cnt_ge40mcst_v1_t */ + uint32 txallfrm; /**< total number of frames sent, incl. Data, ACK, RTS, CTS, + * Control Management (includes retransmissions) + */ + uint32 txrtsfrm; /**< number of RTS sent out by the MAC */ + uint32 txctsfrm; /**< number of CTS sent out by the MAC */ + uint32 txback; /**< blockack txcnt */ + uint32 txucast; /**< number of unicast tx expecting response other than cts/cwcts */ + uint32 txnoack; /**< dot11ACKFailureCount */ + uint32 txframe; /**< tx data frames */ + uint32 txretrans; /**< tx mac retransmits */ + uint32 txpspoll; /**< Number of TX PS-poll */ + + uint32 rxrsptmout; /**< number of response timeouts for transmitted frames + * expecting a response + */ + uint32 txrtsfail; /**< number of rts transmission failure that reach retry limit */ + uint32 rxstrt; /**< number of received frames with a good PLCP */ + uint32 rxbadplcp; /**< number of parity check of the PLCP header failed */ + uint32 rxcrsglitch; /**< PHY was able to correlate the preamble but not the header */ + uint32 rxnodelim; /**< number of no valid delimiter detected by ampdu parser */ + uint32 bphy_badplcp; /**< number of bad PLCP reception on BPHY rate */ + uint32 bphy_rxcrsglitch; /**< PHY count of bphy glitches */ + uint32 rxbadfcs; /**< number of frames for which the CRC check failed in the MAC */ + uint32 rxf0ovfl; /**< number of receive fifo 0 overflows */ + uint32 rxf1ovfl; /**< number of receive fifo 0 overflows */ + uint32 rxhlovfl; /**< number of length / header fifo overflows */ + uint32 rxrtsucast; /**< number of unicast RTS addressed to the MAC (good FCS) */ + uint32 rxctsucast; /**< number of unicast CTS addressed to the MAC (good FCS) */ + uint32 rxackucast; /**< number of ucast ACKS received (good FCS) */ + uint32 rxback; /**< blockack rxcnt */ + uint32 rxbeaconmbss; /**< beacons received from member of BSS */ + uint32 rxdtucastmbss; /**< number of received DATA frames with good FCS and matching RA */ + uint32 rxbeaconobss; /**< beacons received from other BSS */ + uint32 rxdtucastobss; /**< number of unicast frames addressed to the MAC from + * other BSS (WDS FRAME) + */ + uint32 rxdtocast; /**< number of received DATA frames (good FCS and no matching RA) */ + uint32 rxrtsocast; /**< number of received RTS not addressed to the MAC */ + uint32 rxctsocast; /**< number of received CTS not addressed to the MAC */ + uint32 rxdtmcast; /**< number of RX Data multicast frames received by the MAC */ + uint32 rxmpdu_mu; /**< Number of MU MPDUs received */ + uint32 rxtoolate; /**< receive too late */ + uint32 rxframe; /**< rx data frames */ + uint32 lqcm_report; /**< lqcm metric tx/rx idx */ + uint32 tx_toss_cnt; /* number of tx packets tossed */ + uint32 rx_toss_cnt; /* number of rx packets tossed */ + uint32 last_tx_toss_rsn; /* reason because of which last tx pkt tossed */ + uint32 last_rx_toss_rsn; /* reason because of which last rx pkt tossed */ + uint32 txbcnfrm; /**< beacons transmitted */ +} wl_periodic_compact_cntrs_v1_t; + +typedef struct { + uint16 version; + uint16 coreup; + uint32 txndpa; + uint32 txndp; + uint32 rxsf; + uint32 txbfm; + uint32 rxndpa_u; + uint32 rxndpa_m; + uint32 bferpt; + uint32 rxbfpoll; + uint32 txsf; +} wl_periodic_txbf_cntrs_v1_t; + typedef struct { struct ether_addr BSSID; chanspec_t chanspec; @@ -12018,6 +14545,29 @@ typedef struct { wl_rx_signal_metric_t target_bss; } wl_lqm_t; +#define WL_PERIODIC_IF_STATE_VER_1 (1) +typedef struct wl_if_state_compact { + uint8 version; + uint8 assoc_state; + uint8 antenna_count; /**< number of valid antenna rssi */ + int8 noise_level; /**< noise right after tx (in dBm) */ + int8 snr; /* current noise level */ + int8 rssi_sum; /**< summed rssi across all antennas */ + uint16 pad16; + int8 rssi_ant[WL_RSSI_ANT_MAX]; /**< rssi per antenna */ + struct ether_addr BSSID; + chanspec_t chanspec; +} wl_if_state_compact_t; + +#define WL_EVENT_STATISTICS_VER_1 (1) +/* Event based statistics ecounters */ +typedef struct { + uint16 version; + uint16 pad; + struct ether_addr BSSID; /* BSSID of the BSS */ + uint32 txdeauthivalclass; +} wl_event_based_statistics_v1_t; + /* ##### Ecounters v2 section ##### */ #define ECOUNTERS_VERSION_2 2 @@ -12059,6 +14609,43 @@ typedef struct ecounters_stats_types_report_req { uint8 stats_types_req[]; /* XTLVs of requested types */ } ecounters_stats_types_report_req_t; +/* ##### Ecounters_Eventmsgs v2 section ##### */ + +#define ECOUNTERS_EVENTMSGS_VERSION_2 2 + +typedef struct event_ecounters_config_request_v2 { + uint16 version; /* config version */ + uint16 len; /* Length of this struct including variable len */ + uint16 logset; /* Set where data will go. */ + uint16 event_id; /* Event id for which this config is meant for */ + uint8 flags; /* Config flags */ + uint8 pad[3]; /* Reserved for future use */ + uint8 ecounters_xtlvs[]; /* Statistics Types (tags) to retrieve. */ +} event_ecounters_config_request_v2_t; + +#define EVENT_ECOUNTERS_FLAGS_ADD (1 << 0) /* Add configuration for the event_id if set */ +#define EVENT_ECOUNTERS_FLAGS_DEL (1 << 1) /* Delete configuration for event_id if set */ +#define EVENT_ECOUNTERS_FLAGS_ANYIF (1 << 2) /* Interface filtering disable / off bit */ +#define EVENT_ECOUNTERS_FLAGS_BE (1 << 3) /* If cleared report stats of + * one event log buffer + */ +#define EVENT_ECOUNTERS_FLAGS_DEL_ALL (1 << 4) /* Delete all the configurations of + * event ecounters if set + */ + +/* Ecounters suspend resume */ +#define ECOUNTERS_SUSPEND_VERSION_V1 1 +/* To be used in populating suspend_mask and suspend_bitmap */ +#define ECOUNTERS_SUSPEND_TIMER (1 << ECOUNTERS_TRIGGER_REASON_TIMER) +#define ECOUNTERS_SUSPEND_EVENTS (1 << ECOUNTERS_TRIGGER_REASON_EVENTS) + +typedef struct ecounters_suspend { + uint16 version; + uint16 len; + uint32 suspend_bitmap; /* type of ecounter reporting to be suspended */ + uint32 suspend_mask; /* type of ecounter reporting to be suspended */ +} ecounters_suspend_t; + /* -------------- dynamic BTCOEX --------------- */ #define DCTL_TROWS 2 /**< currently practical number of rows */ #define DCTL_TROWS_MAX 4 /**< 2 extra rows RFU */ @@ -12429,7 +15016,6 @@ typedef enum { } ulb_bw_type_t; /* endif WL11ULB */ - #define WL_MESH_IOCTL_VERSION 1 #define MESH_IOC_BUFSZ 512 /* sufficient ioc buff size for mesh */ @@ -12713,7 +15299,6 @@ typedef struct rsdb_bands #define WL_RSDB_CONFIG_LEN sizeof(rsdb_config_t) - typedef uint8 rsdb_opmode_t; typedef uint32 rsdb_flags_t; @@ -12823,11 +15408,37 @@ typedef struct sb_channel_sequence { typedef struct slice_chan_seq { uint8 slice_index; /* 0(Main) or 1 (Aux) */ uint8 num_chanspecs; - uint16 pad; + uint8 dur; + uint8 pad; chanspec_t chanspecs[1]; } slice_chan_seq_t; +#define SLOT_BSS_SLICE_TYPE_DUR_MAX_RANGE 2u + #define WL_SLICE_CHAN_SEQ_FIXED_LEN OFFSETOF(slice_chan_seq_t, chanspecs) +/* Definitions for slotted_bss stats */ +#define SBSS_STATS_VERSION 1 +#define SBSS_STATS_CURRENT_VERSION SBSS_STATS_VERSION + +#define SBSS_MAX_CHAN_STATS 4 +typedef struct sbss_core_stats { + uint32 sb_slot_start; + uint32 sb_slot_end; + uint32 sb_slot_skip; + uint32 mismatch_count; +} sbss_core_stats_t; +typedef struct sbss_chan_stats { + chanspec_t chanspec; + uint32 slot_start; + uint32 slot_end; + uint32 slot_skip; +} sbss_chan_stats_t; +typedef struct sbss_stats_v1 { + uint16 version; + uint16 length; + sbss_core_stats_t corestats[MAX_NUM_D11CORES]; + sbss_chan_stats_t sbss_chanstats[MAX_NUM_D11CORES][SBSS_MAX_CHAN_STATS]; +} sbss_stats_t; typedef struct sim_pm_params { uint32 enabled; @@ -12835,18 +15446,50 @@ typedef struct sim_pm_params { uint16 up; } sim_pm_params_t; +/* Digital napping status */ +#define WL_NAP_STATUS_VERSION_1 1 +typedef struct wl_nap_status_v1 { + uint16 version; /* structure version */ + uint16 len; /* length of returned data */ + uint16 fw_status; /* bitmask of FW disable reasons */ + uint8 hw_status; /* bitmask for actual HW state info */ + uint8 slice_index; /* which slice this represents */ + uint32 total_disable_dur; /* total time (ms) disabled for fw_status */ +} wl_nap_status_v1_t; + /* Bits for fw_status */ -#define NAP_DISABLED_HOST 0x01 /* Host has disabled through nap_enable */ -#define NAP_DISABLED_RSSI 0x02 /* Disabled because of nap_rssi_threshold */ +#define NAP_DISABLED_HOST 0x0001 /* Host has disabled through nap_enable */ +#define NAP_DISABLED_RSSI 0x0002 /* Disabled because of nap_rssi_threshold */ +#define NAP_DISABLED_SCAN 0x0004 /* Disabled because of scan */ +#define NAP_DISABLED_ASSOC 0x0008 /* Disabled because of association */ +#define NAP_DISABLED_LTE 0x0010 /* Disabled because of LTE */ +#define NAP_DISABLED_ACI 0x0020 /* Disabled because of ACI mitigation */ /* Bits for hw_status */ #define NAP_HWCFG 0x01 /* State of NAP config bit in phy HW */ +#define NAP_NOCLK 0x80 /* No clock to read HW (e.g. core down) */ /* ifdef WL_NATOE */ #define WL_NATOE_IOCTL_VERSION 1 #define WL_NATOE_IOC_BUFSZ 512 /* sufficient ioc buff size for natoe */ #define WL_NATOE_DBG_STATS_BUFSZ 2048 +#define NATOE_FLAGS_ENAB_MASK 0x1 +#define NATOE_FLAGS_ACTIVE_MASK 0x2 +#define NATOE_FLAGS_PUBNW_MASK 0x4 +#define NATOE_FLAGS_PVTNW_MASK 0x8 +#define NATOE_FLAGS_ENAB_SHFT_MASK 0 +#define NATOE_FLAGS_ACTIVE_SHFT_MASK 1 +#define NATOE_FLAGS_PUBNW_SHFT_MASK 2 +#define NATOE_FLAGS_PVTNW_SHFT_MASK 3 +#define NATOE_FLAGS_PUB_NW_UP (1 << NATOE_FLAGS_PUBNW_SHFT_MASK) +#define NATOE_FLAGS_PVT_NW_UP (1 << NATOE_FLAGS_PVTNW_SHFT_MASK) + +/* Module version is 1 for IGUANA +*/ +#define WL_NATOE_MODULE_VER_1 1 +/* WL_NATOE_CMD_MOD_VER */ +typedef uint16 wl_natoe_ver_t; /* config natoe STA and AP IP's structure */ typedef struct { uint32 sta_ip; @@ -12881,7 +15524,91 @@ typedef struct wl_natoe_ioc { uint8 data[]; /* var len payload of bcm_xtlv_t type */ } wl_natoe_ioc_t; +typedef struct wl_natoe_pool_stats_v1 { + /* For debug purposes */ + uint16 poolreorg_cnt; + uint16 poolrevert_cnt; + uint16 txfrag_state; + uint16 rxfrag_state; + uint16 txfrag_plen; + uint16 rxfrag_plen; + uint16 tx_pavail; + uint16 rx_pavail; + uint16 txmin_bkup_bufs; + uint16 rxmin_bkup_bufs; + uint16 pktpool_sbuf_alloc; + uint16 pktpool_plen; + uint16 pktpool_pavail; + /* Peak shared buffer count in all iterations */ + uint16 sbuf_peak; + /* Peak shared buffer count in current D3 iteration */ + uint16 sbuf_peak_cur; +} wl_natoe_pool_stats_v1_t; + +typedef struct wl_natoe_arp_entry_v1 { + struct ipv4_addr ip; + struct ether_addr mac_addr; + uint8 lifetime; + uint8 flags; +} wl_natoe_arp_entry_v1_t; + +typedef struct wl_natoe_dbg_arp_tbl_info_v1 { + uint8 valid_arp_entries; + uint8 PAD[3]; + wl_natoe_arp_entry_v1_t arp_ent[]; +} wl_natoe_dbg_arp_tbl_info_v1_t; + +typedef struct wl_natoe_skip_port_entry_v1 { + struct ipv4_addr srcip; + uint16 src_port; + uint16 lifetime; +} wl_natoe_skip_port_entry_v1_t; + +typedef struct wl_natoe_skip_port_info_v1 { + uint8 valid_entries; + uint8 PAD[3]; + wl_natoe_skip_port_entry_v1_t skip_port_ent[]; +} wl_natoe_skip_port_info_v1_t; + +typedef struct wl_natoe_dbg_stats_v1 { + uint16 active_nat_entries; + uint16 active_dns_entries; + uint16 active_icmp_entries; + uint16 valid_arp_entries; + uint16 prev_nat_entries; + uint16 prev_dns_entries; + uint16 tcp_fast_reclaim_cnt; + uint16 mcast_packets; + uint16 bcast_packets; + uint16 port_commands_rcvd; + uint16 unsupported_prot; + uint16 arp_req_sent; + uint16 arp_rsp_rcvd; + uint16 non_ether_frames; + uint16 port_alloc_fail; + uint16 srcip_tbl_full; + uint16 dstip_tbl_full; + uint16 nat_tbl_full; + uint16 icmp_error_cnt; + uint16 pkt_drops_resource; + uint32 frwd_nat_pkt_cnt; + uint32 reverse_nat_pkt_cnt; + uint16 pub_nw_chspec; + uint16 pvt_nw_chspec; + uint8 pubnw_cfg_idx; + uint8 pvtnw_cfg_idx; + uint8 pubnw_cfg_ID; + uint8 pvtnw_cfg_ID; + uint16 natoe_flags; +} wl_natoe_dbg_stats_v1_t; + +typedef struct wl_natoe_exception_port_inf_v1 { + uint16 except_bmap_size; + uint8 port_except_bmap[]; +} wl_natoe_exception_port_inf_v1_t; + enum wl_natoe_cmds { + WL_NATOE_CMD_MOD_VER = 0, WL_NATOE_CMD_ENABLE = 1, WL_NATOE_CMD_CONFIG_IPS = 2, WL_NATOE_CMD_CONFIG_PORTS = 3, @@ -12892,13 +15619,16 @@ enum wl_natoe_cmds { }; enum wl_natoe_cmd_xtlv_id { + WL_NATOE_XTLV_MOD_VER = 0, WL_NATOE_XTLV_ENABLE = 1, WL_NATOE_XTLV_CONFIG_IPS = 2, WL_NATOE_XTLV_CONFIG_PORTS = 3, WL_NATOE_XTLV_DBG_STATS = 4, WL_NATOE_XTLV_EXCEPTION_PORT = 5, WL_NATOE_XTLV_SKIP_PORT = 6, - WL_NATOE_XTLV_TBL_CNT = 7 + WL_NATOE_XTLV_TBL_CNT = 7, + WL_NATOE_XTLV_ARP_TBL = 8, + WL_NATOE_XTLV_POOLREORG = 9 }; /* endif WL_NATOE */ @@ -12952,12 +15682,29 @@ typedef struct wl_utrace_capture_args_v2 { uint32 flag; /* Indicates if there is more data or not */ } wl_utrace_capture_args_v2_t; +/* Signal read end. */ +#define WLC_REGVAL_READ_END 0 +/* Signal more data pending. */ +#define WLC_REGVAL_MORE_DATA 1 +/* Internal read state. */ +#define WLC_REGVAL_READ_CONTINUE 2 + +#define WLC_REGVAL_DUMP_PHYREG 0 +#define WLC_REGVAL_DUMP_RADREG 1 + +#define PHYREGVAL_CAPTURE_BUFFER_LEN 2048 + +typedef struct wl_regval_capture_args { + uint32 control_flag; /* Carries status information. */ +} wl_regval_capture_args_t; + /* XTLV IDs for the Health Check "hc" iovar top level container */ enum { WL_HC_XTLV_ID_CAT_HC = 1, /* category for HC as a whole */ WL_HC_XTLV_ID_CAT_DATAPATH_TX = 2, /* Datapath Tx */ WL_HC_XTLV_ID_CAT_DATAPATH_RX = 3, /* Datapath Rx */ WL_HC_XTLV_ID_CAT_SCAN = 4, /* Scan */ + WL_HC_XTLV_ID_CAT_EVENTMASK = 5, /* Health Check event mask. */ }; /* Health Check: Common XTLV IDs for sub-elements in the top level container @@ -12979,6 +15726,7 @@ enum { WL_HC_TX_XTLV_ID_VAL_FC_FORCE = 7, /* flow ctl force failure */ WL_HC_TX_XTLV_ID_VAL_DELAY_TO_TRAP = 8, /* delay threshold for forced trap */ WL_HC_TX_XTLV_ID_VAL_DELAY_TO_RPT = 9, /* delay threshold for event log report */ + WL_HC_TX_XTLV_ID_VAL_FAILURE_TO_RPT = 10, /* threshold for consecutive TX failures */ }; /* Health Check: Datapath RX IDs */ @@ -12995,15 +15743,28 @@ enum { WL_HC_XTLV_ID_VAL_SCAN_STALL_THRESHOLD = 1, /* scan stall threshold */ }; +/* Health check: PHY IDs */ +typedef enum { + PHY_HC_DD_ALL = 0, + PHY_HC_DD_TEMPSENSE = 1, + PHY_HC_DD_VCOCAL = 2, + PHY_HC_DD_RX = 3, + PHY_HC_DD_TX = 4, + PHY_HC_DD_LAST /* This must be the last entry */ +} phy_hc_dd_type_t; + /* IDs of Health Check report structures for sub types of health checks within WL */ -enum { - WL_HC_DD_UNDEFINED = 0, /* Undefined */ +typedef enum wl_hc_dd_type { + WL_HC_DD_PCIE = 0, /* PCIe */ WL_HC_DD_RX_DMA_STALL = 1, /* RX DMA stall check */ WL_HC_DD_RX_STALL = 2, /* RX stall check */ WL_HC_DD_TX_STALL = 3, /* TX stall check */ WL_HC_DD_SCAN_STALL = 4, /* SCAN stall check */ + WL_HC_DD_PHY = 5, /* PHY health check */ + WL_HC_DD_REINIT = 6, /* Reinit due to other reasons */ + WL_HC_DD_TXQ_STALL = 7, /* TXQ stall */ WL_HC_DD_MAX -}; +} wl_hc_dd_type_t; /* * Health Check report structures for sub types of health checks within WL @@ -13048,35 +15809,90 @@ enum { WL_HE_CMD_TWT_INFO = 4, WL_HE_CMD_BSSCOLOR = 5, WL_HE_CMD_PARTIAL_BSSCOLOR = 6, + WL_HE_CMD_CAP = 7, + WL_HE_CMD_STAID = 8, + WL_HE_CMD_RTSDURTHRESH = 10, + WL_HE_CMD_PEDURATION = 11, WL_HE_CMD_LAST }; -#define WL_HEB_VERSION 0 +/* TWT top level command IDs */ +enum { + WL_TWT_CMD_ENAB = 0, + WL_TWT_CMD_SETUP = 1, + WL_TWT_CMD_TEARDOWN = 2, + WL_TWT_CMD_INFO = 3, + WL_TWT_CMD_LAST +}; + +/* TODO: Remove the follwoing after mering TWT changes to trunk */ +#define WL_TWT_CMD_DEF_IN_WLIOCTL 1 + +#define WL_HEB_VER_1 1 /* HEB top level command IDs */ enum { WL_HEB_CMD_ENAB = 0, WL_HEB_CMD_NUM_HEB = 1, - WL_HEB_CMD_COUNTERS = 1, - WL_HEB_CMD_CLEAR_COUNTERS = 2, + WL_HEB_CMD_COUNTERS = 2, + WL_HEB_CMD_CLEAR_COUNTERS = 3, + WL_HEB_CMD_CONFIG = 4, + WL_HEB_CMD_STATUS = 5, WL_HEB_CMD_LAST }; /* HEB counters structures */ -typedef struct { +typedef struct wl_heb_int_cnt_v1 { uint16 pre_event; uint16 start_event; uint16 end_event; uint16 missed; -} wl_heb_int_cnt_t; +} wl_heb_int_cnt_v1_t; -typedef struct { +typedef struct wl_heb_cnt_v1 { /* structure control */ uint16 version; /* structure version */ uint16 length; /* data length (starting after this field) */ - wl_heb_int_cnt_t heb_int_cnt[1]; -} wl_heb_cnt_t; + wl_heb_int_cnt_v1_t heb_int_cnt[1]; +} wl_heb_cnt_v1_t; +// struct for configuring HEB +typedef struct wl_config_heb_fill_v1 { + uint16 version; /* structure version */ + uint16 length; /* data length (starting after this field) */ + uint32 duration; + uint32 periodicity; + uint16 heb_idx; + uint16 preeventtime; + uint8 count; + uint8 PAD[3]; +} wl_config_heb_fill_v1_t; + +typedef struct wl_heb_blk_params_v1 { + /* Don't change the order of following elements. This is as per the HEB HW spec */ + uint32 event_int_val_l; + uint32 event_int_val_h; + uint32 param2; + uint32 param3; + uint32 pre_event_intmsk_bmp; + uint32 start_event_intmsk_bmp; + uint32 end_event_intmsk_bmp; + uint32 event_driver_info; + uint16 param1; + uint8 event_count; + uint8 noa_invert; +} wl_heb_blk_params_v1_t; + +typedef struct wl_heb_int_status_v1 { + uint32 heb_idx; + wl_heb_blk_params_v1_t blk_params; +} wl_heb_reg_status_v1_t; + +typedef struct wl_heb_status_v1 { + uint16 version; /* structure version */ + uint16 length; /* data length (starting after this field) */ + wl_heb_reg_status_v1_t heb_status[1]; +} wl_heb_status_v1_t; /* TWT Setup descriptor */ typedef struct { @@ -13091,8 +15907,13 @@ typedef struct { uint8 wake_type; /* See WL_TWT_TIME_TYPE_XXXX below */ uint32 wake_time_h; /* target wake time - BSS TSF (us) */ uint32 wake_time_l; - uint32 wake_dur; /* target wake duration in us units */ + uint32 wake_dur; /* target wake duration in unit of microseconds */ uint32 wake_int; /* target wake interval */ + + uint16 bid; /* must be between 0 and 255. Set 0xFFFF for auto assignment */ + uint16 li; /* Listen interval: Units in number of beacon intervals */ + uint8 channel; /* twt channel */ + uint8 pad[3]; } wl_twt_sdesc_t; /* Flow flags */ @@ -13100,12 +15921,17 @@ typedef struct { #define WL_TWT_FLOW_FLAG_IMPLICIT (1<<1) #define WL_TWT_FLOW_FLAG_UNANNOUNCED (1<<2) #define WL_TWT_FLOW_FLAG_TRIGGER (1<<3) +#define WL_TWT_FLOW_FLAG_WAKE_TBTT_NEGO (1<<4) +#define WL_TWT_FLOW_FLAG_REQUEST (1<<5) /* Flow id */ #define WL_TWT_FLOW_ID_FID 0x07 /* flow id */ #define WL_TWT_FLOW_ID_GID_MASK 0x70 /* group id - broadcast TWT only */ #define WL_TWT_FLOW_ID_GID_SHIFT 4 +#define WL_TWT_INV_BCAST_ID 0xFFFFu +#define WL_TWT_INV_FLOW_ID 0xFFu + /* Wake type */ /* TODO: not yet finalized */ #define WL_TWT_TIME_TYPE_BSS 0 /* The time specified in wake_time_h/l is @@ -13145,6 +15971,7 @@ typedef struct { * (only BORADCAST) is applicable) */ uint8 flow_id; /* must be between 0 and 7 */ + uint16 bid; /* must be between 0 and 255 */ } wl_twt_teardown_t; /* twt information descriptor */ @@ -13214,124 +16041,6 @@ typedef struct wlc_clm_power_limits_req { /* Output. Limits taken from country-default (all-product) data */ #define WLC_CLM_POWER_LIMITS_OUTPUT_FLAG_DEFAULT_COUNTRY_LIMITS 0x00000004 -/* - * WOG (Wake On Googlecast) - */ - -#define MAX_GCAST_APPID_CNT_LIMIT 50 -#define MAX_DNS_LABEL 63 - -typedef struct wog_appid { - uint8 appID[MAX_DNS_LABEL+1]; -} wog_appid_t; - -enum { - WOG_APPID_ADD, - WOG_APPID_DEL, - WOG_APPID_CLEAR, - WOG_APPID_LIST, - WOG_MAX_APPID_CNT -}; - -#define WOG_APPID_IOV_VER 1 -typedef struct wog_appid_iov { - /* version for iovar */ - uint32 ver; - /* add/del/clear/list operation */ - uint32 operation; - /* for adding or deleting multiple items */ - /* for WOG_MAX_APPID_CNT, this value is used for max count for AppID */ - uint32 cnt; - /* Application IDs */ - /* If FW found an AppID from this list, FW will respond to discovery */ - /* without wake up the host */ - wog_appid_t appids[1]; -} wog_appid_iov_t; - -/* dns service record */ -/* service name : _googlecast */ -typedef struct wog_srv_record { - uint32 ttl; - uint16 port; /* tcp 8008 or 8009 */ - uint8 PAD[2]; -} wog_srv_record_t; - -#define GCAST_MAX_MODEL_NAME_LEN 16 -#define GCAST_MAX_FNAME_LEN 64 -#define GCAST_MAX_RS_LEN 60 - -#define GCAST_UUID_LEN 32 -#define GCAST_PUBLICKEY_ID_LEN 64 -#define GCAST_VER_LEN 2 -typedef struct wog_txt_record { - uint32 ttl; - /* id : UUID for the receiver */ - char id[GCAST_UUID_LEN+1]; - - /* Cast protocol version supported. Begins at 2 */ - /* and is incremented by 1 with each version */ - char ver[GCAST_VER_LEN+1]; - - /* 256bit receiver Subject Public Key Identifier from the SSL cert */ - char public_key[GCAST_PUBLICKEY_ID_LEN+1]; - - /* A bitfield of device capabilities. */ - /* bit 0 : video_out (1:has video out, 0:no video) */ - /* bit 1 : video_in */ - /* bit 2 : audio_out */ - /* bit 3 : audio_in */ - /* bit 4 : dev_mode */ - /* (1:dev mode enabled, 0: not enabled) */ - char capability; - - /* Receiver status flag 0:IDLE, 1(BUSY/JOIN) */ - /* IDLE : The receiver is idle */ - /* and doesn't need to be connected now. */ - /* BUSY/JOIN : The receiver is hosting an activity */ - /* and invites the sender to join */ - char receiver_status_flag; - - uint8 PAD0[1]; - - char friendly_name[GCAST_MAX_FNAME_LEN+1]; - uint8 PAD1[3]; - - char model_name[GCAST_MAX_MODEL_NAME_LEN+1]; - uint8 PAD2[3]; - - /* Receiver Status text for Cast Protocol v2 */ - /* Spec says that if the status text exceeds 60 characters in length, */ - /* it is truncated at 60 caracters and */ - /* a UTF-8 ellipsis character is appended to indicate trucation. */ - /* But our dongle won't use UTF-8 ellipsis. It's not a big deal. */ - char receiver_status[GCAST_MAX_RS_LEN+1]; - uint8 PAD3[3]; -} wog_txt_record_t; - -/* ip will be taken from the ip of wog_info_t */ -typedef struct wog_a_record { - uint32 ttl; -} wog_a_record_t; - -/* Google Cast protocl uses mDNS SD for its discovery */ -#define WOG_SD_RESP_VER 1 -typedef struct wog_sd_resp { - /* version for iovar */ - int32 ver; - /* device name of Google Cast receiver */ - char device_name[MAX_DNS_LABEL+1]; - /* IP address of Google Cast receiver */ - uint8 ip[4]; - /* ttl of PTR response */ - uint32 ptr_ttl; - /* DNS TXT record */ - wog_txt_record_t txt; - /* DNS SRV record */ - wog_srv_record_t srv; - /* DNS A record */ - wog_a_record_t a; -} wog_sd_resp_t; - enum wl_mbo_cmd_ids { WL_MBO_CMD_ADD_CHAN_PREF = 1, WL_MBO_CMD_DEL_CHAN_PREF = 2, @@ -13342,6 +16051,13 @@ enum wl_mbo_cmd_ids { WL_MBO_CMD_FORCE_ASSOC = 7, WL_MBO_CMD_BSSTRANS_REJECT = 8, WL_MBO_CMD_SEND_NOTIF = 9, + /* Unused command, This enum no can be use + * for next new command + */ + WL_MBO_CMD_CLEAR_CHAN_PREF = 10, + WL_MBO_CMD_NBR_INFO_CACHE = 11, + WL_MBO_CMD_ANQPO_SUPPORT = 12, + WL_MBO_CMD_DBG_EVENT_CHECK = 13, /* Add before this !! */ WL_MBO_CMD_LAST }; @@ -13354,7 +16070,10 @@ enum wl_mbo_xtlv_id { WL_MBO_XTLV_CELL_DATA_CAP = 0x5, WL_MBO_XTLV_COUNTERS = 0x6, WL_MBO_XTLV_ENABLE = 0x7, - WL_MBO_XTLV_SUB_ELEM_TYPE = 0x8 + WL_MBO_XTLV_SUB_ELEM_TYPE = 0x8, + WL_MBO_XTLV_BTQ_TRIG_START_OFFSET = 0x9, + WL_MBO_XTLV_BTQ_TRIG_RSSI_DELTA = 0xa, + WL_MBO_XTLV_ANQP_CELL_SUPP = 0xb }; typedef struct wl_mbo_counters { @@ -13406,6 +16125,84 @@ typedef struct wl_mbo_counters { uint16 wifi_to_cell; } wl_mbo_counters_t; +#define WL_FILS_IOV_MAJOR_VER 1 +#define WL_FILS_IOV_MINOR_VER 1 +#define WL_FILS_IOV_MAJOR_VER_SHIFT 8 +#define WL_FILS_IOV_VERSION \ + ((WL_FILS_IOV_MAJOR_VER << WL_FILS_IOV_MAJOR_VER_SHIFT)| WL_FILS_IOV_MINOR_VER) + +enum wl_fils_cmd_ids { + WL_FILS_CMD_ADD_IND_IE = 1, + WL_FILS_CMD_ADD_AUTH_DATA = 2, /* Deprecated, kept to prevent ROM invalidation */ + WL_FILS_CMD_ADD_HLP_IE = 3, + WL_FILS_CMD_ADD_CONNECT_PARAMS = 4, + WL_FILS_CMD_GET_CONNECT_PARAMS = 5, + /* Add before this !! */ + WL_FILS_CMD_LAST +}; + +enum wl_fils_xtlv_id { + WL_FILS_XTLV_IND_IE = 0x1, + WL_FILS_XTLV_AUTH_DATA = 0x2, /* Deprecated, kept to prevent ROM invalidation */ + WL_FILS_XTLV_HLP_IE = 0x3, + WL_FILS_XTLV_ERP_USERNAME = 0x4, + WL_FILS_XTLV_ERP_REALM = 0x5, + WL_FILS_XTLV_ERP_RRK = 0x6, + WL_FILS_XTLV_ERP_NEXT_SEQ_NUM = 0x7, + WL_FILS_XTLV_KEK = 0x8, + WL_FILS_XTLV_PMK = 0x9, + WL_FILS_XTLV_TK = 0xa, + WL_FILS_XTLV_PMKID = 0xb +}; + +#define WL_OCE_IOV_MAJOR_VER 1 +#define WL_OCE_IOV_MINOR_VER 1 +#define WL_OCE_IOV_MAJOR_VER_SHIFT 8 +#define WL_OCE_IOV_VERSION \ + ((WL_OCE_IOV_MAJOR_VER << WL_OCE_IOV_MAJOR_VER_SHIFT)| WL_OCE_IOV_MINOR_VER) + +enum wl_oce_cmd_ids { + WL_OCE_CMD_ENABLE = 1, + WL_OCE_CMD_PROBE_DEF_TIME = 2, + WL_OCE_CMD_FD_TX_PERIOD = 3, + WL_OCE_CMD_FD_TX_DURATION = 4, + WL_OCE_CMD_RSSI_TH = 5, + WL_OCE_CMD_RWAN_LINKS = 6, + WL_OCE_CMD_CU_TRIGGER = 7, + /* Add before this !! */ + WL_OCE_CMD_LAST +}; + +enum wl_oce_xtlv_id { + WL_OCE_XTLV_ENABLE = 0x1, + WL_OCE_XTLV_PROBE_DEF_TIME = 0x2, + WL_OCE_XTLV_FD_TX_PERIOD = 0x3, + WL_OCE_XTLV_FD_TX_DURATION = 0x4, + WL_OCE_XTLV_RSSI_TH = 0x5, + WL_OCE_XTLV_RWAN_LINKS = 0x6, + WL_OCE_XTLV_CU_TRIGGER = 0x7 +}; + +#define WL_ESP_IOV_MAJOR_VER 1 +#define WL_ESP_IOV_MINOR_VER 1 +#define WL_ESP_IOV_MAJOR_VER_SHIFT 8 +#define WL_ESP_IOV_VERSION \ + ((WL_ESP_IOV_MAJOR_VER << WL_ESP_IOV_MAJOR_VER_SHIFT)| WL_ESP_IOV_MINOR_VER) + +enum wl_esp_cmd_ids { + WL_ESP_CMD_ENABLE = 1, + WL_ESP_CMD_STATIC = 2, + /* Add before this !! */ + WL_ESP_CMD_LAST +}; + +enum wl_esp_xtlv_id { + WL_ESP_XTLV_ENABLE = 0x1, + WL_ESP_XTLV_STATIC_AC = 0x2, /* access category */ + WL_ESP_XTLV_STATIC_TYPE = 0x3, /* data type */ + WL_ESP_XTLV_STATIC_VAL = 0x4 +}; + /* otpread command */ #define WL_OTPREAD_VER 1 @@ -13534,7 +16331,7 @@ typedef struct wl_desense_restage_gain { } wl_desense_restage_gain_t; #define MAX_UCM_CHAINS 5 -#define MAX_UCM_PROFILES 4 +#define MAX_UCM_PROFILES 10 #define UCM_PROFILE_VERSION_1 1 /* UCM per chain attribute struct */ @@ -13699,6 +16496,16 @@ typedef struct wl_adps_dump_summary_v1 { adps_stat_elem_t stat[ADPS_SUMMARY_STEP_NUM]; /* statistics */ } wl_adps_dump_summary_v1_t; +typedef struct wl_adps_dump_summary_v2 { + uint16 version; + uint16 length; + uint8 mode; /* operation mode: On/Off */ + uint8 current_step; /* current step */ + uint8 padding[2]; + uint32 flags; /* restrict flags */ + adps_stat_elem_t stat[ADPS_SUMMARY_STEP_NUM]; /* statistics */ +} wl_adps_dump_summary_v2_t; + typedef struct wlc_btc_2gchain_dis { uint16 ver; uint16 len; @@ -13710,6 +16517,29 @@ typedef struct wlc_btc_2gchain_dis { #define WLC_BTC_2GCHAIN_DIS_VER1 0x1 #define WLC_BTC_2GCHAIN_DIS_VER1_LEN 6 +/* --- BTCX WiFi Protection (btc_wifi_prot iovar) --- */ + +/* Current iovar structure version: 1 */ +#define WL_BTC_WIFI_PROT_VER_1 1 + +typedef struct wl_btc_wifi_prot_v1 { + uint16 ver; /* version */ + uint16 len; /* total length */ + uint8 data[]; /* bcm_xtlv_t payload */ +} wl_btc_wifi_prot_v1_t; + +/* Xtlv tags (protection type) and data */ +#define WL_BTC_WIFI_PROT_M1_M4 1 +typedef struct wl_btc_wifi_prot_m1_m4 { + uint32 enable; /* enable/disable m1-m4 protection */ + uint32 timeout; /* maximum timeout in ms (0: default) */ +} wl_btc_wifi_prot_m1_m4_t; + +#define WL_BTC_WIFI_PROT_ENABLE 1 +#define WL_BTC_WIFI_PROT__DISABLE 0 + +/* --- End BTCX WiFi Protection --- */ + enum wl_rpsnoa_cmd_ids { WL_RPSNOA_CMD_ENABLE = 1, WL_RPSNOA_CMD_STATUS, @@ -13729,6 +16559,14 @@ typedef struct rpsnoa_data { int16 value; } rpsnoa_data_t; +typedef struct rpsnoa_stats { + int16 band; + int16 state; + uint32 sleep_dur; + uint32 sleep_avail_dur; + uint32 last_pps; +} rpsnoa_stats_t; + typedef struct rpsnoa_param { uint16 band; uint8 level; @@ -13742,6 +16580,11 @@ typedef struct rpsnoa_iovar { rpsnoa_data_t data[1]; } rpsnoa_iovar_t; +typedef struct rpsnoa_iovar_status { + rpsnoa_cmnhdr_t hdr; + rpsnoa_stats_t stats[1]; +} rpsnoa_iovar_status_t; + typedef struct rpsnoa_iovar_params { rpsnoa_cmnhdr_t hdr; rpsnoa_param_t param[1]; @@ -13757,7 +16600,15 @@ enum wl_ifstats_xtlv_id { WL_IFSTATS_XTLV_BUS_PCIE = 5, /* Report data across all SCBs using ecounters */ + /* STA_info ecounters */ WL_IFSTATS_XTLV_WL_STA_INFO_ECOUNTERS = 0x100, + /* For AMPDU stat sub-types requested in a different format */ + /* these could be sum and report stats across slices. OR + * report sub-types in pairs so host can sum and add. + * Information sent here is across slices, therefore global + */ + WL_IFSTATS_XTLV_TX_AMPDU_STATS = 0x101, + WL_IFSTATS_XTLV_RX_AMPDU_STATS = 0x102, /* Per-slice information * Per-interface reporting could also include slice specific data @@ -13765,14 +16616,26 @@ enum wl_ifstats_xtlv_id { /* xtlv container for reporting */ WL_IFSTATS_XTLV_WL_SLICE = 0x301, /* Per-slice AMPDU stats */ - WL_IFSTATS_XTLV_WL_SLICE_AMPDU_DUMP = 0x302, + WL_IFSTATS_XTLV_WL_SLICE_TX_AMPDU_DUMP = 0x302, + WL_IFSTATS_XTLV_WL_SLICE_RX_AMPDU_DUMP = 0x303, /* Per-slice BTCOEX stats */ - WL_IFSTATS_XTLV_WL_SLICE_BTCOEX = 0x303, + WL_IFSTATS_XTLV_WL_SLICE_BTCOEX = 0x304, /* V11_WLCNTRS used in ecounters */ - WL_IFSTATS_XTLV_WL_SLICE_V11_WLCNTRS = 0x304, + WL_IFSTATS_XTLV_WL_SLICE_V11_WLCNTRS = 0x305, /* V30_WLCNTRS Used in ecounters */ - WL_IFSTATS_XTLV_WL_SLICE_V30_WLCNTRS = 0x305, - + WL_IFSTATS_XTLV_WL_SLICE_V30_WLCNTRS = 0x306, + /* phy,ucode,scan pwrstats */ + WL_IFSTATS_XTLV_WL_SLICE_PWRSTATS_PHY = 0x307, + WL_IFSTATS_XTLV_WL_SLICE_PWRSTATS_SCAN = 0x308, + WL_IFSTATS_XTLV_WL_SLICE_PWRSTATS_WAKE_V2 = 0x309, + /* Per-slice LTECOEX stats */ + WL_IFSTATS_XTLV_WL_SLICE_LTECOEX = 0x30A, + /* TVPM ecounters */ + WL_IFSTATS_XTLV_WL_SLICE_TVPM = 0x30B, + /* TDMTX ecounters */ + WL_IFSTATS_XTLV_WL_SLICE_TDMTX = 0x30C, + /* Slice specific state capture in periodic fasion */ + WL_SLICESTATS_XTLV_PERIODIC_STATE = 0x30D, /* Per-interface */ /* XTLV container for reporting */ WL_IFSTATS_XTLV_IF = 0x501, @@ -13784,15 +16647,38 @@ enum wl_ifstats_xtlv_id { WL_IFSTATS_XTLV_MGT_CNT = 0x504, /* AMPDU stats on per-IF */ WL_IFSTATS_XTLV_AMPDU_DUMP = 0x505, - WL_IFSTATS_XTLV_IF_SPECIFIC = 0x506 + WL_IFSTATS_XTLV_IF_SPECIFIC = 0x506, + WL_IFSTATS_XTLV_WL_PWRSTATS_AWDL = 0x507, + WL_IFSTATS_XTLV_IF_LQM = 0x508, + /* Interface specific state capture in periodic fashion */ + WL_IFSTATS_XTLV_IF_PERIODIC_STATE = 0x509, + /* Event statistics on per-IF */ + WL_IFSTATS_XTLV_IF_EVENT_STATS = 0x50A }; +/* current version of wl_stats_report_t structure for request */ +#define WL_STATS_REPORT_REQUEST_VERSION_V2 2 + +/* current version of wl_stats_report_t structure for response */ +#define WL_STATS_REPORT_RESPONSE_VERSION_V2 2 + +/** Top structure of if_counters IOVar buffer */ +typedef struct wl_stats_report { + uint16 version; /**< see version definitions above */ + uint16 length; /**< length of data including all paddings. */ + uint8 data []; /**< variable length payload: + * 1 or more bcm_xtlv_t type of tuples. + * each tuple is padded to multiple of 4 bytes. + * 'length' field of this structure includes all paddings. + */ +} wl_stats_report_t; + /* interface specific mgt count */ #define WL_MGT_STATS_VERSION_V1 1 /* Associated stats type: WL_IFSTATS_MGT_CNT */ typedef struct { uint16 version; - uint8 pad[2]; + uint16 length; /* detailed control/management frames */ uint32 txnull; @@ -13827,17 +16713,467 @@ typedef struct { /* Associated stats type: WL_IFSTATS_INFRA_SPECIFIC */ typedef struct wl_infra_stats { uint16 version; /**< version of the structure */ - uint8 pad[2]; + uint16 length; uint32 rxbeaconmbss; uint32 tbtt; } wl_if_infra_stats_t; +#define LTECOEX_STATS_VER 1 + +typedef struct wlc_ltecoex_stats { + uint16 version; /**< WL_IFSTATS_XTLV_WL_SLICE_LTECOEX */ + uint16 len; /* Length of wl_ltecx_stats structure */ + uint8 slice_index; /* Slice unit of wl_ltecx_stats structure */ + uint8 pad[3]; /* Padding */ + /* LTE noise based eCounters Bins + cumulative the wl_cnt_wlc_t and wl_ctl_mgt_cnt_t + counter information based on LTE Coex interference level + */ + uint32 txframe_no_LTE; /* txframe counter in no LTE Coex case */ + uint32 rxframe_no_LTE; /* rxframe counter in no LTE Coex case */ + uint32 rxrtry_no_LTE; /* rxrtry counter in no LTE Coex case */ + uint32 txretrans_no_LTE; /* txretrans counter in no LTE Coex case */ + uint32 txnocts_no_LTE; /* txnocts counter in no LTE Coex case */ + uint32 txrts_no_LTE; /* txrts counter in no LTE Coex case */ + uint32 txdeauth_no_LTE; /* txdeauth counter in no LTE Coex case */ + uint32 txassocreq_no_LTE; /* txassocreq counter in no LTE Coex case */ + uint32 txassocrsp_no_LTE; /* txassocrsp counter in no LTE Coex case */ + uint32 txreassocreq_no_LTE; /* txreassocreq counter in no LTE Coex case */ + uint32 txreassocrsp_no_LTE; /* txreassocrsp counter in no LTE Coex case */ + uint32 txframe_light_LTE; /* txframe counter in light LTE Coex case */ + uint32 txretrans_light_LTE; /* txretrans counter in light LTE Coex case */ + uint32 rxframe_light_LTE; /* rxframe counter in light LTE Coex case */ + uint32 rxrtry_light_LTE; /* rxrtry counter in light LTE Coex case */ + uint32 txnocts_light_LTE; /* txnocts counter in light LTE Coex case */ + uint32 txrts_light_LTE; /* txrts counter in light LTE Coex case */ + uint32 txdeauth_light_LTE; /* txdeauth counter in light LTE Coex case */ + uint32 txassocreq_light_LTE; /* txassocreq counter in light LTE Coex case */ + uint32 txassocrsp_light_LTE; /* txassocrsp counter in light LTE Coex case */ + uint32 txreassocreq_light_LTE; /* txreassocreq counter in light LTE Coex case */ + uint32 txreassocrsp_light_LTE; /* txreassocrsp counter in light LTE Coex case */ + uint32 txframe_heavy_LTE; /* txframe counter in heavy LTE Coex case */ + uint32 txretrans_heavy_LTE; /* txretrans counter in heavy LTE Coex case */ + uint32 rxframe_heavy_LTE; /* rxframe counter in heavy LTE Coex case */ + uint32 rxrtry_heavy_LTE; /* rxrtry counter in heavy LTE Coex case */ + uint32 txnocts_heavy_LTE; /* txnocts counter in heavy LTE Coex case */ + uint32 txrts_heavy_LTE; /* txrts counter in heavy LTE Coex case */ + uint32 txdeauth_heavy_LTE; /* txdeauth counter in heavy LTE Coex case */ + uint32 txassocreq_heavy_LTE; /* txassocreq counter in heavy LTE Coex case */ + uint32 txassocrsp_heavy_LTE; /* txassocrsp counter in heavy LTE Coex case */ + uint32 txreassocreq_heavy_LTE; /* txreassocreq counter in heavy LTE Coex case */ + uint32 txreassocrsp_heavy_LTE; /* txreassocrsp counter in heavy LTE Coex case */ + + /* LTE specific ecounters */ + uint16 type4_txinhi_dur; /* Duration of tx inhibit(in ms) due to Type4 */ + uint16 type4_nonzero_cnt; /* Counts of none zero Type4 msg */ + uint16 type4_timeout_cnt; /* Counts of Type4 timeout */ + uint16 rx_pri_dur; /* Duration of wlan_rx_pri assertions */ + uint16 rx_pri_cnt; /* Count of wlan_rx_pri assertions */ + uint16 type6_dur; /* duration of LTE Tx power limiting assertions */ + uint16 type6_cnt; /* Count of LTE Tx power limiting assertions */ + uint16 ts_prot_frm_cnt; /* count of WLAN protection frames triggered by LTE coex */ + uint16 ts_gr_cnt; /* count of intervals granted to WLAN in timesharing */ + uint16 ts_gr_dur; /* duration granted to WLAN in timesharing */ +} wlc_ltecoex_stats_t; + +#define CSA_EVT_CSA_RXED (1 << 0) +#define CSA_EVT_CSA_TIMEOUT (1 << 1) +#define CSA_EVT_FROM_INFRA (1 << 2) typedef struct csa_event_data { chanspec_t chan_old; dot11_ext_csa_ie_t ecsa; dot11_mesh_csp_ie_t mcsp; dot11_wide_bw_chan_switch_ie_t wbcs; - uint8 PAD; + uint8 flags; + uint8 pad[3]; } csa_event_data_t; +/* ifdef (WL_ASSOC_BCN_RPT) */ +enum wl_bcn_report_cmd_id { + WL_BCN_RPT_CMD_VER = 0, + WL_BCN_RPT_CMD_CONFIG = 1, + WL_BCN_RPT_CMD_VENDOR_IE = 2, + WL_BCN_RPT_CMD_LAST +}; + +/* beacon report specific macros */ +#define WL_BCN_RPT_CCX_IE_OVERRIDE (1u << 0) + +/* beacon report specific macros */ +#define WL_BCN_RPT_ASSOC_SCAN_UNSOLICITED_MODE (1u << 1) +#define WL_BCN_RPT_ASSOC_SCAN_SOLICITED_MODE (1u << 2) +#define WL_BCN_RPT_ASSOC_SCAN_MODE_SHIFT (1) +#define WL_BCN_RPT_ASSOC_SCAN_MODE_MASK (WL_BCN_RPT_ASSOC_SCAN_UNSOLICITED_MODE |\ + WL_BCN_RPT_ASSOC_SCAN_SOLICITED_MODE) +#define WL_BCN_RPT_ASSOC_SCAN_MODE_MAX (WL_BCN_RPT_ASSOC_SCAN_MODE_MASK >> \ + WL_BCN_RPT_ASSOC_SCAN_MODE_SHIFT) +/* beacon report mode specific macro */ +#define WL_BCN_RPT_ASSOC_SCAN_MODE_DEFAULT WL_BCN_RPT_ASSOC_SCAN_UNSOLICITED_MODE + +/* beacon report timeout config specific macros */ +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_TIMEOUT_DEFAULT (120000) +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_TIMEOUT_MIN (60000) +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_TIMEOUT_MAX (0xFFFFFFFF) + +/* beacon report cache count specific macros */ +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_COUNT_MIN (0) +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_COUNT_MAX (8) +#define WL_BCN_RPT_ASSOC_SCAN_CACHE_COUNT_DEFAULT (WL_BCN_RPT_ASSOC_SCAN_CACHE_COUNT_MAX) + +#define WL_BCN_REPORT_CMD_VERSION 1 +struct wl_bcn_report_cfg { + uint32 flags; /**< Flags that defines the operation/setting information */ + uint32 scan_cache_timeout; /**< scan cache timeout value in millisec */ + uint32 scan_cache_timer_pend; /**< Read only pending time for timer expiry in millisec */ + uint8 scan_cache_cnt; /**< scan cache count */ +}; + +/* endif (WL_ASSOC_BCN_RPT) */ + +/* Thermal, Voltage, and Power Mitigation */ +#define TVPM_REQ_VERSION_1 1 +#define TVPM_REQ_CURRENT_VERSION TVPM_REQ_VERSION_1 + +/* tvpm iovar data */ +typedef struct { + uint16 version; /* TVPM request version */ + uint16 length; /* Length of the entire structure */ + + uint16 req_type; /* Request type: wl_tvpm_req_type_t */ + uint16 req_len; /* Length of the following value */ + uint8 value[]; /* Variable length data depending on req_type */ +} wl_tvpm_req_t; + +/* tvpm iovar request types */ +typedef enum { + WL_TVPM_REQ_CLTM_INDEX, /* req_value: uint32, range 1...100 */ + WL_TVPM_REQ_PPM_INDEX, /* req_value: uint32, range 1...100 */ + WL_TVPM_REQ_ENABLE, /* req_value: uint32, range 0...1 */ + WL_TVPM_REQ_STATUS, /* req_value: none */ + WL_TVPM_REQ_PERIOD, /* req_value: int32, range {-1,1-10} */ + WL_TVPM_REQ_MAX +} wl_tvpm_req_type_t; + +/* structure for data returned by request type WL_TVPM_REQ_STATUS */ +typedef struct wl_tvpm_status { + uint16 enable; /* whether TVPM is enabled */ + uint16 tx_dutycycle; /* a percentage: 1-100 */ + int16 tx_power_backoff; /* 0...-6 */ + uint16 num_active_chains; /* 1...3 */ + int16 temp; /* local temperature in degrees C */ + uint8 vbat; /* local voltage in units of 0.1V */ + uint8 pad; +} wl_tvpm_status_t; + +/* TVPM ecounters */ +typedef struct wl_tvpm_ecounters_t { + uint16 version; /* version field */ + uint16 length; /* byte length in wl_tvpm_ecounters_t starting at version */ + uint16 tx_dutycycle; /* a percentage: 1-100 */ + int16 tx_power_backoff; /* 0...-6 */ + uint16 num_active_chains; /* 1...3 */ + int16 temp; /* local temperature */ + uint8 vbat; /* local voltage */ + uint8 cltm; /* CLTM index */ + uint8 ppm; /* PPM index */ + uint8 pad; /* pad to align to uint16 */ +} wl_tvpm_ecounters_t; + +#define TDMTX_ECOUNTERS_VERSION_V1 1 +#define TDMTX_ECOUNTERS_VERSION_V2 2 + +/* TDMTX ecounters */ +typedef struct wl_tdmtx_ecounters_v1 { + uint16 version; /* version field */ + uint16 length; /* byte length in wl_tdmtx_ecounters_t starting at version */ + uint32 txa_on; /* TXA on requests */ + uint32 txa_tmcnt; /* Total number of TXA timeout */ + uint32 por_on; /* TXA POR requests */ + uint32 txpuen; /* Path enable requests */ + uint32 txpudis; /* Total number of times Tx path is muted on the slice */ + uint32 txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint32 txdefer; /* Total number of times Tx was deferred by the slice */ + uint32 txmute; /* Total number of times active Tx muted on the slice */ + uint32 actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint32 txa_dur; /* Total time txa on */ + uint32 txpri_dur; /* Total time TXPri */ + uint32 txdefer_dur; /* Total time txdefer */ +} wl_tdmtx_ecounters_v1_t; + +/* TDMTX ecounters for version 2 */ +typedef struct wl_tdmtx_ecounters_v2 { + uint16 version; /* version field */ + uint16 length; /* byte length in wl_tdmtx_ecounters_t starting at version */ + uint32 txa_on; /* TXA on requests */ + uint32 txa_tmcnt; /* Total number of TXA timeout */ + uint32 porhi_on; /* TXA PORHI requests */ + uint32 porlo_on; /* TXA PORLO requests */ + uint32 txpuen; /* Path enable requests */ + uint32 txpudis; /* Total number of times Tx path is muted on the slice */ + uint32 txpri_on; /* Total number of times Tx priority was obtained by the slice */ + uint32 txdefer; /* Total number of times Tx was deferred by the slice */ + uint32 txmute; /* Total number of times active Tx muted on the slice */ + uint32 actpwrboff; /* Total number of times TX power is backed off by the slice */ + uint32 txa_dur; /* Total time txa on */ + uint32 txpri_dur; /* Total time TXPri */ + uint32 txdefer_dur; /* Total time txdefer */ +} wl_tdmtx_ecounters_v2_t; + +/* + * BT log definitions + */ + +/* common iovar struct */ +typedef struct wl_btl { + uint16 subcmd_id; /* subcommand id */ + uint16 len; /* total length of data[] */ + uint8 data[2]; /* subcommand data, variable length */ +} wl_btl_t; + +/* subcommand ids */ +#define WL_BTL_SUBCMD_ENABLE 0 /* enable/disable logging */ +#define WL_BTL_SUBCMD_STATS 1 /* statistics */ + +/* WL_BTL_SUBCMD_ENABLE data */ +typedef struct wl_blt_enable { + uint8 enable; /* 1 - enable, 0 - disable */ + uint8 pad[3]; /* 4-byte struct alignment */ +} wl_btl_enable_t; + +/* WL_BTL_SUBCMD_STATS data */ +typedef struct wl_blt_stats { + uint32 bt_interrupt; /* num BT interrupts */ + uint32 config_req; /* num CONFIG_REQ */ + uint32 config_res_success; /* num CONFIG_RES successful */ + uint32 config_res_fail; /* num CONFIG_RES failed */ + uint32 log_req; /* num LOG_REQ */ + uint32 log_res_success; /* num LOG_RES successful */ + uint32 log_res_fail; /* num LOG_RES failed */ + uint32 indirect_read_fail; /* num indirect read fail */ + uint32 indirect_write_fail; /* num indirect write fail */ + uint32 dma_fail; /* num DMA failed */ + uint32 min_log_req_duration; /* min log request duration in usec */ + uint32 max_log_req_duration; /* max log request duration in usec */ + uint16 mem_dump_req; /* num mem dump requests */ + uint16 mem_dump_success; /* num mem dumps successful */ + uint16 mem_dump_fail; /* num mem dumps failed */ + uint16 bt_wake_success; /* num BT wakes successful */ + uint16 bt_wake_fail; /* num BT wakes failed */ + uint16 mem_dump_req_interrupt; /* num MEM_DUMP_REQ interrupt */ + uint16 mem_dump_res_interrupt; /* num MEM_DUMP_RES interrupt */ + uint16 mem_dump_res_timeout; /* num MEM_DUMP_RES timeout */ + uint16 mem_dump_proc_no_bt_ready; /* num proceed if no BT ready */ + uint16 mem_dump_proc_no_bt_response; /* num proceed if no BT response */ + uint16 mem_dump_proc_no_bt_clock; /* num proceed if no BT clock */ + uint16 pad; /* alignment */ + uint32 last_failed_region; /* start addr of last failed region */ + uint32 min_mem_dump_duration; /* min mem dump duration in usec */ + uint32 max_mem_dump_duration; /* max mem dump duration in usec */ +} wl_btl_stats_t; + +/* IOV AWD DATA */ + +/* AWD DATA structures */ +typedef struct { + uint8 version; /* Extended trap version info */ + uint8 reserved; /* currently unused */ + uint16 length; /* Length of data excluding this header */ + uint8 data[]; /* this data is TLV of tags */ +} awd_data_v1_t; + +/* AWD TAG structure */ +typedef struct { + uint8 tagid; /* one of AWD DATA TAGs numbers */ + uint8 length; /* the data size represented by this field must be aligned to 32 bits */ + uint8 data[]; /* variable size, defined by length field */ +} awd_tag_data_v1_t; + +/* IOV ETD DATA */ + +/* ETD DATA structures */ +typedef struct { + uint8 version; /* Extended trap version info */ + uint8 reserved; /* currently unused */ + uint16 length; /* Length of data excluding this header */ + uint8 data[]; /* this data is TLV of tags */ +} etd_data_v1_t; + +/* ETD TAG structure */ +typedef struct { + uint8 tagid; /* one of ETD DATA TAGs numbers */ + uint8 length; /* the data size represented by this field must be aligned to 32 bits */ + uint8 data[]; /* variable size, defined by length field */ +} etd_tag_data_v1_t; + +/* ETD information structures associated with ETD_DATA_Tags */ +/* ETD_JOIN_CLASSIFICATION_INFO 10 */ +typedef struct { + uint8 assoc_type; /* assoc type */ + uint8 assoc_state; /* current state of assoc state machine */ + uint8 wpa_state; /* wpa->state */ + uint8 wsec_portopen; /* shows if security port is open */ + uint8 total_attempts_num; /* total number of join attempts (bss_retries) */ + uint8 num_of_targets; /* up to 3, in current design */ + uint8 reserved [2]; /* padding to get 32 bits alignment */ + uint32 wsec; /* bsscfg->wsec */ + uint32 wpa_auth; /* bsscfg->WPA_auth */ + uint32 time_to_join; /* time duration to process WLC_SET_SSID request (ms) */ +} join_classification_info_v1_t; + +/* ETD_JOIN_TARGET_CLASSIFICATION_INFO 11 */ +typedef struct { + int8 rssi; /* RSSI on current channel */ + uint8 cca; /* CCA on current channel */ + uint8 channel; /* current channel */ + uint8 num_of_attempts; /* (bss_retries) up to 5 */ + uint8 oui[3]; /* the first three octets of the AP's address */ + uint8 reserved; /* padding to get 32 bits alignment */ + uint32 time_duration; /* time duration of current attempt (ms) */ +} join_target_classification_info_v1_t; + +/* ETD_ASSOC_STATE 12 */ +typedef struct { + uint8 assoc_state; /* assoc type */ + uint8 reserved [3]; /* padding to get 32 bits alignment */ +} join_assoc_state_v1_t; + +/* ETD_CHANNEL 13 tag */ +typedef struct { + uint8 channel; /* last attempt channel */ + uint8 reserved [3]; /* padding to get 32 bits alignment */ +} join_channel_v1_t; + +/* ETD_TOTAL_NUM_OF_JOIN_ATTEMPTS 14 */ +typedef struct { + uint8 total_attempts_num; /* total number of join attempts (bss_retries) */ + uint8 reserved [3]; /* padding to get 32 bits alignment */ +} join_total_attempts_num_v1_t; + +/* IOV_ROAM_CACHE structures */ + +enum wl_rmc_report_cmd_id { + WL_RMC_RPT_CMD_VER = 0, + WL_RMC_RPT_CMD_DATA = 1, + WL_RMC_RPT_CMD_LAST +}; + +enum wl_rmc_report_xtlv_id { + WL_RMC_RPT_XTLV_VER = 0x0, + WL_RMC_RPT_XTLV_BSS_INFO = 0x1, + WL_RMC_RPT_XTLV_CANDIDATE_INFO = 0x2 +}; + +/* WL_RMC_RPT_XTLV_BSS_INFO */ +typedef struct { + int16 rssi; /* current BSS RSSI */ + uint8 reason; /* reason code for last full scan */ + uint8 status; /* last status code for not roaming */ + uint32 fullscan_count; /* number of full scans performed on current BSS */ + uint32 time_full_scan; /* delta time (in ms) between cur time and full scan timestamp */ +} rmc_bss_info_v1_t; + +/* WL_RMC_RPT_XTLV_CANDIDATE_INFO */ +typedef struct { + int16 rssi; /* last seen rssi */ + uint16 ctl_channel; /* channel */ + uint32 time_last_seen; /* delta time (in ms) between cur time and last seen timestamp */ + uint16 bss_load; /* BSS load */ + uint8 bssid [6]; /* padding to get 32 bits alignment */ +} rmc_candidate_info_v1_t; + +#define WL_FILTER_IE_VERSION 1 +enum wl_filter_ie_options { + WL_FILTER_IE_CLEAR = 0, /* allow element id in packet.For suboption */ + WL_FILTER_IE_SET = 1, /* filter element id in packet.For suboption */ + WL_FILTER_IE_LIST = 2, /* list element ID's.Set as option */ + WL_FILTER_IE_CLEAR_ALL = 3, /* clear all the element.Set as option */ + WL_FILTER_IE_CHECK_SUB_OPTION = 4 /* check for suboptions.Set only as option */ +}; + +typedef struct wl_filter_ie_tlv { + uint16 id; + uint16 len; /* sub option length + pattern length */ + uint8 data[]; /* sub option + pattern matching(OUI,type,sub-type) */ +} wl_filter_ie_tlv_t; + +typedef struct wl_filter_ie_iov { + uint16 version; /* Structure version */ + uint16 len; /* Total length of the structure */ + uint16 fixed_length; /* Total length of fixed fields */ + uint8 option; /* Filter action - check for suboption */ + uint8 pad[1]; /* Align to 4 bytes */ + uint32 pktflag; /* frame type */ + uint8 tlvs[]; /* variable data (zero in for list ,clearall) */ +} wl_filter_ie_iov_v1_t; + +/* Event aggregation config */ +#define EVENT_AGGR_CFG_VERSION 1 +#define EVENT_AGGR_DISABLED 0x0 +#define EVENT_AGGR_ENABLED 0x1 + +#define EVENT_AGGR_BUFSIZE_MAX 1512 +#define EVENT_AGGR_BUFSIZE_MIN 512 + +#define EVENT_AGGR_FLUSH_TIMEOUT_DEFAULT 100 +#define EVENT_AGGR_FLUSH_TIMEOUT_MAX 2000 +#define EVENT_AGGR_NUM_EVENTS_FLUSH 5 +typedef struct event_aggr_config { + uint16 version; + uint16 len; + uint16 flags; /* bit 0 to enable/disable the feature */ + uint16 bufsize; /* Aggregate buffer size */ + uint16 flush_timeout; /* Timeout for event flush */ + uint16 num_events_flush; /* Number of events aggregated before flush */ +} event_aggr_config_t; + +#ifndef WL_TDMTX_TYPEDEF_HAS_ALIAS +typedef tdmtx_cnt_v1_t tdmtx_cnt_t; +typedef tdmtx_cnt_shm_v1_t tdmtx_cnt_shm_t; +typedef wl_tdmtx_ecounters_v1_t wl_tdmtx_ecounters_t; +#define WL_CNT_TDMTX_STRUCT_SZ (sizeof(tdmtx_cnt_t)) +#define WL_CNT_TDMTX_SHM_SZ (sizeof(tdmtx_cnt_shm_t)) +#endif // endif + +/** chanctxt related statistics */ +#define CHANCTXT_STATS_VERSION_1 1 +#define CHANCTXT_STATS_CURRENT_VERSION CHANCTXT_STATS_VERSION_1 +typedef struct wlc_chanctxt_stats { + uint32 excursionq_end_miss; + uint32 activeq_end_miss; + uint32 no_chanctxt_count; + uint32 txqueue_end_incomplete; + uint32 txqueue_start_incomplete; +} wlc_chanctxt_stats_core_t; + +typedef struct chanctxt_stats { + uint16 version; + uint16 length; + wlc_chanctxt_stats_core_t corestats[MAX_NUM_D11CORES]; +} wlc_chanctxt_stats_t; + +typedef struct wl_txdc_ioc { + uint8 ver; + uint8 id; /* ID of the sub-command */ + uint16 len; /* total length of all data[] */ + uint8 data[]; /* var len payload */ +} wl_txdc_ioc_t; + +/* + * iovar subcommand ids + */ +enum { + IOV_TXDC_ENB = 1, + IOV_TXDC_MODE = 2, + IOV_TXDC_DUMP = 3, + IOV_TXDC_LAST +}; + +/* WL_NAN_XTLV_SLOT_STATS */ +/* WL_NAN_EVENT_SLOT_START, WL_NAN_EVENT_SLOT_END */ +typedef struct nan_slot_event_data { + uint32 cur_slot_idx; /* current idx in channel schedule */ + uint32 fw_time; /* target current time in microseconds */ + uint32 band; /* current band (2G/5G) for which the event is received */ +} nan_slot_event_data_t; + #endif /* _wlioctl_h_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/wlioctl_defs.h b/drivers/net/wireless/bcmdhd_oo/include/wlioctl_defs.h index c7d9e0d5276735b21adeb21287d2f8a3f9affa98..169d8826ff6df260e62ca4139337b65d30272b48 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/wlioctl_defs.h +++ b/drivers/net/wireless/bcmdhd_oo/include/wlioctl_defs.h @@ -4,14 +4,14 @@ * * Definitions subject to change without notice. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,7 +19,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. @@ -27,16 +27,12 @@ * * <> * - * $Id: wlioctl_defs.h 677667 2017-01-04 07:43:05Z $ + * $Id: wlioctl_defs.h 738254 2017-12-27 22:33:17Z $ */ - #ifndef wlioctl_defs_h #define wlioctl_defs_h - - - /* All builds use the new 11ac ratespec/chanspec */ #undef D11AC_IOTYPES #define D11AC_IOTYPES @@ -208,9 +204,23 @@ #define WL_BSSTYPE_INFRA 1 #define WL_BSSTYPE_ANY 2 /* deprecated */ #define WL_BSSTYPE_MESH 3 + +/* Bit definitions of mws_active_scan_throttle iovar */ + +#define WL_SCAN_THROTTLE_MASK 0xF + +#define WL_SCAN_THROTTLE_ASSOCSCAN (1U << 0) +#define WL_SCAN_THROTTLE_ROAMSCAN (1U << 1) +#define WL_SCAN_THROTTLE_OTHER_FW_SCAN (1U << 2) /* for other scans like pno etc */ +#define WL_SCAN_THROTTLE_HOSTSCAN (1U << 3) + +#define WL_SCANFLAGS_CLIENT_MASK 0xF00 +#define WL_SCANFLAGS_CLIENT_SHIFT 8 + /* Bitmask for scan_type */ +/* Use lower 16 bit for scan flags, the upper 16 bits are for internal use */ #define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ -#define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ +#define WL_SCANFLAGS_LOW_PRIO 0x02 /* Low priority scan */ #define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ #define WL_SCANFLAGS_OFFCHAN 0x08 /* allow scanning/reporting off-channel APs */ #define WL_SCANFLAGS_HOTSPOT 0x10 /* automatic ANQP to hotspot APs */ @@ -221,6 +231,10 @@ */ #define WL_SCANFLAGS_SISO 0x40 /* Use 1 RX chain for scanning */ #define WL_SCANFLAGS_MIMO 0x80 /* Force MIMO scanning */ +#define WL_SCANFLAGS_ASSOCSCAN 0x100 /* Assoc scan */ +#define WL_SCANFLAGS_ROAMSCAN 0x200 /* Roam scan */ +#define WL_SCANFLAGS_FWSCAN 0x400 /* Other FW scan */ +#define WL_SCANFLAGS_HOSTSCAN 0x800 /* Host scan */ /* wl_iscan_results status values */ #define WL_SCAN_RESULTS_SUCCESS 0 @@ -346,7 +360,6 @@ /* check this magic number */ #define WLC_IOCTL_MAGIC 0x14e46c77 - /* bss_info_cap_t flags */ #define WL_BSS_FLAGS_FROM_BEACON 0x01 /* bss_info derived from beacon */ #define WL_BSS_FLAGS_FROM_CACHE 0x02 /* bss_info collected from cache */ @@ -372,7 +385,6 @@ #define ioctl_pid used /* pid param */ #define ioctl_status needed /* status param */ - /* Enumerate crypto algorithms */ #define CRYPTO_ALGO_OFF 0 #define CRYPTO_ALGO_WEP1 1 @@ -442,6 +454,7 @@ #define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ /* wireless security bitvec */ +#define WSEC_NONE 0x0 #define WEP_ENABLED 0x0001 #define TKIP_ENABLED 0x0002 #define AES_ENABLED 0x0004 @@ -459,6 +472,12 @@ #define WSEC_TKIP_ENABLED(wsec) ((wsec) & TKIP_ENABLED) #define WSEC_AES_ENABLED(wsec) ((wsec) & AES_ENABLED) +/* Macros to check if algorithm is enabled */ +#define WSEC_INFO_ALGO_ENABLED(_wi, _algo) \ + (_wi).cur_algos & (1 << CRYPTO_ALGO_##_algo) + +#define WSEC_INFO_ALGO_NONE(_wi) (((_wi).cur_algos) == 0) + #ifdef BCMCCX #define WSEC_CKIP_KP_ENABLED(wsec) ((wsec) & CKIP_KP_ENABLED) #define WSEC_CKIP_MIC_ENABLED(wsec) ((wsec) & CKIP_MIC_ENABLED) @@ -486,7 +505,6 @@ #define WSEC_SMS4_ENABLED(wsec) ((wsec) & SMS4_ENABLED) #endif /* BCMWAPI_WAI */ - /* Following macros are not used any more. Just kept here to * avoid build issue in BISON/CARIBOU branch */ @@ -518,6 +536,10 @@ #define WPA2_AUTH_TPK 0x2000 /* TDLS Peer Key */ #define WPA2_AUTH_FT 0x4000 /* Fast Transition. */ #define WPA2_AUTH_PSK_SHA256 0x8000 /* PSK with SHA256 key derivation */ +#define WPA2_AUTH_FILS_SHA256 0x10000 /* FILS with SHA256 key derivation */ +#define WPA2_AUTH_FILS_SHA384 0x20000 /* FILS with SHA384 key derivation */ +#define WPA2_AUTH_IS_FILS(auth) ((auth) & (WPA2_AUTH_FILS_SHA256 | WPA2_AUTH_FILS_SHA384)) + /* WPA2_AUTH_SHA256 not used anymore. Just kept here to avoid build issue in DINGO */ #define WPA2_AUTH_SHA256 0x8000 #define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ @@ -528,16 +550,18 @@ /* SROM12 changes */ #define WLC_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ - -#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ -#define WLC_IOCTL_MEDLEN 1536 /* "med" length ioctl buffer required */ +#define WLC_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ +#define WLC_IOCTL_MEDLEN 1896 /* "med" length ioctl buffer required */ #if defined(LCNCONF) || defined(LCN40CONF) || defined(LCN20CONF) #define WLC_SAMPLECOLLECT_MAXLEN 8192 /* Max Sample Collect buffer */ #else #define WLC_SAMPLECOLLECT_MAXLEN 10240 /* Max Sample Collect buffer for two cores */ -#endif +#endif // endif #define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192 +#define WLC_IOCTL_NANRESP_MAXLEN 4096u /* "max" length nan ioctl resp buffer required */ +#define WLC_IOCTL_NANRESP_MEDLEN 800u /* "med" length nan ioctl resp buffer required */ + /* common ioctl definitions */ #define WLC_GET_MAGIC 0 #define WLC_GET_VERSION 1 @@ -781,7 +805,6 @@ #define WLC_GET_KEY_PRIMARY 235 #define WLC_SET_KEY_PRIMARY 236 - /* #define WLC_DUMP_RADIOREGS 237 */ /* no longer supported */ #define WLC_GET_ACI_ARGS 238 #define WLC_SET_ACI_ARGS 239 @@ -872,7 +895,7 @@ #define WLC_LAST 324 #ifndef EPICTRL_COOKIE #define EPICTRL_COOKIE 0xABADCEDE -#endif +#endif // endif /* vx wlc ioctl's offset */ #define CMN_IOCTL_OFF 0x180 @@ -931,6 +954,9 @@ #define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ #define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ +#define WL_AUTH_FILS_SHARED 5 /* d11 fils shared key authentication */ +#define WL_AUTH_FILS_SHARED_PFS 6 /* d11 fils shared key w/ pfs authentication */ +#define WL_AUTH_FILS_PUBLIC 7 /* d11 fils public key authentication */ /* a large TX Power as an init value to factor out of MIN() calculations, * keep low enough to fit in an int8, units are .25 dBm @@ -1181,7 +1207,7 @@ #define WL_RSSI_ANT_MAX 4 /* max possible rx antennas */ #elif WL_RSSI_ANT_MAX != 4 #error "WL_RSSI_ANT_MAX does not match" -#endif +#endif // endif /* dfs_status iovar-related defines */ @@ -1220,6 +1246,7 @@ #define WL_TX_POWER_F_OPENLOOP 0x40 #define WL_TX_POWER_F_PROP11NRATES 0x80 #define WL_TX_POWER_F_UNIT_QDBM 0x100 +#define WL_TX_POWER_F_TXCAP 0x200 /* Message levels */ #define WL_ERROR_VAL 0x00000001 #define WL_TRACE_VAL 0x00000002 @@ -1295,25 +1322,28 @@ #define WL_FBT_VAL 0x00800000 #define WL_RRM_VAL 0x00800000 /* reuse */ #define WL_MQ_VAL 0x01000000 - /* This level is currently used in Phoenix2 only */ #define WL_SRSCAN_VAL 0x02000000 - #define WL_WNM_VAL 0x04000000 /* re-using WL_WNM_VAL for MBO */ #define WL_MBO_VAL 0x04000000 +/* re-using WL_SRSCAN_VAL */ +#define WL_RANDMAC_VAL 0x02000000 #define WL_PWRSEL_VAL 0x10000000 #define WL_NET_DETECT_VAL 0x20000000 #define WL_OCE_VAL 0x20000000 /* reuse */ #define WL_PCIE_VAL 0x40000000 #define WL_PMDUR_VAL 0x80000000 - - /* use top-bit for WL_TIME_STAMP_VAL because this is a modifier * rather than a message-type of its own */ #define WL_TIMESTAMP_VAL 0x80000000 +/* wl_msg_level2 is full. For new bits take the next one and AND with + * wl_msg_level3 in wl_dbg.h + */ +#define WL_ASSOC_AP_VAL 0x00000001 + /* max # of leds supported by GPIO (gpio pin# == led index#) */ #define WL_LED_NUMGPIO 32 /* gpio 0-31 */ @@ -1444,7 +1474,7 @@ #define WL_NUMCHANSPECS 206 #else #define WL_NUMCHANSPECS 110 -#endif +#endif // endif /* WDS link local endpoint WPA role */ #define WL_WDS_WPA_ROLE_AUTH 0 /* authenticator */ @@ -1504,6 +1534,7 @@ #define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 #define WL_PKTENG_PER_RX_STOP 0x08 #define WL_PKTENG_PER_RU_TX_START 0x09 +#define WL_PKTENG_PER_TRIG_TX_START 0x0a #define WL_PKTENG_PER_MASK 0xff #define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ @@ -1513,7 +1544,7 @@ #define WL_PKTENG_MAXPKTSZ PKTENG_LONGPKTSZ #else #define WL_PKTENG_MAXPKTSZ 16384 -#endif +#endif // endif #define NUM_80211b_RATES 4 #define NUM_80211ag_RATES 8 @@ -1722,6 +1753,10 @@ #define WL_P2P_IF_DYNBCN_GO 2 #define WL_P2P_IF_DEV 3 +/* p2p GO configuration */ +#define WL_P2P_ENABLE_CONF 1 /* configure */ +#define WL_P2P_DISABLE_CONF 0 /* un-configure */ + /* count */ #define WL_P2P_SCHED_RSVD 0 #define WL_P2P_SCHED_REPEAT 255 /* anything > 255 will be treated as 255 */ @@ -2024,11 +2059,11 @@ #ifndef BESTN_MAX #define BESTN_MAX 10 -#endif +#endif // endif #ifndef MSCAN_MAX #define MSCAN_MAX 32 -#endif +#endif // endif /* TCP Checksum Offload error injection for testing */ #define TOE_ERRTEST_TX_CSUM 0x00000001 @@ -2046,7 +2081,11 @@ #define ARP_ERRTEST_REPLY_HOST 0x2 #define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ +#if defined(WL_PKT_FLTR_EXT) && !defined(WL_PKT_FLTR_EXT_DISABLED) +#define ND_MULTIHOMING_MAX 32 /* Maximum local host IP addresses */ +#else #define ND_MULTIHOMING_MAX 10 /* Maximum local host IP addresses */ +#endif /* WL_PKT_FLTR_EXT && !WL_PKT_FLTR_EXT_DISABLED */ #define ND_REQUEST_MAX 5 /* Max set of offload params */ /* AOAC wake event flag */ #define WAKE_EVENT_NLO_DISCOVERY_BIT 1 @@ -2057,7 +2096,6 @@ #define MAX_NUM_WOL_PATTERN 22 /* LOGO requirements min 22 */ - /* Packet filter operation mode */ /* True: 1; False: 0 */ #define PKT_FILTER_MODE_FORWARD_ON_MATCH 1 @@ -2150,26 +2188,24 @@ #define WL_PROXD_MODE_TARGET 3 #define WL_PROXD_RANDOM_WAKEUP 0x8000 - #ifdef NET_DETECT #define NET_DETECT_MAX_WAKE_DATA_SIZE 2048 #define NET_DETECT_MAX_PROFILES 16 #define NET_DETECT_MAX_CHANNELS 50 #endif /* NET_DETECT */ - /* Bit masks for radio disabled status - returned by WL_GET_RADIO */ #define WL_RADIO_SW_DISABLE (1<<0) #define WL_RADIO_HW_DISABLE (1<<1) #define WL_RADIO_MPC_DISABLE (1<<2) #define WL_RADIO_COUNTRY_DISABLE (1<<3) /* some countries don't support any channel */ #define WL_RADIO_PERCORE_DISABLE (1<<4) /* Radio diable per core for DVT */ +#define WL_RADIO_TSYNC_PWRSAVE_DISABLE (1<<5) /* Disable Radio in tsync mode for power saving */ #define WL_SPURAVOID_OFF 0 #define WL_SPURAVOID_ON1 1 #define WL_SPURAVOID_ON2 2 - #define WL_4335_SPURAVOID_ON1 1 #define WL_4335_SPURAVOID_ON2 2 #define WL_4335_SPURAVOID_ON3 3 @@ -2254,5 +2290,17 @@ #define WL_PWRSTATS_TYPE_PM_AWAKE2 7 /**< struct wl_pwr_pm_awake_stats_v2 */ #define WL_PWRSTATS_TYPE_SDIO 8 /* struct wl_pwr_sdio_stats */ #define WL_PWRSTATS_TYPE_MIMO_PS_METRICS 9 /* struct wl_mimo_meas_metrics_t */ +#define WL_PWRSTATS_TYPE_SLICE_INDEX 10 /* slice index for which this report is meant for */ +#define WL_PWRSTATS_TYPE_TSYNC 11 /**< struct wl_pwr_tsync_stats */ +#define WL_PWRSTATS_TYPE_OPS_STATS 12 /* struct wl_pwr_ops_stats_t */ +#define WL_PWRSTATS_TYPE_BCNTRIM_STATS 13 /* struct wl_pwr_bcntrim_stats_t */ + +/* IOV AWD DATA */ +#define AWD_DATA_JOIN_INFO 0 +#define AWD_DATA_VERSION_V1 1 + +/* IOV ETD DATA */ +#define ETD_DATA_JOIN_INFO 0 +#define ETD_DATA_VERSION_V1 1 #endif /* wlioctl_defs_h */ diff --git a/drivers/net/wireless/bcmdhd_oo/include/wlioctl_utils.h b/drivers/net/wireless/bcmdhd_oo/include/wlioctl_utils.h index 797531cface763adb6411b925d2159422c037303..d553af5e758518cda8d0f59692ea8333b4bc9c90 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/wlioctl_utils.h +++ b/drivers/net/wireless/bcmdhd_oo/include/wlioctl_utils.h @@ -1,14 +1,14 @@ /* * Custom OID/ioctl related helper functions. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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,13 +16,13 @@ * 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: wlioctl_utils.h 614820 2016-01-23 17:16:17Z $ + * $Id: wlioctl_utils.h 626207 2016-03-19 17:39:14Z $ */ #ifndef _wlioctl_utils_h_ @@ -47,9 +47,9 @@ extern int wl_cntbuf_to_xtlv_format(void *ctx, void *cntbuf, extern const char * wl_get_reinit_rc_name(int rc); /* Get data pointer of wlc layer counters tuple from xtlv formatted counters IOVar buffer. */ -#define GET_WLCCNT_FROM_CNTBUF(cntbuf) \ - bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)cntbuf)->data, \ - ((wl_cnt_info_t *)cntbuf)->datalen, WL_CNT_XTLV_WLC, \ +#define GET_WLCCNT_FROM_CNTBUF(cntbuf) (const wl_cnt_wlc_t*) \ + bcm_get_data_from_xtlv_buf(((const wl_cnt_info_t *)cntbuf)->data, \ + ((const wl_cnt_info_t *)cntbuf)->datalen, WL_CNT_XTLV_WLC, \ NULL, BCM_XTLV_OPTION_ALIGN32) #define CHK_CNTBUF_DATALEN(cntbuf, ioctl_buflen) do { \ diff --git a/drivers/net/wireless/bcmdhd_oo/include/wpa.h b/drivers/net/wireless/bcmdhd_oo/include/wpa.h index 46cf19c336429ce11fba570200010fce97ca06c4..fe540e1672d80a3d5a55a93f386951b214a45a0a 100644 --- a/drivers/net/wireless/bcmdhd_oo/include/wpa.h +++ b/drivers/net/wireless/bcmdhd_oo/include/wpa.h @@ -1,14 +1,14 @@ /* * Fundamental types and constants relating to WPA * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -33,7 +33,6 @@ #include #include - /* This marks the start of a packed structure section. */ #include diff --git a/drivers/net/wireless/bcmdhd_oo/linux_osl.c b/drivers/net/wireless/bcmdhd_oo/linux_osl.c index 523a8b76dd1df07b3c027d19404f7cd68a578dfb..4cec57728d9a6b497031027e6c83f7eab416c0be 100644 --- a/drivers/net/wireless/bcmdhd_oo/linux_osl.c +++ b/drivers/net/wireless/bcmdhd_oo/linux_osl.c @@ -1,14 +1,14 @@ /* * Linux OS Independent Layer * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: linux_osl.c 680580 2017-01-20 11:49:58Z $ + * $Id: linux_osl.c 737888 2017-12-23 13:20:41Z $ */ #define LINUX_PORT @@ -34,12 +34,9 @@ #include #include - -#if !defined(STBLINUX) #if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING) #include #endif /* __ARM_ARCH_7A__ && !DHD_USE_COHERENT_MEM_FOR_RING */ -#endif /* STBLINUX */ #include @@ -49,7 +46,6 @@ #include #include - #ifdef BCM_SECURE_DMA #include #include @@ -71,154 +67,17 @@ #if defined(STB) #include extern spinlock_t l2x0_reg_lock; -#endif +#endif // endif #ifdef BCM_OBJECT_TRACE #include #endif /* BCM_OBJECT_TRACE */ +#include "linux_osl_priv.h" #define PCI_CFG_RETRY 10 -#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ -#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ #define DUMPBUFSZ 1024 -/* dependancy check */ -#if !defined(BCMPCIE) && defined(DHD_USE_STATIC_CTRLBUF) -#error "DHD_USE_STATIC_CTRLBUF suppored PCIE target only" -#endif /* !BCMPCIE && DHD_USE_STATIC_CTRLBUF */ - -#ifdef CONFIG_DHD_USE_STATIC_BUF -#ifdef DHD_USE_STATIC_CTRLBUF -#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1) -#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2) -#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4) - -#define PREALLOC_FREE_MAGIC 0xFEDC -#define PREALLOC_USED_MAGIC 0xFCDE -#else -#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) -#endif /* DHD_USE_STATIC_CTRLBUF */ - -#define STATIC_BUF_MAX_NUM 16 -#define STATIC_BUF_SIZE (PAGE_SIZE*2) -#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) - -typedef struct bcm_static_buf { - spinlock_t static_lock; - unsigned char *buf_ptr; - unsigned char buf_use[STATIC_BUF_MAX_NUM]; -} bcm_static_buf_t; - -static bcm_static_buf_t *bcm_static_buf = 0; - -#ifdef DHD_USE_STATIC_CTRLBUF -#define STATIC_PKT_4PAGE_NUM 0 -#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE -#elif defined(ENHANCED_STATIC_BUF) -#define STATIC_PKT_4PAGE_NUM 1 -#define DHD_SKB_MAX_BUFSIZE DHD_SKB_4PAGE_BUFSIZE -#else -#define STATIC_PKT_4PAGE_NUM 0 -#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE -#endif /* DHD_USE_STATIC_CTRLBUF */ - -#ifdef DHD_USE_STATIC_CTRLBUF -#define STATIC_PKT_1PAGE_NUM 0 -#define STATIC_PKT_2PAGE_NUM 128 -#else -#define STATIC_PKT_1PAGE_NUM 8 -#define STATIC_PKT_2PAGE_NUM 8 -#endif /* DHD_USE_STATIC_CTRLBUF */ - -#define STATIC_PKT_1_2PAGE_NUM \ - ((STATIC_PKT_1PAGE_NUM) + (STATIC_PKT_2PAGE_NUM)) -#define STATIC_PKT_MAX_NUM \ - ((STATIC_PKT_1_2PAGE_NUM) + (STATIC_PKT_4PAGE_NUM)) - -typedef struct bcm_static_pkt { -#ifdef DHD_USE_STATIC_CTRLBUF - struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM]; - unsigned char pkt_invalid[STATIC_PKT_2PAGE_NUM]; - spinlock_t osl_pkt_lock; - uint32 last_allocated_index; -#else - struct sk_buff *skb_4k[STATIC_PKT_1PAGE_NUM]; - struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM]; -#ifdef ENHANCED_STATIC_BUF - struct sk_buff *skb_16k; -#endif /* ENHANCED_STATIC_BUF */ - struct semaphore osl_pkt_sem; -#endif /* DHD_USE_STATIC_CTRLBUF */ - unsigned char pkt_use[STATIC_PKT_MAX_NUM]; -} bcm_static_pkt_t; - -static bcm_static_pkt_t *bcm_static_skb = 0; - -void* wifi_platform_prealloc(void *adapter, int section, unsigned long size); -#endif /* CONFIG_DHD_USE_STATIC_BUF */ - -typedef struct bcm_mem_link { - struct bcm_mem_link *prev; - struct bcm_mem_link *next; - uint size; - int line; - void *osh; - char file[BCM_MEM_FILENAME_LEN]; -} bcm_mem_link_t; - -struct osl_cmn_info { - atomic_t malloced; - atomic_t pktalloced; /* Number of allocated packet buffers */ - spinlock_t dbgmem_lock; - bcm_mem_link_t *dbgmem_list; - bcm_mem_link_t *dbgvmem_list; - spinlock_t pktalloc_lock; - atomic_t refcount; /* Number of references to this shared structure. */ -}; -typedef struct osl_cmn_info osl_cmn_t; - -struct osl_info { - osl_pubinfo_t pub; - uint32 flags; /* If specific cases to be handled in the OSL */ -#ifdef CTFPOOL - ctfpool_t *ctfpool; -#endif /* CTFPOOL */ - uint magic; - void *pdev; - uint failed; - uint bustype; - osl_cmn_t *cmn; /* Common OSL related data shred between two OSH's */ - - void *bus_handle; -#ifdef BCM_SECURE_DMA -#ifdef NOT_YET - struct sec_mem_elem *sec_list_512; - struct sec_mem_elem *sec_list_base_512; - struct sec_mem_elem *sec_list_2048; - struct sec_mem_elem *sec_list_base_2048; -#endif /* NOT_YET */ - struct sec_mem_elem *sec_list_4096; - struct sec_mem_elem *sec_list_base_4096; - phys_addr_t contig_base; - void *contig_base_va; - phys_addr_t contig_base_alloc; - void *contig_base_alloc_va; - phys_addr_t contig_base_alloc_coherent; - void *contig_base_alloc_coherent_va; - void *contig_base_coherent_va; - void *contig_delta_va_pa; - struct { - phys_addr_t pa; - void *va; - bool avail; - } sec_cma_coherent[SEC_CMA_COHERENT_MAX]; - int stb_ext_params; -#endif /* BCM_SECURE_DMA */ -}; #ifdef BCM_SECURE_DMA static void * osl_sec_dma_ioremap(osl_t *osh, struct page *page, size_t size, bool iscache, bool isdecr); @@ -236,29 +95,6 @@ static void *osl_sec_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bi static void osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa); #endif /* BCM_SECURE_DMA */ -#ifdef BCM_OBJECT_TRACE -/* don't clear the first 4 byte that is the pkt sn */ -#define OSL_PKTTAG_CLEAR(p) \ -do { \ - struct sk_buff *s = (struct sk_buff *)(p); \ - ASSERT(OSL_PKTTAG_SZ == 32); \ - *(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) -#else -#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) -#endif /* BCM_OBJECT_TRACE */ - /* PCMCIA attribute space access macros */ uint32 g_assert_type = 0; /* By Default Kernel Panic */ @@ -278,6 +114,16 @@ module_param(secdma_size2, int, 0); static int secdma_found = 0; #endif /* BCM_SECURE_DMA */ +#ifdef USE_DMA_LOCK +#define DMA_LOCK(osh) spin_lock_bh(&(osh)->dma_lock) +#define DMA_UNLOCK(osh) spin_unlock_bh(&(osh)->dma_lock) +#define DMA_LOCK_INIT(osh) spin_lock_init(&(osh)->dma_lock) +#else +#define DMA_LOCK(osh) do { /* noop */ } while(0) +#define DMA_UNLOCK(osh) do { /* noop */ } while(0) +#define DMA_LOCK_INIT(osh) do { /* noop */ } while(0) +#endif /* USE_DMA_LOCK */ + static int16 linuxbcmerrormap[] = { 0, /* 0 */ -EINVAL, /* BCME_ERROR */ @@ -339,19 +185,52 @@ static int16 linuxbcmerrormap[] = -EINVAL, /* BCME_NOA_PND */ -EINVAL, /* BCME_FRAG_Q_FAILED */ -EINVAL, /* BCME_GET_AF_FAILED */ - -EINVAL, /* BCME_MSCH_NOTREADY */ + -EINVAL, /* BCME_MSCH_NOTREADY */ + -EINVAL, /* BCME_IOV_LAST_CMD */ + -EINVAL, /* BCME_MINIPMU_CAL_FAIL */ + -EINVAL, /* BCME_RCAL_FAIL */ + -EINVAL, /* BCME_LPF_RCCAL_FAIL */ + -EINVAL, /* BCME_DACBUF_RCCAL_FAIL */ + -EINVAL, /* BCME_VCOCAL_FAIL */ + -EINVAL, /* BCME_BANDLOCKED */ /* When an new error code is added to bcmutils.h, add os * specific error translation here as well */ /* check if BCME_LAST changed since the last time this function was updated */ -#if BCME_LAST != -60 +#if BCME_LAST != -67 #error "You need to add a OS error translation in the linuxbcmerrormap \ for new error code defined in bcmutils.h" -#endif +#endif // endif }; uint lmtest = FALSE; +#ifdef DHD_MAP_LOGGING +#define DHD_MAP_LOG_SIZE 2048 + +typedef struct dhd_map_record { + dma_addr_t addr; + uint64 time; +} dhd_map_log_t; + +dhd_map_log_t *dhd_map_log = NULL, *dhd_unmap_log = NULL; +uint32 map_idx = 0, unmap_idx = 0; + +void +osl_dma_map_dump(void) +{ + printk("%s: map_idx=%d unmap_idx=%d current time=%llu\n", + __FUNCTION__, map_idx, unmap_idx, OSL_SYSUPTIME_US()); + if (dhd_map_log && dhd_unmap_log) { + printk("%s: dhd_map_log(pa)=%llx size=%d, dma_unmap_log(pa)=%llx size=%d\n", + __FUNCTION__, (uint64)__virt_to_phys((ulong)dhd_map_log), + (uint32)(sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE), + (uint64)__virt_to_phys((ulong)dhd_unmap_log), + (uint32)(sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE)); + } +} +#endif /* DHD_MAP_LOGGING */ + /* translate bcmerrors into linux errors */ int osl_error(int bcmerror) @@ -372,7 +251,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) gfp_t flags; #ifdef BCM_SECURE_DMA u32 secdma_memsize; -#endif +#endif // endif flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC; if (!(osh = kmalloc(sizeof(osl_t), flags))) @@ -493,7 +372,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) * osl_sec_dma_init_elem_mem_block(osh, CMA_BUFSIZE_2K, CMA_BUFNUM, &osh->sec_list_2048); * osh->sec_list_base_2048 = osh->sec_list_2048; */ -#endif +#endif // endif if (BCME_OK != osl_sec_dma_init_elem_mem_block(osh, CMA_BUFSIZE_4K, CMA_BUFNUM, &osh->sec_list_4096)) { osl_sec_dma_iounmap(osh, osh->contig_base_coherent_va, CMA_DMA_DESC_MEMBLOCK); @@ -525,63 +404,22 @@ osl_attach(void *pdev, uint bustype, bool pkttag) break; } + DMA_LOCK_INIT(osh); +#ifdef DHD_MAP_LOGGING + dhd_map_log = kmalloc(sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE, flags); + if (dhd_map_log) { + memset(dhd_map_log, 0, sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE); + } + dhd_unmap_log = kmalloc(sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE, flags); + if (dhd_unmap_log) { + memset(dhd_unmap_log, 0, sizeof(dhd_map_log_t) * DHD_MAP_LOG_SIZE); + } +#endif /* DHD_MAP_LOGGING */ return osh; } -int osl_static_mem_init(osl_t *osh, void *adapter) -{ -#ifdef CONFIG_DHD_USE_STATIC_BUF - if (!bcm_static_buf && adapter) { - if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter, - 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) { - printk("can not alloc static buf!\n"); - bcm_static_skb = NULL; - ASSERT(osh->magic == OS_HANDLE_MAGIC); - return -ENOMEM; - } else { - printk("alloc static buf at %p!\n", bcm_static_buf); - } - - spin_lock_init(&bcm_static_buf->static_lock); - - bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; - } - -#if defined(BCMSDIO) || defined(DHD_USE_STATIC_CTRLBUF) - if (!bcm_static_skb && adapter) { - int i; - void *skb_buff_ptr = 0; - bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); - skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0); - if (!skb_buff_ptr) { - printk("cannot alloc static buf!\n"); - bcm_static_buf = NULL; - bcm_static_skb = NULL; - ASSERT(osh->magic == OS_HANDLE_MAGIC); - return -ENOMEM; - } - - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * - (STATIC_PKT_MAX_NUM)); - for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { - bcm_static_skb->pkt_use[i] = 0; - } - -#ifdef DHD_USE_STATIC_CTRLBUF - spin_lock_init(&bcm_static_skb->osl_pkt_lock); - bcm_static_skb->last_allocated_index = 0; -#else - sema_init(&bcm_static_skb->osl_pkt_sem, 1); -#endif /* DHD_USE_STATIC_CTRLBUF */ - } -#endif /* BCMSDIO || DHD_USE_STATIC_CTRLBUF */ -#endif /* CONFIG_DHD_USE_STATIC_BUF */ - - return 0; -} - void osl_set_bus_handle(osl_t *osh, void *bus_handle) { osh->bus_handle = bus_handle; @@ -592,6 +430,16 @@ void* osl_get_bus_handle(osl_t *osh) return osh->bus_handle; } +#if defined(BCM_BACKPLANE_TIMEOUT) +void osl_set_bpt_cb(osl_t *osh, void *bpt_cb, void *bpt_ctx) +{ + if (osh) { + osh->bpt_cb = (bpt_cb_fn)bpt_cb; + osh->sih = bpt_ctx; + } +} +#endif /* BCM_BACKPLANE_TIMEOUT */ + void osl_detach(osl_t *osh) { @@ -611,9 +459,17 @@ osl_detach(osl_t *osh) secdma_found--; #endif /* BCM_SECURE_DMA */ - bcm_object_trace_deinit(); +#ifdef DHD_MAP_LOGGING + if (dhd_map_log) { + kfree(dhd_map_log); + } + if (dhd_unmap_log) { + kfree(dhd_unmap_log); + } +#endif /* DHD_MAP_LOGGING */ + ASSERT(osh->magic == OS_HANDLE_MAGIC); atomic_sub(1, &osh->cmn->refcount); if (atomic_read(&osh->cmn->refcount) == 0) { @@ -622,21 +478,6 @@ osl_detach(osl_t *osh) kfree(osh); } -int osl_static_mem_deinit(osl_t *osh, void *adapter) -{ -#ifdef CONFIG_DHD_USE_STATIC_BUF - if (bcm_static_buf) { - bcm_static_buf = 0; - } -#ifdef BCMSDIO - if (bcm_static_skb) { - bcm_static_skb = 0; - } -#endif /* BCMSDIO */ -#endif /* CONFIG_DHD_USE_STATIC_BUF */ - return 0; -} - /* APIs to set/get specific quirks in OSL layer */ void BCMFASTPATH osl_flag_set(osl_t *osh, uint32 mask) @@ -654,14 +495,14 @@ osl_flag_clr(osl_t *osh, uint32 mask) inline bool BCMFASTPATH #else bool -#endif +#endif // endif osl_is_flag_set(osl_t *osh, uint32 mask) { return (osh->flags & mask); } - -#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)) +#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)) || \ + defined(STB_SOC_WIFI) inline int BCMFASTPATH osl_arch_is_coherent(void) @@ -680,686 +521,34 @@ osl_cache_flush(void *va, uint size) { if (size > 0) - dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_TO_DEVICE); +#ifdef STB_SOC_WIFI + dma_sync_single_for_device(OSH_NULL, virt_to_phys(va), size, DMA_TX); +#else /* STB_SOC_WIFI */ + dma_sync_single_for_device(OSH_NULL, virt_to_dma(OSH_NULL, va), size, + DMA_TO_DEVICE); +#endif /* STB_SOC_WIFI */ } inline void BCMFASTPATH osl_cache_inv(void *va, uint size) { +#ifdef STB_SOC_WIFI + dma_sync_single_for_cpu(OSH_NULL, virt_to_phys(va), size, DMA_RX); +#else /* STB_SOC_WIFI */ dma_sync_single_for_cpu(OSH_NULL, virt_to_dma(OSH_NULL, va), size, DMA_FROM_DEVICE); +#endif /* STB_SOC_WIFI */ } inline void BCMFASTPATH osl_prefetch(const void *ptr) { - __asm__ __volatile__("pld\t%0" :: "o"(*(char *)ptr) : "cc"); -} - -#endif - -/* - * To avoid ACP latency, a fwder buf will be sent directly to DDR using - * DDR aliasing into non-ACP address space. Such Fwder buffers must be - * explicitly managed from a coherency perspective. - */ -static inline void BCMFASTPATH -osl_fwderbuf_reset(osl_t *osh, struct sk_buff *skb) -{ -} - -static struct sk_buff *osl_alloc_skb(osl_t *osh, unsigned int len) -{ - struct sk_buff *skb; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - gfp_t flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; -#ifdef DHD_USE_ATOMIC_PKTGET - flags = GFP_ATOMIC; -#endif /* DHD_USE_ATOMIC_PKTGET */ - skb = __dev_alloc_skb(len, flags); -#else - skb = dev_alloc_skb(len); -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */ - return skb; +#if !defined(STB_SOC_WIFI) + __asm__ __volatile__("pld\t%0" :: "o"(*(const char *)ptr) : "cc"); +#endif // endif } -#ifdef CTFPOOL - -#define CTFPOOL_LOCK(ctfpool, flags) spin_lock_bh(&(ctfpool)->lock) -#define CTFPOOL_UNLOCK(ctfpool, flags) spin_unlock_bh(&(ctfpool)->lock) -/* - * Allocate and add an object to packet pool. - */ -void * -osl_ctfpool_add(osl_t *osh) -{ - struct sk_buff *skb; - - if ((osh == NULL) || (osh->ctfpool == NULL)) - return NULL; - - CTFPOOL_LOCK(osh->ctfpool, flags); - ASSERT(osh->ctfpool->curr_obj <= osh->ctfpool->max_obj); - - /* No need to allocate more objects */ - if (osh->ctfpool->curr_obj == osh->ctfpool->max_obj) { - CTFPOOL_UNLOCK(osh->ctfpool, flags); - return NULL; - } - - /* Allocate a new skb and add it to the ctfpool */ - skb = osl_alloc_skb(osh, osh->ctfpool->obj_size); - if (skb == NULL) { - printf("%s: skb alloc of len %d failed\n", __FUNCTION__, - osh->ctfpool->obj_size); - CTFPOOL_UNLOCK(osh->ctfpool, flags); - return NULL; - } - - /* Add to ctfpool */ - skb->next = (struct sk_buff *)osh->ctfpool->head; - osh->ctfpool->head = skb; - osh->ctfpool->fast_frees++; - osh->ctfpool->curr_obj++; - - /* Hijack a skb member to store ptr to ctfpool */ - CTFPOOLPTR(osh, skb) = (void *)osh->ctfpool; - - /* Use bit flag to indicate skb from fast ctfpool */ - PKTFAST(osh, skb) = FASTBUF; - - /* If ctfpool's osh is a fwder osh, reset the fwder buf */ - osl_fwderbuf_reset(osh->ctfpool->osh, skb); - - CTFPOOL_UNLOCK(osh->ctfpool, flags); - - return skb; -} - -/* - * Add new objects to the pool. - */ -void -osl_ctfpool_replenish(osl_t *osh, uint thresh) -{ - if ((osh == NULL) || (osh->ctfpool == NULL)) - return; - - /* Do nothing if no refills are required */ - while ((osh->ctfpool->refills > 0) && (thresh--)) { - osl_ctfpool_add(osh); - osh->ctfpool->refills--; - } -} - -/* - * Initialize the packet pool with specified number of objects. - */ -int32 -osl_ctfpool_init(osl_t *osh, uint numobj, uint size) -{ - gfp_t flags; - - flags = CAN_SLEEP() ? GFP_KERNEL: GFP_ATOMIC; - osh->ctfpool = kzalloc(sizeof(ctfpool_t), flags); - ASSERT(osh->ctfpool); - - osh->ctfpool->osh = osh; - - osh->ctfpool->max_obj = numobj; - osh->ctfpool->obj_size = size; - - spin_lock_init(&osh->ctfpool->lock); - - while (numobj--) { - if (!osl_ctfpool_add(osh)) - return -1; - osh->ctfpool->fast_frees--; - } - - return 0; -} - -/* - * Cleanup the packet pool objects. - */ -void -osl_ctfpool_cleanup(osl_t *osh) -{ - struct sk_buff *skb, *nskb; - - if ((osh == NULL) || (osh->ctfpool == NULL)) - return; - - CTFPOOL_LOCK(osh->ctfpool, flags); - - skb = osh->ctfpool->head; - - while (skb != NULL) { - nskb = skb->next; - dev_kfree_skb(skb); - skb = nskb; - osh->ctfpool->curr_obj--; - } - - ASSERT(osh->ctfpool->curr_obj == 0); - osh->ctfpool->head = NULL; - CTFPOOL_UNLOCK(osh->ctfpool, flags); - - kfree(osh->ctfpool); - osh->ctfpool = NULL; -} - -void -osl_ctfpool_stats(osl_t *osh, void *b) -{ - struct bcmstrbuf *bb; - - if ((osh == NULL) || (osh->ctfpool == NULL)) - return; - -#ifdef CONFIG_DHD_USE_STATIC_BUF - if (bcm_static_buf) { - bcm_static_buf = 0; - } -#ifdef BCMSDIO - if (bcm_static_skb) { - bcm_static_skb = 0; - } -#endif /* BCMSDIO */ -#endif /* CONFIG_DHD_USE_STATIC_BUF */ - - bb = b; - - ASSERT((osh != NULL) && (bb != NULL)); - - bcm_bprintf(bb, "max_obj %d obj_size %d curr_obj %d refills %d\n", - osh->ctfpool->max_obj, osh->ctfpool->obj_size, - osh->ctfpool->curr_obj, osh->ctfpool->refills); - bcm_bprintf(bb, "fast_allocs %d fast_frees %d slow_allocs %d\n", - osh->ctfpool->fast_allocs, osh->ctfpool->fast_frees, - osh->ctfpool->slow_allocs); -} - -static inline struct sk_buff * -osl_pktfastget(osl_t *osh, uint len) -{ - struct sk_buff *skb; - - /* Try to do fast allocate. Return null if ctfpool is not in use - * or if there are no items in the ctfpool. - */ - if (osh->ctfpool == NULL) - return NULL; - - CTFPOOL_LOCK(osh->ctfpool, flags); - if (osh->ctfpool->head == NULL) { - ASSERT(osh->ctfpool->curr_obj == 0); - osh->ctfpool->slow_allocs++; - CTFPOOL_UNLOCK(osh->ctfpool, flags); - return NULL; - } - - if (len > osh->ctfpool->obj_size) { - CTFPOOL_UNLOCK(osh->ctfpool, flags); - return NULL; - } - - ASSERT(len <= osh->ctfpool->obj_size); - - /* Get an object from ctfpool */ - skb = (struct sk_buff *)osh->ctfpool->head; - osh->ctfpool->head = (void *)skb->next; - - osh->ctfpool->fast_allocs++; - osh->ctfpool->curr_obj--; - ASSERT(CTFPOOLHEAD(osh, skb) == (struct sock *)osh->ctfpool->head); - CTFPOOL_UNLOCK(osh->ctfpool, flags); - - /* Init skb struct */ - skb->next = skb->prev = NULL; -#if defined(__ARM_ARCH_7A__) - skb->data = skb->head + NET_SKB_PAD; - skb->tail = skb->head + NET_SKB_PAD; -#else - skb->data = skb->head + 16; - skb->tail = skb->head + 16; -#endif /* __ARM_ARCH_7A__ */ - skb->len = 0; - skb->cloned = 0; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 14) - skb->list = NULL; -#endif - atomic_set(&skb->users, 1); - - PKTSETCLINK(skb, NULL); - PKTCCLRATTR(skb); - PKTFAST(osh, skb) &= ~(CTFBUF | SKIPCT | CHAINED); - - return skb; -} -#endif /* CTFPOOL */ - - -/* Convert a driver packet to native(OS) packet - * In the process, packettag is zeroed out before sending up - * IP code depends on skb->cb to be setup correctly with various options - * In our case, that means it should be 0 - */ -struct sk_buff * BCMFASTPATH -osl_pkt_tonative(osl_t *osh, void *pkt) -{ - struct sk_buff *nskb; - - if (osh->pub.pkttag) - OSL_PKTTAG_CLEAR(pkt); - - /* Decrement the packet counter */ - for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->cmn->pktalloced); - - } - return (struct sk_buff *)pkt; -} - -/* Convert a native(OS) packet to driver packet. - * In the process, native packet is destroyed, there is no copying - * Also, a packettag is zeroed out - */ -void * BCMFASTPATH -osl_pkt_frmnative(osl_t *osh, void *pkt) -{ - struct sk_buff *cskb; - struct sk_buff *nskb; - unsigned long pktalloced = 0; - - if (osh->pub.pkttag) - OSL_PKTTAG_CLEAR(pkt); - - /* walk the PKTCLINK() list */ - for (cskb = (struct sk_buff *)pkt; - cskb != NULL; - cskb = PKTISCHAINED(cskb) ? PKTCLINK(cskb) : NULL) { - - /* walk the pkt buffer list */ - for (nskb = cskb; nskb; nskb = nskb->next) { - - /* Increment the packet counter */ - pktalloced++; - - /* clean the 'prev' pointer - * Kernel 3.18 is leaving skb->prev pointer set to skb - * to indicate a non-fragmented skb - */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) - nskb->prev = NULL; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */ - - - } - } - - /* Increment the packet counter */ - atomic_add(pktalloced, &osh->cmn->pktalloced); - - return (void *)pkt; -} - -/* Return a new packet. zero out pkttag */ -#ifdef BCM_OBJECT_TRACE -void * BCMFASTPATH -osl_pktget(osl_t *osh, uint len, int line, const char *caller) -#else -void * BCMFASTPATH -osl_pktget(osl_t *osh, uint len) -#endif /* BCM_OBJECT_TRACE */ -{ - struct sk_buff *skb; - uchar num = 0; - if (lmtest != FALSE) { - get_random_bytes(&num, sizeof(uchar)); - if ((num + 1) <= (256 * lmtest / 100)) - return NULL; - } - -#ifdef CTFPOOL - /* Allocate from local pool */ - skb = osl_pktfastget(osh, len); - if ((skb != NULL) || ((skb = osl_alloc_skb(osh, len)) != NULL)) { -#else /* CTFPOOL */ - if ((skb = osl_alloc_skb(osh, len))) { -#endif /* CTFPOOL */ - skb->tail += len; - skb->len += len; - skb->priority = 0; - - atomic_inc(&osh->cmn->pktalloced); -#ifdef BCM_OBJECT_TRACE - bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, caller, line); -#endif /* BCM_OBJECT_TRACE */ - } - - return ((void*) skb); -} - -#ifdef CTFPOOL -static inline void -osl_pktfastfree(osl_t *osh, struct sk_buff *skb) -{ - ctfpool_t *ctfpool; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) - skb->tstamp.tv.sec = 0; -#else - skb->stamp.tv_sec = 0; -#endif - - /* We only need to init the fields that we change */ - skb->dev = NULL; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) - skb->dst = NULL; -#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); - - /* if osh is a fwder osh, reset the fwder buf */ - osl_fwderbuf_reset(ctfpool->osh, skb); - - /* Add object to the ctfpool */ - CTFPOOL_LOCK(ctfpool, flags); - skb->next = (struct sk_buff *)ctfpool->head; - ctfpool->head = (void *)skb; - - ctfpool->fast_frees++; - ctfpool->curr_obj++; - - ASSERT(ctfpool->curr_obj <= ctfpool->max_obj); - CTFPOOL_UNLOCK(ctfpool, flags); -} -#endif /* CTFPOOL */ - -/* Free the driver packet. Free the tag if present */ -#ifdef BCM_OBJECT_TRACE -void BCMFASTPATH -osl_pktfree(osl_t *osh, void *p, bool send, int line, const char *caller) -#else -void BCMFASTPATH -osl_pktfree(osl_t *osh, void *p, bool send) -#endif /* BCM_OBJECT_TRACE */ -{ - struct sk_buff *skb, *nskb; - if (osh == NULL) - return; - - skb = (struct sk_buff*) p; - - if (send && osh->pub.tx_fn) - osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); - - PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); - -#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_CTRLBUF) - if (skb && (skb->mac_len == PREALLOC_USED_MAGIC)) { - printk("%s: pkt %p is from static pool\n", - __FUNCTION__, p); - dump_stack(); - return; - } - - if (skb && (skb->mac_len == PREALLOC_FREE_MAGIC)) { - printk("%s: pkt %p is from static pool and not in used\n", - __FUNCTION__, p); - dump_stack(); - return; - } -#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_CTRLBUF */ - - /* perversion: we use skb->next to chain multi-skb packets */ - while (skb) { - nskb = skb->next; - skb->next = NULL; - - - -#ifdef BCM_OBJECT_TRACE - bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, caller, line); -#endif /* BCM_OBJECT_TRACE */ - -#ifdef CTFPOOL - if (PKTISFAST(osh, skb)) { - if (atomic_read(&skb->users) == 1) - smp_rmb(); - else if (!atomic_dec_and_test(&skb->users)) - goto next_skb; - osl_pktfastfree(osh, skb); - } else -#endif - { - dev_kfree_skb_any(skb); - } -#ifdef CTFPOOL -next_skb: -#endif - atomic_dec(&osh->cmn->pktalloced); - skb = nskb; - } -} - -#ifdef CONFIG_DHD_USE_STATIC_BUF -void* -osl_pktget_static(osl_t *osh, uint len) -{ - int i = 0; - struct sk_buff *skb; -#ifdef DHD_USE_STATIC_CTRLBUF - unsigned long flags; -#endif /* DHD_USE_STATIC_CTRLBUF */ - - if (!bcm_static_skb) - return osl_pktget(osh, len); - - if (len > DHD_SKB_MAX_BUFSIZE) { - printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); - return osl_pktget(osh, len); - } - -#ifdef DHD_USE_STATIC_CTRLBUF - spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags); - - if (len <= DHD_SKB_2PAGE_BUFSIZE) { - uint32 index; - for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) { - index = bcm_static_skb->last_allocated_index % STATIC_PKT_2PAGE_NUM; - bcm_static_skb->last_allocated_index++; - if (bcm_static_skb->skb_8k[index] && - bcm_static_skb->pkt_use[index] == 0) { - break; - } - } - - if ((i != STATIC_PKT_2PAGE_NUM) && - (index >= 0) && (index < STATIC_PKT_2PAGE_NUM)) { - bcm_static_skb->pkt_use[index] = 1; - skb = bcm_static_skb->skb_8k[index]; - skb->data = skb->head; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb_set_tail_pointer(skb, NET_SKB_PAD); -#else - skb->tail = skb->data + NET_SKB_PAD; -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - skb->data += NET_SKB_PAD; - skb->cloned = 0; - skb->priority = 0; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb_set_tail_pointer(skb, len); -#else - skb->tail = skb->data + len; -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - skb->len = len; - skb->mac_len = PREALLOC_USED_MAGIC; - spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); - return skb; - } - } - - spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); - printk("%s: all static pkt in use!\n", __FUNCTION__); - return NULL; -#else - down(&bcm_static_skb->osl_pkt_sem); - - if (len <= DHD_SKB_1PAGE_BUFSIZE) { - for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) { - if (bcm_static_skb->skb_4k[i] && - bcm_static_skb->pkt_use[i] == 0) { - break; - } - } - - if (i != STATIC_PKT_1PAGE_NUM) { - bcm_static_skb->pkt_use[i] = 1; - - skb = bcm_static_skb->skb_4k[i]; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb_set_tail_pointer(skb, len); -#else - skb->tail = skb->data + len; -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - skb->len = len; - - up(&bcm_static_skb->osl_pkt_sem); - return skb; - } - } - - if (len <= DHD_SKB_2PAGE_BUFSIZE) { - for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) { - if (bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM] && - bcm_static_skb->pkt_use[i] == 0) { - break; - } - } - - if ((i >= STATIC_PKT_1PAGE_NUM) && (i < STATIC_PKT_1_2PAGE_NUM)) { - bcm_static_skb->pkt_use[i] = 1; - skb = bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb_set_tail_pointer(skb, len); -#else - skb->tail = skb->data + len; -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - skb->len = len; - - up(&bcm_static_skb->osl_pkt_sem); - return skb; - } - } - -#if defined(ENHANCED_STATIC_BUF) - if (bcm_static_skb->skb_16k && - bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] == 0) { - bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 1; - - skb = bcm_static_skb->skb_16k; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb_set_tail_pointer(skb, len); -#else - skb->tail = skb->data + len; -#endif /* NET_SKBUFF_DATA_USES_OFFSET */ - skb->len = len; - - up(&bcm_static_skb->osl_pkt_sem); - return skb; - } -#endif /* ENHANCED_STATIC_BUF */ - - up(&bcm_static_skb->osl_pkt_sem); - printk("%s: all static pkt in use!\n", __FUNCTION__); - return osl_pktget(osh, len); -#endif /* DHD_USE_STATIC_CTRLBUF */ -} - -void -osl_pktfree_static(osl_t *osh, void *p, bool send) -{ - int i; -#ifdef DHD_USE_STATIC_CTRLBUF - struct sk_buff *skb = (struct sk_buff *)p; - unsigned long flags; -#endif /* DHD_USE_STATIC_CTRLBUF */ - - if (!p) { - return; - } - - if (!bcm_static_skb) { - osl_pktfree(osh, p, send); - return; - } - -#ifdef DHD_USE_STATIC_CTRLBUF - spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags); - - for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) { - if (p == bcm_static_skb->skb_8k[i]) { - if (bcm_static_skb->pkt_use[i] == 0) { - printk("%s: static pkt idx %d(%p) is double free\n", - __FUNCTION__, i, p); - } else { - bcm_static_skb->pkt_use[i] = 0; - } - - if (skb->mac_len != PREALLOC_USED_MAGIC) { - printk("%s: static pkt idx %d(%p) is not in used\n", - __FUNCTION__, i, p); - } - - skb->mac_len = PREALLOC_FREE_MAGIC; - spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); - return; - } - } - - spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); - printk("%s: packet %p does not exist in the pool\n", __FUNCTION__, p); -#else - down(&bcm_static_skb->osl_pkt_sem); - for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) { - if (p == bcm_static_skb->skb_4k[i]) { - bcm_static_skb->pkt_use[i] = 0; - up(&bcm_static_skb->osl_pkt_sem); - return; - } - } - - for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) { - if (p == bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]) { - bcm_static_skb->pkt_use[i] = 0; - up(&bcm_static_skb->osl_pkt_sem); - return; - } - } -#ifdef ENHANCED_STATIC_BUF - if (p == bcm_static_skb->skb_16k) { - bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 0; - up(&bcm_static_skb->osl_pkt_sem); - return; - } -#endif - up(&bcm_static_skb->osl_pkt_sem); -#endif /* DHD_USE_STATIC_CTRLBUF */ - osl_pktfree(osh, p, send); -} -#endif /* CONFIG_DHD_USE_STATIC_BUF */ +#endif // endif uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size) @@ -1378,7 +567,6 @@ osl_pci_read_config(osl_t *osh, uint offset, uint size) break; } while (retry--); - return (val); } @@ -1412,7 +600,7 @@ osl_pci_bus(osl_t *osh) return pci_domain_nr(((struct pci_dev *)osh->pdev)->bus); #else return ((struct pci_dev *)osh->pdev)->bus->number; -#endif +#endif // endif } /* return slot # for the pci device pointed by osh->pdev */ @@ -1425,7 +613,7 @@ osl_pci_slot(osl_t *osh) return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1; #else return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); -#endif +#endif // endif } /* return domain # for the pci device pointed by osh->pdev */ @@ -1649,7 +837,6 @@ osl_malloc_failed(osl_t *osh) return (osh->failed); } - uint osl_dma_consistent_align(void) { @@ -1668,7 +855,8 @@ osl_dma_alloc_consistent(osl_t *osh, uint size, uint16 align_bits, uint *alloced *alloced = size; #ifndef BCM_SECURE_DMA -#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING) +#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)) || \ + defined(STB_SOC_WIFI) va = kmalloc(size, GFP_ATOMIC | __GFP_ZERO); if (va) *pap = (ulong)__virt_to_phys((ulong)va); @@ -1706,7 +894,8 @@ osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa) ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); #ifndef BCM_SECURE_DMA -#if defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING) +#if (defined(__ARM_ARCH_7A__) && !defined(DHD_USE_COHERENT_MEM_FOR_RING)) || \ + defined(STB_SOC_WIFI) kfree(va); #else #ifdef BCMDMA64OSL @@ -1721,6 +910,21 @@ osl_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa) #endif /* BCM_SECURE_DMA */ } +void * +osl_virt_to_phys(void *va) +{ + return (void *)(uintptr)virt_to_phys(va); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#include +void BCMFASTPATH +osl_dma_flush(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) +{ + return; +} +#endif /* LINUX_VERSION_CODE >= 2.6.36 */ + dmaaddr_t BCMFASTPATH osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) { @@ -1729,20 +933,49 @@ osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_ dma_addr_t map_addr; int ret; + DMA_LOCK(osh); + ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; +#ifdef STB_SOC_WIFI +#if (__LINUX_ARM_ARCH__ == 8) + /* need to flush or invalidate the cache here */ + if (dir == DMA_TX) { /* to device */ + osl_cache_flush(va, size); + } else if (dir == DMA_RX) { /* from device */ + osl_cache_inv(va, size); + } else { /* both */ + osl_cache_flush(va, size); + osl_cache_inv(va, size); + } + DMA_UNLOCK(osh); + return virt_to_phys(va); +#else /* (__LINUX_ARM_ARCH__ == 8) */ + map_addr = dma_map_single(osh->pdev, va, size, dir); + DMA_UNLOCK(osh); + return map_addr; +#endif /* (__LINUX_ARM_ARCH__ == 8) */ +#else /* ! STB_SOC_WIFI */ + map_addr = pci_map_single(osh->pdev, va, size, dir); +#endif /* ! STB_SOC_WIFI */ +#ifdef DHD_MAP_LOGGING + if (dhd_map_log) { + dhd_map_log[map_idx].addr = map_addr; + dhd_map_log[map_idx].time = OSL_SYSUPTIME_US(); + map_idx++; + map_idx = map_idx % DHD_MAP_LOG_SIZE; + } +#endif /* DHD_MAP_LOGGING */ - - map_addr = pci_map_single(osh->pdev, va, size, dir); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) ret = pci_dma_mapping_error(osh->pdev, map_addr); #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 5)) ret = pci_dma_mapping_error(map_addr); #else ret = 0; -#endif +#endif // endif if (ret) { printk("%s: Failed to map memory\n", __FUNCTION__); PHYSADDRLOSET(ret_addr, 0); @@ -1752,6 +985,8 @@ osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_ PHYSADDRHISET(ret_addr, (map_addr >> 32) & 0xffffffff); } + DMA_UNLOCK(osh); + return ret_addr; } @@ -1765,14 +1000,52 @@ osl_dma_unmap(osl_t *osh, dmaaddr_t pa, uint size, int direction) ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); + DMA_LOCK(osh); dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; + #ifdef BCMDMA64OSL PHYSADDRTOULONG(pa, paddr); +#ifdef DHD_MAP_LOGGING + if (dhd_unmap_log) { + dhd_unmap_log[unmap_idx].addr = paddr; + dhd_unmap_log[unmap_idx].time = OSL_SYSUPTIME_US(); + unmap_idx++; + unmap_idx = unmap_idx % DHD_MAP_LOG_SIZE; + } +#endif /* DHD_MAP_LOGGING */ + pci_unmap_single(osh->pdev, paddr, size, dir); -#else +#else /* BCMDMA64OSL */ + +#ifdef STB_SOC_WIFI +#if (__LINUX_ARM_ARCH__ == 8) + if (dir == DMA_TX) { /* to device */ + dma_sync_single_for_device(OSH_NULL, pa, size, DMA_TX); + } else if (dir == DMA_RX) { /* from device */ + dma_sync_single_for_cpu(OSH_NULL, pa, size, DMA_RX); + } else { /* both */ + dma_sync_single_for_device(OSH_NULL, pa, size, DMA_TX); + dma_sync_single_for_cpu(OSH_NULL, pa, size, DMA_RX); + } +#else /* (__LINUX_ARM_ARCH__ == 8) */ + dma_unmap_single(osh->pdev, (uintptr)pa, size, dir); +#endif /* (__LINUX_ARM_ARCH__ == 8) */ +#else /* STB_SOC_WIFI */ +#ifdef DHD_MAP_LOGGING + if (dhd_unmap_log) { + dhd_unmap_log[unmap_idx].addr = pa; + dhd_unmap_log[unmap_idx].time = OSL_SYSUPTIME_US(); + unmap_idx++; + unmap_idx = unmap_idx % DHD_MAP_LOG_SIZE; + } +#endif /* DHD_MAP_LOGGING */ + pci_unmap_single(osh->pdev, (uint32)pa, size, dir); +#endif /* STB_SOC_WIFI */ + #endif /* BCMDMA64OSL */ + DMA_UNLOCK(osh); } /* OSL function for CPU relax */ @@ -1812,7 +1085,6 @@ osl_assert(const char *exp, const char *file, int line) exp, basename, line); #endif /* BCMASSERT_LOG */ - switch (g_assert_type) { case 0: panic("%s", tempbuf); @@ -1830,7 +1102,7 @@ osl_assert(const char *exp, const char *file, int line) break; } } -#endif +#endif // endif void osl_delay(uint usec) @@ -1851,7 +1123,7 @@ osl_sleep(uint ms) if (ms < 20) usleep_range(ms*1000, ms*1000 + 1000); else -#endif +#endif // endif msleep(ms); } @@ -1867,73 +1139,6 @@ osl_sysuptime_us(void) return usec; } - -/* Clone a packet. - * The pkttag contents are NOT cloned. - */ -#ifdef BCM_OBJECT_TRACE -void * -osl_pktdup(osl_t *osh, void *skb, int line, const char *caller) -#else -void * -osl_pktdup(osl_t *osh, void *skb) -#endif /* BCM_OBJECT_TRACE */ -{ - void * p; - - ASSERT(!PKTISCHAINED(skb)); - - /* clear the CTFBUF flag if set and map the rest of the buffer - * before cloning. - */ - PKTCTFMAP(osh, skb); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) - if ((p = pskb_copy((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) -#else - if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) -#endif - return NULL; - -#ifdef CTFPOOL - if (PKTISFAST(osh, skb)) { - ctfpool_t *ctfpool; - - /* if the buffer allocated from ctfpool is cloned then - * we can't be sure when it will be freed. since there - * is a chance that we will be losing a buffer - * from our pool, we increment the refill count for the - * object to be alloced later. - */ - ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); - ASSERT(ctfpool != NULL); - PKTCLRFAST(osh, p); - PKTCLRFAST(osh, skb); - ctfpool->refills++; - } -#endif /* CTFPOOL */ - - /* Clear PKTC context */ - PKTSETCLINK(p, NULL); - PKTCCLRFLAGS(p); - PKTCSETCNT(p, 1); - PKTCSETLEN(p, PKTLEN(osh, skb)); - - /* skb_clone copies skb->cb.. we don't want that */ - if (osh->pub.pkttag) - OSL_PKTTAG_CLEAR(p); - - /* Increment the packet counter */ - atomic_inc(&osh->cmn->pktalloced); -#ifdef BCM_OBJECT_TRACE - bcm_object_trace_opr(p, BCM_OBJDBG_ADD_PKT, caller, line); -#endif /* BCM_OBJECT_TRACE */ - - return (p); -} - - - /* * OSLREGOPS specifies the use of osl_XXX routines to be used for register access */ @@ -1942,15 +1147,6 @@ osl_pktdup(osl_t *osh, void *skb) * BINOSL selects the slightly slower function-call-based binary compatible osl. */ -uint -osl_pktalloced(osl_t *osh) -{ - if (atomic_read(&osh->cmn->refcount) == 1) - return (atomic_read(&osh->cmn->pktalloced)); - else - return 0; -} - uint32 osl_rand(void) { @@ -2022,7 +1218,7 @@ osl_os_image_size(void *image) /* Linux Kernel: File Operations: end */ #if (defined(STB) && defined(__arm__)) -inline void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size) +inline void osl_pcie_rreg(osl_t *osh, ulong addr, volatile void *v, uint size) { unsigned long flags = 0; int pci_access = 0; @@ -2036,23 +1232,60 @@ inline void osl_pcie_rreg(osl_t *osh, ulong addr, void *v, uint size) switch (size) { case sizeof(uint8): - *(uint8*)v = readb((volatile uint8*)(addr)); + *(volatile uint8*)v = readb((volatile uint8*)(addr)); break; case sizeof(uint16): - *(uint16*)v = readw((volatile uint16*)(addr)); + *(volatile uint16*)v = readw((volatile uint16*)(addr)); break; case sizeof(uint32): - *(uint32*)v = readl((volatile uint32*)(addr)); + *(volatile uint32*)v = readl((volatile uint32*)(addr)); break; case sizeof(uint64): - *(uint64*)v = *((volatile uint64*)(addr)); + *(volatile uint64*)v = *((volatile uint64*)(addr)); break; } if (pci_access && acp_war_enab) spin_unlock_irqrestore(&l2x0_reg_lock, flags); } -#endif +#endif // endif + +#if defined(BCM_BACKPLANE_TIMEOUT) +inline void osl_bpt_rreg(osl_t *osh, ulong addr, volatile void *v, uint size) +{ + bool poll_timeout = FALSE; + static int in_si_clear = FALSE; + + switch (size) { + case sizeof(uint8): + *(volatile uint8*)v = readb((volatile uint8*)(addr)); + if (*(volatile uint8*)v == 0xff) + poll_timeout = TRUE; + break; + case sizeof(uint16): + *(volatile uint16*)v = readw((volatile uint16*)(addr)); + if (*(volatile uint16*)v == 0xffff) + poll_timeout = TRUE; + break; + case sizeof(uint32): + *(volatile uint32*)v = readl((volatile uint32*)(addr)); + if (*(volatile uint32*)v == 0xffffffff) + poll_timeout = TRUE; + break; + case sizeof(uint64): + *(volatile uint64*)v = *((volatile uint64*)(addr)); + if (*(volatile uint64*)v == 0xffffffffffffffff) + poll_timeout = TRUE; + break; + } + + if (osh && osh->sih && (in_si_clear == FALSE) && poll_timeout && osh->bpt_cb) { + in_si_clear = TRUE; + osh->bpt_cb((void *)osh->sih, (void *)addr); + in_si_clear = FALSE; + } +} +#endif /* BCM_BACKPLANE_TIMEOUT */ #ifdef BCM_SECURE_DMA static void * @@ -2084,7 +1317,7 @@ osl_sec_dma_ioremap(osl_t *osh, struct page *page, size_t size, bool iscache, bo #if defined(__ARM_ARCH_7A__) addr = vmap(map, size >> PAGE_SHIFT, VM_MAP, pgprot_noncached(__pgprot(PAGE_KERNEL))); -#endif +#endif // endif if (isdecr) { osh->contig_delta_va_pa = ((uint8 *)addr - page_to_phys(page)); } @@ -2139,7 +1372,6 @@ osl_sec_dma_init_elem_mem_block(osl_t *osh, size_t mbsize, int max, sec_mem_elem return ret; } - static void osl_sec_dma_deinit_elem_mem_block(osl_t *osh, size_t mbsize, int max, void *sec_list_base) { @@ -2339,7 +1571,6 @@ osl_sec_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { if (skb_is_nonlinear(skb)) { - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *f = &skb_shinfo(skb)->frags[i]; fragva = kmap_atomic(skb_frag_page(f)); @@ -2413,7 +1644,7 @@ void *p, hnddma_seg_map_t *map, void *ptr_cma_info, uint offset) sec_mem_elem_t *sec_mem_elem; #ifdef NOT_YET struct page *pa_cma_page; -#endif +#endif // endif void *pa_cma_kmap_va = NULL; uint buflen = 0; dma_addr_t pa_cma; @@ -2431,7 +1662,7 @@ void *p, hnddma_seg_map_t *map, void *ptr_cma_info, uint offset) #ifdef NOT_YET pa_cma_page = sec_mem_elem->pa_cma_page; -#endif +#endif // endif if (direction == DMA_RX) { @@ -2573,44 +1804,8 @@ osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa) printf("%s:Error: va = 0x%p pa = 0x%lx size = %d\n", __FUNCTION__, va, (ulong)pa, size); } - #endif /* BCM_SECURE_DMA */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) && defined(TSQ_MULTIPLIER) -#include -#include -void -osl_pkt_orphan_partial(struct sk_buff *skb) -{ - uint32 fraction; - static void *p_tcp_wfree = NULL; - - if (!skb->destructor || skb->destructor == sock_wfree) - return; - - if (unlikely(!p_tcp_wfree)) { - char sym[KSYM_SYMBOL_LEN]; - sprint_symbol(sym, (unsigned long)skb->destructor); - sym[9] = 0; - if (!strcmp(sym, "tcp_wfree")) - p_tcp_wfree = skb->destructor; - else - return; - } - - if (unlikely(skb->destructor != p_tcp_wfree || !skb->sk)) - return; - - /* abstract a certain portion of skb truesize from the socket - * sk_wmem_alloc to allow more skb can be allocated for this - * socket for better cusion meeting WiFi device requirement - */ - fraction = skb->truesize * (TSQ_MULTIPLIER - 1) / TSQ_MULTIPLIER; - skb->truesize -= fraction; - atomic_sub(fraction, &skb->sk->sk_wmem_alloc); -} -#endif /* LINUX_VERSION >= 3.6.0 && TSQ_MULTIPLIER */ - /* timer apis */ /* Note: All timer api's are thread unsafe and should be protected with locks by caller */ @@ -2620,12 +1815,13 @@ osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg) osl_timer_t *t; BCM_REFERENCE(fn); if ((t = MALLOCZ(NULL, sizeof(osl_timer_t))) == NULL) { - printk(KERN_ERR "osl_timer_init: malloced failed for osl_timer_t\n"); + printk(KERN_ERR "osl_timer_init: out of memory, malloced %d bytes\n", + (int)sizeof(osl_timer_t)); return (NULL); } bzero(t, sizeof(osl_timer_t)); if ((t->timer = MALLOCZ(NULL, sizeof(struct timer_list))) == NULL) { - printk(KERN_ERR "osl_timer_init: malloc failed\n"); + printf("osl_timer_init: malloc failed\n"); MFREE(NULL, t, sizeof(osl_timer_t)); return (NULL); } @@ -2641,7 +1837,6 @@ osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg) void osl_timer_add(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic) { - if (t == NULL) { printf("%s: Timer handle is NULL\n", __FUNCTION__); return; @@ -2662,7 +1857,6 @@ osl_timer_add(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic) void osl_timer_update(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic) { - if (t == NULL) { printf("%s: Timer handle is NULL\n", __FUNCTION__); return; diff --git a/drivers/net/wireless/bcmdhd_oo/linux_osl_priv.h b/drivers/net/wireless/bcmdhd_oo/linux_osl_priv.h new file mode 100644 index 0000000000000000000000000000000000000000..0b602cd9035e42950a6e532854e4698d1dd5c011 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/linux_osl_priv.h @@ -0,0 +1,179 @@ +/* + * Private header file for Linux OS Independent Layer + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: linux_osl_priv.h 737887 2017-12-23 12:15:26Z $ + */ + +#ifndef _LINUX_OSL_PRIV_H_ +#define _LINUX_OSL_PRIV_H_ + +#define OS_HANDLE_MAGIC 0x1234abcd /* Magic # to recognize osh */ +#define BCM_MEM_FILENAME_LEN 24 /* Mem. filename length */ + +/* dependancy check */ +#if !defined(BCMPCIE) && defined(DHD_USE_STATIC_CTRLBUF) +#error "DHD_USE_STATIC_CTRLBUF suppored PCIE target only" +#endif /* !BCMPCIE && DHD_USE_STATIC_CTRLBUF */ + +#ifdef CONFIG_DHD_USE_STATIC_BUF +#ifdef DHD_USE_STATIC_CTRLBUF +#define DHD_SKB_1PAGE_BUFSIZE (PAGE_SIZE*1) +#define DHD_SKB_2PAGE_BUFSIZE (PAGE_SIZE*2) +#define DHD_SKB_4PAGE_BUFSIZE (PAGE_SIZE*4) + +#define PREALLOC_FREE_MAGIC 0xFEDC +#define PREALLOC_USED_MAGIC 0xFCDE +#else +#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) +#endif /* DHD_USE_STATIC_CTRLBUF */ + +#define STATIC_BUF_MAX_NUM 16 +#define STATIC_BUF_SIZE (PAGE_SIZE*2) +#define STATIC_BUF_TOTAL_LEN (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE) + +typedef struct bcm_static_buf { + spinlock_t static_lock; + unsigned char *buf_ptr; + unsigned char buf_use[STATIC_BUF_MAX_NUM]; +} bcm_static_buf_t; + +extern bcm_static_buf_t *bcm_static_buf; + +#ifdef DHD_USE_STATIC_CTRLBUF +#define STATIC_PKT_4PAGE_NUM 0 +#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE +#elif defined(ENHANCED_STATIC_BUF) +#define STATIC_PKT_4PAGE_NUM 1 +#define DHD_SKB_MAX_BUFSIZE DHD_SKB_4PAGE_BUFSIZE +#else +#define STATIC_PKT_4PAGE_NUM 0 +#define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE +#endif /* DHD_USE_STATIC_CTRLBUF */ + +#ifdef DHD_USE_STATIC_CTRLBUF +#define STATIC_PKT_1PAGE_NUM 0 +#define STATIC_PKT_2PAGE_NUM 128 +#else +#define STATIC_PKT_1PAGE_NUM 8 +#define STATIC_PKT_2PAGE_NUM 8 +#endif /* DHD_USE_STATIC_CTRLBUF */ + +#define STATIC_PKT_1_2PAGE_NUM \ + ((STATIC_PKT_1PAGE_NUM) + (STATIC_PKT_2PAGE_NUM)) +#define STATIC_PKT_MAX_NUM \ + ((STATIC_PKT_1_2PAGE_NUM) + (STATIC_PKT_4PAGE_NUM)) + +typedef struct bcm_static_pkt { +#ifdef DHD_USE_STATIC_CTRLBUF + struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM]; + unsigned char pkt_invalid[STATIC_PKT_2PAGE_NUM]; + spinlock_t osl_pkt_lock; + uint32 last_allocated_index; +#else + struct sk_buff *skb_4k[STATIC_PKT_1PAGE_NUM]; + struct sk_buff *skb_8k[STATIC_PKT_2PAGE_NUM]; +#ifdef ENHANCED_STATIC_BUF + struct sk_buff *skb_16k; +#endif /* ENHANCED_STATIC_BUF */ + struct semaphore osl_pkt_sem; +#endif /* DHD_USE_STATIC_CTRLBUF */ + unsigned char pkt_use[STATIC_PKT_MAX_NUM]; +} bcm_static_pkt_t; + +extern bcm_static_pkt_t *bcm_static_skb; +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + +typedef struct bcm_mem_link { + struct bcm_mem_link *prev; + struct bcm_mem_link *next; + uint size; + int line; + void *osh; + char file[BCM_MEM_FILENAME_LEN]; +} bcm_mem_link_t; + +struct osl_cmn_info { + atomic_t malloced; + atomic_t pktalloced; /* Number of allocated packet buffers */ + spinlock_t dbgmem_lock; + bcm_mem_link_t *dbgmem_list; + bcm_mem_link_t *dbgvmem_list; + spinlock_t pktalloc_lock; + atomic_t refcount; /* Number of references to this shared structure. */ +}; +typedef struct osl_cmn_info osl_cmn_t; + +#if defined(BCM_BACKPLANE_TIMEOUT) +typedef uint32 (*bpt_cb_fn)(void *ctx, void *addr); +#endif /* BCM_BACKPLANE_TIMEOUT */ + +struct osl_info { + osl_pubinfo_t pub; + uint32 flags; /* If specific cases to be handled in the OSL */ + uint magic; + void *pdev; + uint failed; + uint bustype; + osl_cmn_t *cmn; /* Common OSL related data shred between two OSH's */ + + void *bus_handle; +#ifdef BCM_SECURE_DMA +#ifdef NOT_YET + struct sec_mem_elem *sec_list_512; + struct sec_mem_elem *sec_list_base_512; + struct sec_mem_elem *sec_list_2048; + struct sec_mem_elem *sec_list_base_2048; +#endif /* NOT_YET */ + struct sec_mem_elem *sec_list_4096; + struct sec_mem_elem *sec_list_base_4096; + phys_addr_t contig_base; + void *contig_base_va; + phys_addr_t contig_base_alloc; + void *contig_base_alloc_va; + phys_addr_t contig_base_alloc_coherent; + void *contig_base_alloc_coherent_va; + void *contig_base_coherent_va; + void *contig_delta_va_pa; + struct { + phys_addr_t pa; + void *va; + bool avail; + } sec_cma_coherent[SEC_CMA_COHERENT_MAX]; + int stb_ext_params; +#endif /* BCM_SECURE_DMA */ +#if defined(BCM_BACKPLANE_TIMEOUT) + bpt_cb_fn bpt_cb; + void *sih; +#endif /* BCM_BACKPLANE_TIMEOUT */ +#ifdef USE_DMA_LOCK + spinlock_t dma_lock; +#endif /* USE_DMA_LOCK */ +}; + +#endif /* _LINUX_OSL_PRIV_H_ */ diff --git a/drivers/net/wireless/bcmdhd_oo/linux_pkt.c b/drivers/net/wireless/bcmdhd_oo/linux_pkt.c new file mode 100644 index 0000000000000000000000000000000000000000..d94e6b89424679f8da2963af5ded9f3c9bbe98b2 --- /dev/null +++ b/drivers/net/wireless/bcmdhd_oo/linux_pkt.c @@ -0,0 +1,621 @@ +/* + * Linux Packet (skb) interface + * + * Copyright (C) 1999-2018, Broadcom. + * + * 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: linux_pkt.c 729708 2017-11-02 05:10:59Z $ + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include "linux_osl_priv.h" + +#ifdef CONFIG_DHD_USE_STATIC_BUF + +bcm_static_buf_t *bcm_static_buf = 0; +bcm_static_pkt_t *bcm_static_skb = 0; + +void* wifi_platform_prealloc(void *adapter, int section, unsigned long size); +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + +#ifdef BCM_OBJECT_TRACE +/* don't clear the first 4 byte that is the pkt sn */ +#define OSL_PKTTAG_CLEAR(p) \ +do { \ + struct sk_buff *s = (struct sk_buff *)(p); \ + ASSERT(OSL_PKTTAG_SZ == 32); \ + *(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) +#else +#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) +#endif /* BCM_OBJECT_TRACE */ + +int osl_static_mem_init(osl_t *osh, void *adapter) +{ +#ifdef CONFIG_DHD_USE_STATIC_BUF + if (!bcm_static_buf && adapter) { + if (!(bcm_static_buf = (bcm_static_buf_t *)wifi_platform_prealloc(adapter, + 3, STATIC_BUF_SIZE + STATIC_BUF_TOTAL_LEN))) { + printk("can not alloc static buf!\n"); + bcm_static_skb = NULL; + ASSERT(osh->magic == OS_HANDLE_MAGIC); + return -ENOMEM; + } else { + printk("alloc static buf at %p!\n", bcm_static_buf); + } + + spin_lock_init(&bcm_static_buf->static_lock); + + bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; + } + +#if defined(BCMSDIO) || defined(DHD_USE_STATIC_CTRLBUF) + if (!bcm_static_skb && adapter) { + int i; + void *skb_buff_ptr = 0; + bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); + skb_buff_ptr = wifi_platform_prealloc(adapter, 4, 0); + if (!skb_buff_ptr) { + printk("cannot alloc static buf!\n"); + bcm_static_buf = NULL; + bcm_static_skb = NULL; + ASSERT(osh->magic == OS_HANDLE_MAGIC); + return -ENOMEM; + } + + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * + (STATIC_PKT_MAX_NUM)); + for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { + bcm_static_skb->pkt_use[i] = 0; + } + +#ifdef DHD_USE_STATIC_CTRLBUF + spin_lock_init(&bcm_static_skb->osl_pkt_lock); + bcm_static_skb->last_allocated_index = 0; +#else + sema_init(&bcm_static_skb->osl_pkt_sem, 1); +#endif /* DHD_USE_STATIC_CTRLBUF */ + } +#endif /* BCMSDIO || DHD_USE_STATIC_CTRLBUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + + return 0; +} + +int osl_static_mem_deinit(osl_t *osh, void *adapter) +{ +#ifdef CONFIG_DHD_USE_STATIC_BUF + if (bcm_static_buf) { + bcm_static_buf = 0; + } +#ifdef BCMSDIO + if (bcm_static_skb) { + bcm_static_skb = 0; + } +#endif /* BCMSDIO */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + return 0; +} + +/* + * To avoid ACP latency, a fwder buf will be sent directly to DDR using + * DDR aliasing into non-ACP address space. Such Fwder buffers must be + * explicitly managed from a coherency perspective. + */ +static inline void BCMFASTPATH +osl_fwderbuf_reset(osl_t *osh, struct sk_buff *skb) +{ +} + +static struct sk_buff * BCMFASTPATH +osl_alloc_skb(osl_t *osh, unsigned int len) +{ + struct sk_buff *skb; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) + gfp_t flags = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL; +#ifdef DHD_USE_ATOMIC_PKTGET + flags = GFP_ATOMIC; +#endif /* DHD_USE_ATOMIC_PKTGET */ + skb = __dev_alloc_skb(len, flags); +#else + skb = dev_alloc_skb(len); +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) */ + + return skb; +} + +/* Convert a driver packet to native(OS) packet + * In the process, packettag is zeroed out before sending up + * IP code depends on skb->cb to be setup correctly with various options + * In our case, that means it should be 0 + */ +struct sk_buff * BCMFASTPATH +osl_pkt_tonative(osl_t *osh, void *pkt) +{ + struct sk_buff *nskb; + + if (osh->pub.pkttag) + OSL_PKTTAG_CLEAR(pkt); + + /* Decrement the packet counter */ + for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { + atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->cmn->pktalloced); + + } + return (struct sk_buff *)pkt; +} + +/* Convert a native(OS) packet to driver packet. + * In the process, native packet is destroyed, there is no copying + * Also, a packettag is zeroed out + */ +void * BCMFASTPATH +osl_pkt_frmnative(osl_t *osh, void *pkt) +{ + struct sk_buff *cskb; + struct sk_buff *nskb; + unsigned long pktalloced = 0; + + if (osh->pub.pkttag) + OSL_PKTTAG_CLEAR(pkt); + + /* walk the PKTCLINK() list */ + for (cskb = (struct sk_buff *)pkt; + cskb != NULL; + cskb = PKTISCHAINED(cskb) ? PKTCLINK(cskb) : NULL) { + + /* walk the pkt buffer list */ + for (nskb = cskb; nskb; nskb = nskb->next) { + + /* Increment the packet counter */ + pktalloced++; + + /* clean the 'prev' pointer + * Kernel 3.18 is leaving skb->prev pointer set to skb + * to indicate a non-fragmented skb + */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)) + nskb->prev = NULL; +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */ + + } + } + + /* Increment the packet counter */ + atomic_add(pktalloced, &osh->cmn->pktalloced); + + return (void *)pkt; +} + +/* Return a new packet. zero out pkttag */ +#ifdef BCM_OBJECT_TRACE +void * BCMFASTPATH +linux_pktget(osl_t *osh, uint len, int line, const char *caller) +#else +void * BCMFASTPATH +linux_pktget(osl_t *osh, uint len) +#endif /* BCM_OBJECT_TRACE */ +{ + struct sk_buff *skb; + uchar num = 0; + if (lmtest != FALSE) { + get_random_bytes(&num, sizeof(uchar)); + if ((num + 1) <= (256 * lmtest / 100)) + return NULL; + } + + if ((skb = osl_alloc_skb(osh, len))) { + skb->tail += len; + skb->len += len; + skb->priority = 0; + + atomic_inc(&osh->cmn->pktalloced); +#ifdef BCM_OBJECT_TRACE + bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, caller, line); +#endif /* BCM_OBJECT_TRACE */ + } + + return ((void*) skb); +} + +/* Free the driver packet. Free the tag if present */ +#ifdef BCM_OBJECT_TRACE +void BCMFASTPATH +linux_pktfree(osl_t *osh, void *p, bool send, int line, const char *caller) +#else +void BCMFASTPATH +linux_pktfree(osl_t *osh, void *p, bool send) +#endif /* BCM_OBJECT_TRACE */ +{ + struct sk_buff *skb, *nskb; + if (osh == NULL) + return; + + skb = (struct sk_buff*) p; + + if (send) { + if (osh->pub.tx_fn) { + osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); + } + } else { + if (osh->pub.rx_fn) { + osh->pub.rx_fn(osh->pub.rx_ctx, p); + } + } + + PKTDBG_TRACE(osh, (void *) skb, PKTLIST_PKTFREE); + +#if defined(CONFIG_DHD_USE_STATIC_BUF) && defined(DHD_USE_STATIC_CTRLBUF) + if (skb && (skb->mac_len == PREALLOC_USED_MAGIC)) { + printk("%s: pkt %p is from static pool\n", + __FUNCTION__, p); + dump_stack(); + return; + } + + if (skb && (skb->mac_len == PREALLOC_FREE_MAGIC)) { + printk("%s: pkt %p is from static pool and not in used\n", + __FUNCTION__, p); + dump_stack(); + return; + } +#endif /* CONFIG_DHD_USE_STATIC_BUF && DHD_USE_STATIC_CTRLBUF */ + + /* perversion: we use skb->next to chain multi-skb packets */ + while (skb) { + nskb = skb->next; + skb->next = NULL; + +#ifdef BCM_OBJECT_TRACE + bcm_object_trace_opr(skb, BCM_OBJDBG_REMOVE, caller, line); +#endif /* BCM_OBJECT_TRACE */ + + { + if (skb->destructor) { + /* cannot kfree_skb() on hard IRQ (net/core/skbuff.c) if + * destructor exists + */ + dev_kfree_skb_any(skb); + } else { + /* can free immediately (even in_irq()) if destructor + * does not exist + */ + dev_kfree_skb(skb); + } + } + atomic_dec(&osh->cmn->pktalloced); + skb = nskb; + } +} + +#ifdef CONFIG_DHD_USE_STATIC_BUF +void* +osl_pktget_static(osl_t *osh, uint len) +{ + int i = 0; + struct sk_buff *skb; +#ifdef DHD_USE_STATIC_CTRLBUF + unsigned long flags; +#endif /* DHD_USE_STATIC_CTRLBUF */ + + if (!bcm_static_skb) + return linux_pktget(osh, len); + + if (len > DHD_SKB_MAX_BUFSIZE) { + printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); + return linux_pktget(osh, len); + } + +#ifdef DHD_USE_STATIC_CTRLBUF + spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags); + + if (len <= DHD_SKB_2PAGE_BUFSIZE) { + uint32 index; + for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) { + index = bcm_static_skb->last_allocated_index % STATIC_PKT_2PAGE_NUM; + bcm_static_skb->last_allocated_index++; + if (bcm_static_skb->skb_8k[index] && + bcm_static_skb->pkt_use[index] == 0) { + break; + } + } + + if (i < STATIC_PKT_2PAGE_NUM) { + bcm_static_skb->pkt_use[index] = 1; + skb = bcm_static_skb->skb_8k[index]; + skb->data = skb->head; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_set_tail_pointer(skb, PKT_HEADROOM_DEFAULT); +#else + skb->tail = skb->data + PKT_HEADROOM_DEFAULT; +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + skb->data += PKT_HEADROOM_DEFAULT; + skb->cloned = 0; + skb->priority = 0; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_set_tail_pointer(skb, len); +#else + skb->tail = skb->data + len; +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + skb->len = len; + skb->mac_len = PREALLOC_USED_MAGIC; + spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); + return skb; + } + } + + spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); + printk("%s: all static pkt in use!\n", __FUNCTION__); + return NULL; +#else + down(&bcm_static_skb->osl_pkt_sem); + + if (len <= DHD_SKB_1PAGE_BUFSIZE) { + for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) { + if (bcm_static_skb->skb_4k[i] && + bcm_static_skb->pkt_use[i] == 0) { + break; + } + } + + if (i != STATIC_PKT_1PAGE_NUM) { + bcm_static_skb->pkt_use[i] = 1; + + skb = bcm_static_skb->skb_4k[i]; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_set_tail_pointer(skb, len); +#else + skb->tail = skb->data + len; +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + skb->len = len; + + up(&bcm_static_skb->osl_pkt_sem); + return skb; + } + } + + if (len <= DHD_SKB_2PAGE_BUFSIZE) { + for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) { + if (bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM] && + bcm_static_skb->pkt_use[i] == 0) { + break; + } + } + + if ((i >= STATIC_PKT_1PAGE_NUM) && (i < STATIC_PKT_1_2PAGE_NUM)) { + bcm_static_skb->pkt_use[i] = 1; + skb = bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_set_tail_pointer(skb, len); +#else + skb->tail = skb->data + len; +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + skb->len = len; + + up(&bcm_static_skb->osl_pkt_sem); + return skb; + } + } + +#if defined(ENHANCED_STATIC_BUF) + if (bcm_static_skb->skb_16k && + bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] == 0) { + bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 1; + + skb = bcm_static_skb->skb_16k; +#ifdef NET_SKBUFF_DATA_USES_OFFSET + skb_set_tail_pointer(skb, len); +#else + skb->tail = skb->data + len; +#endif /* NET_SKBUFF_DATA_USES_OFFSET */ + skb->len = len; + + up(&bcm_static_skb->osl_pkt_sem); + return skb; + } +#endif /* ENHANCED_STATIC_BUF */ + + up(&bcm_static_skb->osl_pkt_sem); + printk("%s: all static pkt in use!\n", __FUNCTION__); + return linux_pktget(osh, len); +#endif /* DHD_USE_STATIC_CTRLBUF */ +} + +void +osl_pktfree_static(osl_t *osh, void *p, bool send) +{ + int i; +#ifdef DHD_USE_STATIC_CTRLBUF + struct sk_buff *skb = (struct sk_buff *)p; + unsigned long flags; +#endif /* DHD_USE_STATIC_CTRLBUF */ + + if (!p) { + return; + } + + if (!bcm_static_skb) { + linux_pktfree(osh, p, send); + return; + } + +#ifdef DHD_USE_STATIC_CTRLBUF + spin_lock_irqsave(&bcm_static_skb->osl_pkt_lock, flags); + + for (i = 0; i < STATIC_PKT_2PAGE_NUM; i++) { + if (p == bcm_static_skb->skb_8k[i]) { + if (bcm_static_skb->pkt_use[i] == 0) { + printk("%s: static pkt idx %d(%p) is double free\n", + __FUNCTION__, i, p); + } else { + bcm_static_skb->pkt_use[i] = 0; + } + + if (skb->mac_len != PREALLOC_USED_MAGIC) { + printk("%s: static pkt idx %d(%p) is not in used\n", + __FUNCTION__, i, p); + } + + skb->mac_len = PREALLOC_FREE_MAGIC; + spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); + return; + } + } + + spin_unlock_irqrestore(&bcm_static_skb->osl_pkt_lock, flags); + printk("%s: packet %p does not exist in the pool\n", __FUNCTION__, p); +#else + down(&bcm_static_skb->osl_pkt_sem); + for (i = 0; i < STATIC_PKT_1PAGE_NUM; i++) { + if (p == bcm_static_skb->skb_4k[i]) { + bcm_static_skb->pkt_use[i] = 0; + up(&bcm_static_skb->osl_pkt_sem); + return; + } + } + + for (i = STATIC_PKT_1PAGE_NUM; i < STATIC_PKT_1_2PAGE_NUM; i++) { + if (p == bcm_static_skb->skb_8k[i - STATIC_PKT_1PAGE_NUM]) { + bcm_static_skb->pkt_use[i] = 0; + up(&bcm_static_skb->osl_pkt_sem); + return; + } + } +#ifdef ENHANCED_STATIC_BUF + if (p == bcm_static_skb->skb_16k) { + bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM - 1] = 0; + up(&bcm_static_skb->osl_pkt_sem); + return; + } +#endif // endif + up(&bcm_static_skb->osl_pkt_sem); +#endif /* DHD_USE_STATIC_CTRLBUF */ + linux_pktfree(osh, p, send); +} +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + +/* Clone a packet. + * The pkttag contents are NOT cloned. + */ +#ifdef BCM_OBJECT_TRACE +void * +osl_pktdup(osl_t *osh, void *skb, int line, const char *caller) +#else +void * +osl_pktdup(osl_t *osh, void *skb) +#endif /* BCM_OBJECT_TRACE */ +{ + void * p; + + ASSERT(!PKTISCHAINED(skb)); + + /* clear the CTFBUF flag if set and map the rest of the buffer + * before cloning. + */ + PKTCTFMAP(osh, skb); + + if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) + return NULL; + + /* skb_clone copies skb->cb.. we don't want that */ + if (osh->pub.pkttag) + OSL_PKTTAG_CLEAR(p); + + /* Increment the packet counter */ + atomic_inc(&osh->cmn->pktalloced); +#ifdef BCM_OBJECT_TRACE + bcm_object_trace_opr(p, BCM_OBJDBG_ADD_PKT, caller, line); +#endif /* BCM_OBJECT_TRACE */ + + return (p); +} + +/* + * BINOSL selects the slightly slower function-call-based binary compatible osl. + */ + +uint +osl_pktalloced(osl_t *osh) +{ + if (atomic_read(&osh->cmn->refcount) == 1) + return (atomic_read(&osh->cmn->pktalloced)); + else + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) && defined(TSQ_MULTIPLIER) +#include +#include +void +osl_pkt_orphan_partial(struct sk_buff *skb) +{ + uint32 fraction; + static void *p_tcp_wfree = NULL; + + if (!skb->destructor || skb->destructor == sock_wfree) + return; + + if (unlikely(!p_tcp_wfree)) { + char sym[KSYM_SYMBOL_LEN]; + sprint_symbol(sym, (unsigned long)skb->destructor); + sym[9] = 0; + if (!strcmp(sym, "tcp_wfree")) + p_tcp_wfree = skb->destructor; + else + return; + } + + if (unlikely(skb->destructor != p_tcp_wfree || !skb->sk)) + return; + + /* abstract a certain portion of skb truesize from the socket + * sk_wmem_alloc to allow more skb can be allocated for this + * socket for better cusion meeting WiFi device requirement + */ + fraction = skb->truesize * (TSQ_MULTIPLIER - 1) / TSQ_MULTIPLIER; + skb->truesize -= fraction; + atomic_sub(fraction, &skb->sk->sk_wmem_alloc); +} +#endif /* LINUX_VERSION >= 3.6.0 && TSQ_MULTIPLIER */ diff --git a/drivers/net/wireless/bcmdhd_oo/pcie_core.c b/drivers/net/wireless/bcmdhd_oo/pcie_core.c index 63f955cb66937f3754fafbc2843aa09b2b737651..02bfa896a47f251eabeb1fb9d1d3c96f868bc74e 100644 --- a/drivers/net/wireless/bcmdhd_oo/pcie_core.c +++ b/drivers/net/wireless/bcmdhd_oo/pcie_core.c @@ -3,14 +3,14 @@ * Contains PCIe related functions that are shared between different driver models (e.g. firmware * builds, DHD builds, BMAC builds), in order to avoid code duplication. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -18,7 +18,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. @@ -26,7 +26,7 @@ * * <> * - * $Id: pcie_core.c 658668 2016-09-09 00:42:11Z $ + * $Id: pcie_core.c 735808 2017-12-12 11:35:02Z $ */ #include @@ -38,7 +38,6 @@ #include #include #include - #include "pcie_core.h" /* local prototypes */ @@ -49,8 +48,11 @@ #ifdef BCMDRIVER -void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs) +/* wd_mask/wd_val is only for chipc_corerev >= 65 */ +void pcie_watchdog_reset(osl_t *osh, si_t *sih, uint32 wd_mask, uint32 wd_val) { +/* To avoid hang on FPGA, donot reset watchdog */ +#ifndef BCMFPGA_HW uint32 val, i, lsc; uint16 cfg_offset[] = {PCIECFGREG_STATUS_CMD, PCIECFGREG_PM_CSR, PCIECFGREG_MSI_CAP, PCIECFGREG_MSI_ADDR_L, @@ -58,40 +60,53 @@ void pcie_watchdog_reset(osl_t *osh, si_t *sih, sbpcieregs_t *sbpcieregs) PCIECFGREG_LINK_STATUS_CTRL2, PCIECFGREG_RBAR_CTRL, PCIECFGREG_PML1_SUB_CTRL1, PCIECFGREG_REG_BAR2_CONFIG, PCIECFGREG_REG_BAR3_CONFIG}; - sbpcieregs_t *pcie = NULL; + sbpcieregs_t *pcieregs = NULL; uint32 origidx = si_coreidx(sih); /* Switch to PCIE2 core */ - pcie = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0); - BCM_REFERENCE(pcie); - ASSERT(pcie != NULL); + pcieregs = (sbpcieregs_t *)si_setcore(sih, PCIE2_CORE_ID, 0); + BCM_REFERENCE(pcieregs); + ASSERT(pcieregs != NULL); /* Disable/restore ASPM Control to protect the watchdog reset */ - W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); - lsc = R_REG(osh, &sbpcieregs->configdata); + W_REG(osh, &pcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); + lsc = R_REG(osh, &pcieregs->configdata); val = lsc & (~PCIE_ASPM_ENAB); - W_REG(osh, &sbpcieregs->configdata, val); - - si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4); - OSL_DELAY(100000); + W_REG(osh, &pcieregs->configdata, val); + + if (CCREV(sih->ccrev) >= 65) { + si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), wd_mask, wd_val); + si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), WD_COUNTER_MASK, 4); +#ifdef BCMQT_HW + OSL_DELAY(2000 * 4000); +#else + OSL_DELAY(2000); /* 2 ms */ +#endif // endif + val = si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, intstatus), 0, 0); + si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, intstatus), + wd_mask, val); + } else { + si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, 4); + OSL_DELAY(100000); + } - W_REG(osh, &sbpcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); - W_REG(osh, &sbpcieregs->configdata, lsc); + W_REG(osh, &pcieregs->configaddr, PCIECFGREG_LINK_STATUS_CTRL); + W_REG(osh, &pcieregs->configdata, lsc); if (sih->buscorerev <= 13) { /* Write configuration registers back to the shadow registers * cause shadow registers are cleared out after watchdog reset. */ for (i = 0; i < ARRAYSIZE(cfg_offset); i++) { - W_REG(osh, &sbpcieregs->configaddr, cfg_offset[i]); - val = R_REG(osh, &sbpcieregs->configdata); - W_REG(osh, &sbpcieregs->configdata, val); + W_REG(osh, &pcieregs->configaddr, cfg_offset[i]); + val = R_REG(osh, &pcieregs->configdata); + W_REG(osh, &pcieregs->configdata, val); } } si_setcoreidx(sih, origidx); +#endif /* BCMFPGA_HW */ } - /* CRWLPCIEGEN2-117 pcie_pipe_Iddq should be controlled * by the L12 state from MAC to save power by putting the * SerDes analog in IDDQ mode @@ -132,4 +147,5 @@ void pcie_set_trefup_time_100us(si_t *sih) si_corereg(sih, sih->buscoreidx, OFFSETOF(sbpcieregs_t, configdata), PCIE_PMCR_REFEXT_MASK, PCIE_PMCR_REFEXT_100US); } + #endif /* BCMDRIVER */ diff --git a/drivers/net/wireless/bcmdhd_oo/sbutils.c b/drivers/net/wireless/bcmdhd_oo/sbutils.c index 975ee6afaf08f45ad61d2799c41148818f9b4626..1a3253ac1bda868ef48f6a09945073e3b2f12c69 100644 --- a/drivers/net/wireless/bcmdhd_oo/sbutils.c +++ b/drivers/net/wireless/bcmdhd_oo/sbutils.c @@ -2,14 +2,14 @@ * Misc utility routines for accessing chip-specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: sbutils.c 599296 2015-11-13 06:36:13Z $ + * $Id: sbutils.c 700323 2017-05-18 16:12:11Z $ */ #include @@ -42,11 +42,10 @@ #include "siutils_priv.h" - /* local prototypes */ static uint _sb_coreidx(si_info_t *sii, uint32 sba); static uint _sb_scan(si_info_t *sii, uint32 sba, volatile void *regs, uint bus, uint32 sbba, - uint ncores); + uint ncores, uint devid); static uint32 _sb_coresba(si_info_t *sii); static volatile void *_sb_setcoreidx(si_info_t *sii, uint coreidx); #define SET_SBREG(sii, r, mask, val) \ @@ -68,7 +67,6 @@ sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr) uint8 tmp; uint32 val, intr_val = 0; - /* * compact flash only has 11 bits address, while we needs 12 bits address. * MEM_SEG will be OR'd with other 11 bits address in hardware, @@ -100,7 +98,6 @@ sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v) volatile uint32 dummy; uint32 intr_val = 0; - /* * compact flash only has 11 bits address, while we needs 12 bits address. * MEM_SEG will be OR'd with other 11 bits address in hardware, @@ -211,7 +208,6 @@ _sb_coresba(si_info_t *sii) { uint32 sbaddr; - switch (BUSTYPE(sii->pub.bustype)) { case SI_BUS: { sbconfig_t *sb = REGS2SB(sii->curmap); @@ -239,8 +235,7 @@ _sb_coresba(si_info_t *sii) case SDIO_BUS: sbaddr = (uint32)(uintptr)sii->curmap; break; -#endif - +#endif // endif default: sbaddr = BADCOREADDR; @@ -537,7 +532,7 @@ sb_corereg_addr(si_t *sih, uint coreidx, uint regoff) #define SB_MAXBUSES 2 static uint _sb_scan(si_info_t *sii, uint32 sba, volatile void *regs, uint bus, - uint32 sbba, uint numcores) + uint32 sbba, uint numcores, uint devid) { uint next; uint ncc = 0; @@ -605,15 +600,15 @@ _sb_scan(si_info_t *sii, uint32 sba, volatile void *regs, uint bus, sii->numcores = next + 1; - if ((nsbba & 0xfff00000) != SI_ENUM_BASE) + if ((nsbba & 0xfff00000) != si_enum_base(devid)) continue; nsbba &= 0xfffff000; if (_sb_coreidx(sii, nsbba) != BADIDX) continue; nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16; - nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc); - if (sbba == SI_ENUM_BASE) + nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc, devid); + if (sbba == si_enum_base(devid)) numcores -= nsbcc; ncc += nsbcc; } @@ -643,8 +638,8 @@ sb_scan(si_t *sih, volatile void *regs, uint devid) */ origsba = _sb_coresba(sii); - /* scan all SB(s) starting from SI_ENUM_BASE */ - sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1); + /* scan all SB(s) starting from SI_ENUM_BASE_DEFAULT */ + sii->numcores = _sb_scan(sii, origsba, regs, 0, si_enum_base(devid), 1, devid); } /* @@ -720,7 +715,6 @@ _sb_setcoreidx(si_info_t *sii, uint coreidx) break; #endif /* BCMSDIO */ - default: ASSERT(0); regs = NULL; @@ -800,7 +794,6 @@ sb_addrspacesize(si_t *sih, uint asidx) return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx)))); } - /* do buffered registers update */ void sb_commit(si_t *sih) @@ -972,7 +965,6 @@ sb_set_initiator_to(si_t *sih, uint32 to, uint idx) uint32 tmp, ret = 0xffffffff; sbconfig_t *sb; - if ((to & ~TO_MASK) != 0) return ret; @@ -988,7 +980,7 @@ sb_set_initiator_to(si_t *sih, uint32 to, uint idx) case PCMCIA_BUS: #ifdef BCMSDIO case SDIO_BUS: -#endif +#endif // endif idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0); break; case SI_BUS: @@ -1098,4 +1090,4 @@ sb_dumpregs(si_t *sih, struct bcmstrbuf *b) sb_setcoreidx(sih, origidx); INTR_RESTORE(sii, intr_val); } -#endif +#endif // endif diff --git a/drivers/net/wireless/bcmdhd_oo/siutils.c b/drivers/net/wireless/bcmdhd_oo/siutils.c index f47cd07f652a70c4e703cc40013b8c48da6aeed1..7fb5ccc7ea7af06358e6f62478c1f3e7606b8222 100644 --- a/drivers/net/wireless/bcmdhd_oo/siutils.c +++ b/drivers/net/wireless/bcmdhd_oo/siutils.c @@ -2,14 +2,14 @@ * Misc utility routines for accessing chip-specific features * of the SiliconBackplane-based Broadcom chips. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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 @@ -17,7 +17,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. @@ -25,7 +25,7 @@ * * <> * - * $Id: siutils.c 668442 2016-11-03 08:42:43Z $ + * $Id: siutils.c 729061 2017-10-30 08:41:27Z $ */ #include @@ -64,18 +64,29 @@ #ifdef HNDGCI #include #endif /* HNDGCI */ +#ifdef WLGCIMBHLR +#include +#endif /* WLGCIMBHLR */ #ifdef BCMULP #include #endif /* BCMULP */ +#include +#include #include "siutils_priv.h" #ifdef SECI_UART /* Defines the set of GPIOs to be used for SECI UART if not specified in NVRAM */ +/* For further details on each ppin functionality please refer to PINMUX table in + * Top level architecture of BCMXXXX Chip + */ +#define DEFAULT_SECI_UART_PINMUX 0x08090a0b #define DEFAULT_SECI_UART_PINMUX_43430 0x0102 static bool force_seci_clk = 0; #endif /* SECI_UART */ +#define XTAL_FREQ_26000KHZ 26000 + /** * A set of PMU registers is clocked in the ILP domain, which has an implication on register write * behavior: if such a register is written, it takes multiple ILP clocks for the PMU block to absorb @@ -93,6 +104,18 @@ static bool force_seci_clk = 0; #define GCI_FEM_CTRL_WAR 0x11111111 +#ifndef AXI_TO_VAL +#define AXI_TO_VAL 19 +#endif /* AXI_TO_VAL */ + +#ifndef AXI_TO_VAL_4347 +/* + * Increase BP timeout for fast clock and short PCIe timeouts + * New timeout: 2 ** 25 cycles + */ +#define AXI_TO_VAL_4347 25 +#endif /* AXI_TO_VAL_4347 */ + /* local prototypes */ static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, uint bustype, void *sdh, char **vars, uint *varsz); @@ -100,11 +123,8 @@ static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, uint *origidx, volatile void *regs); - static bool si_pmu_is_ilp_sensitive(uint32 idx, uint regoff); - - /* global variable to indicate reservation/release of gpio's */ static uint32 si_gpioreservation = 0; @@ -125,15 +145,12 @@ int do_4360_pcie2_war = 0; #ifdef BCMULP /* Variable to store boot_type: warm_boot/cold_boot/etc. */ static int boot_type = 0; -#endif +#endif // endif /* global kernel resource */ static si_info_t ksii; static si_cores_info_t ksii_cores_info; -static const char rstr_rmin[] = "rmin"; -static const char rstr_rmax[] = "rmax"; - /** * Allocate an si handle. This function may be called multiple times. * @@ -152,13 +169,15 @@ si_attach(uint devid, osl_t *osh, volatile void *regs, si_info_t *sii; si_cores_info_t *cores_info; /* alloc si_info_t */ - if ((sii = MALLOCZ(osh, sizeof (si_info_t))) == NULL) { + /* freed after ucode download for firmware builds */ + if ((sii = MALLOCZ_NOPERSIST(osh, sizeof(si_info_t))) == NULL) { SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); return (NULL); } /* alloc si_cores_info_t */ - if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, sizeof (si_cores_info_t))) == NULL) { + if ((cores_info = (si_cores_info_t *)MALLOCZ(osh, + sizeof(si_cores_info_t))) == NULL) { SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); MFREE(osh, sii, sizeof(si_info_t)); return (NULL); @@ -176,10 +195,25 @@ si_attach(uint devid, osl_t *osh, volatile void *regs, return (si_t *)sii; } - static uint32 wd_msticks; /**< watchdog timer ticks normalized to ms */ -/** generic kernel variant of si_attach() */ +/** Returns the backplane address of the chipcommon core for a particular chip */ +uint32 +si_enum_base(uint devid) +{ + // NIC/DHD build + switch (devid) { + case BCM7271_CHIP_ID: + case BCM7271_D11AC_ID: + case BCM7271_D11AC2G_ID: + case BCM7271_D11AC5G_ID: + return 0xF1800000; + } + + return SI_ENUM_BASE_DEFAULT; +} + +/** generic kernel variant of si_attach(). Is not called for Linux WLAN NIC builds. */ si_t * si_kattach(osl_t *osh) { @@ -188,12 +222,14 @@ si_kattach(osl_t *osh) if (!ksii_attached) { void *regs = NULL; - regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + const uint device_id = BCM4710_DEVICE_ID; // pick an arbitrary default device_id + + regs = REG_MAP(si_enum_base(device_id), SI_CORE_SIZE); // map physical to virtual cores_info = (si_cores_info_t *)&ksii_cores_info; ksii.cores_info = cores_info; ASSERT(osh); - if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, + if (si_doattach(&ksii, device_id, osh, regs, SI_BUS, NULL, osh != SI_OSH ? &(ksii.vars) : NULL, osh != SI_OSH ? &(ksii.varsz) : NULL) == NULL) { @@ -205,10 +241,8 @@ si_kattach(osl_t *osh) /* save ticks normalized to ms for si_watchdog_ms() */ if (PMUCTL_ENAB(&ksii.pub)) { - { - /* based on 32KHz ILP clock */ - wd_msticks = 32; - } + /* based on 32KHz ILP clock */ + wd_msticks = 32; } else { wd_msticks = ALP_CLOCK / 1000; } @@ -230,8 +264,7 @@ si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) if (BUSTYPE(bustype) == PCMCIA_BUS) sii->memseg = TRUE; - -#if defined(BCMSDIO) +#if defined(BCMSDIO) && !defined(BCMSDIOLITE) if (BUSTYPE(bustype) == SDIO_BUS) { int err; uint8 clkset; @@ -282,7 +315,7 @@ si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) OSL_DELAY(100000); } #endif /* BCMSPI */ -#endif /* BCMSDIO && BCMDONGLEHOST */ +#endif /* BCMSDIO && BCMDONGLEHOST && !BCMSDIOLITE */ return TRUE; } @@ -308,7 +341,7 @@ si_get_pmu_reg_addr(si_t *sih, uint32 offset) pmuaddr = (uint32)(uintptr)((volatile uint8*)pmu + offset); si_setcoreidx(sih, origidx); } else - pmuaddr = SI_ENUM_BASE + offset; + pmuaddr = SI_ENUM_BASE(sih) + offset; done: printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr); @@ -327,7 +360,7 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, #if defined(BCM_BACKPLANE_TIMEOUT) || defined(AXI_TIMEOUTS) /* first, enable backplane timeouts */ si_slave_wrapper_add(&sii->pub); -#endif +#endif // endif sii->curidx = 0; cc = si_setcoreidx(&sii->pub, SI_CC_IDX); @@ -394,26 +427,21 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, crev = si_corerev(&sii->pub); /* Display cores found */ - SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", - i, cid, crev, cores_info->coresba[i], cores_info->regs[i])); + SI_VMSG(("CORE[%d]: id 0x%x rev %d base 0x%x size:%x regs 0x%p\n", + i, cid, crev, sii->coresba[i], sii->coresba_size[i], + OSL_OBFUSCATE_BUF(sii->regs[i]))); if (BUSTYPE(bustype) == SI_BUS) { /* now look at the chipstatus register to figure the pacakge */ /* for SDIO but downloaded on PCIE dev */ +#ifdef BCMPCIEDEV_ENABLED if (cid == PCIE2_CORE_ID) { - if (BCM43602_CHIP(sii->pub.chip) || - (CHIPID(sii->pub.chip) == BCM4365_CHIP_ID) || - (CHIPID(sii->pub.chip) == BCM4347_CHIP_ID) || - (CHIPID(sii->pub.chip) == BCM4366_CHIP_ID) || - ((BCM4345_CHIP(sii->pub.chip) || - BCM4349_CHIP(sii->pub.chip)) && - CST4345_CHIPMODE_PCIE(sii->pub.chipst))) { pcieidx = i; pcierev = crev; pcie = TRUE; pcie_gen2 = TRUE; - } } +#endif // endif } else if (BUSTYPE(bustype) == PCI_BUS) { if (cid == PCI_CORE_ID) { @@ -450,7 +478,6 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, *origidx = i; } - #if defined(PCIE_FULL_DONGLE) if (pcie) { if (pcie_gen2) @@ -481,7 +508,6 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, SI_VMSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, sii->pub.buscorerev)); - #if defined(BCMSDIO) /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was * already running. @@ -499,10 +525,6 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, return TRUE; } - - - - uint16 si_chipid(si_t *sih) { @@ -558,8 +580,41 @@ si_check_boot_type(si_t *sih, osl_t *osh) } #endif /* BCMULP */ +#ifdef BCM_BACKPLANE_TIMEOUT +uint32 +si_clear_backplane_to_fast(void *sih, void *addr) +{ + si_t *_sih = DISCARD_QUAL(sih, si_t); + + if (CHIPTYPE(_sih->socitype) == SOCI_AI) { + return ai_clear_backplane_to_fast(_sih, addr); + } + + return 0; +} + +const si_axi_error_info_t * +si_get_axi_errlog_info(si_t *sih) +{ + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + return (const si_axi_error_info_t *)sih->err_info; + } + + return NULL; +} + +void +si_reset_axi_errlog_info(si_t *sih) +{ + if (sih->err_info) { + sih->err_info->count = 0; + } +} +#endif /* BCM_BACKPLANE_TIMEOUT */ + /** - * Allocate an si handle. This function may be called multiple times. + * Allocate an si handle. This function may be called multiple times. This function is called by + * both si_attach() and si_kattach(). * * vars - pointer to a to-be created pointer area for "environment" variables. Some callers of this * function set 'vars' to NULL. @@ -573,8 +628,9 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, chipcregs_t *cc; char *pvars = NULL; uint origidx; -#if !defined(_CFEZ_) || defined(CFG_WL) -#endif +#ifdef NVSRCX + char *sromvars; +#endif // endif ASSERT(GOODREGS(regs)); @@ -587,16 +643,19 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, sii->sdh = sdh; sii->osh = osh; sii->second_bar0win = ~0x0; + sih->enum_base = si_enum_base(devid); #if defined(BCM_BACKPLANE_TIMEOUT) sih->err_info = MALLOCZ(osh, sizeof(si_axi_error_info_t)); if (sih->err_info == NULL) { - SI_ERROR(("%s: %d bytes MALLOC FAILED", + SI_ERROR(("%s: %zu bytes MALLOC FAILED", __FUNCTION__, sizeof(si_axi_error_info_t))); - return NULL; } #endif /* BCM_BACKPLANE_TIMEOUT */ +#if defined(BCM_BACKPLANE_TIMEOUT) + osl_set_bpt_cb(osh, (void *)si_clear_backplane_to_fast, (void *)sih); +#endif // endif /* check to see if we are a si core mimic'ing a pci core */ if ((bustype == PCI_BUS) && @@ -609,26 +668,28 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, /* find Chipcommon address */ if (bustype == PCI_BUS) { savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) - savewin = SI_ENUM_BASE; - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); + if (!GOODCOREADDR(savewin, SI_ENUM_BASE(sih))) + savewin = SI_ENUM_BASE(sih); + OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE(sih)); if (!regs) return NULL; cc = (chipcregs_t *)regs; #ifdef BCMSDIO } else if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { cc = (chipcregs_t *)sii->curmap; -#endif +#endif // endif } else { - cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); + cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE(sih), SI_CORE_SIZE); } sih->bustype = bustype; +#ifdef BCMBUSTYPE if (bustype != BUSTYPE(bustype)) { SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", bustype, BUSTYPE(bustype))); return NULL; } +#endif // endif /* bus/core/clk setup for register access */ if (!si_buscore_prep(sii, bustype, devid, sdh)) { @@ -655,6 +716,12 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, si_chipid_fixup(sih); + if (CHIPID(sih->chip) == BCM43465_CHIP_ID) { + sih->chip = BCM4366_CHIP_ID; + } else if (CHIPID(sih->chip) == BCM43525_CHIP_ID) { + sih->chip = BCM4365_CHIP_ID; + } + sih->issim = IS_SIM(sih->chippkg); /* scan for cores */ @@ -662,20 +729,27 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || - (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) { + (CHIPTYPE(sii->pub.socitype) == SOCI_NAI) || + (CHIPTYPE(sii->pub.socitype) == SOCI_DVTBUS)) { + if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) SI_MSG(("Found chip type AI (0x%08x)\n", w)); - else + else if (CHIPTYPE(sii->pub.socitype) == SOCI_NAI) SI_MSG(("Found chip type NAI (0x%08x)\n", w)); + else + SI_MSG(("Found chip type DVT (0x%08x)\n", w)); /* pass chipc address instead of original core base */ - sii->axi_wrapper = (axi_wrapper_t *)MALLOCZ(sii->osh, - (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS)); + if (sii->osh) { + sii->axi_wrapper = (axi_wrapper_t *)MALLOCZ(sii->osh, + (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS)); - if (sii->axi_wrapper == NULL) { - SI_ERROR(("%s: %zu bytes MALLOC Failed", __FUNCTION__, - (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS))); - return NULL; + if (sii->axi_wrapper == NULL) { + SI_ERROR(("%s: %zu bytes MALLOC Failed", __FUNCTION__, + (sizeof(axi_wrapper_t) * SI_MAX_AXI_WRAPPERS))); + } + } else { + sii->axi_wrapper = NULL; } ai_scan(&sii->pub, (void *)(uintptr)cc, devid); @@ -699,11 +773,12 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, goto exit; } #ifdef BCMULP - si_check_boot_type(sih, osh); - - if (ulp_module_init(osh, sih) != BCME_OK) { - ULP_ERR(("%s: err in ulp_module_init\n", __FUNCTION__)); - goto exit; + if (BCMULP_ENAB()) { + si_check_boot_type(sih, osh); + if (ulp_module_init(osh, sih) != BCME_OK) { + ULP_ERR(("%s: err in ulp_module_init\n", __FUNCTION__)); + goto exit; + } } #endif /* BCMULP */ @@ -726,10 +801,28 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, OSL_DELAY(10); } + /* Set the clkdiv2 divisor bits (2:0) to 0x4 if srom is present */ + if (bustype == SI_BUS) { + uint32 clkdiv2, sromprsnt, capabilities, srom_supported; + capabilities = R_REG(osh, &cc->capabilities); + srom_supported = capabilities & SROM_SUPPORTED; + if (srom_supported) + { + sromprsnt = R_REG(osh, &cc->sromcontrol); + sromprsnt = sromprsnt & SROM_PRSNT_MASK; + if (sromprsnt) { + /* SROM clock come from backplane clock/div2. Must <= 1Mhz */ + clkdiv2 = (R_REG(osh, &cc->clkdiv2) & ~CLKD2_SROM); + clkdiv2 |= CLKD2_SROMDIV_192; + W_REG(osh, &cc->clkdiv2, clkdiv2); + } + } + } + if (bustype == PCI_BUS) { } -#endif +#endif // endif #ifdef BCM_SDRBL /* 4360 rom bootloader in PCIE case, if the SDR is enabled, But preotection is * not turned on, then we want to hold arm in reset. @@ -754,22 +847,17 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, pvars = NULL; BCM_REFERENCE(pvars); - if (!si_onetimeinit) { + { + sii->lhl_ps_mode = LHL_PS_MODE_0; + } + if (!si_onetimeinit) { if (CCREV(sii->pub.ccrev) >= 20) { uint32 gpiopullup = 0, gpiopulldown = 0; cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ASSERT(cc != NULL); - /* 4314/43142 has pin muxing, don't clear gpio bits */ - if ((CHIPID(sih->chip) == BCM4314_CHIP_ID) || - (CHIPID(sih->chip) == BCM43142_CHIP_ID)) { - gpiopullup |= 0x402e0; - gpiopulldown |= 0x20500; - } - - W_REG(osh, &cc->gpiopullup, gpiopullup); W_REG(osh, &cc->gpiopulldown, gpiopulldown); si_setcoreidx(sih, origidx); @@ -780,11 +868,14 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs, /* clear any previous epidiag-induced target abort */ ASSERT(!si_taclear(sih, FALSE)); +#if defined(BCMPMU_STATS) && !defined(BCMPMU_STATS_DISABLED) + si_pmustatstimer_init(sih); +#endif /* BCMPMU_STATS */ #ifdef BOOTLOADER_CONSOLE_OUTPUT /* Enable console prints */ si_muxenab(sii, 3); -#endif +#endif // endif return (sii); @@ -801,7 +892,6 @@ si_detach(si_t *sih) si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; uint idx; - if (BUSTYPE(sih->bustype) == SI_BUS) for (idx = 0; idx < SI_MAXCORES; idx++) if (cores_info->regs[idx]) { @@ -809,7 +899,6 @@ si_detach(si_t *sih) cores_info->regs[idx] = NULL; } - #if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) if (cores_info != &ksii_cores_info) #endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ @@ -891,7 +980,9 @@ si_intflag(si_t *sih) if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_intflag(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return R_REG(sii->osh, ((uint32 *)(uintptr) (sii->oob_router + OOB_STATUSA))); else { @@ -905,7 +996,9 @@ si_flag(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_flag(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_flag(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_flag(sih); @@ -918,7 +1011,9 @@ si_flag(si_t *sih) uint si_flag_alt(si_t *sih) { - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_flag_alt(sih); else { ASSERT(0); @@ -931,7 +1026,9 @@ si_setint(si_t *sih, int siflag) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_setint(sih, siflag); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_setint(sih, siflag); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_setint(sih, siflag); @@ -994,7 +1091,9 @@ si_corevendor(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corevendor(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corevendor(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corevendor(sih); @@ -1015,7 +1114,9 @@ si_corerev(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corerev(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corerev(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corerev(sih); @@ -1025,6 +1126,16 @@ si_corerev(si_t *sih) } } +uint +si_corerev_minor(si_t *sih) +{ + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + return ai_corerev_minor(sih); + } else { + return 0; + } +} + /* return index of coreid or BADIDX if not found */ uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit) @@ -1034,7 +1145,6 @@ si_findcoreidx(si_t *sih, uint coreid, uint coreunit) uint found; uint i; - found = 0; for (i = 0; i < sii->numcores; i++) @@ -1051,27 +1161,18 @@ si_findcoreidx(si_t *sih, uint coreid, uint coreunit) uint si_numcoreunits(si_t *sih, uint coreid) { - if ((CHIPID(sih->chip) == BCM4347_CHIP_ID) && - (CHIPREV(sih->chiprev) == 0)) { - /* - * 4347TC2 does not have Aux core. - * fixed to 1 here because EROM (using 4349 EROM) has two entries - */ - return 1; - } else { - si_info_t *sii = SI_INFO(sih); - si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; - uint found = 0; - uint i; + si_info_t *sii = SI_INFO(sih); + si_cores_info_t *cores_info = (si_cores_info_t *)sii->cores_info; + uint found = 0; + uint i; - for (i = 0; i < sii->numcores; i++) { - if (cores_info->coreid[i] == coreid) { - found++; - } + for (i = 0; i < sii->numcores; i++) { + if (cores_info->coreid[i] == coreid) { + found++; } - - return found; } + + return found; } /** return total D11 coreunits */ @@ -1128,7 +1229,6 @@ si_coreregs(si_t *sih) return (sii->curmap); } - /** * This function changes logical "focus" to the indicated core; * must be called with interrupts off. @@ -1145,7 +1245,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, idx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, idx); @@ -1160,7 +1262,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, coreidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, coreidx); @@ -1214,7 +1318,9 @@ si_numaddrspaces(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_numaddrspaces(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_numaddrspaces(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_numaddrspaces(sih); @@ -1224,30 +1330,47 @@ si_numaddrspaces(si_t *sih) } } +/* Return the address of the nth address space in the current core + * Arguments: + * sih : Pointer to struct si_t + * spidx : slave port index + * baidx : base address index + */ + uint32 -si_addrspace(si_t *sih, uint asidx) +si_addrspace(si_t *sih, uint spidx, uint baidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspace(sih, asidx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) - return ai_addrspace(sih, asidx); + return sb_addrspace(sih, baidx); + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + return ai_addrspace(sih, spidx, baidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) - return ub_addrspace(sih, asidx); + return ub_addrspace(sih, baidx); else { ASSERT(0); return 0; } } +/* Return the size of the nth address space in the current core + * Arguments: + * sih : Pointer to struct si_t + * spidx : slave port index + * baidx : base address index + */ uint32 -si_addrspacesize(si_t *sih, uint asidx) +si_addrspacesize(si_t *sih, uint spidx, uint baidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspacesize(sih, asidx); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) - return ai_addrspacesize(sih, asidx); + return sb_addrspacesize(sih, baidx); + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) + return ai_addrspacesize(sih, spidx, baidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) - return ub_addrspacesize(sih, asidx); + return ub_addrspacesize(sih, baidx); else { ASSERT(0); return 0; @@ -1258,7 +1381,9 @@ void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) { /* Only supported for SOCI_AI */ - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_coreaddrspaceX(sih, asidx, addr, size); else *size = 0; @@ -1269,7 +1394,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (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); @@ -1284,7 +1411,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (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); @@ -1297,7 +1426,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (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); @@ -1312,7 +1443,9 @@ si_commit(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_commit(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI || CHIPTYPE(sih->socitype) == SOCI_NAI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ; else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ; @@ -1326,7 +1459,9 @@ si_iscoreup(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_iscoreup(sih); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_iscoreup(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_iscoreup(sih); @@ -1340,7 +1475,9 @@ uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) { /* only for AI back plane chips */ - if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return (ai_wrap_reg(sih, offset, mask, val)); return 0; } @@ -1383,7 +1520,7 @@ si_invalidate_second_bar0win(si_t *sih) sii->second_bar0win = ~0x0; } -uint +int si_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read) { volatile uint32 *r = NULL; @@ -1452,7 +1589,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (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); @@ -1508,7 +1647,9 @@ si_corereg_addr(si_t *sih, uint coreidx, uint regoff) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corereg_addr(sih, coreidx, regoff); - else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corereg_addr(sih, coreidx, regoff); else { return 0; @@ -1520,7 +1661,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_disable(sih, bits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_disable(sih, bits); @@ -1531,7 +1674,9 @@ 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) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_reset(sih, bits, resetbits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_reset(sih, bits, resetbits); @@ -1568,25 +1713,28 @@ si_num_slaveports(si_t *sih, uint coreid) uint idx = si_findcoreidx(sih, coreid, 0); uint num = 0; - if ((CHIPTYPE(sih->socitype) == SOCI_AI)) + if (CHIPTYPE(sih->socitype) == SOCI_AI) { num = ai_num_slaveports(sih, idx); + } return num; } uint32 -si_get_slaveport_addr(si_t *sih, uint asidx, uint core_id, uint coreunit) +si_get_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint core_id, uint coreunit) { si_info_t *sii = SI_INFO(sih); uint origidx = sii->curidx; uint32 addr = 0x0; - if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))) + if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI))) goto done; si_setcore(sih, core_id, coreunit); - addr = ai_addrspace(sih, asidx); + addr = ai_addrspace(sih, spidx, baidx); si_setcoreidx(sih, origidx); @@ -1595,18 +1743,20 @@ done: } uint32 -si_get_d11_slaveport_addr(si_t *sih, uint asidx, uint coreunit) +si_get_d11_slaveport_addr(si_t *sih, uint spidx, uint baidx, uint coreunit) { si_info_t *sii = SI_INFO(sih); uint origidx = sii->curidx; uint32 addr = 0x0; - if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI))) + if (!((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS) || + (CHIPTYPE(sih->socitype) == SOCI_NAI))) goto done; si_setcore(sih, D11_CORE_ID, coreunit); - addr = ai_addrspace(sih, asidx); + addr = ai_addrspace(sih, spidx, baidx); si_setcoreidx(sih, origidx); @@ -1638,7 +1788,6 @@ divide_clock(uint32 clock, uint32 div) return div ? clock / div : 0; } - /** calculate the speed the SI would run at given a set of clockcontrol values */ uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m) @@ -1781,13 +1930,27 @@ si_chip_hostif(si_t *sih) else if (CST4349_CHIPMODE_PCIE(sih->chipst)) hosti = CHIP_HOSTIF_PCIEMODE; break; - case BCM4347_CHIP_ID: + case BCM4364_CHIP_ID: + if (CST4364_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4364_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; + case BCM4373_CHIP_ID: + if (CST4373_CHIPMODE_USB20D(sih->chipst)) + hosti = CHIP_HOSTIF_USBMODE; + else if (CST4373_CHIPMODE_SDIOD(sih->chipst)) + hosti = CHIP_HOSTIF_SDIOMODE; + else if (CST4373_CHIPMODE_PCIE(sih->chipst)) + hosti = CHIP_HOSTIF_PCIEMODE; + break; + + case BCM4347_CHIP_GRPID: if (CST4347_CHIPMODE_SDIOD(sih->chipst)) hosti = CHIP_HOSTIF_SDIOMODE; else if (CST4347_CHIPMODE_PCIE(sih->chipst)) hosti = CHIP_HOSTIF_PCIEMODE; break; - case BCM4350_CHIP_ID: case BCM4354_CHIP_ID: case BCM43556_CHIP_ID: @@ -1816,7 +1979,6 @@ si_chip_hostif(si_t *sih) return hosti; } - /** set chip watchdog reset timer to fire in 'ticks' */ void si_watchdog(si_t *sih, uint ticks) @@ -1824,9 +1986,8 @@ si_watchdog(si_t *sih, uint ticks) uint nb, maxt; uint pmu_wdt = 1; - if (PMUCTL_ENAB(sih) && pmu_wdt) { - nb = (CCREV(sih->ccrev) < 26) ? 16 : ((CCREV(sih->ccrev) >= 37) ? 32 : 24); + nb = (CCREV(sih->ccrev) < 26) ? 16 : ((CCREV(sih->ccrev) >= 37) ? 32 : 24); /* The mips compiler uses the sllv instruction, * so we specially handle the 32-bit case. */ @@ -1847,7 +2008,6 @@ si_watchdog(si_t *sih, uint ticks) SPINWAIT((PMU_REG(sih, pmustatus, 0, 0) & PST_ILPFASTLPO), PMU_MAX_TRANSITION_DLY); } - pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks); } else { maxt = (1 << 28) - 1; @@ -1876,8 +2036,6 @@ si_taclear(si_t *sih, bool details) return FALSE; } - - /** return the slow clock source - LPO, XTAL, or PCI */ static uint si_slowclk_src(si_info_t *sii) @@ -2001,7 +2159,6 @@ si_clkctl_init(si_t *sih) si_setcoreidx(sih, origidx); } - /** change logical "focus" to the gpio core for optimized access */ volatile void * si_gpiosetcore(si_t *sih) @@ -2677,7 +2834,6 @@ done: return memsize; } - /** Return the TCM-RAM size of the ARMCR4 core. */ uint32 si_tcm_size(si_t *sih) @@ -2769,10 +2925,6 @@ si_socram_srmem_size(si_t *sih) uint32 coreinfo; uint memsize = 0; - if ((CHIPID(sih->chip) == BCM4334_CHIP_ID) && (CHIPREV(sih->chiprev) < 2)) { - return (32 * 1024); - } - if (CHIPID(sih->chip) == BCM43430_CHIP_ID || CHIPID(sih->chip) == BCM43018_CHIP_ID) { return (64 * 1024); @@ -2814,7 +2966,6 @@ done: return memsize; } - #if !defined(_CFEZ_) || defined(CFG_WL) void si_btcgpiowar(si_t *sih) @@ -2846,42 +2997,6 @@ si_btcgpiowar(si_t *sih) INTR_RESTORE(sii, intr_val); } -void -si_chipcontrl_btshd0_4331(si_t *sih, bool on) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx; - uint32 val; - uint intr_val = 0; - - INTR_OFF(sii, intr_val); - - origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - val = R_REG(sii->osh, &cc->chipcontrol); - - /* bt_shd0 controls are same for 4331 chiprevs 0 and 1, packages 12x9 and 12x12 */ - if (on) { - /* Enable bt_shd0 on gpio4: */ - val |= (CCTRL4331_BT_SHD0_ON_GPIO4); - W_REG(sii->osh, &cc->chipcontrol, val); - } else { - val &= ~(CCTRL4331_BT_SHD0_ON_GPIO4); - W_REG(sii->osh, &cc->chipcontrol, val); - } - - /* restore the original index */ - si_setcoreidx(sih, origidx); - - INTR_RESTORE(sii, intr_val); -} - void si_chipcontrl_restore(si_t *sih, uint32 val) { @@ -2914,42 +3029,6 @@ si_chipcontrl_read(si_t *sih) return val; } -void -si_chipcontrl_epa4331(si_t *sih, bool on) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - uint32 val; - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - val = R_REG(sii->osh, &cc->chipcontrol); - - if (on) { - if (sih->chippkg == 9 || sih->chippkg == 0xb) { - val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); - /* Ext PA Controls for 4331 12x9 Package */ - W_REG(sii->osh, &cc->chipcontrol, val); - } else { - /* Ext PA Controls for 4331 12x12 Package */ - if (CHIPREV(sih->chiprev) > 0) { - W_REG(sii->osh, &cc->chipcontrol, val | - (CCTRL4331_EXTPA_EN) | (CCTRL4331_EXTPA_EN2)); - } else { - W_REG(sii->osh, &cc->chipcontrol, val | (CCTRL4331_EXTPA_EN)); - } - } - } else { - val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_EN2 | CCTRL4331_EXTPA_ON_GPIO2_5); - W_REG(sii->osh, &cc->chipcontrol, val); - } - - si_setcoreidx(sih, origidx); -} - /** switch muxed pins, on: SROM, off: FEMCTRL. Called for a family of ac chips, not just 4360. */ void si_chipcontrl_srom4360(si_t *sih, bool on) @@ -2979,125 +3058,41 @@ si_chipcontrl_srom4360(si_t *sih, bool on) si_setcoreidx(sih, origidx); } +/** + * The SROM clock is derived from the backplane clock. 4365 (200Mhz) and 43684 (240Mhz) have a fast + * backplane clock that requires a higher-than-POR-default clock divisor ratio for the SROM clock. + */ void -si_clk_srom4365(si_t *sih) +si_srom_clk_set(si_t *sih) { si_info_t *sii = SI_INFO(sih); chipcregs_t *cc; uint origidx = si_coreidx(sih); uint32 val; + uint32 divisor = 1; if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); return; } - val = R_REG(sii->osh, &cc->clkdiv2); - W_REG(sii->osh, &cc->clkdiv2, ((val&~0xf) | 0x4)); - - si_setcoreidx(sih, origidx); -} - -void -si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) -{ - si_info_t *sii; - chipcregs_t *cc; - uint origidx; - uint32 val; - bool sel_chip; - - sel_chip = (CHIPID(sih->chip) == BCM4331_CHIP_ID) || - (CHIPID(sih->chip) == BCM43431_CHIP_ID); - sel_chip &= ((sih->chippkg == 9 || sih->chippkg == 0xb)); - - if (!sel_chip) - return; - - sii = SI_INFO(sih); - origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - val = R_REG(sii->osh, &cc->chipcontrol); - if (enter_wowl) { - val |= CCTRL4331_EXTPA_EN; - W_REG(sii->osh, &cc->chipcontrol, val); + val = R_REG(sii->osh, &cc->clkdiv2); + if (BCM4365_CHIP(sih->chip)) { + divisor = CLKD2_SROMDIV_192; /* divide 200 by 192 -> SPROM clock ~ 1.04Mhz */ } else { - val |= (CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); - W_REG(sii->osh, &cc->chipcontrol, val); - } - si_setcoreidx(sih, origidx); -} -#endif - -uint -si_pll_reset(si_t *sih) -{ - uint err = 0; - - return (err); -} - -/** Enable BT-COEX & Ex-PA for 4313 */ -void -si_epa_4313war(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; + ASSERT(0); } - /* EPA Fix */ - W_REG(sii->osh, &cc->gpiocontrol, - R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_EPA_EN_MASK); - + W_REG(sii->osh, &cc->clkdiv2, ((val & ~CLKD2_SROM) | divisor)); si_setcoreidx(sih, origidx); } - -void -si_clk_pmu_htavail_set(si_t *sih, bool set_clear) -{ -} +#endif // endif void si_pmu_avb_clk_set(si_t *sih, osl_t *osh, bool set_flag) { } -/** 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) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - W_REG(sii->osh, &cc->gpiocontrol, - R_REG(sii->osh, &cc->gpiocontrol) | GPIO_CTRL_5_6_EN_MASK); - - W_REG(sii->osh, &cc->gpioouten, - R_REG(sii->osh, &cc->gpioouten) | GPIO_CTRL_5_6_EN_MASK); - - si_setcoreidx(sih, origidx); -} void si_btc_enable_chipcontrol(si_t *sih) { @@ -3116,23 +3111,6 @@ si_btc_enable_chipcontrol(si_t *sih) si_setcoreidx(sih, origidx); } -void -si_btcombo_43228_war(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc; - uint origidx = si_coreidx(sih); - - if ((cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0)) == NULL) { - SI_ERROR(("%s: Failed to find CORE ID!\n", __FUNCTION__)); - return; - } - - W_REG(sii->osh, &cc->gpioouten, GPIO_CTRL_7_6_EN_MASK); - W_REG(sii->osh, &cc->gpioout, GPIO_OUT_7_EN_MASK); - - si_setcoreidx(sih, origidx); -} /** cache device removed state */ void si_set_device_removed(si_t *sih, bool status) @@ -3172,7 +3150,7 @@ si_is_warmboot(void) return (boot_type == WARM_BOOT); #else return FALSE; -#endif +#endif // endif } bool @@ -3200,23 +3178,6 @@ si_is_sprom_available(si_t *sih) case BCM43018_CHIP_ID: case BCM43430_CHIP_ID: return FALSE; - case BCM4336_CHIP_ID: - case BCM43362_CHIP_ID: - return (sih->chipst & CST4336_SPROM_PRESENT) != 0; - case BCM4330_CHIP_ID: - return (sih->chipst & CST4330_SPROM_PRESENT) != 0; - case BCM4313_CHIP_ID: - return (sih->chipst & CST4313_SPROM_PRESENT) != 0; - case BCM4331_CHIP_ID: - case BCM43431_CHIP_ID: - return (sih->chipst & CST4331_SPROM_PRESENT) != 0; - case BCM43239_CHIP_ID: - 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: CASE_BCM4345_CHIP: return ((sih->chipst & CST4335_SPROM_MASK) && @@ -3225,7 +3186,9 @@ si_is_sprom_available(si_t *sih) return (sih->chipst & CST4349_SPROM_PRESENT) != 0; case BCM53573_CHIP_GRPID: return FALSE; /* SPROM PRESENT is not defined for 53573 as of now */ - case BCM4347_CHIP_ID: + case BCM4364_CHIP_ID: + return (sih->chipst & CST4364_SPROM_PRESENT) != 0; + case BCM4347_CHIP_GRPID: return (sih->chipst & CST4347_SPROM_PRESENT) != 0; break; case BCM4350_CHIP_ID: @@ -3242,10 +3205,9 @@ si_is_sprom_available(si_t *sih) return (sih->chipst & CST43602_SPROM_PRESENT) != 0; case BCM43131_CHIP_ID: case BCM43217_CHIP_ID: - case BCM43227_CHIP_ID: - case BCM43228_CHIP_ID: case BCM43428_CHIP_ID: return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT; + case BCM4373_CHIP_ID: case BCM43012_CHIP_ID: return FALSE; default: @@ -3253,7 +3215,6 @@ si_is_sprom_available(si_t *sih) } } - uint32 si_get_sromctl(si_t *sih) { chipcregs_t *cc; @@ -3322,7 +3283,6 @@ si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 return ret_val; } - /* cleanup the timer from the host when ARM is been halted * without a chance for ARM cleanup its resources * If left not cleanup, Intr from a software timer can still @@ -3347,69 +3307,6 @@ si_pmu_rfldo(si_t *sih, bool on) { } - -#ifdef SURVIVE_PERST_ENAB -static uint32 -si_pcie_survive_perst(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - if (!PCIE(sii)) - return (0); - - return pcie_survive_perst(sii->pch, mask, val); -} - -static void -si_watchdog_reset(si_t *sih) -{ - uint32 i; - - /* issue a watchdog reset */ - pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, 2, 2); - /* do busy wait for 20ms */ - for (i = 0; i < 2000; i++) { - OSL_DELAY(10); - } -} -#endif /* SURVIVE_PERST_ENAB */ - -void -si_survive_perst_war(si_t *sih, bool reset, uint32 sperst_mask, uint32 sperst_val) -{ -#ifdef SURVIVE_PERST_ENAB - if (BUSTYPE(sih->bustype) != PCI_BUS) - return; - - if ((CHIPID(sih->chip) != BCM4360_CHIP_ID && CHIPID(sih->chip) != BCM4352_CHIP_ID) || - (CHIPREV(sih->chiprev) >= 4)) - return; - - if (reset) { - si_info_t *sii = SI_INFO(sih); - uint32 bar0win, bar0win_after; - - /* save the bar0win */ - bar0win = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - - si_watchdog_reset(sih); - - bar0win_after = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - if (bar0win_after != bar0win) { - SI_ERROR(("%s: bar0win before %08x, bar0win after %08x\n", - __FUNCTION__, bar0win, bar0win_after)); - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32), bar0win); - } - } - if (sperst_mask) { - /* enable survive perst */ - si_pcie_survive_perst(sih, sperst_mask, sperst_val); - } -#endif /* SURVIVE_PERST_ENAB */ -} - /* Caller of this function should make sure is on PCIE core * Used in pciedev.c. */ @@ -3417,7 +3314,10 @@ void si_pcie_disable_oobselltr(si_t *sih) { ASSERT(si_coreid(sih) == PCIE2_CORE_ID); - si_wrapperreg(sih, AI_OOBSELIND30, ~0, 0); + if (PCIECOREREV(sih->buscorerev) >= 23) + si_wrapperreg(sih, AI_OOBSELIND74, ~0, 0); + else + si_wrapperreg(sih, AI_OOBSELIND30, ~0, 0); } void @@ -3445,38 +3345,12 @@ si_pcie_prep_D3(si_t *sih, bool enter_D3) { } - -#ifdef BCM_BACKPLANE_TIMEOUT -uint32 -si_clear_backplane_to_fast(si_t *sih, void * addr) -{ - if (CHIPTYPE(sih->socitype) == SOCI_AI) { - return ai_clear_backplane_to_fast(sih, addr); - } - - return 0; -} - -const si_axi_error_info_t * si_get_axi_errlog_info(si_t * sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_AI) { - return (const si_axi_error_info_t *)sih->err_info; - } - - return NULL; -} - -void si_reset_axi_errlog_info(si_t * sih) -{ - sih->err_info->count = 0; -} -#endif /* BCM_BACKPLANE_TIMEOUT */ - #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) uint32 si_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wrap) { - if (CHIPTYPE(sih->socitype) == SOCI_AI) { + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) { return ai_clear_backplane_to_per_core(sih, coreid, coreunit, wrap); } @@ -3487,13 +3361,27 @@ si_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void * wra uint32 si_clear_backplane_to(si_t *sih) { - if (CHIPTYPE(sih->socitype) == SOCI_AI) { + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || + (CHIPTYPE(sih->socitype) == SOCI_DVTBUS)) { return ai_clear_backplane_to(sih); } return 0; } +void +si_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout_exp, uint32 cid) +{ +#if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) + /* Enable only for AXI */ + if (CHIPTYPE(sih->socitype) != SOCI_AI) { + return; + } + + ai_update_backplane_timeouts(sih, enable, timeout_exp, cid); +#endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ +} + /* * This routine adds the AXI timeouts for * chipcommon, pcie and ARM slave wrappers @@ -3502,8 +3390,11 @@ void si_slave_wrapper_add(si_t *sih) { #if defined(AXI_TIMEOUTS) || defined(BCM_BACKPLANE_TIMEOUT) + uint32 axi_to = 0; + /* Enable only for AXI */ - if (CHIPTYPE(sih->socitype) != SOCI_AI) { + if ((CHIPTYPE(sih->socitype) != SOCI_AI) && + (CHIPTYPE(sih->socitype) != SOCI_DVTBUS)) { return; } @@ -3523,18 +3414,30 @@ si_slave_wrapper_add(si_t *sih) ASSERT(wrapper_idx >= 0); /* all addresses valid for the chiprev under test */ } + if (BCM4347_CHIP(sih->chip)) { + axi_to = AXI_TO_VAL_4347; + } + else { + axi_to = AXI_TO_VAL; + } + /* All required slave wrappers are added in ai_scan */ - ai_enable_backplane_timeouts(sih); + ai_update_backplane_timeouts(sih, TRUE, axi_to, 0); + +#ifdef DISABLE_PCIE2_AXI_TIMEOUT + ai_update_backplane_timeouts(sih, FALSE, 0, PCIE_CORE_ID); + ai_update_backplane_timeouts(sih, FALSE, 0, PCIE2_CORE_ID); +#endif // endif + #endif /* AXI_TIMEOUTS || BCM_BACKPLANE_TIMEOUT */ -} +} void si_pll_sr_reinit(si_t *sih) { } - /* Programming d11 core oob settings for 4364 * WARs for HW4364-237 and HW4364-166 */ @@ -3578,48 +3481,70 @@ si_pll_closeloop(si_t *sih) } break; #endif /* SAVERESTORE */ + case BCM4347_CHIP_GRPID: + case BCM4369_CHIP_GRPID: + si_pmu_chipcontrol(sih, PMU_CHIPCTL1, + PMU_CC1_ENABLE_CLOSED_LOOP_MASK, PMU_CC1_ENABLE_CLOSED_LOOP); + break; default: /* any unsupported chip bail */ return; } -#endif -} - -void -si_update_macclk_mul_fact(si_t *sih, uint32 mul_fact) -{ - si_info_t *sii = SI_INFO(sih); - sii->macclk_mul_fact = mul_fact; -} - -uint32 -si_get_macclk_mul_fact(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - return sii->macclk_mul_fact; +#endif // endif } - #if defined(BCMSRPWR) && !defined(BCMSRPWR_DISABLED) bool _bcmsrpwr = TRUE; #else bool _bcmsrpwr = FALSE; -#endif +#endif // endif uint32 si_srpwr_request(si_t *sih, uint32 mask, uint32 val) { uint32 r, offset = OFFSETOF(chipcregs_t, powerctl); /* Same 0x1e8 per core */ uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx; - + uint32 mask2 = mask; + uint32 val2 = val; + volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih) + + (uintptr)offset); if (mask || val) { mask <<= SRPWR_REQON_SHIFT; val <<= SRPWR_REQON_SHIFT; - r = ((si_corereg(sih, cidx, offset, 0, 0) & ~mask) | val); - r = si_corereg(sih, cidx, offset, ~0, r); + /* Return if requested power request is already set */ + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + r = si_corereg(sih, cidx, offset, 0, 0); + } + + if ((r & mask) == val) { + return r; + } + + r = (r & ~mask) | val; + + if (BUSTYPE(sih->bustype) == SI_BUS) { + W_REG(OSH_NULL, fast_srpwr_addr, r); + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + r = si_corereg(sih, cidx, offset, ~0, r); + } + + if (val2) { + if ((r & (mask2 << SRPWR_STATUS_SHIFT)) == + (val2 << SRPWR_STATUS_SHIFT)) { + return r; + } + si_srpwr_stat_spinwait(sih, mask2, val2); + } } else { - r = si_corereg(sih, cidx, offset, 0, 0); + if (BUSTYPE(sih->bustype) == SI_BUS) { + r = R_REG(OSH_NULL, fast_srpwr_addr); + } else { + r = si_corereg(sih, cidx, offset, 0, 0); + } } return r; @@ -3630,6 +3555,8 @@ si_srpwr_stat_spinwait(si_t *sih, uint32 mask, uint32 val) { uint32 r, offset = OFFSETOF(chipcregs_t, powerctl); /* Same 0x1e8 per core */ uint cidx = (BUSTYPE(sih->bustype) == SI_BUS) ? SI_CC_IDX : sih->buscoreidx; + volatile uint32 *fast_srpwr_addr = (volatile uint32 *)((uintptr)SI_ENUM_BASE(sih) + + (uintptr)offset); ASSERT(mask); ASSERT(val); @@ -3638,11 +3565,18 @@ si_srpwr_stat_spinwait(si_t *sih, uint32 mask, uint32 val) mask <<= SRPWR_STATUS_SHIFT; val <<= SRPWR_STATUS_SHIFT; - SPINWAIT(((si_corereg(sih, cidx, offset, 0, 0) & mask) != val), - PMU_MAX_TRANSITION_DLY); - ASSERT((si_corereg(sih, cidx, offset, 0, 0) & mask) == val); + if (BUSTYPE(sih->bustype) == SI_BUS) { + SPINWAIT(((R_REG(OSH_NULL, fast_srpwr_addr) & mask) != val), + PMU_MAX_TRANSITION_DLY); + r = R_REG(OSH_NULL, fast_srpwr_addr) & mask; + ASSERT(r == val); + } else { + SPINWAIT(((si_corereg(sih, cidx, offset, 0, 0) & mask) != val), + PMU_MAX_TRANSITION_DLY); + r = si_corereg(sih, cidx, offset, 0, 0) & mask; + ASSERT(r == val); + } - r = si_corereg(sih, cidx, offset, 0, 0) & mask; r = (r >> SRPWR_STATUS_SHIFT) & SRPWR_DMN_ALL_MASK; return r; @@ -3739,3 +3673,10 @@ skip_cfg: return val; } + +uint8 +si_lhl_ps_mode(si_t *sih) +{ + si_info_t *sii = SI_INFO(sih); + return sii->lhl_ps_mode; +} diff --git a/drivers/net/wireless/bcmdhd_oo/siutils_priv.h b/drivers/net/wireless/bcmdhd_oo/siutils_priv.h index ad57e215ce041bcc6a9f14c14ae8f48fa983acf9..72735cc7cb4dcfdff89a844de3278853b429daa9 100644 --- a/drivers/net/wireless/bcmdhd_oo/siutils_priv.h +++ b/drivers/net/wireless/bcmdhd_oo/siutils_priv.h @@ -1,14 +1,14 @@ /* * Include file private to the SOC Interconnect support files. * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: siutils_priv.h 625739 2016-03-17 12:28:03Z $ + * $Id: siutils_priv.h 698933 2017-05-11 06:05:10Z $ */ #ifndef _siutils_priv_h_ @@ -34,7 +34,7 @@ #define SI_ERROR(args) printf args #else #define SI_ERROR(args) -#endif +#endif // endif #if defined(ENABLE_CORECAPTURE) @@ -46,14 +46,13 @@ #endif /* ENABLE_CORECAPTURE */ - #define SI_MSG(args) #ifdef BCMDBG_SI #define SI_VMSG(args) printf args #else #define SI_VMSG(args) -#endif +#endif // endif #define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) @@ -61,7 +60,6 @@ typedef uint32 (*si_intrsoff_t)(void *intr_arg); typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); typedef bool (*si_intrsenabled_t)(void *intr_arg); - #define SI_GPIO_MAX 16 typedef struct gci_gpio_item { @@ -90,9 +88,20 @@ typedef struct axi_wrapper { /* for some combo chips, BT side accesses chipcommon->0x190, as a 16 byte addr */ /* register at 0x19C doesn't exist, so error is logged at the slave wrapper */ #define BT_CC_SPROM_BADREG_LO 0x18000190 +#define BT_CC_SPROM_BADREG_SIZE 4 #define BT_CC_SPROM_BADREG_HI 0 -#define BCM4350_BT_AXI_ID 6 -#define BCM4345_BT_AXI_ID 6 +#define BCM4350_BT_AXI_ID 6 +#define BCM4345_BT_AXI_ID 6 +#define BCM4349_BT_AXI_ID 5 +#define BCM4364_BT_AXI_ID 5 + +/* for BT logging and memory dump, ignore failed access to BT memory */ +#define BCM4347_BT_ADDR_HI 0 +#define BCM4347_BT_ADDR_LO 0x19000000 /* BT address space */ +#define BCM4347_BT_SIZE 0x01000000 /* BT address space size */ +#define BCM4347_UNUSED_AXI_ID 0xffffffff +#define BCM4347_CC_AXI_ID 0 +#define BCM4347_PCIE_AXI_ID 1 typedef struct si_cores_info { volatile void *regs[SI_MAXCORES]; /* other regs va */ @@ -110,8 +119,14 @@ typedef struct si_cores_info { void *wrappers2[SI_MAXCORES]; /**< other cores wrapper va */ uint32 wrapba2[SI_MAXCORES]; /**< address of controlling wrapper */ + void *wrappers3[SI_MAXCORES]; /**< other cores wrapper va */ + uint32 wrapba3[SI_MAXCORES]; /**< address of controlling wrapper */ + uint32 cia[SI_MAXCORES]; /**< erom cia entry for each core */ uint32 cib[SI_MAXCORES]; /**< erom cia entry for each core */ + + uint32 csp2ba[SI_MAXCORES]; /**< Second slave port base addr 0 */ + uint32 csp2ba_size[SI_MAXCORES]; /**< Second slave port addr space size */ } si_cores_info_t; /** misc si info needed by some of the routines */ @@ -150,16 +165,15 @@ typedef struct si_info { uint num_br; /**< # discovered bridges */ uint32 br_wrapba[SI_MAXBR]; /**< address of bridge controlling wrapper */ uint32 xtalfreq; - uint32 macclk_mul_fact; /* Multiplication factor necessary to adjust MAC Clock - * during ULB Mode operation. One instance where this is used is configuring TSF L-frac - * register - */ + uint32 openloop_dco_code; /**< OPEN loop calibration dco code */ + uint8 spurmode; bool device_removed; uint axi_num_wrappers; axi_wrapper_t * axi_wrapper; + uint8 device_wake_opt; /* device_wake GPIO number */ + uint8 lhl_ps_mode; } si_info_t; - #define SI_INFO(sih) ((si_info_t *)(uintptr)sih) #define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ @@ -218,7 +232,7 @@ typedef struct si_info { #ifndef DEFAULT_GPIOTIMERVAL #define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) -#endif +#endif // endif /* Silicon Backplane externs */ extern void sb_scan(si_t *sih, volatile void *regs, uint devid); @@ -250,7 +264,7 @@ extern bool sb_taclear(si_t *sih, bool details); #if defined(BCMDBG_PHYDUMP) extern void sb_dumpregs(si_t *sih, struct bcmstrbuf *b); -#endif +#endif // endif /* Wake-on-wireless-LAN (WOWL) */ extern bool sb_pci_pmecap(si_t *sih); @@ -272,27 +286,30 @@ extern void ai_setint(si_t *sih, int siflag); extern uint ai_coreidx(si_t *sih); extern uint ai_corevendor(si_t *sih); extern uint ai_corerev(si_t *sih); +extern uint ai_corerev_minor(si_t *sih); extern volatile uint32 *ai_corereg_addr(si_t *sih, uint coreidx, uint regoff); extern bool ai_iscoreup(si_t *sih); extern volatile void *ai_setcoreidx(si_t *sih, uint coreidx); extern volatile void *ai_setcoreidx_2ndwrap(si_t *sih, uint coreidx); +extern volatile void *ai_setcoreidx_3rdwrap(si_t *sih, uint coreidx); extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); extern void ai_d11rsdb_core_reset(si_t *sih, uint32 bits, - uint32 resetbits, void *p, void *s); + uint32 resetbits, void *p, volatile void *s); extern void ai_core_disable(si_t *sih, uint32 bits); extern void ai_d11rsdb_core_disable(const si_info_t *sii, uint32 bits, aidmp_t *pmacai, aidmp_t *smacai); extern int ai_numaddrspaces(si_t *sih); -extern uint32 ai_addrspace(si_t *sih, uint asidx); -extern uint32 ai_addrspacesize(si_t *sih, uint asidx); +extern uint32 ai_addrspace(si_t *sih, uint spidx, uint baidx); +extern uint32 ai_addrspacesize(si_t *sih, uint spidx, uint baidx); extern void ai_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size); extern uint ai_wrap_reg(si_t *sih, uint32 offset, uint32 mask, uint32 val); -extern void ai_enable_backplane_timeouts(si_t *sih); +extern void ai_update_backplane_timeouts(si_t *sih, bool enable, uint32 timeout, uint32 cid); extern uint32 ai_clear_backplane_to(si_t *sih); +void ai_force_clocks(si_t *sih, uint clock_state); extern uint ai_num_slaveports(si_t *sih, uint coreidx); #ifdef BCM_BACKPLANE_TIMEOUT @@ -305,10 +322,13 @@ extern uint32 ai_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreun #if defined(BCMDBG_PHYDUMP) extern void ai_dumpregs(si_t *sih, struct bcmstrbuf *b); -#endif +#endif // endif extern uint32 ai_wrapper_dump_buf_size(si_t *sih); extern uint32 ai_wrapper_dump_binary(si_t *sih, uchar *p); +extern bool ai_check_enable_backplane_log(si_t *sih); +extern uint32 ai_wrapper_dump_last_timeout(si_t *sih, uint32 *error, uint32 *core, uint32 *ba, + uchar *p); #define ub_scan(a, b, c) do {} while (0) #define ub_flag(a) (0) diff --git a/drivers/net/wireless/bcmdhd_oo/wl_android.c b/drivers/net/wireless/bcmdhd_oo/wl_android.c index fa692b71de3857befec6be464c8c83cc13c67fb2..3c18d9da8eecefe29b185badea101612a0b9707f 100644 --- a/drivers/net/wireless/bcmdhd_oo/wl_android.c +++ b/drivers/net/wireless/bcmdhd_oo/wl_android.c @@ -1,14 +1,14 @@ /* * Linux cfg80211 driver - Android related functions * - * Copyright (C) 1999-2017, Broadcom Corporation - * + * Copyright (C) 1999-2018, Broadcom. + * * 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. @@ -24,7 +24,7 @@ * * <> * - * $Id: wl_android.c 732190 2017-11-16 04:30:08Z $ + * $Id: wl_android.c 738149 2017-12-27 07:54:37Z $ */ #include @@ -32,11 +32,10 @@ #include #ifdef CONFIG_COMPAT #include -#endif +#endif // endif #include #include -#include #include #include #include @@ -47,25 +46,25 @@ #include #ifdef PNO_SUPPORT #include -#endif +#endif // endif #ifdef BCMSDIO #include -#endif +#endif // endif #ifdef WL_CFG80211 #include -#endif +#endif // endif +#ifdef WL_NAN +#include +#endif /* WL_NAN */ #ifdef DHDTCPACK_SUPPRESS #include #endif /* DHDTCPACK_SUPPRESS */ +#include #include +#include #ifdef DHD_PKT_LOGGING #include #endif /* DHD_PKT_LOGGING */ - -#if defined(STAT_REPORT) -#include -#endif /* STAT_REPORT */ - /* * Android private command strings, PLEASE define new private commands here * so they can be updated easily in the future (if needed) @@ -105,11 +104,10 @@ #define CMD_SETROAMMODE "SETROAMMODE" #define CMD_SETIBSSBEACONOUIDATA "SETIBSSBEACONOUIDATA" #define CMD_MIRACAST "MIRACAST" +#ifdef WL_NAN +#define CMD_NAN "NAN_" +#endif /* WL_NAN */ #define CMD_COUNTRY_DELIMITER "/" -#ifdef WL11ULB -#define CMD_ULB_MODE "ULB_MODE" -#define CMD_ULB_BW "ULB_BW" -#endif /* WL11ULB */ #if defined(WL_SUPPORT_AUTO_CHANNEL) #define CMD_GET_BEST_CHANNELS "GET_BEST_CHANNELS" @@ -158,7 +156,7 @@ #define CCKM_KRK_LEN 16 #define CCKM_BTK_LEN 32 -#endif +#endif // endif #ifdef PNO_SUPPORT #define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" @@ -276,7 +274,7 @@ typedef struct android_wifi_af_params { #ifdef WLFBT #define CMD_GET_FTKEY "GET_FTKEY" -#endif +#endif // endif #ifdef WLAIBSS #define CMD_SETIBSSTXFAILEVENT "SETIBSSTXFAILEVENT" @@ -333,6 +331,14 @@ typedef struct android_wifi_af_params { #define CMD_MURX_BFE_CAP "MURX_BFE_CAP" +#ifdef SUPPORT_RSSI_SUM_REPORT +#define CMD_SET_RSSI_LOGGING "SET_RSSI_LOGGING" +#define CMD_GET_RSSI_LOGGING "GET_RSSI_LOGGING" +#define CMD_GET_RSSI_PER_ANT "GET_RSSI_PER_ANT" +#endif /* SUPPORT_RSSI_SUM_REPORT */ + +#define CMD_GET_SNR "GET_SNR" + #ifdef SUPPORT_AP_HIGHER_BEACONRATE #define CMD_SET_AP_BEACONRATE "SET_AP_BEACONRATE" #define CMD_GET_AP_BASICRATE "GET_AP_BASICRATE" @@ -344,14 +350,6 @@ typedef struct android_wifi_af_params { #define CMD_SET_AP_RPS_PARAMS "SET_AP_RPS_PARAMS" #endif /* SUPPORT_AP_RADIO_PWRSAVE */ -#ifdef SUPPORT_RSSI_SUM_REPORT -#define CMD_SET_RSSI_LOGGING "SET_RSSI_LOGGING" -#define CMD_GET_RSSI_LOGGING "GET_RSSI_LOGGING" -#define CMD_GET_RSSI_PER_ANT "GET_RSSI_PER_ANT" -#endif /* SUPPORT_RSSI_SUM_REPORT */ - -#define CMD_GET_SNR "GET_SNR" - /* miracast related definition */ #define MIRACAST_MODE_OFF 0 #define MIRACAST_MODE_SOURCE 1 @@ -359,15 +357,15 @@ typedef struct android_wifi_af_params { #ifndef MIRACAST_AMPDU_SIZE #define MIRACAST_AMPDU_SIZE 8 -#endif +#endif // endif #ifndef MIRACAST_MCHAN_ALGO #define MIRACAST_MCHAN_ALGO 1 -#endif +#endif // endif #ifndef MIRACAST_MCHAN_BW #define MIRACAST_MCHAN_BW 25 -#endif +#endif // endif #ifdef CONNECTION_STATISTICS #define CMD_GET_CONNECTION_STATS "GET_CONNECTION_STATS" @@ -392,14 +390,16 @@ struct connection_stats { #ifdef SUPPORT_LQCM #define CMD_SET_LQCM_ENABLE "SET_LQCM_ENABLE" #define CMD_GET_LQCM_REPORT "GET_LQCM_REPORT" -#endif +#endif // endif static LIST_HEAD(miracast_resume_list); static u8 miracast_cur_mode; #ifdef DHD_LOG_DUMP -#define CMD_NEW_DEBUG_PRINT_DUMP "DEBUG_DUMP" -extern void dhd_schedule_log_dump(dhd_pub_t *dhdp); +#define CMD_NEW_DEBUG_PRINT_DUMP "DEBUG_DUMP" +#define SUBCMD_UNWANTED "UNWANTED" +#define SUBCMD_DISCONNECTED "DISCONNECTED" +extern void dhd_schedule_log_dump(dhd_pub_t *dhdp, log_dump_type_t *type); extern int dhd_bus_mem_dump(dhd_pub_t *dhd); #endif /* DHD_LOG_DUMP */ @@ -433,6 +433,7 @@ struct io_cfg { (JOIN_PREF_WPA_TUPLE_SIZE * JOIN_PREF_MAX_WPA_TUPLES)) #endif /* BCMFW_ROAM_ENABLE */ +#define CMD_DEBUG_VERBOSE "DEBUG_VERBOSE" #ifdef WL_NATOE #define CMD_NATOE "NATOE" @@ -515,12 +516,12 @@ static const wl_natoe_sub_cmd_t natoe_cmd_list[] = { #define CMD_PKTLOG_FILTER_EXIST "PKTLOG_FILTER_EXIST" #define CMD_PKTLOG_MINMIZE_ENABLE "PKTLOG_MINMIZE_ENABLE" #define CMD_PKTLOG_MINMIZE_DISABLE "PKTLOG_MINMIZE_DISABLE" +#define CMD_PKTLOG_CHANGE_SIZE "PKTLOG_CHANGE_SIZE" #endif /* DHD_PKT_LOGGING */ -#if defined(STAT_REPORT) -#define CMD_STAT_REPORT_GET_START "STAT_REPORT_GET_START" -#define CMD_STAT_REPORT_GET_NEXT "STAT_REPORT_GET_NEXT" -#endif /* STAT_REPORT */ +#ifdef DHD_EVENT_LOG_FILTER +#define CMD_EWP_FILTER "EWP_FILTER" +#endif /* DHD_EVENT_LOG_FILTER */ #ifdef WL_GENL static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info); @@ -662,13 +663,14 @@ static int g_wifi_on = TRUE; #ifdef WLWFDS static int wl_android_set_wfds_hash( - struct net_device *dev, char *command, int total_len, bool enable) + struct net_device *dev, char *command, bool enable) { int error = 0; wl_p2p_wfds_hash_t *wfds_hash = NULL; char *smbuf = NULL; - smbuf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + smbuf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MAXLEN); if (smbuf == NULL) { DHD_ERROR(("%s: failed to allocated memory %d bytes\n", __FUNCTION__, WLC_IOCTL_MAXLEN)); @@ -690,8 +692,9 @@ static int wl_android_set_wfds_hash( DHD_ERROR(("%s: failed to %s, error=%d\n", __FUNCTION__, command, error)); } - if (smbuf) - kfree(smbuf); + if (smbuf) { + MFREE(cfg->osh, smbuf, WLC_IOCTL_MAXLEN); + } return error; } #endif /* WLWFDS */ @@ -741,12 +744,11 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_ DHD_TRACE(("%s: cmd:%s\n", __FUNCTION__, delim)); /* skip space from delim after finding char */ delim++; - if (!(bcm_ether_atoe((delim), &scbval.ea))) - { + if (!(bcm_ether_atoe((delim), &scbval.ea))) { DHD_ERROR(("%s:address err\n", __FUNCTION__)); return -1; } - scbval.val = htod32(0); + scbval.val = htod32(0); DHD_TRACE(("%s: address:"MACDBG, __FUNCTION__, MAC2STRDBG(scbval.ea.octet))); #ifdef WL_VIRTUAL_APSTA /* RSDB AP may have another virtual interface @@ -800,7 +802,7 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_ return bytes_written; } -static int wl_android_set_suspendopt(struct net_device *dev, char *command, int total_len) +static int wl_android_set_suspendopt(struct net_device *dev, char *command) { int suspend_flag; int ret_now; @@ -825,7 +827,7 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int return ret; } -static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len) +static int wl_android_set_suspendmode(struct net_device *dev, char *command) { int ret = 0; @@ -840,7 +842,7 @@ static int wl_android_set_suspendmode(struct net_device *dev, char *command, int DHD_INFO(("%s: Suspend Mode %d\n", __FUNCTION__, suspend_flag)); else DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); -#endif +#endif // endif return ret; } @@ -949,6 +951,7 @@ int wl_android_get_assoclist(struct net_device *dev, char *command, int total_le int error = 0; int bytes_written = 0; uint i; + int len = 0; char mac_buf[MAX_NUM_OF_ASSOCLIST * sizeof(struct ether_addr) + sizeof(uint)] = {0}; struct maclist *assoc_maclist = (struct maclist *)mac_buf; @@ -966,15 +969,25 @@ int wl_android_get_assoclist(struct net_device *dev, char *command, int total_le CMD_ASSOC_CLIENTS, assoc_maclist->count); for (i = 0; i < assoc_maclist->count; i++) { - bytes_written += snprintf(command + bytes_written, total_len, " " MACDBG, + len = snprintf(command + bytes_written, total_len - bytes_written, " " MACDBG, MAC2STRDBG(assoc_maclist->ea[i].octet)); + /* A return value of '(total_len - bytes_written)' or more means that the + * output was truncated + */ + if ((len > 0) && (len < (total_len - bytes_written))) { + bytes_written += len; + } else { + DHD_ERROR(("%s: Insufficient buffer %d, bytes_written %d\n", + __FUNCTION__, total_len, bytes_written)); + bytes_written = -1; + break; + } } return bytes_written; - } extern chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec); -static int wl_android_set_csa(struct net_device *dev, char *command, int total_len) +static int wl_android_set_csa(struct net_device *dev, char *command) { int error = 0; char smbuf[WLC_IOCTL_SMLEN]; @@ -1048,7 +1061,7 @@ static int wl_android_set_csa(struct net_device *dev, char *command, int total_l } static int -wl_android_set_max_dtim(struct net_device *dev, char *command, int total_len) +wl_android_set_max_dtim(struct net_device *dev, char *command) { int ret = 0; int dtim_flag; @@ -1087,7 +1100,7 @@ static bool wl_android_check_wbtext(struct net_device *dev) } static int wl_android_set_roam_trigger( - struct net_device *dev, char* command, int total_len) + struct net_device *dev, char* command) { int roam_trigger[2] = {0, 0}; int error; @@ -1125,7 +1138,7 @@ static int wl_android_get_roam_trigger( int chsp = {0}; chanspec_t chanspec; int i; - wl_roam_prof_band_t rp; + struct wl_roam_prof_band_v2 rp; char smbuf[WLC_IOCTL_SMLEN]; error = wldev_iovar_getint(dev, "chanspec", &chsp); @@ -1151,7 +1164,7 @@ static int wl_android_get_roam_trigger( WL_ERR(("failed to get roam profile (%d)\n", error)); return BCME_ERROR; } - memcpy(&rp, smbuf, sizeof(wl_roam_prof_band_t)); + memcpy(&rp, smbuf, sizeof(struct wl_roam_prof_band_v2)); for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) { if (rp.roam_prof[i].channel_usage == 0) { roam_trigger[0] = rp.roam_prof[i].roam_trigger; @@ -1179,7 +1192,7 @@ static int wl_android_get_roam_trigger( } int wl_android_set_roam_delta( - struct net_device *dev, char* command, int total_len) + struct net_device *dev, char* command) { int roam_delta[2]; @@ -1212,7 +1225,7 @@ static int wl_android_get_roam_delta( } int wl_android_set_roam_scan_period( - struct net_device *dev, char* command, int total_len) + struct net_device *dev, char* command) { int roam_scan_period = 0; @@ -1280,7 +1293,7 @@ static int wl_android_get_full_roam_scan_period( } int wl_android_set_country_rev( - struct net_device *dev, char* command, int total_len) + struct net_device *dev, char* command) { int error = 0; wl_country_t cspec = {{0}, 0, {0} }; @@ -1357,7 +1370,7 @@ int wl_android_get_roam_scan_control(struct net_device *dev, char *command, int return bytes_written; } -int wl_android_set_roam_scan_control(struct net_device *dev, char *command, int total_len) +int wl_android_set_roam_scan_control(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -1382,35 +1395,35 @@ int wl_android_get_roam_scan_channels(struct net_device *dev, char *command, int int bytes_written = 0; unsigned char channels[MAX_ROAM_CHANNEL] = {0}; int channel_cnt = 0; - char channel_info[10 + (MAX_ROAM_CHANNEL * 3)] = {0}; - int channel_info_len = 0; int i = 0; + int buf_avail, len; channel_cnt = get_roamscan_channel_list(dev, channels); - - channel_info_len += snprintf(&channel_info[channel_info_len], sizeof(channel_info), - "%d ", channel_cnt); + bytes_written = snprintf(command, total_len, "%s %d", + CMD_GETROAMSCANCHANNELS, channel_cnt); + buf_avail = total_len - bytes_written; for (i = 0; i < channel_cnt; i++) { - channel_info_len += snprintf(&channel_info[channel_info_len], sizeof(channel_info), - "%d ", channels[i]); - - if (channel_info_len > (sizeof(channel_info) - 10)) + /* A return value of 'buf_avail' or more means that the output was truncated */ + len = snprintf(command + bytes_written, buf_avail, " %d", channels[i]); + if (len >= buf_avail) { + WL_ERR(("%s: Insufficient memory, %d bytes\n", __FUNCTION__, total_len)); + bytes_written = -1; break; + } + /* 'buf_avail' decremented by number of bytes written */ + buf_avail -= len; + bytes_written += len; } - channel_info_len += snprintf(&channel_info[channel_info_len], sizeof(channel_info), - "%s", "\0"); - - bytes_written = snprintf(command, total_len, "%s %s", - CMD_GETROAMSCANCHANNELS, channel_info); + WL_INFORM(("%s: %s\n", __FUNCTION__, command)); return bytes_written; } -int wl_android_set_roam_scan_channels(struct net_device *dev, char *command, int total_len) +int wl_android_set_roam_scan_channels(struct net_device *dev, char *command) { int error = 0; unsigned char *p = (unsigned char *)(command + strlen(CMD_SETROAMSCANCHANNELS) + 1); - int ioctl_version = wl_cfg80211_get_ioctl_version(); - error = set_roamscan_channel_list(dev, p[0], &p[1], ioctl_version); + int get_ioctl_version = wl_cfg80211_get_ioctl_version(); + error = set_roamscan_channel_list(dev, p[0], &p[1], get_ioctl_version); if (error) { DHD_ERROR(("%s: Failed to set Scan Channels %d, error = %d\n", __FUNCTION__, p[0], error)); @@ -1438,7 +1451,7 @@ int wl_android_get_scan_channel_time(struct net_device *dev, char *command, int return bytes_written; } -int wl_android_set_scan_channel_time(struct net_device *dev, char *command, int total_len) +int wl_android_set_scan_channel_time(struct net_device *dev, char *command) { int error = 0; int time = 0; @@ -1460,7 +1473,8 @@ int wl_android_set_scan_channel_time(struct net_device *dev, char *command, int return 0; } -int wl_android_get_scan_unassoc_time(struct net_device *dev, char *command, int total_len) +int +wl_android_get_scan_unassoc_time(struct net_device *dev, char *command, int total_len) { int error = 0; int bytes_written = 0; @@ -1478,7 +1492,8 @@ int wl_android_get_scan_unassoc_time(struct net_device *dev, char *command, int return bytes_written; } -int wl_android_set_scan_unassoc_time(struct net_device *dev, char *command, int total_len) +int +wl_android_set_scan_unassoc_time(struct net_device *dev, char *command) { int error = 0; int time = 0; @@ -1500,7 +1515,8 @@ int wl_android_set_scan_unassoc_time(struct net_device *dev, char *command, int return 0; } -int wl_android_get_scan_passive_time(struct net_device *dev, char *command, int total_len) +int +wl_android_get_scan_passive_time(struct net_device *dev, char *command, int total_len) { int error = 0; int bytes_written = 0; @@ -1518,7 +1534,8 @@ int wl_android_get_scan_passive_time(struct net_device *dev, char *command, int return bytes_written; } -int wl_android_set_scan_passive_time(struct net_device *dev, char *command, int total_len) +int +wl_android_set_scan_passive_time(struct net_device *dev, char *command) { int error = 0; int time = 0; @@ -1557,7 +1574,7 @@ int wl_android_get_scan_home_time(struct net_device *dev, char *command, int tot return bytes_written; } -int wl_android_set_scan_home_time(struct net_device *dev, char *command, int total_len) +int wl_android_set_scan_home_time(struct net_device *dev, char *command) { int error = 0; int time = 0; @@ -1597,7 +1614,7 @@ int wl_android_get_scan_home_away_time(struct net_device *dev, char *command, in return bytes_written; } -int wl_android_set_scan_home_away_time(struct net_device *dev, char *command, int total_len) +int wl_android_set_scan_home_away_time(struct net_device *dev, char *command) { int error = 0; int time = 0; @@ -1636,7 +1653,7 @@ int wl_android_get_scan_nprobes(struct net_device *dev, char *command, int total return bytes_written; } -int wl_android_set_scan_nprobes(struct net_device *dev, char *command, int total_len) +int wl_android_set_scan_nprobes(struct net_device *dev, char *command) { int error = 0; int num = 0; @@ -1680,7 +1697,7 @@ int wl_android_get_scan_dfs_channel_mode(struct net_device *dev, char *command, return bytes_written; } -int wl_android_set_scan_dfs_channel_mode(struct net_device *dev, char *command, int total_len) +int wl_android_set_scan_dfs_channel_mode(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -1713,7 +1730,7 @@ int wl_android_set_scan_dfs_channel_mode(struct net_device *dev, char *command, #define JOINPREFFER_BUF_SIZE 12 static int -wl_android_set_join_prefer(struct net_device *dev, char *command, int total_len) +wl_android_set_join_prefer(struct net_device *dev, char *command) { int error = BCME_OK; char smbuf[WLC_IOCTL_SMLEN]; @@ -1779,6 +1796,13 @@ int wl_android_send_action_frame(struct net_device *dev, char *command, int tota char *smbuf = NULL; struct ether_addr tmp_bssid; int tmp_channel = 0; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + + if (total_len < + (strlen(CMD_SENDACTIONFRAME) + 1 + sizeof(android_wifi_af_params_t))) { + DHD_ERROR(("%s: Invalid parameters \n", __FUNCTION__)); + goto send_action_frame_out; + } params = (android_wifi_af_params_t *)(command + strlen(CMD_SENDACTIONFRAME) + 1); @@ -1788,16 +1812,15 @@ int wl_android_send_action_frame(struct net_device *dev, char *command, int tota goto send_action_frame_out; } - smbuf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + smbuf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MAXLEN); if (smbuf == NULL) { DHD_ERROR(("%s: failed to allocated memory %d bytes\n", __FUNCTION__, WLC_IOCTL_MAXLEN)); goto send_action_frame_out; } - af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL); - if (af_params == NULL) - { + af_params = (wl_af_params_t *)MALLOCZ(cfg->osh, WL_WIFI_AF_PARAMS_SIZE); + if (af_params == NULL) { DHD_ERROR(("%s: unable to allocate frame\n", __FUNCTION__)); goto send_action_frame_out; } @@ -1846,11 +1869,13 @@ int wl_android_send_action_frame(struct net_device *dev, char *command, int tota } send_action_frame_out: - if (af_params) - kfree(af_params); + if (af_params) { + MFREE(cfg->osh, af_params, WL_WIFI_AF_PARAMS_SIZE); + } - if (smbuf) - kfree(smbuf); + if (smbuf) { + MFREE(cfg->osh, smbuf, WLC_IOCTL_MAXLEN); + } if (error) return -1; @@ -1867,6 +1892,11 @@ int wl_android_reassoc(struct net_device *dev, char *command, int total_len) u32 params_size; wl_reassoc_params_t reassoc_params; + if (total_len < + (strlen(CMD_REASSOC) + 1 + sizeof(android_wifi_reassoc_params_t))) { + DHD_ERROR(("%s: Invalid parameters \n", __FUNCTION__)); + return -1; + } params = (android_wifi_reassoc_params_t *)(command + strlen(CMD_REASSOC) + 1); memset(&reassoc_params, 0, WL_REASSOC_PARAMS_FIXED_SIZE); @@ -1906,12 +1936,9 @@ int wl_android_reassoc(struct net_device *dev, char *command, int total_len) error = wldev_ioctl_set(dev, WLC_REASSOC, &reassoc_params, params_size); if (error) { DHD_ERROR(("%s: failed to reassoc, error=%d\n", __FUNCTION__, error)); - } - - if (error) return -1; - else - return 0; + } + return 0; } int wl_android_get_wes_mode(struct net_device *dev, char *command, int total_len) @@ -1926,7 +1953,7 @@ int wl_android_get_wes_mode(struct net_device *dev, char *command, int total_len return bytes_written; } -int wl_android_set_wes_mode(struct net_device *dev, char *command, int total_len) +int wl_android_set_wes_mode(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -1982,7 +2009,7 @@ int wl_android_get_okc_mode(struct net_device *dev, char *command, int total_len return bytes_written; } -int wl_android_set_okc_mode(struct net_device *dev, char *command, int total_len) +int wl_android_set_okc_mode(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -2009,8 +2036,12 @@ wl_android_set_pmk(struct net_device *dev, char *command, int total_len) char smbuf[WLC_IOCTL_SMLEN]; #ifdef OKC_DEBUG int i = 0; -#endif +#endif // endif + if (total_len < (strlen("SET_PMK ") + 32)) { + DHD_ERROR(("%s: Invalid argument\n", __FUNCTION__)); + 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); @@ -2023,12 +2054,12 @@ wl_android_set_pmk(struct net_device *dev, char *command, int total_len) DHD_ERROR(("%02X ", pmk[i])); DHD_ERROR(("\n")); -#endif +#endif // endif return error; } static int -wl_android_okc_enable(struct net_device *dev, char *command, int total_len) +wl_android_okc_enable(struct net_device *dev, char *command) { int error = 0; char okc_enable = 0; @@ -2062,7 +2093,7 @@ int wl_android_tdls_reset(struct net_device *dev) #endif /* WLTDLS */ #ifdef FCC_PWR_LIMIT_2G int -wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total_len) +wl_android_set_fcc_pwr_limit_2g(struct net_device *dev, char *command) { int error = 0; int enable = 0; @@ -2109,20 +2140,35 @@ wl_android_get_fcc_pwr_limit_2g(struct net_device *dev, char *command, int total s32 wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len) { - static char iovar_buf[WLC_IOCTL_MAXLEN]; int bytes_written = -1, ret = 0; char *pcmd = command; char *str; - sta_info_t *sta = NULL; - wl_cnt_wlc_t* wlc_cnt = NULL; + sta_info_v4_t *sta = NULL; + const wl_cnt_wlc_t* wlc_cnt = NULL; struct ether_addr mac; - + char *iovar_buf; /* Client information */ uint16 cap = 0; uint32 rxrtry = 0; uint32 rxmulti = 0; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); + +#ifdef BIGDATA_SOFTAP + void *data = NULL; + int get_bigdata_softap = FALSE; + wl_ap_sta_data_t *sta_data = NULL; + struct bcm_cfg80211 *bcm_cfg = wl_get_cfg(dev); +#endif /* BIGDATA_SOFTAP */ WL_DBG(("%s\n", command)); + + iovar_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN); + if (iovar_buf == NULL) { + DHD_ERROR(("%s: failed to allocated memory %d bytes\n", + __FUNCTION__, WLC_IOCTL_MAXLEN)); + goto error; + } + str = bcmstrtok(&pcmd, " ", NULL); if (str) { str = bcmstrtok(&pcmd, " ", NULL); @@ -2138,12 +2184,25 @@ wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len) ret = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac.octet, ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL); +#ifdef BIGDATA_SOFTAP + get_bigdata_softap = TRUE; +#endif /* BIGDATA_SOFTAP */ if (ret < 0) { WL_ERR(("Get sta_info ERR %d\n", ret)); +#ifndef BIGDATA_SOFTAP goto error; +#else + goto get_bigdata; +#endif /* BIGDATA_SOFTAP */ } - sta = (sta_info_t *)iovar_buf; + sta = (sta_info_v4_t *)iovar_buf; + if (dtoh16(sta->ver) != WL_STA_VER_4) { + WL_ERR(("sta_info struct version mismatch, " + "host ver : %d, fw ver : %d\n", WL_STA_VER_4, + dtoh16(sta->ver))); + goto error; + } cap = dtoh16(sta->cap); rxrtry = dtoh32(sta->rx_pkts_retried); rxmulti = dtoh32(sta->rx_mcast_pkts); @@ -2177,6 +2236,27 @@ wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len) goto error; } +#ifdef BIGDATA_SOFTAP +get_bigdata: + if (get_bigdata_softap) { + WL_ERR(("mac " MACDBG" \n", MAC2STRDBG((char*)&mac))); + if (wl_get_ap_stadata(bcm_cfg, &mac, &data) == BCME_OK) { + sta_data = (wl_ap_sta_data_t *)data; + bytes_written = snprintf(command, total_len, + "%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d " + "CAP=%04x "MACOUI" %d %s %d %d %d %d %d %d\n", + CMD_GET_STA_INFO, str, rxrtry, rxmulti, cap, + MACOUI2STR((char*)&sta_data->mac), + sta_data->channel, + wf_chspec_to_bw_str(sta_data->chanspec), + sta_data->rssi, sta_data->rate, + sta_data->mode_80211, sta_data->nss, sta_data->mimo, + sta_data->reason_code); + WL_ERR_KERN(("command %s\n", command)); + goto error; + } + } +#endif /* BIGDATA_SOFTAP */ bytes_written = snprintf(command, total_len, "%s %s Rx_Retry_Pkts=%d Rx_BcMc_Pkts=%d CAP=%04x\n", CMD_GET_STA_INFO, str, rxrtry, rxmulti, cap); @@ -2184,6 +2264,10 @@ wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len) WL_DBG(("%s", command)); error: + if (iovar_buf) { + MFREE(cfg->osh, iovar_buf, WLC_IOCTL_MAXLEN); + + } return bytes_written; } #endif /* CUSTOMER_HW4_PRIVATE_CMD */ @@ -2301,21 +2385,31 @@ static int wls_parse_batching_cmd(struct net_device *dev, char *command, int total_len) { int err = BCME_OK; - uint i, tokens; + uint i, tokens, len_remain; char *pos, *pos2, *token, *token2, *delim; char param[PNO_PARAM_SIZE+1], value[VALUE_SIZE+1]; struct dhd_pno_batch_params batch_params; + DHD_PNO(("%s: command=%s, len=%d\n", __FUNCTION__, command, total_len)); - if (total_len < strlen(CMD_WLS_BATCHING)) { - DHD_ERROR(("%s argument=%d less min size\n", __FUNCTION__, total_len)); + len_remain = total_len; + if (len_remain > (strlen(CMD_WLS_BATCHING) + 1)) { + pos = command + strlen(CMD_WLS_BATCHING) + 1; + len_remain -= strlen(CMD_WLS_BATCHING) + 1; + } else { + WL_ERR(("%s: No arguments, total_len %d\n", __FUNCTION__, total_len)); err = BCME_ERROR; goto exit; } - pos = command + strlen(CMD_WLS_BATCHING) + 1; memset(&batch_params, 0, sizeof(struct dhd_pno_batch_params)); - if (!strncmp(pos, PNO_BATCHING_SET, strlen(PNO_BATCHING_SET))) { - pos += strlen(PNO_BATCHING_SET) + 1; + if (len_remain > (strlen(PNO_BATCHING_SET) + 1)) { + pos += strlen(PNO_BATCHING_SET) + 1; + } else { + WL_ERR(("%s: %s missing arguments, total_len %d\n", + __FUNCTION__, PNO_BATCHING_SET, total_len)); + err = BCME_ERROR; + goto exit; + } while ((token = strsep(&pos, PNO_PARAMS_DELIMETER)) != NULL) { memset(param, 0, sizeof(param)); memset(value, 0, sizeof(value)); @@ -2454,7 +2548,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t #ifdef PNO_SET_DEBUG memcpy(command, pno_in_example, sizeof(pno_in_example)); total_len = sizeof(pno_in_example); -#endif +#endif // endif str_ptr = command + strlen(CMD_PNOSETUP_SET); tlv_size_left = total_len - strlen(CMD_PNOSETUP_SET); @@ -2518,13 +2612,21 @@ exit_proc: static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) { int ret; - int bytes_written = 0; + struct ether_addr p2pdev_addr; - ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command); - if (ret) - return 0; - bytes_written = sizeof(struct ether_addr); - return bytes_written; +#define MAC_ADDR_STR_LEN 18 + if (total_len < MAC_ADDR_STR_LEN) { + DHD_ERROR(("%s: buflen %d is less than p2p dev addr\n", + __FUNCTION__, total_len)); + return -1; + } + + ret = wl_cfg80211_get_p2p_dev_addr(ndev, &p2pdev_addr); + if (ret) { + DHD_ERROR(("%s Failed to get p2p dev addr\n", __FUNCTION__)); + return -1; + } + return (snprintf(command, total_len, MACF, ETHERP_TO_MACF(&p2pdev_addr))); } #ifdef BCMCCX @@ -2582,7 +2684,7 @@ wl_android_set_cckm_krk(struct net_device *dev, char *command, int total_len) return 0; } -static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command) +static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command, int total_len) { int error; u8 buf[WL_ASSOC_INFO_MAX]; @@ -2607,6 +2709,11 @@ static int wl_android_get_assoc_res_ies(struct net_device *dev, char *command) resp_ies_len = assoc_info.resp_len - sizeof(struct dot11_assoc_resp); } + if (total_len < (sizeof(u32) + resp_ies_len)) { + WL_ERR(("%s: Insufficient memory, %d bytes\n", + __FUNCTION__, total_len)); + return -1; + } /* first 4 bytes are ie len */ memcpy(command, &resp_ies_len, sizeof(u32)); bytes_written = sizeof(u32); @@ -2707,6 +2814,7 @@ wl_android_set_mac_address_filter(struct net_device *dev, char* str) struct maclist *list; char eabuf[ETHER_ADDR_STR_LEN]; const char *token; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); /* string should look like below (macmode/macnum/maclist) */ /* 1 2 00:11:22:33:44:55 00:11:22:33:44:ff */ @@ -2734,8 +2842,8 @@ wl_android_set_mac_address_filter(struct net_device *dev, char* str) return -1; } /* allocate memory for the MAC list */ - list = (struct maclist*)kmalloc(sizeof(int) + - sizeof(struct ether_addr) * macnum, GFP_KERNEL); + list = (struct maclist*) MALLOCZ(cfg->osh, sizeof(int) + + sizeof(struct ether_addr) * macnum); if (!list) { DHD_ERROR(("%s : failed to allocate memory\n", __FUNCTION__)); return -1; @@ -2744,22 +2852,32 @@ wl_android_set_mac_address_filter(struct net_device *dev, char* str) list->count = htod32(macnum); bzero((char *)eabuf, ETHER_ADDR_STR_LEN); for (i = 0; i < list->count; i++) { - strncpy(eabuf, strsep((char**)&str, " "), ETHER_ADDR_STR_LEN - 1); + token = strsep((char**)&str, " "); + if (token == NULL) { + DHD_ERROR(("%s : No mac address present\n", __FUNCTION__)); + ret = -EINVAL; + goto exit; + } + strncpy(eabuf, token, ETHER_ADDR_STR_LEN - 1); if (!(ret = bcm_ether_atoe(eabuf, &list->ea[i]))) { DHD_ERROR(("%s : mac parsing err index=%d, addr=%s\n", __FUNCTION__, i, eabuf)); - list->count--; + list->count = i; break; } DHD_INFO(("%s : %d/%d MACADDR=%s", __FUNCTION__, i, list->count, eabuf)); } + if (i == 0) + goto exit; + /* set the list */ if ((ret = wl_android_set_ap_mac_list(dev, macmode, list)) != 0) DHD_ERROR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret)); - kfree(list); +exit: + MFREE(cfg->osh, list, sizeof(int) + sizeof(struct ether_addr) * macnum); - return 0; + return ret; } /** @@ -2780,11 +2898,10 @@ int wl_android_wifi_on(struct net_device *dev) dhd_net_if_lock(dev); if (!g_wifi_on) { do { - if (!dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY)) { + dhd_net_wifi_platform_set_power(dev, TRUE, WIFI_TURNON_DELAY); #ifdef BCMSDIO - ret = dhd_net_bus_resume(dev, 0); + ret = dhd_net_bus_resume(dev, 0); #endif /* BCMSDIO */ - } #ifdef BCMPCIE ret = dhd_net_bus_devreset(dev, FALSE); #endif /* BCMPCIE */ @@ -2844,7 +2961,7 @@ int wl_android_wifi_off(struct net_device *dev, bool on_failure) if (g_wifi_on || on_failure) { #if defined(BCMSDIO) || defined(BCMPCIE) ret = dhd_net_bus_devreset(dev, TRUE); -#if defined(BCMSDIO) +#ifdef BCMSDIO dhd_net_bus_suspend(dev); #endif /* BCMSDIO */ #endif /* BCMSDIO || BCMPCIE */ @@ -2922,9 +3039,10 @@ static int wl_android_get_connection_stats(struct net_device *dev, char *command, int total_len) { static char iovar_buf[WLC_IOCTL_MAXLEN]; - wl_cnt_wlc_t* wlc_cnt = NULL; + const wl_cnt_wlc_t* wlc_cnt = NULL; #ifndef DISABLE_IF_COUNTERS wl_if_stats_t* if_stats = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); #endif /* DISABLE_IF_COUNTERS */ int link_speed = 0; @@ -2951,14 +3069,20 @@ wl_android_get_connection_stats(struct net_device *dev, char *command, int total output = (struct connection_stats *)command; #ifndef DISABLE_IF_COUNTERS - if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) { - WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__)); + if_stats = (wl_if_stats_t *)MALLOCZ(cfg->osh, sizeof(*if_stats)); + if (if_stats == NULL) { + WL_ERR(("%s(%d): MALLOCZ failed\n", __FUNCTION__, __LINE__)); goto error; } memset(if_stats, 0, sizeof(*if_stats)); - ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0, - (char *)if_stats, sizeof(*if_stats), NULL); + if (FW_SUPPORTED(dhdp, ifst)) { + ret = wl_cfg80211_ifstats_counters(dev, if_stats); + } else { + ret = wldev_iovar_getbuf(dev, "if_counters", NULL, 0, + (char *)if_stats, sizeof(*if_stats), NULL); + } + if (ret) { WL_ERR(("%s: if_counters not supported ret=%d\n", __FUNCTION__, ret)); @@ -3043,7 +3167,7 @@ wl_android_get_connection_stats(struct net_device *dev, char *command, int total error: #ifndef DISABLE_IF_COUNTERS if (if_stats) { - kfree(if_stats); + MFREE(cfg->osh, if_stats, sizeof(*if_stats)); } #endif /* DISABLE_IF_COUNTERS */ @@ -3216,23 +3340,23 @@ wl_android_natoe_subcmd_enable(struct net_device *dev, const wl_natoe_sub_cmd_t int ret = BCME_OK; wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; - uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; char *ioctl_buf = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); return -ENOMEM; } /* alloc mem for ioctl headr + tlv data */ - natoe_ioc = kzalloc(iocsz, kflags); + natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz); if (!natoe_ioc) { WL_ERR(("ioctl header memory alloc failed\n")); - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); return -ENOMEM; } @@ -3279,8 +3403,8 @@ wl_android_natoe_subcmd_enable(struct net_device *dev, const wl_natoe_sub_cmd_t } exit: - kfree(ioctl_buf); - kfree(natoe_ioc); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); + MFREE(cfg->osh, natoe_ioc, iocsz); return ret; } @@ -3294,23 +3418,23 @@ wl_android_natoe_subcmd_config_ips(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; char *str; - uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; char *ioctl_buf = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); return -ENOMEM; } /* alloc mem for ioctl headr + tlv data */ - natoe_ioc = kzalloc(iocsz, kflags); + natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz); if (!natoe_ioc) { WL_ERR(("ioctl header memory alloc failed\n")); - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); return -ENOMEM; } @@ -3399,8 +3523,8 @@ wl_android_natoe_subcmd_config_ips(struct net_device *dev, } exit: - kfree(ioctl_buf); - kfree(natoe_ioc); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); + MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ); return ret; } @@ -3414,23 +3538,23 @@ wl_android_natoe_subcmd_config_ports(struct net_device *dev, wl_natoe_ioc_t *natoe_ioc; char *pcmd = command; char *str; - uint16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; uint16 iocsz = sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ; uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; char *ioctl_buf = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); return -ENOMEM; } /* alloc mem for ioctl headr + tlv data */ - natoe_ioc = kzalloc(iocsz, kflags); + natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz); if (!natoe_ioc) { WL_ERR(("ioctl header memory alloc failed\n")); - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); return -ENOMEM; } @@ -3499,8 +3623,8 @@ wl_android_natoe_subcmd_config_ports(struct net_device *dev, } exit: - kfree(ioctl_buf); - kfree(natoe_ioc); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); + MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ); return ret; } @@ -3517,18 +3641,19 @@ wl_android_natoe_subcmd_dbg_stats(struct net_device *dev, const wl_natoe_sub_cmd uint16 buflen = WL_NATOE_DBG_STATS_BUFSZ; bcm_xtlv_t *pxtlv = NULL; char *ioctl_buf = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - ioctl_buf = kzalloc(WLC_IOCTL_MAXLEN, kflags); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); return -ENOMEM; } /* alloc mem for ioctl headr + tlv data */ - natoe_ioc = kzalloc(iocsz, kflags); + natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz); if (!natoe_ioc) { WL_ERR(("ioctl header memory alloc failed\n")); - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MAXLEN); return -ENOMEM; } @@ -3575,8 +3700,8 @@ wl_android_natoe_subcmd_dbg_stats(struct net_device *dev, const wl_natoe_sub_cmd } exit: - kfree(ioctl_buf); - kfree(natoe_ioc); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MAXLEN); + MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_DBG_STATS_BUFSZ); return ret; } @@ -3593,18 +3718,19 @@ wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev, const wl_natoe_sub_cmd_t uint16 buflen = WL_NATOE_IOC_BUFSZ; bcm_xtlv_t *pxtlv = NULL; char *ioctl_buf = NULL; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, kflags); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); return -ENOMEM; } /* alloc mem for ioctl headr + tlv data */ - natoe_ioc = kzalloc(iocsz, kflags); + natoe_ioc = (wl_natoe_ioc_t *)MALLOCZ(cfg->osh, iocsz); if (!natoe_ioc) { WL_ERR(("ioctl header memory alloc failed\n")); - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); return -ENOMEM; } @@ -3651,8 +3777,8 @@ wl_android_natoe_subcmd_tbl_cnt(struct net_device *dev, const wl_natoe_sub_cmd_t } exit: - kfree(ioctl_buf); - kfree(natoe_ioc); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); + MFREE(cfg->osh, natoe_ioc, sizeof(*natoe_ioc) + WL_NATOE_IOC_BUFSZ); return ret; } @@ -3710,6 +3836,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, u8 *reqbuf = NULL; uint32 band = WLC_BAND_2G; uint32 buf_size; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); if (cmd_str) { WL_INFORM(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str))); @@ -3740,39 +3867,41 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, } WL_INFORM(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band)); - if ((ret = - wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect))) < 0) { - WL_ERR(("ACS: error getting the spect\n")); + /* If STA is connected, return is STA channel, else ACS can be issued, + * set spect to 0 and proceed with ACS + */ + channel = wl_cfg80211_get_sta_channel(cfg); + if (channel) { + channel = (channel <= CH_MAX_2G_CHANNEL) ? + channel : APCS_DEFAULT_2G_CH; + goto done2; + } + + ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect)); + if (ret) { + WL_ERR(("ACS: error getting the spect, ret=%d\n", ret)); goto done; } if (spect > 0) { - /* If STA is connected, return is STA channel, else ACS can be issued, - * set spect to 0 and proceed with ACS - */ - channel = wl_cfg80211_get_sta_channel(dev); - if (channel) { - channel = (channel <= CH_MAX_2G_CHANNEL) ? channel : APCS_DEFAULT_2G_CH; - goto done2; - } - - if ((ret = wl_cfg80211_set_spect(dev, 0) < 0)) { - WL_ERR(("ACS: error while setting spect\n")); + ret = wl_cfg80211_set_spect(dev, 0); + if (ret < 0) { + WL_ERR(("ACS: error while setting spect, ret=%d\n", ret)); goto done; } } - reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL); + reqbuf = (u8 *)MALLOCZ(cfg->osh, CHANSPEC_BUF_SIZE); if (reqbuf == NULL) { WL_ERR(("failed to allocate chanspec buffer\n")); return -ENOMEM; } if (band == WLC_BAND_AUTO) { - WL_INFORM(("ACS full channel scan \n")); + WL_DBG(("ACS full channel scan \n")); reqbuf[0] = htod32(0); } else if (band == WLC_BAND_5G) { - WL_INFORM(("ACS 5G band scan \n")); + WL_DBG(("ACS 5G band scan \n")); if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { WL_ERR(("ACS 5g chanspec retreival failed! \n")); goto done; @@ -3782,7 +3911,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, * If channel argument is not provided/ argument 20 is provided, * Restrict channel to 2GHz, 20MHz BW, No SB */ - WL_INFORM(("ACS 2G band scan \n")); + WL_DBG(("ACS 2G band scan \n")); if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) { WL_ERR(("ACS 2g chanspec retreival failed! \n")); goto done; @@ -3841,7 +3970,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str, break; } } - WL_INFORM(("%d tried, ret = %d, chosen = 0x%x\n", + WL_DBG(("%d tried, ret = %d, chosen = 0x%x\n", (APCS_MAX_RETRY - retry), ret, chosen)); OSL_SLEEP(250); } @@ -3864,16 +3993,15 @@ done2: } if (reqbuf) { - kfree(reqbuf); + MFREE(cfg->osh, reqbuf, CHANSPEC_BUF_SIZE); } if (channel) { - snprintf(command, 4, "%d", channel); + ret = snprintf(command, total_len, "%d", channel); WL_INFORM(("command result is %s \n", command)); - return strlen(command); - } else { - return ret; } + + return ret; } #endif /* WL_SUPPORT_AUTO_CHANNEL */ @@ -3897,15 +4025,19 @@ wl_android_set_ssid(struct net_device *dev, const char* hapd_ssid) s32 ret; ssid.SSID_len = strlen(hapd_ssid); + if (ssid.SSID_len == 0) { + WL_ERR(("%s : No SSID\n", __FUNCTION__)); + return -1; + } if (ssid.SSID_len > DOT11_MAX_SSID_LEN) { ssid.SSID_len = DOT11_MAX_SSID_LEN; - DHD_ERROR(("%s : Too long SSID Length %zu\n", __FUNCTION__, strlen(hapd_ssid))); + WL_ERR(("%s : Too long SSID Length %zu\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_set(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t)); if (ret < 0) { - DHD_ERROR(("%s : WLC_SET_SSID Error:%d\n", __FUNCTION__, ret)); + WL_ERR(("%s : WLC_SET_SSID Error:%d\n", __FUNCTION__, ret)); } return 1; @@ -4058,6 +4190,9 @@ wl_android_rmc_enable(struct net_device *net, int rmc_enable) int err; err = wldev_iovar_setint(net, "rmc_ackreq", rmc_enable); + if (err != BCME_OK) { + DHD_ERROR(("%s: rmc_ackreq, error = %d\n", __FUNCTION__, err)); + } return err; } @@ -4092,7 +4227,7 @@ wl_android_rmc_set_leader(struct net_device *dev, const char* straddr) return error; } -static int wl_android_set_rmc_event(struct net_device *dev, char *command, int total_len) +static int wl_android_set_rmc_event(struct net_device *dev, char *command) { int err = 0; int pid = 0; @@ -4129,7 +4264,7 @@ int wl_android_get_singlecore_scan(struct net_device *dev, char *command, int to return bytes_written; } -int wl_android_set_singlecore_scan(struct net_device *dev, char *command, int total_len) +int wl_android_set_singlecore_scan(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -4209,9 +4344,9 @@ wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num) /* As Samsung specific and their requirement, '0' means activate sarlimit * and '-1' means back to normal state (deactivate sarlimit) */ - if (mode == 0) { - DHD_INFO(("%s: SAR limit control activated\n", __FUNCTION__)); - setval = 1; + if (mode >= 0 && mode < 3) { + DHD_INFO(("%s: SAR limit control activated mode = %d\n", __FUNCTION__, mode)); + setval = mode + 1; } else if (mode == -1) { DHD_INFO(("%s: SAR limit control deactivated\n", __FUNCTION__)); setval = 0; @@ -4228,7 +4363,7 @@ wl_android_set_sarlimit_txctrl(struct net_device *dev, const char* string_num) } #endif /* CUSTOMER_HW4_PRIVATE_CMD */ -int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len) +int wl_android_set_roam_mode(struct net_device *dev, char *command) { int error = 0; int mode = 0; @@ -4260,7 +4395,6 @@ int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, in vndr_ie_setbuf_t *vndr_ie = NULL; s32 iecount; uint32 pktflag; - u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; s32 err = BCME_OK, bssidx; struct bcm_cfg80211 *cfg = wl_get_cfg(dev); @@ -4300,7 +4434,7 @@ int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, in } tot_len = (int)(sizeof(vndr_ie_setbuf_t) + (datalen - 1)); - vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags); + vndr_ie = (vndr_ie_setbuf_t *)MALLOCZ(cfg->osh, tot_len); if (!vndr_ie) { WL_ERR(("IE memory alloc failed\n")); return -ENOMEM; @@ -4328,11 +4462,11 @@ int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, in ielen = DOT11_OUI_LEN + datalen; vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (uchar) ielen; - ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); + ioctl_buf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); if (vndr_ie) { - kfree(vndr_ie); + MFREE(cfg->osh, vndr_ie, tot_len); } return -ENOMEM; } @@ -4343,13 +4477,12 @@ int wl_android_set_ibss_beacon_ouidata(struct net_device *dev, char *command, in goto end; } err = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie", vndr_ie, tot_len, ioctl_buf, - WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync); - + WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync); end: if (err != BCME_OK) { err = -EINVAL; if (vndr_ie) { - kfree(vndr_ie); + MFREE(cfg->osh, vndr_ie, tot_len); } } else { @@ -4358,7 +4491,7 @@ end: } if (ioctl_buf) { - kfree(ioctl_buf); + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); } return err; @@ -4503,8 +4636,9 @@ wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_ { struct io_cfg *resume_cfg; s32 ret; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); - resume_cfg = kzalloc(sizeof(struct io_cfg), GFP_KERNEL); + resume_cfg = (struct io_cfg *)MALLOCZ(cfg->osh, sizeof(struct io_cfg)); if (!resume_cfg) return -ENOMEM; @@ -4525,7 +4659,7 @@ wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_ resume_cfg->iovar = config->iovar; } else { - resume_cfg->arg = kzalloc(config->len, GFP_KERNEL); + resume_cfg->arg = MALLOCZ(cfg->osh, config->len); if (!resume_cfg->arg) { ret = -ENOMEM; goto error; @@ -4552,8 +4686,8 @@ wl_android_iolist_add(struct net_device *dev, struct list_head *head, struct io_ return 0; error: - kfree(resume_cfg->arg); - kfree(resume_cfg); + MFREE(cfg->osh, resume_cfg->arg, config->len); + MFREE(cfg->osh, resume_cfg, sizeof(struct io_cfg)); return ret; } @@ -4563,16 +4697,17 @@ wl_android_iolist_resume(struct net_device *dev, struct list_head *head) struct io_cfg *config; struct list_head *cur, *q; s32 ret = 0; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-qual" -#endif +#endif // endif list_for_each_safe(cur, q, head) { config = list_entry(cur, struct io_cfg, list); #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) #pragma GCC diagnostic pop -#endif +#endif // endif if (config->iovar) { if (!ret) ret = wldev_iovar_setint(dev, config->iovar, @@ -4583,55 +4718,16 @@ wl_android_iolist_resume(struct net_device *dev, struct list_head *head) config->arg, config->len); if (config->ioctl + 1 == WLC_SET_PM) wl_cfg80211_update_power_mode(dev); - kfree(config->arg); + MFREE(cfg->osh, config->arg, config->len); } list_del(cur); - kfree(config); - } -} -#ifdef WL11ULB -static int -wl_android_set_ulb_mode(struct net_device *dev, char *command, int total_len) -{ - int mode = 0; - - DHD_INFO(("set ulb mode (%s) \n", command)); - if (sscanf(command, "%*s %d", &mode) != 1) { - DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__)); - return -1; - } - return wl_cfg80211_set_ulb_mode(dev, mode); -} -static int -wl_android_set_ulb_bw(struct net_device *dev, char *command, int total_len) -{ - int bw = 0; - u8 *pos; - char *ifname = NULL; - DHD_INFO(("set ulb bw (%s) \n", command)); - - /* - * For sta/ap: IFNAME= DRIVER ULB_BW ifname - * For p2p: IFNAME=wlan0 DRIVER ULB_BW p2p-dev-wlan0 - */ - if (total_len < strlen(CMD_ULB_BW) + 2) - return -EINVAL; - - pos = command + strlen(CMD_ULB_BW) + 1; - bw = bcm_atoi(pos); - - if ((strlen(pos) >= 5)) { - ifname = pos + 2; + MFREE(cfg->osh, config, sizeof(struct io_cfg)); } - - DHD_INFO(("[ULB] ifname:%s ulb_bw:%d \n", ifname, bw)); - return wl_cfg80211_set_ulb_bw(dev, bw, ifname); } -#endif /* WL11ULB */ static int -wl_android_set_miracast(struct net_device *dev, char *command, int total_len) +wl_android_set_miracast(struct net_device *dev, char *command) { - int mode, val; + int mode, val = 0; int ret = 0; struct io_cfg config; @@ -4648,7 +4744,7 @@ wl_android_set_miracast(struct net_device *dev, char *command, int total_len) wl_android_iolist_resume(dev, &miracast_resume_list); miracast_cur_mode = MIRACAST_MODE_OFF; - + memset((void *)&config, 0, sizeof(config)); switch (mode) { case MIRACAST_MODE_SOURCE: /* setting mchan_algo to platform specific value */ @@ -4691,6 +4787,8 @@ wl_android_set_miracast(struct net_device *dev, char *command, int total_len) /* disable internal roaming */ config.iovar = "roam_off"; config.param = 1; + config.arg = NULL; + config.len = 0; ret = wl_android_iolist_add(dev, &miracast_resume_list, &config); if (ret) { goto resume; @@ -4744,7 +4842,7 @@ static int wl_netlink_init(void) struct netlink_kernel_cfg cfg = { .input = wl_netlink_recv, }; -#endif +#endif // endif if (nl_sk != NULL) { WL_ERR(("nl_sk already exist\n")); @@ -4758,7 +4856,7 @@ static int wl_netlink_init(void) nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, THIS_MODULE, &cfg); #else nl_sk = netlink_kernel_create(&init_net, NETLINK_OXYGEN, &cfg); -#endif +#endif // endif if (nl_sk == NULL) { WL_ERR(("nl_sk is not ready\n")); @@ -4863,6 +4961,7 @@ static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command, bool found = false; struct ether_addr mac_ea; char *str = command; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); WL_DBG(("get ibss peer info(%s)\n", bAll?"true":"false")); @@ -4878,15 +4977,16 @@ static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command, } } - if ((buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL)) == NULL) { - WL_ERR(("kmalloc failed\n")); + buf = MALLOC(cfg->osh, WLC_IOCTL_MAXLEN); + if (buf == NULL) { + WL_ERR(("MALLOC failed\n")); return -1; } error = wldev_iovar_getbuf(dev, "bss_peer_info", NULL, 0, buf, WLC_IOCTL_MAXLEN, NULL); if (unlikely(error)) { WL_ERR(("could not get ibss peer info (%d)\n", error)); - kfree(buf); + MFREE(cfg->osh, buf, WLC_IOCTL_MAXLEN); return -1; } @@ -4905,7 +5005,6 @@ static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command, peer_info = (bss_peer_info_t *) ((char *)buf + BSS_PEER_LIST_INFO_FIXED_LEN); - for (i = 0; i < peer_list_info.count; i++) { WL_DBG(("index:%d rssi:%d, tx:%u, rx:%u\n", i, peer_info->rssi, @@ -4917,10 +5016,16 @@ static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command, } if (bAll || found) { - bytes_written += snprintf(&command[bytes_written], total_len, - MACF, ETHER_TO_MACF(peer_info->ea)); - bytes_written += snprintf(&command[bytes_written], total_len, - " %u %d ", peer_info->tx_rate/1000, peer_info->rssi); + bytes_written += snprintf(&command[bytes_written], + total_len - bytes_written, + MACF" %u %d ", ETHER_TO_MACF(peer_info->ea), + peer_info->tx_rate/1000, peer_info->rssi); + if (bytes_written >= total_len) { + WL_ERR(("%s: Insufficient memory, %d bytes\n", + __FUNCTION__, total_len)); + bytes_written = -1; + break; + } } if (found) @@ -4932,24 +5037,20 @@ static int wl_android_get_ibss_peer_info(struct net_device *dev, char *command, else { WL_ERR(("could not get ibss peer info : no item\n")); } - bytes_written += snprintf(&command[bytes_written], total_len, "%s", "\0"); - WL_DBG(("command(%u):%s\n", total_len, command)); WL_DBG(("bytes_written:%d\n", bytes_written)); - kfree(buf); + MFREE(cfg->osh, buf, WLC_IOCTL_MAXLEN); return bytes_written; } -int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int total_len) +int wl_android_set_ibss_routetable(struct net_device *dev, char *command) { char *pcmd = command; char *str = NULL; - ibss_route_tbl_t *route_tbl = NULL; char *ioctl_buf = NULL; - u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; s32 err = BCME_OK; uint32 route_tbl_len; uint32 entries; @@ -4957,19 +5058,20 @@ int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int to uint32 i = 0; struct ipv4_addr dipaddr; struct ether_addr ea; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); route_tbl_len = sizeof(ibss_route_tbl_t) + (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t); - route_tbl = (ibss_route_tbl_t *)kzalloc(route_tbl_len, kflags); + route_tbl = (ibss_route_tbl_t *)MALLOCZ(cfg->osh, route_tbl_len); if (!route_tbl) { WL_ERR(("Route TBL alloc failed\n")); return -ENOMEM; } - ioctl_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL); + ioctl_buf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN); if (!ioctl_buf) { WL_ERR(("ioctl memory alloc failed\n")); if (route_tbl) { - kfree(route_tbl); + MFREE(cfg->osh, route_tbl, route_tbl_len); } return -ENOMEM; } @@ -5008,7 +5110,6 @@ int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int to goto exit; } - str = bcmstrtok(&pcmd, " ", NULL); if (!str || !bcm_ether_atoe(str, &ea)) { WL_ERR(("Invalid ethernet string %s\n", str)); @@ -5029,15 +5130,17 @@ int wl_android_set_ibss_routetable(struct net_device *dev, char *command, int to } exit: - if (route_tbl) - kfree(route_tbl); - if (ioctl_buf) - kfree(ioctl_buf); + if (route_tbl) { + MFREE(cfg->osh, route_tbl, sizeof(ibss_route_tbl_t) + + (MAX_IBSS_ROUTE_TBL_ENTRY - 1) * sizeof(ibss_route_entry_t)); + } + if (ioctl_buf) { + MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN); + } return err; } - int wl_android_set_ibss_ampdu(struct net_device *dev, char *command, int total_len) { @@ -5124,12 +5227,13 @@ int wl_android_set_ibss_antenna(struct net_device *dev, char *command, int total } #endif /* WLAIBSS */ -int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len) +int wl_keep_alive_set(struct net_device *dev, char* extra) { wl_mkeep_alive_pkt_t mkeep_alive_pkt; int ret; uint period_msec = 0; char *buf; + struct bcm_cfg80211 *cfg = wl_get_cfg(dev); if (extra == NULL) { DHD_ERROR(("%s: extra is NULL\n", __FUNCTION__)); @@ -5151,7 +5255,7 @@ int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len) mkeep_alive_pkt.keep_alive_id = 0; mkeep_alive_pkt.len_bytes = 0; - buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL); + buf = (char *)MALLOC(cfg->osh, WLC_IOCTL_SMLEN); if (!buf) { DHD_ERROR(("%s: buffer alloc failed\n", __FUNCTION__)); return BCME_NOMEM; @@ -5162,7 +5266,7 @@ int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len) DHD_ERROR(("%s:keep_alive set failed:%d\n", __FUNCTION__, ret)); else DHD_TRACE(("%s:keep_alive set ok\n", __FUNCTION__)); - kfree(buf); + MFREE(cfg->osh, buf, WLC_IOCTL_SMLEN); return ret; } #ifdef P2PRESP_WFDIE_SRC @@ -5202,7 +5306,7 @@ static int wl_android_set_wfdie_resp(struct net_device *dev, int only_resp_wfdsr #ifdef BT_WIFI_HANDOVER static int -wl_tbow_teardown(struct net_device *dev, char *command, int total_len) +wl_tbow_teardown(struct net_device *dev) { int err = BCME_OK; char buf[WLC_IOCTL_SMLEN]; @@ -5214,7 +5318,7 @@ wl_tbow_teardown(struct net_device *dev, char *command, int total_len) sizeof(tbow_setup_netinfo_t), buf, WLC_IOCTL_SMLEN, 0, NULL); if (err < 0) { WL_ERR(("tbow_doho iovar error %d\n", err)); - return err; + return err; } return err; } @@ -5222,7 +5326,7 @@ wl_tbow_teardown(struct net_device *dev, char *command, int total_len) #ifdef SET_RPS_CPUS static int -wl_android_set_rps_cpus(struct net_device *dev, char *command, int total_len) +wl_android_set_rps_cpus(struct net_device *dev, char *command) { int error, enable; @@ -5251,11 +5355,12 @@ static int wl_android_get_link_status(struct net_device *dev, char *command, { int bytes_written, error, result = 0, single_stream, stf = -1, i, nss = 0, mcs_map; uint32 rspec; - uint encode, rate, txexp; - struct wl_bss_info *bi; + uint encode, txexp; + wl_bss_info_t *bi; int datalen = sizeof(uint32) + sizeof(wl_bss_info_t); char buf[datalen]; + memset(buf, 0, datalen); /* get BSS information */ *(u32 *) buf = htod32(datalen); error = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, (void *)buf, datalen); @@ -5264,7 +5369,7 @@ static int wl_android_get_link_status(struct net_device *dev, char *command, return -1; } - bi = (struct wl_bss_info *) (buf + sizeof(uint32)); + bi = (wl_bss_info_t*) (buf + sizeof(uint32)); for (i = 0; i < ETHER_ADDR_LEN; i++) { if (bi->BSSID.octet[i] > 0) { @@ -5292,7 +5397,6 @@ static int wl_android_get_link_status(struct net_device *dev, char *command, } encode = (rspec & WL_RSPEC_ENCODING_MASK); - rate = (rspec & WL_RSPEC_RATE_MASK); txexp = (rspec & WL_RSPEC_TXEXP_MASK) >> WL_RSPEC_TXEXP_SHIFT; switch (encode) { @@ -5325,7 +5429,7 @@ static int wl_android_get_link_status(struct net_device *dev, char *command, } single_stream = (encode == WL_RSPEC_ENCODE_RATE) || - ((encode == WL_RSPEC_ENCODE_HT) && rate < 8) || + ((encode == WL_RSPEC_ENCODE_HT) && (rspec & WL_RSPEC_HT_MCS_MASK) < 8) || ((encode == WL_RSPEC_ENCODE_VHT) && ((rspec & WL_RSPEC_VHT_NSS_MASK) >> WL_RSPEC_VHT_NSS_SHIFT) == 1); @@ -5366,7 +5470,7 @@ static int wl_android_get_link_status(struct net_device *dev, char *command, WL_DBG(("%s:result=%d, stf=%d, single_stream=%d, mcs map=%d\n", __FUNCTION__, result, stf, single_stream, nss)); - bytes_written = sprintf(command, "%s %d", CMD_GET_LINK_STATUS, result); + bytes_written = snprintf(command, total_len, "%s %d", CMD_GET_LINK_STATUS, result); return bytes_written; } @@ -5391,7 +5495,7 @@ wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len) } #endif /* P2P_LISTEN_OFFLOADING */ -#ifdef BCM4359_CHIP +#ifdef WL_MURX int wl_android_murx_bfe_cap(struct net_device *dev, int val) { @@ -5432,294 +5536,90 @@ wl_android_murx_bfe_cap(struct net_device *dev, int val) return err; } -#endif /* BCM4359_CHIP */ +#endif /* WL_MURX */ -#ifdef SUPPORT_AP_HIGHER_BEACONRATE +#ifdef SUPPORT_RSSI_SUM_REPORT int -wl_android_set_ap_beaconrate(struct net_device *dev, char *command) +wl_android_get_rssi_per_ant(struct net_device *dev, char *command, int total_len) { - int rate = 0; - char *pos, *token; + wl_rssi_ant_mimo_t rssi_ant_mimo; char *ifname = NULL; + char *peer_mac = NULL; + char *mimo_cmd = "mimo"; + char *pos, *token; int err = BCME_OK; + int bytes_written = 0; + bool mimo_rssi = FALSE; + memset(&rssi_ant_mimo, 0, sizeof(wl_rssi_ant_mimo_t)); /* - * DRIVER SET_AP_BEACONRATE + * STA I/F: DRIVER GET_RSSI_PER_ANT + * AP/GO I/F: DRIVER GET_RSSI_PER_ANT */ pos = command; /* drop command */ token = bcmstrtok(&pos, " ", NULL); - /* Rate */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - rate = bcm_atoi(token); - /* get the interface name */ token = bcmstrtok(&pos, " ", NULL); - if (!token) + if (!token) { + WL_ERR(("Invalid arguments\n")); return -EINVAL; + } ifname = token; - WL_DBG(("rate %d, ifacename %s\n", rate, ifname)); + /* Optional: Check the MIMO RSSI mode or peer MAC address */ + token = bcmstrtok(&pos, " ", NULL); + if (token) { + /* Check the MIMO RSSI mode */ + if (strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) { + mimo_rssi = TRUE; + } else { + peer_mac = token; + } + } - err = wl_set_ap_beacon_rate(dev, rate, ifname); + /* Optional: Check the MIMO RSSI mode - RSSI sum across antennas */ + token = bcmstrtok(&pos, " ", NULL); + if (token && strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) { + mimo_rssi = TRUE; + } + + err = wl_get_rssi_per_ant(dev, ifname, peer_mac, &rssi_ant_mimo); if (unlikely(err)) { - WL_ERR(("Failed to set ap beacon rate to %d, error = %d\n", rate, err)); + WL_ERR(("Failed to get RSSI info, err=%d\n", err)); + return err; } - return err; + /* Parse the results */ + WL_DBG(("ifname %s, version %d, count %d, mimo rssi %d\n", + ifname, rssi_ant_mimo.version, rssi_ant_mimo.count, mimo_rssi)); + if (mimo_rssi) { + WL_DBG(("MIMO RSSI: %d\n", rssi_ant_mimo.rssi_sum)); + bytes_written = snprintf(command, total_len, "%s MIMO %d", + CMD_GET_RSSI_PER_ANT, rssi_ant_mimo.rssi_sum); + } else { + int cnt; + bytes_written = snprintf(command, total_len, "%s PER_ANT ", CMD_GET_RSSI_PER_ANT); + for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) { + WL_DBG(("RSSI[%d]: %d\n", cnt, rssi_ant_mimo.rssi_ant[cnt])); + bytes_written = snprintf(command, total_len, "%d ", + rssi_ant_mimo.rssi_ant[cnt]); + } + } + + return bytes_written; } -int wl_android_get_ap_basicrate(struct net_device *dev, char *command, int total_len) +int +wl_android_set_rssi_logging(struct net_device *dev, char *command, int total_len) { + rssilog_set_param_t set_param; char *pos, *token; - char *ifname = NULL; - int bytes_written = 0; - /* - * DRIVER GET_AP_BASICRATE - */ - pos = command; - - /* drop command */ - token = bcmstrtok(&pos, " ", NULL); - - /* get the interface name */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - ifname = token; - - WL_DBG(("ifacename %s\n", ifname)); - - bytes_written = wl_get_ap_basic_rate(dev, command, ifname, total_len); - if (bytes_written < 1) { - WL_ERR(("Failed to get ap basic rate, error = %d\n", bytes_written)); - return -EPROTO; - } - - return bytes_written; - -} -#endif /* SUPPORT_AP_HIGHER_BEACONRATE */ - -#ifdef SUPPORT_AP_RADIO_PWRSAVE -int -wl_android_get_ap_rps(struct net_device *dev, char *command, int total_len) -{ - char *pos, *token; - char *ifname = NULL; - int bytes_written = 0; - /* - * DRIVER GET_AP_RPS - */ - pos = command; - - /* drop command */ - token = bcmstrtok(&pos, " ", NULL); - - /* get the interface name */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - ifname = token; - - WL_DBG(("ifacename %s\n", ifname)); - - bytes_written = wl_get_ap_rps(dev, command, ifname, total_len); - if (bytes_written < 1) { - WL_ERR(("Failed to get rps, error = %d\n", bytes_written)); - return -EPROTO; - } - - return bytes_written; - -} - -int -wl_android_set_ap_rps(struct net_device *dev, char *command, int total_len) -{ - int enable = 0; - char *pos, *token; - char *ifname = NULL; - int err = BCME_OK; - - /* - * DRIVER SET_AP_RPS <0/1> - */ - pos = command; - - /* drop command */ - token = bcmstrtok(&pos, " ", NULL); - - /* Enable */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - enable = bcm_atoi(token); - - /* get the interface name */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - ifname = token; - - WL_DBG(("enable %d, ifacename %s\n", enable, ifname)); - - err = wl_set_ap_rps(dev, enable? TRUE: FALSE, ifname); - if (unlikely(err)) { - WL_ERR(("Failed to set rps, enable %d, error = %d\n", enable, err)); - } - - return err; -} - -int -wl_android_set_ap_rps_params(struct net_device *dev, char *command, int total_len) -{ - ap_rps_info_t rps; - char *pos, *token; - char *ifname = NULL; - int err = BCME_OK; - - memset(&rps, 0, sizeof(rps)); - /* - * DRIVER SET_AP_RPS_PARAMS - */ - pos = command; - - /* drop command */ - token = bcmstrtok(&pos, " ", NULL); - - /* pps */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - rps.pps = bcm_atoi(token); - - /* level */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - rps.level = bcm_atoi(token); - - /* quiettime */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - rps.quiet_time = bcm_atoi(token); - - /* sta assoc check */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - rps.sta_assoc_check = bcm_atoi(token); - - /* get the interface name */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) - return -EINVAL; - ifname = token; - - WL_DBG(("pps %d, level %d, quiettime %d, sta_assoc_check %d, " - "ifacename %s\n", rps.pps, rps.level, rps.quiet_time, - rps.sta_assoc_check, ifname)); - - err = wl_update_ap_rps_params(dev, &rps, ifname); - if (unlikely(err)) { - WL_ERR(("Failed to update rps, pps %d, level %d, quiettime %d, " - "sta_assoc_check %d, err = %d\n", rps.pps, rps.level, rps.quiet_time, - rps.sta_assoc_check, err)); - } - - return err; -} -#endif /* SUPPORT_AP_RADIO_PWRSAVE */ - -#ifdef SUPPORT_RSSI_SUM_REPORT -int -wl_android_get_rssi_per_ant(struct net_device *dev, char *command, int total_len) -{ - wl_rssi_ant_mimo_t rssi_ant_mimo; - char *ifname = NULL; - char *peer_mac = NULL; - char *mimo_cmd = "mimo"; - char *pos, *token; - int err = BCME_OK; - int bytes_written = 0; - bool mimo_rssi = FALSE; - - memset(&rssi_ant_mimo, 0, sizeof(wl_rssi_ant_mimo_t)); - /* - * STA I/F: DRIVER GET_RSSI_PER_ANT - * AP/GO I/F: DRIVER GET_RSSI_PER_ANT - */ - pos = command; - - /* drop command */ - token = bcmstrtok(&pos, " ", NULL); - - /* get the interface name */ - token = bcmstrtok(&pos, " ", NULL); - if (!token) { - WL_ERR(("Invalid arguments\n")); - return -EINVAL; - } - ifname = token; - - /* Optional: Check the MIMO RSSI mode or peer MAC address */ - token = bcmstrtok(&pos, " ", NULL); - if (token) { - /* Check the MIMO RSSI mode */ - if (strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) { - mimo_rssi = TRUE; - } else { - peer_mac = token; - } - } - - /* Optional: Check the MIMO RSSI mode - RSSI sum across antennas */ - token = bcmstrtok(&pos, " ", NULL); - if (token && strncmp(token, mimo_cmd, strlen(mimo_cmd)) == 0) { - mimo_rssi = TRUE; - } - - err = wl_get_rssi_per_ant(dev, ifname, peer_mac, &rssi_ant_mimo); - if (unlikely(err)) { - WL_ERR(("Failed to get RSSI info, err=%d\n", err)); - return err; - } - - /* Parse the results */ - WL_DBG(("ifname %s, version %d, count %d, mimo rssi %d\n", - ifname, rssi_ant_mimo.version, rssi_ant_mimo.count, mimo_rssi)); - if (mimo_rssi) { - WL_DBG(("MIMO RSSI: %d\n", rssi_ant_mimo.rssi_sum)); - bytes_written = snprintf(command, total_len, "%s MIMO %d", - CMD_GET_RSSI_PER_ANT, rssi_ant_mimo.rssi_sum); - } else { - int cnt; - bytes_written = snprintf(command, total_len, "%s PER_ANT ", CMD_GET_RSSI_PER_ANT); - for (cnt = 0; cnt < rssi_ant_mimo.count; cnt++) { - WL_DBG(("RSSI[%d]: %d\n", cnt, rssi_ant_mimo.rssi_ant[cnt])); - bytes_written = snprintf(command, total_len, "%d ", - rssi_ant_mimo.rssi_ant[cnt]); - } - } - - return bytes_written; -} - -int -wl_android_set_rssi_logging(struct net_device *dev, char *command, int total_len) -{ - rssilog_set_param_t set_param; - char *pos, *token; - int err = BCME_OK; - - memset(&set_param, 0, sizeof(rssilog_set_param_t)); + int err = BCME_OK; + + memset(&set_param, 0, sizeof(rssilog_set_param_t)); /* * DRIVER SET_RSSI_LOGGING