From 5b9a36407e5283af1142b77b92d800a4df9720ad Mon Sep 17 00:00:00 2001 From: Chad Froebel Date: Sun, 4 Nov 2012 14:02:25 -0500 Subject: [PATCH] Update to bcmdhd from jb-chocolate --- arch/arm/configs/vigor_aosp_defconfig | 4 + drivers/net/wireless/bcmdhd/Kconfig | 33 +- drivers/net/wireless/bcmdhd/Makefile | 77 +- drivers/net/wireless/bcmdhd/aiutils.c | 34 +- drivers/net/wireless/bcmdhd/bcmevent.c | 13 +- drivers/net/wireless/bcmdhd/bcmsdh.c | 39 +- drivers/net/wireless/bcmdhd/bcmsdh_linux.c | 46 +- drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c | 295 +- .../net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c | 57 +- drivers/net/wireless/bcmdhd/bcmutils.c | 21 +- drivers/net/wireless/bcmdhd/bcmwifi.c | 2 +- drivers/net/wireless/bcmdhd/dhd.h | 178 +- drivers/net/wireless/bcmdhd/dhd_bta.c | 2 +- drivers/net/wireless/bcmdhd/dhd_bta.h | 2 +- drivers/net/wireless/bcmdhd/dhd_bus.h | 5 +- drivers/net/wireless/bcmdhd/dhd_cdc.c | 157 +- drivers/net/wireless/bcmdhd/dhd_cfg80211.c | 308 +- drivers/net/wireless/bcmdhd/dhd_cfg80211.h | 3 + drivers/net/wireless/bcmdhd/dhd_common.c | 359 +- drivers/net/wireless/bcmdhd/dhd_custom_gpio.c | 16 +- drivers/net/wireless/bcmdhd/dhd_dbg.h | 11 +- drivers/net/wireless/bcmdhd/dhd_linux.c | 1863 ++++------ drivers/net/wireless/bcmdhd/dhd_linux_mon.c | 393 ++ drivers/net/wireless/bcmdhd/dhd_linux_sched.c | 2 +- drivers/net/wireless/bcmdhd/dhd_proto.h | 2 +- drivers/net/wireless/bcmdhd/dhd_sdio.c | 328 +- drivers/net/wireless/bcmdhd/dhd_wlfc.h | 276 ++ drivers/net/wireless/bcmdhd/dngl_stats.h | 2 +- drivers/net/wireless/bcmdhd/dngl_wlhdr.h | 40 + drivers/net/wireless/bcmdhd/hndpmu.c | 36 +- drivers/net/wireless/bcmdhd/include/Makefile | 2 +- drivers/net/wireless/bcmdhd/include/aidmp.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmcdc.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmdefs.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmdevs.h | 28 +- .../net/wireless/bcmdhd/include/bcmendian.h | 2 +- .../net/wireless/bcmdhd/include/bcmpcispi.h | 181 + drivers/net/wireless/bcmdhd/include/bcmperf.h | 36 + .../net/wireless/bcmdhd/include/bcmsdbus.h | 2 +- drivers/net/wireless/bcmdhd/include/bcmsdh.h | 2 +- .../wireless/bcmdhd/include/bcmsdh_sdmmc.h | 13 +- .../net/wireless/bcmdhd/include/bcmsdpcm.h | 2 +- .../net/wireless/bcmdhd/include/bcmsdspi.h | 135 + .../net/wireless/bcmdhd/include/bcmsdstd.h | 248 ++ drivers/net/wireless/bcmdhd/include/bcmspi.h | 40 + .../net/wireless/bcmdhd/include/bcmutils.h | 13 +- drivers/net/wireless/bcmdhd/include/bcmwifi.h | 2 +- .../net/wireless/bcmdhd/include/dhdioctl.h | 4 +- drivers/net/wireless/bcmdhd/include/epivers.h | 14 +- drivers/net/wireless/bcmdhd/include/hndpmu.h | 5 +- .../wireless/bcmdhd/include/hndrte_armtrap.h | 88 + .../net/wireless/bcmdhd/include/hndrte_cons.h | 68 + drivers/net/wireless/bcmdhd/include/hndsoc.h | 2 +- drivers/net/wireless/bcmdhd/include/htsf.h | 74 + .../net/wireless/bcmdhd/include/linux_osl.h | 25 +- .../net/wireless/bcmdhd/include/linuxver.h | 33 +- drivers/net/wireless/bcmdhd/include/miniopt.h | 77 + .../net/wireless/bcmdhd/include/msgtrace.h | 2 +- drivers/net/wireless/bcmdhd/include/osl.h | 2 +- .../bcmdhd/include/packed_section_end.h | 2 +- .../bcmdhd/include/packed_section_start.h | 2 +- drivers/net/wireless/bcmdhd/include/pcicfg.h | 2 +- .../wireless/bcmdhd/include/proto/802.11.h | 147 +- .../bcmdhd/include/proto/802.11_bta.h | 2 +- .../wireless/bcmdhd/include/proto/802.11e.h | 131 + .../wireless/bcmdhd/include/proto/802.1d.h | 2 +- .../wireless/bcmdhd/include/proto/bcmeth.h | 2 +- .../wireless/bcmdhd/include/proto/bcmevent.h | 12 +- .../net/wireless/bcmdhd/include/proto/bcmip.h | 2 +- .../bcmdhd/include/proto/bt_amp_hci.h | 2 +- .../net/wireless/bcmdhd/include/proto/eapol.h | 173 + .../wireless/bcmdhd/include/proto/ethernet.h | 5 +- .../net/wireless/bcmdhd/include/proto/p2p.h | 2 +- .../net/wireless/bcmdhd/include/proto/sdspi.h | 76 + .../net/wireless/bcmdhd/include/proto/vlan.h | 2 +- .../net/wireless/bcmdhd/include/proto/wpa.h | 37 +- drivers/net/wireless/bcmdhd/include/sbchipc.h | 15 +- .../net/wireless/bcmdhd/include/sbconfig.h | 2 +- .../net/wireless/bcmdhd/include/sbhnddma.h | 2 +- .../net/wireless/bcmdhd/include/sbpcmcia.h | 2 +- drivers/net/wireless/bcmdhd/include/sbsdio.h | 2 +- .../net/wireless/bcmdhd/include/sbsdpcmdev.h | 2 +- .../net/wireless/bcmdhd/include/sbsocram.h | 2 +- drivers/net/wireless/bcmdhd/include/sdio.h | 2 +- drivers/net/wireless/bcmdhd/include/sdioh.h | 2 +- drivers/net/wireless/bcmdhd/include/sdiovar.h | 2 +- drivers/net/wireless/bcmdhd/include/siutils.h | 6 +- drivers/net/wireless/bcmdhd/include/trxhdr.h | 53 + .../net/wireless/bcmdhd/include/typedefs.h | 5 +- .../net/wireless/bcmdhd/include/wlfc_proto.h | 198 ++ drivers/net/wireless/bcmdhd/include/wlioctl.h | 137 +- drivers/net/wireless/bcmdhd/linux_osl.c | 62 +- drivers/net/wireless/bcmdhd/sbutils.c | 23 +- drivers/net/wireless/bcmdhd/siutils.c | 86 +- drivers/net/wireless/bcmdhd/siutils_priv.h | 2 +- drivers/net/wireless/bcmdhd/uamp_api.h | 176 + drivers/net/wireless/bcmdhd/wl_android.c | 1271 +------ drivers/net/wireless/bcmdhd/wl_android.h | 6 +- drivers/net/wireless/bcmdhd/wl_cfg80211.c | 2849 +++++++++------ drivers/net/wireless/bcmdhd/wl_cfg80211.h | 105 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.c | 365 +- drivers/net/wireless/bcmdhd/wl_cfgp2p.h | 52 +- drivers/net/wireless/bcmdhd/wl_dbg.h | 49 + drivers/net/wireless/bcmdhd/wl_iw.c | 3168 +++-------------- drivers/net/wireless/bcmdhd/wl_iw.h | 63 +- drivers/net/wireless/bcmdhd/wl_linux_mon.c | 2 +- drivers/net/wireless/bcmdhd/wldev_common.c | 90 +- drivers/net/wireless/bcmdhd/wldev_common.h | 13 +- include/linux/export.h | 89 + include/linux/module.h | 11 +- include/linux/nl80211.h | 600 +++- include/net/cfg80211-wext.h | 55 + include/net/cfg80211.h | 135 +- include/net/regulatory.h | 22 +- net/wireless/Kconfig | 11 + net/wireless/core.h | 4 + net/wireless/nl80211.c | 239 +- net/wireless/reg.c | 5 +- net/wireless/scan.c | 4 +- net/wireless/sme.c | 9 +- net/wireless/util.c | 46 +- 121 files changed, 8103 insertions(+), 8252 deletions(-) create mode 100644 drivers/net/wireless/bcmdhd/dhd_linux_mon.c create mode 100644 drivers/net/wireless/bcmdhd/dhd_wlfc.h create mode 100644 drivers/net/wireless/bcmdhd/dngl_wlhdr.h create mode 100644 drivers/net/wireless/bcmdhd/include/bcmpcispi.h create mode 100644 drivers/net/wireless/bcmdhd/include/bcmperf.h create mode 100644 drivers/net/wireless/bcmdhd/include/bcmsdspi.h create mode 100644 drivers/net/wireless/bcmdhd/include/bcmsdstd.h create mode 100644 drivers/net/wireless/bcmdhd/include/bcmspi.h create mode 100644 drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h create mode 100644 drivers/net/wireless/bcmdhd/include/hndrte_cons.h create mode 100644 drivers/net/wireless/bcmdhd/include/htsf.h create mode 100644 drivers/net/wireless/bcmdhd/include/miniopt.h create mode 100644 drivers/net/wireless/bcmdhd/include/proto/802.11e.h create mode 100644 drivers/net/wireless/bcmdhd/include/proto/eapol.h create mode 100644 drivers/net/wireless/bcmdhd/include/proto/sdspi.h create mode 100644 drivers/net/wireless/bcmdhd/include/trxhdr.h create mode 100644 drivers/net/wireless/bcmdhd/include/wlfc_proto.h create mode 100644 drivers/net/wireless/bcmdhd/uamp_api.h create mode 100644 drivers/net/wireless/bcmdhd/wl_dbg.h create mode 100644 include/linux/export.h create mode 100644 include/net/cfg80211-wext.h diff --git a/arch/arm/configs/vigor_aosp_defconfig b/arch/arm/configs/vigor_aosp_defconfig index 3b412405..224d494d 100644 --- a/arch/arm/configs/vigor_aosp_defconfig +++ b/arch/arm/configs/vigor_aosp_defconfig @@ -1073,6 +1073,7 @@ CONFIG_CFG80211_WEXT=y # CONFIG_WIRELESS_EXT_SYSFS is not set CONFIG_LIB80211=y # CONFIG_LIB80211_DEBUG is not set +CONFIG_CFG80211_ALLOW_RECONNECT=y # CONFIG_MAC80211 is not set # CONFIG_WIMAX is not set CONFIG_RFKILL=y @@ -1249,6 +1250,9 @@ CONFIG_LIBRA_SDIOIF=y CONFIG_BCMDHD=y CONFIG_BCMDHD_FW_PATH="/system/vendor/firmware/fw_bcmdhd.bin" CONFIG_BCMDHD_NVRAM_PATH="/proc/calibration" +# CONFIG_DHD_USE_STATIC_BUF is not set +# CONFIG_DHD_USE_SCHED_SCAN is not set +# CONFIG_DHD_ENABLE_P2P is not set # CONFIG_HOSTAP is not set # CONFIG_IWM is not set # CONFIG_LIBERTAS is not set diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index ae8a85e9..8b6b92f6 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -1,8 +1,6 @@ config BCMDHD tristate "Broadcom 4329/30 wireless cards support" depends on MMC - select WIRELESS_EXT - select WEXT_PRIV ---help--- This module adds support for wireless adapters based on Broadcom 4329/30 chipset. @@ -22,6 +20,35 @@ config BCMDHD_FW_PATH config BCMDHD_NVRAM_PATH depends on BCMDHD string "NVRAM path" - default "/proc/calibration" + default "/system/etc/wifi/bcmdhd.cal" ---help--- Path to the calibration file. + +config BCMDHD_WEXT + bool "Enable WEXT support" + depends on BCMDHD && CFG80211 = n + select WIRELESS_EXT + select WEXT_PRIV + help + Enables WEXT support + +config DHD_USE_STATIC_BUF + bool "Enable memory preallocation" + depends on BCMDHD + default n + ---help--- + Use memory preallocated in platform + +config DHD_USE_SCHED_SCAN + bool "Use CFG80211 sched scan" + depends on BCMDHD && CFG80211 + default n + ---help--- + Use CFG80211 sched scan + +config DHD_ENABLE_P2P + bool "Enable Wifi Direct" + depends on BCMDHD && CFG80211 + default n + ---help--- + Use Enable Wifi Direct diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 85987b44..eda803e3 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -1,59 +1,38 @@ - -#bcm4330 - -#DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 \ - -DUNRELEASEDCHIP -Dlinux -DDHD_SDALIGN=64 -DMAX_HDR_READ=64 \ - -DDHD_FIRSTREAD=64 -DDHD_GPL -DDHD_SCHED -DBDC -DTOE -DDHD_BCMEVENTS \ - -DSHOW_EVENTS -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS \ - -Wall -Wstrict-prototypes -Werror -DSDIO_ISR_THREAD \ - -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT \ - -DKEEP_ALIVE -DCONFIG_FIRST_SCAN -DAP_ONLY -DCUSTOM_OOB_GPIO_NUM=299 \ - -DOOB_INTR_ONLY -DMMC_SDIO_ABORT \ - -I/home/takara/work/HTC/bcm4330b1 -I/home/takara/work/HTC/bcm4330b1/include - #-DPNO_SUPPORT -DCSCAN -DSET_RANDOM_MAC_SOFTAP -DGET_CUSTOM_MAC_ENABLE - - -DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 \ - -DBCMFILEIMAGE -Dlinux -DDHD_SDALIGN=64 -DMAX_HDR_READ=64 \ - -DDHD_FIRSTREAD=64 -DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DBDC \ - -DTOE -DDHD_BCMEVENTS -DSHOW_EVENTS -DDONGLEOVERLAYS -DOEM_ANDROID \ - -DBCMDBG -DDHD_USE_STATIC_BUF -DCONFIG_FIRST_SCAN -DAP_ONLY \ - -DCUSTOM_OOB_GPIO_NUM=46 -DOOB_INTR_ONLY -DMMC_SDIO_ABORT -DEMBEDDED_PLATFORM -DCUSTOMER_HW2 -DDHD_PRINT_DEBUG \ - -DPNO_SUPPORT -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWIFI_ACT_FRAME -DKEEP_ALIVE \ - -DCSCAN -DBCM4329_LOW_POWER -DBCMWAPI_WAI -DBCMWAPI_WPI -DHTC_KlocWork -DWL_CFG80211 -DWLP2P -DWL_COMPAT_WIRELESS\ - -Wall -Wstrict-prototypes -Werror \ +# bcmdhd +DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER \ + -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DWLBTAMP -DBCMFILEIMAGE \ + -DDHDTHREAD -DDHD_GPL -DDHD_SCHED -DDHD_DEBUG -DSDTEST -DBDC -DTOE \ + -DDHD_BCMEVENTS -DSHOW_EVENTS -DDONGLEOVERLAYS -DBCMDBG \ + -DCUSTOMER_HW2 -DCUSTOM_OOB_GPIO_NUM=2 -DOOB_INTR_ONLY -DHW_OOB \ + -DMMC_SDIO_ABORT -DBCMSDIO -DBCMLXSDMMC -DBCMPLATFORM_BUS -DWLP2P \ + -DNEW_COMPAT_WIRELESS -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT \ + -DKEEP_ALIVE -DCSCAN -DGET_CUSTOM_MAC_ENABLE -DPKT_FILTER_SUPPORT \ + -DEMBEDDED_PLATFORM -DENABLE_INSMOD_NO_FW_LOAD -DPNO_SUPPORT \ + -DSET_RANDOM_MAC_SOFTAP -DWL_CFG80211_STA_EVENT \ -Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include - #-I$(M) -I$(M)/include - # CFG 80211 and P2P compile flag - #-DWL_CFG80211 -DWLP2P -DWL_COMPAT_WIRELESS \ - -#ifdef P2P -DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_COMPAT_WIRELESS -#endif - -ifdef COMPAT_WIRELESS -NOSTDINC_FLAGS := -I$(COMPAT_WIRELESS)/include/ \ - -include $(COMPAT_WIRELESS)/include/linux/compat-2.6.h -endif - -DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \ - siutils.o sbutils.o aiutils.o hndpmu.o bcmwifi.o dhd_sdio.o \ - dhd_linux_sched.o dhd_cdc.o bcmsdh_sdmmc.o bcmsdh.o bcmsdh_linux.o \ - bcmsdh_sdmmc_linux.o bcmevent.o dhd_bta.o wl_android.o wldev_common.o wl_linux_mon.o wl_cfg80211.o wl_cfgp2p.o dhd_cfg80211.o - -#ifdef P2P -DHDOFILES += wl_linux_mon.o wl_cfg80211.o wl_cfgp2p.o -#endif - - - +DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o \ + dhd_linux_sched.o bcmwifi.o dhd_sdio.o bcmevent.o dhd_bta.o hndpmu.o \ + bcmsdh.o dhd_cdc.o bcmsdh_linux.o dhd_common.o linux_osl.o \ + bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o wldev_common.o wl_android.o dhd_cfg80211.o obj-$(CONFIG_BCMDHD) += bcmdhd.o bcmdhd-objs += $(DHDOFILES) ifneq ($(CONFIG_WIRELESS_EXT),) bcmdhd-objs += wl_iw.o -DHDCFLAGS += -DSOFTAP +DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT +endif +ifneq ($(CONFIG_CFG80211),) +bcmdhd-objs += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o +DHDCFLAGS += -DWL_CFG80211 +endif +ifneq ($(CONFIG_DHD_USE_SCHED_SCAN),) +DHDCFLAGS += -DWL_SCHED_SCAN +endif +ifneq ($(CONFIG_DHD_ENABLE_P2P),) +DHDCFLAGS += -DWL_ENABLE_P2P_IF endif EXTRA_CFLAGS = $(DHDCFLAGS) +ifeq ($(CONFIG_BCMDHD),m) EXTRA_LDFLAGS += --strip-debug +endif diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c index f2058c4a..5ca0993c 100644 --- a/drivers/net/wireless/bcmdhd/aiutils.c +++ b/drivers/net/wireless/bcmdhd/aiutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aiutils.c 275693 2011-08-04 19:59:34Z $ + * $Id: aiutils.c,v 1.26.2.1 2010-03-09 18:41:21 $ */ @@ -37,7 +37,7 @@ #include "siutils_priv.h" -#define BCM47162_DMP() (0) + @@ -417,10 +417,6 @@ ai_flag(si_t *sih) aidmp_t *ai; sii = SI_INFO(sih); - if (BCM47162_DMP()) { - SI_ERROR(("%s: Attempting to read MIPS DMP registers on 47162a0", __FUNCTION__)); - return sii->curidx; - } ai = sii->curwrap; return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); @@ -544,12 +540,7 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); } ASSERT(r != NULL); -#ifdef HTC_KlocWork - if(r == NULL) { - printf("[HTCKW] r is NULL at ai_corereg\n"); - return 0; - } -#endif + if (mask || val) { w = (R_REG(sii->osh, r) & ~mask) | val; @@ -629,13 +620,6 @@ ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) uint32 w; sii = SI_INFO(sih); - - if (BCM47162_DMP()) { - SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", - __FUNCTION__)); - return; - } - ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; @@ -655,12 +639,6 @@ ai_core_cflags(si_t *sih, uint32 mask, uint32 val) uint32 w; sii = SI_INFO(sih); - if (BCM47162_DMP()) { - SI_ERROR(("%s: Accessing MIPS DMP register (ioctrl) on 47162a0", - __FUNCTION__)); - return 0; - } - ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; @@ -682,12 +660,6 @@ ai_core_sflags(si_t *sih, uint32 mask, uint32 val) uint32 w; sii = SI_INFO(sih); - if (BCM47162_DMP()) { - SI_ERROR(("%s: Accessing MIPS DMP register (iostatus) on 47162a0", - __FUNCTION__)); - return 0; - } - ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c index cb300ff9..6a25d9a5 100644 --- a/drivers/net/wireless/bcmdhd/bcmevent.c +++ b/drivers/net/wireless/bcmdhd/bcmevent.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmevent.c 275693 2011-08-04 19:59:34Z $ + * $Id: bcmevent.c,v 1.8.2.7 2011-02-01 06:23:39 $ */ #include @@ -29,7 +29,7 @@ #include #include -#if WLC_E_LAST != 90 +#if WLC_E_LAST != 87 #error "You need to add an entry to bcmevent_names[] for the new event" #endif @@ -96,10 +96,6 @@ const bcmevent_name_t bcmevent_names[] = { { WLC_E_ACTION_FRAME_RX, "ACTION_FRAME_RX" }, { WLC_E_ACTION_FRAME_COMPLETE, "ACTION_FRAME_COMPLETE" }, #endif -#ifdef BCMWAPI_WAI - { WLC_E_WAI_STA_EVENT, "WAI_STA_EVENT" }, - { WLC_E_WAI_MSG, "WAI_MSG" }, -#endif /* BCMWAPI_WAI */ { WLC_E_ESCAN_RESULT, "WLC_E_ESCAN_RESULT" }, { WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, "WLC_E_AF_OFF_CHAN_COMPLETE" }, #ifdef WLP2P @@ -123,9 +119,8 @@ const bcmevent_name_t bcmevent_names[] = { #ifdef SOFTAP { WLC_E_GTK_PLUMBED, "GTK_PLUMBED" }, #endif - { WLC_E_RELOAD, "RELOAD_EVENT" }, - { WLC_E_RSSI_LOW, "RSSI_LOW_EVENT" }, - { WLC_E_ASSOCREQ_IE, "ASSOC_REQ_EVENT" } + { WLC_E_ASSOC_REQ_IE, "ASSOC_REQ_IE" }, + { WLC_E_ASSOC_RESP_IE, "ASSOC_RESP_IE" } }; diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c index c9582304..f67b13a0 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.c 275784 2011-08-04 22:41:49Z $ + * $Id: bcmsdh.c 300445 2011-12-03 05:37:20Z $ */ /** @@ -688,40 +688,3 @@ bcmsdh_sleep(void *sdh, bool enab) return BCME_UNSUPPORTED; #endif } - -int -bcmsdh_gpio_init(void *sdh) -{ - bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; - sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); - - return sdioh_gpio_init(sd); -} - -bool -bcmsdh_gpioin(void *sdh, uint32 gpio) -{ - bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; - sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); - - return sdioh_gpioin(sd, gpio); -} - -int -bcmsdh_gpioouten(void *sdh, uint32 gpio) -{ - bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; - sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); - - return sdioh_gpioouten(sd, gpio); -} - -int -bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab) -{ - bcmsdh_info_t *p = (bcmsdh_info_t *)sdh; - sdioh_info_t *sd = (sdioh_info_t *)(p->sdioh); - - return sdioh_gpioout(sd, gpio, enab); -} - diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index 7c2a70a4..d257ddab 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c 281719 2011-09-02 23:50:57Z $ + * $Id: bcmsdh_linux.c 312788 2012-02-03 23:06:32Z $ */ /** @@ -146,17 +146,6 @@ static int __devinit bcmsdh_probe(struct device *dev); static int __devexit bcmsdh_remove(struct device *dev); #endif /* BCMLXSDMMC */ -#ifndef BCMLXSDMMC -static struct device_driver bcmsdh_driver = { - .name = "pxa2xx-mci", - .bus = &platform_bus_type, - .probe = bcmsdh_probe, - .remove = bcmsdh_remove, - .suspend = NULL, - .resume = NULL, - }; -#endif /* BCMLXSDMMC */ - #ifndef BCMLXSDMMC static #endif /* BCMLXSDMMC */ @@ -531,13 +520,8 @@ bcmsdh_register(bcmsdh_driver_t *driver) drvinfo = *driver; #if defined(BCMPLATFORM_BUS) -#if defined(BCMLXSDMMC) SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); error = sdio_function_init(); -#else - SDLX_MSG(("Intel PXA270 SDIO Driver\n")); - error = driver_register(&bcmsdh_driver); -#endif /* defined(BCMLXSDMMC) */ return error; #endif /* defined(BCMPLATFORM_BUS) */ @@ -565,14 +549,12 @@ bcmsdh_unregister(void) if (bcmsdh_pci_driver.node.next) #endif -#if defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - driver_unregister(&bcmsdh_driver); -#endif #if defined(BCMLXSDMMC) sdio_function_cleanup(); #endif /* BCMLXSDMMC */ + #if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - pci_unregister_driver(&bcmsdh_pci_driver); + pci_unregister_driver(&bcmsdh_pci_driver); #endif /* BCMPLATFORM_BUS */ } @@ -599,14 +581,9 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id) dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev); -#ifdef HW_OOB bcmsdh_oob_intr_set(0); -#endif if (dhdp == NULL) { -#ifndef HW_OOB - bcmsdh_oob_intr_set(0); -#endif SDLX_MSG(("Out of band GPIO interrupt fired way too early\n")); return IRQ_HANDLED; } @@ -643,13 +620,6 @@ int bcmsdh_register_oob_intr(void * dhdp) return 0; } -void *bcmsdh_get_drvdata(void) -{ - if (!sdhcinfo) - return NULL; - return dev_get_drvdata(sdhcinfo->dev); -} - void bcmsdh_set_irq(int flag) { if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { @@ -677,6 +647,15 @@ void bcmsdh_unregister_oob_intr(void) } #endif /* defined(OOB_INTR_ONLY) */ +#if defined(BCMLXSDMMC) +void *bcmsdh_get_drvdata(void) +{ + if (!sdhcinfo) + return NULL; + return dev_get_drvdata(sdhcinfo->dev); +} +#endif + /* Module parameters specific to each host-controller driver */ extern uint sd_msglevel; /* Debug message level */ @@ -701,6 +680,7 @@ extern uint sd_f2_blocksize; module_param(sd_f2_blocksize, int, 0); #ifdef BCMSDIOH_STD +extern int sd_uhsimode; module_param(sd_uhsimode, int, 0); #endif diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index 729b19e7..374154fb 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.c 282820 2011-09-09 15:40:35Z $ + * $Id: bcmsdh_sdmmc.c 314904 2012-02-14 21:36:04Z $ */ #include @@ -35,6 +35,7 @@ #include /* ioctl/iovars */ #include +#include #include #include @@ -106,14 +107,13 @@ sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); /* Enable Function 1 */ - if (gInstance->func[1]) { - sdio_claim_host(gInstance->func[1]); - err_ret = sdio_enable_func(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret)); - } + sdio_claim_host(gInstance->func[1]); + err_ret = sdio_enable_func(gInstance->func[1]); + sdio_release_host(gInstance->func[1]); + if (err_ret) { + sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret)); } + return FALSE; } @@ -149,29 +149,24 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) sd->sd_blockmode = TRUE; sd->use_client_ints = TRUE; sd->client_block_size[0] = 64; + sd->use_rxchain = FALSE; gInstance->sd = sd; /* Claim host controller */ - if (gInstance->func[1]) { - /* for debug */ - sd_err(("debug bcmsdh_sdmmc: F1\n")); - /* Claim host controller F1 */ - sdio_claim_host(gInstance->func[1]); + sdio_claim_host(gInstance->func[1]); - sd->client_block_size[1] = 64; - err_ret = sdio_set_block_size(gInstance->func[1], 64); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); - } - - /* Release host controller F1 */ - sdio_release_host(gInstance->func[1]); + sd->client_block_size[1] = 64; + err_ret = sdio_set_block_size(gInstance->func[1], 64); + if (err_ret) { + sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); } + /* Release host controller F1 */ + sdio_release_host(gInstance->func[1]); + if (gInstance->func[2]) { /* Claim host controller F2 */ - sd_err(("debug bcmsdh_sdmmc: F2\n")); sdio_claim_host(gInstance->func[2]); sd->client_block_size[2] = sd_f2_blocksize; @@ -519,7 +514,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, } case IOV_GVAL(IOV_RXCHAIN): - int_val = FALSE; + int_val = (int32)si->use_rxchain; bcopy(&int_val, arg, val_size); break; @@ -686,14 +681,9 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) uint8 data; if (enable) - data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; /* enable hw oob interrupt */ + data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE | SDIO_SEPINT_ACT_HI; else - data = SDIO_SEPINT_ACT_HI; /* disable hw oob interrupt */ - -#if 1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) - /* Needed for Android Linux Kernel 2.6.35 */ - data |= SDIO_SEPINT_ACT_HI; /* Active HIGH */ -#endif /* OEM_ANDROID */ + data = SDIO_SEPINT_ACT_HI; status = sdioh_request_byte(sd, SDIOH_WRITE, 0, SDIOD_CCCR_BRCM_SEPINT, &data); return status; @@ -774,7 +764,7 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) { - int err_ret = 0; /* HTC_KlocWork */ + int err_ret; sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); @@ -909,8 +899,12 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, bool fifo = (fix_inc == SDIOH_DATA_FIX); uint32 SGCount = 0; int err_ret = 0; - - void *pnext; + void *pnext, *pprev; + uint ttl_len, dma_len, lft_len, xfred_len, pkt_len; + uint blk_num; + struct mmc_request mmc_req; + struct mmc_command mmc_cmd; + struct mmc_data mmc_dat; sd_trace(("%s: Enter\n", __FUNCTION__)); @@ -918,66 +912,148 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, DHD_PM_RESUME_WAIT(sdioh_request_packet_wait); DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); - for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { - uint pkt_len = PKTLEN(sd->osh, pnext); - pkt_len += 3; - pkt_len &= 0xFFFFFFFC; + ttl_len = xfred_len = 0; + /* at least 4 bytes alignment of skb buff is guaranteed */ + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) + ttl_len += PKTLEN(sd->osh, pnext); -#ifdef CONFIG_MMC_MSM7X00A - if ((pkt_len % 64) == 32) { - sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); - pkt_len += 32; - } -#endif /* CONFIG_MMC_MSM7X00A */ - /* Make sure the packet is aligned properly. If it isn't, then this - * is the fault of sdioh_request_buffer() which is supposed to give - * us something we can work with. - */ - ASSERT(((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) == 0); - - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (write) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (fifo) { - err_ret = sdio_readsb(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, - pkt_len); - } else { - err_ret = sdio_memcpy_fromio(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, + if (!sd->use_rxchain || ttl_len <= sd->client_block_size[func]) { + blk_num = 0; + dma_len = 0; + } else { + blk_num = ttl_len / sd->client_block_size[func]; + dma_len = blk_num * sd->client_block_size[func]; + } + lft_len = ttl_len - dma_len; + + sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n", + __FUNCTION__, write ? "W" : "R", + ttl_len, func, addr, blk_num, lft_len)); + + if (0 != dma_len) { + memset(&mmc_req, 0, sizeof(struct mmc_request)); + memset(&mmc_cmd, 0, sizeof(struct mmc_command)); + memset(&mmc_dat, 0, sizeof(struct mmc_data)); + + /* Set up DMA descriptors */ + pprev = pkt; + for (pnext = pkt; + pnext && dma_len; + pnext = PKTNEXT(sd->osh, pnext)) { + pkt_len = PKTLEN(sd->osh, pnext); + + if (dma_len > pkt_len) + dma_len -= pkt_len; + else { + pkt_len = xfred_len = dma_len; + dma_len = 0; + pkt = pnext; + } + + sg_set_buf(&sd->sg_list[SGCount++], + (uint8*)PKTDATA(sd->osh, pnext), pkt_len); - } - if (err_ret) { - sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len, err_ret)); - } else { - sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len)); + if (SGCount >= SDIOH_SDMMC_MAX_SG_ENTRIES) { + sd_err(("%s: sg list entries exceed limit\n", + __FUNCTION__)); + return (SDIOH_API_RC_FAIL); + } } - if (!fifo) { - addr += pkt_len; - } - SGCount ++; + mmc_dat.sg = sd->sg_list; + mmc_dat.sg_len = SGCount; + mmc_dat.blksz = sd->client_block_size[func]; + mmc_dat.blocks = blk_num; + mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; + + mmc_cmd.opcode = 53; /* SD_IO_RW_EXTENDED */ + mmc_cmd.arg = write ? 1<<31 : 0; + mmc_cmd.arg |= (func & 0x7) << 28; + mmc_cmd.arg |= 1<<27; + mmc_cmd.arg |= fifo ? 0 : 1<<26; + mmc_cmd.arg |= (addr & 0x1FFFF) << 9; + mmc_cmd.arg |= blk_num & 0x1FF; + mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC; + + mmc_req.cmd = &mmc_cmd; + mmc_req.data = &mmc_dat; + sdio_claim_host(gInstance->func[func]); + mmc_set_data_timeout(&mmc_dat, gInstance->func[func]->card); + mmc_wait_for_req(gInstance->func[func]->card->host, &mmc_req); + sdio_release_host(gInstance->func[func]); + + err_ret = mmc_cmd.error? mmc_cmd.error : mmc_dat.error; + if (0 != err_ret) { + sd_err(("%s:CMD53 %s failed with code %d\n", + __FUNCTION__, + write ? "write" : "read", + err_ret)); + sd_err(("%s:Disabling rxchain and fire it with PIO\n", + __FUNCTION__)); + sd->use_rxchain = FALSE; + pkt = pprev; + lft_len = ttl_len; + } else if (!fifo) { + addr = addr + ttl_len - lft_len - dma_len; + } } - /* Release host controller */ - sdio_release_host(gInstance->func[func]); + /* PIO mode */ + if (0 != lft_len) { + /* Claim host controller */ + sdio_claim_host(gInstance->func[func]); + for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { + uint8 *buf = (uint8*)PKTDATA(sd->osh, pnext) + + xfred_len; + pkt_len = PKTLEN(sd->osh, pnext); + if (0 != xfred_len) { + pkt_len -= xfred_len; + xfred_len = 0; + } + pkt_len = (pkt_len + 3) & 0xFFFFFFFC; +#ifdef CONFIG_MMC_MSM7X00A + if ((pkt_len % 64) == 32) { + sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); + pkt_len += 32; + } +#endif /* CONFIG_MMC_MSM7X00A */ + + if ((write) && (!fifo)) + err_ret = sdio_memcpy_toio( + gInstance->func[func], + addr, buf, pkt_len); + else if (write) + err_ret = sdio_memcpy_toio( + gInstance->func[func], + addr, buf, pkt_len); + else if (fifo) + err_ret = sdio_readsb( + gInstance->func[func], + buf, addr, pkt_len); + else + err_ret = sdio_memcpy_fromio( + gInstance->func[func], + buf, addr, pkt_len); + + if (err_ret) + sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n", + __FUNCTION__, + (write) ? "TX" : "RX", + pnext, SGCount, addr, pkt_len, err_ret)); + else + sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", + __FUNCTION__, + (write) ? "TX" : "RX", + pnext, SGCount, addr, pkt_len)); + + if (!fifo) + addr += pkt_len; + SGCount ++; + } + sdio_release_host(gInstance->func[func]); + } sd_trace(("%s: Exit\n", __FUNCTION__)); return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -1010,11 +1086,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (pkt == NULL) { sd_data(("%s: Creating new %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", buflen_u)); -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) { #else if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buflen_u)); return SDIOH_API_RC_FAIL; @@ -1031,11 +1107,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (!write) { bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); #else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { /* Case 2: We have a packet, but it is unaligned. */ @@ -1044,11 +1120,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u sd_data(("%s: Creating aligned %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt))); -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { #else if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, PKTLEN(sd->osh, pkt))); return SDIOH_API_RC_FAIL; @@ -1069,11 +1145,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u PKTDATA(sd->osh, pkt), PKTLEN(sd->osh, mypkt)); } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); #else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ } else { /* case 3: We have a packet and it is aligned. */ sd_data(("%s: Aligned %s Packet, direct DMA\n", __FUNCTION__, write ? "Tx" : "Rx")); @@ -1239,8 +1315,10 @@ sdioh_start(sdioh_info_t *si, int stage) 2.6.27. The implementation prior to that is buggy, and needs broadcom's patch for it */ - if ((ret = sdio_reset_comm(gInstance->func[0]->card))) + if ((ret = sdio_reset_comm(gInstance->func[0]->card))) { sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); + return ret; + } else { sd->num_funcs = 2; sd->sd_blockmode = TRUE; @@ -1284,8 +1362,8 @@ sdioh_start(sdioh_info_t *si, int stage) #else /* defined(OOB_INTR_ONLY) */ #if defined(HW_OOB) sdioh_enable_func_intr(); - bcmsdh_oob_intr_set(TRUE); #endif + bcmsdh_oob_intr_set(TRUE); #endif /* !defined(OOB_INTR_ONLY) */ } } @@ -1313,8 +1391,8 @@ sdioh_stop(sdioh_info_t *si) #else /* defined(OOB_INTR_ONLY) */ #if defined(HW_OOB) sdioh_disable_func_intr(); - bcmsdh_oob_intr_set(FALSE); #endif + bcmsdh_oob_intr_set(FALSE); #endif /* !defined(OOB_INTR_ONLY) */ } else @@ -1327,28 +1405,3 @@ sdioh_waitlockfree(sdioh_info_t *sd) { return (1); } - -SDIOH_API_RC -sdioh_gpioouten(sdioh_info_t *sd, uint32 gpio) -{ - return SDIOH_API_RC_FAIL; -} - -SDIOH_API_RC -sdioh_gpioout(sdioh_info_t *sd, uint32 gpio, bool enab) -{ - return SDIOH_API_RC_FAIL; -} - -bool -sdioh_gpioin(sdioh_info_t *sd, uint32 gpio) -{ - return FALSE; -} - -SDIOH_API_RC -sdioh_gpio_init(sdioh_info_t *sd) -{ - return SDIOH_API_RC_FAIL; -} - diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index 159d7a79..a78faebe 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c 282820 2011-09-09 15:40:35Z $ + * $Id: bcmsdh_sdmmc_linux.c 312783 2012-02-03 22:53:56Z $ */ #include @@ -55,22 +55,26 @@ #if !defined(SDIO_DEVICE_ID_BROADCOM_4319) #define SDIO_DEVICE_ID_BROADCOM_4319 0x4319 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4319) */ -/* HTC_CSP_START */ #if !defined(SDIO_DEVICE_ID_BROADCOM_4330) #define SDIO_DEVICE_ID_BROADCOM_4330 0x4330 #endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4330) */ -/* HTC_CSP_END */ #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) */ #include #include +#ifdef WL_CFG80211 +extern void wl_cfg80211_set_parent_dev(void *dev); +#endif extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); @@ -97,7 +101,6 @@ PBCMSDH_SDMMC_INSTANCE gInstance; extern int bcmsdh_probe(struct device *dev); extern int bcmsdh_remove(struct device *dev); - extern volatile bool dhd_mmc_suspend; static int bcmsdh_sdmmc_probe(struct sdio_func *func, @@ -161,29 +164,48 @@ static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { { 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) }, -/* HTC_CSP_START */ { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330) }, - // Broadcom, remove SDIO all { SDIO_DEVICE_CLASS(SDIO_CLASS_NONE) }, -/* HTC_CSP_END */ { 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) }, { /* end: all zeroes */ }, }; MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) static int bcmsdh_sdmmc_suspend(struct device *pdev) { struct sdio_func *func = dev_to_sdio_func(pdev); + mmc_pm_flag_t sdio_flags; + int ret; if (func->num != 2) return 0; + + sd_trace(("%s Enter\n", __FUNCTION__)); + if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; + + sdio_flags = sdio_get_host_pm_caps(func); + + if (!(sdio_flags & MMC_PM_KEEP_POWER)) { + sd_err(("%s: can't keep power while host is suspended\n", __FUNCTION__)); + return -EINVAL; + } + + /* keep power while host suspended */ + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (ret) { + sd_err(("%s: error while trying to keep power\n", __FUNCTION__)); + return ret; + } + #if defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); -#endif +#endif /* defined(OOB_INTR_ONLY) */ dhd_mmc_suspend = TRUE; smp_mb(); @@ -192,15 +214,16 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) static int bcmsdh_sdmmc_resume(struct device *pdev) { +#if defined(OOB_INTR_ONLY) struct sdio_func *func = dev_to_sdio_func(pdev); - - if (func->num != 2) - return 0; +#endif + sd_trace(("%s Enter\n", __FUNCTION__)); dhd_mmc_suspend = FALSE; #if defined(OOB_INTR_ONLY) - if (dhd_os_check_if_up(bcmsdh_get_drvdata())) + if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); -#endif +#endif /* (OOB_INTR_ONLY) */ + smp_mb(); return 0; } @@ -209,18 +232,18 @@ static const struct dev_pm_ops bcmsdh_sdmmc_pm_ops = { .suspend = bcmsdh_sdmmc_suspend, .resume = bcmsdh_sdmmc_resume, }; -#endif +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ static struct sdio_driver bcmsdh_sdmmc_driver = { .probe = bcmsdh_sdmmc_probe, .remove = bcmsdh_sdmmc_remove, .name = "bcmsdh_sdmmc", .id_table = bcmsdh_sdmmc_ids, -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) .drv = { .pm = &bcmsdh_sdmmc_pm_ops, }, -#endif +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) && defined(CONFIG_PM) */ }; struct sdos_info { diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c index a7093b5a..6b578e65 100644 --- a/drivers/net/wireless/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/bcmdhd/bcmutils.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.c 275693 2011-08-04 19:59:34Z $ + * $Id: bcmutils.c,v 1.277.2.18 2011-01-26 02:32:08 $ */ #include @@ -286,15 +286,8 @@ pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, ifpkt_cb_t fn, int bool head = (p == q->head); if (head) q->head = PKTLINK(p); - else { -#ifdef HTC_KlocWork - if(!prev) { - printf("[HTCKW] pktq_pflush: prev=NULL\n"); - return; - } -#endif + else PKTSETLINK(prev, PKTLINK(p)); - } PKTSETLINK(p, NULL); PKTFREE(osh, p, dir); q->len--; @@ -507,11 +500,6 @@ pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) if (pq->len == 0) return NULL; -#ifdef HTC_KlocWork - while (pq->hi_prec >= PKTQ_MAX_PREC) - pq->hi_prec--; -#endif - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) pq->hi_prec--; @@ -999,7 +987,6 @@ pktsetprio(void *pkt, bool update_vtag) return (rc | priority); } -#ifndef BCM_BOOTLOADER static char bcm_undeferrstr[32]; static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; @@ -1021,7 +1008,6 @@ bcmerrorstr(int bcmerror) return bcmerrorstrtable[-bcmerror]; } -#endif /* !BCM_BOOTLOADER */ @@ -1604,9 +1590,6 @@ static const char *crypto_algo_names[] = { "UNDEF", "UNDEF", "UNDEF", -#ifdef BCMWAPI_WPI - "WAPI", -#endif /* BCMWAPI_WPI */ "UNDEF" }; diff --git a/drivers/net/wireless/bcmdhd/bcmwifi.c b/drivers/net/wireless/bcmdhd/bcmwifi.c index 6ff51be1..70722170 100644 --- a/drivers/net/wireless/bcmdhd/bcmwifi.c +++ b/drivers/net/wireless/bcmdhd/bcmwifi.c @@ -22,7 +22,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmwifi.c 275693 2011-08-04 19:59:34Z $ + * $Id: bcmwifi.c,v 1.31.8.1 2010-08-03 17:47:05 Exp $ */ diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 528004ff..725a9092 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 285377 2011-09-21 17:57:59Z $ + * $Id: dhd.h 333052 2012-05-12 02:09:28Z $ */ /**************** @@ -51,6 +51,7 @@ #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) */ + /* The kernel threading is sdio-specific */ struct task_struct; struct sched_param; @@ -74,12 +75,16 @@ enum dhd_bus_state { DHD_BUS_DATA /* Ready for frame transfers */ }; - /* Firmware requested operation mode */ #define STA_MASK 0x0001 -#define HOSTAPD_MASK 0x0002 +#define HOSTAPD_MASK 0x0002 #define WFD_MASK 0x0004 -#define SOFTAP_FW_MASK 0x0008 +#define SOFTAP_FW_MASK 0x0008 +#define P2P_GO_ENABLED 0x0010 +#define P2P_GC_ENABLED 0x0020 +#define CONCURENT_MASK 0x00F0 + +#define MANUFACTRING_FW "WLTEST" /* max sequential rxcntl timeouts to set HANG event */ #define MAX_CNTL_TIMEOUT 2 @@ -87,6 +92,9 @@ enum dhd_bus_state { #define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD Driver */ #define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD Driver */ +#define DHD_BEACON_TIMEOUT_NORMAL 4 +#define DHD_BEACON_TIMEOUT_HIGH 10 + enum dhd_bus_wake_state { WAKE_LOCK_OFF, WAKE_LOCK_PRIV, @@ -101,7 +109,6 @@ enum dhd_bus_wake_state { WAKE_LOCK_SOFTAP_STOP, WAKE_LOCK_SOFTAP_START, WAKE_LOCK_SOFTAP_THREAD, - WAKE_LOCK_PROTECT, WAKE_LOCK_MAX }; @@ -120,8 +127,7 @@ typedef enum { DHD_IF_DELETING } dhd_if_state_t; - -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size); void dhd_os_prefree(void *osh, void *addr, uint size); @@ -133,7 +139,7 @@ void dhd_os_prefree(void *osh, void *addr, uint size); #define DHD_OS_PREALLOC(osh, section, size) MALLOC(osh, size) #define DHD_OS_PREFREE(osh, addr, size) MFREE(osh, addr, size) -#endif /* defined(DHD_USE_STATIC_BUF) */ +#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN @@ -207,9 +213,11 @@ typedef struct dhd_pub { char eventmask[WL_EVENTING_MASK_LEN]; int op_mode; /* STA, HostAPD, WFD, SoftAP */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock wakelock[WAKE_LOCK_MAX]; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +/* Set this to 1 to use a seperate interface (p2p0) for p2p operations. + * For ICS MR1 releases it should be disable to be compatable with ICS MR1 Framework + * see target dhd-cdc-sdmmc-panda-cfg80211-icsmr1-gpl-debug in Makefile + */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ @@ -243,7 +251,7 @@ typedef struct dhd_cmn { SMP_RD_BARRIER_DEPENDS(); \ while (dhd_mmc_suspend && retry++ != b) { \ SMP_RD_BARRIER_DEPENDS(); \ - wait_event_interruptible_timeout(a, !dhd_mmc_suspend, HZ/100); \ + wait_event_interruptible_timeout(a, !dhd_mmc_suspend, 1); \ } \ } while (0) #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) @@ -255,7 +263,7 @@ typedef struct dhd_cmn { #define SPINWAIT_SLEEP(a, exp, us) do { \ uint countdown = (us) + 9999; \ while ((exp) && (countdown >= 10000)) { \ - wait_event_interruptible_timeout(a, FALSE, HZ/100); \ + wait_event_interruptible_timeout(a, FALSE, 1); \ countdown -= 10000; \ } \ } while (0) @@ -291,8 +299,8 @@ void dhd_os_spin_unlock(dhd_pub_t *pub, unsigned long flags); extern int dhd_os_wake_lock(dhd_pub_t *pub); extern int dhd_os_wake_unlock(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); -extern int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub, int val); -extern void dhd_htc_wake_lock_timeout(dhd_pub_t *pub, int sec); +extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); +extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) { @@ -318,12 +326,10 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) #define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) -#define DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(pub, val) dhd_os_wake_lock_timeout_enable(pub, val) - -#define WAKE_LOCK_TIMEOUT(pub, sec) dhd_htc_wake_lock_timeout(pub, sec) - -#define DHD_PACKET_TIMEOUT 1 -#define DHD_EVENT_TIMEOUT 2 +#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_PACKET_TIMEOUT_MS 1000 +#define DHD_EVENT_TIMEOUT_MS 1500 /* interface operations (register, remove) should be atomic, use this lock to prevent race * condition among wifi on/off and interface operation functions @@ -351,8 +357,7 @@ typedef enum dhd_attach_states DHD_ATTACH_STATE_WAKELOCKS_INIT = 0x40, DHD_ATTACH_STATE_CFG80211 = 0x80, DHD_ATTACH_STATE_EARLYSUSPEND_DONE = 0x100, - DHD_ATTACH_STATE_DONE = 0x200, - DHD_ATTACH_STATE_SOFTAP = 0x400 /* leverage for detecting softap is bring up */ + DHD_ATTACH_STATE_DONE = 0x200 } dhd_attach_states_t; /* Value -1 means we are unsuccessful in creating the kthread. */ @@ -426,42 +431,38 @@ extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); +extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); +extern int net_os_send_hang_message(struct net_device *dev); +extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); + +#ifdef PNO_SUPPORT extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); extern int dhd_pno_clean(dhd_pub_t *dhd); extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time); extern int dhd_pno_get_status(dhd_pub_t *dhd); extern int dhd_dev_pno_reset(struct net_device *dev); extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time); extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); -extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); -extern bool dhd_check_ap_mode_set(dhd_pub_t *dhd); -extern int wl_android_black_list_match(char *ea); +#endif /* PNO_SUPPORT */ #define DHD_UNICAST_FILTER_NUM 0 #define DHD_BROADCAST_FILTER_NUM 1 #define DHD_MULTICAST4_FILTER_NUM 2 #define DHD_MULTICAST6_FILTER_NUM 3 +#define DHD_MDNS_FILTER_NUM 4 +extern int dhd_os_set_packet_filter(dhd_pub_t *dhdp, int val); extern int net_os_set_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); extern int dhd_get_dtim_skip(dhd_pub_t *dhd); extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); -/* HTC_CSP_START*/ -struct dd_pkt_filter_s{ - int add; - int id; - int offset; - char mask[256]; - char pattern[256]; -}; - -extern int dhd_set_pktfilter(dhd_pub_t *dhd, int add, int id, int offset, char *mask, char *pattern); -extern int wl_android_set_pktfilter(struct net_device *dev, struct dd_pkt_filter_s *data); -/* HTC_CSP_END*/ #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); @@ -485,7 +486,6 @@ extern int dhd_timeout_expired(dhd_timeout_t *tmo); extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); extern int dhd_net2idx(struct dhd_info *dhd, struct net_device *net); extern struct net_device * dhd_idx2net(void *pub, int ifidx); -extern void dhd_state_set_flags(struct dhd_pub *dhd_pub, dhd_attach_states_t flags, int add); extern int wl_host_event(dhd_pub_t *dhd_pub, int *idx, void *pktdata, wl_event_msg_t *, void **data_ptr); extern void wl_event_to_host_order(wl_event_msg_t * evt); @@ -497,6 +497,7 @@ extern int dhd_wl_ioctl_cmd(dhd_pub_t *dhd_pub, int cmd, void *arg, int len, uin extern struct dhd_cmn *dhd_common_init(osl_t *osh); extern void dhd_common_deinit(dhd_pub_t *dhd_pub, dhd_cmn_t *sa_cmn); +extern int dhd_do_driver_init(struct net_device *net); extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx); extern void dhd_del_if(struct dhd_info *dhd, int ifidx); @@ -518,12 +519,12 @@ extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag); extern uint dhd_bus_status(dhd_pub_t *dhdp); extern int dhd_bus_start(dhd_pub_t *dhdp); -//HTC_CSP_START -extern void dhd_info_send_hang_message(dhd_pub_t *dhdp); -//HTC_CSP_END extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size); extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); -extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf); +extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); +extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); +extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp); +extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp); #if defined(KEEP_ALIVE) extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); @@ -544,10 +545,6 @@ typedef enum cust_gpio_modes { 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); -//HTC_CSP_START -extern int net_os_send_rssilow_message(struct net_device *dev); -//HTC_CSP_END - /* * Insmod parameters for debug/test */ @@ -595,18 +592,10 @@ extern int dhd_idletime; /* SDIO Drive Strength */ extern uint dhd_sdiod_drive_strength; -#ifdef SOFTAP -extern uint dhd_apsta; -#endif - /* Override to force tx queueing all the time */ extern uint dhd_force_tx_queueing; -#ifdef CUSTOMER_HW2 -#define KEEP_ALIVE_PERIOD 60000 -#else /* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ #define KEEP_ALIVE_PERIOD 55000 -#endif #define NULL_PKT_STR "null_pkt" #ifdef SDTEST @@ -624,6 +613,8 @@ extern uint dhd_pktgen_len; extern char fw_path[MOD_PARAM_PATHLEN]; extern char nv_path[MOD_PARAM_PATHLEN]; +#define MOD_PARAM_INFOLEN 512 + #ifdef SOFTAP extern char fw_path2[MOD_PARAM_PATHLEN]; #endif @@ -635,27 +626,6 @@ extern uint dhd_download_fw_on_driverload; #define DHD_MAX_IFS 16 #define DHD_DEL_IF -0xe #define DHD_BAD_IF -0xf -#ifdef PNO_SUPPORT -#define MAX_PFN_NUMBER 2 -/* HTC_CSP_START */ -#define PFN_SCAN_FREQ 300 /* in secs */ -/* HTC_CSP_END */ -#define PFN_WAKE_TIME 20000 /* in mini secs */ -int dhd_set_pfn_ssid(char * ssid, int ssid_len); -int dhd_del_pfn_ssid(char * ssid, int ssid_len); -void dhd_clear_pfn(void); -int dhd_set_pfn(dhd_pub_t *dhd, int enabled); -#endif - -/* Packet Filter */ -enum pkt_filter_id { - ALLOW_UNICAST = 100, - ALLOW_ARP, - ALLOW_DHCP, - ALLOW_IPV4_MULTICAST, - ALLOW_IPV6_MULTICAST, -}; -int dhd_set_pktfilter(dhd_pub_t * dhd, int add, int id, int offset, char *mask, char *pattern); #ifdef PROP_TXSTATUS /* Please be mindful that total pkttag space is 32 octets only */ @@ -769,12 +739,6 @@ typedef struct dhd_pkttag { #define DHD_PKTTAG_DSTN(tag) ((dhd_pkttag_t*)(tag))->dstn_ether typedef int (*f_commitpkt_t)(void* ctx, void* p); -int dhd_wlfc_enable(dhd_pub_t *dhd); -int dhd_wlfc_interface_event(struct dhd_info *, uint8 action, uint8 ifid, uint8 iftype, uint8* ea); -int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); -int dhd_wlfc_event(struct dhd_info *dhd); -int dhd_os_wlfc_block(dhd_pub_t *pub); -int dhd_os_wlfc_unblock(dhd_pub_t *pub); #ifdef PROP_TXSTATUS_DEBUG #define DHD_WLFC_CTRINC_MAC_CLOSE(entry) do { (entry)->closed_ct++; } while (0) @@ -786,34 +750,9 @@ int dhd_os_wlfc_unblock(dhd_pub_t *pub); #endif /* PROP_TXSTATUS */ -/* HTC_CSP_START */ -/* power control */ -enum dhdhtc_pwr_ctrl{ - DHDHTC_POWER_CTRL_ANDROID_NORMAL = 0, - DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE, - DHDHTC_POWER_CTRL_USER_CONFIG, - DHDHTC_POWER_CTRL_WIFI_PHONE, - DHDHTC_POWER_CTRL_FOTA_DOWNLOADING, - DHDHTC_POWER_CTRL_MAX_NUM, -}; -extern int dhdhtc_update_wifi_power_mode(int is_screen_off); -extern int dhdhtc_set_power_control(int power_mode, unsigned int reason); -extern unsigned int dhdhtc_get_cur_pwr_ctrl(void); -extern int dhdhtc_update_dtim_listen_interval(int is_screen_off); -#ifdef BCMSDIOH_STD -extern int sd_uhsimode; -#endif -extern char firmware_path[MOD_PARAM_PATHLEN]; -/* HTC_CSP_END */ - extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); -extern int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action); -#if defined(SOFTAP) -extern bool ap_fw_loaded; -#endif - #ifdef ARP_OFFLOAD_SUPPORT #define MAX_IPV4_ENTRIES 8 /* dhd_commn arp offload wrapers */ @@ -823,27 +762,4 @@ int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen); void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr); #endif /* ARP_OFFLOAD_SUPPORT */ -/* HTC_CSP_START */ -extern int dhd_get_txrx_stats(struct net_device *net, unsigned long *rx_packets, unsigned long *tx_packets); -extern bool dhd_APUP; -extern bool wifi_fail_retry; -/* HTC_CSP_END */ - -/* HTC_CSP_START */ -/* The maximum consequent events of "out of bus->txq" */ -#define MAX_TXQ_FULL_EVENT 300 -extern int block_ap_event; -extern int dhdcdc_power_active_while_plugin; -extern char wl_abdroid_gatewaybuf[8+1]; /*HTC_KlocWork*/ -/* HTC_CSP_END */ -#ifdef DHD_BCM_WIFI_HDMI -/* Wireless HDMI run-time enable flag */ -extern bool dhd_bcm_whdmi_enable; - -/* Network interface created for the Wireless HDMI soft AP */ -#define DHD_WHDMI_SOFTAP_IF_NAME "wl0.2" -#define DHD_WHDMI_SOFTAP_IF_NAME_LEN 5 -#define DHD_WHDMI_SOFTAP_IF_NUM 2 - -#endif /* DHD_BCM_WIFI_HDMI */ #endif /* _dhd_h_ */ diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.c b/drivers/net/wireless/bcmdhd/dhd_bta.c index cc12740d..6b782ea4 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bta.c +++ b/drivers/net/wireless/bcmdhd/dhd_bta.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_bta.c 285377 2011-09-21 17:57:59Z $ + * $Id: dhd_bta.c,v 1.10.4.2 2010-12-22 23:47:23 Exp $ */ #include diff --git a/drivers/net/wireless/bcmdhd/dhd_bta.h b/drivers/net/wireless/bcmdhd/dhd_bta.h index 6f8dcb6f..07d9cebb 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bta.h +++ b/drivers/net/wireless/bcmdhd/dhd_bta.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_bta.h 275786 2011-08-04 22:42:42Z $ + * $Id: dhd_bta.h,v 1.2 2009-02-26 22:35:56 Exp $ */ #ifndef __dhd_bta_h__ #define __dhd_bta_h__ diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h index 5a41d1d0..bccb8b66 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bus.h +++ b/drivers/net/wireless/bcmdhd/dhd_bus.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_bus.h 285377 2011-09-21 17:57:59Z $ + * $Id: dhd_bus.h,v 1.14.28.1 2010-12-23 01:13:17 Exp $ */ #ifndef _dhd_bus_h_ @@ -51,9 +51,8 @@ extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex); /* Get the Bus Idle Time */ extern void dhd_bus_getidletime(dhd_pub_t *dhdp, int *idletime); -/* Set the Bus Idle Time */ +/* Set the Bus Idle Time*/ extern void dhd_bus_setidletime(dhd_pub_t *dhdp, int idle_time); - /* Send a data frame to the dongle. Callee disposes of txp. */ extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp); diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 4db27d94..f16d81c9 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c 288105 2011-10-06 01:58:02Z $ + * $Id: dhd_cdc.c 324280 2012-03-28 19:01:17Z $ * * 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 @@ -78,6 +78,8 @@ typedef struct dhd_prot { unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN]; } dhd_prot_t; +extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf); + static int dhdcdc_msg(dhd_pub_t *dhd) { @@ -121,7 +123,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) return ret; } -int +static int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) { dhd_prot_t *prot = dhd->prot; @@ -276,140 +278,6 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 return ret; } -#ifdef PNO_SUPPORT -#define htod32(i) i -#define htod16(i) i - -typedef struct pfn_ssid { - char ssid[32]; - int32 ssid_len; - uint32 weight; -} pfn_ssid_t; - -typedef struct pfn_ssid_set { - pfn_ssid_t pfn_ssids[MAX_PFN_NUMBER]; -} pfn_ssid_set_t; - -static pfn_ssid_set_t pfn_ssid_set; - -int dhd_set_pfn_ssid(char * ssid, int ssid_len) -{ - uint32 i, lightest, weightest, samessid = 0xffff; - - if ((ssid_len < 1) || (ssid_len > 32)) { - printf("Invaild ssid length!\n"); - return -1; - } - printf("pfn: set ssid = %s\n", ssid); - lightest = 0; - weightest = 0; - for (i = 0; i < MAX_PFN_NUMBER; i++) - { - if (pfn_ssid_set.pfn_ssids[i].weight < pfn_ssid_set.pfn_ssids[lightest].weight) - lightest = i; - - if (pfn_ssid_set.pfn_ssids[i].weight > pfn_ssid_set.pfn_ssids[weightest].weight) - weightest = i; - - if (!strcmp(ssid, pfn_ssid_set.pfn_ssids[i].ssid)) - samessid = i; - } - - printf("lightest is %d, weightest is %d, samessid = %d\n", lightest, weightest, samessid); - - if (samessid != 0xffff) { - if (samessid == weightest) { - printf("connect to latest ssid, ignore!\n"); - return 0; - } - pfn_ssid_set.pfn_ssids[samessid].weight = pfn_ssid_set.pfn_ssids[weightest].weight + 1; - return 0; - } - memset(&pfn_ssid_set.pfn_ssids[lightest], 0, sizeof(pfn_ssid_t)); - - strncpy(pfn_ssid_set.pfn_ssids[lightest].ssid, ssid, ssid_len); - pfn_ssid_set.pfn_ssids[lightest].ssid_len = ssid_len; - pfn_ssid_set.pfn_ssids[lightest].weight = pfn_ssid_set.pfn_ssids[weightest].weight + 1; - - return 0; -} - -int dhd_del_pfn_ssid(char * ssid, int ssid_len) -{ - uint32 i; - - if ((ssid_len < 1) || (ssid_len > 32)) { - printf("Invaild ssid length!\n"); - return -1; - } - - for (i = 0; i < MAX_PFN_NUMBER; i++) { - if (!strcmp(ssid, pfn_ssid_set.pfn_ssids[i].ssid)) - break; - } - - if (i == MAX_PFN_NUMBER) { - printf("del ssid [%s] not found!\n", ssid); - return 0; - } - - memset(&pfn_ssid_set.pfn_ssids[i], 0, sizeof(pfn_ssid_t)); - printf("del ssid [%s] complete!\n", ssid); - - return 0; -} -extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); -extern int dhd_pno_clean(dhd_pub_t *dhd); -extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, - ushort scan_fr, int pno_repeat, int pno_freq_expo_max); -/* HTC_CSP_START */ -char project_type[33]; -/* HTC_CSP_END */ -int dhd_set_pfn(dhd_pub_t *dhd, int enabled) -{ - wlc_ssid_t ssids_local[MAX_PFN_NUMBER]; - int i; - int config_network = 0; - - - memset(ssids_local, 0, sizeof(ssids_local)); - - if (enabled) { - for (i = 0; i < MAX_PFN_NUMBER; i++) { - if (pfn_ssid_set.pfn_ssids[i].ssid[0]) { - strncpy((char *)ssids_local[i].SSID, pfn_ssid_set.pfn_ssids[i].ssid, - sizeof(ssids_local[i].SSID)); - ssids_local[i].SSID_len = pfn_ssid_set.pfn_ssids[i].ssid_len; - config_network++; - } - } - - if (!config_network) { - return 0; - } - - /* set pno list */ -/* HTC_CSP_START */ - if (project_type != NULL && !strnicmp(project_type, "KT", strlen("KT")) ) { - dhd_pno_set(dhd, ssids_local, config_network, 120, 0, 0); - } else { - dhd_pno_set(dhd, ssids_local, config_network, PFN_SCAN_FREQ, 0, 0); - } -/* HTC_CSP_END */ - - /* enable pno scan */ - dhd_pno_enable(dhd, 1); - } else - dhd_pno_enable(dhd, 0); - - return 0; -} - -void dhd_clear_pfn() -{ - memset(&pfn_ssid_set, 0, sizeof(pfn_ssid_set_t)); -} -#endif int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) @@ -2308,6 +2176,7 @@ dhd_wlfc_init(dhd_pub_t *dhd) WLFC_FLAGS_CREDIT_STATUS_SIGNALS | WLFC_FLAGS_HOST_PROPTXSTATUS_ACTIVE : 0; + dhd->wlfc_state = NULL; /* try to enable/disable signaling by sending "tlv" iovar. if that fails, @@ -2469,8 +2338,6 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) #endif } -#define RAISE_BK_PRIO 1 - void dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) { @@ -2493,10 +2360,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); -#ifdef RAISE_BK_PRIO - if ((dhd_APUP == true) && (h->priority < 3)) - h->priority = 3; -#endif h->flags2 = 0; h->dataOffset = 0; #endif /* BDC */ @@ -2600,10 +2463,10 @@ dhd_prot_attach(dhd_pub_t *dhd) return 0; fail: -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF if (cdc != NULL) MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ return BCME_NOMEM; } @@ -2614,9 +2477,9 @@ dhd_prot_detach(dhd_pub_t *dhd) #ifdef PROP_TXSTATUS dhd_wlfc_deinit(dhd); #endif -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); -#endif /* DHD_USE_STATIC_BUF */ +#endif /* CONFIG_DHD_USE_STATIC_BUF */ dhd->prot = NULL; } @@ -2655,7 +2518,7 @@ dhd_prot_init(dhd_pub_t *dhd) #if defined(WL_CFG80211) if (dhd_download_fw_on_driverload) #endif /* defined(WL_CFG80211) */ - ret = dhd_preinit_ioctls(dhd); + ret = dhd_preinit_ioctls(dhd); /* Always assumes wl for now */ dhd->iswl = TRUE; diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index 3be542ea..970216ef 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -30,18 +30,16 @@ #include #include #include - extern struct wl_priv *wlcfg_drv_priv; static int dhd_dongle_up = FALSE; +#include +#include +#include +#include +#include + static s32 wl_dongle_up(struct net_device *ndev, u32 up); -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode); -static s32 wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align); -static s32 wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout); -static s32 wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, s32 scan_unassoc_time); -static s32 wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol); -static s32 wl_pattern_atoh(s8 *src, s8 *dst); -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode); /** * Function implementations @@ -59,263 +57,75 @@ s32 dhd_cfg80211_deinit(struct wl_priv *wl) return 0; } -s32 dhd_cfg80211_down(struct wl_priv *wl) +s32 dhd_cfg80211_get_opmode(struct wl_priv *wl) { - dhd_dongle_up = FALSE; - return 0; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + return dhd->op_mode; } -static s32 wl_dongle_up(struct net_device *ndev, u32 up) -{ - s32 err = 0; - - err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); - if (unlikely(err)) { - WL_ERR(("WLC_UP error (%d)\n", err)); - } - return err; -} - -static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode) +s32 dhd_cfg80211_down(struct wl_priv *wl) { - s32 err = 0; - - WL_TRACE(("In\n")); - err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), true); - if (unlikely(err)) { - WL_ERR(("WLC_SET_PM error (%d)\n", err)); - } - return err; + dhd_dongle_up = FALSE; + return 0; } -static s32 -wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align) +s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) { - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + int bcn_timeout = DHD_BEACON_TIMEOUT_HIGH; + char iovbuf[30]; - s32 err = 0; + dhd->op_mode |= val; + WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); - /* Match Host and Dongle rx alignment */ - bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglomalign error (%d)\n", err)); - goto dongle_glom_out; - } - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("txglom error (%d)\n", err)); - goto dongle_glom_out; - } -dongle_glom_out: - return err; -} - -static s32 -wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) -{ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; +#ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, false); +#endif /* ARP_OFFLOAD_SUPPORT */ - s32 err = 0; + dhd_os_set_packet_filter(dhd, 0); /* Setup timeout if Beacons are lost and roam is off to report link down */ - if (roamvar) { - bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("bcn_timeout error (%d)\n", err)); - goto dongle_rom_out; - } - } - /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (unlikely(err)) { - WL_ERR(("roam_off error (%d)\n", err)); - goto dongle_rom_out; - } -dongle_rom_out: - return err; -} + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -static s32 -wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, - s32 scan_unassoc_time) -{ - s32 err = 0; - err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, - sizeof(scan_assoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan assoc time is not supported\n")); - } else { - WL_ERR(("Scan assoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, - sizeof(scan_unassoc_time), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan unassoc time is not supported\n")); - } else { - WL_ERR(("Scan unassoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - -dongle_scantime_out: - return err; + return 0; } -static s32 -wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol) +s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) { - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + int bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL; + char iovbuf[30]; - s32 err = 0; + dhd->op_mode &= ~CONCURENT_MASK; + WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); - /* Set ARP offload */ - bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arpoe is not supported\n")); - else - WL_ERR(("arpoe error (%d)\n", err)); +#ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is disabled, enable arpoe back for STA mode. */ + dhd_arp_offload_set(dhd, dhd_arp_mode); + dhd_arp_offload_enable(dhd, true); +#endif /* ARP_OFFLOAD_SUPPORT */ - goto dongle_offload_out; - } - bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) - WL_INFO(("arp_ol is not supported\n")); - else - WL_ERR(("arp_ol error (%d)\n", err)); - - goto dongle_offload_out; - } + dhd_os_set_packet_filter(dhd, 1); -dongle_offload_out: - return err; -} + /* Setup timeout if Beacons are lost and roam is off to report link down */ + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -static s32 wl_pattern_atoh(s8 *src, s8 *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { - WL_ERR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - WL_ERR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - dst[i] = (u8) simple_strtoul(num, NULL, 16); - src += 2; - } - return i; + return 0; } -static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode) +static s32 wl_dongle_up(struct net_device *ndev, u32 up) { - /* Room for "event_msgs" + '\0' + bitvec */ - s8 iovbuf[WL_EVENTING_MASK_LEN + 12]; - - const s8 *str; - struct wl_pkt_filter pkt_filter; - struct wl_pkt_filter *pkt_filterp; - s32 buf_len; - s32 str_len; - u32 mask_size; - u32 pattern_size; - s8 buf[256]; s32 err = 0; - /* add a default packet filter pattern */ - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[str_len] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(100); - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(0); - - /* Parse filter type. */ - pkt_filter.type = htod32(0); - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(0); - - /* Parse pattern filter mask. */ - mask_size = htod32(wl_pattern_atoh("0xff", - (char *)pkt_filterp->u.pattern. - mask_and_pattern)); - - /* Parse pattern filter pattern. */ - pattern_size = htod32(wl_pattern_atoh("0x00", - (char *)&pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - WL_ERR(("Mask and pattern not the same size\n")); - err = -EINVAL; - goto dongle_filter_out; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - /* Keep-alive attributes are set in local - * variable (keep_alive_pkt), and - * then memcpy'ed into buffer (keep_alive_pktp) since there is no - * guarantee that the buffer is properly aligned. - */ - memcpy((char *)pkt_filterp, &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter not supported\n")); - } else { - WL_ERR(("filter (%d)\n", err)); - } - goto dongle_filter_out; - } - - /* set mode to allow pattern */ - bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, - sizeof(iovbuf)); - err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true); - if (err) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter_mode not supported\n")); - } else { - WL_ERR(("filter_mode (%d)\n", err)); - } - goto dongle_filter_out; + err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), true); + if (unlikely(err)) { + WL_ERR(("WLC_UP error (%d)\n", err)); } - -dongle_filter_out: return err; } @@ -343,24 +153,6 @@ s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock) WL_ERR(("wl_dongle_up failed\n")); goto default_conf_out; } - err = wl_dongle_power(ndev, PM_FAST); - if (unlikely(err)) { - WL_ERR(("wl_dongle_power failed\n")); - goto default_conf_out; - } - err = wl_dongle_glom(ndev, 0, DHD_SDALIGN); - if (unlikely(err)) { - WL_ERR(("wl_dongle_glom failed\n")); - goto default_conf_out; - } - err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3); - if (unlikely(err)) { - WL_ERR(("wl_dongle_roam failed\n")); - goto default_conf_out; - } - wl_dongle_scantime(ndev, 40, 80); - wl_dongle_offload(ndev, 1, 0xf); - wl_dongle_filter(ndev, 1); dhd_dongle_up = true; default_conf_out: @@ -641,7 +433,7 @@ static void wl_cfg80211_bt_handler(struct work_struct *work) __FUNCTION__)); btcx_inf->bt_state = BT_DHCP_OPPR_WIN; mod_timer(&btcx_inf->timer, - jiffies + BT_DHCP_OPPR_WIN_TIME*HZ/1000); + jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME)); btcx_inf->timer_on = 1; break; @@ -661,7 +453,7 @@ static void wl_cfg80211_bt_handler(struct work_struct *work) wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; mod_timer(&btcx_inf->timer, - jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); + jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME)); btcx_inf->timer_on = 1; break; @@ -737,7 +529,6 @@ void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) kfree(wl->btcoex_info); wl->btcoex_info = NULL; } -#endif int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) { @@ -861,3 +652,4 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) return (strlen("OK")); } +#endif diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h index 8dab652c..ced46dbd 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h @@ -33,7 +33,10 @@ s32 dhd_cfg80211_init(struct wl_priv *wl); s32 dhd_cfg80211_deinit(struct wl_priv *wl); +s32 dhd_cfg80211_get_opmode(struct wl_priv *wl); s32 dhd_cfg80211_down(struct wl_priv *wl); +s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val); +s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); int wl_cfg80211_btcoex_init(struct wl_priv *wl); diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index e4fc8864..d5af27f4 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 288105 2011-10-06 01:58:02Z $ + * $Id: dhd_common.c 331276 2012-05-04 08:05:57Z $ */ #include #include @@ -91,9 +91,6 @@ extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx); bool ap_cfg_running = FALSE; bool ap_fw_loaded = FALSE; -#if defined(KEEP_ALIVE) -int dhd_keep_alive_onoff(dhd_pub_t *dhd); -#endif /* KEEP_ALIVE */ #ifdef DHD_DEBUG const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " @@ -137,7 +134,7 @@ enum { }; const bcm_iovar_t dhd_iovars[] = { - {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, + {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, #ifdef DHD_DEBUG {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, #endif /* DHD_DEBUG */ @@ -193,14 +190,14 @@ dhd_common_init(osl_t *osh) #ifdef CONFIG_BCMDHD_FW_PATH bcm_strncpy_s(fw_path, sizeof(fw_path), CONFIG_BCMDHD_FW_PATH, MOD_PARAM_PATHLEN-1); -#else /* CONFIG_BCM4329_FW_PATH */ +#else /* CONFIG_BCMDHD_FW_PATH */ fw_path[0] = '\0'; -#endif /* CONFIG_BCM4329_FW_PATH */ +#endif /* CONFIG_BCMDHD_FW_PATH */ #ifdef CONFIG_BCMDHD_NVRAM_PATH bcm_strncpy_s(nv_path, sizeof(nv_path), CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1); -#else /* CONFIG_BCM4329_NVRAM_PATH */ +#else /* CONFIG_BCMDHD_NVRAM_PATH */ nv_path[0] = '\0'; -#endif /* CONFIG_BCM4329_NVRAM_PATH */ +#endif /* CONFIG_BCMDHD_NVRAM_PATH */ #ifdef SOFTAP fw_path2[0] = '\0'; #endif @@ -303,7 +300,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le dhd_os_proto_block(dhd_pub); ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); - if (!ret) + if (ret) dhd_os_check_hang(dhd_pub, ifindex, ret); dhd_os_proto_unblock(dhd_pub); @@ -339,6 +336,11 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch case IOV_SVAL(IOV_MSGLEVEL): dhd_msg_level = int_val; +#ifdef WL_CFG80211 + /* Enable DHD and WL logs in oneshot */ + if (dhd_msg_level & DHD_WL_VAL) + wl_cfg80211_enable_trace(dhd_msg_level); +#endif break; case IOV_GVAL(IOV_BCMERRORSTR): bcm_strncpy_s((char *)arg, len, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); @@ -571,21 +573,14 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) return FALSE; /* refuse newer (incoming) packet */ /* Evict packet according to discard policy */ p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec); - if (p == NULL) { - DHD_ERROR(("%s: pktq_penq() failed, oldest %d.", - __FUNCTION__, discard_oldest)); - ASSERT(p); - } + ASSERT(p); PKTFREE(dhdp->osh, p, TRUE); } /* Enqueue */ p = pktq_penq(q, prec, pkt); - if (p == NULL) { - DHD_ERROR(("%s: pktq_penq() failed.", __FUNCTION__)); - ASSERT(p); - } + ASSERT(p); return TRUE; } @@ -867,6 +862,8 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data) break; case WLC_E_SCAN_COMPLETE: + case WLC_E_ASSOC_REQ_IE: + case WLC_E_ASSOC_RESP_IE: case WLC_E_PMKID_CACHE: DHD_EVENT(("MACEVENT: %s\n", event_name)); break; @@ -999,6 +996,9 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, datalen = ntoh32_ua((void *)&event->datalen); evlen = datalen + sizeof(bcm_event_t); + DHD_TRACE(("RX: event_type:%d flags:%d status:%d reason:%d \n", + type, flags, status, reason)); + switch (type) { #ifdef PROP_TXSTATUS case WLC_E_FIFO_CREDIT_MAP: @@ -1168,7 +1168,7 @@ dhd_print_buf(void *pbuf, int len, int bytes_per_line) #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) /* Convert user's input in hex pattern to byte-size mask */ -int +static int wl_pattern_atoh(char *src, char *dst) { int i; @@ -1192,115 +1192,6 @@ wl_pattern_atoh(char *src, char *dst) return i; } -#ifdef CUSTOMER_HW2 -/* HTC_CSP_START */ -extern bool hasDLNA; -extern char ip_str[32]; -/* HTC_CSP_END */ -int dhd_set_pktfilter(dhd_pub_t * dhd, int add, int id, int offset, char *mask, char *pattern) -{ - char *str; - wl_pkt_filter_t pkt_filter; - wl_pkt_filter_t *pkt_filterp; - int buf_len; - int str_len; - uint32 mask_size; - uint32 pattern_size; - char buf[256]; - int pkt_id = id; - wl_pkt_filter_enable_t enable_parm; - - printf("Enter set packet filter\n"); - -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - if (add == 1 && pkt_id == 105) - { - printf("MCAST packet filter, hasDLNA is true\n"); - hasDLNA = true; - } -#endif -/* HTC_CSP_END */ - - /* disable pkt filter */ - enable_parm.id = htod32(pkt_id); - enable_parm.enable = htod32(0); - bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, - sizeof(wl_pkt_filter_enable_t), buf, sizeof(buf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); - - /* delete it */ - bcm_mkiovar("pkt_filter_delete", (char *)&pkt_id, 4, buf, sizeof(buf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); - - if (!add) { - return 0; - } - - printf("start to add pkt filter %d\n", pkt_id); - memset(buf, 0, sizeof(buf)); - /* add a packet filter pattern */ - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[ str_len ] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(pkt_id); - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(0); - - /* Parse filter type. */ - pkt_filter.type = htod32(0); - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(offset); - - /* Parse pattern filter mask. */ - mask_size = htod32(wl_pattern_atoh(mask, - (char *) pkt_filterp->u.pattern.mask_and_pattern)); - -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - if (add == 1 && id == 101){ - memcpy(ip_str, pattern+78, 8); - DHD_TRACE(("ip: %s", ip_str)); - } -#endif -/* HTC_CSP_END */ - - /* Parse pattern filter pattern. */ - pattern_size = htod32(wl_pattern_atoh(pattern, - (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - printf("Mask and pattern not the same size\n"); - return -EINVAL; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - memcpy((char *)pkt_filterp, &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); - - enable_parm.id = htod32(pkt_id); - enable_parm.enable = htod32(1); - bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, - sizeof(wl_pkt_filter_enable_t), buf, sizeof(buf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE , 0); - - return 0; -} -#endif - void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode) { @@ -1632,8 +1523,6 @@ dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen) } #endif /* ARP_OFFLOAD_SUPPORT */ - - /* send up locally generated event */ void dhd_sendup_event_common(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) @@ -1837,11 +1726,12 @@ dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) /* * returns = TRUE if associated, FALSE if not associated + * third paramter retval can return error from error */ -bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf) +bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval) { char bssid[6], zbuf[6]; - int ret = -1; + int ret; bzero(bssid, 6); bzero(zbuf, 6); @@ -1849,6 +1739,9 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf) ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0); DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret)); + if (retval) + *retval = ret; + if (ret == BCME_NOTASSOCIATED) { DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret)); } @@ -1870,7 +1763,6 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf) } } - /* Function to estimate possible DTIM_SKIP value */ int dhd_get_dtim_skip(dhd_pub_t *dhd) @@ -1885,7 +1777,7 @@ dhd_get_dtim_skip(dhd_pub_t *dhd) bcn_li_dtim = dhd->dtim_skip; /* Check if associated */ - if (dhd_is_associated(dhd, NULL) == FALSE) { + if (dhd_is_associated(dhd, NULL, NULL) == FALSE) { DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret)); goto exit; } @@ -1928,20 +1820,24 @@ dhd_get_dtim_skip(dhd_pub_t *dhd) bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) { #ifdef WL_CFG80211 +#ifndef WL_ENABLE_P2P_IF + /* To be back compatble with ICS MR1 release where p2p interface + * disable but wlan0 used for p2p + */ if (((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) || - ((dhd->op_mode & WFD_MASK) == WFD_MASK)) + ((dhd->op_mode & WFD_MASK) == WFD_MASK)) { return TRUE; + } else -#endif /* WL_CFG80211 */ - return FALSE; -} - -bool dhd_check_ap_mode_set(dhd_pub_t *dhd) -{ -#ifdef WL_CFG80211 - if ((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) +#else + /* concurent mode with p2p interface for wfd and wlan0 for sta */ + if (((dhd->op_mode & P2P_GO_ENABLED) == P2P_GO_ENABLED) || + ((dhd->op_mode & P2P_GC_ENABLED) == P2P_GC_ENABLED)) { + DHD_ERROR(("%s P2P enabled for mode=%d\n", __FUNCTION__, dhd->op_mode)); return TRUE; + } else +#endif /* WL_ENABLE_P2P_IF */ #endif /* WL_CFG80211 */ return FALSE; } @@ -1988,15 +1884,18 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (ret); memset(iovbuf, 0, sizeof(iovbuf)); - if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) { +#ifndef WL_SCHED_SCAN + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (ret); + + if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) { DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); - //return ret; + return ret; } +#endif /* !WL_SCHED_SCAN */ /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { @@ -2030,17 +1929,15 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, DHD_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, scan_fr)); - if ((!dhd) || (!ssids_local)) { + if ((!dhd) && (!ssids_local)) { DHD_ERROR(("%s error exit\n", __FUNCTION__)); -#ifdef HTC_KlocWork - return err; -#else err = -1; -#endif + return err; } - +#ifndef WL_SCHED_SCAN if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) return (err); +#endif /* !WL_SCHED_SCAN */ /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { @@ -2133,6 +2030,123 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, return err; } +int +dhd_pno_set_ex(dhd_pub_t *dhd, wl_pfn_t* ssidnet, int nssid, ushort pno_interval, + int pno_repeat, int pno_expo_max, int pno_lost_time) +{ + int err = -1; + char iovbuf[128]; + int k, i; + wl_pfn_param_t pfn_param; + wl_pfn_t pfn_element; + uint len = 0; + + DHD_TRACE(("%s nssid=%d pno_interval=%d\n", __FUNCTION__, nssid, pno_interval)); + + if ((!dhd) && (!ssidnet)) { + DHD_ERROR(("%s error exit\n", __FUNCTION__)); + err = -1; + return err; + } + + if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) + return (err); + + /* Check for broadcast ssid */ + for (k = 0; k < nssid; k++) { + if (!ssidnet[k].ssid.SSID_len) { + DHD_ERROR(("%d: Broadcast SSID is ilegal for PNO setting\n", k)); + return err; + } + } +/* #define PNO_DUMP 1 */ +#ifdef PNO_DUMP + { + int j; + for (j = 0; j < nssid; j++) { + DHD_ERROR(("%d: scan for %s size =%d\n", j, + ssidnet[j].ssid.SSID, ssidnet[j].ssid.SSID_len)); + } + } +#endif /* PNO_DUMP */ + + /* clean up everything */ + if ((err = dhd_pno_clean(dhd)) < 0) { + DHD_ERROR(("%s failed error=%d\n", __FUNCTION__, err)); + return err; + } + memset(iovbuf, 0, sizeof(iovbuf)); + memset(&pfn_param, 0, sizeof(pfn_param)); + memset(&pfn_element, 0, sizeof(pfn_element)); + + /* set pfn parameters */ + pfn_param.version = htod32(PFN_VERSION); + pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); + + /* check and set extra pno params */ + if ((pno_repeat != 0) || (pno_expo_max != 0)) { + pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); + pfn_param.repeat = (uchar) (pno_repeat); + pfn_param.exp = (uchar) (pno_expo_max); + } + + /* set up pno scan fr */ + if (pno_interval != 0) + pfn_param.scan_freq = htod32(pno_interval); + + if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) { + DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC)); + return err; + } + if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) { + DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC)); + return err; + } + + /* network lost time */ + pfn_param.lost_network_timeout = htod32(pno_lost_time); + + len = bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); + if ((err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { + DHD_ERROR(("%s pfn_set failed for error=%d\n", + __FUNCTION__, err)); + return err; + } else { + DHD_TRACE(("%s pfn_set OK with PNO time=%d repeat=%d max_adjust=%d\n", + __FUNCTION__, pfn_param.scan_freq, + pfn_param.repeat, pfn_param.exp)); + } + + /* set all pfn ssid */ + for (i = 0; i < nssid; i++) { + pfn_element.flags = htod32(ssidnet[i].flags); + pfn_element.infra = htod32(ssidnet[i].infra); + pfn_element.auth = htod32(ssidnet[i].auth); + pfn_element.wpa_auth = htod32(ssidnet[i].wpa_auth); + pfn_element.wsec = htod32(ssidnet[i].wsec); + + memcpy((char *)pfn_element.ssid.SSID, ssidnet[i].ssid.SSID, ssidnet[i].ssid.SSID_len); + pfn_element.ssid.SSID_len = htod32(ssidnet[i].ssid.SSID_len); + + if ((len = + bcm_mkiovar("pfn_add", (char *)&pfn_element, + sizeof(pfn_element), iovbuf, sizeof(iovbuf))) > 0) { + if ((err = + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, len, TRUE, 0)) < 0) { + DHD_ERROR(("%s pfn_add failed with ssidnet[%d] error=%d\n", + __FUNCTION__, i, err)); + return err; + } else { + DHD_TRACE(("%s pfn_add OK with ssidnet[%d]\n", __FUNCTION__, i)); + } + } else { + DHD_ERROR(("%s bcm_mkiovar failed with ssidnet[%d]\n", __FUNCTION__, i)); + } + } + + return err; +} + int dhd_pno_get_status(dhd_pub_t *dhd) { @@ -2157,10 +2171,6 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) int str_len; int res = -1; -#ifdef HTC_KlocWork - memset(&mkeep_alive_pkt, 0, sizeof(mkeep_alive_pkt)); -#endif - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) return (res); @@ -2179,7 +2189,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) mkeep_alive_pkt.keep_alive_id = 0; mkeep_alive_pkt.len_bytes = 0; buf_len += WL_MKEEP_ALIVE_FIXED_LEN; - /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and + /* Keep-alive attributes are set in local variable (mkeep_alive_pkt), and * then memcpy'ed into buffer (mkeep_alive_pktp) since there is no * guarantee that the buffer is properly aligned. */ @@ -2190,6 +2200,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) return res; } #endif /* defined(KEEP_ALIVE) */ + /* Android ComboSCAN support */ /* @@ -2199,11 +2210,7 @@ int wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, int input_size, int *bytes_left) { -#ifdef HTC_KlocWork - char* str = NULL; -#else char* str = *list_str; -#endif uint16 short_temp; uint32 int_temp; @@ -2211,9 +2218,7 @@ wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, DHD_ERROR(("%s error paramters\n", __FUNCTION__)); return -1; } -#ifdef HTC_KlocWork - str = *list_str; -#endif + /* Clean all dest bytes */ memset(dst, 0, dst_size); while (*bytes_left > 0) { @@ -2254,20 +2259,14 @@ int wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, int channel_num, int *bytes_left) { -#ifdef HTC_KlocWork - char* str = NULL; -#else char* str = *list_str; -#endif int idx = 0; if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { DHD_ERROR(("%s error paramters\n", __FUNCTION__)); return -1; } -#ifdef HTC_KlocWork - str = *list_str; -#endif + while (*bytes_left > 0) { if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { @@ -2306,20 +2305,14 @@ wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) { -#ifdef HTC_KlocWork - char* str = NULL; -#else - char* str = *list_str; -#endif + char* str; int idx = 0; if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { DHD_ERROR(("%s error paramters\n", __FUNCTION__)); return -1; } -#ifdef HTC_KlocWork str = *list_str; -#endif while (*bytes_left > 0) { if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { @@ -2411,11 +2404,7 @@ wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) ssid[idx].SSID_len = 0; if (idx < max) { -#ifdef HTC_KlocWork - bcm_strncpy_s((char*)ssid[idx].SSID, sizeof(ssid[idx].SSID), str, DOT11_MAX_SSID_LEN); -#else - bcm_strcpy_s((char*)ssid[idx].SSID, sizeof(ssid[idx].SSID), str); -#endif + bcm_strcpy_s((char*)ssid[idx].SSID, sizeof(ssid[idx].SSID), str); ssid[idx].SSID_len = strlen(str); } idx++; diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c index db06f323..9750eeb2 100644 --- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c @@ -20,7 +20,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * -* $Id: dhd_custom_gpio.c 275786 2011-08-04 22:42:42Z $ +* $Id: dhd_custom_gpio.c,v 1.2.42.1 2010-10-19 00:41:09 Exp $ */ #include @@ -41,13 +41,19 @@ extern void bcm_wlan_power_off(int); extern void bcm_wlan_power_on(int); #endif /* CUSTOMER_HW */ -#if defined(CUSTOMER_HW2) -int wifi_set_carddetect(int on); +#if defined(CUSTOMER_HW2) +#ifdef CONFIG_WIFI_CONTROL_FUNC int wifi_set_power(int on, unsigned long msec); int wifi_get_irq_number(unsigned long *irq_flags_ptr); int wifi_get_mac_addr(unsigned char *buf); void *wifi_get_country_code(char *ccode); -#endif +#else +int wifi_set_power(int on, unsigned long msec) { return -1; } +int wifi_get_irq_number(unsigned long *irq_flags_ptr) { return -1; } +int wifi_get_mac_addr(unsigned char *buf) { return -1; } +void *wifi_get_country_code(char *ccode) { return NULL; } +#endif /* CONFIG_WIFI_CONTROL_FUNC */ +#endif /* CUSTOMER_HW2 */ #if defined(OOB_INTR_ONLY) @@ -283,5 +289,5 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) cspec->rev = translate_custom_table[0].custom_locale_rev; #endif /* EXMAPLE_TABLE */ return; -#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) */ +#endif /* defined(CUSTOMER_HW2) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */ } diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h index 00ee7e43..01be6a1f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_dbg.h +++ b/drivers/net/wireless/bcmdhd/dhd_dbg.h @@ -27,12 +27,10 @@ #ifndef _dhd_dbg_ #define _dhd_dbg_ -#if defined(DHD_DEBUG) || defined(DHD_PRINT_DEBUG) +#if defined(DHD_DEBUG) -#define DHD_DEFAULT(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ - printf args;} while (0) -#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ - wrnprintf args;} while (0) +#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ + printf args;} while (0) #define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0) #define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0) #define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0) @@ -64,8 +62,7 @@ #else /* defined(BCMDBG) || defined(DHD_DEBUG) */ -#define DHD_DEFAULT(args) do {if (net_ratelimit()) printf args;} while (0) -#define DHD_ERROR(args) do {if (net_ratelimit()) wrnprintf args;} while (0) +#define DHD_ERROR(args) do {if (net_ratelimit()) printf args;} while (0) #define DHD_TRACE(args) #define DHD_INFO(args) #define DHD_DATA(args) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 774fd7b2..d32ce113 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 288104 2011-10-06 01:54:08Z $ + * $Id: dhd_linux.c 333885 2012-05-18 00:39:03Z $ */ #include @@ -42,12 +42,6 @@ #include #include #include -/* HTC_CSP_START */ -#include -#ifdef CONFIG_PERFLOCK -#include -#endif -/* HTC_CSP_END */ #include #include @@ -55,6 +49,7 @@ #include #include #include +#include #include #include @@ -73,19 +68,6 @@ #include #include -extern int bcm_chip_is_4330b1; -extern int bcm_chip_is_4330; -/* HTC_CSP_START */ -dhd_pub_t *priv_dhdp = NULL; - -#define htod32(i) i -#define htod16(i) i -#define dtoh32(i) i -#define dtoh16(i) i -/* HTC_CSP_END */ -static int module_insert = 0; -int module_remove = 0; - #ifdef WLMEDIA_HTSF #include #include @@ -116,7 +98,6 @@ static histo_t vi_d1, vi_d2, vi_d3, vi_d4; extern bool ap_cfg_running; extern bool ap_fw_loaded; #endif -bool wifi_fail_retry = false; /* enable HOSTIP cache update from the host side when an eth0:N is up */ #define AOE_IP_ALIAS_SUPPORT 1 @@ -148,6 +129,9 @@ DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); #if defined(OOB_INTR_ONLY) extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); #endif /* defined(OOB_INTR_ONLY) */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +static void dhd_hang_process(struct work_struct *work); +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL v2"); #endif /* LinuxVer */ @@ -169,16 +153,15 @@ print_tainted() #endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ /* Linux wireless extension support */ -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) #include extern wl_iw_extra_params_t g_wl_iw_params; -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ -#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) #include -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +extern int dhd_get_dtim_skip(dhd_pub_t *dhd); #ifdef PKT_FILTER_SUPPORT extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); @@ -232,9 +215,9 @@ static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0; /* Local private structure (extension of pub) */ typedef struct dhd_info { -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) wl_iw_t iw; /* wireless extensions state (must be first) */ -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ dhd_pub_t pub; @@ -267,23 +250,28 @@ typedef struct dhd_info { bool dhd_tasklet_create; #endif /* DHDTHREAD */ tsk_ctl_t thr_sysioc_ctl; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + struct work_struct work_hang; +#endif /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct wake_lock wl_wifi; /* Wifi wakelock */ struct wake_lock wl_rxwake; /* Wifi rx wakelock */ - struct wake_lock wl_htc; /* HTC timeout wakelock */ + struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) /* net_device interface lock, prevent race conditions among net_dev interface * calls and wifi_on or wifi_off */ struct mutex dhd_net_if_mutex; + struct mutex dhd_suspend_mutex; #endif spinlock_t wakelock_spinlock; int wakelock_counter; - int wakelock_timeout_enable; + int wakelock_rx_timeout_enable; + int wakelock_ctrl_timeout_enable; /* Thread to issue ioctl for multicast */ bool set_macaddress; @@ -292,25 +280,31 @@ typedef struct dhd_info { atomic_t pend_8021x_cnt; dhd_attach_states_t dhd_state; -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) struct early_suspend early_suspend; #endif /* CONFIG_HAS_EARLYSUSPEND */ + #ifdef ARP_OFFLOAD_SUPPORT u32 pend_ipaddr; #endif /* ARP_OFFLOAD_SUPPORT */ - bool dhd_force_exit; } dhd_info_t; /* Definitions to provide path to the firmware and nvram * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt" */ char firmware_path[MOD_PARAM_PATHLEN]; -char fwb1_path[MOD_PARAM_PATHLEN]; -char fwb2_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; +/* load firmware and/or nvram values from the filesystem */ +module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); +module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); + +char info_string[MOD_PARAM_INFOLEN]; +module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444); + +int op_mode = 0; +module_param(op_mode, int, 0644); extern int wl_control_wl_start(struct net_device *dev); -extern int net_os_send_hang_message(struct net_device *dev); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct semaphore dhd_registration_sem; #define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */ @@ -323,19 +317,13 @@ module_param(dhd_sysioc, uint, 0); /* Error bits */ module_param(dhd_msg_level, int, 0); -/* load firmware and/or nvram values from the filesystem */ -module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); -module_param_string(fwb1_path, fwb1_path, MOD_PARAM_PATHLEN, 0); -module_param_string(fwb2_path, fwb2_path, MOD_PARAM_PATHLEN, 0); -module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); - /* Watchdog interval */ uint dhd_watchdog_ms = 10; module_param(dhd_watchdog_ms, uint, 0); #if defined(DHD_DEBUG) /* Console poll interval */ -uint dhd_console_ms = 250; +uint dhd_console_ms = 0; module_param(dhd_console_ms, uint, 0644); #endif /* defined(DHD_DEBUG) */ @@ -357,27 +345,22 @@ module_param(dhd_pkt_filter_init, uint, 0); /* Pkt filter mode control */ uint dhd_master_mode = TRUE; -module_param(dhd_master_mode, uint, 1); +module_param(dhd_master_mode, uint, 0); #ifdef DHDTHREAD /* Watchdog thread priority, -1 to use kernel timer */ -int dhd_watchdog_prio = 97; +int dhd_watchdog_prio = 0; module_param(dhd_watchdog_prio, int, 0); /* DPC thread priority, -1 to use tasklet */ -int dhd_dpc_prio = 98; +int dhd_dpc_prio = 1; module_param(dhd_dpc_prio, int, 0); -/* DPC thread priority, -1 to use tasklet */ extern int dhd_dongle_memsize; module_param(dhd_dongle_memsize, int, 0); #endif /* DHDTHREAD */ /* Control fw roaming */ -#ifdef CUSTOMER_HW2 uint dhd_roam_disable = 0; -#else -uint dhd_roam_disable = 1; -#endif /* Control radio state */ uint dhd_radio_up = 1; @@ -386,25 +369,6 @@ uint dhd_radio_up = 1; char iface_name[IFNAMSIZ] = {'\0'}; module_param_string(iface_name, iface_name, IFNAMSIZ, 0); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define DAEMONIZE(a) daemonize(a); \ - allow_signal(SIGKILL); \ - allow_signal(SIGTERM); -#else /* Linux 2.4 (w/o preemption patch) */ -#define RAISE_RX_SOFTIRQ() \ - cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) -#define DAEMONIZE(a) daemonize(); \ - do { if (a) \ - strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ - } while (0); -#endif /* LINUX_VERSION_CODE */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define BLOCKABLE() (!in_atomic()) -#else -#define BLOCKABLE() (!in_interrupt()) -#endif - /* The following are specific to the SDIO dongle */ /* IOCTL response timeout */ @@ -470,6 +434,11 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR ; static void dhd_net_if_lock_local(dhd_info_t *dhd); 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); +#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) +static u32 dhd_concurrent_fw(dhd_pub_t *dhd); +#endif #ifdef WLMEDIA_HTSF void htsf_update(dhd_info_t *dhd, void *data); @@ -488,9 +457,9 @@ int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ static void dhd_dpc(ulong data); /* forward decl */ @@ -507,25 +476,22 @@ static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event_ptr, void **data_ptr); -#define WLC_HT_TKIP_RESTRICT 0x02 /* restrict HT with WEP */ -#define WLC_HT_WEP_RESTRICT 0x01 /* restrict HT with TKIP */ - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) { int ret = NOTIFY_DONE; -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) - switch (action) { +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) + switch (action) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: dhd_mmc_suspend = TRUE; - ret = NOTIFY_OK; + ret = NOTIFY_OK; break; case PM_POST_HIBERNATION: case PM_POST_SUSPEND: dhd_mmc_suspend = FALSE; - ret = NOTIFY_OK; + ret = NOTIFY_OK; break; } smp_mb(); @@ -535,7 +501,7 @@ static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long actio static struct notifier_block dhd_sleep_pm_notifier = { .notifier_call = dhd_sleep_pm_callback, - .priority = 0 + .priority = 10 }; extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); @@ -547,7 +513,8 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) DHD_TRACE(("%s: %d\n", __FUNCTION__, value)); /* 1 - Enable packet filter, only allow unicast packet to send up */ /* 0 - Disable packet filter */ - if (dhd_pkt_filter_enable) { + if (dhd_pkt_filter_enable && (!value || + (dhd_check_ap_wfd_mode_set(dhd) == FALSE))) { int i; for (i = 0; i < dhd->pktfilter_count; i++) { @@ -559,274 +526,87 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) #endif } -#if defined(CONFIG_HAS_EARLYSUSPEND) -/* HTC_CSP_START */ -/* void wl_iw_set_screen_off(int off); */ -void wl_android_set_screen_off(int off); -dhd_pub_t *pdhd = NULL; -#ifdef BCM4329_LOW_POWER -char ip_str[32]; -bool hasDLNA = false; -bool allowMulticast = false; -int dhd_set_keepalive(int value); -#endif -extern int wl_pattern_atoh(char *src, char *dst); -/* HTC_CSP_END */ static int dhd_set_suspend(int value, dhd_pub_t *dhd) { -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - int ignore_bcmc = 1; + int power_mode = PM_MAX; + /* wl_pkt_filter_enable_t enable_parm; */ char iovbuf[32]; - int is_screen_off = value; -#endif -/* HTC_CSP_END */ - -#ifdef CUSTOMER_HW2 -// uint roamvar = 1; -#endif /* CUSTOMER_HW2 */ + int bcn_li_dtim = 3; + uint roamvar = 1; DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n", __FUNCTION__, value, dhd->in_suspend)); -/* HTC_CSP_START */ - /* indicate wl_iw screen off */ - wl_android_set_screen_off(is_screen_off); - /* wl_iw_set_screen_off(is_screen_off); */ -/* HTC_CSP_END */ - - + dhd_suspend_lock(dhd); if (dhd && dhd->up) { if (value && dhd->in_suspend) { -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - if (!hasDLNA && !allowMulticast) - { - /* ignore broadcast and multicast packet*/ - bcm_mkiovar("pm_ignore_bcmc", (char *)&ignore_bcmc, - 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* keep alive packet*/ - dhd_set_keepalive(1); - } -#endif -/* HTC_CSP_END */ - - /* Kernel suspended */ - DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__)); - -#ifdef PNO_SUPPORT - /* set pfn */ - dhd_set_pfn(dhd, 1); -#endif - -/* HTC_CSP_START */ - /* browser no need active mode in screen off */ - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE); - dhdhtc_update_wifi_power_mode(is_screen_off); - dhdhtc_update_dtim_listen_interval(is_screen_off); -/* HTC_CSP_END */ - - } else { - -/* HTC_CSP_START */ - dhdhtc_update_wifi_power_mode(is_screen_off); - dhdhtc_update_dtim_listen_interval(is_screen_off); -/* HTC_CSP_END */ - - /* Kernel resumed */ - DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); - -#ifdef PNO_SUPPORT - dhd_set_pfn(dhd, 0); -#endif - -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - ignore_bcmc = 0; - /* Not ignore broadcast and multicast packet*/ - bcm_mkiovar("pm_ignore_bcmc", (char *)&ignore_bcmc, - 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* Disable keep alive packet*/ - dhd_set_keepalive(0); -#endif -/* HTC_CSP_END */ - - } - } - - return 0; -} - -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER -int dhd_set_keepalive(int value) -{ - char *str; - int str_len; - int buf_len; - char buf[256]; - wl_keep_alive_pkt_t keep_alive_pkt; - wl_keep_alive_pkt_t *keep_alive_pktp; - char mac_buf[16]; - dhd_pub_t *dhd = pdhd; - char packetstr[128]; -#ifdef HTC_KlocWork - memset(&keep_alive_pkt, 0, sizeof(keep_alive_pkt)); -#endif - /* Set keep-alive attributes */ - str = "keep_alive"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[str_len] = '\0'; - buf_len = str_len + 1; - keep_alive_pktp = (wl_keep_alive_pkt_t *) (buf + str_len + 1); - - if (value == 0) { - keep_alive_pkt.period_msec = htod32(60000); // Default 60s NULL keepalive packet - strncpy(packetstr, "0x6e756c6c207061636b657400", 26); - packetstr[26] = '\0'; - } else { - keep_alive_pkt.period_msec = htod32(15000); // 15s - /* temp packet content */ - strncpy(packetstr, "0xFFFFFFFFFFFF00112233445508060001080006040002002376cf51880a090a09FFFFFFFFFFFFFFFFFFFF", 86); - /* put mac address in */ - sprintf( mac_buf, "%02x%02x%02x%02x%02x%02x", - dhd->mac.octet[0], dhd->mac.octet[1], dhd->mac.octet[2], - dhd->mac.octet[3], dhd->mac.octet[4], dhd->mac.octet[5] - ); - /* put MAC address in */ - memcpy( packetstr+14, mac_buf, ETHER_ADDR_LEN*2); - memcpy( packetstr+46, mac_buf, ETHER_ADDR_LEN*2); - /* put IP address in */ - memcpy( packetstr+58, ip_str, 8); - /* put Default gateway in */ - memcpy(packetstr+78, wl_abdroid_gatewaybuf, 8); - packetstr[86] = '\0'; - DHD_DEFAULT(("%s:Default gateway:%s\n", __FUNCTION__, packetstr)); - } - - keep_alive_pkt.len_bytes = htod16(wl_pattern_atoh(packetstr, (char*)keep_alive_pktp->data)); - - buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes); - - /* Keep-alive attributes are set in local variable (keep_alive_pkt), and - * then memcpy'ed into buffer (keep_alive_pktp) since there is no - * guarantee that the buffer is properly aligned. - */ - memcpy((char*)keep_alive_pktp, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN); - - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0); - - return 0; -} -#endif + /* Kernel suspended */ + DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); -/* bitmask, bit value: 1 - enable, 0 - disable - */ -static unsigned int dhdhtc_power_ctrl_mask = 0; -int dhdcdc_power_active_while_plugin = 1; -int dhdcdc_wifiLock = 0; /* to keep wifi power mode as PM_FAST and bcn_li_dtim as 0 */ -extern int usb_get_connect_type(void); // msm72k_udc.c + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); -int dhdhtc_update_wifi_power_mode(int is_screen_off) -{ - int pm_type; - dhd_pub_t *dhd = pdhd; + /* Enable packet filter, only allow unicast packet to send up */ + dhd_set_packet_filter(1, dhd); - if (!dhd) { - printf("dhd is not attached\n"); - return -1; - } + /* If DTIM skip is set up as default, force it to wake + * each third DTIM for better power savings. Note that + * one side effect is a chance to miss BC/MC packet. + */ + bcn_li_dtim = dhd_get_dtim_skip(dhd); + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + + /* Disable firmware roaming during suspend */ + bcm_mkiovar("roam_off", (char *)&roamvar, 4, + iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } else { - if (dhdhtc_power_ctrl_mask) { - printf("power active. ctrl_mask: 0x%x\n", dhdhtc_power_ctrl_mask); - pm_type = PM_OFF; - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&pm_type, sizeof(pm_type), TRUE, 0); - } else if (dhdcdc_power_active_while_plugin && usb_get_connect_type()) { - printf("power active. usb_type:%d\n", usb_get_connect_type()); - pm_type = PM_OFF; - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&pm_type, sizeof(pm_type), TRUE, 0); - } else { - if (is_screen_off && !dhdcdc_wifiLock) - pm_type = PM_MAX; - else - pm_type = PM_FAST; - printf("update pm: %s, wifiLock: %d\n", pm_type==1?"PM_MAX":"PM_FAST", dhdcdc_wifiLock); - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&pm_type, sizeof(pm_type), TRUE, 0); - } + /* Kernel resumed */ + DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); - return 0; -} + power_mode = PM_FAST; + dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode), TRUE, 0); + /* disable pkt filter */ + dhd_set_packet_filter(0, dhd); -int dhdhtc_set_power_control(int power_mode, unsigned int reason) -{ + /* restore pre-suspend setting for dtim_skip */ + bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, + 4, iovbuf, sizeof(iovbuf)); - if (reason < DHDHTC_POWER_CTRL_MAX_NUM) { - if (power_mode) { - dhdhtc_power_ctrl_mask |= 0x1<pub; + int ret = 0; DHD_OS_WAKE_LOCK(dhdp); /* Set flag when early suspend was called */ dhdp->in_suspend = val; - if ((!dhdp->suspend_disable_flag) && (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) - dhd_set_suspend(val, dhdp); + if ((force || !dhdp->suspend_disable_flag) && + (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) { + ret = dhd_set_suspend(val, dhdp); + } DHD_OS_WAKE_UNLOCK(dhdp); + return ret; } +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) static void dhd_early_suspend(struct early_suspend *h) { struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend); @@ -834,7 +614,7 @@ static void dhd_early_suspend(struct early_suspend *h) DHD_TRACE(("%s: enter\n", __FUNCTION__)); if (dhd) - dhd_suspend_resume_helper(dhd, 1); + dhd_suspend_resume_helper(dhd, 1, 0); } static void dhd_late_resume(struct early_suspend *h) @@ -844,7 +624,7 @@ static void dhd_late_resume(struct early_suspend *h) DHD_TRACE(("%s: enter\n", __FUNCTION__)); if (dhd) - dhd_suspend_resume_helper(dhd, 0); + dhd_suspend_resume_helper(dhd, 0, 0); } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ @@ -866,7 +646,7 @@ dhd_timeout_start(dhd_timeout_t *tmo, uint usec) tmo->limit = usec; tmo->increment = 0; tmo->elapsed = 0; - tmo->tick = 1000000 / HZ; + tmo->tick = jiffies_to_usecs(1); } int @@ -892,16 +672,12 @@ dhd_timeout_expired(dhd_timeout_t *tmo) } else { wait_queue_head_t delay_wait; DECLARE_WAITQUEUE(wait, current); - int pending; init_waitqueue_head(&delay_wait); add_wait_queue(&delay_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(1); - pending = signal_pending(current); remove_wait_queue(&delay_wait, &wait); set_current_state(TASK_RUNNING); - if (pending) - return 1; /* Interrupted */ } return 0; @@ -992,24 +768,6 @@ dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx) } -void -dhd_state_set_flags(dhd_pub_t *dhdp, dhd_attach_states_t flags, int add) -{ - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - - ASSERT(dhd); - - if (add) { - DHD_INFO(("%s: add flags %x to dhd_state(%x).\n", __FUNCTION__, flags, dhd->dhd_state)); - dhd->dhd_state |= flags; - } else { - DHD_INFO(("%s: remove flags %x to dhd_state(%x).\n", __FUNCTION__, flags, dhd->dhd_state)); - dhd->dhd_state &= (~flags); - } - - DHD_INFO(("%s: dhd_state=%x.\n", __FUNCTION__, dhd->dhd_state)); -} - static void _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) { @@ -1026,10 +784,6 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) uint buflen; int ret; - if (module_remove) { - printf("%s: module removed.\n", __FUNCTION__); - return; - } ASSERT(dhd && dhd->iflist[ifidx]); dev = dhd->iflist[ifidx]->net; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) @@ -1159,11 +913,6 @@ _dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr) wl_ioctl_t ioc; int ret; - if (module_remove) { - printf("%s: module removed.\n", __FUNCTION__); - return -1; - } - if (!bcm_mkiovar("cur_etheraddr", (char*)addr, ETHER_ADDR_LEN, buf, 32)) { DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n", dhd_ifname(&dhd->pub, ifidx))); return -1; @@ -1202,7 +951,6 @@ dhd_op_if(dhd_if_t *ifp) if (!ifp || !ifp->info || !ifp->idx) return; ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */ - dhd = ifp->info; DHD_TRACE(("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state)); @@ -1273,12 +1021,18 @@ dhd_op_if(dhd_if_t *ifp) DHD_TRACE(("\n%s: got 'DHD_IF_DEL' state\n", __FUNCTION__)); #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { - wl_cfg80211_notify_ifdel(ifp->net); + wl_cfg80211_ifdel_ops(ifp->net); } #endif netif_stop_queue(ifp->net); unregister_netdev(ifp->net); - ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ + ret = DHD_DEL_IF; + +#ifdef WL_CFG80211 + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + wl_cfg80211_notify_ifdel(); + } +#endif } break; case DHD_IF_DELETING: @@ -1325,8 +1079,6 @@ _dhd_sysioc_thread(void *data) while (down_interruptible(&tsk->sema) == 0) { - if (dhd->dhd_force_exit== TRUE) - break; SMP_RD_BARRIER_DEPENDS(); if (tsk->terminated) { break; @@ -1393,18 +1145,11 @@ dhd_set_mac_address(struct net_device *dev, void *addr) struct sockaddr *sa = (struct sockaddr *)addr; int ifidx; - printf("enter %s\n", __func__); - - /* BRCM: anthony, add for debug, reject if down */ - if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) { - printf("%s: dhd is down. skip it.\n", __func__); - return -ENODEV; - } ifidx = dhd_net2idx(dhd, dev); if (ifidx == DHD_BAD_IF) return -1; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); memcpy(&dhd->macvalue, sa->sa_data, ETHER_ADDR_LEN); dhd->set_macaddress = TRUE; up(&dhd->thr_sysioc_ctl.sema); @@ -1417,19 +1162,12 @@ dhd_set_multicast_list(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ifidx; - printf("enter %s\n", __func__); - - /* BRCM: anthoy, add for debug, reject if down */ - if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN) ) { - printf("%s: dhd is down. skip it.\n", __func__); - return; - } ifidx = dhd_net2idx(dhd, dev); if (ifidx == DHD_BAD_IF) return; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); dhd->iflist[ifidx]->set_multicast = TRUE; up(&dhd->thr_sysioc_ctl.sema); } @@ -1440,6 +1178,7 @@ dhd_os_wlfc_block(dhd_pub_t *pub) { dhd_info_t *di = (dhd_info_t *)(pub->info); ASSERT(di != NULL); + spin_lock_bh(&di->wlfc_spinlock); return 1; } @@ -1448,8 +1187,6 @@ int dhd_os_wlfc_unblock(dhd_pub_t *pub) { dhd_info_t *di = (dhd_info_t *)(pub->info); - - (void)di; ASSERT(di != NULL); spin_unlock_bh(&di->wlfc_spinlock); return 1; @@ -1484,8 +1221,8 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) atomic_inc(&dhd->pend_8021x_cnt); } else { - PKTFREE(dhd->pub.osh, pktbuf, TRUE); - return BCME_ERROR; + PKTFREE(dhd->pub.osh, pktbuf, TRUE); + return BCME_ERROR; } /* Look into the packet and update the packet priority */ @@ -1539,9 +1276,6 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) return ret; } -/* HTC_CSP_START */ -static int txq_full_event_num = 0; -/* HTC_CSP_END */ int dhd_start_xmit(struct sk_buff *skb, struct net_device *net) { @@ -1557,15 +1291,6 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); -/* HTC_CSP_START */ - if (module_remove) { - printf("%s: module removed.", __FUNCTION__); - dev_kfree_skb(skb); /* Add to free skb */ - netif_stop_queue(net); - return -ENODEV; - } -/* HTC_CSP_END */ - DHD_OS_WAKE_LOCK(&dhd->pub); /* Reject if down */ @@ -1573,14 +1298,13 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n", __FUNCTION__, dhd->pub.up, dhd->pub.busstate)); netif_stop_queue(net); -/* HTC_CSP_START */ - dev_kfree_skb(skb); -/* HTC_CSP_END */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) /* Send Event when bus down detected during data session */ if (dhd->pub.busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s: Event HANG sent up\n", __FUNCTION__)); net_os_send_hang_message(net); } +#endif DHD_OS_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -1589,9 +1313,6 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) if (ifidx == DHD_BAD_IF) { DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); netif_stop_queue(net); -/* HTC_CSP_START */ - dev_kfree_skb(skb); -/* HTC_CSP_END */ DHD_OS_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -1637,21 +1358,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) #endif ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf); -/* HTC_CSP_START */ - /* check if "out of bus->txq" event happended */ - if ( ret == BCME_NORESOURCE ) { - txq_full_event_num++; - - /* if the consequent event number is over maximum number, just send HANG event. */ - if ( txq_full_event_num >= MAX_TXQ_FULL_EVENT ) { - txq_full_event_num = 0; - net_os_send_hang_message(net); - } - } - else { - txq_full_event_num = 0; - } -/* HTC_CSP_END */ + done: if (ret) @@ -1707,31 +1414,14 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) struct sk_buff *skb; uchar *eth; uint len; - void *data = NULL, *pnext = NULL, *save_pktbuf; + void *data, *pnext = NULL, *save_pktbuf; int i; dhd_if_t *ifp; wl_event_msg_t event; - int tout = DHD_PACKET_TIMEOUT; -#ifdef HTC_KlocWork - memset(&event,0,sizeof(event)); -#endif - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + int tout_rx = 0; + int tout_ctrl = 0; -/* HTC_CSP_START */ - if (module_remove || (!module_insert)) { - for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) { - pnext = PKTNEXT(dhdp->osh, pktbuf); - PKTSETNEXT(wl->sh.osh, pktbuf, NULL); - skb = PKTTONATIVE(dhdp->osh, pktbuf); - dev_kfree_skb_any(skb); - } - if (!module_insert) - DHD_ERROR(("%s: module not insert, skip\n", __FUNCTION__)); - else - DHD_ERROR(("%s: module removed. skip rx frame\n", __FUNCTION__)); - return; - } -/* HTC_CSP_END */ + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); save_pktbuf = pktbuf; @@ -1741,12 +1431,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) ifp = dhd->iflist[ifidx]; if (ifp == NULL) { - DHD_ERROR(("%s: ifp is NULL. drop packet \n", - __FUNCTION__)); - PKTFREE(dhdp->osh, pktbuf, TRUE); - continue; + DHD_ERROR(("%s: ifp is NULL. drop packet\n", + __FUNCTION__)); + PKTFREE(dhdp->osh, pktbuf, TRUE); + continue; } - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) /* Dropping packets before registering net device to avoid kernel panic */ if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) { @@ -1755,6 +1445,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) PKTFREE(dhdp->osh, pktbuf, TRUE); continue; } +#endif pnext = PKTNEXT(dhdp->osh, pktbuf); PKTSETNEXT(wl->sh.osh, pktbuf, NULL); @@ -1779,6 +1470,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) */ ((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++; PKTFREE(dhdp->osh, pktbuf, TRUE); + DHD_TRACE(("RX: wlfc header \n")); continue; } #endif @@ -1830,16 +1522,18 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) &data); wl_event_to_host_order(&event); + if (!tout_ctrl) + tout_ctrl = DHD_PACKET_TIMEOUT_MS; if (event.event_type == WLC_E_BTA_HCI_EVENT) { -#ifdef HTC_KlocWork - if(!data) { - printf("[HTCKW] dhd_rx_frame: data=NULL\n"); - } - else -#endif dhd_bta_doevt(dhdp, data, event.datalen); } - tout = DHD_EVENT_TIMEOUT; +#ifdef PNO_SUPPORT + if (event.event_type == WLC_E_PFN_NET_FOUND) { + tout_ctrl *= 2; + } +#endif /* PNO_SUPPORT */ + } else { + tout_rx = DHD_PACKET_TIMEOUT_MS; } ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); @@ -1872,7 +1566,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ } } - DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(dhdp, tout); + + DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); } void @@ -1935,11 +1631,8 @@ dhd_get_stats(struct net_device *net) ASSERT(dhd && ifp); if (dhd->pub.up) { - if (module_remove) { - printf("%s: module removed. return old value. ifp=%p, dhd=%p\n", __FUNCTION__, ifp, dhd); - } else - /* Use the protocol to get dongle stats */ - dhd_prot_dstats(&dhd->pub); + /* Use the protocol to get dongle stats */ + dhd_prot_dstats(&dhd->pub); } /* Copy dongle stats to net device stats */ @@ -1977,11 +1670,9 @@ dhd_watchdog_thread(void *data) /* Run until signal received */ complete(&tsk->completed); - while (1) { + while (1) if (down_interruptible (&tsk->sema) == 0) { unsigned long flags; - if (dhd->dhd_force_exit== TRUE) - break; SMP_RD_BARRIER_DEPENDS(); if (tsk->terminated) { @@ -2001,7 +1692,7 @@ dhd_watchdog_thread(void *data) /* Reschedule the watchdog */ if (dhd->wd_timer_valid) mod_timer(&dhd->timer, - jiffies + dhd_watchdog_ms * HZ / 1000); + jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd_os_spin_unlock(&dhd->pub, flags); } dhd_os_sdunlock(&dhd->pub); @@ -2009,7 +1700,7 @@ dhd_watchdog_thread(void *data) } else { break; } - } + complete_and_exit(&tsk->completed, 0); } #endif /* DHDTHREAD */ @@ -2029,9 +1720,6 @@ static void dhd_watchdog(ulong data) if (dhd->thr_wdt_ctl.thr_pid >= 0) { up(&dhd->thr_wdt_ctl.sema); return; - } else { - DHD_ERROR(("watch_dog thr stopped, ignore\n")); - return; } #endif /* DHDTHREAD */ @@ -2045,29 +1733,12 @@ static void dhd_watchdog(ulong data) /* Reschedule the watchdog */ if (dhd->wd_timer_valid) - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd_os_spin_unlock(&dhd->pub, flags); dhd_os_sdunlock(&dhd->pub); DHD_OS_WAKE_UNLOCK(&dhd->pub); } -/* HTC_CSP_START */ -extern int wlan_ioprio_idle; -static int prev_wlan_ioprio_idle=0; -static inline void set_wlan_ioprio(void) -{ - int ret, prio; - - if(wlan_ioprio_idle == 1){ - prio = ((IOPRIO_CLASS_IDLE << IOPRIO_CLASS_SHIFT) | 0); - } else { - prio = ((IOPRIO_CLASS_NONE << IOPRIO_CLASS_SHIFT) | 4); - } - ret = set_task_ioprio(current, prio); - DHD_DEFAULT(("set_wlan_ioprio: prio=0x%X, ret=%d\n", prio, ret)); -} -/* HTC_CSP_END */ - #ifdef DHDTHREAD static int dhd_dpc_thread(void *data) @@ -2093,15 +1764,7 @@ dhd_dpc_thread(void *data) /* Run until signal received */ while (1) { - /* HTC_CSP_START */ - if(prev_wlan_ioprio_idle != wlan_ioprio_idle){ - set_wlan_ioprio(); - prev_wlan_ioprio_idle = wlan_ioprio_idle; - } - /* HTC_CSP_END */ if (down_interruptible(&tsk->sema) == 0) { - if (dhd->dhd_force_exit== TRUE) - break; SMP_RD_BARRIER_DEPENDS(); if (tsk->terminated) { @@ -2373,6 +2036,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) if (!dhdp) return FALSE; if ((error == -ETIMEDOUT) || ((dhdp->busstate == DHD_BUS_DOWN) && @@ -2382,8 +2046,10 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) net_os_send_hang_message(net); return TRUE; } +#endif return FALSE; } + static int dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) { @@ -2396,24 +2062,12 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) int ifidx; int ret; -/* HTC_CSP_START */ - if (module_remove) { - printf("%s: module removed. cmd 0x%04x\n", __FUNCTION__, cmd); - return -1; - } -/* HTC_CSP_END */ - - /* BRCM: anthoy, add for debug, reject if down */ - if ( !dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)){ - printf("%s: dhd is down. skip it.\n", __func__); - return -ENODEV; - } DHD_OS_WAKE_LOCK(&dhd->pub); /* send to dongle only if we are not waiting for reload already */ if (dhd->pub.hang_was_sent) { DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); - DHD_OS_WAKE_LOCK_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); DHD_OS_WAKE_UNLOCK(&dhd->pub); return OSL_ERROR(BCME_DONGLE_DOWN); } @@ -2427,7 +2081,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) return -1; } -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) /* linux wireless extensions */ if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { /* may recurse, do NOT lock */ @@ -2435,7 +2089,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) DHD_OS_WAKE_UNLOCK(&dhd->pub); return ret; } -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) if (cmd == SIOCETHTOOL) { @@ -2620,17 +2274,17 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) #endif for (i = 1; i < DHD_MAX_IFS; i++) { + dhd_net_if_lock_local(dhd); if (dhd->iflist[i]) { DHD_TRACE(("Deleting IF: %d \n", i)); if ((dhd->iflist[i]->state != DHD_IF_DEL) && (dhd->iflist[i]->state != DHD_IF_DELETING)) { dhd->iflist[i]->state = DHD_IF_DEL; dhd->iflist[i]->idx = i; - dhd_net_if_lock_local(dhd); dhd_op_if(dhd->iflist[i]); - dhd_net_if_unlock_local(dhd); } } + dhd_net_if_unlock_local(dhd); } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) @@ -2645,10 +2299,10 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) static int dhd_stop(struct net_device *net) { - int ifidx; + int ifidx = 0; dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); DHD_OS_WAKE_LOCK(&dhd->pub); - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + DHD_TRACE(("%s: Enter %p\n", __FUNCTION__, net)); if (dhd->pub.up == 0) { goto exit; } @@ -2679,78 +2333,18 @@ dhd_stop(struct net_device *net) /* Stop the protocol module */ dhd_prot_stop(&dhd->pub); -#if defined(WL_CFG80211) -/* #ifndef MODULE */ + OLD_MOD_DEC_USE_COUNT; +exit: +#if defined(WL_CFG80211) if (ifidx == 0 && !dhd_download_fw_on_driverload) wl_android_wifi_off(net); -/* #endif */ -#endif - dhd->pub.hang_was_sent = 0; +#endif dhd->pub.rxcnt_timeout = 0; dhd->pub.txcnt_timeout = 0; - OLD_MOD_DEC_USE_COUNT; -exit: + DHD_OS_WAKE_UNLOCK(&dhd->pub); return 0; } -#ifdef DHD_BCM_WIFI_HDMI -bool dhd_bcm_whdmi_enable = FALSE; - -/* Check for the presence of a given kernel parameter string, - * eg. "wifi=4330_whdmi". Returns 0 if found. - */ -static int -dhd_check_kernel_param(dhd_info_t *dhd, const char *str) -{ -#define DHD_KPARAM_LEN 1024 - int bcmerror = -1; - uint len; - void *fp = NULL; - char *kparam = NULL; - - DHD_INFO(("%s\n", __func__)); - - fp = dhd_os_open_image("/proc/cmdline"); - if (fp == NULL) - goto err; - - kparam = MALLOC(dhd->pub.osh, DHD_KPARAM_LEN); - if (kparam == NULL) { - DHD_ERROR(("%s: MALLOC of %u bytes failed!\n", - __func__, DHD_KPARAM_LEN)); - goto err; - } - - /* Read the kernel cmdline and search for a matching string */ - len = dhd_os_get_image_block(kparam, DHD_KPARAM_LEN, fp); - if (len > 0) { - kparam[DHD_KPARAM_LEN - 1] = '\0'; - if (strstr(kparam, str) != NULL) - bcmerror = 0; - /* - DHD_ERROR(("%s: err=%d len=%u kparam=%s\n", - __FUNCTION__, bcmerror, len, kparam)); - */ - } - -err: - if (kparam) - MFREE(dhd->pub.osh, kparam, DHD_KPARAM_LEN); - - dhd_os_close_image(fp); - - return bcmerror; -} -#endif /* DHD_BCM_WIFI_HDMI */ - -#define BCM4330B1_STA_FW_PATH "/system/etc/firmware/fw_bcm4330_b1.bin" -#define BCM4330B1_APSTA_FW_PATH "/system/etc/firmware/fw_bcm4330_apsta_b1.bin" -#define BCM4330B1_P2P_FW_PATH "/system/etc/firmware/fw_bcm4330_p2p_b1.bin" -#define BCM4330B1_MFG_FW_PATH "/system/etc/firmware/bcm_mfg.bin" -#define BCM4330B2_STA_FW_PATH "/system/etc/firmware/fw_bcm4330_b2.bin" -#define BCM4330B2_APSTA_FW_PATH "/system/etc/firmware/fw_bcm4330_apsta_b2.bin" -#define BCM4330B2_P2P_FW_PATH "/system/etc/firmware/fw_bcm4330_p2p_b2.bin" -#define BCM4330B2_MFG_FW_PATH "/system/etc/firmware/bcm_mfg2.bin" static int dhd_open(struct net_device *net) @@ -2764,78 +2358,37 @@ dhd_open(struct net_device *net) int32 ret = 0; DHD_OS_WAKE_LOCK(&dhd->pub); -/* HTC_CSP_START */ - if (module_remove) { - printf("%s: module removed. Just return.\n", __FUNCTION__); - return -1; - } -/* HTC_CSP_END */ - -#ifdef DHD_BCM_WIFI_HDMI - /* Parse kernel parameters for WHDMI enable flag */ - if (dhd_check_kernel_param(dhd, "wifi=4330_whdmi") == 0) { - dhd_bcm_whdmi_enable = TRUE; - } -#endif /* DHD_BCM_WIFI_HDMI */ - -#ifdef CONFIG_WIRELESS_EXT - if (wl_iw_get_onoff() == G_WLAN_SET_OFF) { - return -1; - } -#endif - /* Update FW path if it was changed */ if ((firmware_path != NULL) && (firmware_path[0] != '\0')) { - if (bcm_chip_is_4330) { - printf("chip is 4330!\n"); - if (strstr(firmware_path, "_apsta") != NULL) { - if (bcm_chip_is_4330b1) - strcpy(fw_path, BCM4330B1_APSTA_FW_PATH); - else - strcpy(fw_path, BCM4330B2_APSTA_FW_PATH); - } else if (strstr(firmware_path, "_p2p") != NULL) { - if (bcm_chip_is_4330b1) - strcpy(fw_path, BCM4330B1_P2P_FW_PATH); - else - strcpy(fw_path, BCM4330B2_P2P_FW_PATH); - } else if (strstr(firmware_path, "mfg") != NULL) { - if (bcm_chip_is_4330b1) - strcpy(fw_path, BCM4330B1_MFG_FW_PATH); - else - strcpy(fw_path, BCM4330B2_MFG_FW_PATH); - } else { - if (bcm_chip_is_4330b1) - strcpy(fw_path, BCM4330B1_STA_FW_PATH); - else - strcpy(fw_path, BCM4330B2_STA_FW_PATH); - } - } else { - if (firmware_path[strlen(firmware_path)-1] == '\n') - firmware_path[strlen(firmware_path)-1] = '\0'; - strcpy(fw_path, firmware_path); - } + if (firmware_path[strlen(firmware_path)-1] == '\n') + firmware_path[strlen(firmware_path)-1] = '\0'; + strcpy(fw_path, firmware_path); firmware_path[0] = '\0'; } + dhd->pub.hang_was_sent = 0; #if !defined(WL_CFG80211) /* * Force start if ifconfig_up gets called before START command * We keep WEXT's wl_control_wl_start to provide backward compatibility * This should be removed in the future */ - wl_control_wl_start(net); + ret = wl_control_wl_start(net); + if (ret != 0) { + DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; + } #endif ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); -#ifdef HTC_KlocWork if (ifidx < 0) { DHD_ERROR(("%s: Error: called with invalid IF\n", __FUNCTION__)); ret = -1; goto exit; } -#endif if (!dhd->iflist[ifidx] || dhd->iflist[ifidx]->state == DHD_IF_DEL) { DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__)); @@ -2846,14 +2399,18 @@ dhd_open(struct net_device *net) if (ifidx == 0) { atomic_set(&dhd->pend_8021x_cnt, 0); #if defined(WL_CFG80211) -/* #ifndef MODULE */ DHD_ERROR(("\n%s\n", dhd_version)); - if (!dhd_download_fw_on_driverload) - wl_android_wifi_on(net); -/* #endif */ -#endif + if (!dhd_download_fw_on_driverload) { + ret = wl_android_wifi_on(net); + if (ret != 0) { + DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; + } + } +#endif /* defined(WL_CFG80211) */ + if (dhd->pub.busstate != DHD_BUS_DATA) { - int ret; /* try to bring up bus */ if ((ret = dhd_bus_start(&dhd->pub)) != 0) { @@ -2894,24 +2451,52 @@ dhd_open(struct net_device *net) OLD_MOD_INC_USE_COUNT; exit: + if (ret) + dhd_stop(net); + DHD_OS_WAKE_UNLOCK(&dhd->pub); return ret; } -osl_t * -dhd_osl_attach(void *pdev, uint bustype) +int dhd_do_driver_init(struct net_device *net) { - return osl_attach(pdev, bustype, TRUE); -} + dhd_info_t *dhd = NULL; -void -dhd_osl_detach(osl_t *osh) -{ - if (MALLOCED(osh)) { - DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); + if (!net) { + DHD_ERROR(("Primary Interface not initialized \n")); + return -EINVAL; + } + + dhd = *(dhd_info_t **)netdev_priv(net); + + /* If driver is already initialized, do nothing + */ + if (dhd->pub.busstate == DHD_BUS_DATA) { + DHD_TRACE(("Driver already Inititalized. Nothing to do")); + return 0; + } + + if (dhd_open(net) < 0) { + DHD_ERROR(("Driver Init Failed \n")); + return -1; + } + + return 0; +} + +osl_t * +dhd_osl_attach(void *pdev, uint bustype) +{ + return osl_attach(pdev, bustype, TRUE); +} + +void +dhd_osl_detach(osl_t *osh) +{ + if (MALLOCED(osh)) { + DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); } osl_detach(osh); - wifi_fail_retry = true; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) up(&dhd_registration_sem); #endif @@ -2952,7 +2537,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, ifp->state = DHD_IF_ADD; ifp->idx = ifidx; ifp->bssidx = bssidx; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); up(&dhd->thr_sysioc_ctl.sema); } else ifp->net = (struct net_device *)handle; @@ -2976,7 +2561,7 @@ dhd_del_if(dhd_info_t *dhd, int ifidx) ifp->state = DHD_IF_DEL; ifp->idx = ifidx; - ASSERT(&dhd->thr_sysioc_ctl.thr_pid >= 0); + ASSERT(dhd->thr_sysioc_ctl.thr_pid >= 0); up(&dhd->thr_sysioc_ctl.sema); } @@ -3012,17 +2597,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* updates firmware nvram path if it was provided as module parameters */ if ((firmware_path != NULL) && (firmware_path[0] != '\0')) strcpy(fw_path, firmware_path); - - if (bcm_chip_is_4330) { - if (bcm_chip_is_4330b1) { - if ((fwb1_path != NULL) && (fwb1_path[0] != '\0')) - strcpy(fw_path, fwb1_path); - } else { - if ((fwb2_path != NULL) && (fwb2_path[0] != '\0')) - strcpy(fw_path, fwb2_path); - } - } - if ((nvram_path != NULL) && (nvram_path[0] != '\0')) strcpy(nv_path, nvram_path); @@ -3068,30 +2642,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) strncpy(net->name, iface_name, IFNAMSIZ); net->name[IFNAMSIZ - 1] = 0; len = strlen(net->name); -#ifdef HTC_KlocWork - if(len > 0) { - ch = net->name[len - 1]; - if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) - strcat(net->name, "%d"); - } -#else - ch = net->name[len - 1]; - if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) - strcat(net->name, "%d"); -#endif + ch = net->name[len - 1]; + if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) + strcat(net->name, "%d"); } - if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF) - goto fail; - dhd_state |= DHD_ATTACH_STATE_ADD_IF; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - net->open = NULL; -#else - net->netdev_ops = NULL; -#endif - sema_init(&dhd->proto_sem, 1); + sema_init(&dhd->sdsem, 1); #ifdef PROP_TXSTATUS spin_lock_init(&dhd->wlfc_spinlock); @@ -3107,17 +2664,30 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) spin_lock_init(&dhd->txqlock); spin_lock_init(&dhd->dhd_lock); + + if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF) + goto fail; + dhd_state |= DHD_ATTACH_STATE_ADD_IF; + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) + net->open = NULL; +#else + net->netdev_ops = NULL; +#endif + /* Initialize Wakelock stuff */ spin_lock_init(&dhd->wakelock_spinlock); dhd->wakelock_counter = 0; - dhd->wakelock_timeout_enable = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; #ifdef CONFIG_HAS_WAKELOCK wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); - wake_lock_init(&dhd->wl_htc, WAKE_LOCK_SUSPEND, "wlan_htc"); + wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) mutex_init(&dhd->dhd_net_if_mutex); + mutex_init(&dhd->dhd_suspend_mutex); #endif dhd_state |= DHD_ATTACH_STATE_WAKELOCKS_INIT; @@ -3138,16 +2708,16 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_monitor_init(&dhd->pub); dhd_state |= DHD_ATTACH_STATE_CFG80211; #endif -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) /* Attach and link in the iw */ - //if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { + if (!(dhd_state & DHD_ATTACH_STATE_CFG80211)) { if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { DHD_ERROR(("wl_iw_attach failed\n")); goto fail; } dhd_state |= DHD_ATTACH_STATE_WL_ATTACH; - //} -#endif /* defined(CONFIG_WIRELESS_EXT) */ + } +#endif /* defined(WL_WIRELESS_EXT) */ /* Set up the watchdog timer */ @@ -3157,7 +2727,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #ifdef DHDTHREAD /* Initialize thread based operation and lock */ - sema_init(&dhd->sdsem, 1); if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)) { dhd->threads_only = TRUE; } @@ -3165,8 +2734,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->threads_only = FALSE; } - dhd->dhd_force_exit = FALSE; - if (dhd_dpc_prio >= 0) { /* Initialize watchdog thread */ PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0); @@ -3195,7 +2762,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->thr_sysioc_ctl.thr_pid = -1; } dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; - +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + INIT_WORK(&dhd->work_hang, dhd_hang_process); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ /* * Save the dhd_info into the priv */ @@ -3205,7 +2774,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) register_pm_notifier(&dhd_sleep_pm_notifier); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ -#ifdef CONFIG_HAS_EARLYSUSPEND +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; dhd->early_suspend.suspend = dhd_early_suspend; dhd->early_suspend.resume = dhd_late_resume; @@ -3242,9 +2811,6 @@ dhd_bus_start(dhd_pub_t *dhdp) int ret = -1; dhd_info_t *dhd = (dhd_info_t*)dhdp->info; unsigned long flags; -#ifdef CUSTOMER_HW2 - char mac_buf[16]; -#endif ASSERT(dhd); @@ -3255,12 +2821,10 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd_os_sdlock(dhdp); #endif /* DHDTHREAD */ - /* try to download image and nvram to the dongle */ if ((dhd->pub.busstate == DHD_BUS_DOWN) && (fw_path != NULL) && (fw_path[0] != '\0') && (nv_path != NULL) && (nv_path[0] != '\0')) { - printf("load firmware from %s\n", fw_path); /* wake lock moved to dhdsdio_download_firmware */ if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, fw_path, nv_path))) { @@ -3344,31 +2908,10 @@ dhd_bus_start(dhd_pub_t *dhdp) if ((ret = dhd_prot_init(&dhd->pub)) < 0) return ret; -#ifdef CUSTOMER_HW2 - if (ap_fw_loaded == FALSE) { - sprintf( mac_buf, "0x%02x%02x%02x%02x%02x%02x", - dhdp->mac.octet[0], dhdp->mac.octet[1], dhdp->mac.octet[2], - dhdp->mac.octet[3], dhdp->mac.octet[4], dhdp->mac.octet[5] ); - dhdp->pktfilter_count = 3; - /* add a default packet filter pattern */ -#if 0 - dhd_set_pktfilter(dhdp, 1, ALLOW_UNICAST, 0, "0xffffffffffff", mac_buf); - dhd_set_pktfilter(dhdp, 1, ALLOW_DHCP, 0, "0xffffffffffff000000000000ffff00000000000000000000000000000000000000000000ffff", "0xffffffffffff0000000000000800000000000000000000000000000000000000000000000044"); - dhd_set_pktfilter(dhdp, 1, ALLOW_IPV6_MULTICAST, 0, "0xffff", "0x3333"); -#endif - } -#else - dhdp->pktfilter_count = 1; - /* Setup filter to allow only unicast */ - dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00"; -#endif #ifdef WRITE_MACADDR dhd_write_macaddr(dhd->pub.mac.octet); #endif -/* HTC_CSP_START */ - priv_dhdp = dhdp; -/* HTC_CSP_END */ #ifdef ARP_OFFLOAD_SUPPORT if (dhd->pend_ipaddr) { #ifdef AOE_IP_ALIAS_SUPPORT @@ -3377,75 +2920,86 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd->pend_ipaddr = 0; } #endif /* ARP_OFFLOAD_SUPPORT */ + return 0; } -/* HTC_CSP_START */ -/* traffic indicate parameters */ -/* The throughput mapping to packet count is as below: - * 2Mbps: ~280 packets / second - * 4Mbps: ~540 packets / second - * 6Mbps: ~800 packets / second - * 8Mbps: ~1200 packets / second - * 12Mbps: ~1500 packets / second - * 14Mbps: ~1800 packets / second - * 16Mbps: ~2000 packets / second - * 18Mbps: ~2300 packets / second - * 20Mbps: ~2600 packets / second +#if !defined(AP) && defined(WLP2P) && defined(WL_ENABLE_P2P_IF) +/* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware + * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA + * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware + * would still be named as fw_bcmdhd_apsta. */ +static u32 +dhd_concurrent_fw(dhd_pub_t *dhd) +{ + int ret = 0; + char buf[WLC_IOCTL_SMLEN]; -#define TRAFFIC_HIGH_WATER_MARK 670 *(3000/1000) -#define TRAFFIC_LOW_WATER_MARK 280 * (3000/1000) - -extern dhd_pub_t *pdhd; -/* HTC_CSP_END */ + if ((!op_mode) && (strstr(fw_path, "_p2p") == NULL) && + (strstr(fw_path, "_apsta") == NULL)) { + /* Given path is for the STA firmware. Check whether P2P support is present in + * the firmware. If so, set mode as P2P (concurrent support). + */ + memset(buf, 0, sizeof(buf)); + bcm_mkiovar("p2p", 0, 0, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), + FALSE, 0)) < 0) { + DHD_ERROR(("%s: Get P2P failed (error=%d)\n", __FUNCTION__, ret)); + } else if (buf[0] == 1) { + DHD_TRACE(("%s: P2P is supported\n", __FUNCTION__)); + return 1; + } + } + return ret; +} +#endif +/* + * dhd_preinit_ioctls makes special pre-setting in the firmware before radio turns on + * returns : 0 if all settings passed or negative value if anything failed +*/ int dhd_preinit_ioctls(dhd_pub_t *dhd) { int ret = 0; char eventmask[WL_EVENTING_MASK_LEN]; char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - - char buf[256]; - char *ptr; +#if !defined(WL_CFG80211) uint up = 0; +#endif /* defined(WL_CFG80211) */ uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = 0; - uint bcn_timeout = 4; - uint retry_max = 10; + uint bcn_timeout = DHD_BEACON_TIMEOUT_NORMAL; + + uint retry_max = 3; #if defined(ARP_OFFLOAD_SUPPORT) - int arpoe = 0; /* Do not enable ARP offload feature since it has bug */ + int arpoe = 1; #endif - int scan_assoc_time = 40; - int scan_unassoc_time = 80; - int scan_passive_time = 100; - uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ +#if defined(KEEP_ALIVE) + int res; +#endif /* defined(KEEP_ALIVE) */ + int scan_assoc_time = DHD_SCAN_ACTIVE_TIME; + int scan_unassoc_time = 40; + int scan_passive_time = DHD_SCAN_PASSIVE_TIME; + char buf[WLC_IOCTL_SMLEN]; + char *ptr; + uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ + uint16 chipID; #if defined(SOFTAP) uint dtim = 1; -// uint32 wme = 0; #endif -#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) || \ - defined(DHD_BCM_WIFI_HDMI) +#if (defined(AP) && !defined(WLP2P)) || (!defined(AP) && defined(WL_CFG80211)) uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */ #endif -int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; -/* Contorl fw roaming */ -#ifdef CUSTOMER_HW2 - uint dhd_roam = 0; -#else - uint dhd_roam = 1; -#endif - #if defined(AP) || defined(WLP2P) uint32 apsta = 1; /* Enable APSTA mode */ -#endif /* defined(AP) || defined(WLP2P) || defined(DHD_BCM_WIFI_HDMI) */ +#endif /* defined(AP) || defined(WLP2P) */ #ifdef GET_CUSTOM_MAC_ENABLE struct ether_addr ea_addr; #endif /* GET_CUSTOM_MAC_ENABLE */ - - DHD_TRACE(("Enter %s\n", __func__)); + DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; #ifdef GET_CUSTOM_MAC_ENABLE ret = dhd_custom_get_mac_address(ea_addr.octet); @@ -3454,33 +3008,28 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); if (ret < 0) { - DHD_ERROR(("%s: can't set MAC address , error=%d\n", __func__, ret)); + DHD_ERROR(("%s: can't set custom MAC address , error=%d\n", __FUNCTION__, ret)); return BCME_NOTUP; } + memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN); } else { #endif /* GET_CUSTOM_MAC_ENABLE */ - -/* HTC_CSP_START */ - pdhd = dhd; -/* HTC_CSP_END */ -#ifdef PNO_SUPPORT - /* init pfn data */ - dhd_clear_pfn(); -#endif - - /* Get the device MAC address */ - strcpy(iovbuf, "cur_etheraddr"); - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) { - DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret)); - return BCME_NOTUP; - } - memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN); + /* Get the default device MAC address directly from firmware */ + memset(buf, 0, sizeof(buf)); + bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), + FALSE, 0)) < 0) { + DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret)); + return BCME_NOTUP; + } + /* Update public MAC address after reading from Firmware */ + memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); #ifdef GET_CUSTOM_MAC_ENABLE } #endif /* GET_CUSTOM_MAC_ENABLE */ #ifdef SET_RANDOM_MAC_SOFTAP - if (strstr(fw_path, "_apsta") != NULL) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { uint rand_mac; srandom32((uint)jiffies); @@ -3494,34 +3043,73 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); - if (ret < 0) - DHD_ERROR(("%s: can't set MAC address , error=%d\n", __func__, ret)); - else + if (ret < 0) { + DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret)); + } else memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN); } #endif /* SET_RANDOM_MAC_SOFTAP */ DHD_TRACE(("Firmware = %s\n", fw_path)); -#if !defined(AP) && defined(WLP2P) + +#if !defined(AP) && defined(WLP2P) /* Check if firmware with WFD support used */ - if (strstr(fw_path, "_p2p") != NULL) { +#if defined(WL_ENABLE_P2P_IF) + if ((ret = dhd_concurrent_fw(dhd)) < 0) { + DHD_ERROR(("%s error : firmware can't support p2p mode\n", __FUNCTION__)); + goto done; + } +#endif /* (WL_ENABLE_P2P_IF) */ + + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) +#if defined(WL_ENABLE_P2P_IF) + || (op_mode == WFD_MASK) || (dhd_concurrent_fw(dhd) == 1) +#endif + ) { bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) { - DHD_ERROR(("%s APSTA for WFD failed ret= %d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s APSTA setting failed ret= %d\n", __FUNCTION__, ret)); } else { dhd->op_mode |= WFD_MASK; -#if defined(ARP_OFFLOAD_SUPPORT) - arpoe = 0; -#endif /* (ARP_OFFLOAD_SUPPORT) */ +#if !defined(WL_ENABLE_P2P_IF) + /* ICS back capability : disable any packet filtering for p2p only mode */ dhd_pkt_filter_enable = FALSE; +#endif /*!defined(WL_ENABLE_P2P_IF) */ } } -#endif +#endif #if !defined(AP) && defined(WL_CFG80211) /* Check if firmware with HostAPD support used */ - if (strstr(fw_path, "_apsta") != NULL) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { + /* Disable A-band for HostAPD */ + uint band = WLC_BAND_2G; + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, (char *)&band, sizeof(band), + TRUE, 0)) < 0) { + DHD_ERROR(("%s:set band failed error (%d)\n", __FUNCTION__, ret)); + } + + /* Turn off wme if we are having only g ONLY firmware */ + bcm_mkiovar("nmode", 0, 0, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), + FALSE, 0)) < 0) { + DHD_ERROR(("%s:get nmode failed error (%d)\n", __FUNCTION__, ret)); + } + else { + DHD_TRACE(("%s:get nmode returned %d\n", __FUNCTION__,buf[0])); + } + if (buf[0] == 0) { + int wme = 0; + bcm_mkiovar("wme", (char *)&wme, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s set wme for HostAPD failed %d\n", __FUNCTION__, ret)); + } + else { + DHD_TRACE(("%s set wme succeeded for g ONLY firmware\n", __FUNCTION__)); + } + } /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, @@ -3532,16 +3120,20 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif /* (ARP_OFFLOAD_SUPPORT) */ + /* disable any filtering for SoftAP mode */ dhd_pkt_filter_enable = FALSE; } } -#endif +#endif +#if !defined(WL_ENABLE_P2P_IF) + /* ICS mode setting for sta */ if ((dhd->op_mode != WFD_MASK) && (dhd->op_mode != HOSTAPD_MASK)) { /* STA only operation mode */ dhd->op_mode |= STA_MASK; dhd_pkt_filter_enable = TRUE; } +#endif /* !defined(WL_ENABLE_P2P_IF) */ DHD_ERROR(("Firmware up: op_mode=%d, " "Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", @@ -3562,16 +3154,6 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) DHD_ERROR(("%s assoc_listen failed %d\n", __FUNCTION__, ret)); - /* query for 'ver' to get version info from firmware */ - memset(buf, 0, sizeof(buf)); - ptr = buf; - bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf)); -/* HTC_CSP_START */ - dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf),WL_IOCTL_ACTION_SET); - bcmstrtok(&ptr, "\n", 0); - /* Print fw version info */ - DHD_DEFAULT(("Firmware version = %s\n", buf)); -/* HTC_CSP_END */ /* Set PowerSave mode */ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); @@ -3579,16 +3161,21 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + /* disable glom option for some chips */ + chipID = (uint16)dhd_bus_chip_id(dhd); + if ((chipID == BCM4330_CHIP_ID) || (chipID == BCM4329_CHIP_ID)) { + DHD_INFO(("%s disable glom for chipID=0x%X\n", __FUNCTION__, chipID)); + bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + } /* Setup timeout if Beacons are lost and roam is off to report link down */ bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf)); + /* Setup assoc_retry_max count to reconnect target AP in dongle */ + bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + #if defined(AP) && !defined(WLP2P) /* Turn off MPC in AP mode */ bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); @@ -3603,69 +3190,14 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; } #endif - if (dhd_roam == 0) - { - /* set internal roaming roaming parameters */ - int roam_scan_period = 30; /* in sec */ - int roam_fullscan_period = 120; /* in sec */ -#ifdef CUSTOMER_HW2 - int roam_trigger = -80; - int roam_delta = 10; -#else - int roam_trigger = -85; - int roam_delta = 15; -#endif - int band; - int band_temp_set = WLC_BAND_2G; - - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, \ - (char *)&roam_scan_period, sizeof(roam_scan_period),TRUE,0) < 0) - DHD_ERROR(("%s: roam scan setup failed\n", __FUNCTION__)); - - bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, \ - 4, iovbuf, sizeof(iovbuf)); - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, \ - iovbuf, sizeof(iovbuf), TRUE, 0) < 0) - DHD_ERROR(("%s: roam fullscan setup failed\n", __FUNCTION__)); - - if (dhdcdc_query_ioctl(dhd, 0, WLC_GET_BAND, \ - (char *)&band, sizeof(band),WL_IOCTL_ACTION_GET) < 0) - DHD_ERROR(("%s: roam delta setting failed\n", __FUNCTION__)); - else { - if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_ALL)) - { - /* temp set band to insert new roams values */ - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, \ - (char *)&band_temp_set, sizeof(band_temp_set), TRUE, 0) < 0) - DHD_ERROR(("%s: local band seting failed\n", __FUNCTION__)); - } - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, \ - (char *)&roam_delta, sizeof(roam_delta), TRUE, 0) < 0) - DHD_ERROR(("%s: roam delta setting failed\n", __FUNCTION__)); - - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, \ - (char *)&roam_trigger, sizeof(roam_trigger), TRUE, 0) < 0) - DHD_ERROR(("%s: roam trigger setting failed\n", __FUNCTION__)); - - /* Restore original band settinngs */ - if (dhd_wl_ioctl_cmd(dhd, WLC_SET_BAND, \ - (char *)&band, sizeof(band), TRUE, 0) < 0) - DHD_ERROR(("%s: Original band restore failed\n", __FUNCTION__)); - } - } - #if defined(KEEP_ALIVE) - { /* Set Keep Alive : be sure to use FW with -keepalive */ - int res; - #if defined(SOFTAP) if (ap_fw_loaded == FALSE) -#endif +#endif if ((res = dhd_keep_alive_onoff(dhd)) < 0) DHD_ERROR(("%s set keeplive failed %d\n", __FUNCTION__, res)); - } #endif /* defined(KEEP_ALIVE) */ /* Read event_msgs mask */ @@ -3692,37 +3224,29 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; setbit(eventmask, WLC_E_LINK); setbit(eventmask, WLC_E_NDIS_LINK); setbit(eventmask, WLC_E_MIC_ERROR); + setbit(eventmask, WLC_E_ASSOC_REQ_IE); + setbit(eventmask, WLC_E_ASSOC_RESP_IE); setbit(eventmask, WLC_E_PMKID_CACHE); - /* setbit(dhdp->eventmask, WLC_E_TXFAIL); */ + setbit(eventmask, WLC_E_TXFAIL); setbit(eventmask, WLC_E_JOIN_START); setbit(eventmask, WLC_E_SCAN_COMPLETE); - setbit(eventmask, WLC_E_RELOAD); #ifdef WLMEDIA_HTSF setbit(eventmask, WLC_E_HTSFSYNC); #endif /* WLMEDIA_HTSF */ #ifdef PNO_SUPPORT setbit(eventmask, WLC_E_PFN_NET_FOUND); #endif /* PNO_SUPPORT */ - -#ifdef WLC_E_RSSI_LOW - setbit(eventmask, WLC_E_RSSI_LOW); -#endif /* WLC_E_RSSI_LOW */ /* enable dongle roaming event */ setbit(eventmask, WLC_E_ROAM); - setbit(eventmask, WLC_E_ASSOCREQ_IE); -/* HTC_CSP_START */ - setbit(eventmask, WLC_E_LOAD_IND); -/* HTC_CSP_END */ - #ifdef WL_CFG80211 setbit(eventmask, WLC_E_ESCAN_RESULT); - //if ((dhd->op_mode & WFD_MASK) == WFD_MASK) { + if ((dhd->op_mode & WFD_MASK) == WFD_MASK) { setbit(eventmask, WLC_E_ACTION_FRAME_RX); setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE); setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE); setbit(eventmask, WLC_E_P2P_PROBREQ_MSG); setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE); - //} + } #endif /* WL_CFG80211 */ /* Write updated Event mask */ @@ -3736,25 +3260,8 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; 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); -/* HTC_CSP_START */ dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_PASSIVE_TIME, (char *)&scan_passive_time, sizeof(scan_passive_time), TRUE, 0); -/* HTC_CSP_END */ - - /* set HT restrict */ - bcm_mkiovar("ht_wsec_restrict", (char *)&ht_wsec_restrict, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd,WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - - /* set assoc retry */ - bcm_mkiovar("assoc_retry_max", (char *)&retry_max, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - -/* HTC_CSP_START */ - /* set scanresult_minrssi */ - /*bcm_mkiovar("scanresults_minrssi", (char *)&scanresults_minrssi, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - */ -/* HTC_CSP_END */ #ifdef ARP_OFFLOAD_SUPPORT /* Set and enable ARP offload feature for STA only */ @@ -3771,52 +3278,56 @@ int ht_wsec_restrict = WLC_HT_TKIP_RESTRICT | WLC_HT_WEP_RESTRICT; } #endif /* ARP_OFFLOAD_SUPPORT */ -/* HTC_CSP_START */ - /* Lock CPU frequency to improve hotspot throughput*/ - ret = 3; - bcm_mkiovar("tc_period", (char *)&ret, 4, iovbuf, sizeof(iovbuf)); -#if defined(DHD_BCM_WIFI_HDMI) - if (dhd_bcm_whdmi_enable) { - DHD_ERROR(("DHD WiFi HDMI is enabled\n")); - -#if !defined(AP) && !defined(WLP2P) - /* Turn off MPC, turn on APSTA */ - bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* !defined(AP) && !defined(WLP2P) */ - - /* Disable legacy power save modes */ - power_mode = PM_OFF; - dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); - -#ifdef ARP_OFFLOAD_SUPPORT - /* Disable ARP offload */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, FALSE); -#endif /* ARP_OFFLOAD_SUPPORT */ - - } else { - /* DHD_ERROR(("DHD WiFi HDMI is NOT enabled\n")); */ +#ifdef PKT_FILTER_SUPPORT + /* Setup defintions for pktfilter , enable in suspend */ + dhd->pktfilter_count = 5; + /* Setup filter to allow only unicast */ + dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; + dhd->pktfilter[1] = NULL; + dhd->pktfilter[2] = NULL; + dhd->pktfilter[3] = NULL; + /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ + dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; +#if defined(SOFTAP) + if (ap_fw_loaded) { + int i; + for (i = 0; i < dhd->pktfilter_count; i++) { + dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], + 0, dhd_master_mode); + } } -#endif /* defined(DHD_BCM_WIFI_HDMI) */ /* Force STA UP */ - ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0); - if (ret < 0) { +#endif /* defined(SOFTAP) */ +#endif /* PKT_FILTER_SUPPORT */ + +#if !defined(WL_CFG80211) + /* Force STA UP */ + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) { DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret)); goto done; } - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - ret = TRAFFIC_LOW_WATER_MARK; - bcm_mkiovar("tc_lo_wm", (char *)&ret, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - ret = TRAFFIC_HIGH_WATER_MARK; - bcm_mkiovar("tc_hi_wm", (char *)&ret, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - ret = 1; - bcm_mkiovar("tc_enable", (char *)&ret, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -/* HTC_CSP_END */ +#endif + /* query for 'ver' to get version info from firmware */ + memset(buf, 0, sizeof(buf)); + ptr = buf; + bcm_mkiovar("ver", (char *)&buf, 4, buf, sizeof(buf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0) + DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret)); + else { + bcmstrtok(&ptr, "\n", 0); + /* Print fw version info */ + DHD_ERROR(("Firmware version = %s\n", buf)); + + dhd_set_version_info(dhd, buf); + + DHD_BLOG(buf, strlen(buf) + 1); + DHD_BLOG(dhd_version, strlen(dhd_version) + 1); + + /* Check and adjust IOCTL response timeout for Manufactring firmware */ + if (strstr(buf, MANUFACTRING_FW) != NULL) { + dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT * 10); + DHD_ERROR(("%s : adjust IOCTL response time for Manufactring Firmware\n", __FUNCTION__)); + } + } done: return ret; @@ -3959,11 +3470,6 @@ static int dhd_device_event(struct notifier_block *this, dhd->pend_ipaddr = ifa->ifa_address; break; } - /* firmware not downloaded, do nothing */ - if (dhd->pub.busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s: bus is down, exit\n", __FUNCTION__)); - break; - } #ifdef AOE_IP_ALIAS_SUPPORT if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) { @@ -4030,7 +3536,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) #else ASSERT(!net->netdev_ops); net->netdev_ops = &dhd_ops_virt; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ +#endif /* Ok, link into the network layer... */ if (ifidx == 0) { @@ -4042,7 +3548,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) net->stop = dhd_stop; #else net->netdev_ops = &dhd_ops_pri; -#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */ +#endif } else { /* * We have to use the primary MAC for virtual interfaces @@ -4066,14 +3572,14 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) net->ethtool_ops = &dhd_ethtool_ops; #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) #if WIRELESS_EXT < 19 net->get_wireless_stats = dhd_get_wireless_stats; #endif /* WIRELESS_EXT < 19 */ #if WIRELESS_EXT > 12 net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; #endif /* WIRELESS_EXT > 12 */ -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ dhd->pub.rxsz = DBUS_RX_BUFFER_SIZE_DHD(net); @@ -4089,7 +3595,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) net->dev_addr[0], net->dev_addr[1], net->dev_addr[2], net->dev_addr[3], net->dev_addr[4], net->dev_addr[5]); -#if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211) +#if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211) wl_iw_iscan_set_scan_broadcast_prep(net, 1); #endif @@ -4154,8 +3660,6 @@ void dhd_detach(dhd_pub_t *dhdp) if (!dhd) return; - dhd->dhd_force_exit = TRUE; - DHD_TRACE(("%s: Enter state 0x%x\n", __FUNCTION__, dhd->dhd_state)); if (!(dhd->dhd_state & DHD_ATTACH_STATE_DONE)) { @@ -4169,24 +3673,26 @@ void dhd_detach(dhd_pub_t *dhdp) unregister_inetaddr_notifier(&dhd_notifier); #endif /* ARP_OFFLOAD_SUPPORT */ -#if defined(CONFIG_HAS_EARLYSUSPEND) +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) if (dhd->dhd_state & DHD_ATTACH_STATE_EARLYSUSPEND_DONE) { if (dhd->early_suspend.suspend) unregister_early_suspend(&dhd->early_suspend); } #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + cancel_work_sync(&dhd->work_hang); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) if (dhd->dhd_state & DHD_ATTACH_STATE_WL_ATTACH) { /* Detatch and unlink in the iw */ wl_iw_detach(); } -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ - if (dhd->dhd_state & DHD_ATTACH_STATE_THREADS_CREATED) { - if (&dhd->thr_sysioc_ctl.thr_pid >= 0) - PROC_STOP(&dhd->thr_sysioc_ctl); + if (dhd->thr_sysioc_ctl.thr_pid >= 0) { + PROC_STOP(&dhd->thr_sysioc_ctl); } /* delete all interfaces, start with virtual */ @@ -4195,39 +3701,33 @@ void dhd_detach(dhd_pub_t *dhdp) dhd_if_t *ifp; /* Cleanup virtual interfaces */ - for (i = 1; i < DHD_MAX_IFS; i++) + for (i = 1; i < DHD_MAX_IFS; i++) { + dhd_net_if_lock_local(dhd); if (dhd->iflist[i]) { dhd->iflist[i]->state = DHD_IF_DEL; dhd->iflist[i]->idx = i; dhd_op_if(dhd->iflist[i]); } - + dhd_net_if_unlock_local(dhd); + } /* delete primary interface 0 */ ifp = dhd->iflist[0]; ASSERT(ifp); -#ifdef HTC_KlocWork - if (ifp->net) { -#endif #if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - if (ifp->net->open) + if (ifp->net->open) #else - if (ifp->net->netdev_ops == &dhd_ops_pri) + if (ifp->net->netdev_ops == &dhd_ops_pri) #endif - { - if (ifp->net) { - unregister_netdev(ifp->net); - /* HTC_CSP_START */ - free_netdev(ifp->net); - /* HTC_CSP_END */ - ifp->net = NULL; - } - MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); - dhd->iflist[0] = NULL; + { + if (ifp->net) { + unregister_netdev(ifp->net); + free_netdev(ifp->net); + ifp->net = NULL; } -#ifdef HTC_KlocWork + MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); + dhd->iflist[0] = NULL; } -#endif } /* Clear the watchdog timer */ @@ -4247,10 +3747,6 @@ void dhd_detach(dhd_pub_t *dhdp) if (dhd->thr_dpc_ctl.thr_pid >= 0) { PROC_STOP(&dhd->thr_dpc_ctl); } - - if (dhd->thr_sysioc_ctl.thr_pid >= 0) { - PROC_STOP(&dhd->thr_sysioc_ctl); - } else #endif /* DHDTHREAD */ tasklet_kill(&dhd->tasklet); @@ -4269,20 +3765,17 @@ void dhd_detach(dhd_pub_t *dhdp) } #endif - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) unregister_pm_notifier(&dhd_sleep_pm_notifier); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ - /* && defined(CONFIG_PM_SLEEP) */ if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { #ifdef CONFIG_HAS_WAKELOCK wake_lock_destroy(&dhd->wl_wifi); wake_lock_destroy(&dhd->wl_rxwake); - wake_lock_destroy(&dhd->wl_htc); + wake_lock_destroy(&dhd->wl_ctrlwake); #endif } - dhd->dhd_force_exit = FALSE; } @@ -4299,35 +3792,11 @@ dhd_free(dhd_pub_t *dhdp) } } -/* HTC_CSP_START */ -extern struct perf_lock wlan_perf_lock; -/* HTC_CSP_END */ -extern void disable_dev_wlc_ioctl(void); static void __exit dhd_module_cleanup(void) { DHD_TRACE(("%s: Enter\n", __FUNCTION__)); -/* HTC_CSP_START */ - if (priv_dhdp) - dhd_net_if_lock_local(priv_dhdp->info); -/* HTC_CSP_END */ - -#ifdef CONFIG_WIRELESS_EXT - disable_dev_wlc_ioctl(); -#endif - -/* HTC_CSP_START */ - module_remove = 1; - module_insert = 0; -/* HTC_CSP_END */ - -/* HTC_CSP_START */ - if (priv_dhdp) - dhd_net_if_unlock_local(priv_dhdp->info); -/* HTC_CSP_END */ - - msleep(1000); dhd_bus_unregister(); #if defined(CONFIG_WIFI_CONTROL_FUNC) @@ -4335,31 +3804,19 @@ dhd_module_cleanup(void) #endif /* CONFIG_WIFI_CONTROL_FUNC */ wl_android_exit(); -/* HTC_CSP_START */ -#ifdef CONFIG_PERLOCK - if (is_perf_lock_active(&wlan_perf_lock)) - perf_unlock(&wlan_perf_lock); -#endif -/* HTC_CSP_END */ - /* Call customer gpio to turn off power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); - printf("[ATS][press_widget][turn_off]\n"); //For Auto Test System log parsing } - static int __init dhd_module_init(void) { int error = 0; - int retry = 0; - wifi_fail_retry = false; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); wl_android_init(); -init_retry: #ifdef DHDTHREAD /* Sanity check on the module parameters */ do { @@ -4382,7 +3839,7 @@ dhd_module_init(void) #if defined(CONFIG_WIFI_CONTROL_FUNC) if (wl_android_wifictrl_func_add() < 0) goto fail_1; -#endif +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) sema_init(&dhd_registration_sem, 0); @@ -4390,43 +3847,33 @@ dhd_module_init(void) error = dhd_bus_register(); if (!error) - printf("%s\n", dhd_version); + printf("\n%s\n", dhd_version); else { DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__)); goto fail_1; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - /* - * Wait till MMC sdio_register_driver callback called and made driver attach. - * It's needed to make sync up exit from dhd insmod and - * Kernel MMC sdio device callback registration - */ + /* + * Wait till MMC sdio_register_driver callback called and made driver attach. + * It's needed to make sync up exit from dhd insmod and + * Kernel MMC sdio device callback registration + */ if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) { - error = -EINVAL; + error = -ENODEV; DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__)); goto fail_2; - } -#endif - if (wifi_fail_retry) { - wifi_fail_retry = false; - DHD_ERROR(("%s: wifi_fail_retry is true\n", __FUNCTION__)); - goto fail_2; } - +#endif #if defined(WL_CFG80211) wl_android_post_init(); -#endif +#endif /* defined(WL_CFG80211) */ -/* HTC_CSP_START */ - module_insert = 1; -/* HTC_CSP_END */ - printf("[ATS][press_widget][launch]\n"); //For Auto Test System log parsing return error; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) fail_2: dhd_bus_unregister(); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ +#endif fail_1: #if defined(CONFIG_WIFI_CONTROL_FUNC) wl_android_wifictrl_func_del(); @@ -4435,11 +3882,6 @@ dhd_module_init(void) /* Call customer gpio to turn off power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); - if (!retry) { - printf("module init fail, try again!\n"); - retry = 1; - goto init_retry; - } return error; } @@ -4495,36 +3937,12 @@ int dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) { dhd_info_t * dhd = (dhd_info_t *)(pub->info); - DECLARE_WAITQUEUE(wait, current); - int timeout = dhd_ioctl_timeout_msec; + int timeout; /* Convert timeout in millsecond to jiffies */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - timeout = msecs_to_jiffies(timeout); -#else - timeout = timeout * HZ / 1000; -#endif - - /* Wait until control frame is available */ - add_wait_queue(&dhd->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - /* Memory barrier to support multi-processing - * As the variable "condition", which points to dhd->rxlen (dhd_bus_rxctl[dhd_sdio.c]) - * Can be changed by another processor. - */ - smp_mb(); - while (!(*condition) && (!signal_pending(current) && timeout)) { - timeout = schedule_timeout(timeout); - smp_mb(); - } - - if (signal_pending(current)) - *pending = TRUE; - - set_current_state(TASK_RUNNING); - remove_wait_queue(&dhd->ioctl_resp_wait, &wait); + timeout = msecs_to_jiffies(dhd_ioctl_timeout_msec); + timeout = wait_event_timeout(dhd->ioctl_resp_wait, (*condition), timeout); return timeout; } @@ -4534,13 +3952,12 @@ dhd_os_ioctl_resp_wake(dhd_pub_t *pub) dhd_info_t *dhd = (dhd_info_t *)(pub->info); if (waitqueue_active(&dhd->ioctl_resp_wait)) { - wake_up_interruptible(&dhd->ioctl_resp_wait); + wake_up(&dhd->ioctl_resp_wait); } return 0; } -/* HTC_CSP_START */ void dhd_os_wd_timer(void *bus, uint wdtick) { @@ -4573,12 +3990,11 @@ dhd_os_wd_timer(void *bus, uint wdtick) if (wdtick) { dhd_watchdog_ms = (uint)wdtick; /* Re arm the timer, at last watchdog period */ - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); + mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd->wd_timer_valid = TRUE; } dhd_os_spin_unlock(pub, flags); } -/* HTC_CSP_END */ void * dhd_os_open_image(char *filename) @@ -4692,7 +4108,7 @@ dhd_os_sdtxunlock(dhd_pub_t *pub) dhd_os_sdunlock(pub); } -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size) { return (uint8*)wl_android_prealloc(section, size); @@ -4701,9 +4117,9 @@ uint8* dhd_os_prealloc(void *osh, int section, uint size) void dhd_os_prefree(void *osh, void *addr, uint size) { } -#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ +#endif /* defined(CONFIG_DHD_USE_STATIC_BUF) */ -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) struct iw_statistics * dhd_get_wireless_stats(struct net_device *dev) { @@ -4721,7 +4137,7 @@ dhd_get_wireless_stats(struct net_device *dev) else return NULL; } -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, @@ -4734,7 +4150,7 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, if (bcmerror != BCME_OK) return (bcmerror); -#if defined(CONFIG_WIRELESS_EXT) +#if defined(WL_WIRELESS_EXT) if (event->bsscfgidx == 0) { /* * Wireless ext is on primary interface only @@ -4747,10 +4163,16 @@ dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); } } -#endif /* defined(CONFIG_WIRELESS_EXT) */ +#endif /* defined(WL_WIRELESS_EXT) */ #ifdef WL_CFG80211 - + if ((ntoh32(event->event_type) == WLC_E_IF) && + (((dhd_if_event_t *)*data)->action == WLC_E_IF_ADD)) + /* If ADD_IF has been called directly by wl utility then we + * should not report this. In case if ADD_IF was called from + * CFG stack, then too this event need not be reported back + */ + return (BCME_OK); if ((wl_cfg80211_is_progress_ifchange() || wl_cfg80211_is_progress_ifadd()) && (*ifidx != 0)) { /* @@ -4879,8 +4301,9 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) { #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) struct dhd_info *dhdinfo = dhd->info; + int timeout = msecs_to_jiffies(2000); dhd_os_sdunlock(dhd); - wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 2); + wait_event_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), timeout); dhd_os_sdlock(dhd); #endif return; @@ -4891,7 +4314,7 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) struct dhd_info *dhdinfo = dhd->info; if (waitqueue_active(&dhdinfo->ctrl_wait)) - wake_up_interruptible(&dhdinfo->ctrl_wait); + wake_up(&dhdinfo->ctrl_wait); #endif return; } @@ -4924,16 +4347,18 @@ int net_os_set_suspend_disable(struct net_device *dev, int val) return ret; } -int net_os_set_suspend(struct net_device *dev, int val) +int net_os_set_suspend(struct net_device *dev, int val, int force) { int ret = 0; -#if defined(CONFIG_HAS_EARLYSUSPEND) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); if (dhd) { +#if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) ret = dhd_set_suspend(val, &dhd->pub); +#else + ret = dhd_suspend_resume_helper(dhd, val, force); +#endif } -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ return ret; } @@ -4953,7 +4378,8 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) char *filterp = NULL; int ret = 0; - if (!dhd || (num == DHD_UNICAST_FILTER_NUM)) + if (!dhd || (num == DHD_UNICAST_FILTER_NUM) || + (num == DHD_MDNS_FILTER_NUM)) return ret; if (num >= dhd->pub.pktfilter_count) return -EINVAL; @@ -4976,21 +4402,8 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) return ret; } -/*HTC_CSP_START */ -int wl_android_set_pktfilter(struct net_device *dev, struct dd_pkt_filter_s *data) +int dhd_os_set_packet_filter(dhd_pub_t *dhdp, int val) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - /* printf("%s: add: %d, id: %d, offset: %d, mask: %s, pattern: %s\n", __func__, - data->add, data->id, data->offset, data->mask, data->pattern); - */ - return dhd_set_pktfilter(&dhd->pub, data->add, data->id, data->offset, data->mask, data->pattern); - -} -/* HTC_CSP_END */ - -int net_os_set_packet_filter(struct net_device *dev, int val) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; /* Packet filtering is set only if we still in early-suspend and @@ -4998,22 +4411,29 @@ int net_os_set_packet_filter(struct net_device *dev, int val) * We can always turn it OFF in case of early-suspend, but we turn it * back ON only if suspend_disable_flag was not set */ - if (dhd && dhd->pub.up) { - if (dhd->pub.in_suspend) { - if (!val || (val && !dhd->pub.suspend_disable_flag)) - dhd_set_packet_filter(val, &dhd->pub); + if (dhdp && dhdp->up) { + if (dhdp->in_suspend) { + if (!val || (val && !dhdp->suspend_disable_flag)) + dhd_set_packet_filter(val, dhdp); } } return ret; + } +int net_os_set_packet_filter(struct net_device *dev, int val) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); -void + return dhd_os_set_packet_filter(&dhd->pub, val); +} + +int dhd_dev_init_ioctl(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - dhd_preinit_ioctls(&dhd->pub); + return dhd_preinit_ioctls(&dhd->pub); } #ifdef PNO_SUPPORT @@ -5047,6 +4467,17 @@ dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max)); } +/* Linux wrapper to call common dhd_pno_set_ex */ +int +dhd_dev_pno_set_ex(struct net_device *dev, wl_pfn_t* ssidnet, int nssid, + ushort pno_interval, int pno_repeat, int pno_expo_max, int pno_lost_time) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + + return (dhd_pno_set_ex(&dhd->pub, ssidnet, nssid, + pno_interval, pno_repeat, pno_expo_max, pno_lost_time)); +} + /* Linux wrapper to get pno status */ int dhd_dev_get_pno_status(struct net_device *dev) @@ -5058,79 +4489,76 @@ dhd_dev_get_pno_status(struct net_device *dev) #endif /* PNO_SUPPORT */ -int net_os_send_hang_message(struct net_device *dev) +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) +static void dhd_hang_process(struct work_struct *work) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; + dhd_info_t *dhd; + struct net_device *dev; - if (module_remove) { - printf("%s: module removed. Do not send hang event.\n", __FUNCTION__); - return ret; - } + dhd = (dhd_info_t *)container_of(work, dhd_info_t, work_hang); + dev = dhd->iflist[0]->net; - if (dhd) { - if (!dhd->pub.hang_was_sent) { - dhd->pub.hang_was_sent = 1; -#if defined(CONFIG_WIRELESS_EXT) - ret = wl_iw_send_priv_event(dev, "HANG"); + if (dev) { + rtnl_lock(); + dev_close(dev); + rtnl_unlock(); +#if defined(WL_WIRELESS_EXT) + wl_iw_send_priv_event(dev, "HANG"); #endif #if defined(WL_CFG80211) - ret = wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); + wl_cfg80211_hang(dev, WLAN_REASON_UNSPECIFIED); #endif - } } - return ret; } +#endif -/* HTC_CSP_START */ -#if defined(CONFIG_WIRELESS_EXT) -void dhd_info_send_hang_message(dhd_pub_t *dhdp) +int dhd_os_send_hang_message(dhd_pub_t *dhdp) { - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - struct net_device *dev = NULL; - if ((dhd == NULL) || dhd->iflist[0]->net == NULL) { - return; - } - - dev = dhd->iflist[0]->net; - net_os_send_hang_message(dev); + int ret = 0; - return; + if (dhdp) { + if (!dhdp->hang_was_sent) { + dhdp->hang_was_sent = 1; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + schedule_work(&dhdp->info->work_hang); +#endif + } + } + return ret; } -int net_os_send_rssilow_message(struct net_device *dev) +int net_os_send_hang_message(struct net_device *dev) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; - if (module_remove) { - printf("%s: module removed. Do not send rssi_low event.\n", __FUNCTION__); - return ret; - } + if (dhd) + ret = dhd_os_send_hang_message(&dhd->pub); - if (dhd) { - ret = wl_iw_send_priv_event(dev, "RSSI_LOW_IND"); - } - return ret; + return ret; } -#endif -/* HTC_CSP_END */ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - if (dhd && dhd->pub.up) - memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); + if (dhd && dhd->pub.up) { + memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); +#ifdef WL_CFG80211 + wl_update_wiphybands(NULL); +#endif + } } -wl_country_t *dhd_bus_country_get(struct net_device *dev) +void dhd_bus_band_set(struct net_device *dev, uint band) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - if (dhd && (dhd->pub.dhd_cspec.ccode[0] != 0)) - return &dhd->pub.dhd_cspec; - return NULL; + if (dhd && dhd->pub.up) { +#ifdef WL_CFG80211 + wl_update_wiphybands(NULL); +#endif + } } void dhd_net_if_lock(struct net_device *dev) @@ -5161,6 +4589,24 @@ static void dhd_net_if_unlock_local(dhd_info_t *dhd) #endif } +static void dhd_suspend_lock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_lock(&dhd->dhd_suspend_mutex); +#endif +} + +static void dhd_suspend_unlock(dhd_pub_t *pub) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + if (dhd) + mutex_unlock(&dhd->dhd_suspend_mutex); +#endif +} + unsigned long dhd_os_spin_lock(dhd_pub_t *pub) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); @@ -5192,7 +4638,7 @@ int dhd_wait_pend8021x(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int timeout = 10 * HZ / 1000; + int timeout = msecs_to_jiffies(10); int ntimes = MAX_WAIT_FOR_8021X_TX; int pend = dhd_get_pend_8021x_cnt(dhd); @@ -5245,15 +4691,6 @@ write_to_file(dhd_pub_t *dhd, uint8 *buf, int size) } #endif /* DHD_DEBUG */ -void dhd_htc_wake_lock_timeout(dhd_pub_t *pub, int sec) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_timeout(&dhd->wl_htc, sec * HZ); -#endif -} - int dhd_os_wake_lock_timeout(dhd_pub_t *pub) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); @@ -5262,13 +4699,18 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub) if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - ret = dhd->wakelock_timeout_enable; + ret = dhd->wakelock_rx_timeout_enable > dhd->wakelock_ctrl_timeout_enable ? + dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; #ifdef CONFIG_HAS_WAKELOCK - if (dhd->wakelock_timeout_enable) + if (dhd->wakelock_rx_timeout_enable) wake_lock_timeout(&dhd->wl_rxwake, - dhd->wakelock_timeout_enable * HZ); + msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); + if (dhd->wakelock_ctrl_timeout_enable) + wake_lock_timeout(&dhd->wl_ctrlwake, + msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); #endif - dhd->wakelock_timeout_enable = 0; + dhd->wakelock_rx_timeout_enable = 0; + dhd->wakelock_ctrl_timeout_enable = 0; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return ret; @@ -5284,92 +4726,84 @@ int net_os_wake_lock_timeout(struct net_device *dev) return ret; } -int dhd_os_wake_lock_timeout_enable(dhd_pub_t *pub, int val) +int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (val > dhd->wakelock_timeout_enable) - dhd->wakelock_timeout_enable = val; + if (val > dhd->wakelock_rx_timeout_enable) + dhd->wakelock_rx_timeout_enable = val; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return 0; } -int net_os_wake_lock_timeout_enable(struct net_device *dev, int val) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; - - if (dhd) - ret = dhd_os_wake_lock_timeout_enable(&dhd->pub, val); - return ret; -} - -int dhd_os_wake_lock(dhd_pub_t *pub) +int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; - int ret = 0; if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); -#ifdef CONFIG_HAS_WAKELOCK - if (!dhd->wakelock_counter) - wake_lock(&dhd->wl_wifi); -#endif - dhd->wakelock_counter++; - ret = dhd->wakelock_counter; + if (val > dhd->wakelock_ctrl_timeout_enable) + dhd->wakelock_ctrl_timeout_enable = val; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } + return 0; +} + +int net_os_wake_lock_rx_timeout_enable(struct net_device *dev, int val) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; + + if (dhd) + ret = dhd_os_wake_lock_rx_timeout_enable(&dhd->pub, val); return ret; } -int net_os_wake_lock(struct net_device *dev) +int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; if (dhd) - ret = dhd_os_wake_lock(&dhd->pub); + ret = dhd_os_wake_lock_ctrl_timeout_enable(&dhd->pub, val); return ret; } -int dhd_os_wake_unlock(dhd_pub_t *pub) +int dhd_os_wake_lock(dhd_pub_t *pub) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; int ret = 0; - dhd_os_wake_lock_timeout(pub); if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - if (dhd->wakelock_counter) { - dhd->wakelock_counter--; #ifdef CONFIG_HAS_WAKELOCK - if (!dhd->wakelock_counter) - wake_unlock(&dhd->wl_wifi); + if (!dhd->wakelock_counter) + wake_lock(&dhd->wl_wifi); #endif - ret = dhd->wakelock_counter; - } + dhd->wakelock_counter++; + ret = dhd->wakelock_counter; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); } return ret; } -int net_os_wake_unlock(struct net_device *dev) +int net_os_wake_lock(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; if (dhd) - ret = dhd_os_wake_unlock(&dhd->pub); + ret = dhd_os_wake_lock(&dhd->pub); return ret; } -int dhd_os_wake_force_unlock(dhd_pub_t *pub) +int dhd_os_wake_unlock(dhd_pub_t *pub) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); unsigned long flags; @@ -5379,8 +4813,7 @@ int dhd_os_wake_force_unlock(dhd_pub_t *pub) if (dhd) { spin_lock_irqsave(&dhd->wakelock_spinlock, flags); if (dhd->wakelock_counter) { - printf("wakelock_counter = %d, set to 0\n", dhd->wakelock_counter); - dhd->wakelock_counter = 0; + dhd->wakelock_counter--; #ifdef CONFIG_HAS_WAKELOCK if (!dhd->wakelock_counter) wake_unlock(&dhd->wl_wifi); @@ -5408,6 +4841,16 @@ int dhd_os_check_wakelock(void *dhdp) return 0; } +int net_os_wake_unlock(struct net_device *dev) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int ret = 0; + + if (dhd) + ret = dhd_os_wake_unlock(&dhd->pub); + return ret; +} + int dhd_os_check_if_up(void *dhdp) { dhd_pub_t *pub = (dhd_pub_t *)dhdp; @@ -5417,6 +4860,20 @@ int dhd_os_check_if_up(void *dhdp) return pub->up; } +void dhd_set_version_info(dhd_pub_t *dhdp, char *fw) +{ + int i; + + i = snprintf(info_string, sizeof(info_string), + " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw); + + if (!dhdp) + return; + i = snprintf(&info_string[i], sizeof(info_string) - i, + "\n Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp), + dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp)); +} + int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) { int ifidx; @@ -5456,8 +4913,8 @@ extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t uint8 iftype, uint8* ea); extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); -int dhd_wlfc_interface_event(struct dhd_info *dhd, uint8 action, uint8 ifid, uint8 iftype, - uint8* ea) +int dhd_wlfc_interface_event(struct dhd_info *dhd, + ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) { if (dhd->pub.wlfc_state == NULL) return BCME_OK; @@ -5944,33 +5401,3 @@ void htsf_update(dhd_info_t *dhd, void *data) } #endif /* WLMEDIA_HTSF */ - -void dhd_reset_hang_was_sent(struct net_device *dev) -{ -/* reset the hang counter */ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - if (dhd) - dhd->pub.hang_was_sent = 0; - -} - -/* HTC_CSP_START */ -int dhd_get_txrx_stats(struct net_device *net, unsigned long *rx_packets, unsigned long *tx_packets) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - dhd_pub_t *dhdp; - - if (!dhd) - return -1; - - dhdp = &dhd->pub; - - if (!dhdp) - return -1; - - *rx_packets = dhdp->rx_packets; - *tx_packets = dhdp->tx_packets; - - return 0; -} -/* HTC_CSP_END */ diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c new file mode 100644 index 00000000..dd9c71f7 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c @@ -0,0 +1,393 @@ +/* + * Broadcom Dongle Host Driver (DHD), Linux monitor network interface + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: dhd_linux_mon.c,v 1.131.2.55 2011-02-09 05:31:56 Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +typedef enum monitor_states +{ + MONITOR_STATE_DEINIT = 0x0, + MONITOR_STATE_INIT = 0x1, + MONITOR_STATE_INTERFACE_ADDED = 0x2, + MONITOR_STATE_INTERFACE_DELETED = 0x4 +} monitor_states_t; +extern int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); + +/** + * Local declarations and defintions (not exposed) + */ +#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__) +#define MON_TRACE MON_PRINT + +typedef struct monitor_interface { + int radiotap_enabled; + struct net_device* real_ndev; /* The real interface that the monitor is on */ + struct net_device* mon_ndev; +} monitor_interface; + +typedef struct dhd_linux_monitor { + void *dhd_pub; + monitor_states_t monitor_state; + monitor_interface mon_if[DHD_MAX_IFS]; + struct mutex lock; /* lock to protect mon_if */ +} dhd_linux_monitor_t; + +static dhd_linux_monitor_t g_monitor; + +static struct net_device* lookup_real_netdev(char *name); +static monitor_interface* ndev_to_monif(struct net_device *ndev); +static int dhd_mon_if_open(struct net_device *ndev); +static int dhd_mon_if_stop(struct net_device *ndev); +static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev); +static void dhd_mon_if_set_multicast_list(struct net_device *ndev); +static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr); + +static const struct net_device_ops dhd_mon_if_ops = { + .ndo_open = dhd_mon_if_open, + .ndo_stop = dhd_mon_if_stop, + .ndo_start_xmit = dhd_mon_if_subif_start_xmit, + .ndo_set_multicast_list = dhd_mon_if_set_multicast_list, + .ndo_set_mac_address = dhd_mon_if_change_mac, +}; + +/** + * Local static function defintions + */ + +/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0" + * "p2p-eth0-0" is a match for "mon.p2p-eth0-0") + */ +static struct net_device* lookup_real_netdev(char *name) +{ + int i; + int last_name_len = 0; + struct net_device *ndev; + struct net_device *ndev_found = NULL; + + /* We want to find interface "p2p-eth0-0" for monitor interface "mon.p2p-eth0-0", so + * we skip "eth0" even if "mon.p2p-eth0-0" contains "eth0" + */ + for (i = 0; i < DHD_MAX_IFS; i++) { + ndev = dhd_idx2net(g_monitor.dhd_pub, i); + if (ndev && strstr(name, ndev->name)) { + if (strlen(ndev->name) > last_name_len) { + ndev_found = ndev; + last_name_len = strlen(ndev->name); + } + } + } + + return ndev_found; +} + +static monitor_interface* ndev_to_monif(struct net_device *ndev) +{ + int i; + + for (i = 0; i < DHD_MAX_IFS; i++) { + if (g_monitor.mon_if[i].mon_ndev == ndev) + return &g_monitor.mon_if[i]; + } + + return NULL; +} + +static int dhd_mon_if_open(struct net_device *ndev) +{ + int ret = 0; + + MON_PRINT("enter\n"); + return ret; +} + +static int dhd_mon_if_stop(struct net_device *ndev) +{ + int ret = 0; + + MON_PRINT("enter\n"); + return ret; +} + +static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev) +{ + int ret = 0; + int rtap_len; + int qos_len = 0; + int dot11_hdr_len = 24; + int snap_len = 6; + unsigned char *pdata; + unsigned short frame_ctl; + unsigned char src_mac_addr[6]; + unsigned char dst_mac_addr[6]; + struct ieee80211_hdr *dot11_hdr; + struct ieee80211_radiotap_header *rtap_hdr; + monitor_interface* mon_if; + + MON_PRINT("enter\n"); + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + goto fail; + } + + if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header))) + goto fail; + + rtap_hdr = (struct ieee80211_radiotap_header *)skb->data; + if (unlikely(rtap_hdr->it_version)) + goto fail; + + rtap_len = ieee80211_get_radiotap_len(skb->data); + if (unlikely(skb->len < rtap_len)) + goto fail; + + MON_PRINT("radiotap len (should be 14): %d\n", rtap_len); + + /* Skip the ratio tap header */ + skb_pull(skb, rtap_len); + + dot11_hdr = (struct ieee80211_hdr *)skb->data; + frame_ctl = le16_to_cpu(dot11_hdr->frame_control); + /* Check if the QoS bit is set */ + if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { + /* Check if this ia a Wireless Distribution System (WDS) frame + * which has 4 MAC addresses + */ + if (dot11_hdr->frame_control & 0x0080) + qos_len = 2; + if ((dot11_hdr->frame_control & 0x0300) == 0x0300) + dot11_hdr_len += 6; + + memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr)); + memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr)); + + /* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for + * for two MAC addresses + */ + skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2); + pdata = (unsigned char*)skb->data; + memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr)); + memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr)); + + MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); + + /* Use the real net device to transmit the packet */ + ret = dhd_start_xmit(skb, mon_if->real_ndev); + + return ret; + } +fail: + dev_kfree_skb(skb); + return 0; +} + +static void dhd_mon_if_set_multicast_list(struct net_device *ndev) +{ + monitor_interface* mon_if; + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } + + MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); +} + +static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr) +{ + int ret = 0; + monitor_interface* mon_if; + + mon_if = ndev_to_monif(ndev); + if (mon_if == NULL || mon_if->real_ndev == NULL) { + MON_PRINT(" cannot find matched net dev, skip the packet\n"); + } + + MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name); + return ret; +} + +/** + * Global function definitions (declared in dhd_linux_mon.h) + */ + +int dhd_add_monitor(char *name, struct net_device **new_ndev) +{ + int i; + int idx = -1; + int ret = 0; + struct net_device* ndev = NULL; + dhd_linux_monitor_t **dhd_mon; + + mutex_lock(&g_monitor.lock); + + MON_TRACE("enter, if name: %s\n", name); + if (!name || !new_ndev) { + MON_PRINT("invalid parameters\n"); + ret = -EINVAL; + goto out; + } + + /* + * Find a vacancy + */ + for (i = 0; i < DHD_MAX_IFS; i++) + if (g_monitor.mon_if[i].mon_ndev == NULL) { + idx = i; + break; + } + if (idx == -1) { + MON_PRINT("exceeds maximum interfaces\n"); + ret = -EFAULT; + goto out; + } + + ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*)); + if (!ndev) { + MON_PRINT("failed to allocate memory\n"); + ret = -ENOMEM; + goto out; + } + + ndev->type = ARPHRD_IEEE80211_RADIOTAP; + strncpy(ndev->name, name, IFNAMSIZ); + ndev->name[IFNAMSIZ - 1] = 0; + ndev->netdev_ops = &dhd_mon_if_ops; + + ret = register_netdevice(ndev); + if (ret) { + MON_PRINT(" register_netdevice failed (%d)\n", ret); + goto out; + } + + *new_ndev = ndev; + g_monitor.mon_if[idx].radiotap_enabled = TRUE; + g_monitor.mon_if[idx].mon_ndev = ndev; + g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name); + dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev); + *dhd_mon = &g_monitor; + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_ADDED; + MON_PRINT("net device returned: 0x%p\n", ndev); + MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name); + +out: + if (ret && ndev) + free_netdev(ndev); + + mutex_unlock(&g_monitor.lock); + return ret; + +} + +int dhd_del_monitor(struct net_device *ndev) +{ + int i; + bool rollback_lock = false; + if (!ndev) + return -EINVAL; + mutex_lock(&g_monitor.lock); + for (i = 0; i < DHD_MAX_IFS; i++) { + if (g_monitor.mon_if[i].mon_ndev == ndev || + g_monitor.mon_if[i].real_ndev == ndev) { + g_monitor.mon_if[i].real_ndev = NULL; + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(g_monitor.mon_if[i].mon_ndev); + free_netdev(g_monitor.mon_if[i].mon_ndev); + g_monitor.mon_if[i].mon_ndev = NULL; + g_monitor.monitor_state = MONITOR_STATE_INTERFACE_DELETED; + break; + } + } + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + + if (g_monitor.monitor_state != + MONITOR_STATE_INTERFACE_DELETED) + MON_PRINT("interface not found in monitor IF array, is this a monitor IF? 0x%p\n", + ndev); + mutex_unlock(&g_monitor.lock); + + return 0; +} + +int dhd_monitor_init(void *dhd_pub) +{ + if (g_monitor.monitor_state == MONITOR_STATE_DEINIT) { + g_monitor.dhd_pub = dhd_pub; + mutex_init(&g_monitor.lock); + g_monitor.monitor_state = MONITOR_STATE_INIT; + } + return 0; +} + +int dhd_monitor_uninit(void) +{ + int i; + struct net_device *ndev; + bool rollback_lock = false; + mutex_lock(&g_monitor.lock); + if (g_monitor.monitor_state != MONITOR_STATE_DEINIT) { + for (i = 0; i < DHD_MAX_IFS; i++) { + ndev = g_monitor.mon_if[i].mon_ndev; + if (ndev) { + if (rtnl_is_locked()) { + rtnl_unlock(); + rollback_lock = true; + } + unregister_netdev(ndev); + free_netdev(ndev); + g_monitor.mon_if[i].real_ndev = NULL; + g_monitor.mon_if[i].mon_ndev = NULL; + if (rollback_lock) { + rtnl_lock(); + rollback_lock = false; + } + } + } + g_monitor.monitor_state = MONITOR_STATE_DEINIT; + } + mutex_unlock(&g_monitor.lock); + return 0; +} diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_sched.c b/drivers/net/wireless/bcmdhd/dhd_linux_sched.c index ac5fc74d..aadd122f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux_sched.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux_sched.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux_sched.c 279742 2011-08-25 17:24:48Z $ + * $Id: dhd_linux_sched.c,v 1.3 2009-04-10 04:14:49 Exp $ */ #include #include diff --git a/drivers/net/wireless/bcmdhd/dhd_proto.h b/drivers/net/wireless/bcmdhd/dhd_proto.h index 0787cb36..bb1d7365 100644 --- a/drivers/net/wireless/bcmdhd/dhd_proto.h +++ b/drivers/net/wireless/bcmdhd/dhd_proto.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_proto.h 275786 2011-08-04 22:42:42Z $ + * $Id: dhd_proto.h,v 1.8.10.6 2010-12-22 23:47:24 Exp $ */ #ifndef _dhd_proto_h_ diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 7d37461b..e578d702 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 288105 2011-10-06 01:58:02Z $ + * $Id: dhd_sdio.c 326662 2012-04-10 06:38:08Z $ */ #include @@ -351,7 +351,7 @@ static const uint retry_limit = 2; static bool forcealign; /* Flag to indicate if we should download firmware on driver load */ -uint dhd_download_fw_on_driverload = FALSE; +uint dhd_download_fw_on_driverload = TRUE; #define ALIGNMENT 4 @@ -380,10 +380,9 @@ static const uint max_roundup = 512; /* Try doing readahead */ static bool dhd_readahead; - /* To check if there's window offered */ #define DATAOK(bus) \ - (((uint8)(bus->tx_max - bus->tx_seq) > 2) && \ + (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) /* To check if there's window offered for ctrl frame */ @@ -537,12 +536,11 @@ dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address) /* Turn backplane clock on or off */ -/* HTC_CSP_START */ -static int htclk_fail = 0; -/* HTC_CSP_END */ static int dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) { +#define HT_AVAIL_ERROR_MAX 10 + static int ht_avail_error = 0; int err; uint8 clkctl, clkreq, devctl; bcmsdh_info_t *sdh; @@ -555,18 +553,22 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) clkctl = 0; sdh = bus->sdh; - if (on) { /* Request HT Avail */ clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; - - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); if (err) { - DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); - goto error; + ht_avail_error++; + if (ht_avail_error < HT_AVAIL_ERROR_MAX) { + DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); + } else { + if (ht_avail_error == HT_AVAIL_ERROR_MAX) + dhd_os_send_hang_message(bus->dhd); + } + return BCME_ERROR; + } else { + ht_avail_error = 0; } if (pendok && @@ -579,7 +581,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); if (err) { DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err)); - goto error; + return BCME_ERROR; } /* Go to pending and await interrupt if appropriate */ @@ -589,14 +591,13 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) if (err) { DHD_ERROR(("%s: Devctl access error setting CA: %d\n", __FUNCTION__, err)); - goto error; + return BCME_ERROR; } devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); DHD_INFO(("CLKCTL: set PENDING\n")); bus->clkstate = CLK_PENDING; - htclk_fail = 0; return BCME_OK; } else if (bus->clkstate == CLK_PENDING) { /* Cancel CA-only interrupt filter */ @@ -614,12 +615,12 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) } if (err) { DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); - goto error; + return BCME_ERROR; } if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n", __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl)); - goto error; + return BCME_ERROR; } @@ -658,20 +659,10 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) if (err) { DHD_ERROR(("%s: Failed access turning clock off: %d\n", __FUNCTION__, err)); - goto error; + return BCME_ERROR; } } - htclk_fail = 0; return BCME_OK; -/* HTC_CSP_START */ -error: - htclk_fail++; - if (htclk_fail >= 3) { - htclk_fail = 0; - dhd_info_send_hang_message(bus->dhd); - } - return BCME_ERROR; -/* HTC_CSP_END */ } /* Change idle/active SD state */ @@ -816,7 +807,8 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) #ifdef DHD_DEBUG if (dhd_console_ms == 0) #endif /* DHD_DEBUG */ - dhd_os_wd_timer(bus->dhd, 0); + if (bus->poll == 0) + dhd_os_wd_timer(bus->dhd, 0); break; } #ifdef DHD_DEBUG @@ -866,8 +858,10 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); /* Isolate the bus */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, - SBSDIO_DEVCTL_PADS_ISO, NULL); + if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) { + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_PADS_ISO, NULL); + } /* Change state */ bus->sleeping = TRUE; @@ -1191,7 +1185,6 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) if (!bus->dhd->wlfc_state) #endif PKTFREE(osh, pkt, TRUE); - DHD_ERROR(("%s: out of bus->txq !!!\n", __FUNCTION__)); ret = BCME_NORESOURCE; } else @@ -1308,10 +1301,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) return cnt; } -/* HTC_CSP_START */ -static int bus_txctl_failed_num = 0; -/* HTC_CSP_END */ - int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) { @@ -1386,9 +1375,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Send from dpc */ bus->ctrl_frame_buf = frame; bus->ctrl_frame_len = len; - dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); - if (bus->ctrl_frame_stat == FALSE) { DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__)); ret = 0; @@ -1406,11 +1393,6 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) bus->dhd->txcnt_timeout = 0; if (ret == -1) { - -/* HTC_CSP_START */ - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; -/* HTC_CSP_END */ - #ifdef DHD_DEBUG if (DHD_BYTES_ON() && DHD_CTL_ON()) { prhex("Tx Frame", frame, len); @@ -1448,6 +1430,9 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) } } + if (ret == 0) { + bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; + } } while ((ret < 0) && retries++ < TXRETRIES); } @@ -1464,20 +1449,6 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) else bus->dhd->tx_ctlpkts++; -/* HTC_CSP_START */ - if (ret) { - bus_txctl_failed_num++; - - /* if the bus_txctl failed number is over 3 times, just send HANG event. */ - if (bus_txctl_failed_num >= 3) { - bus_txctl_failed_num = 0; - DHD_ERROR(("%s: Event HANG sent up\n", __func__)); - dhd_info_send_hang_message(bus->dhd); - } - } else - bus_txctl_failed_num = 0; -/* HTC_CSP_END */ - if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT) return -ETIMEDOUT; @@ -1489,7 +1460,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) { int timeleft; uint rxlen = 0; - bool pending; + bool pending = FALSE; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1516,8 +1487,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) dhd_os_sdunlock(bus->dhd); #endif /* DHD_DEBUG */ } else if (pending == TRUE) { - DHD_CTL(("%s: canceled\n", __FUNCTION__)); - return -ERESTARTSYS; + /* signal pending */ + DHD_ERROR(("%s: signal pending\n", __FUNCTION__)); + return -EINTR; } else { DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); #ifdef DHD_DEBUG @@ -1556,7 +1528,7 @@ enum { #ifdef DHD_DEBUG IOV_CHECKDIED, IOV_SERIALCONS, -#endif +#endif /* DHD_DEBUG */ IOV_DOWNLOAD, IOV_SOCRAM_STATE, IOV_FORCEEVEN, @@ -2821,6 +2793,9 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) uint retries; int bcmerror = 0; + if (!bus->sih) + return BCME_ERROR; + /* To enter download state, disable ARM and reset SOCRAM. * To exit download state, simply reset ARM (default is RAM boot). */ @@ -3021,7 +2996,6 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, return bcmerror; } -static bool dhd_bus_do_stop = FALSE; void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) { @@ -3042,7 +3016,6 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) dhd_os_sdlock(bus->dhd); BUS_WAKE(bus); - dhd_bus_do_stop = TRUE; /* Change our idea of bus state */ bus->dhd->busstate = DHD_BUS_DOWN; @@ -3096,7 +3069,12 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) bus->rxskip = FALSE; bus->tx_seq = bus->rx_seq = 0; - dhd_bus_do_stop = FALSE; + /* Set to a safe default. It gets updated when we + * receive a packet from the fw but when we reset, + * we need a safe default to be able to send the + * initial mac address. + */ + bus->tx_max = 4; if (enforce_mutex) dhd_os_sdunlock(bus->dhd); @@ -3152,9 +3130,9 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000); ready = 0; - while (ready != enable && !dhd_timeout_expired(&tmo)) - ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); - + do { + ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); + } while (ready != enable && !dhd_timeout_expired(&tmo)); DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", __FUNCTION__, enable, ready, tmo.elapsed)); @@ -3175,9 +3153,6 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) bus->hostintmask &= ~I_HMB_FRAME_IND; bus->hostintmask |= I_XMTDATA_AVAIL; } -#ifdef HTC_KlocWork - if(bus->regs != NULL) -#endif W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); @@ -3608,7 +3583,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -3809,6 +3784,14 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; rxseq++, rxleft--) { +#ifdef DHDTHREAD + /* tx more to improve rx performance */ + if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && + pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { + dhdsdio_sendfromq(bus, dhd_txbound); + } +#endif /* DHDTHREAD */ + /* Handle glomming separately */ if (bus->glom || bus->glomd) { uint8 cnt; @@ -4029,7 +4012,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -4186,7 +4169,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) if ((uint8)(txmax - bus->tx_seq) > 0x40) { DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq; + txmax = bus->tx_max; } bus->tx_max = txmax; @@ -4455,13 +4438,12 @@ dhdsdio_dpc(dhd_bus_t *bus) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); -#ifndef OOB_INTR_ONLY if (bus->dhd->busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__)); bus->intstatus = 0; return 0; } -#endif + /* Start with leftover status bits */ intstatus = bus->intstatus; @@ -4620,8 +4602,32 @@ dhdsdio_dpc(dhd_bus_t *bus) bcmsdh_intr_enable(sdh); } +#if defined(OOB_INTR_ONLY) && !defined(HW_OOB) + /* In case of SW-OOB(using edge trigger), + * Check interrupt status in the dongle again after enable irq on the host. + * and rechedule dpc if interrupt is pended in the dongle. + * There is a chance to miss OOB interrupt while irq is disabled on the host. + * No need to do this with HW-OOB(level trigger) + */ + R_SDREG(newstatus, ®s->intstatus, retries); + if (bcmsdh_regfail(bus->sdh)) + newstatus = 0; + if (newstatus & bus->hostintmask) { + bus->ipend = TRUE; + resched = TRUE; + } +#endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ + if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { int ret, i; + uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; + + if (*frame_seq != bus->tx_seq) { + DHD_INFO(("%s IOCTL frame seq lag detected!" + " frm_seq:%d != bus->tx_seq:%d, corrected\n", + __FUNCTION__, *frame_seq, bus->tx_seq)); + *frame_seq = bus->tx_seq; + } ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, @@ -4722,7 +4728,7 @@ dhdsdio_isr(void *arg) } sdh = bus->sdh; - if ((bus->dhd->busstate == DHD_BUS_DOWN)&&(!dhd_bus_do_stop)) { + if (bus->dhd->busstate == DHD_BUS_DOWN) { DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); return; } @@ -5216,30 +5222,28 @@ dhd_dump_cis(uint fn, uint8 *cis) } #endif /* DHD_DEBUG */ -int bcm_add_ie_reverse = 0; static bool dhdsdio_chipmatch(uint16 chipid) { if (chipid == BCM4325_CHIP_ID) return TRUE; - if (chipid == BCM4329_CHIP_ID) { - bcm_add_ie_reverse = 1; + if (chipid == BCM4329_CHIP_ID) return TRUE; - } if (chipid == BCM4315_CHIP_ID) return TRUE; if (chipid == BCM4319_CHIP_ID) return TRUE; - if (chipid == BCM4336_CHIP_ID) - return TRUE; if (chipid == BCM4330_CHIP_ID) return TRUE; + if (chipid == BCM43239_CHIP_ID) + return TRUE; + if (chipid == BCM4336_CHIP_ID) + return TRUE; if (chipid == BCM43237_CHIP_ID) return TRUE; if (chipid == BCM43362_CHIP_ID) return TRUE; - if (chipid == BCM43239_CHIP_ID) - return TRUE; + return FALSE; } @@ -5416,6 +5420,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, if (ret == BCME_NOTUP) goto fail; } + /* Ok, have the per-port tell the stack we're open for business */ if (dhd_net_attach(bus->dhd, 0) != 0) { DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); @@ -5490,13 +5495,13 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, for (fn = 0; fn <= numfn; fn++) { if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { - DHD_ERROR(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); + DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); break; } bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) { - DHD_ERROR(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); + DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); break; } @@ -5505,8 +5510,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, while (fn-- > 0) { ASSERT(cis[fn]); - if(cis[fn]) - MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); + MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); } if (err) { @@ -5593,8 +5597,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, return TRUE; fail: - if (bus->sih != NULL) + if (bus->sih != NULL) { si_detach(bus->sih); + bus->sih = NULL; + } return FALSE; } @@ -5784,7 +5790,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) return; if (bus->rxbuf) { -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->rxbuf, bus->rxblen); #endif bus->rxctl = bus->rxbuf = NULL; @@ -5792,7 +5798,7 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) } if (bus->databuf) { -#ifndef DHD_USE_STATIC_BUF +#ifndef CONFIG_DHD_USE_STATIC_BUF MFREE(osh, bus->databuf, MAX_DATA_BUF); #endif bus->databuf = NULL; @@ -5816,19 +5822,18 @@ dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool r return; if (bus->sih) { -#if !defined(BCMLXSDMMC) if (bus->dhd) { dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); } - +#if !defined(BCMLXSDMMC) if (dongle_isolation == FALSE) si_watchdog(bus->sih, 4); - +#endif /* !defined(BCMLXSDMMC) */ if (bus->dhd) { dhdsdio_clkctl(bus, CLK_NONE, FALSE); } -#endif /* !defined(BCMLXSDMMC) */ si_detach(bus->sih); + bus->sih = NULL; if (bus->vars && bus->varsz) MFREE(osh, bus->vars, bus->varsz); bus->vars = NULL; @@ -6023,93 +6028,6 @@ dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params) bus->nvram_params = nvram_params; } -/* HTC_CSP_START */ -#define WIFI_MAC_PARAM_STR "macaddr=" -#define WIFI_MAX_MAC_LEN 17 /* XX:XX:XX:XX:XX:XX */ - -#define NVS_LEN_OFFSET 0x0C -#define NVS_DATA_OFFSET 0x40 - -extern unsigned char *get_wifi_nvs_ram(void); - -static uint -get_mac_from_wifi_nvs_ram(char* buf, unsigned int buf_len) -{ - unsigned char *nvs_ptr; - unsigned char *mac_ptr; - uint len = 0; - - if (!buf || !buf_len) { - return 0; - } - - nvs_ptr = get_wifi_nvs_ram(); - if (nvs_ptr) { - nvs_ptr += NVS_DATA_OFFSET; - } - - mac_ptr = strstr(nvs_ptr, WIFI_MAC_PARAM_STR); - if (mac_ptr) { - mac_ptr += strlen(WIFI_MAC_PARAM_STR); - - /* skip leading space */ - while (mac_ptr[0] == ' ') { - mac_ptr++; - } - - /* locate end-of-line */ - len = 0; - while (mac_ptr[len] != '\r' && mac_ptr[len] != '\n' && - mac_ptr[len] != '\0') { - len++; - } - - if (len > buf_len) { - len = buf_len; - } - memcpy(buf, mac_ptr, len); - } - - return len; -} - -/* - * Modify mac address attribute in buffer - * return : length of modified buffer - */ -static uint -modify_mac_attr(char* buf, unsigned buf_len, char *mac, unsigned int mac_len) -{ - unsigned char *mac_ptr; - uint len; - - if (!buf || !mac) { - return buf_len; - } - - mac_ptr = strstr(buf, WIFI_MAC_PARAM_STR); - if (mac_ptr) { - mac_ptr += strlen(WIFI_MAC_PARAM_STR); - - /* locate end-of-line */ - len = 0; - while (mac_ptr[len] != '\r' && mac_ptr[len] != '\n' && - mac_ptr[len] != '\0') { - len++; - } - - if (len != mac_len) { - /* shift remaining data */ - memmove(&mac_ptr[mac_len + 1], &mac_ptr[len + 1], buf_len - len); - buf_len = buf_len - len + mac_len; - } - memcpy(mac_ptr, mac, mac_len); - } - - return buf_len; -} -/* HTC_CSP_END */ - static int dhdsdio_download_nvram(struct dhd_bus *bus) { @@ -6120,11 +6038,7 @@ dhdsdio_download_nvram(struct dhd_bus *bus) char *bufp; char *pnv_path; bool nvram_file_exists; -/* HTC_CSP_START */ - char mac[WIFI_MAX_MAC_LEN]; - unsigned mac_len; -/* HTC_CSP_END */ - + pnv_path = bus->nv_path; nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0')); @@ -6132,7 +6046,6 @@ dhdsdio_download_nvram(struct dhd_bus *bus) return (0); if (nvram_file_exists) { - printf("%s: nvram_path=%s\n", __FUNCTION__, nv_path); image = dhd_os_open_image(pnv_path); if (image == NULL) goto err; @@ -6148,12 +6061,6 @@ dhdsdio_download_nvram(struct dhd_bus *bus) /* Download variables */ if (nvram_file_exists) { len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image); - /* HTC_CSP_START */ - mac_len = get_mac_from_wifi_nvs_ram(mac, WIFI_MAX_MAC_LEN); - if (mac_len > 0) { - len = modify_mac_attr(memblock, len, mac, mac_len); - } - /* HTC_CSP_END */ } else { len = strlen(bus->nvram_params); @@ -6208,9 +6115,7 @@ _dhdsdio_download_firmware(struct dhd_bus *bus) return 0; #endif } -/* HTC_CSP_START */ - DHD_DEFAULT(("firmware path = %s \n", bus->fw_path)); -/* HTC_CSP_END */ + /* Keep arm in reset */ if (dhdsdio_download_state(bus, TRUE)) { DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__)); @@ -6291,6 +6196,7 @@ dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf uint dhd_bus_chip(struct dhd_bus *bus) { + ASSERT(bus); ASSERT(bus->sih != NULL); return bus->sih->chip; } @@ -6298,6 +6204,7 @@ dhd_bus_chip(struct dhd_bus *bus) void * dhd_bus_pub(struct dhd_bus *bus) { + ASSERT(bus); return bus->dhd; } @@ -6344,7 +6251,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) bus->dhd->dongle_reset = TRUE; bus->dhd->up = FALSE; dhd_os_sdunlock(dhdp); - DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); /* App can now remove power from device */ } else @@ -6415,6 +6321,30 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) return bcmerror; } +/* Get Chip ID version */ +uint dhd_bus_chip_id(dhd_pub_t *dhdp) +{ + dhd_bus_t *bus = dhdp->bus; + + return bus->sih->chip; +} + +/* Get Chip Rev ID version */ +uint dhd_bus_chiprev_id(dhd_pub_t *dhdp) +{ + dhd_bus_t *bus = dhdp->bus; + + return bus->sih->chiprev; +} + +/* Get Chip Pkg ID version */ +uint dhd_bus_chippkg_id(dhd_pub_t *dhdp) +{ + dhd_bus_t *bus = dhdp->bus; + + return bus->sih->chippkg; +} + int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size) { diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h new file mode 100644 index 00000000..c4d25180 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.h @@ -0,0 +1,276 @@ +/* +* Copyright (C) 1999-2011, Broadcom Corporation +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2 (the "GPL"), +* available at http://www.broadcom.com/licenses/GPLv2.php, with the +* following added to such license: +* +* As a special exception, the copyright holders of this software give you +* permission to link this software with independent modules, and to copy and +* distribute the resulting executable under terms of your choice, provided that +* you also meet, for each linked independent module, the terms and conditions of +* the license of that module. An independent module is a module which is not +* derived from this software. The special exception does not apply to any +* modifications of the software. +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a license +* other than the GPL, without Broadcom's express prior written consent. +* $Id: dhd_wlfc.h 286994 2011-09-29 21:27:44Z $ +* +*/ +#ifndef __wlfc_host_driver_definitions_h__ +#define __wlfc_host_driver_definitions_h__ + +/* 16 bits will provide an absolute max of 65536 slots */ +#define WLFC_HANGER_MAXITEMS 1024 + +#define WLFC_HANGER_ITEM_STATE_FREE 1 +#define WLFC_HANGER_ITEM_STATE_INUSE 2 + +#define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ +#define WLFC_PKTID_HSLOT_SHIFT 8 + +/* x -> TXSTATUS TAG to/from firmware */ +#define WLFC_PKTID_HSLOT_GET(x) \ + (((x) >> WLFC_PKTID_HSLOT_SHIFT) & WLFC_PKTID_HSLOT_MASK) +#define WLFC_PKTID_HSLOT_SET(var, slot) \ + ((var) = ((var) & ~(WLFC_PKTID_HSLOT_MASK << WLFC_PKTID_HSLOT_SHIFT)) | \ + (((slot) & WLFC_PKTID_HSLOT_MASK) << WLFC_PKTID_HSLOT_SHIFT)) + +#define WLFC_PKTID_FREERUNCTR_MASK 0xff + +#define WLFC_PKTID_FREERUNCTR_GET(x) ((x) & WLFC_PKTID_FREERUNCTR_MASK) +#define WLFC_PKTID_FREERUNCTR_SET(var, ctr) \ + ((var) = (((var) & ~WLFC_PKTID_FREERUNCTR_MASK) | \ + (((ctr) & WLFC_PKTID_FREERUNCTR_MASK)))) + +#define WLFC_PKTQ_PENQ(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec)))? \ + NULL : pktq_penq((pq), (prec), (p))) +#define WLFC_PKTQ_PENQ_HEAD(pq, prec, p) ((pktq_full((pq)) || pktq_pfull((pq), (prec))) ? \ + NULL : pktq_penq_head((pq), (prec), (p))) + +typedef enum ewlfc_packet_state { + eWLFC_PKTTYPE_NEW, + eWLFC_PKTTYPE_DELAYED, + eWLFC_PKTTYPE_SUPPRESSED, + eWLFC_PKTTYPE_MAX +} ewlfc_packet_state_t; + +typedef enum ewlfc_mac_entry_action { + eWLFC_MAC_ENTRY_ACTION_ADD, + eWLFC_MAC_ENTRY_ACTION_DEL, + eWLFC_MAC_ENTRY_ACTION_MAX +} ewlfc_mac_entry_action_t; + +typedef struct wlfc_hanger_item { + uint8 state; + uint8 pad[3]; + uint32 identifier; + void* pkt; +#ifdef PROP_TXSTATUS_DEBUG + uint32 push_time; +#endif +} wlfc_hanger_item_t; + +typedef struct wlfc_hanger { + int max_items; + uint32 pushed; + uint32 popped; + uint32 failed_to_push; + uint32 failed_to_pop; + uint32 failed_slotfind; + wlfc_hanger_item_t items[1]; +} wlfc_hanger_t; + +#define WLFC_HANGER_SIZE(n) ((sizeof(wlfc_hanger_t) - \ + sizeof(wlfc_hanger_item_t)) + ((n)*sizeof(wlfc_hanger_item_t))) + +#define WLFC_STATE_OPEN 1 +#define WLFC_STATE_CLOSE 2 + +#define WLFC_PSQ_PREC_COUNT ((AC_COUNT + 1) * 2) /* 2 for each AC traffic and bc/mc */ +#define WLFC_PSQ_LEN 64 +#define WLFC_SENDQ_LEN 256 + +#define WLFC_FLOWCONTROL_DELTA 8 +#define WLFC_FLOWCONTROL_HIWATER (WLFC_PSQ_LEN - WLFC_FLOWCONTROL_DELTA) +#define WLFC_FLOWCONTROL_LOWATER (WLFC_FLOWCONTROL_HIWATER - WLFC_FLOWCONTROL_DELTA) + +typedef struct wlfc_mac_descriptor { + uint8 occupied; + uint8 interface_id; + uint8 iftype; + uint8 state; + uint8 ac_bitmap; /* for APSD */ + uint8 requested_credit; + uint8 requested_packet; + uint8 ea[ETHER_ADDR_LEN]; + /* + maintain (MAC,AC) based seq count for + packets going to the device. As well as bc/mc. + */ + uint8 seq[AC_COUNT + 1]; + uint8 generation; + struct pktq psq; + /* The AC pending bitmap that was reported to the fw at last change */ + uint8 traffic_lastreported_bmp; + /* The new AC pending bitmap */ + uint8 traffic_pending_bmp; + /* 1= send on next opportunity */ + uint8 send_tim_signal; + uint8 mac_handle; +#ifdef PROP_TXSTATUS_DEBUG + uint32 dstncredit_sent_packets; + uint32 dstncredit_acks; + uint32 opened_ct; + uint32 closed_ct; +#endif +} wlfc_mac_descriptor_t; + +#define WLFC_DECR_SEQCOUNT(entry, prec) do { if (entry->seq[(prec)] == 0) {\ + entry->seq[prec] = 0xff; } else entry->seq[prec]--;} while (0) + +#define WLFC_INCR_SEQCOUNT(entry, prec) entry->seq[(prec)]++ +#define WLFC_SEQCOUNT(entry, prec) entry->seq[(prec)] + +typedef struct athost_wl_stat_counters { + uint32 pktin; + uint32 pkt2bus; + uint32 pktdropped; + uint32 tlv_parse_failed; + uint32 rollback; + uint32 rollback_failed; + uint32 sendq_full_error; + uint32 delayq_full_error; + uint32 credit_request_failed; + uint32 packet_request_failed; + uint32 mac_update_failed; + uint32 psmode_update_failed; + uint32 interface_update_failed; + uint32 wlfc_header_only_pkt; + uint32 txstatus_in; + uint32 d11_suppress; + uint32 wl_suppress; + uint32 bad_suppress; + uint32 pkt_freed; + uint32 pkt_free_err; + uint32 psq_wlsup_retx; + uint32 psq_wlsup_enq; + uint32 psq_d11sup_retx; + uint32 psq_d11sup_enq; + uint32 psq_hostq_retx; + uint32 psq_hostq_enq; + uint32 mac_handle_notfound; + uint32 wlc_tossed_pkts; + uint32 dhd_hdrpulls; + uint32 generic_error; + /* an extra one for bc/mc traffic */ + uint32 sendq_pkts[AC_COUNT + 1]; +#ifdef PROP_TXSTATUS_DEBUG + /* all pkt2bus -> txstatus latency accumulated */ + uint32 latency_sample_count; + uint32 total_status_latency; + uint32 latency_most_recent; + int idx_delta; + uint32 deltas[10]; + uint32 fifo_credits_sent[6]; + uint32 fifo_credits_back[6]; + uint32 dropped_qfull[6]; + uint32 signal_only_pkts_sent; + uint32 signal_only_pkts_freed; +#endif +} athost_wl_stat_counters_t; + +#ifdef PROP_TXSTATUS_DEBUG +#define WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac) do { \ + (ctx)->stats.fifo_credits_sent[(ac)]++;} while (0) +#define WLFC_HOST_FIFO_CREDIT_INC_BACKCTRS(ctx, ac) do { \ + (ctx)->stats.fifo_credits_back[(ac)]++;} while (0) +#define WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, ac) do { \ + (ctx)->stats.dropped_qfull[(ac)]++;} while (0) +#else +#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 + +#define WLFC_FCMODE_NONE 0 +#define WLFC_FCMODE_IMPLIED_CREDIT 1 +#define WLFC_FCMODE_EXPLICIT_CREDIT 2 + +/* How long to defer borrowing in milliseconds */ +#define WLFC_BORROW_DEFER_PERIOD_MS 100 + +/* Mask to represent available ACs (note: BC/MC is ignored */ +#define WLFC_AC_MASK 0xF + +/* Mask to check for only on-going AC_BE traffic */ +#define WLFC_AC_BE_TRAFFIC_ONLY 0xD + +typedef struct athost_wl_status_info { + uint8 last_seqid_to_wlc; + + /* OSL handle */ + osl_t* osh; + /* dhd pub */ + void* dhdp; + + /* stats */ + athost_wl_stat_counters_t stats; + + /* the additional ones are for bc/mc and ATIM FIFO */ + int FIFO_credit[AC_COUNT + 2]; + + /* Credit borrow counts for each FIFO from each of the other FIFOs */ + int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; + + struct pktq SENDQ; + + /* packet hanger and MAC->handle lookup table */ + void* hanger; + struct { + /* table for individual nodes */ + wlfc_mac_descriptor_t nodes[WLFC_MAC_DESC_TABLE_SIZE]; + /* table for interfaces */ + wlfc_mac_descriptor_t interfaces[WLFC_MAX_IFNUM]; + /* OS may send packets to unknown (unassociated) destinations */ + /* A place holder for bc/mc and packets to unknown destinations */ + wlfc_mac_descriptor_t other; + } destination_entries; + /* token position for different priority packets */ + uint8 token_pos[AC_COUNT+1]; + /* ON/OFF state for flow control to the host network interface */ + uint8 hostif_flow_state[WLFC_MAX_IFNUM]; + uint8 host_ifidx; + /* to flow control an OS interface */ + uint8 toggle_host_if; + + /* + Mode in which the dhd flow control shall operate. Must be set before + traffic starts to the device. + 0 - Do not do any proptxtstatus flow control + 1 - Use implied credit from a packet status + 2 - Use explicit credit + */ + uint8 proptxstatus_mode; + + /* To borrow credits */ + uint8 allow_credit_borrow; + + /* Timestamp to compute how long to defer borrowing for */ + uint32 borrow_defer_timestamp; + +} athost_wl_status_info_t; + +int dhd_wlfc_enable(dhd_pub_t *dhd); +int dhd_wlfc_interface_event(struct dhd_info *, + ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea); +int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data); +int dhd_wlfc_event(struct dhd_info *dhd); +int dhd_os_wlfc_block(dhd_pub_t *pub); +int dhd_os_wlfc_unblock(dhd_pub_t *pub); + +#endif /* __wlfc_host_driver_definitions_h__ */ diff --git a/drivers/net/wireless/bcmdhd/dngl_stats.h b/drivers/net/wireless/bcmdhd/dngl_stats.h index 76989423..9cdf718b 100644 --- a/drivers/net/wireless/bcmdhd/dngl_stats.h +++ b/drivers/net/wireless/bcmdhd/dngl_stats.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dngl_stats.h,v 1.5 2008-06-02 16:56:20 $ + * $Id: dngl_stats.h,v 1.5 2008-06-02 16:56:20 Exp $ */ #ifndef _dngl_stats_h_ diff --git a/drivers/net/wireless/bcmdhd/dngl_wlhdr.h b/drivers/net/wireless/bcmdhd/dngl_wlhdr.h new file mode 100644 index 00000000..8b39b9ec --- /dev/null +++ b/drivers/net/wireless/bcmdhd/dngl_wlhdr.h @@ -0,0 +1,40 @@ +/* + * Dongle WL Header definitions + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: dngl_wlhdr.h,v 1.1 2009-01-08 01:21:12 Exp $ + */ + +#ifndef _dngl_wlhdr_h_ +#define _dngl_wlhdr_h_ + +typedef struct wl_header { + uint8 type; /* Header type */ + uint8 version; /* Header version */ + int8 rssi; /* RSSI */ + uint8 pad; /* Unused */ +} wl_header_t; + +#define WL_HEADER_LEN sizeof(wl_header_t) +#define WL_HEADER_TYPE 0 +#define WL_HEADER_VER 1 +#endif /* _dngl_wlhdr_h_ */ diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c index ccf4a7a0..0e493343 100644 --- a/drivers/net/wireless/bcmdhd/hndpmu.c +++ b/drivers/net/wireless/bcmdhd/hndpmu.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.c 279296 2011-08-23 23:17:20Z $ + * $Id: hndpmu.c,v 1.228.2.56 2011-02-11 22:49:07 $ */ #include @@ -93,26 +93,8 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v8[] = { {0, 0x1} }; /* SDIO Drive Strength to sel value table for PMU Rev 11 (1.2v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab4_1v2[] = { - {16, 0x3}, - {13, 0x2}, - {11, 0x1}, - {8, 0x0}, - {6, 0x7}, - {4, 0x6}, - {2, 0x5}, - {0, 0x4} }; /* SDIO Drive Strength to sel value table for PMU Rev 11 (2.5v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab4_2v5[] = { - {80, 0x5}, - {65, 0x4}, - {55, 0x7}, - {40, 0x6}, - {30, 0x1}, - {20, 0x0}, - {10, 0x3}, - {0, 0x2} }; /* SDIO Drive Strength to sel value table for PMU Rev 13 (1.8v) */ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { @@ -125,14 +107,6 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab5_1v8[] = { {0, 0x0} }; /* SDIO Drive Strength to sel value table for PMU Rev 13 (3.3v) */ -static const sdiod_drive_str_t sdiod_drive_strength_tab5_3v3[] = { - {12, 0x7}, - {10, 0x6}, - {8, 0x5}, - {6, 0x4}, - {4, 0x2}, - {2, 0x1}, - {0, 0x0} }; #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) @@ -206,10 +180,7 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) if (i > 0 && drivestrength > str_tab[i].strength) i--; -#ifdef HTC_KlocWork - if( cc!= NULL ) - { -#endif + W_REG(osh, &cc->chipcontrol_addr, 1); cc_data_temp = R_REG(osh, &cc->chipcontrol_data); cc_data_temp &= ~str_mask; @@ -219,9 +190,6 @@ si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) PMU_MSG(("SDIO: %dmA drive strength requested; set to %dmA\n", drivestrength, str_tab[i].strength)); } -#ifdef HTC_KlocWork - } // cc!=NULL -#endif /* Return to original core */ si_restore_core(sih, origidx, intr_val); diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile index c07266fd..67c4906f 100644 --- a/drivers/net/wireless/bcmdhd/include/Makefile +++ b/drivers/net/wireless/bcmdhd/include/Makefile @@ -10,7 +10,7 @@ # # Copyright 2005, Broadcom, Inc. # -# $Id: Makefile 241702 2011-02-19 00:41:03Z automrgr $ +# $Id: Makefile 241702 2011-02-19 00:41:03Z $ # SRCBASE := .. diff --git a/drivers/net/wireless/bcmdhd/include/aidmp.h b/drivers/net/wireless/bcmdhd/include/aidmp.h index 71b25b0f..b993a033 100644 --- a/drivers/net/wireless/bcmdhd/include/aidmp.h +++ b/drivers/net/wireless/bcmdhd/include/aidmp.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aidmp.h 275703 2011-08-04 20:20:27Z $ + * $Id: aidmp.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmcdc.h b/drivers/net/wireless/bcmdhd/include/bcmcdc.h index 701e6736..77a20f87 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmcdc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmcdc.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmcdc.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmcdc.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bcmcdc_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmdefs.h b/drivers/net/wireless/bcmdhd/include/bcmdefs.h index 0b0d00c7..17cc0e95 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdefs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdefs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdefs.h 279291 2011-08-23 23:10:02Z $ + * $Id: bcmdefs.h 279282 2011-08-23 22:44:02Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index 3f69b139..cdfc5fe6 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdevs.h 279768 2011-08-25 19:38:56Z $ + * $Id: bcmdevs.h 332966 2012-05-11 22:40:21Z $ */ @@ -63,6 +63,7 @@ #define BCM_DNGL_BL_PID_43239 0xbd1b #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 +#define BCM_DNGL_BL_PID_4324 0xbd1c #define BCM_HWUSB_PID_43239 43239 @@ -135,10 +136,15 @@ #define BCM43237_D11N5G_ID 0x4356 #define BCM43227_D11N2G_ID 0x4358 #define BCM43228_D11N_ID 0x4359 -#define BCM43228_D11N5G_ID 0x435a +#define BCM43228_D11N5G_ID 0x435a #define BCM43362_D11N_ID 0x4363 #define BCM43239_D11N_ID 0x4370 +#define BCM4324_D11N_ID 0x4374 +#define BCM43217_D11N2G_ID 0x43a9 +#define BCM43131_D11N2G_ID 0x43aa +#define BCM4314_D11N2G_ID 0x4364 +#define BCM43142_D11N2G_ID 0x4365 #define BCMGPRS_UART_ID 0x4333 #define BCMGPRS2_UART_ID 0x4344 @@ -200,7 +206,7 @@ #define BCM4319_CHIP_ID 0x4319 #define BCM4320_CHIP_ID 0x4320 #define BCM4321_CHIP_ID 0x4321 -#define BCM43217_CHIP_ID 43217 +#define BCM43217_CHIP_ID 43217 #define BCM4322_CHIP_ID 0x4322 #define BCM43221_CHIP_ID 43221 #define BCM43222_CHIP_ID 43222 @@ -228,8 +234,9 @@ #define BCM43362_CHIP_ID 43362 #define BCM4330_CHIP_ID 0x4330 #define BCM6362_CHIP_ID 0x6362 -#define BCM43142_CHIP_ID 43142 -#define BCM4314_CHIP_ID 0x4314 +#define BCM4314_CHIP_ID 0x4314 +#define BCM43142_CHIP_ID 43142 +#define BCM4324_CHIP_ID 0x4324 #define BCM4342_CHIP_ID 4342 #define BCM4402_CHIP_ID 0x4402 @@ -285,6 +292,12 @@ #define BCM43224_FAB_SMIC 0xa #define BCM4336_WLBGA_PKG_ID 0x8 #define BCM4330_WLBGA_PKG_ID 0x0 +#define BCM4314PCIE_ARM_PKG_ID (8 | 0) +#define BCM4314SDIO_PKG_ID (8 | 1) +#define BCM4314PCIE_PKG_ID (8 | 2) +#define BCM4314SDIO_ARM_PKG_ID (8 | 3) +#define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) +#define BCM4314DEV_PKG_ID (8 | 6) #define PCIXX21_FLASHMEDIA0_ID 0x8033 #define PCIXX21_SDIOH0_ID 0x8034 @@ -360,10 +373,10 @@ #define BFL2_EXTLNA_TX 0x08000000 #define BFL2_4313_RADIOREG 0x10000000 +#define BFL2_SECI_LOPWR_DIS 0x20000000 - #define BOARD_GPIO_BTC3W_IN 0x850 #define BOARD_GPIO_BTC3W_OUT 0x020 #define BOARD_GPIO_BTCMOD_IN 0x010 @@ -628,6 +641,7 @@ #define BCM94319USBSDB_SSID 0x05a2 + #define BCM94329AGB_SSID 0X04b9 #define BCM94329TDKMDL1_SSID 0X04ba #define BCM94329TDKMDL11_SSID 0X04fc @@ -677,6 +691,7 @@ #define BCM943239MOD_SSID 0x05ac +#define BCM943239REF_SSID 0x05aa #define BCM94331X19 0x00D6 @@ -697,7 +712,6 @@ #define BCM94331CSAX_SSID 0x00EF - #define BCM953572BU_SSID 0x058D #define BCM953572NR2_SSID 0x058E #define BCM947188NR2_SSID 0x058F diff --git a/drivers/net/wireless/bcmdhd/include/bcmendian.h b/drivers/net/wireless/bcmdhd/include/bcmendian.h index ac06c6e7..f3356a72 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmendian.h +++ b/drivers/net/wireless/bcmdhd/include/bcmendian.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmendian.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmendian.h 277737 2011-08-16 17:54:59Z $ * * This file by default provides proper behavior on little-endian architectures. * On big-endian architectures, IL_BIGENDIAN should be defined. diff --git a/drivers/net/wireless/bcmdhd/include/bcmpcispi.h b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h new file mode 100644 index 00000000..51e0427e --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmpcispi.h @@ -0,0 +1,181 @@ +/* + * Broadcom PCI-SPI Host Controller Register Definitions + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmpcispi.h 277737 2011-08-16 17:54:59Z $ + */ +#ifndef _BCM_PCI_SPI_H +#define _BCM_PCI_SPI_H + +/* cpp contortions to concatenate w/arg prescan */ +#ifndef PAD +#define _PADLINE(line) pad ## line +#define _XSTR(line) _PADLINE(line) +#define PAD _XSTR(__LINE__) +#endif /* PAD */ + + +typedef volatile struct { + uint32 spih_ctrl; /* 0x00 SPI Control Register */ + uint32 spih_stat; /* 0x04 SPI Status Register */ + uint32 spih_data; /* 0x08 SPI Data Register, 32-bits wide */ + uint32 spih_ext; /* 0x0C SPI Extension Register */ + uint32 PAD[4]; /* 0x10-0x1F PADDING */ + + uint32 spih_gpio_ctrl; /* 0x20 SPI GPIO Control Register */ + uint32 spih_gpio_data; /* 0x24 SPI GPIO Data Register */ + uint32 PAD[6]; /* 0x28-0x3F PADDING */ + + uint32 spih_int_edge; /* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */ + uint32 spih_int_pol; /* 0x44 SPI Interrupt Polarity Register (0=Active Low, */ + /* 1=Active High) */ + uint32 spih_int_mask; /* 0x48 SPI Interrupt Mask */ + uint32 spih_int_status; /* 0x4C SPI Interrupt Status */ + uint32 PAD[4]; /* 0x50-0x5F PADDING */ + + uint32 spih_hex_disp; /* 0x60 SPI 4-digit hex display value */ + uint32 spih_current_ma; /* 0x64 SPI SD card current consumption in mA */ + uint32 PAD[1]; /* 0x68 PADDING */ + uint32 spih_disp_sel; /* 0x6c SPI 4-digit hex display mode select (1=current) */ + uint32 PAD[4]; /* 0x70-0x7F PADDING */ + uint32 PAD[8]; /* 0x80-0x9F PADDING */ + uint32 PAD[8]; /* 0xA0-0xBF PADDING */ + uint32 spih_pll_ctrl; /* 0xC0 PLL Control Register */ + uint32 spih_pll_status; /* 0xC4 PLL Status Register */ + uint32 spih_xtal_freq; /* 0xC8 External Clock Frequency in units of 10000Hz */ + uint32 spih_clk_count; /* 0xCC External Clock Count Register */ + +} spih_regs_t; + +typedef volatile struct { + uint32 cfg_space[0x40]; /* 0x000-0x0FF PCI Configuration Space (Read Only) */ + uint32 P_IMG_CTRL0; /* 0x100 PCI Image0 Control Register */ + + uint32 P_BA0; /* 0x104 32 R/W PCI Image0 Base Address register */ + uint32 P_AM0; /* 0x108 32 R/W PCI Image0 Address Mask register */ + uint32 P_TA0; /* 0x10C 32 R/W PCI Image0 Translation Address register */ + uint32 P_IMG_CTRL1; /* 0x110 32 R/W PCI Image1 Control register */ + uint32 P_BA1; /* 0x114 32 R/W PCI Image1 Base Address register */ + uint32 P_AM1; /* 0x118 32 R/W PCI Image1 Address Mask register */ + uint32 P_TA1; /* 0x11C 32 R/W PCI Image1 Translation Address register */ + uint32 P_IMG_CTRL2; /* 0x120 32 R/W PCI Image2 Control register */ + uint32 P_BA2; /* 0x124 32 R/W PCI Image2 Base Address register */ + uint32 P_AM2; /* 0x128 32 R/W PCI Image2 Address Mask register */ + uint32 P_TA2; /* 0x12C 32 R/W PCI Image2 Translation Address register */ + uint32 P_IMG_CTRL3; /* 0x130 32 R/W PCI Image3 Control register */ + uint32 P_BA3; /* 0x134 32 R/W PCI Image3 Base Address register */ + uint32 P_AM3; /* 0x138 32 R/W PCI Image3 Address Mask register */ + uint32 P_TA3; /* 0x13C 32 R/W PCI Image3 Translation Address register */ + uint32 P_IMG_CTRL4; /* 0x140 32 R/W PCI Image4 Control register */ + uint32 P_BA4; /* 0x144 32 R/W PCI Image4 Base Address register */ + uint32 P_AM4; /* 0x148 32 R/W PCI Image4 Address Mask register */ + uint32 P_TA4; /* 0x14C 32 R/W PCI Image4 Translation Address register */ + uint32 P_IMG_CTRL5; /* 0x150 32 R/W PCI Image5 Control register */ + uint32 P_BA5; /* 0x154 32 R/W PCI Image5 Base Address register */ + uint32 P_AM5; /* 0x158 32 R/W PCI Image5 Address Mask register */ + uint32 P_TA5; /* 0x15C 32 R/W PCI Image5 Translation Address register */ + uint32 P_ERR_CS; /* 0x160 32 R/W PCI Error Control and Status register */ + uint32 P_ERR_ADDR; /* 0x164 32 R PCI Erroneous Address register */ + uint32 P_ERR_DATA; /* 0x168 32 R PCI Erroneous Data register */ + + uint32 PAD[5]; /* 0x16C-0x17F PADDING */ + + uint32 WB_CONF_SPC_BAR; /* 0x180 32 R WISHBONE Configuration Space Base Address */ + uint32 W_IMG_CTRL1; /* 0x184 32 R/W WISHBONE Image1 Control register */ + uint32 W_BA1; /* 0x188 32 R/W WISHBONE Image1 Base Address register */ + uint32 W_AM1; /* 0x18C 32 R/W WISHBONE Image1 Address Mask register */ + uint32 W_TA1; /* 0x190 32 R/W WISHBONE Image1 Translation Address reg */ + uint32 W_IMG_CTRL2; /* 0x194 32 R/W WISHBONE Image2 Control register */ + uint32 W_BA2; /* 0x198 32 R/W WISHBONE Image2 Base Address register */ + uint32 W_AM2; /* 0x19C 32 R/W WISHBONE Image2 Address Mask register */ + uint32 W_TA2; /* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */ + uint32 W_IMG_CTRL3; /* 0x1A4 32 R/W WISHBONE Image3 Control register */ + uint32 W_BA3; /* 0x1A8 32 R/W WISHBONE Image3 Base Address register */ + uint32 W_AM3; /* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */ + uint32 W_TA3; /* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */ + uint32 W_IMG_CTRL4; /* 0x1B4 32 R/W WISHBONE Image4 Control register */ + uint32 W_BA4; /* 0x1B8 32 R/W WISHBONE Image4 Base Address register */ + uint32 W_AM4; /* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */ + uint32 W_TA4; /* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */ + uint32 W_IMG_CTRL5; /* 0x1C4 32 R/W WISHBONE Image5 Control register */ + uint32 W_BA5; /* 0x1C8 32 R/W WISHBONE Image5 Base Address register */ + uint32 W_AM5; /* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */ + uint32 W_TA5; /* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */ + uint32 W_ERR_CS; /* 0x1D4 32 R/W WISHBONE Error Control and Status reg */ + uint32 W_ERR_ADDR; /* 0x1D8 32 R WISHBONE Erroneous Address register */ + uint32 W_ERR_DATA; /* 0x1DC 32 R WISHBONE Erroneous Data register */ + uint32 CNF_ADDR; /* 0x1E0 32 R/W Configuration Cycle register */ + uint32 CNF_DATA; /* 0x1E4 32 R/W Configuration Cycle Generation Data reg */ + + uint32 INT_ACK; /* 0x1E8 32 R Interrupt Acknowledge register */ + uint32 ICR; /* 0x1EC 32 R/W Interrupt Control register */ + uint32 ISR; /* 0x1F0 32 R/W Interrupt Status register */ +} spih_pciregs_t; + +/* + * PCI Core interrupt enable and status bit definitions. + */ + +/* PCI Core ICR Register bit definitions */ +#define PCI_INT_PROP_EN (1 << 0) /* Interrupt Propagation Enable */ +#define PCI_WB_ERR_INT_EN (1 << 1) /* Wishbone Error Interrupt Enable */ +#define PCI_PCI_ERR_INT_EN (1 << 2) /* PCI Error Interrupt Enable */ +#define PCI_PAR_ERR_INT_EN (1 << 3) /* Parity Error Interrupt Enable */ +#define PCI_SYS_ERR_INT_EN (1 << 4) /* System Error Interrupt Enable */ +#define PCI_SOFTWARE_RESET (1U << 31) /* Software reset of the PCI Core. */ + + +/* PCI Core ISR Register bit definitions */ +#define PCI_INT_PROP_ST (1 << 0) /* Interrupt Propagation Status */ +#define PCI_WB_ERR_INT_ST (1 << 1) /* Wishbone Error Interrupt Status */ +#define PCI_PCI_ERR_INT_ST (1 << 2) /* PCI Error Interrupt Status */ +#define PCI_PAR_ERR_INT_ST (1 << 3) /* Parity Error Interrupt Status */ +#define PCI_SYS_ERR_INT_ST (1 << 4) /* System Error Interrupt Status */ + + +/* Registers on the Wishbone bus */ +#define SPIH_CTLR_INTR (1 << 0) /* SPI Host Controller Core Interrupt */ +#define SPIH_DEV_INTR (1 << 1) /* SPI Device Interrupt */ +#define SPIH_WFIFO_INTR (1 << 2) /* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */ + +/* GPIO Bit definitions */ +#define SPIH_CS (1 << 0) /* SPI Chip Select (active low) */ +#define SPIH_SLOT_POWER (1 << 1) /* SD Card Slot Power Enable */ +#define SPIH_CARD_DETECT (1 << 2) /* SD Card Detect */ + +/* SPI Status Register Bit definitions */ +#define SPIH_STATE_MASK 0x30 /* SPI Transfer State Machine state mask */ +#define SPIH_STATE_SHIFT 4 /* SPI Transfer State Machine state shift */ +#define SPIH_WFFULL (1 << 3) /* SPI Write FIFO Full */ +#define SPIH_WFEMPTY (1 << 2) /* SPI Write FIFO Empty */ +#define SPIH_RFFULL (1 << 1) /* SPI Read FIFO Full */ +#define SPIH_RFEMPTY (1 << 0) /* SPI Read FIFO Empty */ + +#define SPIH_EXT_CLK (1U << 31) /* Use External Clock as PLL Clock source. */ + +#define SPIH_PLL_NO_CLK (1 << 1) /* Set to 1 if the PLL's input clock is lost. */ +#define SPIH_PLL_LOCKED (1 << 3) /* Set to 1 when the PLL is locked. */ + +/* Spin bit loop bound check */ +#define SPI_SPIN_BOUND 0xf4240 /* 1 million */ + +#endif /* _BCM_PCI_SPI_H */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmperf.h b/drivers/net/wireless/bcmdhd/include/bcmperf.h new file mode 100644 index 00000000..a503edbd --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmperf.h @@ -0,0 +1,36 @@ +/* + * Performance counters software interface. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmperf.h 277737 2011-08-16 17:54:59Z $ + */ +/* essai */ +#ifndef _BCMPERF_H_ +#define _BCMPERF_H_ +/* get cache hits and misses */ +#define BCMPERF_ENABLE_INSTRCOUNT() +#define BCMPERF_ENABLE_ICACHE_MISS() +#define BCMPERF_ENABLE_ICACHE_HIT() +#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) +#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) +#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) +#endif /* _BCMPERF_H_ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h index 3968e43f..21a58b47 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdbus.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmsdbus.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _sdio_api_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h index 42722149..def3c026 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmsdh.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _bcmsdh_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index bdf6fb99..db8ea596 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmsdh_sdmmc.h 314048 2012-02-09 20:31:56Z $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -82,9 +82,10 @@ struct sdioh_info { uint8 num_funcs; /* Supported funcs on client */ uint32 com_cis_ptr; uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - uint max_dma_len; - uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */ -// SDDMA_DESCRIPTOR SGList[32]; /* Scatter/Gather DMA List */ + +#define SDIOH_SDMMC_MAX_SG_ENTRIES 32 + struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES]; + bool use_rxchain; }; /************************************************************ @@ -119,8 +120,4 @@ typedef struct _BCMSDH_SDMMC_INSTANCE { struct sdio_func *func[SDIOD_MAX_IOFUNCS]; } BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; -#ifdef WL_CFG80211 -extern void wl_cfg80211_set_parent_dev(void *dev); -#endif - #endif /* __BCMSDH_SDMMC_H__ */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h index 20587ec5..1b9d39fe 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdpcm.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmsdpcm.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bcmsdpcm_h_ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdspi.h b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h new file mode 100644 index 00000000..a62bee42 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmsdspi.h @@ -0,0 +1,135 @@ +/* + * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmsdspi.h 277737 2011-08-16 17:54:59Z $ + */ +#ifndef _BCM_SD_SPI_H +#define _BCM_SD_SPI_H + +/* global msglevel for debug messages - bitvals come from sdiovar.h */ + +#define sd_err(x) +#define sd_trace(x) +#define sd_info(x) +#define sd_debug(x) +#define sd_data(x) +#define sd_ctrl(x) + +#define sd_log(x) + +#define SDIOH_ASSERT(exp) \ + do { if (!(exp)) \ + printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ + } while (0) + +#define BLOCK_SIZE_4318 64 +#define BLOCK_SIZE_4328 512 + +/* internal return code */ +#define SUCCESS 0 +#undef ERROR +#define ERROR 1 + +/* private bus modes */ +#define SDIOH_MODE_SPI 0 + +#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ +#define USE_MULTIBLOCK 0x4 + +struct sdioh_info { + uint cfg_bar; /* pci cfg address for bar */ + uint32 caps; /* cached value of capabilities reg */ + uint bar0; /* BAR0 for PCI Device */ + osl_t *osh; /* osh handler */ + void *controller; /* Pointer to SPI Controller's private data struct */ + + uint lockcount; /* nest count of sdspi_lock() calls */ + bool client_intr_enabled; /* interrupt connnected flag */ + bool intr_handler_valid; /* client driver interrupt handler valid */ + sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ + void *intr_handler_arg; /* argument to call interrupt handler */ + bool initialized; /* card initialized */ + uint32 target_dev; /* Target device ID */ + uint32 intmask; /* Current active interrupts */ + void *sdos_info; /* Pointer to per-OS private data */ + + uint32 controller_type; /* Host controller type */ + uint8 version; /* Host Controller Spec Compliance Version */ + uint irq; /* Client irq */ + uint32 intrcount; /* Client interrupts */ + uint32 local_intrcount; /* Controller interrupts */ + bool host_init_done; /* Controller initted */ + bool card_init_done; /* Client SDIO interface initted */ + bool polled_mode; /* polling for command completion */ + + bool sd_use_dma; /* DMA on CMD53 */ + bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ + /* Must be on for sd_multiblock to be effective */ + bool use_client_ints; /* If this is false, make sure to restore */ + bool got_hcint; /* Host Controller interrupt. */ + /* polling hack in wl_linux.c:wl_timer() */ + int adapter_slot; /* Maybe dealing with multiple slots/controllers */ + int sd_mode; /* SD1/SD4/SPI */ + int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ + uint32 data_xfer_count; /* Current register transfer size */ + uint32 cmd53_wr_data; /* Used to pass CMD53 write data */ + uint32 card_response; /* Used to pass back response status byte */ + uint32 card_rsp_data; /* Used to pass back response data word */ + uint16 card_rca; /* Current Address */ + uint8 num_funcs; /* Supported funcs on client */ + uint32 com_cis_ptr; + uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; + void *dma_buf; + ulong dma_phys; + int r_cnt; /* rx count */ + int t_cnt; /* tx_count */ +}; + +/************************************************************ + * Internal interfaces: per-port references into bcmsdspi.c + */ + +/* Global message bits */ +extern uint sd_msglevel; + +/************************************************************** + * Internal interfaces: bcmsdspi.c references to per-port code + */ + +/* Register mapping routines */ +extern uint32 *spi_reg_map(osl_t *osh, uintptr addr, int size); +extern void spi_reg_unmap(osl_t *osh, uintptr addr, int size); + +/* Interrupt (de)registration routines */ +extern int spi_register_irq(sdioh_info_t *sd, uint irq); +extern void spi_free_irq(uint irq, sdioh_info_t *sd); + +/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ +extern void spi_lock(sdioh_info_t *sd); +extern void spi_unlock(sdioh_info_t *sd); + +/* Allocate/init/free per-OS private data */ +extern int spi_osinit(sdioh_info_t *sd); +extern void spi_osfree(sdioh_info_t *sd); + +#endif /* _BCM_SD_SPI_H */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h new file mode 100644 index 00000000..c7382540 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h @@ -0,0 +1,248 @@ +/* + * 'Standard' SDIO HOST CONTROLLER driver + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmsdstd.h 324819 2012-03-30 12:15:19Z $ + */ +#ifndef _BCM_SD_STD_H +#define _BCM_SD_STD_H + +/* global msglevel for debug messages - bitvals come from sdiovar.h */ +#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0) +#define sd_trace(x) +#define sd_info(x) +#define sd_debug(x) +#define sd_data(x) +#define sd_ctrl(x) +#define sd_dma(x) + +#define sd_sync_dma(sd, read, nbytes) +#define sd_init_dma(sd) +#define sd_ack_intr(sd) +#define sd_wakeup(sd); +/* Allocate/init/free per-OS private data */ +extern int sdstd_osinit(sdioh_info_t *sd); +extern void sdstd_osfree(sdioh_info_t *sd); + +#define sd_log(x) + +#define SDIOH_ASSERT(exp) \ + do { if (!(exp)) \ + printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ + } while (0) + +#define BLOCK_SIZE_4318 64 +#define BLOCK_SIZE_4328 512 + +/* internal return code */ +#define SUCCESS 0 +#define ERROR 1 + +/* private bus modes */ +#define SDIOH_MODE_SPI 0 +#define SDIOH_MODE_SD1 1 +#define SDIOH_MODE_SD4 2 + +#define MAX_SLOTS 6 /* For PCI: Only 6 BAR entries => 6 slots */ +#define SDIOH_REG_WINSZ 0x100 /* Number of registers in Standard Host Controller */ + +#define SDIOH_TYPE_ARASAN_HDK 1 +#define SDIOH_TYPE_BCM27XX 2 +#define SDIOH_TYPE_TI_PCIXX21 4 /* TI PCIxx21 Standard Host Controller */ +#define SDIOH_TYPE_RICOH_R5C822 5 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter */ +#define SDIOH_TYPE_JMICRON 6 /* JMicron Standard SDIO Host Controller */ + +/* For linux, allow yielding for dongle */ +#define BCMSDYIELD + +/* Expected card status value for CMD7 */ +#define SDIOH_CMD7_EXP_STATUS 0x00001E00 + +#define RETRIES_LARGE 100000 +#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 + +#define USE_FIFO 0x8 /* Fifo vs non-fifo */ + +#define CLIENT_INTR 0x100 /* Get rid of this! */ + +#define HC_INTR_RETUNING 0x1000 + + +struct sdioh_info { + uint cfg_bar; /* pci cfg address for bar */ + uint32 caps; /* cached value of capabilities reg */ + uint32 curr_caps; /* max current capabilities reg */ + + osl_t *osh; /* osh handler */ + volatile char *mem_space; /* pci device memory va */ + uint lockcount; /* nest count of sdstd_lock() calls */ + bool client_intr_enabled; /* interrupt connnected flag */ + bool intr_handler_valid; /* client driver interrupt handler valid */ + sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ + void *intr_handler_arg; /* argument to call interrupt handler */ + bool initialized; /* card initialized */ + uint target_dev; /* Target device ID */ + uint16 intmask; /* Current active interrupts */ + void *sdos_info; /* Pointer to per-OS private data */ + + uint32 controller_type; /* Host controller type */ + uint8 version; /* Host Controller Spec Compliance Version */ + uint irq; /* Client irq */ + int intrcount; /* Client interrupts */ + int local_intrcount; /* Controller interrupts */ + bool host_init_done; /* Controller initted */ + bool card_init_done; /* Client SDIO interface initted */ + bool polled_mode; /* polling for command completion */ + + bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ + /* Must be on for sd_multiblock to be effective */ + bool use_client_ints; /* If this is false, make sure to restore */ + /* polling hack in wl_linux.c:wl_timer() */ + int adapter_slot; /* Maybe dealing with multiple slots/controllers */ + int sd_mode; /* SD1/SD4/SPI */ + int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ + uint32 data_xfer_count; /* Current transfer */ + uint16 card_rca; /* Current Address */ + int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */ + uint8 num_funcs; /* Supported funcs on client */ + uint32 com_cis_ptr; + uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; + void *dma_buf; /* DMA Buffer virtual address */ + ulong dma_phys; /* DMA Buffer physical address */ + void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */ + ulong adma2_dscr_phys; /* ADMA2 Descriptor Buffer physical address */ + + /* adjustments needed to make the dma align properly */ + void *dma_start_buf; + ulong dma_start_phys; + uint alloced_dma_size; + void *adma2_dscr_start_buf; + ulong adma2_dscr_start_phys; + uint alloced_adma2_dscr_size; + + int r_cnt; /* rx count */ + int t_cnt; /* tx_count */ + bool got_hcint; /* local interrupt flag */ + uint16 last_intrstatus; /* to cache intrstatus */ + int host_UHSISupported; /* whether UHSI is supported for HC. */ + int card_UHSI_voltage_Supported; /* whether UHSI is supported for + * Card in terms of Voltage [1.8 or 3.3]. + */ + int global_UHSI_Supp; /* type of UHSI support in both host and card. + * HOST_SDR_UNSUPP: capabilities not supported/matched + * HOST_SDR_12_25: SDR12 and SDR25 supported + * HOST_SDR_50_104_DDR: one of SDR50/SDR104 or DDR50 supptd + */ + int sd3_dat_state; /* data transfer state used for retuning check */ + int sd3_tun_state; /* tuning state used for retuning check */ + bool sd3_tuning_reqd; /* tuning requirement parameter */ + uint32 caps3; /* cached value of 32 MSbits capabilities reg (SDIO 3.0) */ +}; + +#define DMA_MODE_NONE 0 +#define DMA_MODE_SDMA 1 +#define DMA_MODE_ADMA1 2 +#define DMA_MODE_ADMA2 3 +#define DMA_MODE_ADMA2_64 4 +#define DMA_MODE_AUTO -1 + +#define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE)) + +/* States for Tuning and corr data */ +#define TUNING_IDLE 0 +#define TUNING_START 1 +#define TUNING_START_AFTER_DAT 2 +#define TUNING_ONGOING 3 + +#define DATA_TRANSFER_IDLE 0 +#define DATA_TRANSFER_ONGOING 1 +#define CHECK_TUNING_PRE_DATA 1 +#define CHECK_TUNING_POST_DATA 2 + + +/************************************************************ + * Internal interfaces: per-port references into bcmsdstd.c + */ + +/* Global message bits */ +extern uint sd_msglevel; + +/* OS-independent interrupt handler */ +extern bool check_client_intr(sdioh_info_t *sd); + +/* Core interrupt enable/disable of device interrupts */ +extern void sdstd_devintr_on(sdioh_info_t *sd); +extern void sdstd_devintr_off(sdioh_info_t *sd); + +/* Enable/disable interrupts for local controller events */ +extern void sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err); +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 + */ + +/* Register mapping routines */ +extern uint32 *sdstd_reg_map(osl_t *osh, int32 addr, int size); +extern void sdstd_reg_unmap(osl_t *osh, int32 addr, int size); + +/* Interrupt (de)registration routines */ +extern int sdstd_register_irq(sdioh_info_t *sd, uint irq); +extern void sdstd_free_irq(uint irq, sdioh_info_t *sd); + +/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ +extern void sdstd_lock(sdioh_info_t *sd); +extern void sdstd_unlock(sdioh_info_t *sd); +extern void sdstd_waitlockfree(sdioh_info_t *sd); + +/* OS-specific wait-for-interrupt-or-status */ +extern int sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield, uint16 *bits); + +/* used by bcmsdstd_linux [implemented in sdstd] */ +extern void sdstd_3_enable_retuning_int(sdioh_info_t *sd); +extern void sdstd_3_disable_retuning_int(sdioh_info_t *sd); +extern bool sdstd_3_is_retuning_int_set(sdioh_info_t *sd); +extern void sdstd_3_check_and_do_tuning(sdioh_info_t *sd, int tuning_param); +extern bool sdstd_3_check_and_set_retuning(sdioh_info_t *sd); +extern int sdstd_3_get_tune_state(sdioh_info_t *sd); +extern int sdstd_3_get_data_state(sdioh_info_t *sd); +extern void sdstd_3_set_tune_state(sdioh_info_t *sd, int state); +extern void sdstd_3_set_data_state(sdioh_info_t *sd, int state); +extern uint8 sdstd_3_get_tuning_exp(sdioh_info_t *sd); +extern uint32 sdstd_3_get_uhsi_clkmode(sdioh_info_t *sd); +extern int sdstd_3_clk_tuning(sdioh_info_t *sd, uint32 sd3ClkMode); + +/* used by sdstd [implemented in bcmsdstd_linux/ndis] */ +extern void sdstd_3_start_tuning(sdioh_info_t *sd); +extern void sdstd_3_osinit_tuning(sdioh_info_t *sd); +extern void sdstd_3_osclean_tuning(sdioh_info_t *sd); + +#endif /* _BCM_SD_STD_H */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmspi.h b/drivers/net/wireless/bcmdhd/include/bcmspi.h new file mode 100644 index 00000000..34a02d00 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmspi.h @@ -0,0 +1,40 @@ +/* + * Broadcom SPI Low-Level Hardware Driver API + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmspi.h 277737 2011-08-16 17:54:59Z $ + */ +#ifndef _BCM_SPI_H +#define _BCM_SPI_H + +extern void spi_devintr_off(sdioh_info_t *sd); +extern void spi_devintr_on(sdioh_info_t *sd); +extern bool spi_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor); +extern bool spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode); +extern bool spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr); +extern bool spi_hw_attach(sdioh_info_t *sd); +extern bool spi_hw_detach(sdioh_info_t *sd); +extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen); +extern void spi_spinbits(sdioh_info_t *sd); +extern void spi_waitbits(sdioh_info_t *sd, bool yield); + +#endif /* _BCM_SPI_H */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index 3b9a7754..6849c26d 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmutils.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmutils.h 294991 2011-11-09 00:17:28Z $ */ @@ -221,7 +221,9 @@ extern uint16 pktpool_avail(pktpool_t *pktp); extern int pktpool_avail_register(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 void pktpool_emptycb_disable(pktpool_t *pktp, bool disable); +extern bool pktpool_emptycb_disabled(pktpool_t *pktp); #define POOLPTR(pp) ((pktpool_t *)(pp)) #define pktpool_len(pp) (POOLPTR(pp)->len - 1) @@ -332,7 +334,6 @@ extern void bcm_mdelay(uint ms); #define NVRAM_RECLAIM_CHECK(name) - 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); @@ -537,9 +538,17 @@ extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); & ~((boundary) - 1)) #define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) #define VALID_MASK(mask) !((mask) & ((mask) + 1)) + #ifndef OFFSETOF +#ifdef __ARMCC_VERSION + +#include +#define OFFSETOF(type, member) offsetof(type, member) +#else #define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) #endif +#endif + #ifndef ARRAYSIZE #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) #endif diff --git a/drivers/net/wireless/bcmdhd/include/bcmwifi.h b/drivers/net/wireless/bcmdhd/include/bcmwifi.h index 0e03a6bd..e5207e9c 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmwifi.h +++ b/drivers/net/wireless/bcmdhd/include/bcmwifi.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmwifi.h 275703 2011-08-04 20:20:27Z $ + * $Id: bcmwifi.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index b9289bce..175ff854 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h 275703 2011-08-04 20:20:27Z $ + * $Id: dhdioctl.h 323572 2012-03-26 06:28:14Z $ */ #ifndef _dhdioctl_h_ @@ -87,6 +87,8 @@ enum { #define DHD_BTA_VAL 0x1000 #define DHD_ISCAN_VAL 0x2000 #define DHD_ARPOE_VAL 0x4000 +#define DHD_REORDER_VAL 0x8000 +#define DHD_WL_VAL 0x10000 #ifdef SDTEST /* For pktgen iovar */ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 2bbde333..5df25c16 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -19,7 +19,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: epivers.h.in,v 13.32.4.1 2010-09-17 00:39:18 $ + * $Id: epivers.h.in 277737 2011-08-16 17:54:59Z $ * */ @@ -31,19 +31,19 @@ #define EPI_MINOR_VERSION 90 -#define EPI_RC_NUMBER 125 +#define EPI_RC_NUMBER 195 -#define EPI_INCREMENTAL_NUMBER 120 +#define EPI_INCREMENTAL_NUMBER 75 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 5, 90, 125, 120 +#define EPI_VERSION 5, 90, 195, 75 -#define EPI_VERSION_NUM 0x055a7d78 +#define EPI_VERSION_NUM 0x055ac34b -#define EPI_VERSION_DEV 5.90.125 +#define EPI_VERSION_DEV 5.90.195 -#define EPI_VERSION_STR "5.90.125.120" +#define EPI_VERSION_STR "5.90.195.75" #endif diff --git a/drivers/net/wireless/bcmdhd/include/hndpmu.h b/drivers/net/wireless/bcmdhd/include/hndpmu.h index e9e36802..9bfc8c92 100644 --- a/drivers/net/wireless/bcmdhd/include/hndpmu.h +++ b/drivers/net/wireless/bcmdhd/include/hndpmu.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.h 275703 2011-08-04 20:20:27Z $ + * $Id: hndpmu.h 335486 2012-05-28 09:47:55Z $ */ #ifndef _hndpmu_h_ @@ -31,4 +31,7 @@ extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on); extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); +extern void si_pmu_set_otp_wr_volts(si_t *sih); +extern void si_pmu_set_otp_rd_volts(si_t *sih); + #endif /* _hndpmu_h_ */ diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h new file mode 100644 index 00000000..7d862c4d --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/hndrte_armtrap.h @@ -0,0 +1,88 @@ +/* + * HNDRTE arm trap handling. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: hndrte_armtrap.h 277737 2011-08-16 17:54:59Z $ + */ + +#ifndef _hndrte_armtrap_h +#define _hndrte_armtrap_h + + +/* ARM trap handling */ + +/* Trap types defined by ARM (see arminc.h) */ + +/* Trap locations in lo memory */ +#define TRAP_STRIDE 4 +#define FIRST_TRAP TR_RST +#define LAST_TRAP (TR_FIQ * TRAP_STRIDE) + +#if defined(__ARM_ARCH_4T__) +#define MAX_TRAP_TYPE (TR_FIQ + 1) +#elif defined(__ARM_ARCH_7M__) +#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS) +#endif /* __ARM_ARCH_7M__ */ + +/* The trap structure is defined here as offsets for assembly */ +#define TR_TYPE 0x00 +#define TR_EPC 0x04 +#define TR_CPSR 0x08 +#define TR_SPSR 0x0c +#define TR_REGS 0x10 +#define TR_REG(n) (TR_REGS + (n) * 4) +#define TR_SP TR_REG(13) +#define TR_LR TR_REG(14) +#define TR_PC TR_REG(15) + +#define TRAP_T_SIZE 80 + +#ifndef _LANGUAGE_ASSEMBLY + +#include + +typedef struct _trap_struct { + uint32 type; + uint32 epc; + uint32 cpsr; + uint32 spsr; + uint32 r0; + uint32 r1; + uint32 r2; + uint32 r3; + uint32 r4; + uint32 r5; + uint32 r6; + uint32 r7; + uint32 r8; + uint32 r9; + uint32 r10; + uint32 r11; + uint32 r12; + uint32 r13; + uint32 r14; + uint32 pc; +} trap_t; + +#endif /* !_LANGUAGE_ASSEMBLY */ + +#endif /* _hndrte_armtrap_h */ diff --git a/drivers/net/wireless/bcmdhd/include/hndrte_cons.h b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h new file mode 100644 index 00000000..859ddc89 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/hndrte_cons.h @@ -0,0 +1,68 @@ +/* + * Console support for hndrte. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: hndrte_cons.h 277737 2011-08-16 17:54:59Z $ + */ + +#ifndef _HNDRTE_CONS_H +#define _HNDRTE_CONS_H + +#include + +#define CBUF_LEN (128) + +#define LOG_BUF_LEN 1024 + +typedef struct { + uint32 buf; /* Can't be pointer on (64-bit) hosts */ + uint buf_size; + uint idx; + char *_buf_compat; /* redundant pointer for backward compat. */ +} hndrte_log_t; + +typedef struct { + /* Virtual UART + * When there is no UART (e.g. Quickturn), the host should write a complete + * input line directly into cbuf and then write the length into vcons_in. + * This may also be used when there is a real UART (at risk of conflicting with + * the real UART). vcons_out is currently unused. + */ + volatile uint vcons_in; + volatile uint vcons_out; + + /* Output (logging) buffer + * Console output is written to a ring buffer log_buf at index log_idx. + * The host may read the output when it sees log_idx advance. + * Output will be lost if the output wraps around faster than the host polls. + */ + hndrte_log_t log; + + /* Console input line buffer + * Characters are read one at a time into cbuf until is received, then + * the buffer is processed as a command line. Also used for virtual UART. + */ + uint cbuf_idx; + char cbuf[CBUF_LEN]; +} hndrte_cons_t; + +#endif /* _HNDRTE_CONS_H */ diff --git a/drivers/net/wireless/bcmdhd/include/hndsoc.h b/drivers/net/wireless/bcmdhd/include/hndsoc.h index e5133b67..34f927c6 100644 --- a/drivers/net/wireless/bcmdhd/include/hndsoc.h +++ b/drivers/net/wireless/bcmdhd/include/hndsoc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndsoc.h 275703 2011-08-04 20:20:27Z $ + * $Id: hndsoc.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _HNDSOC_H diff --git a/drivers/net/wireless/bcmdhd/include/htsf.h b/drivers/net/wireless/bcmdhd/include/htsf.h new file mode 100644 index 00000000..d875edb8 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/htsf.h @@ -0,0 +1,74 @@ +/* + * Time stamps for latency measurements + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: htsf.h 277737 2011-08-16 17:54:59Z $ + */ +#ifndef _HTSF_H_ +#define _HTSF_H_ + +#define HTSFMAGIC 0xCDCDABAB /* in network order for tcpdump */ +#define HTSFENDMAGIC 0xEFEFABAB /* to distinguish from RT2 magic */ +#define HTSF_HOSTOFFSET 102 +#define HTSF_DNGLOFFSET HTSF_HOSTOFFSET - 4 +#define HTSF_DNGLOFFSET2 HTSF_HOSTOFFSET + 106 +#define HTSF_MIN_PKTLEN 200 +#define ETHER_TYPE_BRCM_PKTDLYSTATS 0x886d + +typedef enum htsfts_type { + T10, + T20, + T30, + T40, + T50, + T60, + T70, + T80, + T90, + TA0, + TE0 +} htsf_timestamp_t; + +typedef struct { + uint32 magic; + uint32 prio; + uint32 seqnum; + uint32 misc; + uint32 c10; + uint32 t10; + uint32 c20; + uint32 t20; + uint32 t30; + uint32 t40; + uint32 t50; + uint32 t60; + uint32 t70; + uint32 t80; + uint32 t90; + uint32 cA0; + uint32 tA0; + uint32 cE0; + uint32 tE0; + uint32 endmagic; +} htsfts_t; + +#endif /* _HTSF_H_ */ diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h index e54db21e..7f92966d 100644 --- a/drivers/net/wireless/bcmdhd/include/linux_osl.h +++ b/drivers/net/wireless/bcmdhd/include/linux_osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.h 284903 2011-09-20 02:36:51Z $ + * $Id: linux_osl.h 301794 2011-12-08 20:41:35Z $ */ @@ -155,22 +155,6 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); #define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \ mmap_op : bus_op -/* HTC_CSP_START */ -#ifndef errprintf -#define errprintf(fmt, args...) printk(KERN_WARNING "[WLAN][ERR] "fmt, ## args) -#endif - -#ifndef wrnprintf -#define wrnprintf(fmt, args...) printk(KERN_WARNING "[WLAN][WRN] "fmt, ## args) -#endif - -#ifndef printf -#define printf(fmt, args...) printk(KERN_INFO "[WLAN] "fmt, ## args) -#endif - -#define HTC_KERNEL_FEEDBACK(x) errprintf x -/* HTC_CSP_END */ - #define OSL_ERROR(bcmerror) osl_error(bcmerror) extern int osl_error(int bcmerror); @@ -179,7 +163,8 @@ extern int osl_error(int bcmerror); -#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) +#define OSL_SYSUPTIME() ((uint32)jiffies_to_msecs(jiffies)) +#define printf(fmt, args...) printk(fmt , ## args) #include #include @@ -283,10 +268,10 @@ extern int osl_error(int bcmerror); #define PKTLIST_DUMP(osh, buf) #define PKTDBG_TRACE(osh, pkt, bit) #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -#ifdef DHD_USE_STATIC_BUF +#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)) -#endif +#endif #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) #define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) #define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h index 1b5e3ffc..54d88ee9 100644 --- a/drivers/net/wireless/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd/include/linuxver.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linuxver.h 275790 2011-08-04 23:02:47Z $ + * $Id: linuxver.h 312264 2012-02-02 00:49:43Z $ */ @@ -497,7 +497,7 @@ typedef struct { (tsk_ctl)->terminated = FALSE; \ (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ if ((tsk_ctl)->thr_pid > 0) \ - wait_for_completion_timeout(&((tsk_ctl)->completed), 2*HZ); \ + wait_for_completion(&((tsk_ctl)->completed)); \ DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ } @@ -511,17 +511,34 @@ typedef struct { (tsk_ctl)->thr_pid = -1; \ } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define DAEMONIZE(a) daemonize(a); \ + allow_signal(SIGKILL); \ + allow_signal(SIGTERM); +#else /* Linux 2.4 (w/o preemption patch) */ +#define RAISE_RX_SOFTIRQ() \ + cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) +#define DAEMONIZE(a) daemonize(); \ + do { if (a) \ + strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ + } while (0); +#endif /* LINUX_VERSION_CODE */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define BLOCKABLE() (!in_atomic()) +#else +#define BLOCKABLE() (!in_interrupt()) +#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) -/* HTC_CSP_START */ -#define KILL_PROC(pid, sig) \ +#define KILL_PROC(nr, sig) \ { \ - struct task_struct *tsk; \ - tsk = pid_task(find_vpid(pid), PIDTYPE_PID); \ - if (tsk) send_sig(sig, tsk, 1); \ +struct task_struct *tsk; \ +struct pid *pid; \ +pid = find_get_pid((pid_t)nr); \ +tsk = pid_task(pid, PIDTYPE_PID); \ +if (tsk) send_sig(sig, tsk, 1); \ } -/* HTC_CSP_END */ #else #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ KERNEL_VERSION(2, 6, 30)) diff --git a/drivers/net/wireless/bcmdhd/include/miniopt.h b/drivers/net/wireless/bcmdhd/include/miniopt.h new file mode 100644 index 00000000..77eace62 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/miniopt.h @@ -0,0 +1,77 @@ +/* + * Command line options parser. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * $Id: miniopt.h 277737 2011-08-16 17:54:59Z $ + */ + + +#ifndef MINI_OPT_H +#define MINI_OPT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ---- Include Files ---------------------------------------------------- */ +/* ---- Constants and Types ---------------------------------------------- */ + +#define MINIOPT_MAXKEY 128 /* Max options */ +typedef struct miniopt { + + /* These are persistent after miniopt_init() */ + const char* name; /* name for prompt in error strings */ + const char* flags; /* option chars that take no args */ + bool longflags; /* long options may be flags */ + bool opt_end; /* at end of options (passed a "--") */ + + /* These are per-call to miniopt() */ + + int consumed; /* number of argv entries cosumed in + * the most recent call to miniopt() + */ + bool positional; + bool good_int; /* 'val' member is the result of a sucessful + * strtol conversion of the option value + */ + char opt; + char key[MINIOPT_MAXKEY]; + char* valstr; /* positional param, or value for the option, + * or null if the option had + * no accompanying value + */ + uint uval; /* strtol translation of valstr */ + int val; /* strtol translation of valstr */ +} miniopt_t; + +void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags); +int miniopt(miniopt_t *t, char **argv); + + +/* ---- Variable Externs ------------------------------------------------- */ +/* ---- Function Prototypes ---------------------------------------------- */ + + +#ifdef __cplusplus + } +#endif + +#endif /* MINI_OPT_H */ diff --git a/drivers/net/wireless/bcmdhd/include/msgtrace.h b/drivers/net/wireless/bcmdhd/include/msgtrace.h index 315722b6..088f1e84 100644 --- a/drivers/net/wireless/bcmdhd/include/msgtrace.h +++ b/drivers/net/wireless/bcmdhd/include/msgtrace.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: msgtrace.h 275703 2011-08-04 20:20:27Z $ + * $Id: msgtrace.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _MSGTRACE_H diff --git a/drivers/net/wireless/bcmdhd/include/osl.h b/drivers/net/wireless/bcmdhd/include/osl.h index b1d37287..b8cc2569 100644 --- a/drivers/net/wireless/bcmdhd/include/osl.h +++ b/drivers/net/wireless/bcmdhd/include/osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: osl.h 275703 2011-08-04 20:20:27Z $ + * $Id: osl.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_end.h b/drivers/net/wireless/bcmdhd/include/packed_section_end.h index 24072903..71f8b2e1 100644 --- a/drivers/net/wireless/bcmdhd/include/packed_section_end.h +++ b/drivers/net/wireless/bcmdhd/include/packed_section_end.h @@ -34,7 +34,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_end.h 275703 2011-08-04 20:20:27Z $ + * $Id: packed_section_end.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/packed_section_start.h b/drivers/net/wireless/bcmdhd/include/packed_section_start.h index e62169b2..afc2ba32 100644 --- a/drivers/net/wireless/bcmdhd/include/packed_section_start.h +++ b/drivers/net/wireless/bcmdhd/include/packed_section_start.h @@ -34,7 +34,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_start.h 275703 2011-08-04 20:20:27Z $ + * $Id: packed_section_start.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/pcicfg.h b/drivers/net/wireless/bcmdhd/include/pcicfg.h index 1a98fb12..66199431 100644 --- a/drivers/net/wireless/bcmdhd/include/pcicfg.h +++ b/drivers/net/wireless/bcmdhd/include/pcicfg.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: pcicfg.h 275703 2011-08-04 20:20:27Z $ + * $Id: pcicfg.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h index e085475c..fd69aac4 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h,v 9.260.2.6 2010-12-15 21:41:14 $ + * $Id: 802.11.h 304058 2011-12-21 00:39:12Z $ */ @@ -429,10 +429,26 @@ typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { uint8 id; uint8 len; - uint8 cap; + uint8 cap[1]; } BWL_POST_PACKED_STRUCT; typedef struct dot11_extcap_ie dot11_extcap_ie_t; #define DOT11_EXTCAP_LEN 1 +#define DOT11_EXTCAP_LEN_TDLS 5 + +BWL_PRE_PACKED_STRUCT struct dot11_extcap { + uint8 extcap[DOT11_EXTCAP_LEN_TDLS]; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_extcap dot11_extcap_t; + + +#define TDLS_CAP_TDLS 37 +#define TDLS_CAP_PU_BUFFER_STA 28 +#define TDLS_CAP_PEER_PSM 20 +#define TDLS_CAP_CH_SW 30 +#define TDLS_CAP_PROH 38 +#define TDLS_CAP_CH_SW_PROH 39 + +#define TDLS_CAP_MAX_BIT 39 @@ -545,6 +561,9 @@ typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; #define WME_SUBTYPE_IE 0 #define WME_SUBTYPE_PARAM_IE 1 #define WME_SUBTYPE_TSPEC 2 +#define WME_VERSION_LEN 1 +#define WME_PARAMETER_IE_LEN 24 + #define AC_BE 0 @@ -709,6 +728,15 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_MGMT_NOTIFICATION_LEN 4 +BWL_PRE_PACKED_STRUCT struct ti_ie { + uint8 ti_type; + uint32 ti_val; +} BWL_POST_PACKED_STRUCT; +typedef struct ti_ie ti_ie_t; +#define TI_TYPE_REASSOC_DEADLINE 1 +#define TI_TYPE_KEY_LIFETIME 2 + + #define WME_ADDTS_REQUEST 0 #define WME_ADDTS_RESPONSE 1 #define WME_DELTS_REQUEST 2 @@ -724,8 +752,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_OPEN_SYSTEM 0 #define DOT11_SHARED_KEY 1 -#define DOT11_OPEN_SHARED 2 -#define DOT11_FAST_BSS 3 +#define DOT11_FAST_BSS 2 #define DOT11_CHALLENGE_LEN 128 @@ -926,9 +953,18 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_RC_MAX 23 +#define DOT11_RC_TDLS_PEER_UNREACH 25 +#define DOT11_RC_TDLS_DOWN_UNSPECIFIED 26 + #define DOT11_SC_SUCCESS 0 #define DOT11_SC_FAILURE 1 +#define DOT11_SC_TDLS_WAKEUP_SCH_ALT 2 + +#define DOT11_SC_TDLS_WAKEUP_SCH_REJ 3 +#define DOT11_SC_TDLS_SEC_DISABLED 5 +#define DOT11_SC_LIFETIME_REJ 6 +#define DOT11_SC_NOT_SAME_BSS 7 #define DOT11_SC_CAP_MISMATCH 10 #define DOT11_SC_REASSOC_FAIL 11 #define DOT11_SC_ASSOC_FAIL 12 @@ -951,14 +987,14 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_SC_ASSOC_TRY_LATER 30 #define DOT11_SC_ASSOC_MFP_VIOLATION 31 -#define DOT11_SC_DECLINED 37 -#define DOT11_SC_INVALID_PARAMS 38 +#define DOT11_SC_DECLINED 37 +#define DOT11_SC_INVALID_PARAMS 38 #define DOT11_SC_INVALID_PAIRWISE_CIPHER 42 -#define DOT11_SC_INVALID_AKMP 43 +#define DOT11_SC_INVALID_AKMP 43 #define DOT11_SC_INVALID_RSNIE_CAP 45 #define DOT11_SC_INVALID_PMKID 53 -#define DOT11_SC_INVALID_MDID 54 -#define DOT11_SC_INVALID_FTIE 55 +#define DOT11_SC_INVALID_MDID 54 +#define DOT11_SC_INVALID_FTIE 55 #define DOT11_SC_UNEXP_MSG 70 #define DOT11_SC_INVALID_SNONCE 71 @@ -1022,15 +1058,18 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_MNG_EXT_CSA_ID 60 #define DOT11_MNG_HT_ADD 61 #define DOT11_MNG_EXT_CHANNEL_OFFSET 62 -#ifdef BCMWAPI_WAI -#define DOT11_MNG_WAPI_ID 68 /* d11 management WAPI id */ -#endif #define DOT11_MNG_RRM_CAP_ID 70 #define DOT11_MNG_HT_BSS_COEXINFO_ID 72 #define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 #define DOT11_MNG_HT_OBSS_ID 74 +#define DOT11_MNG_CHANNEL_USAGE 97 +#define DOT11_MNG_LINK_IDENTIFIER_ID 101 +#define DOT11_MNG_WAKEUP_SCHEDULE_ID 102 +#define DOT11_MNG_CHANNEL_SWITCH_TIMING_ID 104 +#define DOT11_MNG_PTI_CONTROL_ID 105 +#define DOT11_MNG_PU_BUFFER_STATUS_ID 106 #define DOT11_MNG_EXT_CAP_ID 127 #define DOT11_MNG_WPA_ID 221 #define DOT11_MNG_PROPR_ID 221 @@ -1355,6 +1394,14 @@ typedef struct dot11_ext_cap_ie dot11_ext_cap_ie_t; #define DOT11_OP_CLASS_NONE 255 +BWL_PRE_PACKED_STRUCT struct do11_ap_chrep { + uint8 id; + uint8 len; + uint8 reg; + uint8 chanlist[1]; +} BWL_POST_PACKED_STRUCT; +typedef struct do11_ap_chrep dot11_ap_chrep_t; + #define DOT11_RM_ACTION_RM_REQ 0 #define DOT11_RM_ACTION_RM_REP 1 @@ -1445,7 +1492,7 @@ typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; #define DOT11_RMREQ_BCN_REPINFO_ID 1 #define DOT11_RMREQ_BCN_REPDET_ID 2 #define DOT11_RMREQ_BCN_REQUEST_ID 10 -#define DOT11_RMREQ_BCN_APCHREP_ID 51 +#define DOT11_RMREQ_BCN_APCHREP_ID DOT11_MNG_AP_CHREP_ID #define DOT11_RMREQ_BCN_REPDET_FIXED 0 @@ -1462,6 +1509,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { uint8 reg; uint8 channel; uint8 phytype; + uchar sub_elements[1]; } BWL_POST_PACKED_STRUCT; typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; #define DOT11_RMREP_NBR_LEN 13 @@ -1850,6 +1898,9 @@ typedef struct dot11_obss_ie dot11_obss_ie_t; #define RSN_AKM_PSK 2 #define RSN_AKM_FBT_1X 3 #define RSN_AKM_FBT_PSK 4 +#define RSN_AKM_MFP_1X 5 +#define RSN_AKM_MFP_PSK 6 +#define RSN_AKM_TPK 7 #define DOT11_MAX_DEFAULT_KEYS 4 @@ -1877,11 +1928,6 @@ typedef struct dot11_obss_ie dot11_obss_ie_t; #define WCN_OUI "\x00\x50\xf2" #define WCN_TYPE 4 -#ifdef BCMWAPI_WPI -#define SMS4_KEY_LEN 16 -#define SMS4_WPI_CBC_MAC_LEN 16 -#endif - @@ -1922,13 +1968,64 @@ typedef struct dot11_gtk_ie dot11_gtk_ie_t; #define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" #define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" -#ifdef BCMWAPI_WAI -#define WAPI_IE_MIN_LEN 20 /* WAPI IE min length */ -#define WAPI_VERSION 1 /* WAPI version */ -#define WAPI_VERSION_LEN 2 /* WAPI version length */ -#define WAPI_OUI "\x00\x14\x72" /* WAPI OUI */ -#define WAPI_OUI_LEN DOT11_OUI_LEN /* WAPI OUI length */ -#endif /* BCMWAPI_WAI */ + + +BWL_PRE_PACKED_STRUCT struct link_id_ie { + uint8 id; + uint8 len; + struct ether_addr bssid; + struct ether_addr tdls_init_mac; + 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 + + +BWL_PRE_PACKED_STRUCT struct wakeup_sch_ie { + uint8 id; + uint8 len; + uint32 offset; + uint32 interval; + uint32 awake_win_slots; + uint32 max_wake_win; + uint16 idle_cnt; +} BWL_POST_PACKED_STRUCT; +typedef struct wakeup_sch_ie wakeup_sch_ie_t; +#define TDLS_WAKEUP_SCH_IE_LEN 18 + + +BWL_PRE_PACKED_STRUCT struct channel_switch_timing_ie { + uint8 id; + uint8 len; + uint16 switch_time; + uint16 switch_timeout; +} BWL_POST_PACKED_STRUCT; +typedef struct channel_switch_timing_ie channel_switch_timing_ie_t; +#define TDLS_CHANNEL_SWITCH_TIMING_IE_LEN 4 + + +BWL_PRE_PACKED_STRUCT struct pti_control_ie { + uint8 id; + uint8 len; + uint8 tid; + uint16 seq_control; +} BWL_POST_PACKED_STRUCT; +typedef struct pti_control_ie pti_control_ie_t; +#define TDLS_PTI_CONTROL_IE_LEN 3 + + +BWL_PRE_PACKED_STRUCT struct pu_buffer_status_ie { + uint8 id; + uint8 len; + uint8 status; +} BWL_POST_PACKED_STRUCT; +typedef struct pu_buffer_status_ie pu_buffer_status_ie_t; +#define TDLS_PU_BUFFER_STATUS_IE_LEN 1 +#define TDLS_PU_BUFFER_STATUS_AC_BK 1 +#define TDLS_PU_BUFFER_STATUS_AC_BE 2 +#define TDLS_PU_BUFFER_STATUS_AC_VI 4 +#define TDLS_PU_BUFFER_STATUS_AC_VO 8 + #include diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h index bb4be3e2..cbdd05e6 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11_bta.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: 802.11_bta.h,v 9.2 2008-10-28 23:27:13 $ + * $Id: 802.11_bta.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _802_11_BTA_H_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11e.h b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h new file mode 100644 index 00000000..0e070a47 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11e.h @@ -0,0 +1,131 @@ +/* + * 802.11e protocol header file + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: 802.11e.h 277737 2011-08-16 17:54:59Z $ + */ + +#ifndef _802_11e_H_ +#define _802_11e_H_ + +#ifndef _TYPEDEFS_H_ +#include +#endif + +/* This marks the start of a packed structure section. */ +#include + + +/* WME Traffic Specification (TSPEC) element */ +#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ +#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ + +#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ +#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ +#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ +#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ + +BWL_PRE_PACKED_STRUCT struct tsinfo { + uint8 octets[3]; +} BWL_POST_PACKED_STRUCT; + +typedef struct tsinfo tsinfo_t; + +/* 802.11e TSPEC IE */ +typedef BWL_PRE_PACKED_STRUCT struct tspec { + uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ + uint8 type; /* WME_TYPE */ + uint8 subtype; /* WME_SUBTYPE_TSPEC */ + uint8 version; /* WME_VERSION */ + tsinfo_t tsinfo; /* TS Info bit field */ + uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ + uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ + uint32 min_srv_interval; /* Minimum Service Interval (us) */ + uint32 max_srv_interval; /* Maximum Service Interval (us) */ + uint32 inactivity_interval; /* Inactivity Interval (us) */ + uint32 suspension_interval; /* Suspension Interval (us) */ + uint32 srv_start_time; /* Service Start Time (us) */ + uint32 min_data_rate; /* Minimum Data Rate (bps) */ + uint32 mean_data_rate; /* Mean Data Rate (bps) */ + uint32 peak_data_rate; /* Peak Data Rate (bps) */ + uint32 max_burst_size; /* Maximum Burst Size (bytes) */ + uint32 delay_bound; /* Delay Bound (us) */ + uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ + uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ + uint16 medium_time; /* Medium Time (32 us/s periods) */ +} BWL_POST_PACKED_STRUCT tspec_t; + +#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ + +/* ts_info */ +/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ +#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ +#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ +#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ +#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ +#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ +#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ +#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ +#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ +#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ +#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ +#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ +#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ +/* TS info. user priority mask */ +#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) + +/* Macro to get/set bit(s) field in TSINFO */ +#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) +#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ + TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) +#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) +#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ + TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) + +#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ + ((id) << TS_INFO_TID_SHIFT)) +#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ + ((prio) << TS_INFO_USER_PRIO_SHIFT)) + +/* 802.11e QBSS Load IE */ +#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ +#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ + +#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */ + +/* 802.11e ADDTS status code */ +#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ +#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ +#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ +#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ + +/* 802.11e DELTS status code */ +#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ +#define DOT11E_STATUS_END_TS 37 /* END TS */ +#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ +#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ + + +/* This marks the end of a packed structure section. */ +#include + +#endif /* _802_11e_CAC_H_ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h index ab488eb1..c7e07bd5 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.1d.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.1d.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.1D * - * $Id: 802.1d.h,v 9.3 2007-04-10 21:33:06 $ + * $Id: 802.1d.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h index d46285a5..0f75d3c8 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmeth.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmeth.h,v 9.12 2009-12-29 19:57:18 $ + * $Id: bcmeth.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h index 04b531cc..e8c2387d 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h @@ -23,7 +23,7 @@ * * Dependencies: proto/bcmeth.h * - * $Id: bcmevent.h,v 9.64.2.9 2011-02-01 06:24:21 $ + * $Id: bcmevent.h 288077 2011-10-06 00:08:47Z $ * */ @@ -182,12 +182,9 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event { #define WLC_E_PFN_SCAN_NONE 82 #define WLC_E_PFN_SCAN_ALLGONE 83 #define WLC_E_GTK_PLUMBED 84 -#define WLC_E_RELOAD 85 -#define WLC_E_RSSI_LOW 86 /* Send up rssi low event */ -#define WLC_E_ASSOCREQ_IE 87 /* Send up assoc ie */ -#define WLC_E_LOAD_IND 88 -#define WLC_E_TX_STAT_ERROR 89 -#define WLC_E_LAST 90 +#define WLC_E_ASSOC_REQ_IE 85 +#define WLC_E_ASSOC_RESP_IE 86 +#define WLC_E_LAST 87 @@ -314,7 +311,6 @@ typedef struct wl_event_data_if { #define WLC_E_OVL_DOWNLOAD 0 #define WLC_E_OVL_UPDATE_IND 1 -#define WLC_E_RELOAD_STATUS1 1 /* Internal Firmware Error */ #include diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h index 426f6d58..55eff247 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h @@ -21,7 +21,7 @@ * * Fundamental constants relating to IP Protocol * - * $Id: bcmip.h,v 9.19 2009-11-10 20:08:33 $ + * $Id: bcmip.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h index 8e43ee90..91ab4fe5 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bt_amp_hci.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bt_amp_hci.h,v 9.14.8.2 2010-09-10 18:37:47 $ + * $Id: bt_amp_hci.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _bt_amp_hci_h diff --git a/drivers/net/wireless/bcmdhd/include/proto/eapol.h b/drivers/net/wireless/bcmdhd/include/proto/eapol.h new file mode 100644 index 00000000..92634c12 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/proto/eapol.h @@ -0,0 +1,173 @@ +/* + * 802.1x EAPOL definitions + * + * See + * IEEE Std 802.1X-2001 + * IEEE 802.1X RADIUS Usage Guidelines + * + * Copyright (C) 2002 Broadcom Corporation + * + * $Id: eapol.h 277737 2011-08-16 17:54:59Z $ + */ + +#ifndef _eapol_h_ +#define _eapol_h_ + +#ifndef _TYPEDEFS_H_ +#include +#endif + +/* This marks the start of a packed structure section. */ +#include + +#include + +/* EAPOL for 802.3/Ethernet */ +typedef 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) */ +} eapol_header_t; + +#define EAPOL_HEADER_LEN 18 + +/* 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_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 + 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_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 + +/* 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 + +/* 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 + +/* 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/include/proto/ethernet.h b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h index 5ab94271..20865dc5 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h +++ b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: ethernet.h,v 9.56 2009-10-15 22:54:58 $ + * $Id: ethernet.h 285437 2011-09-21 22:16:56Z $ */ @@ -68,9 +68,8 @@ #define ETHER_TYPE_BRCM 0x886c #define ETHER_TYPE_802_1X 0x888e #define ETHER_TYPE_802_1X_PREAUTH 0x88c7 -#ifdef BCMWAPI_WPI #define ETHER_TYPE_WAI 0x88b4 -#endif +#define ETHER_TYPE_89_0D 0x890d diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h index 4fe0afee..d2bf3f20 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h +++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) * - * $Id: p2p.h,v 9.17.2.4 2010-12-15 21:41:21 $ + * $Id: p2p.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _P2P_H_ diff --git a/drivers/net/wireless/bcmdhd/include/proto/sdspi.h b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h new file mode 100644 index 00000000..7353ff0d --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/proto/sdspi.h @@ -0,0 +1,76 @@ +/* + * SD-SPI Protocol Standard + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: sdspi.h 277737 2011-08-16 17:54:59Z $ + */ + +#ifndef _SD_SPI_H +#define _SD_SPI_H + +#define SPI_START_M BITFIELD_MASK(1) /* Bit [31] - Start Bit */ +#define SPI_START_S 31 +#define SPI_DIR_M BITFIELD_MASK(1) /* Bit [30] - Direction */ +#define SPI_DIR_S 30 +#define SPI_CMD_INDEX_M BITFIELD_MASK(6) /* Bits [29:24] - Command number */ +#define SPI_CMD_INDEX_S 24 +#define SPI_RW_M BITFIELD_MASK(1) /* Bit [23] - Read=0, Write=1 */ +#define SPI_RW_S 23 +#define SPI_FUNC_M BITFIELD_MASK(3) /* Bits [22:20] - Function Number */ +#define SPI_FUNC_S 20 +#define SPI_RAW_M BITFIELD_MASK(1) /* Bit [19] - Read After Wr */ +#define SPI_RAW_S 19 +#define SPI_STUFF_M BITFIELD_MASK(1) /* Bit [18] - Stuff bit */ +#define SPI_STUFF_S 18 +#define SPI_BLKMODE_M BITFIELD_MASK(1) /* Bit [19] - Blockmode 1=blk */ +#define SPI_BLKMODE_S 19 +#define SPI_OPCODE_M BITFIELD_MASK(1) /* Bit [18] - OP Code */ +#define SPI_OPCODE_S 18 +#define SPI_ADDR_M BITFIELD_MASK(17) /* Bits [17:1] - Address */ +#define SPI_ADDR_S 1 +#define SPI_STUFF0_M BITFIELD_MASK(1) /* Bit [0] - Stuff bit */ +#define SPI_STUFF0_S 0 + +#define SPI_RSP_START_M BITFIELD_MASK(1) /* Bit [7] - Start Bit (always 0) */ +#define SPI_RSP_START_S 7 +#define SPI_RSP_PARAM_ERR_M BITFIELD_MASK(1) /* Bit [6] - Parameter Error */ +#define SPI_RSP_PARAM_ERR_S 6 +#define SPI_RSP_RFU5_M BITFIELD_MASK(1) /* Bit [5] - RFU (Always 0) */ +#define SPI_RSP_RFU5_S 5 +#define SPI_RSP_FUNC_ERR_M BITFIELD_MASK(1) /* Bit [4] - Function number error */ +#define SPI_RSP_FUNC_ERR_S 4 +#define SPI_RSP_CRC_ERR_M BITFIELD_MASK(1) /* Bit [3] - COM CRC Error */ +#define SPI_RSP_CRC_ERR_S 3 +#define SPI_RSP_ILL_CMD_M BITFIELD_MASK(1) /* Bit [2] - Illegal Command error */ +#define SPI_RSP_ILL_CMD_S 2 +#define SPI_RSP_RFU1_M BITFIELD_MASK(1) /* Bit [1] - RFU (Always 0) */ +#define SPI_RSP_RFU1_S 1 +#define SPI_RSP_IDLE_M BITFIELD_MASK(1) /* Bit [0] - In idle state */ +#define SPI_RSP_IDLE_S 0 + +/* SD-SPI Protocol Definitions */ +#define SDSPI_COMMAND_LEN 6 /* Number of bytes in an SD command */ +#define SDSPI_START_BLOCK 0xFE /* SD Start Block Token */ +#define SDSPI_IDLE_PAD 0xFF /* SD-SPI idle value for MOSI */ +#define SDSPI_START_BIT_MASK 0x80 + +#endif /* _SD_SPI_H */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/vlan.h b/drivers/net/wireless/bcmdhd/include/proto/vlan.h index 1737e8ce..27f00553 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/vlan.h +++ b/drivers/net/wireless/bcmdhd/include/proto/vlan.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: vlan.h,v 9.7 2009-03-13 01:11:50 $ + * $Id: vlan.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/proto/wpa.h b/drivers/net/wireless/bcmdhd/include/proto/wpa.h index 067d5eae..7361cbf2 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/wpa.h +++ b/drivers/net/wireless/bcmdhd/include/proto/wpa.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wpa.h,v 1.19 2009-07-13 08:29:58 $ + * $Id: wpa.h 285437 2011-09-21 22:16:56Z $ */ @@ -114,30 +114,18 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CIPHER_AES_OCB 3 #define WPA_CIPHER_AES_CCM 4 #define WPA_CIPHER_WEP_104 5 +#define WPA_CIPHER_BIP 6 +#define WPA_CIPHER_TPK 7 -#ifdef BCMWAPI_WAI -#define WAPI_CIPHER_NONE WPA_CIPHER_NONE -#define WAPI_CIPHER_SMS4 11 -#define WAPI_CSE_WPI_SMS4 1 -#endif /* BCMWAPI_WAI */ #define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ (cipher) == WPA_CIPHER_WEP_40 || \ (cipher) == WPA_CIPHER_WEP_104 || \ (cipher) == WPA_CIPHER_TKIP || \ (cipher) == WPA_CIPHER_AES_OCB || \ - (cipher) == WPA_CIPHER_AES_CCM) -#ifdef BCMWAPI_WAI -#define IS_WAPI_CIPHER(cipher) ((cipher) == WAPI_CIPHER_NONE || \ - (cipher) == WAPI_CSE_WPI_SMS4) + (cipher) == WPA_CIPHER_AES_CCM || \ + (cipher) == WPA_CIPHER_TPK) -/* convert WAPI_CSE_WPI_XXX to WAPI_CIPHER_XXX */ -#define WAPI_CSE_WPI_2_CIPHER(cse) ((cse) == WAPI_CSE_WPI_SMS4 ? \ - WAPI_CIPHER_SMS4 : WAPI_CIPHER_NONE) - -#define WAPI_CIPHER_2_CSE_WPI(cipher) ((cipher) == WAPI_CIPHER_SMS4 ? \ - WAPI_CSE_WPI_SMS4 : WAPI_CIPHER_NONE) -#endif /* BCMWAPI_WAI */ #define WPA_TKIP_CM_DETECT 60 @@ -165,23 +153,16 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK +#define WPA_CAP_PEER_KEY_ENABLE (0x1 << 1) + + #define WPA_CAP_LEN RSN_CAP_LEN +#define WPA_PMKID_CNT_LEN 2 #define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH -#ifdef BCMWAPI_WAI -#define WAPI_CAP_PREAUTH RSN_CAP_PREAUTH -/* Other WAI definition */ -#define WAPI_WAI_REQUEST 0x00F1 -#define WAPI_UNICAST_REKEY 0x00F2 -#define WAPI_STA_AGING 0x00F3 -#define WAPI_MUTIL_REKEY 0x00F4 -#define WAPI_STA_STATS 0x00F5 -#define WAPI_USK_REKEY_COUNT 0x4000000 /* 0xA00000 */ -#define WAPI_MSK_REKEY_COUNT 0x4000000 /* 0xA00000 */ -#endif /* BCMWAPI_WAI */ #include #endif diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h index 45e90014..aa4df443 100644 --- a/drivers/net/wireless/bcmdhd/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h @@ -5,7 +5,7 @@ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, * GPIO interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbchipc.h 333924 2012-05-18 04:48:52Z $ * * Copyright (C) 1999-2011, Broadcom Corporation * @@ -1441,17 +1441,17 @@ typedef volatile struct { #define CCTRL4331_EXT_LNA_G (1<<2) #define CCTRL4331_SPROM_GPIO13_15 (1<<3) #define CCTRL4331_EXTPA_EN (1<<4) -#define CCTRL4331_GPIOCLK_ON_SPROMCS <1<<5) +#define CCTRL4331_GPIOCLK_ON_SPROMCS (1<<5) #define CCTRL4331_PCIE_MDIO_ON_SPROMCS (1<<6) #define CCTRL4331_EXTPA_ON_GPIO2_5 (1<<7) #define CCTRL4331_OVR_PIPEAUXCLKEN (1<<8) #define CCTRL4331_OVR_PIPEAUXPWRDOWN (1<<9) -#define CCTRL4331_PCIE_AUXCLKEN <1<<10) -#define CCTRL4331_PCIE_PIPE_PLLDOWN <1<<11) +#define CCTRL4331_PCIE_AUXCLKEN (1<<10) +#define CCTRL4331_PCIE_PIPE_PLLDOWN (1<<11) #define CCTRL4331_EXTPA_EN2 (1<<12) #define CCTRL4331_EXT_LNA_A (1<<13) -#define CCTRL4331_BT_SHD0_ON_GPIO4 <1<<16) -#define CCTRL4331_BT_SHD1_ON_GPIO5 <1<<17) +#define CCTRL4331_BT_SHD0_ON_GPIO4 (1<<16) +#define CCTRL4331_BT_SHD1_ON_GPIO5 (1<<17) #define CCTRL4331_EXTPA_ANA_EN (1<<24) @@ -1659,6 +1659,9 @@ typedef volatile struct { #define CCTRL_4330_JTAG_DISABLE 0x00000008 +#define CCTRL_43239_GPIO_SEL 0x00000002 +#define CCTRL_43239_SDIO_HOST_WAKE 0x00000004 + #define RES4313_BB_PU_RSRC 0 #define RES4313_ILP_REQ_RSRC 1 #define RES4313_XTAL_PU_RSRC 2 diff --git a/drivers/net/wireless/bcmdhd/include/sbconfig.h b/drivers/net/wireless/bcmdhd/include/sbconfig.h index e186c10e..f45351a5 100644 --- a/drivers/net/wireless/bcmdhd/include/sbconfig.h +++ b/drivers/net/wireless/bcmdhd/include/sbconfig.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbconfig.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbconfig.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbhnddma.h b/drivers/net/wireless/bcmdhd/include/sbhnddma.h index 9fd688a2..77c413f7 100644 --- a/drivers/net/wireless/bcmdhd/include/sbhnddma.h +++ b/drivers/net/wireless/bcmdhd/include/sbhnddma.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbhnddma.h 281450 2011-09-02 01:38:29Z $ + * $Id: sbhnddma.h 278779 2011-08-19 22:07:18Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h index e3058b3f..d84f69ab 100644 --- a/drivers/net/wireless/bcmdhd/include/sbpcmcia.h +++ b/drivers/net/wireless/bcmdhd/include/sbpcmcia.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbpcmcia.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbpcmcia.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h index 0bb01cf0..7aaeb73f 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdio.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbsdio.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _SBSDIO_H diff --git a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h index fe274b0f..e5176483 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdpcmdev.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbsdpcmdev.h 282638 2011-09-08 21:18:10Z $ */ #ifndef _sbsdpcmdev_h_ diff --git a/drivers/net/wireless/bcmdhd/include/sbsocram.h b/drivers/net/wireless/bcmdhd/include/sbsocram.h index 0d7fd798..45c4dc20 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsocram.h +++ b/drivers/net/wireless/bcmdhd/include/sbsocram.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsocram.h 275703 2011-08-04 20:20:27Z $ + * $Id: sbsocram.h 277737 2011-08-16 17:54:59Z $ */ diff --git a/drivers/net/wireless/bcmdhd/include/sdio.h b/drivers/net/wireless/bcmdhd/include/sdio.h index 7f69f54a..c8ac7b77 100644 --- a/drivers/net/wireless/bcmdhd/include/sdio.h +++ b/drivers/net/wireless/bcmdhd/include/sdio.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdio.h 275703 2011-08-04 20:20:27Z $ + * $Id: sdio.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _SDIO_H diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h index a62156ad..5f47d6f8 100644 --- a/drivers/net/wireless/bcmdhd/include/sdioh.h +++ b/drivers/net/wireless/bcmdhd/include/sdioh.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdioh.h 275703 2011-08-04 20:20:27Z $ + * $Id: sdioh.h 300017 2011-12-01 20:30:27Z $ */ #ifndef _SDIOH_H diff --git a/drivers/net/wireless/bcmdhd/include/sdiovar.h b/drivers/net/wireless/bcmdhd/include/sdiovar.h index fa113ec9..55a3d349 100644 --- a/drivers/net/wireless/bcmdhd/include/sdiovar.h +++ b/drivers/net/wireless/bcmdhd/include/sdiovar.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdiovar.h 275703 2011-08-04 20:20:27Z $ + * $Id: sdiovar.h 277737 2011-08-16 17:54:59Z $ */ #ifndef _sdiovar_h_ diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h index c7961d5d..4e7aeb71 100644 --- a/drivers/net/wireless/bcmdhd/include/siutils.h +++ b/drivers/net/wireless/bcmdhd/include/siutils.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.h 275703 2011-08-04 20:20:27Z $ + * $Id: siutils.h 335486 2012-05-28 09:47:55Z $ */ @@ -60,6 +60,7 @@ struct si_pub { typedef const struct si_pub si_t; + #define SI_OSH NULL #define BADIDX (SI_MAXCORES + 1) @@ -221,6 +222,8 @@ static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} extern bool si_is_otp_disabled(si_t *sih); extern bool si_is_otp_powered(si_t *sih); extern void si_otp_power(si_t *sih, bool on); +extern void si_set_otp_wr_volts(si_t *sih); +extern void si_set_otp_rd_volts(si_t *sih); extern bool si_is_sprom_available(si_t *sih); @@ -270,4 +273,5 @@ extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint3 char *si_getnvramflvar(si_t *sih, const char *name); + #endif diff --git a/drivers/net/wireless/bcmdhd/include/trxhdr.h b/drivers/net/wireless/bcmdhd/include/trxhdr.h new file mode 100644 index 00000000..b52fb15b --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/trxhdr.h @@ -0,0 +1,53 @@ +/* + * TRX image file header format. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: trxhdr.h 286295 2011-09-27 06:39:43Z $ + */ + +#ifndef _TRX_HDR_H_ +#define _TRX_HDR_H_ + +#include + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_VERSION 1 /* Version 1 */ +#define TRX_MAX_LEN 0x3B0000 /* Max length */ +#define TRX_NO_HEADER 1 /* Do not write TRX header */ +#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ +#define TRX_OVERLAYS 0x4 /* Contains an overlay header after the trx header */ +#define TRX_MAX_OFFSET 3 /* Max number of individual files */ +#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ +#define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ + +struct trx_header { + uint32 magic; /* "HDR0" */ + uint32 len; /* Length of file including header */ + uint32 crc32; /* 32-bit CRC from flag_version to end of file */ + uint32 flag_version; /* 0:15 flags, 16:31 version */ + uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ +}; + +/* Compatibility */ +typedef struct trx_header TRXHDR, *PTRXHDR; + +#endif /* _TRX_HDR_H_ */ diff --git a/drivers/net/wireless/bcmdhd/include/typedefs.h b/drivers/net/wireless/bcmdhd/include/typedefs.h index 63e84c47..d0902fe8 100644 --- a/drivers/net/wireless/bcmdhd/include/typedefs.h +++ b/drivers/net/wireless/bcmdhd/include/typedefs.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: typedefs.h 275703 2011-08-04 20:20:27Z $ + * $Id: typedefs.h 290055 2011-10-15 21:26:26Z $ */ @@ -305,5 +305,8 @@ typedef float64 float_t; #define UNUSED_PARAMETER(x) (void)(x) +#define DISCARD_QUAL(ptr, type) ((type *)(uintptr)(ptr)) + + #include #endif diff --git a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h new file mode 100644 index 00000000..d3710516 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h @@ -0,0 +1,198 @@ +/* +* Copyright (C) 1999-2011, Broadcom Corporation +* +* Unless you and Broadcom execute a separate written software license +* agreement governing use of this software, this software is licensed to you +* under the terms of the GNU General Public License version 2 (the "GPL"), +* available at http://www.broadcom.com/licenses/GPLv2.php, with the +* following added to such license: +* +* As a special exception, the copyright holders of this software give you +* permission to link this software with independent modules, and to copy and +* distribute the resulting executable under terms of your choice, provided that +* you also meet, for each linked independent module, the terms and conditions of +* the license of that module. An independent module is a module which is not +* derived from this software. The special exception does not apply to any +* modifications of the software. +* +* Notwithstanding the above, under no circumstances may you combine this +* software in any way with any other Broadcom software provided under a license +* other than the GPL, without Broadcom's express prior written consent. +* $Id: wlfc_proto.h 277737 2011-08-16 17:54:59Z $ +* +*/ +#ifndef __wlfc_proto_definitions_h__ +#define __wlfc_proto_definitions_h__ + + /* Use TLV to convey WLFC information. + --------------------------------------------------------------------------- + | Type | Len | value | Description + --------------------------------------------------------------------------- + | 1 | 1 | (handle) | MAC OPEN + --------------------------------------------------------------------------- + | 2 | 1 | (handle) | MAC CLOSE + --------------------------------------------------------------------------- + | 3 | 2 | (count, handle, prec_bmp)| Set the credit depth for a MAC dstn + --------------------------------------------------------------------------- + | 4 | 4 | see pkttag comments | TXSTATUS + --------------------------------------------------------------------------- + | 5 | 4 | see pkttag comments | PKKTTAG [host->firmware] + --------------------------------------------------------------------------- + | 6 | 8 | (handle, ifid, MAC) | MAC ADD + --------------------------------------------------------------------------- + | 7 | 8 | (handle, ifid, MAC) | MAC DEL + --------------------------------------------------------------------------- + | 8 | 1 | (rssi) | RSSI - RSSI value for the packet. + --------------------------------------------------------------------------- + | 9 | 1 | (interface ID) | Interface OPEN + --------------------------------------------------------------------------- + | 10 | 1 | (interface ID) | Interface CLOSE + --------------------------------------------------------------------------- + | 11 | 8 | fifo credit returns map | FIFO credits back to the host + | | | | + | | | | -------------------------------------- + | | | | | ac0 | ac1 | ac2 | ac3 | bcmc | atim | + | | | | -------------------------------------- + | | | | + --------------------------------------------------------------------------- + | 12 | 2 | MAC handle, | Host provides a bitmap of pending + | | | AC[0-3] traffic bitmap | unicast traffic for MAC-handle dstn. + | | | | [host->firmware] + --------------------------------------------------------------------------- + | 13 | 3 | (count, handle, prec_bmp)| One time request for packet to a specific + | | | | MAC destination. + --------------------------------------------------------------------------- + | 255 | N/A | N/A | FILLER - This is a special type + | | | | that has no length or value. + | | | | Typically used for padding. + --------------------------------------------------------------------------- + */ + +#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 + +#define WLFC_CTL_TYPE_MACDESC_ADD 6 +#define WLFC_CTL_TYPE_MACDESC_DEL 7 +#define WLFC_CTL_TYPE_RSSI 8 + +#define WLFC_CTL_TYPE_INTERFACE_OPEN 9 +#define WLFC_CTL_TYPE_INTERFACE_CLOSE 10 + +#define WLFC_CTL_TYPE_FIFO_CREDITBACK 11 + +#define WLFC_CTL_TYPE_PENDING_TRAFFIC_BMP 12 +#define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13 + +#define WLFC_CTL_TYPE_FILLER 255 + +#define WLFC_CTL_VALUE_LEN_MACDESC 8 /* handle, interface, MAC */ + +#define WLFC_CTL_VALUE_LEN_MAC 1 /* MAC-handle */ +#define WLFC_CTL_VALUE_LEN_RSSI 1 + +#define WLFC_CTL_VALUE_LEN_INTERFACE 1 +#define WLFC_CTL_VALUE_LEN_PENDING_TRAFFIC_BMP 2 + +#define WLFC_CTL_VALUE_LEN_TXSTATUS 4 +#define WLFC_CTL_VALUE_LEN_PKTTAG 4 + +/* enough space to host all 4 ACs, bc/mc and atim fifo credit */ +#define WLFC_CTL_VALUE_LEN_FIFO_CREDITBACK 6 + +#define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT 3 /* credit, MAC-handle, prec_bitmap */ +#define WLFC_CTL_VALUE_LEN_REQUEST_PACKET 3 /* credit, MAC-handle, prec_bitmap */ + + + +#define WLFC_PKTID_GEN_MASK 0x80000000 +#define WLFC_PKTID_GEN_SHIFT 31 + +#define WLFC_PKTID_GEN(x) (((x) & WLFC_PKTID_GEN_MASK) >> WLFC_PKTID_GEN_SHIFT) +#define WLFC_PKTID_SETGEN(x, gen) (x) = ((x) & ~WLFC_PKTID_GEN_MASK) | \ + (((gen) << WLFC_PKTID_GEN_SHIFT) & WLFC_PKTID_GEN_MASK) + +#define WLFC_PKTFLAG_PKTFROMHOST 0x01 +#define WLFC_PKTFLAG_PKT_REQUESTED 0x02 + +#define WL_TXSTATUS_FLAGS_MASK 0xf /* allow 4 bits only */ +#define WL_TXSTATUS_FLAGS_SHIFT 27 + +#define WL_TXSTATUS_SET_FLAGS(x, flags) ((x) = \ + ((x) & ~(WL_TXSTATUS_FLAGS_MASK << WL_TXSTATUS_FLAGS_SHIFT)) | \ + (((flags) & WL_TXSTATUS_FLAGS_MASK) << WL_TXSTATUS_FLAGS_SHIFT)) +#define WL_TXSTATUS_GET_FLAGS(x) (((x) >> WL_TXSTATUS_FLAGS_SHIFT) & \ + WL_TXSTATUS_FLAGS_MASK) + +#define WL_TXSTATUS_FIFO_MASK 0x7 /* allow 3 bits for FIFO ID */ +#define WL_TXSTATUS_FIFO_SHIFT 24 + +#define WL_TXSTATUS_SET_FIFO(x, flags) ((x) = \ + ((x) & ~(WL_TXSTATUS_FIFO_MASK << WL_TXSTATUS_FIFO_SHIFT)) | \ + (((flags) & WL_TXSTATUS_FIFO_MASK) << WL_TXSTATUS_FIFO_SHIFT)) +#define WL_TXSTATUS_GET_FIFO(x) (((x) >> WL_TXSTATUS_FIFO_SHIFT) & WL_TXSTATUS_FIFO_MASK) + +#define WL_TXSTATUS_PKTID_MASK 0xffffff /* allow 24 bits */ +#define WL_TXSTATUS_SET_PKTID(x, num) ((x) = \ + ((x) & ~WL_TXSTATUS_PKTID_MASK) | (num)) +#define WL_TXSTATUS_GET_PKTID(x) ((x) & WL_TXSTATUS_PKTID_MASK) + +/* 32 STA should be enough??, 6 bits; Must be power of 2 */ +#define WLFC_MAC_DESC_TABLE_SIZE 32 +#define WLFC_MAX_IFNUM 16 +#define WLFC_MAC_DESC_ID_INVALID 0xff + +/* b[7:5] -reuse guard, b[4:0] -value */ +#define WLFC_MAC_DESC_GET_LOOKUP_INDEX(x) ((x) & 0x1f) + +#define WLFC_PKTFLAG_SET_PKTREQUESTED(x) (x) |= \ + (WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT) + +#define WLFC_PKTFLAG_CLR_PKTREQUESTED(x) (x) &= \ + ~(WLFC_PKTFLAG_PKT_REQUESTED << WL_TXSTATUS_FLAGS_SHIFT) + +#define WL_TXSTATUS_GENERATION_MASK 1 +#define WL_TXSTATUS_GENERATION_SHIFT 31 + +#define WLFC_PKTFLAG_SET_GENERATION(x, gen) ((x) = \ + ((x) & ~(WL_TXSTATUS_GENERATION_MASK << WL_TXSTATUS_GENERATION_SHIFT)) | \ + (((gen) & WL_TXSTATUS_GENERATION_MASK) << WL_TXSTATUS_GENERATION_SHIFT)) + +#define WLFC_PKTFLAG_GENERATION(x) (((x) >> WL_TXSTATUS_GENERATION_SHIFT) & \ + WL_TXSTATUS_GENERATION_MASK) + +#define WLFC_MAX_PENDING_DATALEN 120 + +/* host is free to discard the packet */ +#define WLFC_CTL_PKTFLAG_DISCARD 0 +/* D11 suppressed a packet */ +#define WLFC_CTL_PKTFLAG_D11SUPPRESS 1 +/* WL firmware suppressed a packet because MAC is + already in PSMode (short time window) +*/ +#define WLFC_CTL_PKTFLAG_WLSUPPRESS 2 +/* Firmware tossed this packet */ +#define WLFC_CTL_PKTFLAG_TOSSED_BYWLC 3 + +#define WLFC_D11_STATUS_INTERPRET(txs) ((((txs)->status & TX_STATUS_SUPR_MASK) >> \ + TX_STATUS_SUPR_SHIFT)) ? WLFC_CTL_PKTFLAG_D11SUPPRESS : WLFC_CTL_PKTFLAG_DISCARD + +#ifdef PROP_TXSTATUS_DEBUG +#define WLFC_DBGMESG(x) printf x +/* wlfc-breadcrumb */ +#define WLFC_BREADCRUMB(x) do {if ((x) == NULL) \ + {printf("WLFC: %s():%d:caller:%p\n", \ + __FUNCTION__, __LINE__, __builtin_return_address(0));}} while (0) +#define WLFC_PRINTMAC(banner, ea) do {printf("%s MAC: [%02x:%02x:%02x:%02x:%02x:%02x]\n", \ + banner, ea[0], ea[1], ea[2], ea[3], ea[4], ea[5]); } while (0) +#define WLFC_WHEREIS(s) printf("WLFC: at %s():%d, %s\n", __FUNCTION__, __LINE__, (s)) +#else +#define WLFC_DBGMESG(x) +#define WLFC_BREADCRUMB(x) +#define WLFC_PRINTMAC(banner, ea) +#define WLFC_WHEREIS(s) +#endif + +#endif /* __wlfc_proto_definitions_h__ */ diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 61ca38de..e543bfa6 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 287802 2011-10-04 22:44:46Z $ + * $Id: wlioctl.h 331292 2012-05-04 09:04:23Z $ */ @@ -180,6 +180,7 @@ typedef struct wlc_ssid { uchar SSID[32]; } wlc_ssid_t; +#define WL_BSS_FLAGS_FROM_BEACON 0x01 #define WL_BSSTYPE_INFRA 1 #define WL_BSSTYPE_INDEP 0 @@ -377,6 +378,8 @@ typedef struct { #define NRATE_SGI_SHIFT 23 #define NRATE_LDPC_CODING 0x00400000 #define NRATE_LDPC_SHIFT 22 +#define NRATE_BCMC_OVERRIDE 0x00200000 +#define NRATE_BCMC_SHIFT 21 #define NRATE_STF_SISO 0 #define NRATE_STF_CDD 1 @@ -556,10 +559,6 @@ typedef enum sup_auth_status { #define CRYPTO_ALGO_AES_OCB_MSDU 5 #define CRYPTO_ALGO_AES_OCB_MPDU 6 #define CRYPTO_ALGO_NALG 7 - -#ifdef BCMWAPI_WPI -#define CRYPTO_ALGO_SMS4 11 -#endif /* BCMWAPI_WPI */ #define CRYPTO_ALGO_PMK 12 #define WSEC_GEN_MIC_ERROR 0x0001 @@ -612,9 +611,6 @@ typedef struct { #define WSEC_SWFLAG 0x0008 #define SES_OW_ENABLED 0x0040 -#ifdef BCMWAPI_WPI -#define SMS4_ENABLED 0x0100 -#endif /* BCMWAPI_WPI */ #define WPA_AUTH_DISABLED 0x0000 #define WPA_AUTH_NONE 0x0001 @@ -625,12 +621,6 @@ typedef struct { #define WPA2_AUTH_PSK 0x0080 #define BRCM_AUTH_PSK 0x0100 #define BRCM_AUTH_DPT 0x0200 -#ifdef BCMWAPI_WAI -#define WPA_AUTH_WAPI 0x0400 -#define WAPI_AUTH_NONE WPA_AUTH_NONE /* none (IBSS) */ -#define WAPI_AUTH_UNSPECIFIED 0x0400 /* over AS */ -#define WAPI_AUTH_PSK 0x0800 /* Pre-shared key */ -#endif /* BCMWAPI_WAI */ #define WPA2_AUTH_MFP 0x1000 #define WPA2_AUTH_TPK 0x2000 #define WPA2_AUTH_FT 0x4000 @@ -832,8 +822,14 @@ typedef struct wlc_iov_trx_s { #define WLC_IOCTL_MEDLEN 1536 #ifdef WLC_HIGH_ONLY #define WLC_SAMPLECOLLECT_MAXLEN 1024 +#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 1024 +#else +#if defined(LCNCONF) || defined(LCN40CONF) +#define WLC_SAMPLECOLLECT_MAXLEN 8192 #else -#define WLC_SAMPLECOLLECT_MAXLEN 10240 +#define WLC_SAMPLECOLLECT_MAXLEN 10240 +#endif +#define WLC_SAMPLECOLLECT_MAXLEN_LCN40 8192 #endif @@ -865,6 +861,7 @@ typedef struct wlc_iov_trx_s { #define WLC_GET_SSID 25 #define WLC_SET_SSID 26 #define WLC_RESTART 27 +#define WLC_TERMINATED 28 #define WLC_GET_CHANNEL 29 #define WLC_SET_CHANNEL 30 @@ -1217,7 +1214,7 @@ typedef struct { #define WL_AUTH_OPEN_SYSTEM 0 #define WL_AUTH_SHARED_KEY 1 -#define WL_AUTH_OPEN_SHARED 2 +#define WL_AUTH_OPEN_SHARED 2 #define WL_RADIO_SW_DISABLE (1<<0) @@ -1294,12 +1291,6 @@ typedef struct wl_po { #define WL_CHAN_FREQ_RANGE_5GM 2 #define WL_CHAN_FREQ_RANGE_5GH 3 -#define WL_CHAN_FREQ_RANGE_5GLL_VER2 4 -#define WL_CHAN_FREQ_RANGE_5GLH_VER2 5 -#define WL_CHAN_FREQ_RANGE_5GML_VER2 6 -#define WL_CHAN_FREQ_RANGE_5GMH_VER2 7 -#define WL_CHAN_FREQ_RANGE_5GH_VER2 8 - #define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 #define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 #define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 @@ -1427,7 +1418,7 @@ typedef struct wl_aci_args { #define TRIGGER_BADPLCP 0x10 #define TRIGGER_CRSGLITCH 0x20 #define WL_ACI_ARGS_LEGACY_LENGTH 16 -#define WL_SAMPLECOLLECT_T_VERSION 1 +#define WL_SAMPLECOLLECT_T_VERSION 2 typedef struct wl_samplecollect_args { uint8 coll_us; @@ -1435,7 +1426,7 @@ typedef struct wl_samplecollect_args { uint16 version; uint16 length; - uint8 trigger; + int8 trigger; uint16 timeout; uint16 mode; uint32 pre_dur; @@ -1445,6 +1436,11 @@ typedef struct wl_samplecollect_args { bool be_deaf; bool agc; bool filter; + + uint8 trigger_state; + uint8 module_sel1; + uint8 module_sel2; + uint16 nsamps; } wl_samplecollect_args_t; #define WL_SAMPLEDATA_HEADER_TYPE 1 @@ -1465,6 +1461,14 @@ typedef struct wl_sampledata { } wl_sampledata_t; +#define WL_CHAN_VALID_HW (1 << 0) +#define WL_CHAN_VALID_SW (1 << 1) +#define WL_CHAN_BAND_5G (1 << 2) +#define WL_CHAN_RADAR (1 << 3) +#define WL_CHAN_INACTIVE (1 << 4) +#define WL_CHAN_PASSIVE (1 << 5) +#define WL_CHAN_RESTRICTED (1 << 6) + #define WL_ERROR_VAL 0x00000001 #define WL_TRACE_VAL 0x00000002 @@ -1512,6 +1516,7 @@ typedef struct wl_sampledata { #define WL_P2P_VAL 0x00000200 #define WL_TXRX_VAL 0x00000400 #define WL_MCHAN_VAL 0x00000800 +#define WL_TDLS_VAL 0x00001000 #define WL_LED_NUMGPIO 16 @@ -2037,8 +2042,31 @@ typedef struct wl_keep_alive_pkt { +#define MAX_WAKE_PACKET_BYTES 128 + + +typedef struct pm_wake_packet { + uint32 status; + uint32 pattern_id; + uint32 original_packet_size; + uint32 saved_packet_size; + uchar packet[MAX_WAKE_PACKET_BYTES]; +} pm_wake_packet_t; + + + +#define PKT_FILTER_MODE_FORWARD_ON_MATCH 1 + +#define PKT_FILTER_MODE_DISABLE 2 + +#define PKT_FILTER_MODE_PKT_CACHE_ON_MATCH 4 + +#define PKT_FILTER_MODE_PKT_FORWARD_OFF_DEFAULT 8 + + typedef enum wl_pkt_filter_type { - WL_PKT_FILTER_TYPE_PATTERN_MATCH + WL_PKT_FILTER_TYPE_PATTERN_MATCH, + WL_PKT_FILTER_TYPE_MAGIC_PATTERN_MATCH } wl_pkt_filter_type_t; #define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t @@ -2445,20 +2473,6 @@ typedef struct assertlog_results { #define LOGRRC_FIX_LEN 8 #define IOBUF_ALLOWED_NUM_OF_LOGREC(type, len) ((len - LOGRRC_FIX_LEN)/sizeof(type)) -#ifdef BCMWAPI_WAI -#define IV_LEN 16 /* XXX, same as SMS4_WPI_PN_LEN */ -struct wapi_sta_msg_t -{ - uint16 msg_type; - uint16 datalen; - uint8 vap_mac[6]; - uint8 reserve_data1[2]; - uint8 sta_mac[6]; - uint8 reserve_data2[2]; - uint8 gsn[IV_LEN]; - uint8 wie[256]; -}; -#endif /* BCMWAPI_WAI */ @@ -2585,6 +2599,12 @@ typedef struct wl_phycal_state { #define WL_PHYCAL_STAT_FIXED_LEN OFFSETOF(wl_phycal_state_t, phycal_core) #endif +#ifdef WLDSTA +typedef struct wl_dsta_if { + struct ether_addr addr; +} wl_dsta_if_t; +#endif + #ifdef WLP2P typedef struct wl_p2p_disc_st { @@ -2789,43 +2809,4 @@ enum { SPATIAL_MODE_MAX_IDX }; -#ifdef SOFTAP -#define SSID_LEN 33 -#define SEC_LEN 16 -#define KEY_LEN 65 -#define PROFILE_OFFSET 32 -struct ap_profile { - uint8 ssid[SSID_LEN]; - uint8 sec[SEC_LEN]; - uint8 key[KEY_LEN]; - uint32 channel; - uint32 preamble; - uint32 max_scb; - uint32 closednet; - char country_code[WLC_CNTRY_BUF_SZ]; -}; - - -#define MACLIST_MODE_DISABLED 0 -#define MACLIST_MODE_DENY 1 -#define MACLIST_MODE_ALLOW 2 -struct mflist { - uint count; - struct ether_addr ea[16]; -}; -#ifdef CUSTOMER_HW2 -struct mac_list_set { - uint32 mode; - struct mflist white_list; - struct mflist black_list; -}; -#else -struct mac_list_set { - uint32 mode; - struct mflist mac_list; -}; -#endif -#endif - - #endif diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index 26844fbb..4ef7bf7b 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.c 281175 2011-09-01 09:46:46Z $ + * $Id: linux_osl.c,v 1.168.2.7 2011-01-27 17:01:13 $ */ @@ -47,7 +47,7 @@ #define OS_HANDLE_MAGIC 0x1234abcd #define BCM_MEM_FILENAME_LEN 24 -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF #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) @@ -70,7 +70,7 @@ typedef struct bcm_static_pkt { } bcm_static_pkt_t; static bcm_static_pkt_t *bcm_static_skb = 0; -#endif +#endif typedef struct bcm_mem_link { struct bcm_mem_link *prev; @@ -179,12 +179,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); #endif ASSERT(osh); -#ifdef HTC_KlocWork - if(osh == NULL) { - printf("[HTCKW] osl_attach: osh == NULL\n"); - return NULL; - } -#endif + bzero(osh, sizeof(osl_t)); @@ -216,18 +211,14 @@ osl_attach(void *pdev, uint bustype, bool pkttag) break; } -#if defined(DHD_USE_STATIC_BUF) +#if defined(CONFIG_DHD_USE_STATIC_BUF) if (!bcm_static_buf) { if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(osh, 3, STATIC_BUF_SIZE+ STATIC_BUF_TOTAL_LEN))) { - printf("can not alloc static buf!\n"); -#ifdef HTC_KlocWork - return NULL; -#endif + printk("can not alloc static buf!\n"); } else - printf("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); - + printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); sema_init(&bcm_static_buf->static_sem, 1); @@ -240,16 +231,13 @@ osl_attach(void *pdev, uint bustype, bool pkttag) bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); -#ifdef HTC_KlocWork - if(skb_buff_ptr != NULL) -#endif bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * 16); for (i = 0; i < STATIC_PKT_MAX_NUM * 2; i++) bcm_static_skb->pkt_use[i] = 0; sema_init(&bcm_static_skb->osl_pkt_sem, 1); } -#endif +#endif return osh; } @@ -399,7 +387,7 @@ osl_ctfpool_stats(osl_t *osh, void *b) if ((osh == NULL) || (osh->ctfpool == NULL)) return; -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF if (bcm_static_buf) { bcm_static_buf = 0; } @@ -462,7 +450,7 @@ osl_pktfastget(osl_t *osh, uint len) return skb; } -#endif +#endif void * BCMFASTPATH @@ -471,16 +459,14 @@ osl_pktget(osl_t *osh, uint len) struct sk_buff *skb; #ifdef CTFPOOL - skb = osl_pktfastget(osh, len); if ((skb != NULL) || ((skb = osl_alloc_skb(len)) != NULL)) { -#else +#else if ((skb = osl_alloc_skb(len))) { -#endif +#endif skb_put(skb, len); skb->priority = 0; - osh->pub.pktalloced++; } @@ -561,15 +547,15 @@ osl_pktfree(osl_t *osh, void *p, bool send) } } -#ifdef DHD_USE_STATIC_BUF +#ifdef CONFIG_DHD_USE_STATIC_BUF void * osl_pktget_static(osl_t *osh, uint len) { int i; struct sk_buff *skb; - if (len > (PAGE_SIZE * 2)) { - printf("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); + if (!bcm_static_skb || (len > (PAGE_SIZE * 2))) { + printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); return osl_pktget(osh, len); } @@ -583,10 +569,10 @@ osl_pktget_static(osl_t *osh, uint len) if (i != STATIC_PKT_MAX_NUM) { bcm_static_skb->pkt_use[i] = 1; - up(&bcm_static_skb->osl_pkt_sem); skb = bcm_static_skb->skb_4k[i]; skb->tail = skb->data + len; skb->len = len; + up(&bcm_static_skb->osl_pkt_sem); return skb; } } @@ -599,15 +585,15 @@ osl_pktget_static(osl_t *osh, uint len) if (i != STATIC_PKT_MAX_NUM) { bcm_static_skb->pkt_use[i+STATIC_PKT_MAX_NUM] = 1; - up(&bcm_static_skb->osl_pkt_sem); skb = bcm_static_skb->skb_8k[i]; skb->tail = skb->data + len; skb->len = len; + up(&bcm_static_skb->osl_pkt_sem); return skb; } up(&bcm_static_skb->osl_pkt_sem); - printf("%s: all static pkt in use!\n", __FUNCTION__); + printk("%s: all static pkt in use!\n", __FUNCTION__); return osl_pktget(osh, len); } @@ -616,9 +602,14 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) { int i; + if (!bcm_static_skb) { + osl_pktfree(osh, p, send); + return; + } + + down(&bcm_static_skb->osl_pkt_sem); for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (p == bcm_static_skb->skb_4k[i]) { - down(&bcm_static_skb->osl_pkt_sem); bcm_static_skb->pkt_use[i] = 0; up(&bcm_static_skb->osl_pkt_sem); return; @@ -627,14 +618,15 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (p == bcm_static_skb->skb_8k[i]) { - down(&bcm_static_skb->osl_pkt_sem); bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] = 0; up(&bcm_static_skb->osl_pkt_sem); return; } } + up(&bcm_static_skb->osl_pkt_sem); - return osl_pktfree(osh, p, send); + osl_pktfree(osh, p, send); + return; } #endif diff --git a/drivers/net/wireless/bcmdhd/sbutils.c b/drivers/net/wireless/bcmdhd/sbutils.c index 85833670..02d1bc0a 100644 --- a/drivers/net/wireless/bcmdhd/sbutils.c +++ b/drivers/net/wireless/bcmdhd/sbutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbutils.c 275693 2011-08-04 19:59:34Z $ + * $Id: sbutils.c,v 1.687.2.1 2010-11-29 20:21:56 Exp $ */ #include @@ -426,12 +426,7 @@ sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff); } ASSERT(r != NULL); -#ifdef HTC_KlocWork - if(r == NULL) { - SI_ERROR(("[HTCKW] sb_corereg: r is NULL\n")); - return 0; - } -#endif + /* mask and set */ if (mask || val) { if (regoff >= SBCONFIGOFF) { @@ -512,13 +507,9 @@ _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint num uint32 ccrev = sb_corerev(&sii->pub); /* determine numcores - this is the total # cores in the chip */ - if (((ccrev == 4) || (ccrev >= 6))){ -#ifdef HTC_KlocWork - if(cc != NULL) -#endif + if (((ccrev == 4) || (ccrev >= 6))) numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> CID_CC_SHIFT; - } else { /* Older chips */ uint chip = CHIPID(sii->pub.chip); @@ -762,17 +753,9 @@ sb_commit(si_t *sih) chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ASSERT(ccregs != NULL); -#ifdef HTC_KlocWork - if(ccregs != NULL) { - /* do the buffer registers update */ - W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT); - W_REG(sii->osh, &ccregs->broadcastdata, 0x0); - } -#else /* do the buffer registers update */ W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT); W_REG(sii->osh, &ccregs->broadcastdata, 0x0); -#endif } else ASSERT(0); diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c index d0d2fa59..a655ac4e 100644 --- a/drivers/net/wireless/bcmdhd/siutils.c +++ b/drivers/net/wireless/bcmdhd/siutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.c 279502 2011-08-24 20:46:27Z $ + * $Id: siutils.c,v 1.813.2.36 2011-02-10 23:43:55 $ */ #include @@ -44,14 +44,8 @@ #include #include -#if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) -#include -#endif - #include "siutils_priv.h" -int bcm_chip_is_4330b1 = 0; -int bcm_chip_is_4330 = 0; /* local prototypes */ static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, uint bustype, void *sdh, char **vars, uint *varsz); @@ -110,12 +104,7 @@ si_kattach(osl_t *osh) if (!ksii_attached) { void *regs; regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); -#ifdef HTC_KlocWork - if(!osh){ - SI_ERROR(("[HTCKW] si_kattach: osh is NULL\n")); - return NULL; - } -#endif + if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, SI_BUS, NULL, osh != SI_OSH ? &ksii.vars : NULL, @@ -197,12 +186,7 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, cc = si_setcoreidx(&sii->pub, SI_CC_IDX); ASSERT((uintptr)cc); -#ifdef HTC_KlocWork - if(cc == NULL){ - SI_ERROR(("[HTCKW] si_buscore_setup: cc is NULL\n")); - return FALSE; - } -#endif + /* get chipcommon rev */ sii->pub.ccrev = (int)si_corerev(&sii->pub); @@ -229,11 +213,11 @@ si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, /* figure out bus/orignal core idx */ sii->pub.buscoretype = NODEV_CORE_ID; - sii->pub.buscorerev = NOREV; + sii->pub.buscorerev = (uint)NOREV; sii->pub.buscoreidx = BADIDX; pci = pcie = FALSE; - pcirev = pcierev = NOREV; + pcirev = pcierev = (uint)NOREV; pciidx = pcieidx = BADIDX; for (i = 0; i < sii->numcores; i++) { @@ -368,23 +352,11 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), * some way of recognizing them needs to be added here. */ -#ifdef HTC_KlocWork - if (cc == NULL) { - SI_ERROR(("[HTCKW] si_doattach: cc is NULL-1\n")); - return NULL; - } -#endif w = R_REG(osh, &cc->chipid); sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; /* Might as wll fill in chip id rev & pkg */ sih->chip = w & CID_ID_MASK; sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; - if (sih->chip == BCM4330_CHIP_ID) { - printf("sih->chiprev = %d\n", sih->chiprev); - bcm_chip_is_4330 = 1; - if (sih->chiprev == 3) - bcm_chip_is_4330b1 = 1; - } sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | @@ -393,6 +365,19 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, return NULL; } +#if defined(HW_OOB) + if (CHIPID(sih->chip) == BCM43362_CHIP_ID) { + uint32 gpiocontrol, addr; + addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, gpiocontrol); + gpiocontrol = bcmsdh_reg_read(sdh, addr, 4); + gpiocontrol |= 0x2; + bcmsdh_reg_write(sdh, addr, 4, gpiocontrol); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10005, 0xf, NULL); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10006, 0x0, NULL); + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, 0x10007, 0x2, NULL); + } +#endif + if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chiprev == 0) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) { sih->chippkg = BCM4329_182PIN_PKG_ID; @@ -429,8 +414,9 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, } /* assume current core is CC */ - if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43236_CHIP_ID || + if ((sii->pub.ccrev == 0x25) && ((CHIPID(sih->chip) == BCM43234_CHIP_ID || CHIPID(sih->chip) == BCM43235_CHIP_ID || + CHIPID(sih->chip) == BCM43236_CHIP_ID || CHIPID(sih->chip) == BCM43238_CHIP_ID) && (CHIPREV(sii->pub.chiprev) == 0))) { @@ -452,12 +438,6 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, if (sii->pub.ccrev >= 20) { cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); -#ifdef HTC_KlocWork - if (cc == NULL) { - SI_ERROR(("[HTCKW] si_doattach: cc is NULL-2\n")); - return NULL; - } -#endif ASSERT(cc != NULL); W_REG(osh, &cc->gpiopullup, 0); W_REG(osh, &cc->gpiopulldown, 0); @@ -466,10 +446,6 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, -#if !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) - sr_save_restore_init(sih); -#endif /* !defined(BCM_BOOTLOADER) && defined(SAVERESTORE) */ - return (sii); @@ -1148,12 +1124,6 @@ si_slowclk_src(si_info_t *sii) return (SCC_SS_XTAL); } else if (sii->pub.ccrev < 10) { cc = (chipcregs_t *)si_setcoreidx(&sii->pub, sii->curidx); -#ifdef HTC_KlocWork - if (cc == NULL) { - SI_ERROR(("[HTCKW] si_slowclk_src: cc is NULL-1\n")); - return -1; - } -#endif return (R_REG(sii->osh, &cc->slow_clk_ctl) & SCC_SS_MASK); } else /* Insta-clock */ return (SCC_SS_XTAL); @@ -1257,7 +1227,6 @@ si_clkctl_init(si_t *sih) si_setcoreidx(sih, origidx); } - /* change logical "focus" to the gpio core for optimized access */ void * si_gpiosetcore(si_t *sih) @@ -1847,12 +1816,7 @@ si_btcgpiowar(si_t *sih) cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); ASSERT(cc != NULL); -#ifdef HTC_KlocWork - if (cc == NULL) { - SI_ERROR(("[HTCKW] si_btcgpiowar: cc is NULL-1\n")); - return; - } -#endif + W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); /* restore the original index */ @@ -1904,12 +1868,6 @@ si_is_sprom_available(si_t *sih) sii = SI_INFO(sih); origidx = sii->curidx; cc = si_setcoreidx(sih, SI_CC_IDX); -#ifdef HTC_KlocWork - if (cc == NULL) { - SI_ERROR(("[HTCKW] si_is_sprom_available: cc is NULL-1\n")); - return FALSE; - } -#endif sromctrl = R_REG(sii->osh, &cc->sromcontrol); si_setcoreidx(sih, origidx); return (sromctrl & SRC_PRESENT); @@ -1939,9 +1897,11 @@ si_is_sprom_available(si_t *sih) return (sih->chipst & CST4315_SPROM_SEL) != 0; case BCM4319_CHIP_ID: return (sih->chipst & CST4319_SPROM_SEL) != 0; + 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: diff --git a/drivers/net/wireless/bcmdhd/siutils_priv.h b/drivers/net/wireless/bcmdhd/siutils_priv.h index 6595c5f5..d80246e0 100644 --- a/drivers/net/wireless/bcmdhd/siutils_priv.h +++ b/drivers/net/wireless/bcmdhd/siutils_priv.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils_priv.h 275693 2011-08-04 19:59:34Z $ + * $Id: siutils_priv.h,v 1.17.4.3 2010-10-25 16:56:56 Exp $ */ #ifndef _siutils_priv_h_ diff --git a/drivers/net/wireless/bcmdhd/uamp_api.h b/drivers/net/wireless/bcmdhd/uamp_api.h new file mode 100644 index 00000000..c51c68cd --- /dev/null +++ b/drivers/net/wireless/bcmdhd/uamp_api.h @@ -0,0 +1,176 @@ +/* + * Name: uamp_api.h + * + * Description: Universal AMP API + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: uamp_api.h,v 1.2.8.1 2011-02-05 00:16:14 Exp $ + * + */ +#ifndef UAMP_API_H +#define UAMP_API_H + + +#include "typedefs.h" + + +/***************************************************************************** +** Constant and Type Definitions +****************************************************************************** +*/ + +#define BT_API + +/* Types. */ +typedef bool BOOLEAN; +typedef uint8 UINT8; +typedef uint16 UINT16; + + +/* UAMP identifiers */ +#define UAMP_ID_1 1 +#define UAMP_ID_2 2 +typedef UINT8 tUAMP_ID; + +/* UAMP event ids (used by UAMP_CBACK) */ +#define UAMP_EVT_RX_READY 0 /* Data from AMP controller is ready to be read */ +#define UAMP_EVT_CTLR_REMOVED 1 /* Controller removed */ +#define UAMP_EVT_CTLR_READY 2 /* Controller added/ready */ +typedef UINT8 tUAMP_EVT; + + +/* UAMP Channels */ +#define UAMP_CH_HCI_CMD 0 /* HCI Command channel */ +#define UAMP_CH_HCI_EVT 1 /* HCI Event channel */ +#define UAMP_CH_HCI_DATA 2 /* HCI ACL Data channel */ +typedef UINT8 tUAMP_CH; + +/* tUAMP_EVT_DATA: union for event-specific data, used by UAMP_CBACK */ +typedef union { + tUAMP_CH channel; /* UAMP_EVT_RX_READY: channel for which rx occured */ +} tUAMP_EVT_DATA; + + +/***************************************************************************** +** +** Function: UAMP_CBACK +** +** Description: Callback for events. Register callback using UAMP_Init. +** +** Parameters amp_id: AMP device identifier that generated the event +** amp_evt: event id +** p_amp_evt_data: pointer to event-specific data +** +****************************************************************************** +*/ +typedef void (*tUAMP_CBACK)(tUAMP_ID amp_id, tUAMP_EVT amp_evt, tUAMP_EVT_DATA *p_amp_evt_data); + +/***************************************************************************** +** external function declarations +****************************************************************************** +*/ +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************************************************************************** +** +** Function: UAMP_Init +** +** Description: Initialize UAMP driver +** +** Parameters p_cback: Callback function for UAMP event notification +** +****************************************************************************** +*/ +BT_API BOOLEAN UAMP_Init(tUAMP_CBACK p_cback); + + +/***************************************************************************** +** +** Function: UAMP_Open +** +** Description: Open connection to local AMP device. +** +** Parameters app_id: Application specific AMP identifer. This value +** will be included in AMP messages sent to the +** BTU task, to identify source of the message +** +****************************************************************************** +*/ +BT_API BOOLEAN UAMP_Open(tUAMP_ID amp_id); + +/***************************************************************************** +** +** Function: UAMP_Close +** +** Description: Close connection to local AMP device. +** +** Parameters app_id: Application specific AMP identifer. +** +****************************************************************************** +*/ +BT_API void UAMP_Close(tUAMP_ID amp_id); + + +/***************************************************************************** +** +** Function: UAMP_Write +** +** Description: Send buffer to AMP device. Frees GKI buffer when done. +** +** +** Parameters: app_id: AMP identifer. +** p_buf: pointer to buffer to write +** num_bytes: number of bytes to write +** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_CMD +** +** Returns: number of bytes written +** +****************************************************************************** +*/ +BT_API UINT16 UAMP_Write(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 num_bytes, tUAMP_CH channel); + +/***************************************************************************** +** +** Function: UAMP_Read +** +** Description: Read incoming data from AMP. Call after receiving a +** UAMP_EVT_RX_READY callback event. +** +** Parameters: app_id: AMP identifer. +** p_buf: pointer to buffer for holding incoming AMP data +** buf_size: size of p_buf +** channel: UAMP_CH_HCI_ACL, or UAMP_CH_HCI_EVT +** +** Returns: number of bytes read +** +****************************************************************************** +*/ +BT_API UINT16 UAMP_Read(tUAMP_ID amp_id, UINT8 *p_buf, UINT16 buf_size, tUAMP_CH channel); + +#ifdef __cplusplus +} +#endif + +#endif /* UAMP_API_H */ diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 69fc40ca..4fcdcd32 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -53,57 +53,39 @@ * so they can be updated easily in the future (if needed) */ -#define CMD_START "START" -#define CMD_STOP "STOP" +#define CMD_START "START" +#define CMD_STOP "STOP" #define CMD_SCAN_ACTIVE "SCAN-ACTIVE" #define CMD_SCAN_PASSIVE "SCAN-PASSIVE" -#define CMD_RSSI "RSSI" +#define CMD_RSSI "RSSI" #define CMD_LINKSPEED "LINKSPEED" #define CMD_RXFILTER_START "RXFILTER-START" #define CMD_RXFILTER_STOP "RXFILTER-STOP" #define CMD_RXFILTER_ADD "RXFILTER-ADD" #define CMD_RXFILTER_REMOVE "RXFILTER-REMOVE" -#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" +#define CMD_BTCOEXSCAN_START "BTCOEXSCAN-START" #define CMD_BTCOEXSCAN_STOP "BTCOEXSCAN-STOP" #define CMD_BTCOEXMODE "BTCOEXMODE" #define CMD_SETSUSPENDOPT "SETSUSPENDOPT" -#define CMD_MAC_ADDR "MACADDR" +#define CMD_SETSUSPENDMODE "SETSUSPENDMODE" #define CMD_P2P_DEV_ADDR "P2P_DEV_ADDR" #define CMD_SETFWPATH "SETFWPATH" -#define CMD_SETBAND "SETBAND" -#define CMD_GETBAND "GETBAND" -#define CMD_COUNTRY "COUNTRY" +#define CMD_SETBAND "SETBAND" +#define CMD_GETBAND "GETBAND" +#define CMD_COUNTRY "COUNTRY" #define CMD_P2P_SET_NOA "P2P_SET_NOA" +#if !defined WL_ENABLE_P2P_IF #define CMD_P2P_GET_NOA "P2P_GET_NOA" +#endif #define CMD_P2P_SET_PS "P2P_SET_PS" -#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" -#define CMD_P2P_SET_MPC "P2P_MPC_SET" -#define CMD_DEAUTH_STA "DEAUTH_STA" - -#define CMD_DTIM_SKIP_SET "DTIMSKIPSET" -#define CMD_DTIM_SKIP_GET "DTIMSKIPGET" -#define CMD_TXPOWER_SET "TXPOWER" -#define CMD_POWER_MODE_SET "POWERMODE" -#define CMD_POWER_MODE_GET "GETPOWER" -#define CMD_AP_TXPOWER_SET "AP_TXPOWER_SET" -#define CMD_AP_ASSOC_LIST_GET "AP_ASSOC_LIST_GET" -#define CMD_AP_MAC_LIST_SET "AP_MAC_LIST_SET" -#define CMD_SCAN_MINRSSI_SET "SCAN_MINRSSI" -#define CMD_LOW_RSSI_SET "LOW_RSSI_IND_SET" - -/* HTC_CSP_START */ -#define CMD_GETWIFILOCK "GETWIFILOCK" -#define CMD_SETWIFICALL "WIFICALL" -#define CMD_SETPROJECT "SET_PROJECT" -#define CMD_GATEWAYADD "GATEWAY-ADD" -/* HTC_CSP_END */ +#define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" + #ifdef PNO_SUPPORT #define CMD_PNOSSIDCLR_SET "PNOSSIDCLR" #define CMD_PNOSETUP_SET "PNOSETUP " #define CMD_PNOENABLE_SET "PNOFORCE" #define CMD_PNODEBUG_SET "PNODEBUG" -#define CMD_PFN_REMOVE "PFN_REMOVE" #define PNO_TLV_PREFIX 'S' #define PNO_TLV_VERSION '1' @@ -114,9 +96,6 @@ #define PNO_TLV_FREQ_REPEAT 'R' #define PNO_TLV_FREQ_EXPO_MAX 'M' -/* HTC specific command */ -#define CMD_GET_AUTO_CHANNEL "AUTOCHANNELGET" - typedef struct cmd_tlv { char prefix; char version; @@ -131,15 +110,13 @@ typedef struct android_wifi_priv_cmd { int total_len; } android_wifi_priv_cmd; -#define htod32(i) i /** * Extern function declarations (TODO: move them to dhd_linux.h) */ void dhd_customer_gpio_wlan_ctrl(int onoff); uint dhd_dev_reset(struct net_device *dev, uint8 flag); -void dhd_dev_init_ioctl(struct net_device *dev); +int dhd_dev_init_ioctl(struct net_device *dev); #ifdef WL_CFG80211 -int wl_cfg80211_get_mac_addr(struct net_device *net, struct ether_addr *mac_addr); int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr); int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command); #else @@ -151,11 +128,6 @@ int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len) { return 0; } int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) { return 0; } -int wl_cfg80211_set_mpc(struct net_device *net, char* buf, int len) -{ return 0; } -int wl_cfg80211_deauth_sta(struct net_device *net, char* buf, int len) -{ return 0; } - #endif extern int dhd_os_check_if_up(void *dhdp); extern void *bcmsdh_get_drvdata(void); @@ -174,7 +146,6 @@ extern char iface_name[IFNAMSIZ]; * wl_android_wifi_on */ static int g_wifi_on = TRUE; -int block_ap_event = 0; /** * Local (static) function definitions @@ -211,7 +182,7 @@ static int wl_android_get_rssi(struct net_device *net, char *command, int total_ if (error) return -1; if ((ssid.SSID_len == 0) || (ssid.SSID_len > DOT11_MAX_SSID_LEN)) { - DHD_TRACE(("%s: wldev_get_ssid failed\n", __FUNCTION__)); + DHD_ERROR(("%s: wldev_get_ssid failed\n", __FUNCTION__)); } else { memcpy(command, ssid.SSID, ssid.SSID_len); bytes_written = ssid.SSID_len; @@ -234,7 +205,7 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int ret_now = net_os_set_suspend_disable(dev, suspend_flag); if (ret_now != suspend_flag) { - if (!(ret = net_os_set_suspend(dev, ret_now))) + if (!(ret = net_os_set_suspend(dev, ret_now, 1))) DHD_INFO(("%s: Suspend Flag %d -> %d\n", __FUNCTION__, ret_now, suspend_flag)); else @@ -243,424 +214,40 @@ static int wl_android_set_suspendopt(struct net_device *dev, char *command, int return ret; } -static int wl_android_get_band(struct net_device *dev, char *command, int total_len) -{ - uint band; - int bytes_written; - int error; - - error = wldev_get_band(dev, &band); - if (error) - return -1; - bytes_written = snprintf(command, total_len, "Band %d", band); - return bytes_written; -} - -#if 0 -static int wl_android_set_active_scan(struct net_device *dev, char *command, int total_len) -{ - uint as = 0; - int bytes_written; - int error = 0; - - error = wldev_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as), 0); - if (error) - return -1; - bytes_written = snprintf(command, total_len, "OK"); - return bytes_written; -} - -static int wl_android_set_passive_scan(struct net_device *dev, char *command, int total_len) -{ - uint ps = 1; - int bytes_written; - int error = 0; - - error = wldev_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps), 1); - if (error) - return -1; - bytes_written = snprintf(command, total_len, "OK"); - return bytes_written; -} -#endif - -static int wl_android_get_dtim_skip(struct net_device *dev, char *command, int total_len) -{ - char iovbuf[32]; - int bytes_written; - int error = 0; - - memset(iovbuf, 0, sizeof(iovbuf)); - strcpy(iovbuf, "bcn_li_dtim"); - - if ((error = wldev_ioctl(dev, WLC_GET_VAR, &iovbuf, sizeof(iovbuf), 0)) >= 0) { - bytes_written = snprintf(command, total_len, "Dtim_skip %d", iovbuf[0]); - DHD_INFO(("%s: get dtim_skip = %d\n", __FUNCTION__, iovbuf[0])); - return bytes_written; - } - else { - DHD_ERROR(("%s: get dtim_skip failed code %d\n", __FUNCTION__, error)); - return -1; - } -} - -static int wl_android_set_dtim_skip(struct net_device *dev, char *command, int total_len) -{ - char iovbuf[32]; - int bytes_written; - int error = -1; - int bcn_li_dtim; - - bcn_li_dtim = htod32((uint)*(command + strlen(CMD_DTIM_SKIP_SET) + 1) - '0'); - - if ((bcn_li_dtim >= 0) || ((bcn_li_dtim <= 5))) { - memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, 4, iovbuf, sizeof(iovbuf)); - - if ((error = wldev_ioctl(dev, WLC_SET_VAR, &iovbuf, sizeof(iovbuf), 1)) >= 0) { - bytes_written = snprintf(command, total_len, "Dtim_skip %d", iovbuf[0]); - DHD_INFO(("%s: set dtim_skip = %d\n", __FUNCTION__, iovbuf[0])); - return bytes_written; - } - else { - DHD_ERROR(("%s: set dtim_skip failed code %d\n", __FUNCTION__, error)); - } - } - else { - DHD_ERROR(("%s Incorrect dtim_skip setting %d, ignored\n", __FUNCTION__, bcn_li_dtim)); - } - return -1; -} - -static int wl_android_set_txpower(struct net_device *dev, char *command, int total_len) -{ - int bytes_written; - int error = -1; - int txpower = -1; - - txpower = bcm_atoi(command + strlen(CMD_TXPOWER_SET) + 1); - - if ((txpower >= 0) || ((txpower <= 127))) { - txpower |= WL_TXPWR_OVERRIDE; - txpower = htod32(txpower); - if ((error = wldev_iovar_setint(dev, "qtxpower", txpower)) >= 0) { - bytes_written = snprintf(command, total_len, "OK"); - DHD_INFO(("%s: set TXpower 0x%X is OK\n", __FUNCTION__, txpower)); - return bytes_written; - } - else { - DHD_ERROR(("%s: set tx power failed, txpower=%d\n", __FUNCTION__, txpower)); - } - } else { - DHD_ERROR(("%s: Unsupported tx power value, txpower=%d\n", __FUNCTION__, txpower)); - } - - bytes_written = snprintf(command, total_len, "FAIL"); - return -1; -} - -static int wl_android_set_ap_txpower(struct net_device *dev, char *command, int total_len) -{ - int ap_txpower = 0, ap_txpower_orig = 0; - char iovbuf[32]; - - ap_txpower = bcm_atoi(command + strlen(CMD_AP_TXPOWER_SET) + 1); - if (ap_txpower == 0) { - /* get the default txpower */ - memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("qtxpower", (char *)&ap_txpower_orig, 4, iovbuf, sizeof(iovbuf)); - wldev_ioctl(dev, WLC_GET_VAR, &iovbuf, sizeof(iovbuf), 0); - DHD_ERROR(("default tx power is %d\n", ap_txpower_orig)); - ap_txpower_orig |= WL_TXPWR_OVERRIDE; - } - - if (ap_txpower == 99) { - /* set to default value */ - ap_txpower = ap_txpower_orig; - } else { - ap_txpower |= WL_TXPWR_OVERRIDE; - } - - DHD_ERROR(("set tx power to 0x%x\n", ap_txpower)); - bcm_mkiovar("qtxpower", (char *)&ap_txpower, 4, iovbuf, sizeof(iovbuf)); - wldev_ioctl(dev, WLC_SET_VAR, &iovbuf, sizeof(iovbuf), 1); - - return 0; -} - -static int wl_android_set_scan_minrssi(struct net_device *dev, char *command, int total_len) -{ - int minrssi = 0; - int err = 0; - int bytes_written; - - DHD_TRACE(("%s\n", __FUNCTION__)); - - minrssi = bcm_strtoul((char *)(command + strlen("SCAN_MINRSSI") + 1), NULL, 10); - - err = wldev_iovar_setint(dev, "scanresults_minrssi", minrssi); - - if (err) { - DHD_ERROR(("set scan_minrssi fail!\n")); - bytes_written = snprintf(command, total_len, "FAIL"); - } else - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; -} - -#ifdef WLC_E_RSSI_LOW -static int wl_android_low_rssi_set(struct net_device *dev, char *command, int total_len) -{ - int low_rssi_trigger; - int low_rssi_duration; - int trigger_offset; - int duration_offset; - char tran_buf[16] = {0}; - char *pp; - int err = 0; - int bytes_written; - - DHD_TRACE(("%s\n", __FUNCTION__)); - - trigger_offset = strcspn(command, " "); - pp = command + trigger_offset + 1; - duration_offset = strcspn(pp, " "); - - memcpy(tran_buf, pp, duration_offset); - low_rssi_trigger = bcm_strtoul(tran_buf, NULL, 10); - err |= wldev_iovar_setint(dev, "low_rssi_trigger", low_rssi_trigger); - - memset(tran_buf, 0, 16); - pp = command + trigger_offset + duration_offset + 2; - memcpy(tran_buf, pp, strlen(command) - (trigger_offset+duration_offset+1)); - low_rssi_duration = bcm_strtoul(tran_buf, NULL, 10); - err |= wldev_iovar_setint(dev, "low_rssi_duration", low_rssi_duration); - - DHD_TRACE(("set low rssi trigger %d, duration %d\n", low_rssi_trigger, low_rssi_duration)); - - if (err) { - DHD_ERROR(("set low rssi ind fail!\n")); - bytes_written = snprintf(command, total_len, "FAIL"); - } else - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; -} -#endif /* WLC_E_RSSI_LOW */ - - -#if 0 -static int wl_android_process_private_ascii_cmd(struct net_device *dev, char *cmd_str, int total_len) +static int wl_android_set_suspendmode(struct net_device *dev, char *command, int total_len) { int ret = 0; - char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD="); - - WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n", - __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET)); - - if ( (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) || - (strnicmp(sub_cmd, "APSTA_CFG", strlen("APSTA_CFG")) == 0)) { - /* broadcom, add apsta cfg detection above. */ - WL_SOFTAP((" AP_CFG or APSTA_CFG\n")); - - - if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) { - WL_ERROR(("ERROR: SoftAP CFG prams !\n")); - ret = -1; - } else { -#ifndef AP_ONLY - if ( apsta_enable ) - ret = set_apsta_cfg(dev, &my_ap); - else -#endif - ret = set_ap_cfg(dev, &my_ap); - } - - } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) { - - WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n")); - - WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name)); - -#ifndef AP_ONLY - if (ap_net_dev == NULL) { - printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n"); - } else { - - if ((ret = iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str)) < 0) - WL_ERROR(("%s line %d fail to set bss up\n", - __FUNCTION__, __LINE__)); - } -#else - if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0) - WL_ERROR(("%s line %d fail to set bss up\n", - __FUNCTION__, __LINE__)); -#endif - } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) { +#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND) + int suspend_flag; - + suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; - } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) { + if (suspend_flag != 0) + suspend_flag = 1; - WL_SOFTAP((" \n temp DOWN SOFTAP\n")); -#ifndef AP_ONLY - if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { - WL_ERROR(("%s line %d fail to set bss down\n", - __FUNCTION__, __LINE__)); - } + if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) + DHD_INFO(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag)); + else + DHD_ERROR(("%s: failed %d\n",__FUNCTION__,ret)); #endif - } - return ret; - } -#endif - -static struct mac_list_set android_mac_list_buf; -static struct mflist android_ap_black_list; -static int android_ap_macmode = MACLIST_MODE_DISABLED; -int wl_android_black_list_match(char *mac) -{ - int i; - - if (android_ap_macmode) { - for (i = 0; i < android_ap_black_list.count; i++) { - if (!bcmp(mac, &android_ap_black_list.ea[i], - sizeof(struct ether_addr))) { - DHD_ERROR(("mac in black list, ignore it\n")); - break; - } - } - - if (i == android_ap_black_list.count) - return 1; - } - - return 0; -} - -static int -wl_android_get_assoc_sta_list(struct net_device *dev, char *buf, int len) -{ - struct maclist *maclist = (struct maclist *) buf; - int ret,i; - char mac_lst[256]; - char *p_mac_str; - - bcm_mdelay(500); - maclist->count = 10; - ret = wldev_ioctl(dev, WLC_GET_ASSOCLIST, buf, len, 0); - - memset(mac_lst, 0, sizeof(mac_lst)); - p_mac_str = mac_lst; - - /* format: "count|sta 1, sta2, ..." - */ - - p_mac_str += snprintf(p_mac_str, 80, "%d|", maclist->count); - for (i = 0; i < maclist->count; i++) { - struct ether_addr *id = &maclist->ea[i]; - - - p_mac_str += snprintf(p_mac_str, 80, "%02X:%02X:%02X:%02X:%02X:%02X,", - id->octet[0], id->octet[1], id->octet[2], - id->octet[3], id->octet[4], id->octet[5]); - } - - if (ret != 0) { - DHD_ERROR(("get assoc count fail\n")); - maclist->count = 0; - } else - printf("get assoc count %d, len %d\n", maclist->count, len); - - memset(buf, 0x0, len); - memcpy(buf, mac_lst, len); - return len; -} - -static int wl_android_set_ap_mac_list(struct net_device *dev, void *buf) +static int wl_android_get_band(struct net_device *dev, char *command, int total_len) { - struct mac_list_set *mac_list_set = (struct mac_list_set *)buf; - struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list; - struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list; - int mac_mode = mac_list_set->mode; - int length; - int i; - - printf("%s in\n", __func__); - if (white_maclist->count > 16 || black_maclist->count > 16) { - DHD_TRACE(("invalid count white: %d black: %d\n", white_maclist->count, black_maclist->count)); - return 0; - } - - if (buf != (char *)&android_mac_list_buf) { - DHD_TRACE(("Backup the mac list\n")); - memcpy((char *)&android_mac_list_buf, buf, sizeof(struct mac_list_set)); - } else - DHD_TRACE(("recover, don't back up mac list\n")); - - android_ap_macmode = mac_mode; - if (mac_mode == MACLIST_MODE_DISABLED) { - - bzero(&android_ap_black_list, sizeof(struct mflist)); + uint band; + int bytes_written; + int error; - wldev_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode), 1); - } else { - scb_val_t scbval; - char mac_buf[256] = {0}; - struct maclist *assoc_maclist = (struct maclist *) mac_buf; - - mac_mode = MACLIST_MODE_ALLOW; - - wldev_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode), 1); - - length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN; - wldev_ioctl(dev, WLC_SET_MACLIST, white_maclist, length, 1); - printf("White List, length %d:\n", length); - for (i = 0; i < white_maclist->count; i++) - printf("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1], white_maclist->ea[i].octet[2], - white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4], white_maclist->ea[i].octet[5]); - - /* set the black list */ - bcopy(black_maclist, &android_ap_black_list, sizeof(android_ap_black_list)); - - printf("Black List, size %d:\n", sizeof(android_ap_black_list)); - for (i = 0; i < android_ap_black_list.count; i++) - printf("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, android_ap_black_list.ea[i].octet[0], android_ap_black_list.ea[i].octet[1], android_ap_black_list.ea[i].octet[2], - android_ap_black_list.ea[i].octet[3], android_ap_black_list.ea[i].octet[4], android_ap_black_list.ea[i].octet[5]); - - /* deauth if there is associated station not in list */ - assoc_maclist->count = 10; - wldev_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256, 0); - if (assoc_maclist->count) { - int j; - for (i = 0; i < assoc_maclist->count; i++) { - for (j = 0; j < white_maclist->count; j++) { - if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j], ETHER_ADDR_LEN)) { - DHD_TRACE(("match allow, let it be\n")); - break; - } - } - if (j == white_maclist->count) { - DHD_TRACE(("match black, deauth it\n")); - scbval.val = htod32(1); - bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN); - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, - sizeof(scb_val_t), 1); - } - } - } - } - return 0; + error = wldev_get_band(dev, &band); + if (error) + return -1; + bytes_written = snprintf(command, total_len, "Band %d", band); + return bytes_written; } - -#ifdef PNO_SUPPORT +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) { wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; @@ -701,7 +288,6 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t goto exit_proc; } - #ifdef PNO_SET_DEBUG memcpy(command, pno_in_example, sizeof(pno_in_example)); for (i = 0; i < sizeof(pno_in_example); i++) @@ -767,56 +353,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t exit_proc: return res; } - -static int wl_android_del_pfn(struct net_device *dev, char *command, int total_len) -{ - char ssid[33]; - int ssid_offset; - int ssid_size; - int bytes_written; - - DHD_TRACE(("%s\n", __FUNCTION__)); - - memset(ssid, 0, sizeof(ssid)); - - ssid_offset = strcspn(command, " "); - ssid_size = strlen(command) - ssid_offset; - - if (ssid_offset == 0) { - DHD_ERROR(("%s, no ssid specified\n", __FUNCTION__)); - return 0; - } - - strncpy(ssid, command + ssid_offset+1, - MIN(ssid_size, sizeof(ssid))); - - DHD_ERROR(("%s: remove ssid: %s\n", __FUNCTION__, ssid)); - dhd_del_pfn_ssid(ssid, ssid_size); - - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; - -} - -#endif /* PNO_SUPPORT */ - -#ifdef WL_CFG80211 -static int wl_android_get_mac_addr(struct net_device *ndev, char *command, int total_len) -{ - int ret; - int bytes_written = 0; - struct ether_addr id; - - ret = wl_cfg80211_get_mac_addr(ndev, &id); - if (ret) - return 0; - bytes_written = snprintf(command, total_len, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - id.octet[0], id.octet[1], id.octet[2], - id.octet[3], id.octet[4], id.octet[5]); - return bytes_written; -} -#endif +#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) { @@ -830,550 +367,6 @@ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, i return bytes_written; } -/* HTC_CSP_START */ -extern int dhdcdc_wifiLock; -extern char project_type[33]; -static int wl_android_wifi_call = 0; -static struct mutex wl_wificall_mutex; -static struct mutex wl_wifionoff_mutex; -#ifdef BCM4329_LOW_POWER -char wl_abdroid_gatewaybuf[8+1]; /* HTC_KlocWork */ -extern bool hasDLNA; -extern bool allowMulticast; -extern int dhd_set_keepalive(int value); -#endif - -static int active_level = -80; -static int active_period = 20000; /*in mini secs*/ -static int wl_android_active_expired = 0; -struct timer_list *wl_android_active_timer = NULL; -static int screen_off = 0; - -static void wl_android_act_time_expire(void) -{ - struct timer_list **timer; - timer = &wl_android_active_timer; - - if (*timer) { - WL_TRACE(("ac timer expired\n")); - del_timer_sync(*timer); - kfree(*timer); - *timer = NULL; - if (screen_off) - return; - wl_android_active_expired = 1; - } - return; -} - -static void wl_android_deactive(void) -{ - struct timer_list **timer; - timer = &wl_android_active_timer; - - if (*timer) { - WL_TRACE(("previous ac exist\n")); - del_timer_sync(*timer); - kfree(*timer); - *timer = NULL; - } - wl_android_active_expired = 0; - WL_TRACE(("wl_android_deactive\n")); - return; -} - -void wl_android_set_active_level(int level) -{ - active_level = level; - printf("set active level to %d\n", active_level); - return; -} - -void wl_android_set_active_period(int period) -{ - active_period = period; - printf("set active_period to %d\n", active_period); - return; -} - -int wl_android_get_active_level(void) -{ - return active_level; -} - -int wl_android_get_active_period(void) -{ - return active_period; -} - -void wl_android_set_screen_off(int off) -{ - screen_off = off; - printf("wl_android_set_screen_off %d\n", screen_off); - if (screen_off) - wl_android_deactive(); - - return; -} - -static int wl_android_set_power_mode(struct net_device *dev, char *command, int total_len) -{ - -/* HTC_CSP_START */ -#if 1 - int bytes_written; - int pm_val; - - pm_val = bcm_atoi(command + strlen(CMD_POWER_MODE_SET) + 1); - - switch (pm_val) { - /* Android normal usage */ - case 0: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_ANDROID_NORMAL); - dhdhtc_update_wifi_power_mode(screen_off); - /*btcoex_dhcp_timer_stop(dev);*/ - break; - case 1: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_ANDROID_NORMAL); - dhdhtc_update_wifi_power_mode(screen_off); - /*btcoex_dhcp_timer_start(dev);*/ - break; - /* for web loading page */ - case 10: - wl_android_deactive(); - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 11: - if (!screen_off) { - struct timer_list **timer; - timer = &wl_android_active_timer; - - if (*timer) { - mod_timer(*timer, jiffies + active_period * HZ / 1000); - /* printf("mod_timer\n"); */ - } else { - *timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); - if (*timer) { - (*timer)->function = (void *)wl_android_act_time_expire; - init_timer(*timer); - (*timer)->expires = jiffies + active_period * HZ / 1000; - add_timer(*timer); - /* printf("add_timer\n"); */ - } - } - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE); - dhdhtc_update_wifi_power_mode(screen_off); - } - break; - /* for best performance configure */ - case 20: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_USER_CONFIG); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 21: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_USER_CONFIG); - dhdhtc_update_wifi_power_mode(screen_off); - break; - /* for fota download */ - case 30: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 31: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING); - dhdhtc_update_wifi_power_mode(screen_off); - break; - - case 87: /* For wifilock release*/ - printf("wifilock release\n"); - dhdcdc_wifiLock = 0; - dhdhtc_update_wifi_power_mode(screen_off); - dhdhtc_update_dtim_listen_interval(screen_off); - break; - - case 88: /* For wifilock lock*/ - printf("wifilock accquire\n"); - dhdcdc_wifiLock = 1; - dhdhtc_update_wifi_power_mode(screen_off); - dhdhtc_update_dtim_listen_interval(screen_off); - break; - - case 99: /* For debug. power active or not while usb plugin */ - dhdcdc_power_active_while_plugin = !dhdcdc_power_active_while_plugin; - dhdhtc_update_wifi_power_mode(screen_off); - break; -#if 0 - /* for wifi phone */ - case 30: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 31: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - break; -#endif - default: - DHD_ERROR(("%s: not support mode: %d\n", __func__, pm_val)); - break; - - } - -#else - - static int pm = PM_FAST; - int pm_local = PM_OFF; - char powermode_val = 0; - int bytes_written; - - DHD_INFO(("%s: DHCP session cmd:%s\n", __func__, command)); - - strncpy((char *)&powermode_val, command + strlen("POWERMODE") + 1, 1); - - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - - WL_TRACE(("%s: DHCP session starts\n", __func__)); - wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), 0); - wldev_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local), 1); - - net_os_set_packet_filter(dev, 0); - -#ifdef COEX_DHCP -#if 0 - g_bt->ts_dhcp_start = JF2MS; - g_bt->dhcp_done = FALSE; - WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n", - __func__, pm, pm_local)); -#endif -#endif - } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { - - wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1); - - net_os_set_packet_filter(dev, 1); - -#ifdef COEX_DHCP -#if 0 - g_bt->dhcp_done = TRUE; - g_bt->ts_dhcp_ok = JF2MS; - WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n", - __func__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm)); -#endif -#endif - } else { - DHD_ERROR(("%s Unkwown yet power setting, ignored\n", - __func__)); - } -#endif -/* HTC_CSP_END*/ - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; - -} - -static int wl_android_get_power_mode(struct net_device *dev, char *command, int total_len) -{ - int error = 0; - int pm_local = PM_FAST; - int bytes_written; - - error = wldev_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local), 0); - if (!error) { - DHD_TRACE(("%s: Powermode = %d\n", __func__, pm_local)); - if (pm_local == PM_OFF) - pm_local = 1; - else - pm_local = 0; - bytes_written = snprintf(command, total_len, "powermode = %d\n", pm_local); - - } else { - DHD_TRACE(("%s: Error = %d\n", __func__, error)); - bytes_written = snprintf(command, total_len, "FAIL\n"); - } - return bytes_written; -} -static int wl_android_get_wifilock(struct net_device *ndev, char *command, int total_len) -{ - int bytes_written = 0; - - bytes_written = snprintf(command, total_len, "%d", dhdcdc_wifiLock); - printf("dhdcdc_wifiLock: %s\n", command); - - return bytes_written; -} - -int wl_android_is_during_wifi_call(void) -{ - return wl_android_wifi_call; -} - -static int wl_android_set_wificall(struct net_device *ndev, char *command, int total_len) -{ - int bytes_written = 0; - char *s; - int set_val; - - mutex_lock(&wl_wificall_mutex); - s = command + strlen("WIFICALL") + 1; - set_val = bcm_atoi(s); - - - /* 1. change power mode - * 2. change dtim listen interval - */ - - switch (set_val) { - case 0: - if (0 == wl_android_is_during_wifi_call()) { - printf("wifi call is in disconnected state!\n"); - break; - } - - printf("wifi call ends: %d\n", set_val); - wl_android_wifi_call = 0; - - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - - dhdhtc_update_dtim_listen_interval(screen_off); - - break; - case 1: - if (1 == wl_android_is_during_wifi_call()) { - printf("wifi call is already in running state!\n"); - break; - } - - printf("wifi call comes: %d\n", set_val); - wl_android_wifi_call = 1; - - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - - dhdhtc_update_dtim_listen_interval(screen_off); - - break; - default: - DHD_ERROR(("%s: not support mode: %d\n", __func__, set_val)); - break; - - } - - bytes_written = snprintf(command, total_len, "OK"); - mutex_unlock(&wl_wificall_mutex); - - return bytes_written; -} - -int dhd_set_project(char * project, int project_len) -{ - - if ((project_len < 1) || (project_len > 32)) { - printf("Invaild project name length!\n"); - return -1; - } - - strncpy(project_type, project, project_len); - DHD_DEFAULT(("%s: set project type: %s\n", __FUNCTION__, project_type)); - - return 0; -} - -static int wl_android_set_project(struct net_device *ndev, char *command, int total_len) -{ - int bytes_written = 0; - char project[33]; - int project_offset; - int project_size; - - DHD_TRACE(("%s\n", __FUNCTION__)); - memset(project, 0, sizeof(project)); - - project_offset = strcspn(command, " "); - project_size = strlen(command) - project_offset; - - if (project_offset == 0) { - DHD_ERROR(("%s, no project specified\n", __FUNCTION__)); - return 0; - } - - if (project_size > 32) { - DHD_ERROR(("%s: project name is too long: %s\n", __FUNCTION__, - (char *)command + project_offset + 1)); - return 0; - } - - strncpy(project, command + project_offset + 1, MIN(project_size, sizeof(project))); - - DHD_DEFAULT(("%s: set project: %s\n", __FUNCTION__, project)); - dhd_set_project(project, project_size); - - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; -} - -static int wl_android_gateway_add(struct net_device *ndev, char *command, int total_len) -{ - int bytes_written = 0; - - int i; - DHD_TRACE(("Driver GET GATEWAY-ADD CMD!!!\n")); - sscanf(command+12,"%d",&i); - sprintf( wl_abdroid_gatewaybuf, "%02x%02x%02x%02x", - i & 0xff, ((i >> 8) & 0xff), ((i >> 16) & 0xff), ((i >> 24) & 0xff) - ); - - if (strcmp(wl_abdroid_gatewaybuf, "00000000") == 0) - sprintf( wl_abdroid_gatewaybuf, "FFFFFFFF"); - - DHD_TRACE(("gatewaybuf: %s",wl_abdroid_gatewaybuf)); - - if (screen_off && !hasDLNA && !allowMulticast) - dhd_set_keepalive(1); - - bytes_written = snprintf(command, total_len, "OK"); - - return bytes_written; -} - -static int last_auto_channel = 6; -static int wl_android_auto_channel(struct net_device *dev, char *command, int total_len) -{ - int chosen = 0; - char req_buf[64] = {0}; - wl_uint32_list_t *request = (wl_uint32_list_t *)req_buf; - int rescan = 0; - int retry = 0; - int updown = 0; - wlc_ssid_t null_ssid; - int res = 0; - int spec = 0; - int start_channel = 1, end_channel = 14; - int i = 0; - int channel = 0; - int isup = 0; - int bytes_written = 0; - int apsta_var = 0; - - DHD_TRACE(("Enter %s\n", __func__)); - - channel = bcm_atoi(command); - - wldev_ioctl(dev, WLC_GET_UP, &isup, sizeof(isup), 0); - - res = wldev_ioctl(dev, WLC_DOWN, &updown, sizeof(updown), 1); - if (res) { - DHD_ERROR(("%s fail to set updown\n", __func__)); - goto fail; - } - - apsta_var = 0; - res = wldev_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var), 1); - if (res) { - DHD_ERROR(("%s fail to set apsta_var 0\n", __func__)); - goto fail; - } - apsta_var = 1; - res = wldev_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var), 1); - if (res) { - DHD_ERROR(("%s fail to set apsta_var 1\n", __func__)); - goto fail; - } - res = wldev_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var), 0); - - updown = 1; - res = wldev_ioctl(dev, WLC_UP, &updown, sizeof(updown), 1); - if (res < 0) { - DHD_ERROR(("%s fail to set apsta \n", __func__)); - goto fail; - } - -auto_channel_retry: - memset(&null_ssid, 0, sizeof(wlc_ssid_t)); - null_ssid.SSID_len = strlen("test"); - strncpy(null_ssid.SSID, "test", null_ssid.SSID_len); - - res |= wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spec, sizeof(spec), 1); - res |= wldev_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid), 1); - res |= wldev_ioctl(dev, WLC_UP, &updown, sizeof(updown), 1); - - memset(&null_ssid, 0, sizeof(wlc_ssid_t)); - res |= wldev_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid), 1); - - request->count = htod32(0); - if (channel >> 8) { - start_channel = (channel >> 8) & 0xff; - end_channel = channel & 0xff; - request->count = end_channel - start_channel + 1; - DHD_ERROR(("request channel: %d to %d ,request->count =%d\n", start_channel, end_channel, request->count)); - for (i = 0; i < request->count; i++) { - request->element[i] = CH20MHZ_CHSPEC((start_channel + i)); - /* request->element[i] = (start_channel + i); */ - printf("request.element[%d]=0x%x\n", i, request->element[i]); - } - } - - res = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, request, sizeof(req_buf), 1); - if (res < 0) { - DHD_ERROR(("can't start auto channel\n")); - chosen = 6; - goto fail; - } - -get_channel_retry: - bcm_mdelay(500); - - res = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen), 0); - - if (res < 0 || dtoh32(chosen) == 0) { - if (retry++ < 6) - goto get_channel_retry; - else { - DHD_ERROR(("can't get auto channel sel, err = %d, " - "chosen = %d\n", res, chosen)); - chosen = 6; /*Alan: Set default channel when get auto channel failed*/ - } - } - - if ((chosen == start_channel) && (!rescan++)) { - retry = 0; - goto auto_channel_retry; - } - - if (channel == 0) { - channel = chosen; - last_auto_channel = chosen; - } else { - DHD_ERROR(("channel range from %d to %d ,chosen = %d\n", start_channel, end_channel, chosen)); - - if (chosen > end_channel) { - if (chosen <= 6) - chosen = end_channel; - else - chosen = start_channel; - } else if (chosen < start_channel) - chosen = start_channel; - - channel = chosen; - } - - res = wldev_ioctl(dev, WLC_DOWN, &updown, sizeof(updown), 1); - if (res < 0) { - DHD_ERROR(("%s fail to set up err =%d\n", __func__, res)); - goto fail; - } - -fail : - - bytes_written = snprintf(command, total_len, "%d", channel); - return bytes_written; - -} -/* HTC_CSP_END */ - /** * Global function definitions (declared in wl_android.h) */ @@ -1382,22 +375,25 @@ int wl_android_wifi_on(struct net_device *dev) { int ret = 0; - printf("%s in\n", __FUNCTION__); + printk("%s in\n", __FUNCTION__); if (!dev) { DHD_ERROR(("%s: dev is null\n", __FUNCTION__)); return -EINVAL; } - mutex_lock(&wl_wifionoff_mutex); + + dhd_net_if_lock(dev); if (!g_wifi_on) { dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); sdioh_start(NULL, 0); ret = dhd_dev_reset(dev, FALSE); sdioh_start(NULL, 1); - if (!ret) - dhd_dev_init_ioctl(dev); + if (!ret) { + if (dhd_dev_init_ioctl(dev) < 0) + ret = -EFAULT; + } g_wifi_on = 1; } - mutex_unlock(&wl_wifionoff_mutex); + dhd_net_if_unlock(dev); return ret; } @@ -1406,27 +402,21 @@ int wl_android_wifi_off(struct net_device *dev) { int ret = 0; - printf("%s in\n", __FUNCTION__); + printk("%s in\n", __FUNCTION__); if (!dev) { DHD_TRACE(("%s: dev is null\n", __FUNCTION__)); return -EINVAL; } - mutex_lock(&wl_wifionoff_mutex); - /* HTC_WIFI_START */ - if (dhd_APUP) { - printf("apmode off - AP_DOWN\n"); - dhd_APUP = false; - wl_iw_send_priv_event(dev, "AP_DOWN"); - } - /* HTC_WIFI_END */ + + dhd_net_if_lock(dev); if (g_wifi_on) { ret = dhd_dev_reset(dev, TRUE); sdioh_stop(NULL); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); g_wifi_on = 0; } + dhd_net_if_unlock(dev); - mutex_unlock(&wl_wifionoff_mutex); return ret; } @@ -1453,8 +443,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) int bytes_written = 0; android_wifi_priv_cmd priv_cmd; - struct dd_pkt_filter_s *data; - net_os_wake_lock(net); if (!ifr->ifr_data) { @@ -1498,10 +486,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_wifi_off(net); } else if (strnicmp(command, CMD_SCAN_ACTIVE, strlen(CMD_SCAN_ACTIVE)) == 0) { - /* bytes_written = wl_android_set_active_scan(net, command, priv_cmd.total_len); */ + /* TBD: SCAN-ACTIVE */ } else if (strnicmp(command, CMD_SCAN_PASSIVE, strlen(CMD_SCAN_PASSIVE)) == 0) { - /* bytes_written = wl_android_set_passive_scan(net, command, priv_cmd.total_len); */ + /* TBD: SCAN-PASSIVE */ } else if (strnicmp(command, CMD_RSSI, strlen(CMD_RSSI)) == 0) { bytes_written = wl_android_get_rssi(net, command, priv_cmd.total_len); @@ -1510,54 +498,18 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_get_link_speed(net, command, priv_cmd.total_len); } else if (strnicmp(command, CMD_RXFILTER_START, strlen(CMD_RXFILTER_START)) == 0) { - /* HTC_CSP_START*/ - snprintf(command, 3, "OK"); - bytes_written = strlen("OK"); - /*bytes_written = net_os_set_packet_filter(net, 1);*/ - /* HTC_CSP_END*/ + bytes_written = net_os_set_packet_filter(net, 1); } else if (strnicmp(command, CMD_RXFILTER_STOP, strlen(CMD_RXFILTER_STOP)) == 0) { - /* HTC_CSP_START*/ - snprintf(command, 3, "OK"); - bytes_written = strlen("OK"); - /*bytes_written = net_os_set_packet_filter(net, 0);*/ - /* HTC_CSP_END*/ + bytes_written = net_os_set_packet_filter(net, 0); } else if (strnicmp(command, CMD_RXFILTER_ADD, strlen(CMD_RXFILTER_ADD)) == 0) { - /*HTC_CSP_START*/ -#ifdef BCM4329_LOW_POWER - data = (struct dd_pkt_filter_s *)&command[32]; - if ((data->id == ALLOW_IPV6_MULTICAST) || (data->id == ALLOW_IPV4_MULTICAST)) { - WL_TRACE(("RXFILTER-ADD MULTICAST filter\n")); - allowMulticast = false; - } -#endif - wl_android_set_pktfilter(net, (struct dd_pkt_filter_s *)&command[32]); - snprintf(command, 3, "OK"); - bytes_written = strlen("OK"); - /* int filter_num = *(command + strlen(CMD_RXFILTER_ADD) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, TRUE, filter_num); - */ - /* HTC_CSP_END */ } else if (strnicmp(command, CMD_RXFILTER_REMOVE, strlen(CMD_RXFILTER_REMOVE)) == 0) { - /*HTC_CSP_START*/ -#ifdef BCM4329_LOW_POWER - data = (struct dd_pkt_filter_s *)&command[32]; - if ((data->id == ALLOW_IPV6_MULTICAST) || (data->id == ALLOW_IPV4_MULTICAST)) { - WL_TRACE(("RXFILTER-REMOVE MULTICAST filter\n")); - allowMulticast = true; - } -#endif - wl_android_set_pktfilter(net, (struct dd_pkt_filter_s *)&command[32]); - snprintf(command, 3, "OK"); - bytes_written = strlen("OK"); - /* int filter_num = *(command + strlen(CMD_RXFILTER_REMOVE) + 1) - '0'; bytes_written = net_os_rxfilter_add_remove(net, FALSE, filter_num); - */ - /*HTC_CSP_END*/ } else if (strnicmp(command, CMD_BTCOEXSCAN_START, strlen(CMD_BTCOEXSCAN_START)) == 0) { /* TBD: BTCOEXSCAN-START */ @@ -1579,6 +531,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_SETSUSPENDOPT, strlen(CMD_SETSUSPENDOPT)) == 0) { bytes_written = wl_android_set_suspendopt(net, command, priv_cmd.total_len); } + else if (strnicmp(command, CMD_SETSUSPENDMODE, strlen(CMD_SETSUSPENDMODE)) == 0) { + bytes_written = wl_android_set_suspendmode(net, command, priv_cmd.total_len); + } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; bytes_written = wldev_set_band(net, band); @@ -1590,7 +545,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code); } -#ifdef PNO_SUPPORT +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } @@ -1601,11 +556,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; bytes_written = dhd_dev_pno_enable(net, pfn_enabled); } -#endif -#ifdef WL_CFG80211 - else if (strnicmp(command, CMD_MAC_ADDR, strlen(CMD_MAC_ADDR)) == 0) { - bytes_written = wl_android_get_mac_addr(net, command, priv_cmd.total_len); - } #endif else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) { bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len); @@ -1615,9 +565,11 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip, priv_cmd.total_len - skip); } +#if !defined WL_ENABLE_P2P_IF else if (strnicmp(command, CMD_P2P_GET_NOA, strlen(CMD_P2P_GET_NOA)) == 0) { bytes_written = wl_cfg80211_get_p2p_noa(net, command, priv_cmd.total_len); } +#endif else if (strnicmp(command, CMD_P2P_SET_PS, strlen(CMD_P2P_SET_PS)) == 0) { int skip = strlen(CMD_P2P_SET_PS) + 1; bytes_written = wl_cfg80211_set_p2p_ps(net, command + skip, @@ -1629,83 +581,18 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) int skip = strlen(CMD_SET_AP_WPS_P2P_IE) + 3; bytes_written = wl_cfg80211_set_wps_p2p_ie(net, command + skip, priv_cmd.total_len - skip, *(command + skip - 2) - '0'); - } else if (strnicmp(command, CMD_P2P_SET_MPC, strlen(CMD_P2P_SET_MPC)) == 0) { - int skip = strlen(CMD_P2P_SET_MPC) + 1; - bytes_written = wl_cfg80211_set_mpc(net, command + skip, - priv_cmd.total_len - skip); - } else if (strnicmp(command, CMD_DEAUTH_STA, strlen(CMD_DEAUTH_STA)) == 0) { - int skip = strlen(CMD_DEAUTH_STA) + 1; - bytes_written = wl_cfg80211_deauth_sta(net, command + skip, - priv_cmd.total_len - skip); - } -#endif /* WL_CFG80211 */ - else if (strnicmp(command, CMD_DTIM_SKIP_GET, strlen(CMD_DTIM_SKIP_GET)) == 0) { - bytes_written = wl_android_get_dtim_skip(net, command, priv_cmd.total_len); } - else if (strnicmp(command, CMD_DTIM_SKIP_SET, strlen(CMD_DTIM_SKIP_SET)) == 0) { - bytes_written = wl_android_set_dtim_skip(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_TXPOWER_SET, strlen(CMD_TXPOWER_SET)) == 0) { - bytes_written = wl_android_set_txpower(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_POWER_MODE_SET, strlen(CMD_POWER_MODE_SET)) == 0) { - bytes_written = wl_android_set_power_mode(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_POWER_MODE_GET, strlen(CMD_POWER_MODE_GET)) == 0) { - bytes_written = wl_android_get_power_mode(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_AP_TXPOWER_SET, strlen(CMD_AP_TXPOWER_SET)) == 0) { - bytes_written = wl_android_set_ap_txpower(net, command, priv_cmd.total_len); - } else if (strnicmp(command, CMD_AP_ASSOC_LIST_GET, strlen(CMD_AP_ASSOC_LIST_GET)) == 0) { - bytes_written = wl_android_get_assoc_sta_list(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_AP_MAC_LIST_SET, strlen(CMD_AP_MAC_LIST_SET)) == 0) { - bytes_written = wl_android_set_ap_mac_list(net, command + PROFILE_OFFSET); - } - else if (strnicmp(command, CMD_SCAN_MINRSSI_SET, strlen(CMD_SCAN_MINRSSI_SET)) == 0) { - bytes_written = wl_android_set_scan_minrssi(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_LOW_RSSI_SET, strlen(CMD_LOW_RSSI_SET)) == 0) { - bytes_written = wl_android_low_rssi_set(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_PFN_REMOVE, strlen(CMD_PFN_REMOVE)) == 0) { - bytes_written = wl_android_del_pfn(net, command, priv_cmd.total_len); - } -/* HTC_CSP_START */ -#if 0 - else if (strnicmp(command, CMD_GETCSCAN, strlen(CMD_GETCSCAN)) == 0) { - bytes_written = wl_android_get_cscan(net, command, priv_cmd.total_len); - } -#endif - else if (strnicmp(command, CMD_GETWIFILOCK, strlen(CMD_GETWIFILOCK)) == 0) { - bytes_written = wl_android_get_wifilock(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_SETWIFICALL, strlen(CMD_SETWIFICALL)) == 0) { - bytes_written = wl_android_set_wificall(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_SETPROJECT, strlen(CMD_SETPROJECT)) == 0) { - bytes_written = wl_android_set_project(net, command, priv_cmd.total_len); - } - else if (strnicmp(command, CMD_GATEWAYADD, strlen(CMD_GATEWAYADD)) == 0) { - bytes_written = wl_android_gateway_add(net, command, priv_cmd.total_len); - - } else if (strnicmp(command, CMD_GET_AUTO_CHANNEL, strlen(CMD_GET_AUTO_CHANNEL)) == 0) { - int skip = strlen(CMD_GET_AUTO_CHANNEL) + 1; - block_ap_event = 1; - bytes_written = wl_android_auto_channel(net, command + skip, - priv_cmd.total_len - skip) + skip; - block_ap_event = 0; - } -/* HTC_CSP_END */ +#endif /* WL_CFG80211 */ else { - DHD_ERROR(("%s: Unknown PRIVATE command %s - ignored\n", __FUNCTION__, command)); + DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); bytes_written = strlen("OK"); } + if (bytes_written >= 0) { - if (bytes_written == 0) + if ((bytes_written == 0) && (priv_cmd.total_len > 0)) command[0] = '\0'; - if (bytes_written > priv_cmd.total_len) { + if (bytes_written >= priv_cmd.total_len) { DHD_ERROR(("%s: bytes_written = %d\n", __FUNCTION__, bytes_written)); bytes_written = priv_cmd.total_len; } else { @@ -1716,7 +603,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) DHD_ERROR(("%s: failed to copy data to user buffer\n", __FUNCTION__)); ret = -EFAULT; } - } else { + } + else { ret = bytes_written; } @@ -1733,7 +621,7 @@ int wl_android_init(void) { int ret = 0; - dhd_msg_level = DHD_ERROR_VAL; + dhd_msg_level |= DHD_ERROR_VAL; #ifdef ENABLE_INSMOD_NO_FW_LOAD dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ @@ -1743,11 +631,6 @@ int wl_android_init(void) bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ); } #endif /* CUSTOMER_HW2 */ - -/*HTC_CSP_START*/ - mutex_init(&wl_wificall_mutex); - mutex_init(&wl_wifionoff_mutex); -/*HTC_CSP_END*/ return ret; } @@ -1816,13 +699,14 @@ void* wl_android_prealloc(int section, unsigned long size) alloc_ptr = wifi_control_data->mem_prealloc(section, size); if (alloc_ptr) { DHD_INFO(("success alloc section %d\n", section)); - bzero(alloc_ptr, size); + if (size != 0L) + bzero(alloc_ptr, size); return alloc_ptr; } } DHD_ERROR(("can't alloc section %d\n", section)); - return 0; + return NULL; } int wifi_get_irq_number(unsigned long *irq_flags_ptr) @@ -1852,7 +736,7 @@ int wifi_set_power(int on, unsigned long msec) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) int wifi_get_mac_addr(unsigned char *buf) { - DHD_DEFAULT(("%s\n", __FUNCTION__)); + DHD_ERROR(("%s\n", __FUNCTION__)); if (!buf) return -EINVAL; if (wifi_control_data && wifi_control_data->get_mac_addr) { @@ -1877,7 +761,7 @@ void *wifi_get_country_code(char *ccode) static int wifi_set_carddetect(int on) { - DHD_DEFAULT(("%s = %d\n", __FUNCTION__, on)); + DHD_ERROR(("%s = %d\n", __FUNCTION__, on)); if (wifi_control_data && wifi_control_data->set_carddetect) { wifi_control_data->set_carddetect(on); } @@ -1889,7 +773,7 @@ static int wifi_probe(struct platform_device *pdev) struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); - DHD_DEFAULT(("## %s\n", __FUNCTION__)); + DHD_ERROR(("## %s\n", __FUNCTION__)); wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq"); if (wifi_irqres == NULL) wifi_irqres = platform_get_resource_byname(pdev, @@ -1908,33 +792,32 @@ static int wifi_remove(struct platform_device *pdev) struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); - DHD_DEFAULT(("## %s\n", __FUNCTION__)); + DHD_ERROR(("## %s\n", __FUNCTION__)); wifi_control_data = wifi_ctrl; wifi_set_power(0, 0); /* Power Off */ wifi_set_carddetect(0); /* CardDetect (1->0) */ up(&wifi_control_sem); - DHD_DEFAULT(("## %s leave\n", __FUNCTION__)); return 0; } static int wifi_suspend(struct platform_device *pdev, pm_message_t state) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) bcmsdh_oob_intr_set(0); -#endif /* (OOB_INTR_ONLY) */ +#endif return 0; } static int wifi_resume(struct platform_device *pdev) { DHD_TRACE(("##> %s\n", __FUNCTION__)); -#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)) && defined(OOB_INTR_ONLY) if (dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); -#endif /* (OOB_INTR_ONLY) */ +#endif return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h index 03dd8245..3983306c 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.h +++ b/drivers/net/wireless/bcmdhd/wl_android.h @@ -2,13 +2,13 @@ * Linux cfg80211 driver - Android related functions * * Copyright (C) 1999-2011, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 512eaebb..2365bdd4 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -60,42 +60,8 @@ #include #include - -#ifdef BCMWAPI_WPI -/* these items should evetually go into wireless.h of the linux system headfile dir */ -#ifndef IW_ENCODE_ALG_SM4 -#define IW_ENCODE_ALG_SM4 0x20 -#endif - -#ifndef IW_AUTH_WAPI_ENABLED -#define IW_AUTH_WAPI_ENABLED 0x20 -#endif - -#ifndef IW_AUTH_WAPI_VERSION_1 -#define IW_AUTH_WAPI_VERSION_1 0x00000008 -#endif - -#ifndef IW_AUTH_CIPHER_SMS4 -#define IW_AUTH_CIPHER_SMS4 0x00000020 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK -#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT -#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 -#endif -#endif /* BCMWAPI_WPI */ - -#ifdef BCMWAPI_WPI -#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) -#else /* BCMWAPI_WPI */ -#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) -#endif /* BCMWAPI_WPI */ -#define FORCE_MPC - static struct device *cfg80211_parent_dev = NULL; +static int vsdb_supported = 0; struct wl_priv *wlcfg_drv_priv = NULL; u32 wl_dbg_level = WL_DBG_ERR; @@ -105,18 +71,13 @@ u32 wl_dbg_level = WL_DBG_ERR; #define MAX_WAIT_TIME 1500 #define WL_SCAN_ACTIVE_TIME 40 #define WL_SCAN_PASSIVE_TIME 130 - - +#define WL_FRAME_LEN 300 +#define WL_SCAN_BUSY_MAX 8 #define DNGL_FUNC(func, parameters) func parameters; #define COEX_DHCP -/* Set this to 1 to use a seperate interface (p2p0) - * for p2p operations. - */ -#define ENABLE_P2P_INTERFACE 0 - /* This is to override regulatory domains defined in cfg80211 module (reg.c) * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165). @@ -124,19 +85,19 @@ u32 wl_dbg_level = WL_DBG_ERR; * All the chnages in world regulatory domain are to be done here. */ static const struct ieee80211_regdomain brcm_regdom = { - .n_reg_rules = 5, + .n_reg_rules = 4, .alpha2 = "99", .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ - REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), + REG_RULE(2412-10, 2472+10, 40, 6, 20, 0), /* IEEE 802.11b/g, channels 12..13. No HT40 * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, - NL80211_RRF_PASSIVE_SCAN | - NL80211_RRF_NO_IBSS), - /* IEEE 802.11 channel 14 - Only JP enables - * this and for 802.11b only + /* If any */ + /* + * IEEE 802.11 channel 14 - is for JP only, + * we need cfg80211 to allow it (reg_flags = 0); so that + * hostapd could request auto channel by sending down ch 14 */ REG_RULE(2484-10, 2484+10, 20, 6, 20, NL80211_RRF_PASSIVE_SCAN | @@ -238,7 +199,8 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); -static void wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted); +static s32 wl_notify_escan_complete(struct wl_priv *wl, + struct net_device *ndev, bool aborted, bool fw_abort); /* * event & event Q handlers for cfg80211 interfaces */ @@ -256,6 +218,8 @@ static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type, const wl_event_msg_t *msg, void *data); static void wl_put_event(struct wl_event_q *e); static void wl_wakeup_event(struct wl_priv *wl); +static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); static s32 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); @@ -266,10 +230,21 @@ static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data, bool completed); +static s32 wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, bool completed); static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); +#ifdef WL_SCHED_SCAN +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +#endif /* WL_SCHED_SCAN */ +#ifdef PNO_SUPPORT +static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +#endif /* PNO_SUPPORT */ /* * register/deregister parent device */ @@ -303,16 +278,6 @@ static s32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme); static s32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme); -#ifdef BCMWAPI_WPI -#if 0 -static s32 wl_set_set_rx_unencrypted_eapol(struct net_device *dev, - struct cfg80211_connect_params *sme); -#endif -static s32 wl_set_set_wapi_ie(struct net_device *dev, - struct cfg80211_connect_params *sme); -static s32 wl_enable_wapi_auth(struct net_device *dev, - struct cfg80211_connect_params *sme); -#endif static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev); static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, size_t *join_params_size); @@ -327,11 +292,12 @@ static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size); static u32 wl_get_ielen(struct wl_priv *wl); -static struct wireless_dev *wl_alloc_wdev(struct device *dev); +static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); +static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid); static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); @@ -371,7 +337,6 @@ static void wl_link_up(struct wl_priv *wl); static void wl_link_down(struct wl_priv *wl); static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype); static void wl_init_conf(struct wl_conf *conf); -static s32 wl_update_wiphybands(struct wl_priv *wl); /* * iscan handler @@ -418,12 +383,6 @@ int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); -/*HTC_WIFI_START*/ -bool dhd_APUP = false; -static u8 ap_resp_ie[256]; -static int ap_resp_ie_len = 0; -/*HTC_WIFI_END*/ - #define CHECK_SYS_UP(wlpriv) \ do { \ struct net_device *ndev = wl_to_prmry_ndev(wlpriv); \ @@ -571,10 +530,7 @@ static const u32 __wl_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC -#ifdef BCMWAPI_WPI - ,WLAN_CIPHER_SUITE_SMS4 -#endif + WLAN_CIPHER_SUITE_AES_CMAC, }; /* There isn't a lot of sense in it, but you can transmit anything you like */ @@ -727,43 +683,47 @@ wl_validate_wps_ie(char *wps_ie, bool *pbc) static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) { - chanspec_t chspec; - int err = 0; - struct wl_priv *wl = wiphy_priv(wiphy); - struct net_device *dev = wl_to_prmry_ndev(wl); - struct ether_addr bssid; - struct wl_bss_info *bss = NULL; - - if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { - /* STA interface is not associated. So start the new interface on a temp - * channel . Later proper channel will be applied by the above framework - * via set_channel (cfg80211 API). - */ - WL_DBG(("Not associated. Return a temp channel. \n")); + if (vsdb_supported) { return wf_chspec_aton(WL_P2P_TEMP_CHAN); } + else { + chanspec_t chspec; + int err = 0; + struct wl_priv *wl = wiphy_priv(wiphy); + struct net_device *dev = wl_to_prmry_ndev(wl); + struct ether_addr bssid; + struct wl_bss_info *bss = NULL; + if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) { + /* STA interface is not associated. So start the new interface on a temp + * channel . Later proper channel will be applied by the above framework + * via set_channel (cfg80211 API). + */ + WL_DBG(("Not associated. Return a temp channel. \n")); + return wf_chspec_aton(WL_P2P_TEMP_CHAN); + } - *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); - err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, - sizeof(WL_EXTRA_BUF_MAX), false); - if (err) { - WL_ERR(("Failed to get associated bss info, use temp channel \n")); - chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); - } else { - bss = (struct wl_bss_info *) (wl->extra_buf + 4); - chspec = bss->chanspec; - WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); + if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf, + WL_EXTRA_BUF_MAX, false))) { + WL_ERR(("Failed to get associated bss info, use temp channel \n")); + chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN); + } + else { + bss = (struct wl_bss_info *) (wl->extra_buf + 4); + chspec = bss->chanspec; + WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + } + return chspec; } - - return chspec; } static struct net_device* wl_cfg80211_add_monitor_if(char *name) { + int ret = 0; struct net_device* ndev = NULL; - dhd_add_monitor(name, &ndev); + ret = dhd_add_monitor(name, &ndev); WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev)); return ndev; } @@ -777,6 +737,9 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 timeout = -1; s32 wlif_type = -1; s32 mode = 0; +#if defined(WL_ENABLE_P2P_IF) + s32 dhd_mode = 0; +#endif /* (WL_ENABLE_P2P_IF) */ chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); struct net_device *_ndev; @@ -784,7 +747,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, int (*net_attach)(void *dhdp, int ifidx); bool rollback_lock = false; - /* Use primary I/F for to send commands down */ + /* Use primary I/F for sending cmds down to firmware */ _ndev = wl_to_prmry_ndev(wl); WL_DBG(("if name: %s, type: %d\n", name, type)); @@ -818,8 +781,6 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("name is NULL\n")); return NULL; } - if (wl->iface_cnt == IFACE_MAX_CNT) - return ERR_PTR(-ENOMEM); if (wl->p2p_supported && (wlif_type != -1)) { if (wl_get_p2p_status(wl, IF_DELETING)) { /* wait till IF_DEL is complete @@ -847,18 +808,25 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("timeount < 0, return -EAGAIN\n")); return ERR_PTR(-EAGAIN); } + /* It should be now be safe to put this check here since we are sure + * by now netdev_notifier (unregister) would have been called */ + if (wl->iface_cnt == IFACE_MAX_CNT) + return ERR_PTR(-ENOMEM); } - if (!p2p_is_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) { + if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) { p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); wl_cfgp2p_init_discovery(wl); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, + &wl->p2p->dev_addr, &wl->p2p->int_addr); } memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); + wldev_iovar_setint(_ndev, "mpc", 0); + wl_notify_escan_complete(wl, _ndev, true, true); /* In concurrency case, STA may be already associated in a particular channel. * so retrieve the current channel of primary interface and then start the virtual * interface on that. @@ -889,7 +857,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, } vwdev->wiphy = wl->wdev->wiphy; WL_INFO((" virtual interface(%s) is created memalloc done \n", - wl->p2p->vir_ifname)); + wl->p2p->vir_ifname)); vwdev->iftype = type; _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); _ndev->ieee80211_ptr = vwdev; @@ -905,8 +873,21 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, } if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) { wl_alloc_netinfo(wl, _ndev, vwdev, mode); - WL_DBG((" virtual interface(%s) is " + WL_ERR((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); +#if defined(WL_ENABLE_P2P_IF) + if (type == NL80211_IFTYPE_P2P_CLIENT) + dhd_mode = P2P_GC_ENABLED; + else if (type == NL80211_IFTYPE_P2P_GO) + dhd_mode = P2P_GO_ENABLED; + DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); +#endif /* (WL_ENABLE_P2P_IF) */ + /* Start the P2P I/F with PM disabled. Enable PM from + * the framework + */ + if ((type == NL80211_IFTYPE_P2P_CLIENT) || ( + type == NL80211_IFTYPE_P2P_GO)) + vwdev->ps = NL80211_PS_DISABLED; } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -939,24 +920,26 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) WL_DBG(("Enter\n")); if (wl->p2p_net == dev) { - /* Since there is no ifidx corresponding to p2p0, - * all commands should be routed through primary I/F + /* Since there is no ifidx corresponding to p2p0, cmds to + * firmware should be routed through primary I/F */ dev = wl_to_prmry_ndev(wl); } if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); + + /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases + */ + WL_DBG(("P2P: GO_NEG_PHASE status cleared ")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); if (wl->p2p->vif_created) { - if (wl_get_drv_status(wl, SCANNING, dev)) - wl_cfg80211_scan_abort(wl, dev); -#ifdef FORCE_MPC - if (!strstr(firmware_path, "_p2p")) -#endif - wldev_iovar_setint(dev, "mpc", 1); + if (wl_get_drv_status(wl, SCANNING, dev)) { + wl_notify_escan_complete(wl, dev, true, true); + } + wldev_iovar_setint(dev, "mpc", 1); wl_set_p2p_status(wl, IF_DELETING); ret = wl_cfgp2p_ifdel(wl, &p2p_mac); -#if defined(DONGLEHOST) /* Firmware could not delete the interface so we will not get WLC_E_IF * event for cleaning the dhd virtual nw interace * So lets do it here. Failures from fw will ensure the application to do @@ -970,14 +953,16 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) "HANG Notification sent to %s\n", ret, ndev->name)); wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED); } -#endif /* defined(DONGLEHOST) */ /* Wait for any pending scan req to get aborted from the sysioc context */ timeout = wait_event_interruptible_timeout(wl->netif_change_event, - (wl_get_p2p_status(wl, IF_DELETING) == false), + (wl->p2p->vif_created == false), msecs_to_jiffies(MAX_WAIT_TIME)); - if (timeout > 0 && !wl_get_p2p_status(wl, IF_DELETING)) { + if (timeout > 0 && (wl->p2p->vif_created == false)) { WL_DBG(("IFDEL operation done\n")); +#if defined(WL_ENABLE_P2P_IF) + DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); +#endif /* (WL_ENABLE_P2P_IF)) */ } else { WL_ERR(("IFDEL didn't complete properly\n")); } @@ -994,12 +979,14 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, { s32 ap = 0; s32 infra = 0; + s32 err = BCME_OK; + s32 timeout = -1; s32 wlif_type; s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); - WL_DBG(("Enter \n")); + WL_DBG(("Enter type %d\n", type)); switch (type) { case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_WDS: @@ -1025,12 +1012,15 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, default: return -EINVAL; } + WL_DBG(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); if (ap) { wl_set_mode_by_netdev(wl, ndev, mode); if (wl->p2p_supported && wl->p2p->vif_created) { WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created, - p2p_on(wl))); + p2p_on(wl))); + wldev_iovar_setint(ndev, "mpc", 0); + wl_notify_escan_complete(wl, ndev, true, true); /* In concurrency case, STA may be already associated in a particular * channel. so retrieve the current channel of primary interface and @@ -1038,13 +1028,13 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, */ chspec = wl_cfg80211_get_shared_freq(wiphy); - wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT; + wlif_type = WL_P2P_IF_GO; WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type)); wl_set_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); - wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); - wait_event_interruptible_timeout(wl->netif_change_event, + err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); + timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); wl_set_mode_by_netdev(wl, ndev, mode); @@ -1062,6 +1052,14 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, WL_ERR(("Cannot change the interface for GO or SOFTAP\n")); return -EINVAL; } + } else { + infra = htod32(infra); + err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true); + if (err) { + WL_ERR(("WLC_SET_INFRA error (%d)\n", err)); + return -EAGAIN; + } + wl_set_mode_by_netdev(wl, ndev, mode); } ndev->ieee80211_ptr->iftype = type; @@ -1069,16 +1067,18 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, } s32 -wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, void* _net_attach) +wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, + void* _net_attach) { struct wl_priv *wl = wlcfg_drv_priv; s32 ret = BCME_OK; + WL_DBG(("Enter")); if (!ndev) { WL_ERR(("net is NULL\n")); return 0; } if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) { - WL_DBG(("IF_ADD event received, old interface name: %s," + WL_DBG(("IF_ADD event called from dongle, old interface name: %s," "new name: %s\n", ndev->name, wl->p2p->vir_ifname)); /* Assign the net device to CONNECT BSSCFG */ strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1); @@ -1096,11 +1096,23 @@ wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, void* _ne } s32 -wl_cfg80211_notify_ifdel(struct net_device *ndev) +wl_cfg80211_notify_ifdel(void) +{ + struct wl_priv *wl = wlcfg_drv_priv; + + WL_DBG(("Enter \n")); + wl_clr_p2p_status(wl, IF_DELETING); + wake_up_interruptible(&wl->netif_change_event); + return 0; +} + +s32 +wl_cfg80211_ifdel_ops(struct net_device *ndev) { struct wl_priv *wl = wlcfg_drv_priv; bool rollback_lock = false; s32 index = 0; + if (!ndev || !ndev->name) { WL_ERR(("net is NULL\n")); return 0; @@ -1117,11 +1129,11 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) rollback_lock = true; } WL_DBG(("ESCAN COMPLETED\n")); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); if (rollback_lock) rtnl_unlock(); } - WL_ERR(("IF_DEL event received, net %x, vif name: %s\n", + WL_ERR(("IF_DEL event called from dongle, net %x, vif name: %s\n", (unsigned int)ndev, wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); @@ -1131,10 +1143,10 @@ wl_cfg80211_notify_ifdel(struct net_device *ndev) wl->p2p->vif_created = false; wl_cfgp2p_clear_management_ie(wl, index); - wl_clr_p2p_status(wl, IF_DELETING); WL_DBG(("index : %d\n", index)); } + /* Wake up any waiting thread */ wake_up_interruptible(&wl->netif_change_event); @@ -1238,7 +1250,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK; params->channel_list[i] |= chanspec; WL_SCAN(("Chan : %d, Channel spec: %x \n", - channel, params->channel_list[i])); + channel, params->channel_list[i])); params->channel_list[i] = htod16(params->channel_list[i]); } } else { @@ -1343,12 +1355,31 @@ static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request } wl->iscan_kickstart = true; wl_run_iscan(iscan, request, WL_SCAN_ACTION_START); - mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; return err; } +static s32 +wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size) +{ + wl_uint32_list_t *list; + s32 err = BCME_OK; + if (valid_chan_list == NULL || size <= 0) + return -ENOMEM; + + memset(valid_chan_list, 0, size); + list = (wl_uint32_list_t *)(void *) valid_chan_list; + list->count = htod32(WL_NUMCHANNELS); + err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false); + if (err != 0) { + WL_ERR(("get channels failed with %d\n", err)); + } + + return err; +} + static s32 wl_run_escan(struct wl_priv *wl, struct net_device *ndev, struct cfg80211_scan_request *request, uint16 action) @@ -1357,12 +1388,16 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, u32 n_channels; u32 n_ssids; s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params)); - wl_escan_params_t *params; + wl_escan_params_t *params = NULL; struct cfg80211_scan_request *scan_request = wl->scan_request; + u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)]; u32 num_chans = 0; + s32 channel; + s32 n_valid_chan; s32 search_state = WL_P2P_DISC_ST_SCAN; - u32 i; + u32 i, j, n_nodfs = 0; u16 *default_chan_list = NULL; + wl_uint32_list_t *list; struct net_device *dev = NULL; WL_DBG(("Enter \n")); @@ -1409,6 +1444,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, } else if (p2p_is_on(wl) && p2p_scan(wl)) { /* P2P SCAN TRIGGER */ + s32 _freq = 0; + n_nodfs = 0; if (scan_request && scan_request->n_channels) { num_chans = scan_request->n_channels; WL_SCAN((" chann number : %d\n", num_chans)); @@ -1419,11 +1456,26 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, err = -ENOMEM; goto exit; } - for (i = 0; i < num_chans; i++) - { - default_chan_list[i] = - ieee80211_frequency_to_channel( - scan_request->channels[i]->center_freq); + if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { + list = (wl_uint32_list_t *) chan_buf; + n_valid_chan = dtoh32(list->count); + for (i = 0; i < num_chans; i++) + { + _freq = scan_request->channels[i]->center_freq; + channel = ieee80211_frequency_to_channel(_freq); + /* remove DFS channels */ + if (channel < 52 || channel > 140) { + for (j = 0; j < n_valid_chan; j++) { + /* allows only supported channel on + * current reguatory + */ + if (channel == (dtoh32(list->element[j]))) + default_chan_list[n_nodfs++] = + channel; + } + } + + } } if (num_chans == 3 && ( (default_chan_list[0] == SOCIAL_CHAN_1) && @@ -1437,8 +1489,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, /* If you are already a GO, then do SEARCH only */ WL_INFO(("Already a GO. Do SEARCH Only")); search_state = WL_P2P_DISC_ST_SEARCH; + num_chans = n_nodfs; + } else { WL_INFO(("P2P SCAN STATE START \n")); + num_chans = n_nodfs; } } @@ -1490,14 +1545,11 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct wl_priv *wl = wiphy_priv(wiphy); struct cfg80211_ssid *ssids; struct wl_scan_req *sr = wl_to_sr(wl); + struct ether_addr primary_mac; wpa_ie_fixed_t *wps_ie; s32 passive_scan; bool iscan_req; -#ifdef HTC_KlocWork bool escan_req = false; -#else - bool escan_req; -#endif bool p2p_ssid; s32 err = 0; s32 i; @@ -1507,8 +1559,9 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* If scan req comes for p2p0, send it over primary I/F * Scan results will be delivered corresponding to cfg80211_scan_request */ - if (ndev == wl->p2p_net) + if (ndev == wl->p2p_net) { ndev = wl_to_prmry_ndev(wl); + } WL_DBG(("Enter wiphy (%p)\n", wiphy)); if (wl_get_drv_status_all(wl, SCANNING)) { @@ -1519,19 +1572,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WL_ERR(("Scanning being aborted\n")); return -EAGAIN; } -#ifdef HTC_KlocWork - if (request) { -#endif - if (request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { - WL_ERR(("n_ssids > WL_SCAN_PARAMS_SSID_MAX\n")); - return -EOPNOTSUPP; - } -#ifdef HTC_KlocWork + if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) { + WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n")); + return -EOPNOTSUPP; } -#endif + /* Arm scan timeout timer */ - mod_timer(&wl->scan_timeout, jiffies + WL_SCAN_TIMER_INTERVAL_MS * HZ / 1000); + mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS)); iscan_req = false; + wl->scan_request = request; if (request) { /* scan bss */ ssids = request->ssids; if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) { @@ -1548,12 +1597,16 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, if (p2p_ssid) { if (wl->p2p_supported) { /* p2p scan trigger */ - wldev_iovar_setint(ndev, "mpc", 0); if (p2p_on(wl) == false) { /* p2p on at the first time */ p2p_on(wl) = true; wl_cfgp2p_set_firm_p2p(wl); + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, + &wl->p2p->dev_addr, &wl->p2p->int_addr); } + wl_clr_p2p_status(wl, GO_NEG_PHASE); + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); p2p_scan(wl) = true; } } else { @@ -1592,10 +1645,13 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } else { wpsie_len = 0; } - err = wl_cfgp2p_set_management_ie(wl, ndev, -1, - VNDR_IE_PRBREQ_FLAG, wpsie, wpsie_len); - if (unlikely(err)) { - goto scan_out; + if (wpsie_len > 0) { + err = wl_cfgp2p_set_management_ie(wl, + ndev, -1, VNDR_IE_PRBREQ_FLAG, + wpsie, wpsie_len); + if (unlikely(err)) { + goto scan_out; + } } } } @@ -1605,7 +1661,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* we don't do iscan in ibss */ ssids = this_ssid; } - wl->scan_request = request; wl_set_drv_status(wl, SCANNING, ndev); if (iscan_req) { err = wl_do_iscan(wl, request); @@ -1617,11 +1672,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, if (wl->p2p_supported) { if (p2p_on(wl) && p2p_scan(wl)) { -#ifdef HTC_KlocWork - if (request) -#endif - err = wl_cfgp2p_enable_discovery(wl, ndev, - request->ie, request->ie_len); + err = wl_cfgp2p_enable_discovery(wl, ndev, + request->ie, request->ie_len); if (unlikely(err)) { goto scan_out; @@ -1672,7 +1724,12 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, scan_out: wl_clr_drv_status(wl, SCANNING, ndev); - wl->scan_request = NULL; + if (wl->scan_request) { + if (timer_pending(&wl->scan_timeout)) + del_timer_sync(&wl->scan_timeout); + cfg80211_scan_done(wl->scan_request, true); + wl->scan_request = NULL; + } return err; } @@ -1689,6 +1746,13 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); if (unlikely(err)) { WL_ERR(("scan error (%d)\n", err)); + if (err == BCME_BUSY) { + wl->scan_busy_count++; + if (wl->scan_busy_count > WL_SCAN_BUSY_MAX) { + wl->scan_busy_count = 0; + net_os_send_hang_message(ndev); + } + } return err; } @@ -1740,6 +1804,7 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) s32 err = 0; CHECK_SYS_UP(wl); + WL_DBG(("Enter\n")); if (changed & WIPHY_PARAM_RTS_THRESHOLD && (wl->conf->rts_threshold != wiphy->rts_threshold)) { wl->conf->rts_threshold = wiphy->rts_threshold; @@ -1769,7 +1834,6 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } } - return err; } @@ -1778,90 +1842,192 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params) { struct wl_priv *wl = wiphy_priv(wiphy); - struct cfg80211_bss *bss; - struct ieee80211_channel *chan; struct wl_join_params join_params; - struct cfg80211_ssid ssid; - s32 scan_retry = 0; + struct wlc_ssid ssid; + struct ether_addr bssid; + size_t join_params_size = 0; + s32 wsec = 0; + s32 bcnprd; s32 err = 0; - bool rollback_lock = false; WL_TRACE(("In\n")); CHECK_SYS_UP(wl); - if (params->bssid) { - WL_ERR(("Invalid bssid\n")); - return -EOPNOTSUPP; - } - bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); - if (!bss) { - memcpy(ssid.ssid, params->ssid, params->ssid_len); - ssid.ssid_len = params->ssid_len; - do { - if (unlikely - (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == - -EBUSY)) { - wl_delay(150); - } else { - break; - } - } while (++scan_retry < WL_SCAN_RETRY_MAX); - /* to allow scan_inform to propagate to cfg80211 plane */ - if (rtnl_is_locked()) { - rtnl_unlock(); - rollback_lock = true; - } - - /* wait 4 secons till scan done.... */ - schedule_timeout_interruptible(4 * HZ); - if (rollback_lock) - rtnl_lock(); - bss = cfg80211_get_ibss(wiphy, NULL, - params->ssid, params->ssid_len); - } - if (bss) { - wl->ibss_starter = false; - WL_DBG(("Found IBSS\n")); - } else { - wl->ibss_starter = true; - } - chan = params->channel; - if (chan) - wl->channel = ieee80211_frequency_to_channel(chan->center_freq); + /* - * Join with specific BSSID and cached SSID - * If SSID is zero join based on BSSID only + * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ - memset(&join_params, 0, sizeof(join_params)); - memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, - params->ssid_len); - join_params.ssid.SSID_len = htod32(params->ssid_len); - if (params->bssid) { -#ifdef PNO_SUPPORT - dhd_set_pfn_ssid(params->ssid, params->ssid_len); -#endif - memcpy(&join_params.params.bssid, params->bssid, - ETHER_ADDR_LEN); + if (wl->scan_request) { + wl_notify_escan_complete(wl, dev, true, true); + } + /* Clean BSSID */ + bzero(&bssid, sizeof(bssid)); + wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID); + + if (params->ssid) + WL_INFO(("SSID: %s\n", params->ssid)); + else { + WL_ERR(("SSID: NULL, Not supported\n")); + err = -EOPNOTSUPP; + goto CleanUp; + } + + if (params->bssid) + WL_INFO(("BSSID: %02X:%02X:%02X:%02X:%02X:%02X\n", + params->bssid[0], params->bssid[1], params->bssid[2], + params->bssid[3], params->bssid[4], params->bssid[5])); + + if (params->channel) + WL_INFO(("channel: %d\n", params->channel->center_freq)); + + if (params->channel_fixed) + WL_INFO(("fixed channel required\n")); + + if (params->ie && params->ie_len) + WL_INFO(("ie len: %d\n", params->ie_len)); + + if (params->beacon_interval) + WL_INFO(("beacon interval: %d\n", params->beacon_interval)); + + if (params->basic_rates) + WL_INFO(("basic rates: %08X\n", params->basic_rates)); + + if (params->privacy) + WL_INFO(("privacy required\n")); + + wl_set_drv_status(wl, CONNECTING, dev); + + /* Configure Privacy for starter */ + if (params->privacy) + wsec |= WEP_ENABLED; + + err = wldev_iovar_setint(dev, "wsec", wsec); + if (err) { + WL_ERR(("wsec failed (%d)\n", err)); + goto CleanUp; + } + + err = wldev_iovar_setint(dev, "auth", WL_AUTH_OPEN_SYSTEM); + if (err) { + WL_ERR(("auth failed (%d)\n", err)); + goto CleanUp; + } + + err = wldev_iovar_setint(dev, "wpa_auth", 0); + if (err) { + WL_ERR(("wpa_auth failed (%d)\n", err)); + goto CleanUp; } + + /* Configure Beacon Interval for starter */ + if (params->beacon_interval) + bcnprd = params->beacon_interval; else - memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); + bcnprd = 100; - err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, - sizeof(join_params), false); - if (unlikely(err)) { - WL_ERR(("Error (%d)\n", err)); - return err; + bcnprd = htod32(bcnprd); + err = wldev_ioctl(dev, WLC_SET_BCNPRD, &bcnprd, sizeof(bcnprd), true); + if (err) { + WL_ERR(("WLC_SET_BCNPRD failed (%d)\n", err)); + goto CleanUp; + } + + /* Configure required join parameter */ + memset(&join_params, 0, sizeof(struct wl_join_params)); + + /* SSID */ + memset(&ssid, 0, sizeof(struct wlc_ssid)); + ssid.SSID_len = MIN(params->ssid_len, 32); + join_params.ssid.SSID_len = htod32(ssid.SSID_len); + memcpy(ssid.SSID, params->ssid, ssid.SSID_len); + memcpy(join_params.ssid.SSID, params->ssid, ssid.SSID_len); + join_params_size = sizeof(join_params.ssid); + + wl_update_prof(wl, dev, NULL, &ssid, WL_PROF_SSID); + + /* BSSID */ + if (params->bssid) { + memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN); + join_params_size = sizeof(join_params.ssid) + + WL_ASSOC_PARAMS_FIXED_SIZE; + + wl_update_prof(wl, dev, NULL, params->bssid, WL_PROF_BSSID); + } else { + memcpy(&join_params.params.bssid, ðer_bcast, ETHER_ADDR_LEN); + } + + /* Channel */ + if (params->channel) { + u32 target_channel; + + target_channel = ieee80211_frequency_to_channel( + params->channel->center_freq); + if (params->channel_fixed) { + /* adding chanspec */ + wl_ch_to_chanspec(target_channel, + &join_params, &join_params_size); + } + + /* set channel for starter */ + target_channel = htod32(target_channel); + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &target_channel, sizeof(target_channel), true); + if (err) { + WL_ERR(("WLC_SET_CHANNEL failed (%d)\n", err)); + goto CleanUp; + } + } + + wl->ibss_starter = false; + + err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true); + if (err) { + WL_ERR(("WLC_SET_SSID failed (%d)\n", err)); + goto CleanUp; } + +CleanUp: + + if (err) + wl_clr_drv_status(wl, CONNECTING, dev); + + WL_TRACE(("Exit\n")); return err; } static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) { struct wl_priv *wl = wiphy_priv(wiphy); + scb_val_t scbval; + bool act = false; s32 err = 0; + u8 *curbssid; + + WL_TRACE(("Enter\n")); CHECK_SYS_UP(wl); - wl_link_down(wl); + act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); + curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); + if (act) { + /* + * Cancel ongoing scan to sync up with sme state machine of cfg80211. + */ + if (wl->scan_request) { + wl_notify_escan_complete(wl, dev, true, true); + } + wl_set_drv_status(wl, DISCONNECTING, dev); + scbval.val = DOT11_RC_DISASSOC_LEAVING; + memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); + scbval.val = htod32(scbval.val); + err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, + sizeof(scb_val_t), true); + if (unlikely(err)) { + wl_clr_drv_status(wl, DISCONNECTING, dev); + WL_ERR(("error (%d)\n", err)); + return err; + } + } + WL_TRACE(("Exit\n")); return err; } @@ -1883,13 +2049,6 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) if (is_wps_conn(sme)) val = WPA_AUTH_DISABLED; -#ifdef BCMWAPI_WPI - if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) - { - WL_DBG((" * wl_set_wpa_version, set wpa_auth to WPA_AUTH_WAPI 0x400")); - val = WPA_AUTH_WAPI; - } -#endif WL_DBG(("setting wpa_auth to 0x%0x\n", val)); err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); @@ -1902,88 +2061,31 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) return err; } -#ifdef BCMWAPI_WPI -static s32 wl_enable_wapi_auth(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = wlcfg_drv_priv; - s32 err = 0; - s32 wsec; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - WL_ERR((" %s \n",__FUNCTION__)); - - if(sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) - { - err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); - if (unlikely(err)) { - WL_ERR(("get wsec error (%d)\n", err)); - return err; - } - wsec |= SMS4_ENABLED; - wsec = 256; - err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx); - if (unlikely(err)) { - WL_ERR(("set wsec error (%d)\n", err)); - return err; - } - - err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", 0x800, bssidx); - if (unlikely(err)) { - WL_ERR(("set wpa_auth error (%d)\n", err)); - return err; - } - } - else - WL_DBG((" * skip \n")); - return err; -} static s32 -wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme) +wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) { struct wl_priv *wl = wlcfg_drv_priv; - s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - - WL_ERR((" %s \n",__FUNCTION__)); - - if(sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) - { - err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie, sme->ie_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); - - if (unlikely(err)) { - WL_ERR(("===> set_wapi_ie Error (%d)\n", err)); - return err; - } - } - else - WL_DBG((" * skip \n")); - return err; -} -#endif -static s32 -wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = wlcfg_drv_priv; - struct wl_security *sec; - s32 val = 0; + struct wl_security *sec; + s32 val = 0; s32 err = 0; s32 bssidx = wl_cfgp2p_find_idx(wl, dev); switch (sme->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: - val = 0; + val = WL_AUTH_OPEN_SYSTEM; WL_DBG(("open system\n")); break; case NL80211_AUTHTYPE_SHARED_KEY: - val = 1; + val = WL_AUTH_SHARED_KEY; WL_DBG(("shared key\n")); break; case NL80211_AUTHTYPE_AUTOMATIC: - val = 2; + val = WL_AUTH_OPEN_SHARED; WL_DBG(("automatic\n")); break; case NL80211_AUTHTYPE_NETWORK_EAP: WL_DBG(("network eap\n")); default: - val = 2; + val = WL_AUTH_OPEN_SHARED; WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); break; } @@ -2006,9 +2108,6 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) s32 pval = 0; s32 gval = 0; s32 err = 0; -#ifdef BCMWAPI_WPI - int val = 0; -#endif s32 bssidx = wl_cfgp2p_find_idx(wl, dev); if (sme->crypto.n_ciphers_pairwise) { @@ -2026,13 +2125,6 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_CIPHER_SUITE_AES_CMAC: pval = AES_ENABLED; break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - WL_ERR((" * ciphers_pairwise, Set value to SMS4_ENABLED")); - val = SMS4_ENABLED; - pval = SMS4_ENABLED; - break; -#endif default: WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0])); @@ -2054,13 +2146,6 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_CIPHER_SUITE_AES_CMAC: gval = AES_ENABLED; break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - WL_ERR((" * cipher_group, Set value to SMS4_ENABLED")); - val = SMS4_ENABLED; - gval = SMS4_ENABLED; - break; -#endif default: WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group)); @@ -2071,23 +2156,15 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) WL_DBG(("pval (%d) gval (%d)\n", pval, gval)); if (is_wps_conn(sme)) { - err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); + if (sme->privacy) + err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx); + else + /* WPS-2.0 allowes no security */ + err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx); } else { -#ifdef BCMWAPI_WPI - if(sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) { - WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED")); - - err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx); - } - else { - -#endif - WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC")); - err = wldev_iovar_setint_bsscfg(dev, "wsec", + WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC")); + err = wldev_iovar_setint_bsscfg(dev, "wsec", pval | gval, bssidx); -#ifdef BCMWAPI_WPI - } -#endif } if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); @@ -2143,14 +2220,6 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) return -EINVAL; } } -#ifdef BCMWAPI_WPI - else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) - { - - WL_ERR((" * wl_set_key_mgmt, WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED")); - val = WPA_AUTH_WAPI; - } -#endif WL_DBG(("setting wpa_auth to %d\n", val)); err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); @@ -2182,17 +2251,9 @@ wl_set_set_sharedkey(struct net_device *dev, WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise)); if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | - NL80211_WPA_VERSION_2 -#ifdef BCMWAPI_WPI - | NL80211_WAPI_VERSION_1 -#endif - )) && + NL80211_WPA_VERSION_2)) && (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | - WLAN_CIPHER_SUITE_WEP104 -#ifdef BCMWAPI_WPI - | WLAN_CIPHER_SUITE_SMS4 -#endif - ))) + WLAN_CIPHER_SUITE_WEP104))) { memset(&key, 0, sizeof(key)); key.len = (u32) sme->key_len; @@ -2210,12 +2271,6 @@ wl_set_set_sharedkey(struct net_device *dev, case WLAN_CIPHER_SUITE_WEP104: key.algo = CRYPTO_ALGO_WEP128; break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - WL_DBG((" * wl_set_set_sharedkey, set shared key to CRYPTO_ALGO_SMS4")); - key.algo = CRYPTO_ALGO_SMS4; - break; -#endif default: WL_ERR(("Invalid algorithm (%d)\n", sme->crypto.ciphers_pairwise[0])); @@ -2232,9 +2287,9 @@ wl_set_set_sharedkey(struct net_device *dev, WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; } - if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { + if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { WL_DBG(("set auth_type to shared key\n")); - val = 2; /* openshared key */ + val = WL_AUTH_SHARED_KEY; /* shared key */ err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx); if (unlikely(err)) { WL_ERR(("set auth failed (%d)\n", err)); @@ -2273,7 +2328,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } /* Clean BSSID */ bzero(&bssid, sizeof(bssid)); @@ -2301,6 +2356,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, */ WL_DBG(("ASSOC2 p2p index : %d sme->ie_len %d\n", wl_cfgp2p_find_idx(wl, dev), sme->ie_len)); + wl_cfgp2p_set_management_ie(wl, dev, + wl_cfgp2p_find_idx(wl, dev), VNDR_IE_PRBREQ_FLAG, + sme->ie, sme->ie_len); wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } @@ -2353,48 +2411,18 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, chan->center_freq)); } else wl->channel = 0; -#ifdef BCMWAPI_WPI - - WL_DBG(("1. enable wapi auth\n")); - err = wl_enable_wapi_auth(dev, sme); - if (unlikely(err)) - return err; - - if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) - { - WL_DBG(("2. set wapi ie \n")); - err = wl_set_set_wapi_ie(dev, sme); - if (unlikely(err)) - return err; - } - else - WL_DBG(("2. Not wapi ie \n")); - - -#endif WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len)); - WL_DBG(("3. set wapi version \n")); err = wl_set_wpa_version(dev, sme); if (unlikely(err)) { WL_ERR(("Invalid wpa_version\n")); return err; } -#ifdef BCMWAPI_WPI - if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) - WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n")); - else - { - WL_DBG(("4. wl_set_auth_type\n")); -#endif - err = wl_set_auth_type(dev, sme); - if (unlikely(err)) { - WL_ERR(("Invalid auth type\n")); - return err; - } -#ifdef BCMWAPI_WPI - } -#endif + err = wl_set_auth_type(dev, sme); + if (unlikely(err)) { + WL_ERR(("Invalid auth type\n")); + return err; + } err = wl_set_set_cipher(dev, sme); if (unlikely(err)) { @@ -2525,7 +2553,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, * Cancel ongoing scan to sync up with sme state machine of cfg80211. */ if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } wl_set_drv_status(wl, DISCONNECTING, dev); scbval.val = reason_code; @@ -2719,38 +2747,17 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, key.algo = CRYPTO_ALGO_AES_CCM; WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - key.algo = CRYPTO_ALGO_SMS4; - WL_DBG(("wl_add_keyext : set key to CRYPTO_ALGO_SMS4\n")); - break; -#endif default: WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); return -EINVAL; } swap_key_from_BE(&key); -#if defined(CONFIG_WIRELESS_EXT) - dhd_wait_pend8021x(dev); -#endif wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (unlikely(err)) { WL_ERR(("WLC_SET_KEY error (%d)\n", err)); return err; } -#ifdef BCMWAPI_WPI - if ( params->cipher == WLAN_CIPHER_SUITE_SMS4) - { - WL_DBG((" * wl_set_wpa_version, set wpa_auth to WPA_AUTH_WAPI 0x400")); - - err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_WAPI, bssidx); - if (unlikely(err)) { - WL_ERR(("set wpa_auth failed (%d)\n", err)); - return err; - } - } -#endif } return err; } @@ -2821,13 +2828,6 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, val = AES_ENABLED; WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - key.algo = CRYPTO_ALGO_SMS4; - val = SMS4_ENABLED; - WL_DBG((" * wl_cfg80211_add_key, set key to WLAN_CIPHER_SUITE_SMS4\n")); - break; -#endif default: WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); return -EINVAL; @@ -2872,9 +2872,9 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); memset(&key, 0, sizeof(key)); - key.index = (u32) key_idx; key.flags = WL_PRIMARY_KEY; key.algo = CRYPTO_ALGO_OFF; + key.index = (u32) key_idx; WL_DBG(("key index (%d)\n", key_idx)); /* Set the new key/index */ @@ -2941,12 +2941,6 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); break; -#ifdef BCMWAPI_WPI - case WLAN_CIPHER_SUITE_SMS4: - key.algo = CRYPTO_ALGO_SMS4; - WL_DBG((" * wl_cfg80211_add_key, set key to WLAN_CIPHER_SUITE_SMS4\n")); - break; -#endif default: WL_ERR(("Invalid algo (0x%x)\n", wsec)); return -EINVAL; @@ -2978,6 +2972,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, s8 eabuf[ETHER_ADDR_STR_LEN]; #endif dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + CHECK_SYS_UP(wl); if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, @@ -3004,47 +2999,46 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, sta->idle * 1000)); #endif } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) { - u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); - if (!wl_get_drv_status(wl, CONNECTED, dev) || - (dhd_is_associated(dhd, NULL) == FALSE)) { - - WL_ERR(("NOT assoc\n")); - err = -ENODEV; - goto get_station_err; - } - if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { - WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n", - MAC2STR(mac), MAC2STR(curmacp))); - } + u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID); + err = -ENODEV; + if (!wl_get_drv_status(wl, CONNECTED, dev) || + (dhd_is_associated(dhd, NULL, &err) == FALSE)) { + WL_ERR(("NOT assoc: %d\n", err)); + goto get_station_err; + } + if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { + WL_ERR(("Wrong Mac address: "MACSTR" != "MACSTR"\n", + MAC2STR(mac), MAC2STR(curmacp))); + } - /* Report the current tx rate */ - err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); - if (err) { - WL_ERR(("Could not get rate (%d)\n", err)); - } else { - rate = dtoh32(rate); - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rate * 5; - WL_DBG(("Rate %d Mbps\n", (rate / 2))); - } + /* Report the current tx rate */ + err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false); + if (err) { + WL_ERR(("Could not get rate (%d)\n", err)); + } else { + rate = dtoh32(rate); + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = rate * 5; + WL_DBG(("Rate %d Mbps\n", (rate / 2))); + } - memset(&scb_val, 0, sizeof(scb_val)); - scb_val.val = 0; - err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, - sizeof(scb_val_t), false); - if (err) { - WL_ERR(("Could not get rssi (%d)\n", err)); - goto get_station_err; - } - rssi = dtoh32(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_DBG(("RSSI %d dBm\n", rssi)); + memset(&scb_val, 0, sizeof(scb_val)); + scb_val.val = 0; + err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val, + sizeof(scb_val_t), false); + if (err) { + WL_ERR(("Could not get rssi (%d)\n", err)); + goto get_station_err; + } + rssi = dtoh32(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_DBG(("RSSI %d dBm\n", rssi)); get_station_err: - if (err) { + if (err && (err != -ETIMEDOUT) && (err != -EIO)) { /* Disconnect due to zero BSSID or error to get RSSI */ - WL_ERR(("force cfg80211_disconnected\n")); + WL_ERR(("force cfg80211_disconnected: %d\n", err)); wl_clr_drv_status(wl, CONNECTED, dev); cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); wl_link_down(wl); @@ -3064,18 +3058,13 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, CHECK_SYS_UP(wl); + WL_DBG(("Enter : power save %s\n", (enabled ? "enable" : "disable"))); if (wl->p2p_net == dev) { return err; } pm = enabled ? PM_FAST : PM_OFF; - /* Do not enable the power save after assoc if it is p2p interface */ - if (wl->p2p && wl->p2p->vif_created) { - WL_DBG(("Do not enable the power save for p2p interfaces even after assoc\n")); - pm = PM_OFF; - } pm = htod32(pm); - WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true); if (unlikely(err)) { if (err == -ENODEV) @@ -3084,6 +3073,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("error (%d)\n", err)); return err; } + WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); return err; } @@ -3141,6 +3131,7 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy) struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); unsigned long flags; + if (unlikely(!wl_get_drv_status(wl, READY, ndev))) { WL_INFO(("device is not ready : status (%d)\n", (int)wl->status)); @@ -3181,8 +3172,8 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, return -EINVAL; } /* pmk list is supported only for STA interface i.e. primary interface - * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init - */ + * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init + */ if (primary_dev != dev) { WL_INFO(("Not supporting Flushing pmklist on virtual" " interfaces than primary interface\n")); @@ -3332,45 +3323,12 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) /* Our scan params have 1 channel and 0 ssids */ params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) | - (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); + (num_chans & WL_SCAN_PARAMS_COUNT_MASK)); *out_params_size = params_size; /* rtn size to the caller */ return params; } -s32 -wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev) -{ - wl_scan_params_t *params = NULL; - s32 params_size = 0; - s32 err = BCME_OK; - unsigned long flags; - - WL_DBG(("Enter\n")); - /* Our scan params only need space for 1 channel and 0 ssids */ - params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); - if (params == NULL) { - WL_ERR(("scan params allocation failed \n")); - err = -ENOMEM; - } else { - /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, true); - if (err < 0) { - WL_ERR(("scan abort failed \n")); - } - } - del_timer_sync(&wl->scan_timeout); - spin_lock_irqsave(&wl->cfgdrv_lock, flags); - if (wl->scan_request) { - cfg80211_scan_done(wl->scan_request, true); - wl->scan_request = NULL; - } - wl_clr_drv_status(wl, SCANNING, ndev); - spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - if (params) - kfree(params); - return err; -} static s32 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_channel * channel, @@ -3393,9 +3351,8 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, } if (wl_get_drv_status(wl, SCANNING, ndev)) { - wl_cfg80211_scan_abort(wl, ndev); + wl_notify_escan_complete(wl, ndev, true, true); } - target_channel = ieee80211_frequency_to_channel(channel->center_freq); memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel)); wl->remain_on_chan_type = channel_type; @@ -3405,7 +3362,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, *cookie = id; cfg80211_ready_on_channel(dev, *cookie, channel, channel_type, duration, GFP_KERNEL); - if (!p2p_is_on(wl)) { + if (wl->p2p && !wl->p2p->on) { get_primary_mac(wl, &primary_mac); wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); @@ -3436,6 +3393,7 @@ wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev WL_DBG((" enter ) netdev_ifidx: %d \n", dev->ifindex)); return err; } + static s32 wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl) { @@ -3457,7 +3415,7 @@ wl_cfg80211_send_pending_tx_act_frm(struct wl_priv *wl) */ wl_clr_drv_status(wl, SENDING_ACT_FRM, wl->afx_hdl->dev); wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); wl_cfgp2p_discover_enable_search(wl, false); tx_act_frm->channel = wl->afx_hdl->peer_chan; wl->afx_hdl->ack_recv = (wl_cfgp2p_tx_action_frame(wl, dev, @@ -3511,8 +3469,8 @@ wl_cfg80211_send_at_common_channel(struct wl_priv *wl, if (wl->afx_hdl->peer_chan != WL_INVALID) wl_cfg80211_send_pending_tx_act_frm(wl); else { - WL_ERR(("Couldn't find the peer after %d retries\n", - wl->afx_hdl->retry)); + WL_ERR(("Couldn't find the peer " MACSTR " after %d retries\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), wl->afx_hdl->retry)); } wl->afx_hdl->dev = NULL; wl->afx_hdl->bssidx = WL_INVALID; @@ -3528,9 +3486,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *channel, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, - const u8* buf, size_t len, u64 *cookie) + const u8* buf, size_t len, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + bool no_cck, +#endif + u64 *cookie) { - struct ether_addr primary_mac; wl_action_frame_t *action_frame; wl_af_params_t *af_params; wifi_p2p_ie_t *p2p_ie; @@ -3544,9 +3505,13 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, u32 p2pie_len = 0; u32 wpsie_len = 0; u32 id; + u32 retry = 0; bool ack = false; - wifi_p2p_pub_act_frame_t *act_frm; + wifi_p2p_pub_act_frame_t *act_frm = NULL; + wifi_p2p_action_frame_t *p2p_act_frm = NULL; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; s8 eabuf[ETHER_ADDR_STR_LEN]; + int retry_cnt = 0; WL_DBG(("Enter \n")); @@ -3565,8 +3530,6 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, return -ENODEV; } if (p2p_is_on(wl)) { - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr); /* Suspend P2P discovery search-listen to prevent it from changing the * channel. */ @@ -3585,21 +3548,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, if (ieee80211_is_probe_resp(mgmt->frame_control)) { s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; s32 ie_len = len - ie_offset; - s32 left_ie_len = 0; if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)(buf + ie_offset), ie_len)) != NULL) { /* Total length of P2P Information Element */ p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); - /* find the second p2p ie if any, allow 2 max right now */ - left_ie_len = ie_len - (s32)((u8 *)p2p_ie - (u8 *)(buf + ie_offset)) - p2pie_len; - if ((left_ie_len > 0) && ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)p2p_ie + p2pie_len, left_ie_len)) - != NULL)) { - /* Total length of P2P Information Element */ - p2pie_len += p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id); - /* Have to change p2p device address in dev_info attribute - * because Supplicant use primary eth0 address - */ - } } if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len)) != NULL) { @@ -3622,19 +3574,26 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, scb_val.val = mgmt->u.disassoc.reason_code; wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); - WL_DBG(("Disconnect STA : %s\n", - bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf))); + WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), + scb_val.val)); + /* Wait for the deauth event to come, supplicant will do the + * delete iface immediately and we will have problem in sending + * deauth frame if we delete the bss in firmware + */ + wl_delay(400); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; } else if (ieee80211_is_action(mgmt->frame_control)) { - /* Abort the dwell time of any previous off-channel action frame that may - * be still in effect. Sending off-channel action frames relies on the - * driver's scan engine. If a previous off-channel action frame tx is - * still in progress (including the dwell time), then this new action - * frame will not be sent out. + /* Abort the dwell time of any previous off-channel + * action frame that may be still in effect. Sending + * off-channel action frames relies on the driver's + * scan engine. If a previous off-channel action frame + * tx is still in progress (including the dwell time), + * then this new action frame will not be sent out. */ - wl_cfg80211_scan_abort(wl, dev); + wl_notify_escan_complete(wl, dev, true, true); } @@ -3669,6 +3628,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, ieee80211_frequency_to_channel(channel->center_freq); if (channel->band == IEEE80211_BAND_5GHZ) { + WL_DBG(("5GHz channel %d", af_params->channel)); err = wldev_ioctl(dev, WLC_SET_CHANNEL, &af_params->channel, sizeof(af_params->channel), true); if (err < 0) { @@ -3683,39 +3643,96 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, af_params->dwell_time = WL_DWELL_TIME; memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len); + if (wl_cfgp2p_is_pub_action(action_frame->data, action_frame->len)) { + act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data); + WL_DBG(("P2P PUB action_frame->len: %d chan %d category %d subtype %d\n", + action_frame->len, af_params->channel, + act_frm->category, act_frm->subtype)); + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_REQ) || + (act_frm->subtype == P2P_PAF_GON_RSP) || + (act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_REQ))) { + wldev_iovar_setint(dev, "mpc", 0); + } - act_frm = (wifi_p2p_pub_act_frame_t *) (action_frame->data); - WL_DBG(("action_frame->len: %d chan %d category %d subtype %d\n", - action_frame->len, af_params->channel, - act_frm->category, act_frm->subtype)); - /* - * To make sure to send successfully action frame, we have to turn off mpc - */ - - if ((act_frm->subtype == P2P_PAF_GON_REQ) || - (act_frm->subtype == P2P_PAF_GON_RSP) || - (act_frm->subtype == P2P_PAF_GON_CONF) || - (act_frm->subtype == P2P_PAF_PROVDIS_REQ)) { - wldev_iovar_setint(dev, "mpc", 0); - } - - if (act_frm->subtype == P2P_PAF_DEVDIS_REQ) - af_params->dwell_time = WL_LONG_DWELL_TIME; + if (act_frm->subtype == P2P_PAF_GON_REQ) { + WL_DBG(("P2P: GO_NEG_PHASE status set \n")); + wl_set_p2p_status(wl, GO_NEG_PHASE); + } else if (act_frm->subtype == P2P_PAF_GON_CONF) { + /* If we reached till GO Neg confirmation + * reset the filter + */ + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); + } + if (act_frm->subtype == P2P_PAF_GON_RSP) + retry_cnt = 1; + else retry_cnt = WL_ACT_FRAME_RETRY; + + if (act_frm && act_frm->subtype == P2P_PAF_DEVDIS_REQ) { + af_params->dwell_time = WL_LONG_DWELL_TIME; + } else if (act_frm && + (act_frm->subtype == P2P_PAF_PROVDIS_REQ || + act_frm->subtype == P2P_PAF_PROVDIS_RSP || + act_frm->subtype == P2P_PAF_GON_RSP)) { + af_params->dwell_time = WL_MED_DWELL_TIME; + } + } else if (wl_cfgp2p_is_p2p_action(action_frame->data, action_frame->len)) { + p2p_act_frm = (wifi_p2p_action_frame_t *) (action_frame->data); + WL_DBG(("P2P action_frame->len: %d chan %d category %d subtype %d\n", + action_frame->len, af_params->channel, + p2p_act_frm->category, p2p_act_frm->subtype)); + } else if (wl_cfgp2p_is_gas_action(action_frame->data, action_frame->len)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) (action_frame->data); + WL_DBG(("Service Discovery action_frame->len: %d chan %d category %d action %d\n", + action_frame->len, af_params->channel, + sd_act_frm->category, sd_act_frm->action)); + af_params->dwell_time = WL_MED_DWELL_TIME; + retry_cnt = WL_ACT_FRAME_RETRY; + } + wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); + /* + * To make sure to send successfully action frame, we have to turn off mpc + */ if (IS_P2P_SOCIAL(af_params->channel) && - (IS_P2P_ACT_REQ(act_frm->category, act_frm->subtype) || - IS_GAS_REQ(act_frm->category, act_frm->action))) { + (IS_P2P_PUB_ACT_REQ(act_frm, &act_frm->elts[0], action_frame->len) || + IS_GAS_REQ(sd_act_frm, action_frame->len)) && + wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) { + /* channel offload require P2P IE for Probe request + * otherwise, we will use wl_cfgp2p_tx_action_frame directly. + * channel offload for action request frame + */ + /* channel offload for action request frame */ ack = wl_cfg80211_send_at_common_channel(wl, dev, af_params); + /* We need to retry Service discovery frames as they don't get retried immediately by supplicant*/ + if ((!ack) && (IS_GAS_REQ(sd_act_frm, action_frame->len))) { + for (retry = 1; retry < retry_cnt; retry++) { + WL_DBG(("Service Discovery action_frame retry %d len: %d chan %d category %d action %d\n", + retry, action_frame->len, af_params->channel, + sd_act_frm->category, sd_act_frm->action)); + ack = (wl_cfgp2p_tx_action_frame(wl, dev, + af_params, bssidx)) ? false : true; + if (ack) + break; + } + } } else { ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? false : true; + if (!ack) { + for (retry = 1; retry < retry_cnt; retry++) { + ack = (wl_cfgp2p_tx_action_frame(wl, dev, + af_params, bssidx)) ? false : true; + if (ack) + break; + } + } + } cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, ack, GFP_KERNEL); - if (act_frm->subtype == P2P_PAF_GON_CONF) { -#ifdef FORCE_MPC - if (!strstr(firmware_path, "_p2p")) -#endif - wldev_iovar_setint(dev, "mpc", 1); + if (act_frm && act_frm->subtype == P2P_PAF_GON_CONF) { + wldev_iovar_setint(dev, "mpc", 1); } kfree(af_params); exit: @@ -3776,6 +3793,15 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, dev = wl_to_prmry_ndev(wl); } channel = ieee80211_frequency_to_channel(chan->center_freq); + + if (wl_get_drv_status(wl, AP_CREATING, dev)) { + WL_TRACE(("<0> %s: as!!! in AP creating mode, save chan num:%d\n", + __FUNCTION__, channel)); + wl->hostapd_chan = channel; + if (channel == 14) + return err; /* hostapd requested ch auto-select, will be done later */ + } + WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n", dev->ifindex, channel_type, channel)); err = wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), true); @@ -3790,7 +3816,7 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) { s32 len = 0; s32 err = BCME_OK; - u16 auth = 0; /* d11 open authentication */ + u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */ u32 wsec; u32 pval = 0; u32 gval = 0; @@ -3821,11 +3847,6 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) case WPA_CIPHER_AES_CCM: gval = AES_ENABLED; break; -#ifdef BCMWAPI_WPI - case WAPI_CIPHER_SMS4: - gval = SMS4_ENABLED; - break; -#endif default: WL_ERR(("No Security Info\n")); break; @@ -3849,11 +3870,6 @@ wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx) case WPA_CIPHER_AES_CCM: pval = AES_ENABLED; break; -#ifdef BCMWAPI_WPI - case WAPI_CIPHER_SMS4: - pval = SMS4_ENABLED; - break; -#endif default: WL_ERR(("No Security Info\n")); } @@ -3904,7 +3920,7 @@ wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx) wpa_suite_mcast_t *mcast; wpa_suite_ucast_t *ucast; wpa_suite_auth_key_mgmt_t *mgmt; - u16 auth = 0; /* d11 open authentication */ + u16 auth = WL_AUTH_OPEN_SYSTEM; /* d11 open authentication */ u16 count; s32 err = BCME_OK; s32 len = 0; @@ -4056,9 +4072,6 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, wpa_ie_fixed_t *wps_ie; wpa_ie_fixed_t *wpa_ie; bcm_tlv_t *wpa2_ie; -#ifdef BCMWAPI_WPI - bcm_tlv_t *wapi_ie; -#endif wifi_p2p_ie_t *p2p_ie; bool is_bssup = false; bool update_bss = false; @@ -4126,31 +4139,15 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len + p2pie_len); -// ZZZZZ - /* find the WPA_IE */ - if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, info->tail_len)) != NULL) { - WL_DBG((" WPA IE is found\n")); - } -// ZZZZZZ + /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, DOT11_MNG_RSN_ID)) != NULL) { WL_DBG((" WPA2 IE is found\n")); } -#ifdef BCMWAPI_WPI - if ((wapi_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, - DOT11_MNG_WAPI_ID)) != NULL) { - WL_DBG(("%s: found a WAPI IE...\n", __FUNCTION__)); - } -#endif - is_bssup = wl_cfgp2p_bss_isup(dev, bssidx); - if (!is_bssup && (wpa_ie != NULL || wpa2_ie != NULL -#ifdef BCMWAPI_WPI - || wapi_ie != NULL -#endif - )) { + if (!is_bssup && (wpa2_ie != NULL)) { wldev_iovar_setint(dev, "mpc", 0); if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) { WL_ERR(("WPA2 IE parsing error")); @@ -4180,25 +4177,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], info->head_len - ie_offset, DOT11_MNG_SSID_ID)) != NULL) { - - /*HTC_CSP_START*/ - int closed = 0; - int max_assoc = 8; - bcm_tlv_t *max_assoc_ie; - - if (ssid_ie->len == 0) { - printf("%s: search SSID again to get real SSID.\n", __func__); - ssid_ie = bcm_parse_tlvs((u8 *)ssid_ie->data, - info->head_len - ie_offset - 1, - DOT11_MNG_SSID_ID); - if (ssid_ie != NULL) - printf("%s: got real ssid, use it instead. ssid_ie->len=%d\n", __func__, ssid_ie->len); - else - printf("%s: so sad. no real ssid found.\n", __func__); - closed = 1; - } - /*HTC_CSP_END*/ - memset(&ssid, 0, sizeof(wlc_ssid_t)); + memset(&ssid, 0, sizeof(wlc_ssid_t)); memcpy(ssid.SSID, ssid_ie->data, ssid_ie->len); WL_DBG(("SSID is (%s) in Head \n", ssid.SSID)); ssid.SSID_len = ssid_ie->len; @@ -4209,6 +4188,26 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("setting AP mode failed %d \n", err)); return err; } + + /* if requested, do softap ch autoselect */ + if (wl->hostapd_chan == 14) { + int auto_chan; + if ((err = wldev_get_auto_channel(dev, &auto_chan)) != 0) { + WL_ERR(("softap: auto chan select failed," + " will use ch 6\n")); + auto_chan = 6; + } else { + printf("<0>softap: got auto ch:%d\n", auto_chan); + } + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &auto_chan, sizeof(auto_chan), true); + if (err < 0) { + WL_ERR(("softap: WLC_SET_CHANNEL error %d chip" + " may not be supporting this channel\n", err)); + return err; + } + } + /* find the RSN_IE */ if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len, DOT11_MNG_RSN_ID)) != NULL) { @@ -4264,7 +4263,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, memcpy(beacon_ie, wps_ie, wpsie_len); wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, beacon_ie, wpsie_len); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else { @@ -4284,33 +4283,11 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, return err; } } - /*HTC_CSP_START*/ - if (closed) { - err = wldev_ioctl(dev, WLC_SET_CLOSED, &closed, sizeof(closed), true); - if (err) - WL_ERR(("Set hidden ap error, %d\n", err)); - } - /*HTC_CSP_END*/ err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true); if (unlikely(err)) { WL_ERR(("WLC_UP error (%d)\n", err)); return err; } - - /*HTC_CSP_START*/ - /* find the max_assoc */ - max_assoc_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], - info->head_len - ie_offset, - DOT11_MNG_VS_ID + 1); - if (max_assoc_ie != NULL) { - max_assoc = max_assoc_ie->data[0]; - printf("%s: got max_num_sta, max_assoc=%d\n", __func__, max_assoc); - } - err = wldev_iovar_setint(dev, "maxassoc", max_assoc); - if (err) - WL_ERR(("%s fail to set maxassoc, err=(%d)\n", __func__, err)); - /*HTC_CSP_END*/ - memset(&join_params, 0, sizeof(join_params)); /* join parameters starts with ssid */ join_params_size = sizeof(join_params.ssid); @@ -4339,12 +4316,12 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) { WL_DBG((" WPS IE is changed\n")); kfree(wl->ap_info->wps_ie); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } else if (wl->ap_info->wps_ie == NULL) { WL_DBG((" WPS IE is added\n")); - wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); + wl->ap_info->wps_ie = kmemdup(wps_ie, wpsie_len, GFP_KERNEL); /* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */ wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, pbc); } @@ -4426,13 +4403,112 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, } exit: if (err) -#ifdef FORCE_MPC - if (!strstr(firmware_path, "_p2p")) -#endif - wldev_iovar_setint(dev, "mpc", 1); + wldev_iovar_setint(dev, "mpc", 1); return err; } +#ifdef WL_SCHED_SCAN +#define PNO_TIME 30 +#define PNO_REPEAT 4 +#define PNO_FREQ_EXPO_MAX 2 +int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + ushort pno_time = PNO_TIME; + int pno_repeat = PNO_REPEAT; + int pno_freq_expo_max = PNO_FREQ_EXPO_MAX; + wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; + struct wl_priv *wl = wiphy_priv(wiphy); + struct cfg80211_ssid *ssid = NULL; + int ssid_count = 0; + int i; + int ret = 0; + + WL_DBG(("Enter n_match_sets:%d n_ssids:%d \n", + request->n_match_sets, request->n_ssids)); + WL_DBG(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n", + request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max)); + +#if defined(WL_ENABLE_P2P_IF) + /* While GO is operational, PNO is not supported */ + if (dhd_cfg80211_get_opmode(wl) & P2P_GO_ENABLED) { + WL_DBG(("PNO not enabled! op_mode: P2P GO")); + return -1; + } +#endif + + if (!request || !request->n_ssids || !request->n_match_sets) { + WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids)); + return -EINVAL; + } + + memset(&ssids_local, 0, sizeof(ssids_local)); + + if (request->n_match_sets > 0) { + for (i = 0; i < request->n_match_sets; i++) { + ssid = &request->match_sets[i].ssid; + memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len); + ssids_local[i].SSID_len = ssid->ssid_len; + WL_DBG((">>> PNO filter set for ssid (%s) \n", ssid->ssid)); + ssid_count++; + } + } + + if (request->n_ssids > 0) { + for (i = 0; i < request->n_ssids; i++) { + /* Active scan req for ssids */ + WL_DBG((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid)); + + /* match_set ssids is a supert set of n_ssid list, so we need + * not add these set seperately + */ + } + } + + if (ssid_count) { + if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets, + pno_time, pno_repeat, pno_freq_expo_max)) < 0) { + WL_ERR(("PNO setup failed!! ret=%d \n", ret)); + return -EINVAL; + } + + /* Enable the PNO */ + if (dhd_dev_pno_enable(dev, 1) < 0) { + WL_ERR(("PNO enable failed!! ret=%d \n", ret)); + return -EINVAL; + } + wl->sched_scan_req = request; + } else { + return -EINVAL; + } + + return 0; +} + +int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) +{ + struct wl_priv *wl = wiphy_priv(wiphy); + + WL_DBG(("Enter \n")); + + if (dhd_dev_pno_enable(dev, 0) < 0) + WL_ERR(("PNO disable failed")); + + if (dhd_dev_pno_reset(dev) < 0) + WL_ERR(("PNO reset failed")); + + if (wl->scan_request && wl->sched_scan_running) { + wl_notify_escan_complete(wl, dev, true, true); + } + + wl->sched_scan_req = NULL; + wl->sched_scan_running = FALSE; + + return 0; +} +#endif /* WL_SCHED_SCAN */ + static struct cfg80211_ops wl_cfg80211_ops = { .add_virtual_intf = wl_cfg80211_add_virtual_iface, .del_virtual_intf = wl_cfg80211_del_virtual_iface, @@ -4465,6 +4541,10 @@ static struct cfg80211_ops wl_cfg80211_ops = { .set_channel = wl_cfg80211_set_channel, .set_beacon = wl_cfg80211_add_set_beacon, .add_beacon = wl_cfg80211_add_set_beacon, +#ifdef WL_SCHED_SCAN + .sched_scan_start = wl_cfg80211_sched_scan_start, + .sched_scan_stop = wl_cfg80211_sched_scan_stop, +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -4485,86 +4565,62 @@ s32 wl_mode_to_nl80211_iftype(s32 mode) return err; } -static struct wireless_dev *wl_alloc_wdev(struct device *dev) +static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev) { - struct wireless_dev *wdev; s32 err = 0; - wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); - if (unlikely(!wdev)) { - WL_ERR(("Could not allocate wireless device\n")); - return ERR_PTR(-ENOMEM); - } wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv)); if (unlikely(!wdev->wiphy)) { WL_ERR(("Couldn not allocate wiphy device\n")); err = -ENOMEM; - goto wiphy_new_out; + return err; } -#ifdef HTC_KlocWork - if (wdev->wiphy) { -#endif - set_wiphy_dev(wdev->wiphy, dev); - wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX; - /* Report how many SSIDs Driver can support per Scan request */ - wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; - wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; - wdev->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) + set_wiphy_dev(wdev->wiphy, sdiofunc_dev); + wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX; + /* Report how many SSIDs Driver can support per Scan request */ + wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; + wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; +#ifdef WL_SCHED_SCAN + wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX; + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif /* WL_SCHED_SCAN */ + wdev->wiphy->interface_modes = + BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR); - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - wdev->wiphy->cipher_suites = __wl_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); - wdev->wiphy->max_remain_on_channel_duration = 5000; - wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes; + wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; + /* wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - set in runtime */ + wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + wdev->wiphy->cipher_suites = __wl_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); + wdev->wiphy->max_remain_on_channel_duration = 5000; + wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes; #ifndef WL_POWERSAVE_DISABLED - wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; + wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; #else - wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; #endif /* !WL_POWERSAVE_DISABLED */ - wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK | - WIPHY_FLAG_4ADDR_AP | + wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK | + WIPHY_FLAG_4ADDR_AP | #if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39) - WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS | -#endif - WIPHY_FLAG_4ADDR_STATION; - - WL_DBG(("Registering custom regulatory)\n")); - wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; - wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom); - /* Now we can register wiphy with cfg80211 module */ - err = wiphy_register(wdev->wiphy); - if (unlikely(err < 0)) { - WL_ERR(("Couldn not register wiphy device (%d)\n", err)); - goto wiphy_register_out; - } - return wdev; -#ifdef HTC_KlocWork - } else { - WL_ERR(("Couldn not allocate wiphy device\n")); - err = -ENOMEM; - goto wiphy_new_out; - } + WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS | #endif -wiphy_register_out: -#ifdef HTC_KlocWork - if (wdev->wiphy) { + WIPHY_FLAG_4ADDR_STATION; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; #endif + WL_DBG(("Registering custom regulatory)\n")); + wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom); + /* Now we can register wiphy with cfg80211 module */ + err = wiphy_register(wdev->wiphy); + if (unlikely(err < 0)) { + WL_ERR(("Couldn not register wiphy device (%d)\n", err)); wiphy_free(wdev->wiphy); -#ifdef HTC_KlocWork - } else { - WL_ERR(("Couldn not allocate wiphy device\n")); - err = -ENOMEM; } -#endif - -wiphy_new_out: - kfree(wdev); - - return ERR_PTR(err); + return err; } static void wl_free_wdev(struct wl_priv *wl) @@ -4619,8 +4675,6 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) u32 freq; s32 err = 0; - if (wiphy == NULL) - wiphy = wl_to_wiphy(wl); if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { WL_DBG(("Beacon is larger than buffer. Discarding\n")); return err; @@ -4639,8 +4693,13 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; - notif_bss_info->rssi = dtoh16(bi->RSSI); - memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); + if (!band) { + WL_ERR(("No valid band")); + kfree(notif_bss_info); + return -EINVAL; + } + notif_bss_info->rssi = dtoh16(bi->RSSI); + memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); mgmt_type = wl->active_scan ? IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON; if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) { @@ -4661,13 +4720,17 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) u.beacon.variable) + wl_get_ielen(wl); #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(notif_bss_info->channel); - (void)band->band; #else freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band); #endif channel = ieee80211_get_channel(wiphy, freq); + if (!channel) { + WL_ERR(("No valid channel: %u\n", freq)); + kfree(notif_bss_info); + return -EINVAL; + } - WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" + WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM " "mgmt_type %d frame_len %d\n", bi->SSID, notif_bss_info->rssi, notif_bss_info->channel, mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type, @@ -4675,20 +4738,12 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) signal = notif_bss_info->rssi * 100; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE - if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { -#else - if (p2p_is_on(wl) && p2p_scan(wl)) { -#endif - /* find the P2PIE, if we do not find it, we will discard this frame */ - wifi_p2p_ie_t *p2p_ie; - p2p_ie = wl_cfgp2p_find_p2pie((u8 *)beacon_proberesp->variable, - wl_get_ielen(wl)); - if (p2p_ie == NULL) { - WL_ERR(("Couldn't find P2PIE in probe response/beacon\n")); - kfree(notif_bss_info); - return err; - } + if (!mgmt->u.probe_resp.timestamp) { + struct timeval tv; + + do_gettimeofday(&tv); + mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec * 1000000) + + tv.tv_usec; } cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt, @@ -4705,21 +4760,129 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) return err; } +static s32 wl_inform_ibss(struct wl_priv *wl, const u8 *bssid) +{ + struct net_device *ndev = wl_to_prmry_ndev(wl); + struct wiphy *wiphy = wl_to_wiphy(wl); + struct wl_bss_info *bi = NULL; + struct ieee80211_channel *notify_channel; + struct ieee80211_supported_band *band; + struct cfg80211_bss *bss; + s32 err = 0; + u16 channel; + u32 freq; + u32 wsec = 0; + u16 notify_capability; + u16 notify_interval; + u8 *notify_ie; + size_t notify_ielen; + s32 notify_signal; + + WL_TRACE(("Enter\n")); + + if (wl->scan_request) { + wl_notify_escan_complete(wl, ndev, true, true); + } + + mutex_lock(&wl->usr_sync); + + *(u32 *)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); + err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, wl->extra_buf, + WL_EXTRA_BUF_MAX, false); + if (err) { + WL_ERR(("Failed to get bss info for IBSS\n")); + err = -EIO; + goto CleanUp; + } + bi = (struct wl_bss_info *)(wl->extra_buf + 4); + + if (memcmp(bssid, &bi->BSSID, ETHER_ADDR_LEN)) { + WL_ERR(("BSSID mismatch: Inform %02x:%02x:%02x:%02x:%02x:%02x," + "%02x:%02x:%02x:%02x:%02x:%02x\n", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5], + bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], + bi->BSSID.octet[3], bi->BSSID.octet[4], + bi->BSSID.octet[5])); + err = -EINVAL; + goto CleanUp; + } + + err = wldev_iovar_getint(ndev, "wsec", &wsec); + if (err) { + WL_ERR(("wsec failed: %d\n", err)); + err = -EIO; + goto CleanUp; + } + + channel = bi->ctl_ch ? bi->ctl_ch : + CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); + (void)band->band; +#else + freq = ieee80211_channel_to_frequency(channel, band->band); +#endif + notify_channel = ieee80211_get_channel(wiphy, freq); + + notify_capability = dtoh16(bi->capability); + notify_interval = dtoh16(bi->beacon_period); + notify_ie = (u8 *)bi + dtoh16(bi->ie_offset); + notify_ielen = dtoh32(bi->ie_length); + notify_signal = (int16)dtoh16(bi->RSSI) * 100; + + if (wl->p2p_supported) { + notify_capability |= DOT11_CAP_IBSS; + if (wsec) + notify_capability |= DOT11_CAP_PRIVACY; + } + + WL_DBG(("BSSID %02x:%02x:%02x:%02x:%02x:%02x", + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5])); + WL_INFO(("channel: %d(%d)\n", channel, freq)); + WL_INFO(("capability: %X\n", notify_capability)); + WL_INFO(("beacon interval: %d ms\n", notify_interval)); + WL_INFO(("signal: %d dBm\n", notify_signal)); + WL_INFO(("ie_len: %d\n", notify_ielen)); + bss = cfg80211_inform_bss(wiphy, notify_channel, bssid, 0, + notify_capability, notify_interval, + notify_ie, notify_ielen, notify_signal, GFP_KERNEL); + if (!bss) { + WL_ERR(("cfg80211_inform_bss() Failed\n")); + err = -ENOMEM; + goto CleanUp; + } + + cfg80211_put_bss(bss); + err = 0; + +CleanUp: + + mutex_unlock(&wl->usr_sync); + + WL_TRACE(("Exit\n")); + return err; +} + static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev) { u32 event = ntoh32(e->event_type); u32 status = ntoh32(e->status); u16 flags = ntoh16(e->flags); - WL_DBG(("event %d, status %d\n", event, status)); + WL_DBG(("event %d, status %d flags %x\n", event, status, flags)); if (event == WLC_E_SET_SSID) { if (status == WLC_E_STATUS_SUCCESS) { - if (!wl_is_ibssmode(wl, ndev)) - return true; + return true; } } else if (event == WLC_E_LINK) { if (flags & WLC_EVENT_MSG_LINK) - return true; + if (!wl_is_ibssmode(wl, ndev)) + return true; } WL_DBG(("wl_is_linkup false\n")); @@ -4757,165 +4920,230 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e) return false; } +/* The mainline kernel >= 3.2.0 has support for indicating new/del station + * to AP/P2P GO via events. If this change is backported to kernel for which + * this driver is being built, then define WL_CFG80211_STA_EVENT. You + * should use this new/del sta event mechanism for BRCM supplicant >= 22. + */ static s32 -wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, +wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) { - bool act; - bool isfree = false; s32 err = 0; - s32 freq; - s32 channel; - u8 body[200]; u32 event = ntoh32(e->event_type); u32 reason = ntoh32(e->reason); u32 len = ntoh32(e->datalen); - u16 fc = 0; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) + bool isfree = false; u8 *mgmt_frame; u8 bsscfgidx = e->bsscfgidx; + s32 freq; + s32 channel; + u8 body[WL_FRAME_LEN]; + u16 fc = 0; struct ieee80211_supported_band *band; struct ether_addr da; struct ether_addr bssid; struct wiphy *wiphy = wl_to_wiphy(wl); channel_info_t ci; +#else + struct station_info sinfo; +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */ + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) memset(body, 0, sizeof(body)); memset(&bssid, 0, ETHER_ADDR_LEN); - WL_DBG(("Enter \n")); + WL_DBG(("Enter event %d ndev %p\n", event, ndev)); if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) return WL_INVALID; - if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { - memcpy(body, data, len); - wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", - NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); - memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); - err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); - switch (event) { - case WLC_E_ASSOC_IND: - fc = FC_ASSOC_REQ; - break; - case WLC_E_REASSOC_IND: - fc = FC_REASSOC_REQ; - break; - case WLC_E_DISASSOC_IND: - fc = FC_DISASSOC; - break; - case WLC_E_DEAUTH_IND: - fc = FC_DISASSOC; - break; - case WLC_E_DEAUTH: - fc = FC_DISASSOC; - break; - default: - fc = 0; - goto exit; - } - if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) - return err; - - channel = dtoh32(ci.hw_channel); - if (channel <= CH_MAX_2G_CHANNEL) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (len > WL_FRAME_LEN) { + WL_ERR(("Received frame length %d from dongle is greater than" + " allocated body buffer len %d", len, WL_FRAME_LEN)); + goto exit; + } + memcpy(body, data, len); + wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr", + NULL, 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bsscfgidx, &wl->ioctl_buf_sync); + memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); + err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + switch (event) { + case WLC_E_ASSOC_IND: + fc = FC_ASSOC_REQ; + break; + case WLC_E_REASSOC_IND: + fc = FC_REASSOC_REQ; + break; + case WLC_E_DISASSOC_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH_IND: + fc = FC_DISASSOC; + break; + case WLC_E_DEAUTH: + fc = FC_DISASSOC; + break; + default: + fc = 0; + goto exit; + } + if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) + return err; + channel = dtoh32(ci.hw_channel); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (!band) { + WL_ERR(("No valid band")); + return -EINVAL; + } #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) - freq = ieee80211_channel_to_frequency(channel); - (void)band->band; + freq = ieee80211_channel_to_frequency(channel); #else - freq = ieee80211_channel_to_frequency(channel, band->band); + freq = ieee80211_channel_to_frequency(channel, band->band); #endif - err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, + err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid, &mgmt_frame, &len, body); - if (err < 0) - goto exit; - isfree = true; + if (err < 0) + goto exit; + isfree = true; + + if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } else if (event == WLC_E_DISASSOC_IND) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { + cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); + } - if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); - } else if (event == WLC_E_DISASSOC_IND) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); - } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { - cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); +exit: + if (isfree) + kfree(mgmt_frame); + return err; +#else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ + sinfo.filled = 0; + if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) && + reason == DOT11_SC_SUCCESS) { + sinfo.filled = STATION_INFO_ASSOC_REQ_IES; + if (!data) { + WL_ERR(("No IEs present in ASSOC/REASSOC_IND")); + return -EINVAL; } + sinfo.assoc_req_ies = data; + sinfo.assoc_req_ies_len = len; + cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC); + } else if (event == WLC_E_DISASSOC_IND) { + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { + cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC); + } +#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) && !WL_CFG80211_STA_EVENT */ + return err; +} +static s32 +wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + bool act; + s32 err = 0; + u32 event = ntoh32(e->event_type); + u32 reason; + + if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { + wl_notify_connect_status_ap(wl, ndev, e, data); } else { - WL_DBG(("wl_notify_connect_status : event %d status : %d \n", - ntoh32(e->event_type), ntoh32(e->status))); + WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n", + ntoh32(e->event_type), ntoh32(e->status), ndev)); + if((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DISASSOC_IND)) { + reason = ntoh32(e->reason); + wl->deauth_reason = reason; + WL_ERR(("Received %s event with reason code: %d\n", + (event == WLC_E_DEAUTH_IND)? + "WLC_E_DEAUTH_IND":"WLC_E_DISASSOC_IND", reason)); + } if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); act = true; wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT); wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID); + wl->deauth_reason = 0; if (wl_is_ibssmode(wl, ndev)) { - printk("cfg80211_ibss_joined\n"); - cfg80211_ibss_joined(ndev, (s8 *)&e->addr, - GFP_KERNEL); - WL_DBG(("joined in IBSS network\n")); + wl_ibss_join_done(wl, ndev, e, data, true); + WL_DBG(("wl_ibss_join_done succeeded\n")); } else { if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { - printf("wl_bss_connect_done succeeded\n"); + printk("wl_bss_connect_done succeeded\n"); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID)); } } - } else if (wl_is_linkdown(wl, e)) { if (wl->scan_request) { - del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, ndev, true); - } else + wl_notify_escan_complete(wl, ndev, true, true); + } else { + del_timer_sync(&wl->scan_timeout); wl_iscan_aborted(wl); + } } if (wl_get_drv_status(wl, CONNECTED, ndev)) { scb_val_t scbval; u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - printk("link down, call cfg80211_disconnected\n"); wl_clr_drv_status(wl, CONNECTED, ndev); - /* To make sure disconnect, explictly send dissassoc - * for BSSID 00:00:00:00:00:00 issue - */ - scbval.val = WLAN_REASON_DEAUTH_LEAVING; - - memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); - scbval.val = htod32(scbval.val); - wldev_ioctl(ndev, WLC_DISASSOC, &scbval, - sizeof(scb_val_t), true); - cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - wl_link_down(wl); - wl_init_prof(wl, ndev); - } else if (wl_get_drv_status(wl, CONNECTING, ndev)) { - printf("link down, during connecting\n"); - wl_bss_connect_done(wl, ndev, e, data, false); + if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) { + /* To make sure disconnect, explictly send dissassoc + * for BSSID 00:00:00:00:00:00 issue + */ + scbval.val = WLAN_REASON_DEAUTH_LEAVING; + + memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN); + scbval.val = htod32(scbval.val); + wldev_ioctl(ndev, WLC_DISASSOC, &scbval, + sizeof(scb_val_t), true); + WL_ERR(("link down, calling cfg80211_disconnected" + " with deauth_reason:%d\n", wl->deauth_reason)); + if (!wl_is_ibssmode(wl, ndev)) + cfg80211_disconnected(ndev, wl->deauth_reason, + NULL, 0, GFP_KERNEL); + wl_link_down(wl); + wl_init_prof(wl, ndev); + } + } + else if (wl_get_drv_status(wl, CONNECTING, ndev)) { + printk("link down, during connecting\n"); + if (wl_is_ibssmode(wl, ndev)) + wl_ibss_join_done(wl, ndev, e, data, false); + else + wl_bss_connect_done(wl, ndev, e, data, false); } wl_clr_drv_status(wl, DISCONNECTING, ndev); } else if (wl_is_nonetwork(wl, e)) { - printf("connect failed event=%d e->status 0x%x\n", + printk("connect failed event=%d e->status 0x%x\n", event, (int)ntoh32(e->status)); /* Clean up any pending scan request */ if (wl->scan_request) { - del_timer_sync(&wl->scan_timeout); if (wl->escan_on) { - wl_notify_escan_complete(wl, ndev, true); - } else + wl_notify_escan_complete(wl, ndev, true, true); + } else { + del_timer_sync(&wl->scan_timeout); wl_iscan_aborted(wl); + } } if (wl_get_drv_status(wl, CONNECTING, ndev)) wl_bss_connect_done(wl, ndev, e, data, false); } else { - printf("%s nothing\n", __FUNCTION__); + printk("%s nothing\n", __FUNCTION__); } } -exit: - if (isfree) - kfree(mgmt_frame); return err; } @@ -5092,18 +5320,11 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) ie_len = bi->ie_length; beacon_interval = cpu_to_le16(bi->beacon_period); } else { -#ifdef HTC_KlocWork - if (bss) { -#endif - WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); - ie = bss->information_elements; - ie_len = bss->len_information_elements; - beacon_interval = bss->beacon_interval; - cfg80211_put_bss(bss); - } else { - WL_DBG(("Could not find the AP\n")); - goto update_bss_info_out; - } + WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid)); + ie = bss->information_elements; + ie_len = bss->len_information_elements; + beacon_interval = bss->beacon_interval; + cfg80211_put_bss(bss); } tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM); @@ -5139,19 +5360,11 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, s32 err = 0; u8 *curbssid; - WL_DBG(("Enter %s\n", __func__)); wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); - - if (ap_resp_ie_len) { - /* hacked ap_resp_ie to conn_info->resp_ie */ - memcpy(conn_info->resp_ie, ap_resp_ie, ap_resp_ie_len); - conn_info->resp_ie_len = ap_resp_ie_len; - } - cfg80211_roamed(ndev, #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) NULL, @@ -5176,7 +5389,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, WL_DBG((" enter\n")); if (wl->scan_request) { - wl_cfg80211_scan_abort(wl, ndev); + wl_notify_escan_complete(wl, ndev, true, true); } if (wl_get_drv_status(wl, CONNECTING, ndev)) { wl_clr_drv_status(wl, CONNECTING, ndev); @@ -5204,6 +5417,35 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, return err; } +static s32 +wl_ibss_join_done(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data, bool completed) +{ + s32 err = 0; + + WL_TRACE(("Enter\n")); + + if (wl->scan_request) { + wl_notify_escan_complete(wl, ndev, true, true); + } + if (wl_get_drv_status(wl, CONNECTING, ndev)) { + wl_clr_drv_status(wl, CONNECTING, ndev); + if (completed) { + err = wl_inform_ibss(wl, (u8 *)&e->addr); + if (err) { + WL_ERR(("wl_inform_ibss() failed: %d\n", err)); + } + wl_set_drv_status(wl, CONNECTED, ndev); + + cfg80211_ibss_joined(ndev, (u8 *)&e->addr, GFP_KERNEL); + WL_DBG(("cfg80211_ibss_joined() called with valid BSSID\n")); + } + } + + WL_TRACE(("Exit\n")); + return err; +} + static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -5224,6 +5466,28 @@ wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, return 0; } +#ifdef PNO_SUPPORT +static s32 +wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + WL_ERR((" PNO Event\n")); + + mutex_lock(&wl->usr_sync); +#ifndef WL_SCHED_SCAN + /* TODO: Use cfg80211_sched_scan_results(wiphy); */ + cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); +#else + /* If cfg80211 scheduled scan is supported, report the pno results via sched + * scan results + */ + wl_notify_sched_scan_results(wl, ndev, e, data); +#endif /* WL_SCHED_SCAN */ + mutex_unlock(&wl->usr_sync); + return 0; +} +#endif /* PNO_SUPPORT */ + static s32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data) @@ -5270,7 +5534,6 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, bss_list->version = dtoh32(bss_list->version); bss_list->count = dtoh32(bss_list->count); - printf("scan count = %d\n", bss_list->count); err = wl_inform_bss(wl); scan_done_out: @@ -5338,7 +5601,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, s32 err = 0; s32 freq; struct net_device *dev = NULL; - wifi_p2p_pub_act_frame_t *act_frm; + wifi_p2p_pub_act_frame_t *act_frm = NULL; + wifi_p2p_action_frame_t *p2p_act_frm = NULL; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL; wl_event_rx_frame_data_t *rxframe = (wl_event_rx_frame_data_t*)data; u32 event = ntoh32(e->event_type); @@ -5359,10 +5624,19 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, band = wiphy->bands[IEEE80211_BAND_2GHZ]; else band = wiphy->bands[IEEE80211_BAND_5GHZ]; + if (!band) { + WL_ERR(("No valid band")); + return -EINVAL; + } + + if ((event == WLC_E_P2P_PROBREQ_MSG) && + wl->p2p && wl_get_p2p_status(wl, GO_NEG_PHASE)) { + WL_DBG(("Filtering P2P probe_req while being in GO-Neg state\n")); + goto exit; + } #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) freq = ieee80211_channel_to_frequency(channel); - (void)band->band; #else freq = ieee80211_channel_to_frequency(channel, band->band); #endif @@ -5381,17 +5655,41 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, goto exit; } isfree = true; - act_frm = - (wifi_p2p_pub_act_frame_t *) (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + act_frm = (wifi_p2p_pub_act_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + p2p_act_frm = (wifi_p2p_action_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + (void) p2p_act_frm; + } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) + (&mgmt_frame[DOT11_MGMT_HDR_LEN]); + (void) sd_act_frm; + } + wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN], + mgmt_frame_len - DOT11_MGMT_HDR_LEN); /* * After complete GO Negotiation, roll back to mpc mode */ - if ((act_frm->subtype == P2P_PAF_GON_CONF) || - (act_frm->subtype == P2P_PAF_PROVDIS_RSP)) { -#ifdef FORCE_MPC - if (!strstr(firmware_path, "_p2p")) -#endif - wldev_iovar_setint(dev, "mpc", 1); + if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) || + (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) { + wldev_iovar_setint(dev, "mpc", 1); + } + + if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) { + WL_DBG(("P2P: GO_NEG_PHASE status cleared \n")); + wl_clr_p2p_status(wl, GO_NEG_PHASE); + } + + if (act_frm && (act_frm->subtype == P2P_PAF_GON_RSP)) { + /* Cancel the dwell time of req frame */ + WL_DBG(("P2P: Received GO NEG Resp frame, cancelling the dwell time\n")); + wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); } } else { mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1); @@ -5408,6 +5706,119 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, return 0; } +#ifdef WL_SCHED_SCAN +/* If target scan is not reliable, set the below define to "1" to do a + * full escan + */ +#define FULL_ESCAN_ON_PFN_NET_FOUND 0 +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + wl_pfn_net_info_t *netinfo, *pnetinfo; + struct cfg80211_scan_request request; + struct wiphy *wiphy = wl_to_wiphy(wl); + int err = 0; + struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT]; + struct ieee80211_channel *channel = NULL; + int channel_req = 0; + int band = 0; + struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data; + + WL_DBG(("Enter\n")); + + if (e->event_type == WLC_E_PFN_NET_LOST) { + WL_DBG(("PFN NET LOST event. Do Nothing \n")); + return 0; + } + WL_DBG(("PFN NET FOUND event. count:%d \n", pfn_result->count)); + if (pfn_result->count > 0) { + int i; + + memset(&request, 0x00, sizeof(struct cfg80211_scan_request)); + memset(&ssid, 0x00, sizeof(ssid)); + request.wiphy = wiphy; + + pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) + - sizeof(wl_pfn_net_info_t)); + channel = (struct ieee80211_channel *)kzalloc( + (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), + GFP_KERNEL); + if (!channel) { + WL_ERR(("No memory")); + err = -ENOMEM; + goto out_err; + } + + for (i = 0; i < pfn_result->count; i++) { + netinfo = &pnetinfo[i]; + if (!netinfo) { + WL_ERR(("Invalid netinfo ptr. index:%d", i)); + err = -EINVAL; + goto out_err; + } + WL_DBG(("SSID:%s Channel:%d \n", + netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel)); + /* PFN result doesn't have all the info which are required by the supplicant + * (For e.g IEs) Do a target Escan so that sched scan results are reported + * via wl_inform_single_bss in the required format. Escan does require the + * scan request in the form of cfg80211_scan_request. For timebeing, create + * cfg80211_scan_request one out of the received PNO event. + */ + memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, + netinfo->pfnsubnet.SSID_len); + ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len; + request.n_ssids++; + + channel_req = netinfo->pfnsubnet.channel; + band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ + : NL80211_BAND_5GHZ; + channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); + channel[i].band = band; + channel[i].flags |= IEEE80211_CHAN_NO_HT40; + request.channels[i] = &channel[i]; + request.n_channels++; + } + + /* assign parsed ssid array */ + if (request.n_ssids) + request.ssids = &ssid[0]; + + if (wl_get_drv_status_all(wl, SCANNING)) { + /* Abort any on-going scan */ + wl_notify_escan_complete(wl, ndev, true, true); + } + + if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + err = wl_cfgp2p_discover_enable_search(wl, false); + if (unlikely(err)) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + } + + wl_set_drv_status(wl, SCANNING, ndev); +#if FULL_ESCAN_ON_PFN_NET_FOUND + err = wl_do_escan(wl, wiphy, ndev, NULL); +#else + err = wl_do_escan(wl, wiphy, ndev, &request); +#endif + if (err) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + wl->sched_scan_running = TRUE; + } + else { + WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); + } +out_err: + if (channel) + kfree(channel); + return err; +} +#endif /* WL_SCHED_SCAN */ + static void wl_init_conf(struct wl_conf *conf) { WL_DBG(("Enter \n")); @@ -5433,7 +5844,6 @@ static void wl_init_event_handler(struct wl_priv *wl) memset(wl->evt_handler, 0, sizeof(wl->evt_handler)); wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status; - /* wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status; */ wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status; wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status; wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status; @@ -5449,22 +5859,14 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; - +#ifdef PNO_SUPPORT + wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; +#endif /* PNO_SUPPORT */ } static s32 wl_init_priv_mem(struct wl_priv *wl) { WL_DBG(("Enter \n")); - wl->scan_results = NULL; - wl->conf = NULL; - wl->scan_req_int = NULL; - wl->ioctl_buf = NULL; - wl->escan_ioctl_buf = NULL; - wl->extra_buf = NULL; - wl->iscan = NULL; - wl->pmk_list = NULL; - wl->sta_info = NULL; - wl->afx_hdl = NULL; wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); if (unlikely(!wl->scan_results)) { WL_ERR(("Scan results alloc failed\n")); @@ -5529,42 +5931,24 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) static void wl_deinit_priv_mem(struct wl_priv *wl) { - if (wl->scan_results) { - kfree(wl->scan_results); - wl->scan_results = NULL; - } - if (wl->conf) { - kfree(wl->conf); - wl->conf = NULL; - } - if (wl->scan_req_int) { - kfree(wl->scan_req_int); - wl->scan_req_int = NULL; - } - if (wl->ioctl_buf) { - kfree(wl->ioctl_buf); - wl->ioctl_buf = NULL; - } - if (wl->escan_ioctl_buf) { - kfree(wl->escan_ioctl_buf); - wl->escan_ioctl_buf = NULL; - } - if (wl->extra_buf) { - kfree(wl->extra_buf); - wl->extra_buf = NULL; - } - if (wl->iscan) { - kfree(wl->iscan); - wl->iscan = NULL; - } - if (wl->pmk_list) { - kfree(wl->pmk_list); - wl->pmk_list = NULL; - } - if (wl->sta_info) { - kfree(wl->sta_info); - wl->sta_info = NULL; - } + kfree(wl->scan_results); + wl->scan_results = NULL; + kfree(wl->conf); + wl->conf = NULL; + kfree(wl->scan_req_int); + wl->scan_req_int = NULL; + kfree(wl->ioctl_buf); + wl->ioctl_buf = NULL; + kfree(wl->escan_ioctl_buf); + wl->escan_ioctl_buf = NULL; + kfree(wl->extra_buf); + wl->extra_buf = NULL; + kfree(wl->iscan); + wl->iscan = NULL; + kfree(wl->pmk_list); + wl->pmk_list = NULL; + kfree(wl->sta_info); + wl->sta_info = NULL; if (wl->afx_hdl) { cancel_work_sync(&wl->afx_hdl->work); kfree(wl->afx_hdl); @@ -5620,6 +6004,7 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) unsigned long flags; WL_DBG(("Enter \n")); + wl->scan_busy_count = 0; if (!wl_get_drv_status(wl, SCANNING, ndev)) { wl_clr_drv_status(wl, SCANNING, ndev); WL_ERR(("Scan complete while device not scanning\n")); @@ -5703,7 +6088,7 @@ static s32 wl_iscan_pending(struct wl_priv *wl) s32 err = 0; /* Reschedule the timer */ - mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; return err; @@ -5719,7 +6104,7 @@ static s32 wl_iscan_inprogress(struct wl_priv *wl) wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); mutex_unlock(&wl->usr_sync); /* Reschedule the timer */ - mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; return err; @@ -5779,11 +6164,12 @@ static void wl_scan_timeout(unsigned long data) if (wl->scan_request) { WL_ERR(("timer expired\n")); if (wl->escan_on) - wl_notify_escan_complete(wl, wl->escan_info.ndev, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, false); else wl_notify_iscan_complete(wl_to_iscan(wl), true); } } + static void wl_iscan_timer(unsigned long data) { struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; @@ -5834,36 +6220,100 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, struct wl_priv *wl = wlcfg_drv_priv; WL_DBG(("Enter \n")); - if (!wdev || dev == wl_to_prmry_ndev(wl)) + if (!wdev || !wl || dev == wl_to_prmry_ndev(wl)) return NOTIFY_DONE; switch (state) { case NETDEV_UNREGISTER: - /* after calling list_del_rcu(&wdev->list) */ - wl_dealloc_netinfo(wl, ndev); - break; + /* after calling list_del_rcu(&wdev->list) */ + wl_dealloc_netinfo(wl, ndev); + break; + case NETDEV_GOING_DOWN: + /* At NETDEV_DOWN state, wdev_cleanup_work work will be called. + * In front of door, the function checks + * whether current scan is working or not. + * If the scanning is still working, wdev_cleanup_work call WARN_ON and + * make the scan done forcibly. + */ + if (wl_get_drv_status(wl, SCANNING, dev)) { + if (wl->escan_on) { + wl_notify_escan_complete(wl, dev, true, true); + } + } + break; } return NOTIFY_DONE; } static struct notifier_block wl_cfg80211_netdev_notifier = { .notifier_call = wl_cfg80211_netdev_notifier_call, }; -static void wl_notify_escan_complete(struct wl_priv *wl, + +static s32 wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, - bool aborted) + bool aborted, bool fw_abort) { + wl_scan_params_t *params = NULL; + s32 params_size = 0; + s32 err = BCME_OK; unsigned long flags; + struct net_device *dev; WL_DBG(("Enter \n")); - wl_clr_drv_status(wl, SCANNING, ndev); - if (p2p_is_on(wl)) - wl_clr_p2p_status(wl, SCANNING); + wl->scan_busy_count = 0; + if (wl->scan_request) { + if (wl->scan_request->dev == wl->p2p_net) + dev = wl_to_prmry_ndev(wl); + else + dev = wl->scan_request->dev; + } + else { + WL_ERR(("wl->scan_request is NULL may be internal scan." + "doing scan_abort for ndev %p primary %p p2p_net %p", + ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); + dev = ndev; + } + if (fw_abort && !in_atomic()) { + /* Our scan params only need space for 1 channel and 0 ssids */ + params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); + if (params == NULL) { + WL_ERR(("scan params allocation failed \n")); + err = -ENOMEM; + } else { + /* Do a scan abort to stop the driver's scan engine */ + err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); + if (err < 0) { + WL_ERR(("scan abort failed \n")); + } + } + } + if (timer_pending(&wl->scan_timeout)) + del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); + +#ifdef WL_SCHED_SCAN + if (wl->sched_scan_req && !wl->scan_request) { + WL_DBG((" REPORTING SCHED SCAN RESULTS \n")); + if (aborted) + cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); + else + cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); + wl->sched_scan_running = FALSE; + wl->sched_scan_req = NULL; + } +#endif /* WL_SCHED_SCAN */ + if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; } + if (p2p_is_on(wl)) + wl_clr_p2p_status(wl, SCANNING); + wl_clr_drv_status(wl, SCANNING, dev); spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); + if (params) + kfree(params); + + return err; } static s32 wl_escan_handler(struct wl_priv *wl, @@ -5878,8 +6328,8 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_scan_results_t *list; u32 bi_length; u32 i; + wifi_p2p_ie_t * p2p_ie; u8 *p2p_dev_addr = NULL; - WL_DBG((" enter event type : %d, status : %d \n", ntoh32(e->event_type), ntoh32(e->status))); /* P2P SCAN is coming from primary interface */ @@ -5919,12 +6369,20 @@ static s32 wl_escan_handler(struct wl_priv *wl, goto exit; } + if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { + if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { + WL_DBG(("Ignoring IBSS result\n")); + goto exit; + } + } + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); if (p2p_dev_addr && !memcmp(p2p_dev_addr, wl->afx_hdl->pending_tx_dst_addr.octet, ETHER_ADDR_LEN)) { s32 channel = CHSPEC_CHANNEL(dtohchanspec(bi->chanspec)); - WL_DBG(("ACTION FRAME SCAN : Peer found, channel : %d\n", channel)); + WL_DBG(("ACTION FRAME SCAN : Peer " MACSTR " found, channel : %d\n", + MAC2STR(wl->afx_hdl->pending_tx_dst_addr.octet), channel)); wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -5937,6 +6395,22 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_ERR(("Buffer is too small: ignoring\n")); goto exit; } +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) + if (wl->p2p_net && wl->scan_request && + wl->scan_request->dev == wl->p2p_net) { +#else + if (p2p_is_on(wl) && p2p_scan(wl)) { +#endif + /* p2p scan && allow only probe response */ + if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) + goto exit; + if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, + bi->ie_length)) == NULL) { + WL_ERR(("Couldn't find P2PIE in probe" + " response/beacon\n")); + goto exit; + } + } #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -5980,13 +6454,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN COMPLETED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, false); + wl_notify_escan_complete(wl, ndev, false, false); mutex_unlock(&wl->usr_sync); } } @@ -5998,13 +6471,12 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_p2p_status(wl, SCANNING); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); WL_INFO(("ESCAN ABORTED\n")); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); mutex_unlock(&wl->usr_sync); } } @@ -6017,12 +6489,11 @@ static s32 wl_escan_handler(struct wl_priv *wl, wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { mutex_lock(&wl->usr_sync); - del_timer_sync(&wl->scan_timeout); wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; wl_inform_bss(wl); - wl_notify_escan_complete(wl, ndev, true); + wl_notify_escan_complete(wl, ndev, true, false); mutex_unlock(&wl->usr_sync); } } @@ -6073,40 +6544,30 @@ static s32 wl_init_priv(struct wl_priv *wl) wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); wl->iscan_on = false; wl->escan_on = true; - wl->roam_on = true; + wl->roam_on = false; wl->iscan_kickstart = false; wl->active_scan = true; wl->rf_blocked = false; + wl->deauth_reason = 0; spin_lock_init(&wl->cfgdrv_lock); mutex_init(&wl->ioctl_buf_sync); init_waitqueue_head(&wl->netif_change_event); wl_init_eq(wl); err = wl_init_priv_mem(wl); if (err) - goto wl_init_priv_fail; - if (wl_create_event_handler(wl)) { - err = -ENOMEM; - goto wl_init_priv_fail1; - } + return err; + if (wl_create_event_handler(wl)) + return -ENOMEM; wl_init_event_handler(wl); mutex_init(&wl->usr_sync); err = wl_init_scan(wl); if (err) - goto wl_init_priv_fail2; + return err; wl_init_conf(wl->conf); wl_init_prof(wl, ndev); wl_link_down(wl); DNGL_FUNC(dhd_cfg80211_init, (wl)); - return err; - -wl_init_priv_fail2: - wl_destroy_event_handler(wl); -wl_init_priv_fail1: - wl_deinit_priv_mem(wl); -wl_init_priv_fail: - wl_flush_eq(wl); - return err; } @@ -6122,7 +6583,7 @@ static void wl_deinit_priv(struct wl_priv *wl) unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); } -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) static s32 wl_cfg80211_attach_p2p(void) { struct wl_priv *wl = wlcfg_drv_priv; @@ -6157,7 +6618,7 @@ static s32 wl_cfg80211_detach_p2p(void) return 0; } -#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ +#endif /* defined(WLP2P) && defined(WL_ENABLE_P2P_IF) */ s32 wl_cfg80211_attach_post(struct net_device *ndev) { @@ -6172,25 +6633,27 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) if (wl && !wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { +#if !defined(WL_ENABLE_P2P_IF) wl->wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO)); +#endif if ((err = wl_cfgp2p_init_priv(wl)) != 0) goto fail; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) if (wl->p2p_net) { /* Update MAC addr for p2p0 interface here. */ memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN); wl->p2p_net->dev_addr[0] |= 0x02; - printf("%s: p2p_dev_addr="MACSTR "\n", + printk("%s: p2p_dev_addr="MACSTR "\n", wl->p2p_net->name, MAC2STR(wl->p2p_net->dev_addr)); } else { WL_ERR(("p2p_net not yet populated." " Couldn't update the MAC Address for p2p0 \n")); return -ENODEV; } -#endif /* defined(WLP2P) && (ENABLE_P2P_INTERFACE) */ +#endif /* defined(WLP2P) && (WL_ENABLE_P2P_IF) */ wl->p2p_supported = true; } @@ -6215,8 +6678,15 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) } WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev())); dev = wl_cfg80211_get_parent_dev(); - wdev = wl_alloc_wdev(dev); - if (IS_ERR(wdev)) { + + wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); + if (unlikely(!wdev)) { + WL_ERR(("Could not allocate wireless device\n")); + return -ENOMEM; + } + err = wl_setup_wiphy(wdev, dev); + if (unlikely(err)) { + kfree(wdev); return -ENOMEM; } wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); @@ -6246,35 +6716,25 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier); if (err) { WL_ERR(("Failed to register notifierl %d\n", err)); - goto cfg80211_attach_out1; + goto cfg80211_attach_out; } #if defined(COEX_DHCP) if (wl_cfg80211_btcoex_init(wl)) - goto cfg80211_attach_out2; -#endif /* COEX_DHCP */ + goto cfg80211_attach_out; +#endif wlcfg_drv_priv = wl; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) err = wl_cfg80211_attach_p2p(); if (err) - goto cfg80211_attach_out3; + goto cfg80211_attach_out; #endif return err; -#if defined(WLP2P) && ENABLE_P2P_INTERFACE -cfg80211_attach_out3: -#endif -#if defined(COEX_DHCP) - wl_cfg80211_btcoex_deinit(wl); -cfg80211_attach_out2: -#endif - unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier); -cfg80211_attach_out1: - wl_setup_rfkill(wl, FALSE); - cfg80211_attach_out: + err = wl_setup_rfkill(wl, FALSE); wl_free_wdev(wl); return err; } @@ -6283,16 +6743,15 @@ void wl_cfg80211_detach(void *para) { struct wl_priv *wl; - (void)para; wl = wlcfg_drv_priv; WL_TRACE(("In\n")); #if defined(COEX_DHCP) wl_cfg80211_btcoex_deinit(wl); -#endif +#endif -#if defined(WLP2P) && ENABLE_P2P_INTERFACE +#if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) wl_cfg80211_detach_p2p(); #endif wl_setup_rfkill(wl, FALSE); @@ -6359,6 +6818,7 @@ static s32 wl_event_handler(void *data) tsk_ctl_t *tsk = (tsk_ctl_t *)data; wl = (struct wl_priv *)tsk->parent; + DAEMONIZE("dhd_cfg80211_event"); complete(&tsk->completed); while (down_interruptible (&tsk->sema) == 0) { @@ -6371,11 +6831,11 @@ static s32 wl_event_handler(void *data) * there is no corresponding bsscfg for P2P interface. Map it to p2p0 * interface. */ - if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) + if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) { netdev = wl->p2p_net; - else + } else { netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx); - + } if (!netdev) netdev = wl_to_prmry_ndev(wl); if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) { @@ -6387,104 +6847,15 @@ static s32 wl_event_handler(void *data) } DHD_OS_WAKE_UNLOCK(wl->pub); } - WL_DBG(("%s was terminated\n", __func__)); + WL_ERR(("%s was terminated\n", __func__)); complete_and_exit(&tsk->completed, 0); return 0; } -static void wl_cfg80211_send_priv_event -( - struct net_device *dev, - char *flag -) -{ -#if defined(CONFIG_WIRELESS_EXT) - wl_iw_send_priv_event(dev, flag); -#endif - return; -} -#if defined(SOFTAP) -static void wl_cfg80211_hotspot_event_process(struct net_device *ndev, const wl_event_msg_t *e, void *data) -{ - u32 event_type = ntoh32(e->event_type); - uint16 flags = ntoh16(e->flags); - uint32 datalen = ntoh32(e->datalen); - uint32 status = ntoh32(e->status); - - switch (event_type) { - case WLC_E_PRUNE: - { - char *macaddr = (char *)&e->addr; - char mac_buf[32] = {0}; - WL_INFO(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n", - macaddr[0], macaddr[1], macaddr[2], macaddr[3], - macaddr[4], macaddr[5])); - - if (status) { - printf("reach max!!\n"); - break; - } - - if (wl_android_black_list_match(macaddr)) { - printf("STA block\n"); - sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - wl_iw_send_priv_event(ndev, mac_buf); - } - } - break; - case WLC_E_JOIN: - case WLC_E_ASSOC_IND: - case WLC_E_REASSOC_IND: - printf("STA connect received %d\n", event_type); - wl_cfg80211_send_priv_event(ndev, "STA_JOIN"); - break; - case WLC_E_DEAUTH_IND: - case WLC_E_DISASSOC_IND: - printf("STA disconnect received %d\n", event_type); - wl_cfg80211_send_priv_event(ndev, "STA_LEAVE"); - break; - case WLC_E_LINK: - case WLC_E_NDIS_LINK: - if(block_ap_event) { - printf("Block ap event\n"); - break; - } - if (!(flags & WLC_EVENT_MSG_LINK)) { - printf("AP DOWN %d\n", event_type); - wl_cfg80211_send_priv_event(ndev, "AP_DOWN"); - } else { - printf("AP UP %d\n", event_type); - dhd_APUP = true; - wl_cfg80211_send_priv_event(ndev, "AP_UP"); - } - break; - - case WLC_E_LOAD_IND: - printf("WLC_E_LOAD_IND, %d\n", datalen); - if (datalen > IW_CUSTOM_MAX) - break; - - if (status) - printf("HIGH INDICATE!!\n"); - else - printf("LOW INDICATE!!\n"); - - break; - default: - break; - } - return; -} -#endif - void -wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data) +wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data) { u32 event_type = ntoh32(e->event_type); - u32 status = ntoh32(e->status); - u32 len = ntoh32(e->datalen); struct wl_priv *wl = wlcfg_drv_priv; #if (WL_DBG_LEVEL > 0) @@ -6493,30 +6864,6 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data) WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr)); #endif /* (WL_DBG_LEVEL > 0) */ - if (event_type == WLC_E_PFN_NET_FOUND) - WL_ERR((" PNO Event\n")); - -#if defined(SOFTAP) - if (dhd_check_ap_mode_set(wl->pub)) - wl_cfg80211_hotspot_event_process(ndev, e, data); -#endif - - switch (event_type) { - case WLC_E_ASSOCREQ_IE: - WL_DBG(("WLC_E_ASSOCREQ_IE\n")); - if (!ap_resp_ie_len) - memset(ap_resp_ie, 0, 256); - if (status == 1) { - WL_DBG(("set ap_resp_ie, len = %d\n", len)); - memcpy(ap_resp_ie, data, len); - ap_resp_ie_len = len; - } - break; - default: - break; - - } - if (likely(!wl_enq_event(wl, ndev, event_type, e, data))) wl_wakeup_event(wl); } @@ -6677,27 +7024,210 @@ static s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) } +static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) +{ + struct net_device *dev = wl_to_prmry_ndev(wl); + struct ieee80211_channel *band_chan_arr = NULL; + wl_uint32_list_t *list; + u32 i, j, index, n_2g, n_5g, band, channel, array_size; + u32 *n_cnt = NULL; + chanspec_t c = 0; + s32 err = BCME_OK; + bool update; + bool ht40_allowed; + u8 *pbuf = NULL; + +#define LOCAL_BUF_LEN 1024 + pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL); + if (pbuf == NULL) { + WL_ERR(("failed to allocate local buf\n")); + return -ENOMEM; + } + + list = (wl_uint32_list_t *)(void *)pbuf; + list->count = htod32(WL_NUMCHANSPECS); + + err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL, + 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync); + if (err != 0) { + WL_ERR(("get chanspecs failed with %d\n", err)); + kfree(pbuf); + return err; + } +#undef LOCAL_BUF_LEN + + band = array_size = n_2g = n_5g = 0; + for (i = 0; i < dtoh32(list->count); i++) { + index = 0; + update = FALSE; + ht40_allowed = FALSE; + c = (chanspec_t)dtoh32(list->element[i]); + channel = CHSPEC_CHANNEL(c); + if (CHSPEC_IS40(c)) { + if (CHSPEC_SB_UPPER(c)) + channel += CH_10MHZ_APART; + else + channel -= CH_10MHZ_APART; + } + + if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) { + band_chan_arr = __wl_2ghz_channels; + array_size = ARRAYSIZE(__wl_2ghz_channels); + n_cnt = &n_2g; + band = IEEE80211_BAND_2GHZ; + ht40_allowed = (bw_cap == WLC_N_BW_40ALL) ? TRUE : FALSE; + } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) { + band_chan_arr = __wl_5ghz_a_channels; + array_size = ARRAYSIZE(__wl_5ghz_a_channels); + n_cnt = &n_5g; + band = IEEE80211_BAND_5GHZ; + ht40_allowed = (bw_cap == WLC_N_BW_20ALL) ? FALSE : TRUE; + } + + for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { + if (band_chan_arr[j].hw_value == channel) { + update = TRUE; + break; + } + } + + if (update) + index = j; + else + index = *n_cnt; + + if (index < array_size) { +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + band_chan_arr[index].center_freq = + ieee80211_channel_to_frequency(channel); +#else + band_chan_arr[index].center_freq = + ieee80211_channel_to_frequency(channel, band); +#endif + band_chan_arr[index].hw_value = channel; + + if (CHSPEC_IS40(c) && ht40_allowed) { + u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40; + if (CHSPEC_SB_UPPER(c)) { + if (ht40_flag == IEEE80211_CHAN_NO_HT40) + band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; + band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS; + } else { + band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; + if (ht40_flag == IEEE80211_CHAN_NO_HT40) + band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40MINUS; + } + } else { + band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40; + if (band == IEEE80211_BAND_2GHZ) + channel |= WL_CHANSPEC_BAND_2G; + else + channel |= WL_CHANSPEC_BAND_5G; + err = wldev_iovar_getint(dev, "per_chan_info", &channel); + if (!err) { + if (channel & WL_CHAN_RADAR) { + band_chan_arr[index].flags |= IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IBSS; + } + if (channel & WL_CHAN_PASSIVE) { + band_chan_arr[index].flags |= IEEE80211_CHAN_PASSIVE_SCAN | IEEE80211_CHAN_NO_IBSS; + } + } + } + + if (!update) + (*n_cnt)++; + } + } + + __wl_band_2ghz.n_channels = n_2g; + __wl_band_5ghz_a.n_channels = n_5g; + + kfree(pbuf); + return err; +} + s32 wl_update_wiphybands(struct wl_priv *wl) { struct wiphy *wiphy; - s8 phylist_buf[128]; - s8 *phy; + struct net_device *dev; + u32 bandlist[3]; + u32 nband = 0; + u32 i = 0; s32 err = 0; + int nmode = 0; + int bw_cap = 0; + int index = 0; + bool rollback_lock = false; + + WL_DBG(("Entry")); + + if (wl == NULL) { + wl = wlcfg_drv_priv; + mutex_lock(&wl->usr_sync); + rollback_lock = true; + } + dev = wl_to_prmry_ndev(wl); - err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, phylist_buf, - sizeof(phylist_buf), false); + memset(bandlist, 0, sizeof(bandlist)); + err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist, + sizeof(bandlist), false); if (unlikely(err)) { - WL_ERR(("error (%d)\n", err)); - return err; + WL_ERR(("error read bandlist (%d)\n", err)); + goto end_bands; + } + wiphy = wl_to_wiphy(wl); + nband = bandlist[0]; + wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; + wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; + + err = wldev_iovar_getint(dev, "nmode", &nmode); + if (unlikely(err)) { + WL_ERR(("error reading nmode (%d)\n", err)); + } else { + /* For nmodeonly check bw cap */ + err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); + if (unlikely(err)) { + WL_ERR(("error get mimo_bw_cap (%d)\n", err)); + } } - phy = phylist_buf; - for (; *phy; phy++) { - if (*phy == 'a' || *phy == 'n') { - wiphy = wl_to_wiphy(wl); + + err = wl_construct_reginfo(wl, bw_cap); + if (err) { + WL_ERR(("wl_construct_reginfo() fails err=%d\n", err)); + if (err != BCME_UNSUPPORTED) + goto end_bands; + /* Ignore error if "chanspecs" command is not supported */ + err = 0; + } + for (i = 1; i <= nband && i < sizeof(bandlist)/sizeof(u32); i++) { + index = -1; + if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) { wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; + index = IEEE80211_BAND_5GHZ; + if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) { + wiphy->bands[IEEE80211_BAND_2GHZ] = + &__wl_band_2ghz; + index = IEEE80211_BAND_2GHZ; + if (bandlist[i] == WLC_BAND_2G && bw_cap == WLC_N_BW_40ALL) + wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + } + if ((index >= 0) && nmode) { + wiphy->bands[index]->ht_cap.cap |= + IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40; + wiphy->bands[index]->ht_cap.ht_supported = TRUE; + wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; } } + + wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); + +end_bands: + if (rollback_lock) + mutex_unlock(&wl->usr_sync); return err; } @@ -6707,13 +7237,11 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) struct net_device *ndev = wl_to_prmry_ndev(wl); struct wireless_dev *wdev = ndev->ieee80211_ptr; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); -#if 0 err = dhd_config_dongle(wl, false); if (unlikely(err)) return err; -#endif err = wl_config_ifmode(wl, ndev, wdev->iftype); if (unlikely(err && err != -EINPROGRESS)) { @@ -6736,8 +7264,12 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) unsigned long flags; struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); +#ifdef WL_ENABLE_P2P_IF + struct wiphy *wiphy = wl_to_prmry_ndev(wl)->ieee80211_ptr->wiphy; + struct net_device *p2p_net = wl->p2p_net; +#endif - WL_TRACE(("In\n")); + WL_DBG(("In\n")); /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ @@ -6762,6 +7294,15 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; +#ifdef WL_ENABLE_P2P_IF + wiphy->interface_modes = (wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO))); + if ((p2p_net) && (p2p_net->flags & IFF_UP)) { + /* p2p0 interface is still UP. Bring it down */ + p2p_net->flags &= ~IFF_UP; + } +#endif /* WL_ENABLE_P2P_IF */ spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); DNGL_FUNC(dhd_cfg80211_down, (wl)); @@ -6779,8 +7320,7 @@ s32 wl_cfg80211_up(void *para) struct wl_priv *wl; s32 err = 0; - (void)para; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); wl = wlcfg_drv_priv; mutex_lock(&wl->usr_sync); wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); @@ -6788,7 +7328,6 @@ s32 wl_cfg80211_up(void *para) if (err) WL_ERR(("__wl_cfg80211_up failed\n")); mutex_unlock(&wl->usr_sync); - return err; } @@ -6811,8 +7350,7 @@ s32 wl_cfg80211_down(void *para) struct wl_priv *wl; s32 err = 0; - (void)para; - WL_TRACE(("In\n")); + WL_DBG(("In\n")); wl = wlcfg_drv_priv; mutex_lock(&wl->usr_sync); err = __wl_cfg80211_down(wl); @@ -7013,35 +7551,28 @@ static void wl_init_eq_lock(struct wl_priv *wl) static void wl_delay(u32 ms) { - if (ms < 1000 / HZ) { - cond_resched(); + if (in_atomic() || (ms < jiffies_to_msecs(1))) { mdelay(ms); } else { msleep(ms); } } -s32 wl_cfg80211_get_mac_addr(struct net_device *net, struct ether_addr *mac_addr) -{ - struct wl_priv *wl; - dhd_pub_t *dhd_pub; - - wl = wlcfg_drv_priv; - dhd_pub = (dhd_pub_t *)wl->pub; - memcpy(mac_addr, &dhd_pub->mac, sizeof(*mac_addr)); - - return 0; -} - s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr) { - struct wl_priv *wl; + struct wl_priv *wl = wlcfg_drv_priv; struct ether_addr p2pif_addr; struct ether_addr primary_mac; - wl = wlcfg_drv_priv; - get_primary_mac(wl, &primary_mac); - wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); + if (!wl->p2p) + return -1; + if (!p2p_is_on(wl)) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr); + } else { + memcpy(p2pdev_addr->octet, + wl->p2p->dev_addr.octet, ETHER_ADDR_LEN); + } return 0; } @@ -7070,47 +7601,49 @@ s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) return wl_cfgp2p_set_p2p_ps(wl, net, buf, len); } - -extern int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac); -s32 wl_cfg80211_deauth_sta(struct net_device *net, char* buf, int len) -{ - printf("deauth: %02X:%02X:%02X:%02X:%02x:%02X\n", buf[0], buf[1], buf[2], - buf[3],buf[4],buf[5]); - return wl_iw_softap_deassoc_stations(net, buf); -} - -s32 wl_cfg80211_set_mpc(struct net_device *net, char* buf, int len) -{ - s32 mpc = -1; - s32 arpoe = -1; - - sscanf(buf, "%d", &mpc); - arpoe = mpc; - if ((mpc != 0) && (mpc !=1)) { - printf("%s: Bad arg!\n", __FUNCTION__); - } - - wldev_iovar_setint(net, "arpoe", arpoe); - return wldev_iovar_setint(net, "mpc", mpc); - -} - s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, enum wl_management_type type) { struct wl_priv *wl; struct net_device *ndev = NULL; + struct ether_addr primary_mac; s32 ret = 0; s32 bssidx = 0; s32 pktflag = 0; wl = wlcfg_drv_priv; - if (wl->p2p && wl->p2p->vif_created) { - ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); - } else if (wl_get_drv_status(wl, AP_CREATING, net) || + + if (wl_get_drv_status(wl, AP_CREATING, net) || wl_get_drv_status(wl, AP_CREATED, net)) { ndev = net; bssidx = 0; + } else if (wl->p2p) { + if (net == wl->p2p_net) { + net = wl_to_prmry_ndev(wl); + } + + if (!wl->p2p->on) { + get_primary_mac(wl, &primary_mac); + wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, + &wl->p2p->int_addr); + /* In case of p2p_listen command, supplicant send remain_on_channel + * without turning on P2P + */ + p2p_on(wl) = true; + ret = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0); + + if (unlikely(ret)) { + goto exit; + } + } + if (net != wl_to_prmry_ndev(wl)) { + if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION); + } + } else { + ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + } } if (ndev != NULL) { switch (type) { @@ -7127,7 +7660,7 @@ s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, if (pktflag) ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len); } - +exit: return ret; } @@ -7206,3 +7739,21 @@ static void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac) 0, wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN); } + +int wl_cfg80211_do_driver_init(struct net_device *net) +{ + struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net); + + if (!wl || !wl->wdev) + return -EINVAL; + + if (dhd_do_driver_init(wl->wdev->netdev) < 0) + return -1; + + return 0; +} + +void wl_cfg80211_enable_trace(int level) +{ + wl_dbg_level |= WL_DBG_DBG; +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index a9e392bb..49bed703 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -64,7 +64,7 @@ struct wl_ibss; #define WL_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printf(KERN_ERR "CFG80211-ERROR) %s : ", __func__); \ + printk(KERN_ERR "CFG80211-ERROR) %s : ", __func__); \ printk args; \ } \ } while (0) @@ -74,7 +74,7 @@ do { \ #define WL_INFO(args) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printf(KERN_ERR "CFG80211-INFO) %s : ", __func__); \ + printk(KERN_ERR "CFG80211-INFO) %s : ", __func__); \ printk args; \ } \ } while (0) @@ -84,7 +84,7 @@ do { \ #define WL_SCAN(args) \ do { \ if (wl_dbg_level & WL_DBG_SCAN) { \ - printf(KERN_ERR "CFG80211-SCAN) %s :", __func__); \ + printk(KERN_ERR "CFG80211-SCAN) %s :", __func__); \ printk args; \ } \ } while (0) @@ -94,7 +94,7 @@ do { \ #define WL_TRACE(args) \ do { \ if (wl_dbg_level & WL_DBG_TRACE) { \ - printf(KERN_ERR "CFG80211-TRACE) %s :", __func__); \ + printk(KERN_ERR "CFG80211-TRACE) %s :", __func__); \ printk args; \ } \ } while (0) @@ -102,7 +102,7 @@ do { \ #define WL_DBG(args) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printf(KERN_ERR "CFG80211-DEBUG) %s :", __func__); \ + printk(KERN_ERR "CFG80211-DEBUG) %s :", __func__); \ printk args; \ } \ } while (0) @@ -111,40 +111,37 @@ do { \ #endif /* (WL_DBG_LEVEL > 0) */ -#define WL_SCAN_RETRY_MAX 3 /* used for ibss scan */ -#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used - * for 2.6.33 kernel - * or later - */ -#define WL_SCAN_BUF_MAX (1024 * 8) -#define WL_TLV_INFO_MAX 1024 +#define WL_SCAN_RETRY_MAX 3 +#define WL_NUM_PMKIDS_MAX MAXPMKID +#define WL_SCAN_BUF_MAX (1024 * 8) +#define WL_TLV_INFO_MAX 1024 #define WL_SCAN_IE_LEN_MAX 2048 -#define WL_BSS_INFO_MAX 2048 -#define WL_ASSOC_INFO_MAX 512 /* - * needs to grab assoc info from dongle to - * report it to cfg80211 through "connect" - * event - */ +#define WL_BSS_INFO_MAX 2048 +#define WL_ASSOC_INFO_MAX 512 #define WL_IOCTL_LEN_MAX 1024 #define WL_EXTRA_BUF_MAX 2048 -#define WL_ISCAN_BUF_MAX 2048 /* - * the buf lengh can be WLC_IOCTL_MAXLEN (8K) - * to reduce iteration - */ +#define WL_ISCAN_BUF_MAX 2048 #define WL_ISCAN_TIMER_INTERVAL_MS 3000 #define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1) -#define WL_AP_MAX 256 /* virtually unlimitted as long - * as kernel memory allows - */ -#define WL_FILE_NAME_MAX 256 -#define WL_DWELL_TIME 200 -#define WL_LONG_DWELL_TIME 1000 +#define WL_AP_MAX 256 +#define WL_FILE_NAME_MAX 256 +#define WL_DWELL_TIME 200 +#define WL_MED_DWELL_TIME 400 +#define WL_LONG_DWELL_TIME 1000 #define IFACE_MAX_CNT 2 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ -#define WL_CHANNEL_SYNC_RETRY 5 +#define WL_CHANNEL_SYNC_RETRY 3 +#define WL_ACT_FRAME_RETRY 4 + #define WL_INVALID -1 + +/* Bring down SCB Timeout to 20secs from 60secs default */ +#ifndef WL_SCB_TIMEOUT +#define WL_SCB_TIMEOUT 20 +#endif + /* driver status */ enum wl_status { WL_STATUS_READY = 0, @@ -453,17 +450,24 @@ struct wl_priv { bool p2p_supported; struct btcoex_info *btcoex_info; struct timer_list scan_timeout; /* Timer for catch scan event timeout */ +#ifdef WL_SCHED_SCAN + struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ +#endif /* WL_SCHED_SCAN */ + bool sched_scan_running; /* scheduled scan req status */ + u16 hostapd_chan; /* remember chan requested by framework for hostapd */ + u16 deauth_reason; /* Place holder to save deauth/disassoc reasons */ + u16 scan_busy_count; }; - static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss) { return bss = bss ? (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info; } + static inline s32 wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev, - struct wireless_dev *wdev, s32 mode) + struct wireless_dev * wdev, s32 mode) { struct net_info *_net_info; s32 err = 0; @@ -481,6 +485,7 @@ wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev, } return err; } + static inline void wl_dealloc_netinfo(struct wl_priv *wl, struct net_device *ndev) { @@ -490,14 +495,15 @@ wl_dealloc_netinfo(struct wl_priv *wl, struct net_device *ndev) if (ndev && (_net_info->ndev == ndev)) { list_del(&_net_info->list); wl->iface_cnt--; - kfree(_net_info->wdev); - ndev->ieee80211_ptr = NULL; - + if (_net_info->wdev) { + kfree(_net_info->wdev); + ndev->ieee80211_ptr = NULL; + } kfree(_net_info); } } - } + static inline void wl_delete_all_netinfo(struct wl_priv *wl) { @@ -505,12 +511,13 @@ wl_delete_all_netinfo(struct wl_priv *wl) list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { list_del(&_net_info->list); - - kfree(_net_info->wdev); + if (_net_info->wdev) + kfree(_net_info->wdev); kfree(_net_info); } wl->iface_cnt = 0; } + static inline bool wl_get_status_all(struct wl_priv *wl, s32 status) @@ -524,6 +531,7 @@ wl_get_status_all(struct wl_priv *wl, s32 status) } return cnt? true: false; } + static inline void wl_set_status_by_netdev(struct wl_priv *wl, s32 status, struct net_device *ndev, u32 op) @@ -534,20 +542,19 @@ wl_set_status_by_netdev(struct wl_priv *wl, s32 status, list_for_each_entry_safe(_net_info, next, &wl->net_list, list) { if (ndev && (_net_info->ndev == ndev)) { switch (op) { - case 1: + case 1: set_bit(status, &_net_info->sme_state); break; - case 2: + case 2: clear_bit(status, &_net_info->sme_state); break; - case 4: + case 4: change_bit(status, &_net_info->sme_state); break; } } } - } static inline u32 @@ -575,7 +582,6 @@ wl_get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev) return -1; } - static inline void wl_set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, s32 mode) @@ -587,6 +593,7 @@ wl_set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, _net_info->mode = mode; } } + static inline struct wl_profile * wl_get_profile_by_netdev(struct wl_priv *wl, struct net_device *ndev) { @@ -643,9 +650,10 @@ struct device *wl_cfg80211_get_parent_dev(void); extern s32 wl_cfg80211_up(void *para); extern s32 wl_cfg80211_down(void *para); -extern s32 wl_cfg80211_notify_ifadd(struct net_device *net, s32 idx, s32 bssidx, void *_net_attach); +extern s32 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx, + void* _net_attach); extern s32 wl_cfg80211_ifdel_ops(struct net_device *net); -extern s32 wl_cfg80211_notify_ifdel(struct net_device *ndev); +extern s32 wl_cfg80211_notify_ifdel(void); extern s32 wl_cfg80211_is_progress_ifadd(void); extern s32 wl_cfg80211_is_progress_ifchange(void); extern s32 wl_cfg80211_is_progress_ifadd(void); @@ -659,11 +667,8 @@ extern s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len extern s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len); extern int wl_cfg80211_hang(struct net_device *dev, u16 reason); extern s32 wl_mode_to_nl80211_iftype(s32 mode); -extern s32 wl_cfg80211_set_mpc(struct net_device *net, char* buf, int len); -extern s32 wl_cfg80211_deauth_sta(struct net_device *net, char* buf, int len); - -/* do scan abort */ -extern s32 wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev); - +int wl_cfg80211_do_driver_init(struct net_device *net); +void wl_cfg80211_enable_trace(int level); +extern s32 wl_update_wiphybands(struct wl_priv *wl); extern s32 wl_cfg80211_if_is_group_owner(void); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 914fbca2..bdcfa953 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -59,6 +59,8 @@ static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd); static int wl_cfgp2p_if_open(struct net_device *net); static int wl_cfgp2p_if_stop(struct net_device *net); +static s32 wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, + bool notify); static const struct net_device_ops wl_cfgp2p_if_ops = { .ndo_open = wl_cfgp2p_if_open, @@ -67,6 +69,171 @@ static const struct net_device_ops wl_cfgp2p_if_ops = { .ndo_start_xmit = wl_cfgp2p_start_xmit, }; +bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len) +{ + wifi_p2p_pub_act_frame_t *pact_frm; + + if (frame == NULL) + return false; + pact_frm = (wifi_p2p_pub_act_frame_t *)frame; + if (frame_len < sizeof(wifi_p2p_pub_act_frame_t) -1) + return false; + + if (pact_frm->category == P2P_PUB_AF_CATEGORY && + pact_frm->action == P2P_PUB_AF_ACTION && + pact_frm->oui_type == P2P_VER && + memcmp(pact_frm->oui, P2P_OUI, sizeof(pact_frm->oui)) == 0) { + return true; + } + + return false; +} + +bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) +{ + wifi_p2p_action_frame_t *act_frm; + + if (frame == NULL) + return false; + act_frm = (wifi_p2p_action_frame_t *)frame; + if (frame_len < sizeof(wifi_p2p_action_frame_t) -1) + return false; + + if (act_frm->category == P2P_AF_CATEGORY && + act_frm->type == P2P_VER && + memcmp(act_frm->OUI, P2P_OUI, DOT11_OUI_LEN) == 0) { + return true; + } + + return false; +} + +bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) +{ + + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; + + if (frame == NULL) + return false; + + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + if (frame_len < sizeof(wifi_p2psd_gas_pub_act_frame_t) - 1) + return false; + if (sd_act_frm->category != P2PSD_ACTION_CATEGORY) + return false; + + if (sd_act_frm->action == P2PSD_ACTION_ID_GAS_IREQ || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_IRESP || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_CREQ || + sd_act_frm->action == P2PSD_ACTION_ID_GAS_CRESP) + return true; + else + return false; + +} + +void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) +{ + wifi_p2p_pub_act_frame_t *pact_frm; + wifi_p2p_action_frame_t *act_frm; + wifi_p2psd_gas_pub_act_frame_t *sd_act_frm; + if (!frame || frame_len <= 2) + return; + + if (wl_cfgp2p_is_pub_action(frame, frame_len)) { + pact_frm = (wifi_p2p_pub_act_frame_t *)frame; + switch (pact_frm->subtype) { + case P2P_PAF_GON_REQ: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Req Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_RSP: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Rsp Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_GON_CONF: + CFGP2P_DBG(("%s P2P Group Owner Negotiation Confirm Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_REQ: + CFGP2P_DBG(("%s P2P Invitation Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_INVITE_RSP: + CFGP2P_DBG(("%s P2P Invitation Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_REQ: + CFGP2P_DBG(("%s P2P Device Discoverability Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_DEVDIS_RSP: + CFGP2P_DBG(("%s P2P Device Discoverability Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_REQ: + CFGP2P_DBG(("%s P2P Provision Discovery Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_PAF_PROVDIS_RSP: + CFGP2P_DBG(("%s P2P Provision Discovery Response Frame\n", + (tx)? "TX": "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P Public Action Frame\n", + (tx)? "TX": "RX")); + + } + + } else if (wl_cfgp2p_is_p2p_action(frame, frame_len)) { + act_frm = (wifi_p2p_action_frame_t *)frame; + switch (act_frm->subtype) { + case P2P_AF_NOTICE_OF_ABSENCE: + CFGP2P_DBG(("%s P2P Notice of Absence Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_REQ: + CFGP2P_DBG(("%s P2P Presence Request Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_PRESENCE_RSP: + CFGP2P_DBG(("%s P2P Presence Response Frame\n", + (tx)? "TX": "RX")); + break; + case P2P_AF_GO_DISC_REQ: + CFGP2P_DBG(("%s P2P Discoverability Request Frame\n", + (tx)? "TX": "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P Action Frame\n", + (tx)? "TX": "RX")); + } + + } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; + switch (sd_act_frm->action) { + case P2PSD_ACTION_ID_GAS_IREQ: + CFGP2P_DBG(("%s P2P GAS Initial Request\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_IRESP: + CFGP2P_DBG(("%s P2P GAS Initial Response\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CREQ: + CFGP2P_DBG(("%s P2P GAS Comback Request\n", + (tx)? "TX" : "RX")); + break; + case P2PSD_ACTION_ID_GAS_CRESP: + CFGP2P_DBG(("%s P2P GAS Comback Response\n", + (tx)? "TX" : "RX")); + break; + default: + CFGP2P_DBG(("%s Unknown P2P GAS Frame\n", + (tx)? "TX" : "RX")); + } + } +} /* * Initialize variables related to P2P @@ -108,7 +275,6 @@ wl_cfgp2p_init_priv(struct wl_priv *wl) wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL; wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0; - spin_lock_init(&wl->p2p->timer_lock); return BCME_OK; } @@ -123,6 +289,7 @@ wl_cfgp2p_deinit_priv(struct wl_priv *wl) if (wl->p2p) { kfree(wl->p2p); + wl->p2p = NULL; } wl->p2p_supported = 0; } @@ -154,7 +321,7 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) ret = wldev_iovar_setbuf_bsscfg(ndev, "p2p_da_override", &null_eth_addr, sizeof(null_eth_addr), wl->ioctl_buf, WLC_IOCTL_MAXLEN, 0, &wl->ioctl_buf_sync); if (ret && ret != BCME_UNSUPPORTED) { - CFGP2P_ERR(("failed to update device address\n")); + CFGP2P_ERR(("failed to update device address ret %d\n", ret)); } return ret; } @@ -173,12 +340,13 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, wl_p2p_if_t ifreq; s32 err; struct net_device *ndev = wl_to_prmry_ndev(wl); + u32 scb_timeout = WL_SCB_TIMEOUT; ifreq.type = if_type; ifreq.chspec = chspec; memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); - CFGP2P_INFO(("---wl p2p_ifadd %02x:%02x:%02x:%02x:%02x:%02x %s %u\n", + CFGP2P_DBG(("---wl p2p_ifadd %02x:%02x:%02x:%02x:%02x:%02x %s %u\n", ifreq.addr.octet[0], ifreq.addr.octet[1], ifreq.addr.octet[2], ifreq.addr.octet[3], ifreq.addr.octet[4], ifreq.addr.octet[5], (if_type == WL_P2P_IF_GO) ? "go" : "client", @@ -186,6 +354,15 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + + if (unlikely(err < 0)) { + printk("'wl p2p_ifadd' error %d\n", err); + } else if (if_type == WL_P2P_IF_GO) { + err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); + if (unlikely(err < 0)) + printk("'wl scb_timeout' error %d\n", err); + } + return err; } @@ -206,7 +383,7 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { - printf("'wl p2p_ifdel' error %d\n", ret); + printk("'wl p2p_ifdel' error %d\n", ret); } return ret; } @@ -222,6 +399,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, { wl_p2p_if_t ifreq; s32 err; + u32 scb_timeout = WL_SCB_TIMEOUT; struct net_device *netdev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION); ifreq.type = if_type; @@ -238,7 +416,11 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(err < 0)) { - printf("'wl p2p_ifupd' error %d\n", err); + printk("'wl p2p_ifupd' error %d\n", err); + } else if (if_type == WL_P2P_IF_GO) { + err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true); + if (unlikely(err < 0)) + printk("'wl scb_timeout' error %d\n", err); } return err; } @@ -375,7 +557,7 @@ wl_cfgp2p_init_discovery(struct wl_priv *wl) /* Set the initial discovery state to SCAN */ ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); if (unlikely(ret != 0)) { CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n")); @@ -523,10 +705,10 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, wl_escan_params_t *eparams; wlc_ssid_t ssid; /* Scan parameters */ -#define P2PAPI_SCAN_NPROBES 2 +#define P2PAPI_SCAN_NPROBES 1 #define P2PAPI_SCAN_DWELL_TIME_MS 50 #define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40 -#define P2PAPI_SCAN_HOME_TIME_MS 10 +#define P2PAPI_SCAN_HOME_TIME_MS 60 struct net_device *pri_dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY); wl_set_p2p_status(wl, SCANNING); /* Allocate scan params which need space for 3 channels and 0 ssids */ @@ -534,9 +716,6 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, OFFSETOF(wl_escan_params_t, params)) + num_chans * sizeof(eparams->params.channel_list[0]); -#ifdef HTC_KlocWork - memset(&ssid, 0, sizeof(ssid)); -#endif memsize = sizeof(wl_p2p_scan_t) + eparams_size; memblk = scanparambuf; if (memsize > sizeof(scanparambuf)) { @@ -679,7 +858,6 @@ wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, * Returns 0 if success. */ -extern int bcm_add_ie_reverse; s32 wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len) @@ -694,9 +872,6 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss u32 *mgmt_ie_len = 0; u8 ie_id, ie_len; u8 delete = 0; - u32 p2pie_pos[2] = {0}; - u32 p2pie_count = 0; - s32 i = 0; #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) if (p2p_is_on(wl) && bssidx != -1) { @@ -825,31 +1000,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :" "%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2])); - if ((bcm_add_ie_reverse)&&(wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) { - if (p2pie_count >= 2) { - CFGP2P_ERR(("more than 2 p2p ie set, ignore!\n")); - break; - } - p2pie_pos[p2pie_count++] = pos - 2; - } - else - ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, ie_buf+pos, - VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete); + ret = wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, + ie_buf+pos, VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, + ie_len-3, delete); } pos += ie_len; } - - if (bcm_add_ie_reverse) { - for (i = 1; i >=0; i--) { - if (p2pie_pos[i]) { - pos = p2pie_pos[i]; - ie_id = ie_buf[pos++]; - ie_len = ie_buf[pos++]; - ret |= wl_cfgp2p_vndr_ie(wl, ndev, bssidx, pktflag, ie_buf+pos, - VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete); - } - } - } } } #undef IE_TYPE @@ -1042,12 +1198,15 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev, s32 ret = BCME_OK; CFGP2P_DBG((" Enter\n")); + + /* If p2p_info is de-initialized, do nothing */ + if (!wl->p2p) + return ret; + if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) { wl_set_p2p_status(wl, LISTEN_EXPIRED); if (timer_pending(&wl->p2p->listen_timer)) { - spin_lock_bh(&wl->p2p->timer_lock); del_timer_sync(&wl->p2p->listen_timer); - spin_unlock_bh(&wl->p2p->timer_lock); } cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); @@ -1070,10 +1229,38 @@ wl_cfgp2p_listen_expired(unsigned long data) struct wl_priv *wl = (struct wl_priv *) data; CFGP2P_DBG((" Enter\n")); + memset(&msg, 0, sizeof(wl_event_msg_t)); msg.event_type = hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE); wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL); } +/* + * Routine for cancelling the P2P LISTEN + */ +static s32 +wl_cfgp2p_cancel_listen(struct wl_priv *wl, struct net_device *ndev, + bool notify) +{ + WL_DBG(("Enter \n")); + + /* Irrespective of whether timer is running or not, reset + * the LISTEN state. + */ + wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + + if (timer_pending(&wl->p2p->listen_timer)) { + del_timer_sync(&wl->p2p->listen_timer); + + if (notify) + cfg80211_remain_on_channel_expired(ndev, wl->last_roc_id, + &wl->remain_on_chan, wl->remain_on_chan_type, GFP_KERNEL); + } + + + return 0; +} + /* * Do a P2P Listen on the given channel for the given duration. * A listen consists of sitting idle and responding to P2P probe requests @@ -1178,10 +1365,10 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, wl_set_p2p_status(wl, ACTION_TX_NOACK); CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); } - wake_up_interruptible(&wl->netif_change_event); } else { CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," "status : %d\n", status)); + wake_up_interruptible(&wl->netif_change_event); } return ret; } @@ -1215,13 +1402,12 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (ret < 0) { - CFGP2P_ERR((" sending action frame is failed\n")); goto exit; } timeout = wait_event_interruptible_timeout(wl->netif_change_event, - (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), - msecs_to_jiffies(MAX_WAIT_TIME)); + (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || wl_get_p2p_status(wl, ACTION_TX_NOACK)), + msecs_to_jiffies(MAX_WAIT_TIME)); if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { CFGP2P_INFO(("tx action frame operation is completed\n")); @@ -1388,15 +1574,19 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) } return p2p_supported; } + /* Cleanup P2P resources */ s32 wl_cfgp2p_down(struct wl_priv *wl) { - if (timer_pending(&wl->p2p->listen_timer)) - del_timer_sync(&wl->p2p->listen_timer); + + wl_cfgp2p_cancel_listen(wl, + wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); + wl_cfgp2p_deinit_priv(wl); return 0; } + s32 wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) { @@ -1470,17 +1660,13 @@ wl_cfgp2p_set_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in } return ret; } + s32 wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, int buf_len) { - wifi_p2p_noa_desc_t *noa_desc; int len = 0, i; -#ifdef HTC_KlocWork - char _buf[200] = {0}; -#else char _buf[200]; -#endif CFGP2P_DBG((" Enter\n")); buf[0] = '\0'; @@ -1517,6 +1703,7 @@ wl_cfgp2p_get_p2p_noa(struct wl_priv *wl, struct net_device *ndev, char* buf, in } return len * 2; } + s32 wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int len) { @@ -1542,15 +1729,14 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int } } - if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { + if (legacy_ps != -1) { + s32 pm = legacy_ps ? PM_MAX : PM_OFF; ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), - WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); + WLC_SET_PM, &pm, sizeof(pm), true); if (unlikely(ret)) { CFGP2P_ERR(("error (%d)\n", ret)); } } - else - CFGP2P_ERR(("ilegal setting\n")); } else { CFGP2P_ERR(("ERROR: set_p2p_ps in non-p2p mode\n")); @@ -1583,7 +1769,7 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) len -= 4; /* exclude OUI + OUI_TYPE */ while (len >= 3) { - /* attribute id */ + /* attribute id */ subelt_id = *subel; subel += 1; len -= 1; @@ -1614,31 +1800,29 @@ wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id) u8 * wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length) { - wifi_p2p_ie_t *p2p_ie = NULL; + wifi_p2p_ie_t * p2p_ie = NULL; u8 *capability = NULL; bool p2p_go = 0; u8 *ptr = NULL; - p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length); - if (!p2p_ie) { + if (!(p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length))) { WL_ERR(("P2P IE not found")); return NULL; } - capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO); - if (!capability) { + if (!(capability = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_P2P_INFO))) { WL_ERR(("P2P Capability attribute not found")); return NULL; } /* Check Group capability for Group Owner bit */ p2p_go = capability[1] & P2P_GROUP_CAPAB_GO_BIT; - if (!p2p_go) + if (!p2p_go) { return bi->BSSID.octet; + } /* In probe responses, DEVICE INFO attribute will be present */ - ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO); - if (!ptr) { + if (!(ptr = wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_DEV_INFO))) { /* If DEVICE_INFO is not found, this might be a beacon frame. * check for DEVICE_ID in the beacon frame. */ @@ -1655,14 +1839,13 @@ s32 wl_cfgp2p_register_ndev(struct wl_priv *wl) { int ret = 0; - struct net_device *net = NULL; + struct net_device* net = NULL; struct wireless_dev *wdev; uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 }; /* Allocate etherdev, including space for private structure */ - net = alloc_etherdev(sizeof(wl)); - if (!net) { - CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __func__)); + if (!(net = alloc_etherdev(sizeof(wl)))) { + CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); goto fail; } @@ -1672,8 +1855,16 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) /* Copy the reference to wl_priv */ memcpy((void *)netdev_priv(net), &wl, sizeof(wl)); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) + ASSERT(!net->open); + net->do_ioctl = wl_cfgp2p_do_ioctl; + net->hard_start_xmit = wl_cfgp2p_start_xmit; + net->open = wl_cfgp2p_if_open; + net->stop = wl_cfgp2p_if_stop; +#else ASSERT(!net->netdev_ops); net->netdev_ops = &wl_cfgp2p_if_ops; +#endif /* Register with a dummy MAC addr */ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); @@ -1712,13 +1903,16 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) goto fail; } - printf("%s: P2P Interface Registered\n", net->name); + printk("%s: P2P Interface Registered\n", net->name); return ret; fail: +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) + net->open = NULL; +#else net->netdev_ops = NULL; - +#endif if (net) { unregister_netdev(net); @@ -1742,6 +1936,7 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl) return 0; } + static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) { CFGP2P_DBG(("(%s) is not used for data operations. Droping the packet. \n", ndev->name)); @@ -1759,15 +1954,11 @@ static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd * For Android PRIV CMD handling map it to primary I/F */ if (cmd == SIOCDEVPRIVATE+1) { -#if defined(OEM_ANROID) ret = wl_android_priv_cmd(ndev, ifr, cmd); -#else - (void)ndev; -#endif } else { CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n", - __func__, cmd)); + __FUNCTION__, cmd)); return -1; } @@ -1776,12 +1967,34 @@ static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd static int wl_cfgp2p_if_open(struct net_device *net) { - CFGP2P_DBG(("Do Nothing \n")); + struct wireless_dev *wdev = net->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + /* If suppose F/W download (ifconfig wlan0 up) hasn't been done by now, + * do it here. This will make sure that in concurrent mode, supplicant + * is not dependent on a particular order of interface initialization. + * i.e you may give wpa_supp -iwlan0 -N -ip2p0 or wpa_supp -ip2p0 -N + * -iwlan0. + */ + wl_cfg80211_do_driver_init(net); + + wdev->wiphy->interface_modes |= (BIT(NL80211_IFTYPE_P2P_CLIENT) + | BIT(NL80211_IFTYPE_P2P_GO)); + return 0; } static int wl_cfgp2p_if_stop(struct net_device *net) { - CFGP2P_DBG(("Do Nothing \n")); + struct wireless_dev *wdev = net->ieee80211_ptr; + + if (!wdev) + return -EINVAL; + + wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) + & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| + BIT(NL80211_IFTYPE_P2P_GO))); return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index bfd17c1c..05323ed5 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -42,12 +42,11 @@ typedef enum { P2PAPI_BSSCFG_MAX } p2p_bsscfg_type_t; -#define IE_MAX_LEN 300 -#define IE_MAX_LEN_PROB_RESP 768 +#define IE_MAX_LEN 512 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ struct p2p_saved_ie { u8 p2p_probe_req_ie[IE_MAX_LEN]; - u8 p2p_probe_res_ie[IE_MAX_LEN_PROB_RESP]; + u8 p2p_probe_res_ie[IE_MAX_LEN]; u8 p2p_assoc_req_ie[IE_MAX_LEN]; u8 p2p_assoc_res_ie[IE_MAX_LEN]; u8 p2p_beacon_ie[IE_MAX_LEN]; @@ -78,7 +77,6 @@ struct p2p_info { wl_p2p_sched_t noa; wl_p2p_ops_t ops; wlc_ssid_t ssid; - spinlock_t timer_lock; }; /* dongle status */ @@ -93,7 +91,8 @@ enum wl_cfgp2p_status { WLP2P_STATUS_LISTEN_EXPIRED, WLP2P_STATUS_ACTION_TX_COMPLETED, WLP2P_STATUS_ACTION_TX_NOACK, - WLP2P_STATUS_SCANNING + WLP2P_STATUS_SCANNING, + WLP2P_STATUS_GO_NEG_PHASE }; @@ -102,13 +101,13 @@ enum wl_cfgp2p_status { #define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie) #define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data) #define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) -#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ +#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:test_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ +#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:set_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : clear_bit(WLP2P_STATUS_ ## stat, \ +#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:clear_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) -#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0: change_bit(WLP2P_STATUS_ ## stat, \ +#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0:change_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) #define p2p_on(wl) ((wl)->p2p->on) #define p2p_scan(wl) ((wl)->p2p->scan) @@ -122,26 +121,33 @@ enum wl_cfgp2p_status { #define CFGP2P_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printf(KERN_ERR "CFGP2P-ERROR) %s : ", __func__); \ + printk(KERN_ERR "CFGP2P-ERROR) %s : ", __func__); \ printk args; \ } \ } while (0) #define CFGP2P_INFO(args) \ do { \ if (wl_dbg_level & WL_DBG_INFO) { \ - printf(KERN_ERR "CFGP2P-INFO) %s : ", __func__); \ + printk(KERN_ERR "CFGP2P-INFO) %s : ", __func__); \ printk args; \ } \ } while (0) #define CFGP2P_DBG(args) \ do { \ if (wl_dbg_level & WL_DBG_DBG) { \ - printf(KERN_ERR "CFGP2P-DEBUG) %s :", __func__); \ + printk(KERN_ERR "CFGP2P-DEBUG) %s :", __func__); \ printk args; \ } \ } while (0) - +extern bool +wl_cfgp2p_is_pub_action(void *frame, u32 frame_len); +extern bool +wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len); +extern bool +wl_cfgp2p_is_gas_action(void *frame, u32 frame_len); +extern void +wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len); extern s32 wl_cfgp2p_init_priv(struct wl_priv *wl); extern void @@ -261,15 +267,17 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define WL_P2P_WILDCARD_SSID_LEN 7 #define WL_P2P_INTERFACE_PREFIX "p2p" #define WL_P2P_TEMP_CHAN "11" -#define IS_PUB_ACT_FRAME(category) ((category == P2P_PUB_AF_CATEGORY)) -#define IS_P2P_ACTION(categry, action) (IS_PUB_ACT_FRAME(category) && (action == P2P_PUB_AF_ACTION)) -#define IS_GAS_REQ(category, action) (IS_PUB_ACT_FRAME(category) && \ - ((action == P2PSD_ACTION_ID_GAS_IREQ) || \ - (action == P2PSD_ACTION_ID_GAS_CREQ))) -#define IS_P2P_ACT_REQ(category, subtype) (IS_PUB_ACT_FRAME(category) && \ - ((subtype == P2P_PAF_GON_REQ) || \ - (subtype == P2P_PAF_INVITE_REQ) || \ - (subtype == P2P_PAF_PROVDIS_REQ))) + +/* If the provision discovery is for JOIN operations, then we need not do an internal scan to find GO */ +#define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL ) + +#define IS_GAS_REQ(frame, len) (wl_cfgp2p_is_gas_action(frame, len) && \ + ((frame->action == P2PSD_ACTION_ID_GAS_IREQ) || \ + (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) +#define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) (wl_cfgp2p_is_pub_action(frame, len) && \ + ((frame->subtype == P2P_PAF_GON_REQ) || \ + (frame->subtype == P2P_PAF_INVITE_REQ) || \ + ((frame->subtype == P2P_PAF_PROVDIS_REQ) && IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len)))) #define IS_P2P_SOCIAL(ch) ((ch == SOCIAL_CHAN_1) || (ch == SOCIAL_CHAN_2) || (ch == SOCIAL_CHAN_3)) #define IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0) #endif /* _wl_cfgp2p_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_dbg.h b/drivers/net/wireless/bcmdhd/wl_dbg.h new file mode 100644 index 00000000..0b99557c --- /dev/null +++ b/drivers/net/wireless/bcmdhd/wl_dbg.h @@ -0,0 +1,49 @@ +/* + * Minimal debug/trace/assert driver definitions for + * Broadcom 802.11 Networking Adapter. + * + * Copyright (C) 1999-2011, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: wl_dbg.h,v 1.115.6.3 2010-12-15 21:42:23 Exp $ + */ + + + +#ifndef _wl_dbg_h_ +#define _wl_dbg_h_ + + +extern uint32 wl_msg_level; +extern uint32 wl_msg_level2; + +#define WL_PRINT(args) printf args + + + +#define WL_NONE(args) + +#define WL_ERROR(args) +#define WL_TRACE(args) + + +extern uint32 wl_msg_level; +extern uint32 wl_msg_level2; +#endif diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index a27e723b..d60c21c0 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -36,11 +36,7 @@ #include #include -/* HTC_CSP_START */ -#ifdef CONFIG_PERFLOCK -#include -#endif -/* HTC_CSP_END */ + #include #include #include @@ -53,12 +49,9 @@ typedef const struct si_pub si_t; #include #include #include -/* HTC_CSP_START */ -#define WL_DEFAULT(x) printf x -#define WL_ERROR(x) wrnprintf x -/* HTC_CSP_END */ -#define WL_TRACE(x) -#define WL_ASSOC(x) +#define WL_ERROR(x) printf x +#define WL_TRACE(x) +#define WL_ASSOC(x) #define WL_INFORM(x) #define WL_WSEC(x) #define WL_SCAN(x) @@ -71,7 +64,7 @@ typedef const struct si_pub si_t; #endif -#define JF2MS ((((jiffies / HZ) * 1000) + ((jiffies % HZ) * 1000) / HZ)) +#define JF2MS jiffies_to_msecs(jiffies) #ifdef COEX_DBG #define WL_TRACE_COEX(x) printf("TS:%lu ", JF2MS); \ @@ -93,38 +86,7 @@ typedef const struct si_pub si_t; -#ifdef BCMWAPI_WPI -/* these items should evetually go into wireless.h of the linux system headfile dir */ -#ifndef IW_ENCODE_ALG_SM4 -#define IW_ENCODE_ALG_SM4 0x20 -#endif - -#ifndef IW_AUTH_WAPI_ENABLED -#define IW_AUTH_WAPI_ENABLED 0x20 -#endif - -#ifndef IW_AUTH_WAPI_VERSION_1 -#define IW_AUTH_WAPI_VERSION_1 0x00000008 -#endif - -#ifndef IW_AUTH_CIPHER_SMS4 -#define IW_AUTH_CIPHER_SMS4 0x00000020 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK -#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT -#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 -#endif -#endif /* BCMWAPI_WPI */ - -#ifdef BCMWAPI_WPI -#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) -#else /* BCMWAPI_WPI */ #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)) -#endif /* BCMWAPI_WPI */ #include @@ -139,36 +101,15 @@ bool g_set_essid_before_scan = TRUE; struct mutex g_wl_ss_scan_lock; #endif - -#ifdef WL_PROTECT -#define WL_PROTECT_TIME 1000 -#define WL_MAX_FAIL_COUNT 2 -typedef struct wlp_info { - struct timer_list timer; - uint32 timer_on; - uint32 reset_now; - tsk_ctl_t tsk_ctl; -} wlp_info_t; -wlp_info_t *g_wl_protect = NULL; - -static void wl_iw_protect_timerfunc(ulong data); -#endif - -static int iw_link_state = 0; -static int wl_iw_force_exit = 0; #if defined(SOFTAP) -#define WL_SOFTAP(x) printf x +#define WL_SOFTAP(x) static struct net_device *priv_dev; extern bool ap_cfg_running; -bool apsta_enable = FALSE; extern bool ap_fw_loaded; struct net_device *ap_net_dev = NULL; -tsk_ctl_t ap_eth_ctl; +tsk_ctl_t ap_eth_ctl; static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap); -int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac); -void wl_iw_apsta_restart(struct work_struct *work); -DECLARE_DELAYED_WORK(restart_apsta, wl_iw_apsta_restart); -static int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val); +static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac); #endif @@ -203,31 +144,14 @@ static struct mutex wl_softap_lock; #define DHD_OS_MUTEX_UNLOCK(a) #endif -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY -static bool use_non_dfs_channels = true; -#endif #include extern void dhd_customer_gpio_wlan_ctrl(int onoff); extern uint dhd_dev_reset(struct net_device *dev, uint8 flag); -extern void dhd_dev_init_ioctl(struct net_device *dev); -extern int wifi_get_cscan_enable(void); -extern void dhd_reset_hang_was_sent(struct net_device *dev); +extern int dhd_dev_init_ioctl(struct net_device *dev); uint wl_msg_level = WL_ERROR_VAL; -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER -char gatewaybuf[8+1]; //HTC_KlocWork -extern bool hasDLNA; -extern bool allowMulticast; -extern int dhd_set_keepalive(int value); -#endif - -extern struct perf_lock wlan_perf_lock; -extern char project_type[33]; -/* HTC_CSP_END */ - #define MAX_WLIW_IOCTL_LEN 1024 @@ -238,11 +162,8 @@ extern char project_type[33]; #define htodchanspec(i) i #define dtohchanspec(i) i -#ifdef CONFIG_WIRELESS_EXT - extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); extern int dhd_wait_pend8021x(struct net_device *dev); -#endif #if WIRELESS_EXT < 19 #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) @@ -251,21 +172,14 @@ extern int dhd_wait_pend8021x(struct net_device *dev); static void *g_scan = NULL; static volatile uint g_scan_specified_ssid; -#ifndef WL_CFG80211 static wlc_ssid_t g_specific_ssid; -static wlc_ssid_t g_ssid; -#endif -/* HTC_CSP_START */ -static int wl_active_expired = 0; -struct timer_list *wl_active_timer = NULL; -static int screen_off = 0; -/* HTC_CSP_END */ +static wlc_ssid_t g_ssid; #ifdef CONFIG_WPS2 static char *g_wps_probe_req_ie; static int g_wps_probe_req_ie_len; -#endif +#endif bool btcoex_is_sco_active(struct net_device *dev); static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl; @@ -289,11 +203,11 @@ static volatile uint g_first_counter_scans; #endif #if defined(WL_IW_USE_ISCAN) -#if !defined(CSCAN) && !defined(WL_CFG80211) +#if !defined(CSCAN) static void wl_iw_free_ss_cache(void); static int wl_iw_run_ss_cache_timer(int kick_off); #endif -#if defined(CONFIG_FIRST_SCAN) && !defined(WL_CFG80211) +#if defined(CONFIG_FIRST_SCAN) int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); #endif static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len); @@ -341,6 +255,14 @@ typedef struct iscan_info { #define BT_DHCP_FLAG_FORCE_TIME 5500 + +static int wl_iw_set_btcoex_dhcp( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +); + static void wl_iw_bt_flag_set(struct net_device *dev, bool set); static void wl_iw_bt_release(void); @@ -372,15 +294,12 @@ static void wl_iw_bt_timerfunc(ulong data); #endif iscan_info_t *g_iscan = NULL; void dhd_print_buf(void *pbuf, int len, int bytes_per_line); -#ifndef WL_CFG80211 static void wl_iw_timerfunc(ulong data); static void wl_iw_set_event_mask(struct net_device *dev); static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); -#endif /* ifndef WL_CFG80211 */ #endif -#ifndef WL_CFG80211 static int wl_iw_set_scan( struct net_device *dev, @@ -434,14 +353,6 @@ swap_key_to_BE( key->rxiv.lo = dtoh16(key->rxiv.lo); key->iv_initialized = dtoh32(key->iv_initialized); } -#endif /* ifdef WL_CFG80211 */ - -static int dev_wlc_ioctl_off = 0; - -void disable_dev_wlc_ioctl(void) -{ - dev_wlc_ioctl_off = 1; -} static int dev_wlc_ioctl( @@ -456,12 +367,6 @@ dev_wlc_ioctl( mm_segment_t fs; int ret = -EINVAL; - if (dev_wlc_ioctl_off) - { - printf("%s: module removing. skip it.\n", __FUNCTION__); - return -ENODEV; - } - if (!dev) { WL_ERROR(("%s: dev is null\n", __FUNCTION__)); return ret; @@ -507,44 +412,7 @@ dev_wlc_ioctl( return ret; } -/* HTC_CSP_START */ -#if !defined(WL_CFG80211) -static void wl_iw_act_time_expire(void) -{ - struct timer_list **timer; - timer = &wl_active_timer; - - if (*timer) { - WL_TRACE(("ac timer expired\n")); - del_timer_sync(*timer); - kfree(*timer); - *timer = NULL; - if (screen_off) - return; - wl_active_expired = 1; - } - return; -} -#endif /* !defined(WL_CFG80211) */ - -static void wl_iw_deactive(void) -{ - struct timer_list **timer; - timer = &wl_active_timer; - - if (*timer) { - WL_TRACE(("previous ac exist\n")); - del_timer_sync(*timer); - kfree(*timer); - *timer = NULL; - } - wl_active_expired = 0; - WL_TRACE(("wl_iw_deactive\n")); - return; -} -/* HTC_CSP_END*/ -#if 0 static int dev_wlc_intvar_get_reg( struct net_device *dev, @@ -583,7 +451,9 @@ dev_wlc_intvar_set_reg( return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr))); } -#endif + + + static int dev_wlc_intvar_set( @@ -622,7 +492,6 @@ dev_iw_iovar_setbuf( return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); } -#ifndef WL_CFG80211 static int dev_iw_iovar_getbuf( struct net_device *dev, @@ -639,8 +508,7 @@ dev_iw_iovar_getbuf( return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen)); } -#endif /* ifndef WL_CFG80211 */ -#endif /* if defined(WL_IW_USE_ISCAN) */ +#endif #if WIRELESS_EXT > 17 @@ -690,7 +558,6 @@ dev_wlc_bufvar_get( -#ifndef WL_CFG80211 static int dev_wlc_intvar_get( struct net_device *dev, @@ -714,7 +581,6 @@ dev_wlc_intvar_get( return (error); } -#endif /* ifndef WL_CFG80211 */ #if WIRELESS_EXT > 12 @@ -833,182 +699,6 @@ wl_iw_get_macaddr( } -#ifdef WLC_E_RSSI_LOW -static int -wl_iw_low_rssi_set( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char *p = extra; - int low_rssi_trigger; - int low_rssi_duration; - int trigger_offset; - int duration_offset; - char tran_buf[16] = {0}; - char *pp; - int err = 0; - WL_TRACE(("%s\n", __FUNCTION__)); - - trigger_offset = strcspn(extra, " "); - duration_offset = strcspn(extra+trigger_offset + 1, " "); - - pp = extra+trigger_offset+1; - - memcpy(tran_buf, pp, duration_offset); - low_rssi_trigger = bcm_strtoul(tran_buf, NULL, 10); - err |= dev_wlc_intvar_set(dev, "low_rssi_trigger", low_rssi_trigger); - - memset(tran_buf, 0, 16); - pp = extra+trigger_offset+duration_offset+2; - memcpy(tran_buf, pp, strlen(extra) - (trigger_offset+duration_offset+1)); - low_rssi_duration = bcm_strtoul(tran_buf, NULL, 10); - err |= dev_wlc_intvar_set(dev, "low_rssi_duration", low_rssi_duration); - - WL_DEFAULT(("set low rssi trigger %d, duration %d\n",low_rssi_trigger, low_rssi_duration)); - - if (err) { - WL_ERROR(("set low rssi ind fail!\n")); - p += snprintf(p, MAX_WX_STRING, "FAIL"); - } else - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return 0; -} -#endif /* WLC_E_RSSI_LOW */ - -/* HTC_CSP_START */ -#if !defined(WL_CFG80211) -int dhd_set_project(char * project, int project_len) -{ - - if ((project_len < 1) || (project_len > 32)) { - printf("Invaild project name length!\n"); - return -1; - } - - strncpy(project_type, project, project_len); - WL_DEFAULT(("%s: set project type: %s\n", __FUNCTION__, project_type)); - - return 0; -} - -static int -wl_iw_set_project( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char project[33]; - char *p = extra; - int project_offset; - int project_size; - - WL_TRACE(("%s\n", __FUNCTION__)); - - memset(project, 0, sizeof(project)); - - project_offset = strcspn(extra, " "); - project_size = strlen(extra) - project_offset; - - if (project_offset == 0) { - WL_ERROR(("%s, no project specified\n", __FUNCTION__)); - return 0; - } - - if (project_size > 32) { - WL_ERROR(("%s: project name is too long: %s\n", __FUNCTION__, - (char *)extra + project_offset + 1)); - return 0; - } - - strncpy(project, extra + project_offset + 1, - MIN(project_size, sizeof(project))); - - WL_DEFAULT(("%s: set project: %s\n", __FUNCTION__, project)); - dhd_set_project(project, project_size); - - p += snprintf(p, MAX_WX_STRING, "OK"); - wrqu->data.length = p - extra + 1; - - return 0; -} -#endif /* #if !defined(WL_CFG80211) */ -/* HTC_CSP_END */ - -static int -wl_iw_scan_minrssi( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char *p = extra; - int minrssi = 0; - int err = 0; - - WL_TRACE(("%s\n", __FUNCTION__)); - - minrssi = bcm_strtoul((char *)(extra + strlen("SCAN_MINRSSI") + 1), NULL, 10); - - err = dev_wlc_intvar_set(dev, "scanresults_minrssi", minrssi); - - if (err) { - WL_ERROR(("set scan_minrssi fail!\n")); - p += snprintf(p, MAX_WX_STRING, "FAIL"); - } else - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return 0; -} - -#ifdef PNO_SUPPORT -static int -wl_iw_del_pfn( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char ssid[33]; - char *p = extra; - int ssid_offset; - int ssid_size; - - WL_TRACE(("%s\n", __FUNCTION__)); - - memset(ssid, 0, sizeof(ssid)); - - ssid_offset = strcspn(extra, " "); - ssid_size = strlen(extra) - ssid_offset; - - if (ssid_offset == 0) { - WL_ERROR(("%s, no ssid specified\n", __FUNCTION__)); - return 0; - } - - strncpy(ssid, extra + ssid_offset+1, - MIN(ssid_size, sizeof(ssid))); - - WL_ERROR(("%s: remove ssid: %s\n", __FUNCTION__, ssid)); - dhd_del_pfn_ssid(ssid, ssid_size); - - p += snprintf(p, MAX_WX_STRING, "OK"); - wrqu->data.length = p - extra + 1; - - return 0; -} -#endif static int wl_iw_set_country( @@ -1027,16 +717,11 @@ wl_iw_set_country( char smbuf[WLC_IOCTL_SMLEN]; scb_val_t scbval; - channel_info_t ci; - int retry = 0; cspec.rev = -1; memset(country_code, 0, sizeof(country_code)); memset(smbuf, 0, sizeof(smbuf)); -#ifdef HTC_KlocWork - memset(&ci,0,sizeof(ci)); -#endif - + country_offset = strcspn(extra, " "); country_code_size = strlen(extra) - country_offset; @@ -1052,36 +737,16 @@ wl_iw_set_country( goto exit_failed; } - WL_DEFAULT(("%s: Try to set country %s\n", __FUNCTION__, country_code)); -get_channel_retry: - if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) { - WL_ERROR(("%s: get channel fail!\n", __FUNCTION__)); - goto exit_failed; - } - ci.scan_channel = dtoh32(ci.scan_channel); - if (ci.scan_channel) { - retry++; - WL_ERROR(("%s: scan in progress, retry %d!\n", __FUNCTION__, retry)); - if (retry > 3) - goto exit_failed; - bcm_mdelay(1000); - goto get_channel_retry; - } memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); -/* HTC_CSP_START */ - if (!strncmp(cspec.country_abbrev, "US", 2)) - cspec.rev = 5; -/* HTC_CSP_END */ - get_customized_country_code((char *)&cspec.country_abbrev, &cspec); if ((error = dev_iw_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), smbuf, sizeof(smbuf))) >= 0) { p += snprintf(p, MAX_WX_STRING, "OK"); - WL_TRACE(("%s: set country for %s as %s rev %d is OK\n", + WL_ERROR(("%s: set country for %s as %s rev %d is OK\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev)); dhd_bus_country_set(dev, &cspec); goto exit; @@ -1099,518 +764,83 @@ wl_iw_set_country( return error; } -/* HTC_CSP_START */ -#ifdef CUSTOMER_HW2 -static int active_level = -80; -static int active_period = 20000; //in mini secs - -void wl_iw_set_active_level(int level) +static int +wl_iw_set_power_mode( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) { - active_level = level; - printf("set active level to %d\n", active_level); - return; -} + int error = 0; + char *p = extra; + static int pm = PM_FAST; + int pm_local = PM_OFF; + char powermode_val = 0; -void wl_iw_set_active_period(int period) -{ - active_period = period; - printf("set active_period to %d\n", active_period); - return; -} + WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra)); -int wl_iw_get_active_level(void) -{ - return active_level; -} + strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1); -int wl_iw_get_active_period(void) -{ - return active_period; -} + if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { -void wl_iw_set_screen_off(int off) -{ - screen_off = off; - if (screen_off) - wl_iw_deactive(); + WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - return; -} -#if !defined(WL_CFG80211) -static void btcoex_dhcp_timer_stop(struct net_device *dev) -{ - char buf_reg66val_defualt[8] = { 66, 00, 00, 00, 0x88, 0x13, 0x00, 0x00 }; - char buf_reg41val_defualt[8] = { 41, 00, 00, 00, 0x13, 0x00, 0x00, 0x00 }; - char buf_reg68val_defualt[8] = { 68, 00, 00, 00, 0x14, 0x00, 0x00, 0x00 }; -#ifdef BTCOEX_TIMER_ENABLED - char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; + dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)); + dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); - WL_DEFAULT(("%s disable BT DHCP Timer\n", __FUNCTION__)); - if (g_bt&&g_bt->timer_on) { - g_bt->timer_on = 0; - del_timer_sync(&g_bt->timer); - WL_DEFAULT(("%s BT DHCP Timer disabled\n", __FUNCTION__)); - } + + net_os_set_packet_filter(dev, 0); - dev_wlc_bufvar_set(dev, "btc_flags", \ - (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); -#endif +#ifdef COEX_DHCP + g_bt->ts_dhcp_start = JF2MS; + g_bt->dhcp_done = FALSE; + WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n", + __FUNCTION__, pm, pm_local)); - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg66val_defualt[0], sizeof(buf_reg66val_defualt)); +#endif + } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { + - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg41val_defualt[0], sizeof(buf_reg41val_defualt)); + dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg68val_defualt[0], sizeof(buf_reg68val_defualt)); -} + + net_os_set_packet_filter(dev, 1); -static int btcoex_dhcp_timer_start(struct net_device *dev) -{ - char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; - char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; - char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; -//#ifdef BTCOEX_TIMER_ENABLED - static char ioctlbuf[MAX_WLIW_IOCTL_LEN]; - char buf_reg12va_sco_time[4] = { 12, 0, 0, 0}; - int sco_lasttime = 0; - int ret; +#ifdef COEX_DHCP + g_bt->dhcp_done = TRUE; + g_bt->ts_dhcp_ok = JF2MS; + WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n", + __FUNCTION__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm)); +#endif - bcm_mkiovar("btc_params", (char*)&buf_reg12va_sco_time[0], sizeof(buf_reg12va_sco_time), ioctlbuf, sizeof(ioctlbuf)); - ret = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN); - if ( !ret ){ - sco_lasttime = dtoh32(*(unsigned int*)ioctlbuf); - printf("%s: sco time=%x\n", __FUNCTION__, sco_lasttime); } else { - printf("%s: get sco last time error. ret =%d\n", __FUNCTION__, ret); + WL_ERROR(("%s Unkwown yet power setting, ignored\n", + __FUNCTION__)); } - if (g_bt&&g_bt->timer_on) { - printf("%s: BT DHCP Timer has enabled\n", __FUNCTION__); - if (sco_lasttime) { - /* stop timer if sco running. */ - printf("%s: SCO running stop timer.\n", __FUNCTION__); - btcoex_dhcp_timer_stop(dev); - } - return 1; - } + p += snprintf(p, MAX_WX_STRING, "OK"); - if (sco_lasttime) { - printf("%s: SCO running, skip it.\n", __FUNCTION__); - return 1; - } -//#endif + wrqu->data.length = p - extra + 1; - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on)); + return error; +} - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on)); - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on)); +bool btcoex_is_sco_active(struct net_device *dev) +{ + int ioc_res = 0; + bool res = FALSE; + int sco_id_cnt = 0; + int param27; + int i; -#ifdef BTCOEX_TIMER_ENABLED - g_bt->bt_state = BT_DHCP_START; - g_bt->timer_on = 1; - mod_timer(&g_bt->timer, g_bt->timer.expires); + for (i = 0; i < 12; i++) { - printf("%s: enable BT DHCP Timer\n", __FUNCTION__); -#endif + ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); - return 0; -} -#endif /* #if !defined(WL_CFG80211) */ - -#if !defined(WL_CFG80211) -extern int dhdcdc_power_active_while_plugin; -extern int dhdcdc_wifiLock; - -static int -wl_iw_set_power_mode( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; - char *s; - int pm_val; - - if (dev_wlc_ioctl_off) { - WL_ERROR(("%s: wl driver going down!\n", __func__)); - goto end; - } - - s = extra + strlen("POWERMODE") + 1; - pm_val = bcm_atoi(s); - - switch (pm_val) { - /* Android normal usage */ - case 0: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_ANDROID_NORMAL); - dhdhtc_update_wifi_power_mode(screen_off); - btcoex_dhcp_timer_stop(dev); - break; - case 1: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_ANDROID_NORMAL); - dhdhtc_update_wifi_power_mode(screen_off); - btcoex_dhcp_timer_start(dev); - break; - /* for web loading page */ - case 10: - wl_iw_deactive(); - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 11: - if (!screen_off) { - struct timer_list **timer; - timer = &wl_active_timer; - - if (*timer) { - mod_timer(*timer, jiffies + active_period * HZ / 1000); - /* printf("mod_timer\n"); */ - } else { - *timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); - if (*timer) { - (*timer)->function = (void *)wl_iw_act_time_expire; - init_timer(*timer); - (*timer)->expires = jiffies + active_period * HZ / 1000; - add_timer(*timer); - /* printf("add_timer\n"); */ - } - } - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_BROWSER_LOAD_PAGE); - dhdhtc_update_wifi_power_mode(screen_off); - } - break; - /* for best performance configure */ - case 20: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_USER_CONFIG); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 21: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_USER_CONFIG); - dhdhtc_update_wifi_power_mode(screen_off); - break; - /* for fota download */ - case 30: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 31: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_FOTA_DOWNLOADING); - dhdhtc_update_wifi_power_mode(screen_off); - break; - - case 87: /* For wifilock release*/ - printf("wifilock release\n"); - dhdcdc_wifiLock = 0; - dhdhtc_update_wifi_power_mode(screen_off); - dhdhtc_update_dtim_listen_interval(screen_off); - break; - - case 88: /* For wifilock lock*/ - printf("wifilock accquire\n"); - dhdcdc_wifiLock = 1; - dhdhtc_update_wifi_power_mode(screen_off); - dhdhtc_update_dtim_listen_interval(screen_off); - break; - - case 99: /* For debug. power active or not while usb plugin */ - dhdcdc_power_active_while_plugin = !dhdcdc_power_active_while_plugin; - dhdhtc_update_wifi_power_mode(screen_off); - break; -#if 0 - /* for wifi phone */ - case 30: - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - break; - case 31: - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - break; -#endif - default: - WL_ERROR(("%s: not support mode: %d\n", __func__, pm_val)); - break; - - } - -end: - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return error; -} - -static int -wl_iw_get_power_mode( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error; - char *p = extra; - int pm_local=PM_OFF, pm_and; //HTC_KlocWork, add PM_OFF - - error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local)); - if (!error) { - WL_TRACE(("%s: Powermode = %d\n", __func__, pm_local)); - if (pm_local == PM_OFF) - pm_and = 1; /* Active */ - else - pm_and = 0; /* Auto */ - p += snprintf(p, MAX_WX_STRING, "and_pm = %d, dhd_pm: %d, " - "ctrl_mask: 0x%x, usb_act: %d\n", pm_and, pm_local, - dhdhtc_get_cur_pwr_ctrl(), dhdcdc_power_active_while_plugin); - } - else { - WL_TRACE(("%s: Error = %d\n", __func__, error)); - p += snprintf(p, MAX_WX_STRING, "FAIL"); - } - wrqu->data.length = p - extra + 1; - - printf("getpower: %s\n", extra); - return error; -} -static int -wl_iw_get_wifilock_mode( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char *p = extra; - - p += snprintf(p, MAX_WX_STRING, "%d", dhdcdc_wifiLock); - wrqu->data.length = p - extra + 1; - - printf("dhdcdc_wifiLock: %s\n", extra); - return 0; -} - -static int wl_iw_wifi_call = 0; -// static struct perf_lock wl_wificall_perf_lock; -static struct mutex wl_wificall_mutex; - -int wl_iw_is_during_wifi_call(void) -{ - return wl_iw_wifi_call; -} - -static int -wl_iw_set_wifi_call( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char *p = extra; - char *s; - int set_val; - - mutex_lock(&wl_wificall_mutex); - s = extra + strlen("WIFICALL") + 1; - set_val = bcm_atoi(s); - - /* 1. change power mode - * 2. change dtim listen interval - * 3. lock/unlock cpu freq - */ - - switch (set_val) { - case 0: - if (0 == wl_iw_is_during_wifi_call()) { - printf("wifi call is in disconnected state!\n"); - break; - } - - printf("wifi call ends: %d\n", set_val); - wl_iw_wifi_call = 0; - - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - - dhdhtc_update_dtim_listen_interval(screen_off); - - // perf_unlock(&wl_wificall_perf_lock); - break; - case 1: - if (1 == wl_iw_is_during_wifi_call()) { - printf("wifi call is already in running state!\n"); - break; - } - - printf("wifi call comes: %d\n", set_val); - wl_iw_wifi_call = 1; - - dhdhtc_set_power_control(1, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - - dhdhtc_update_dtim_listen_interval(screen_off); - - // perf_lock(&wl_wificall_perf_lock); - break; - default: - WL_ERROR(("%s: not support mode: %d\n", __func__, set_val)); - break; - - } - - p += snprintf(p, MAX_WX_STRING, "OK"); - wrqu->data.length = p - extra + 1; - mutex_unlock(&wl_wificall_mutex); - - return 0; -} -#endif /* !defined(WL_CFG80211) */ -#endif -/* HTC_CSP_END */ - -#if 0 -#if defined(WL_CFG80211) -static int -wl_iw_set_p2p_mpc( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; - static int mpc = -1; - static int arpoe = -1; - char mpc_val = 0; - int res = 0; - - - WL_ERROR(("enter %s\n", __FUNCTION__)); - strncpy((char *)&mpc_val, extra + strlen("P2P_MPC_SET") +1, 1); - - if (strnicmp((char *)&mpc_val, "1", strlen("1")) == 0) { - mpc = 1; - arpoe = 1; - if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { - WL_ERROR(("%s fail to set mpc %d\n", __FUNCTION__, mpc)); - } - if ((res = dev_wlc_intvar_set(dev, "arpoe", arpoe))) { - WL_ERROR(("%s fail to set arpoe %d\n", __FUNCTION__, arpoe)); - } - } else if (strnicmp((char *)&mpc_val, "0", strlen("0")) == 0) { - mpc = 0; - arpoe = 0; - if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { - WL_ERROR(("%s fail to set mpc %d\n", __FUNCTION__, mpc)); - } - if ((res = dev_wlc_intvar_set(dev, "arpoe", arpoe))) { - WL_ERROR(("%s fail to set arpoe %d\n", __FUNCTION__, arpoe)); - } - } else { - WL_ERROR(("%s Unkwown yet mpc setting, ignored\n", - __FUNCTION__)); - } - - printf("set mpc to %d\n", mpc); - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return error; -} -#endif -#endif - -#if 0 -#if !defined(WL_CFG80211) -static int -wl_iw_set_power_mode( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; - static int pm = PM_FAST; - int pm_local = PM_OFF; - char powermode_val = 0; - - WL_TRACE_COEX(("%s: DHCP session cmd:%s\n", __FUNCTION__, extra)); - - strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1); - - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - - dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)); - dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); - - - net_os_set_packet_filter(dev, 0); - -#ifdef COEX_DHCP - g_bt->ts_dhcp_start = JF2MS; - g_bt->dhcp_done = FALSE; - WL_TRACE_COEX(("%s: DHCP start, pm:%d changed to pm:%d\n", - __FUNCTION__, pm, pm_local)); - -#endif - } else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { - - - dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); - - - net_os_set_packet_filter(dev, 1); - -#ifdef COEX_DHCP - g_bt->dhcp_done = TRUE; - g_bt->ts_dhcp_ok = JF2MS; - WL_TRACE_COEX(("%s: DHCP done for:%d ms, restored pm:%d\n", - __FUNCTION__, (g_bt->ts_dhcp_ok - g_bt->ts_dhcp_start), pm)); -#endif - - } else { - WL_ERROR(("%s Unkwown yet power setting, ignored\n", - __FUNCTION__)); - } - - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return error; -} -#endif - -bool btcoex_is_sco_active(struct net_device *dev) -{ - int ioc_res = 0; - bool res = FALSE; - int sco_id_cnt = 0; - int param27; - int i; - - for (i = 0; i < 12; i++) { - - ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); - - WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n", - __FUNCTION__, i, param27)); + WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n", + __FUNCTION__, i, param27)); if (ioc_res < 0) { WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__)); @@ -1729,7 +959,6 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco) #endif -#if !defined(WL_CFG80211) static int wl_iw_get_power_mode( struct net_device *dev, @@ -1739,7 +968,7 @@ wl_iw_get_power_mode( ) { int error = 0; - int pm_local = PM_FAST; + int pm_local; char *p = extra; error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local)); @@ -1888,11 +1117,9 @@ wl_iw_set_btcoex_dhcp( return error; } -#endif -#endif /* #if 0 */ static int -wl_iw_set_suspend( +wl_iw_set_suspend_opt( struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, @@ -1903,16 +1130,15 @@ char *extra int ret_now; int ret = 0; - suspend_flag = *(extra + strlen(SETSUSPEND_CMD) + 1) - '0'; + suspend_flag = *(extra + strlen(SETSUSPENDOPT_CMD) + 1) - '0'; if (suspend_flag != 0) suspend_flag = 1; ret_now = net_os_set_suspend_disable(dev, suspend_flag); - if (ret_now != suspend_flag) { - if (!(ret = net_os_set_suspend(dev, ret_now))) + if (!(ret = net_os_set_suspend(dev, ret_now, 1))) WL_ERROR(("%s: Suspend Flag %d -> %d\n", __FUNCTION__, ret_now, suspend_flag)); else @@ -1922,21 +1148,31 @@ char *extra return ret; } -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY static int -wl_iw_set_dfs_channels( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra +wl_iw_set_suspend_mode( +struct net_device *dev, +struct iw_request_info *info, +union iwreq_data *wrqu, +char *extra ) { - use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0'; - use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true; - wl_iw_set_country_code(dev, NULL); - return 0; -} + int ret = 0; + +#if !defined(CONFIG_HAS_EARLYSUSPEND) || !defined(DHD_USE_EARLYSUSPEND) + int suspend_flag; + + suspend_flag = *(extra + strlen(SETSUSPENDMODE_CMD) + 1) - '0'; + + if (suspend_flag != 0) + suspend_flag = 1; + + if (!(ret = net_os_set_suspend(dev, suspend_flag, 0))) + WL_ERROR(("%s: Suspend Mode %d\n",__FUNCTION__,suspend_flag)); + else + WL_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); #endif + return ret; +} static int wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) @@ -2350,73 +1586,64 @@ wl_iw_set_pno_set( net_os_wake_unlock(dev); return res; } -#endif -/* HTC_CSP_START */ -/* traffic indicate parameters */ -/* framework will obtain RSSI every 3000 ms*/ -/* The throughput mapping to packet count is as below: - * 2Mbps: ~280 packets / second - * 4Mbps: ~540 packets / second - * 6Mbps: ~800 packets / second - * 8Mbps: ~1200 packets / second - * 12Mbps: ~1500 packets / second - * 14Mbps: ~1800 packets / second - * 16Mbps: ~2000 packets / second - * 18Mbps: ~2300 packets / second - * 20Mbps: ~2600 packets / second - */ -#define TRAFFIC_HIGH_WATER_MARK 2300 *(3000/1000) -#define TRAFFIC_LOW_WATER_MARK 256 * (3000/1000) -typedef enum traffic_ind { - TRAFFIC_STATS_HIGH = 0, - TRAFFIC_STATS_NORMAL, -} traffic_ind_t; - - -static int traffic_stats_flag = TRAFFIC_STATS_NORMAL; -static unsigned long current_traffic_count = 0; -static unsigned long last_traffic_count = 0; -extern struct perf_lock wlan_perf_lock; - -static void wl_iw_traffic_monitor(struct net_device *dev) -{ - unsigned long rx_packets_count = 0; - unsigned long tx_packets_count = 0; - unsigned long traffic_diff = 0; - - /*for Traffic High/Low indication */ - dhd_get_txrx_stats(dev, &rx_packets_count, &tx_packets_count); - current_traffic_count = rx_packets_count + tx_packets_count; - - if (current_traffic_count >= last_traffic_count) { - traffic_diff = current_traffic_count - last_traffic_count; - if (traffic_stats_flag == TRAFFIC_STATS_NORMAL) { - if (traffic_diff > TRAFFIC_HIGH_WATER_MARK) { - traffic_stats_flag = TRAFFIC_STATS_HIGH; -#if 0 -/* #ifdef CONFIG_PERFLOCK */ - if (!is_perf_lock_active(&wlan_perf_lock)) - perf_lock(&wlan_perf_lock); -#endif - printf("lock cpu here, traffic-count=%ld\n", traffic_diff / 3); - } - } else { - if (traffic_diff < TRAFFIC_LOW_WATER_MARK) { - traffic_stats_flag = TRAFFIC_STATS_NORMAL; -#if 0 -/* #ifdef CONFIG_PERFLOCK */ - if (is_perf_lock_active(&wlan_perf_lock)) - perf_unlock(&wlan_perf_lock); -#endif - printf("unlock cpu here, traffic-count=%ld\n", traffic_diff / 3); - } - } - } - last_traffic_count = current_traffic_count; - /*End of Traffic High/Low indication */ +static int +wl_iw_set_pno_setadd( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int ret = -1; + char *tmp_ptr; + int size, tmp_size; + + net_os_wake_lock(dev); + WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", + __FUNCTION__, info->cmd, info->flags, + wrqu->data.pointer, wrqu->data.length)); + + if (g_onoff == G_WLAN_SET_OFF) { + WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); + goto exit_proc; + } + + if (wrqu->data.length <= strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)) { + WL_ERROR(("%s argument=%d less than %d\n", __FUNCTION__, + wrqu->data.length, (int)(strlen(PNOSETADD_SET_CMD) + sizeof(cmd_tlv_t)))); + goto exit_proc; + } + + + bcopy(PNOSETUP_SET_CMD, extra, strlen(PNOSETUP_SET_CMD)); + + tmp_ptr = extra + strlen(PNOSETUP_SET_CMD); + size = wrqu->data.length - strlen(PNOSETUP_SET_CMD); + tmp_size = size; + + while (*tmp_ptr && tmp_size > 0) { + if ((*tmp_ptr == 'S') && (size - tmp_size) >= sizeof(cmd_tlv_t)) { + *(tmp_ptr + 1) = ((*(tmp_ptr + 1) - '0') << 4) + (*(tmp_ptr + 2) - '0'); + memmove(tmp_ptr + 2, tmp_ptr + 3, tmp_size - 3); + tmp_size -= 2 + *(tmp_ptr + 1); + tmp_ptr += 2 + *(tmp_ptr + 1); + size--; + } else { + tmp_ptr++; + tmp_size--; + } + } + + wrqu->data.length = strlen(PNOSETUP_SET_CMD) + size; + ret = wl_iw_set_pno_set(dev, info, wrqu, extra); + +exit_proc: + net_os_wake_unlock(dev); + return ret; + } -/* HTC_CSP_END */ +#endif static int wl_iw_get_rssi( @@ -2453,18 +1680,9 @@ wl_iw_get_rssi( } } - /* HTC_CSP_START */ - /* if rssi is 0, it means we lost the connection */ - if (rssi == 0) - rssi = WL_IW_RSSI_MINVAL; - /* HTC_CSP_END */ - p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi); wrqu->data.length = p - extra + 1; -/* HTC_CSP_START */ - wl_iw_traffic_monitor(dev); -/* HTC_CSP_END */ net_os_wake_unlock(dev); return error; } @@ -2484,24 +1702,12 @@ wl_iw_send_priv_event( if (strlen(flag) > sizeof(extra)) return -1; -#ifdef HTC_KlocWork - strncpy(extra, flag, IW_CUSTOM_MAX + 1); -#else strcpy(extra, flag); -#endif wrqu.data.length = strlen(extra); wireless_send_event(dev, cmd, &wrqu, extra); - net_os_wake_lock_timeout_enable(dev, DHD_EVENT_TIMEOUT); + net_os_wake_lock_ctrl_timeout_enable(dev, DHD_EVENT_TIMEOUT_MS); WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); -#ifdef WL_PROTECT - if ( !strncmp( flag, "HANG", 4) && g_wl_protect ){ - g_wl_protect->reset_now = 1; - WL_TRACE(("%s: Reset firmware\n", __FUNCTION__)); - up(&g_wl_protect->tsk_ctl.sema); - } -#endif - return 0; } @@ -2540,7 +1746,6 @@ wl_control_wl_start(struct net_device *dev) #if defined(BCMLXSDMMC) sdioh_start(NULL, 1); #endif - if (!ret) dhd_dev_init_ioctl(dev); @@ -2549,23 +1754,9 @@ wl_control_wl_start(struct net_device *dev) WL_TRACE(("Exited %s\n", __FUNCTION__)); dhd_net_if_unlock(dev); - -#ifdef WL_PROTECT - if (g_wl_protect && !g_wl_protect->timer_on) { - g_wl_protect->timer_on = 1; - mod_timer(&g_wl_protect->timer, jiffies + WL_PROTECT_TIME*HZ/1000); - WL_TRACE(("%s Start WL Protect Timer\n", __FUNCTION__)); - } -#endif - return ret; } -int wl_iw_get_onoff() -{ - return g_onoff; -} - static int wl_iw_control_wl_off( @@ -2576,7 +1767,7 @@ wl_iw_control_wl_off( wl_iw_t *iw; int ret = 0; - WL_DEFAULT(("Enter %s\n", __FUNCTION__)); + WL_TRACE(("Enter %s\n", __FUNCTION__)); if (!dev) { WL_ERROR(("%s: dev is null\n", __FUNCTION__)); @@ -2592,14 +1783,6 @@ wl_iw_control_wl_off( dhd_net_if_lock(dev); -#ifdef WL_PROTECT - if (g_wl_protect && g_wl_protect->timer_on) { - g_wl_protect->timer_on = 0; - del_timer_sync(&g_wl_protect->timer); - WL_TRACE(("%s Stop WL Protect Timer\n", __FUNCTION__)); - } -#endif - #ifdef SOFTAP ap_cfg_running = FALSE; #endif @@ -2611,10 +1794,10 @@ wl_iw_control_wl_off( g_iscan->iscan_state = ISCAN_STATE_IDLE; #endif - dhd_dev_reset(dev, 1); + ret = dhd_dev_reset(dev, 1); #if defined(WL_IW_USE_ISCAN) -#if !defined(CSCAN) && !defined(WL_CFG80211) +#if !defined(CSCAN) wl_iw_free_ss_cache(); wl_iw_run_ss_cache_timer(0); @@ -2634,8 +1817,6 @@ wl_iw_control_wl_off( sdioh_stop(NULL); #endif - - dhd_os_wake_force_unlock(iw->pub); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); wl_iw_send_priv_event(dev, "STOP"); @@ -2662,7 +1843,6 @@ wl_iw_control_wl_on( wl_iw_send_priv_event(dev, "START"); -#ifndef WL_CFG80211 #ifdef SOFTAP if (!ap_fw_loaded) { wl_iw_iscan_set_scan_broadcast_prep(dev, 0); @@ -2670,12 +1850,6 @@ wl_iw_control_wl_on( #else wl_iw_iscan_set_scan_broadcast_prep(dev, 0); #endif -#else - /* anthony: don't need to invert ret value here. - * return 0 to upper-layer if success - */ - //ret = (ret)?0:1; -#endif /* !WL_CFG80211 */ WL_TRACE(("Exited %s\n", __FUNCTION__)); @@ -2684,10 +1858,7 @@ wl_iw_control_wl_on( #ifdef SOFTAP static struct ap_profile my_ap; -static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap); -#ifndef AP_ONLY -static int set_apsta_cfg(struct net_device *dev, struct ap_profile *ap); -#endif +static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap); static int get_assoc_sta_list(struct net_device *dev, char *buf, int len); static int set_ap_mac_list(struct net_device *dev, void *buf); @@ -2698,7 +1869,6 @@ static int set_ap_mac_list(struct net_device *dev, void *buf); static int get_parameter_from_string( char **str_ptr, const char *token, int param_type, void *dst, int param_max_len); -#endif static int hex2num(char c) @@ -2735,7 +1905,7 @@ hstr_2_buf(const char *txt, u8 *buf, int len) } -#ifdef SOFTAP + static int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) { @@ -2751,16 +1921,11 @@ init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) PTYPE_STRING, sub_cmd, SSID_LEN) != 0) { return -1; } - /* broadcom, init apsta_enable flag here */ - apsta_enable = FALSE; if (strncmp(sub_cmd, "AP_CFG", 6)) { - /* broadcom, add the APSTA_CFG detection */ - if (strncmp(sub_cmd, "APSTA_CFG", 9)) { - WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd)); - return -1; - } - apsta_enable = TRUE; + WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd)); + return -1; } + ret = get_parameter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN); @@ -2771,22 +1936,27 @@ init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) ret |= get_parameter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5); - ret |= get_parameter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5); + + get_parameter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5); - ret |= get_parameter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5); + + get_parameter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5); - /* [kenn] temp mark for hidden AP - ret |= get_parameter_from_string(&str_ptr, "HIDDEN=", PTYPE_INTDEC, &ap_cfg->closednet, 5); - */ -#if 0 + + get_parameter_from_string(&str_ptr, "HIDDEN=", + PTYPE_INTDEC, &ap_cfg->closednet, 5); + + get_parameter_from_string(&str_ptr, "COUNTRY=", PTYPE_STRING, &ap_cfg->country_code, 3); -#endif + return ret; } +#endif +#ifdef SOFTAP static int iwpriv_set_ap_config(struct net_device *dev, struct iw_request_info *info, @@ -2820,11 +1990,7 @@ iwpriv_set_ap_config(struct net_device *dev, } extra[wrqu->data.length] = 0; - -/* HTC_CSP_START */ - /* WL_SOFTAP((" Got str param in iw_point: %s\n", extra)); */ - WL_SOFTAP((" Got str param in iw_point\n")); -/* HTC_CSP_END*/ + WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra)); memset(ap_cfg, 0, sizeof(struct ap_profile)); @@ -2844,18 +2010,9 @@ iwpriv_set_ap_config(struct net_device *dev, return -1; } - /* broadcom, call set_apsta_cfg if apsta_enable is true. */ -#ifndef AP_ONLY - if ( apsta_enable ) { - if ((res = set_apsta_cfg(dev, ap_cfg)) < 0) - WL_ERROR(("%s failed to set_apsta_cfg %d\n", __FUNCTION__, res)); - } else { -#endif - if ((res = set_ap_cfg(dev, ap_cfg)) < 0) - WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res)); -#ifndef AP_ONLY - } -#endif + if ((res = set_ap_cfg(dev, ap_cfg)) < 0) + WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res)); + kfree(extra); return res; @@ -2876,76 +2033,104 @@ static int iwpriv_get_assoc_list(struct net_device *dev, char mac_lst[384]; char *p_mac_str; - WL_TRACE(("%s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, " - "iwp.len:%p, iwp.flags:%x\n", __FUNCTION__, info->cmd, info->flags, - extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags)); + char *p_mac_str_end; + wl_iw_t *iw; + + if ((!dev) || (!extra)) { + + return -EINVAL; + } + + + iw = *(wl_iw_t **)netdev_priv(dev); + + net_os_wake_lock(dev); + DHD_OS_MUTEX_LOCK(&wl_softap_lock); + + WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d," + "iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, + extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags)); -/* HTC_CSP_START */ - //WL_SOFTAP(("extra:%s\n", extra)); - //dhd_print_buf((u8 *)p_iwrq, 16, 0); -/* HTC_CSP_END */ memset(sta_maclist, 0, sizeof(mac_buf)); sta_maclist->count = 8; - WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf))); - get_assoc_sta_list(dev, mac_buf, 256); - WL_TRACE((" got %d stations\n", sta_maclist->count)); + WL_SOFTAP(("%s: net device:%s, buf_sz:%d\n", + __FUNCTION__, dev->name, sizeof(mac_buf))); + + if ((ret = get_assoc_sta_list(dev, mac_buf, sizeof(mac_buf))) < 0) { + WL_ERROR(("%s: sta list ioctl error:%d\n", + __FUNCTION__, ret)); + goto func_exit; + } + + WL_SOFTAP(("%s: got %d stations\n", __FUNCTION__, + sta_maclist->count)); memset(mac_lst, 0, sizeof(mac_lst)); p_mac_str = mac_lst; + p_mac_str_end = &mac_lst[sizeof(mac_lst)-1]; -/* HTC_CSP_START */ - /* format: "count|sta 1, sta2, ..." - */ - p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, "%d|", sta_maclist->count); - - for (i = 0; i < sta_maclist->count; i++) { + for (i = 0; i < 8; i++) { struct ether_addr * id = &sta_maclist->ea[i]; + if (!ETHER_ISNULLADDR(id->octet)) { + scb_val_t scb_val; + int rssi = 0; + bzero(&scb_val, sizeof(scb_val_t)); - //WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i)); - //dhd_print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0); + + if ((p_mac_str_end - p_mac_str) <= 36) { + WL_ERROR(("%s: mac list buf is < 36 for item[%i] item\n", + __FUNCTION__, i)); + break; + } - p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, - "%02X:%02X:%02X:%02X:%02X:%02X,", + p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, + "\nMac[%d]=%02X:%02X:%02X:%02X:%02X:%02X,", i, id->octet[0], id->octet[1], id->octet[2], id->octet[3], id->octet[4], id->octet[5]); + + + bcopy(id->octet, &scb_val.ea, 6); + ret = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); + if (ret < 0) { + snprintf(p_mac_str, MAX_WX_STRING, "RSSI:ERR"); + WL_ERROR(("%s: RSSI ioctl error:%d\n", + __FUNCTION__, ret)); + break; + } + + rssi = dtoh32(scb_val.val); + p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, + "RSSI:%d", rssi); + } } -/* HTC_CSP_END */ - p_iwrq->data.length = strlen(mac_lst); + p_iwrq->data.length = strlen(mac_lst)+1; - WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer)); - WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length)); + WL_SOFTAP(("%s: data to user:\n%s\n usr_ptr:%p\n", __FUNCTION__, + mac_lst, p_iwrq->data.pointer)); if (p_iwrq->data.length) { - if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) { - WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__)); - return -EFAULT; - } + bcopy(mac_lst, extra, p_iwrq->data.length); } - WL_DEFAULT(("Exited %s \n", __FUNCTION__)); +func_exit: + + DHD_OS_MUTEX_UNLOCK(&wl_softap_lock); + net_os_wake_unlock(dev); + + WL_SOFTAP(("%s: Exited\n", __FUNCTION__)); return ret; } #endif #ifdef SOFTAP -#ifdef CUSTOMER_HW2 -static int -iwpriv_set_mac_filters(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - return 0; -} -#else #define MAC_FILT_MAX 8 static int iwpriv_set_mac_filters(struct net_device *dev, struct iw_request_info *info, @@ -3015,7 +2200,7 @@ static int iwpriv_set_mac_filters(struct net_device *dev, WL_SOFTAP(("MAC_MODE=:%d, MAC_CNT=%d, MACs:..\n", mac_mode, mac_cnt)); for (i = 0; i < mac_cnt; i++) { WL_SOFTAP(("mac_filt[%d]:", i)); - //dhd_print_buf(&p_ea[i], 6, 0); + dhd_print_buf(&p_ea[i], 6, 0); } @@ -3038,7 +2223,6 @@ static int iwpriv_set_mac_filters(struct net_device *dev, kfree(extra); return ret; } -#endif /* CUSTOMER_HW2 */ #endif @@ -3092,7 +2276,6 @@ typedef int (*iw_handler)(struct net_device *dev, char *extra); #endif -#ifndef WL_CFG80211 static int wl_iw_config_commit( struct net_device *dev, @@ -3104,9 +2287,6 @@ wl_iw_config_commit( wlc_ssid_t ssid; int error; struct sockaddr bssid; -#ifdef HTC_KlocWork - memset(&ssid, 0, sizeof(ssid)); -#endif WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name)); @@ -3156,7 +2336,7 @@ wl_iw_set_freq( WL_TRACE(("%s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name)); #if defined(SOFTAP) - if (ap_cfg_running && !apsta_enable) { + if (ap_cfg_running) { WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__)); return 0; } @@ -3205,9 +2385,7 @@ wl_iw_get_freq( { channel_info_t ci; int error; -#ifdef HTC_KlocWork - memset(&ci,0,sizeof(ci)); -#endif + WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name)); if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) @@ -3247,16 +2425,10 @@ wl_iw_set_mode( infra = htod32(infra); ap = htod32(ap); - if (dhd_apsta){ - if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra)))){ - WL_ERROR(("%s: WLC_SET_INFRA error=%d\n", __FUNCTION__, error)); - return error; - } - } else { - if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) || - (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap)))) - return error; - } + if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) || + (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap)))) + return error; + return -EINPROGRESS; } @@ -3299,7 +2471,7 @@ wl_iw_get_range( int error, i, k; uint sf, ch; - int phytype = 0; //HTC_KlocWork + int phytype; int bw_cap = 0, sgi_tx = 0, nmode = 0; channel_info_t ci; uint8 nrate_list2copy = 0; @@ -3309,10 +2481,7 @@ wl_iw_get_range( {30, 60, 90, 120, 180, 240, 270, 300}}; WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); -#ifdef HTC_KlocWork - memset(&rateset,0,sizeof(rateset)); - memset(&ci,0,sizeof(ci)); -#endif + if (!extra) return -EINVAL; @@ -3374,11 +2543,7 @@ wl_iw_get_range( } rateset.count = dtoh32(rateset.count); range->num_bitrates = rateset.count; -#ifdef HTC_KlocWork - for (i = 0; i < rateset.count && i < WL_NUMRATES; i++) -#else for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) -#endif range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000; dev_wlc_intvar_get(dev, "nmode", &nmode); dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); @@ -3481,6 +2646,8 @@ wl_iw_get_range( IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCREQIE); + IW_EVENT_CAPA_SET(range->event_capa, IWEVASSOCRESPIE); IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); #endif @@ -3597,19 +2764,6 @@ wl_iw_ch_to_chanspec(int ch, wl_join_params_t *join_params, int *join_params_siz return 1; } -#ifdef SOFTAP -void wl_iw_check_apasta_concurrent(struct net_device *dev) -{ - if ( apsta_enable && ap_net_dev ) { - printf("%s: stop the ap part of apsta concurrent\n", __FUNCTION__); - if (dev_iw_write_cfg1_bss_var(dev, 0) < 0) { - WL_ERROR(("%s line %d fail to set bss down\n", \ - __FUNCTION__, __LINE__)); - } - } -} -#endif - static int wl_iw_set_wap( struct net_device *dev, @@ -3640,22 +2794,10 @@ wl_iw_set_wap( } -#ifdef SOFTAP - if ( apsta_enable && ap_net_dev ) { - printf("%s: stop the ap part of apsta concurrent\n", __FUNCTION__); - if (dev_iw_write_cfg1_bss_var(dev, 0) < 0) { - WL_ERROR(("%s line %d fail to set bss down\n", \ - __FUNCTION__, __LINE__)); - } - } -#endif memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid); -#ifdef PNO_SUPPORT - dhd_set_pfn_ssid(g_ssid.SSID, g_ssid.SSID_len); -#endif memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len); join_params.ssid.SSID_len = htod32(g_ssid.SSID_len); memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN); @@ -3839,9 +2981,7 @@ wl_iw_iscan_get_aplist( struct iw_quality qual[IW_MAX_AP]; wl_bss_info_t *bi = NULL; int i; -#ifdef HTC_KlocWork - memset(&qual,0,sizeof(qual)); -#endif + WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); if (!extra) @@ -3892,15 +3032,8 @@ wl_iw_iscan_get_aplist( buf = buf->next; } if (dwrq->length) { -#ifdef HTC_KlocWork - int cpylen = sizeof(struct iw_quality) * dwrq->length; - if( cpylen > sizeof(qual)) - cpylen = sizeof(qual); - - memcpy(&addr[dwrq->length], qual, cpylen); -#else memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); -#endif + dwrq->flags = 1; } @@ -3941,11 +3074,6 @@ wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) { int err = 0; - if (dev_wlc_ioctl_off){ - WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__)); - return -EINVAL; - } - iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); iscan->iscan_ex_params_p->action = htod16(action); iscan->iscan_ex_params_p->scan_duration = htod16(0); @@ -3991,18 +3119,6 @@ wl_iw_set_event_mask(struct net_device *dev) dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); } -static void wl_iw_set_event_mask_deauth(struct net_device *dev) -{ - char eventmask[WL_EVENTING_MASK_LEN]; - char iovbuf[WL_EVENTING_MASK_LEN + 12]; - - WL_SOFTAP(("set deauth event!\n")); - dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf)); - bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); - setbit(eventmask, WLC_E_DEAUTH); - dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, - iovbuf, sizeof(iovbuf)); -} static uint32 wl_iw_iscan_get(iscan_info_t *iscan) @@ -4122,17 +3238,14 @@ _iscan_sysioc_thread(void *data) while (down_interruptible(&tsk_ctl->sema) == 0) { - if (wl_iw_force_exit) - break; - SMP_RD_BARRIER_DEPENDS(); if (tsk_ctl->terminated) { break; } #if defined(SOFTAP) - if (ap_cfg_running && !apsta_enable) { - WL_SCAN(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); + if (ap_cfg_running) { + WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); net_os_wake_unlock(iscan->dev); continue; } @@ -4171,7 +3284,7 @@ _iscan_sysioc_thread(void *data) rtnl_unlock(); #endif - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; break; case WL_SCAN_RESULTS_SUCCESS: @@ -4182,7 +3295,7 @@ _iscan_sysioc_thread(void *data) case WL_SCAN_RESULTS_PENDING: WL_TRACE(("iscanresults pending\n")); - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; break; case WL_SCAN_RESULTS_ABORTED: @@ -4282,9 +3395,9 @@ wl_iw_run_ss_cache_timer(int kick_off) if (*timer) { if (kick_off) { #ifdef CONFIG_PRESCANNED - (*timer)->expires = jiffies + 70000 * HZ / 1000; + (*timer)->expires = jiffies + msecs_to_jiffies(70000); #else - (*timer)->expires = jiffies + 30000 * HZ / 1000; + (*timer)->expires = jiffies + msecs_to_jiffies(30000); #endif add_timer(*timer); WL_TRACE(("%s : timer starts \n", __FUNCTION__)); @@ -4566,11 +3679,6 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) wlc_ssid_t ssid; iscan_info_t *iscan = g_iscan; - if (dev_wlc_ioctl_off) { - WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__)); - return -EINVAL; - } - #if defined(CONFIG_FIRST_SCAN) if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) { @@ -4607,7 +3715,7 @@ wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) rtnl_unlock(); #endif - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; @@ -4628,11 +3736,6 @@ wl_iw_iscan_set_scan( WL_TRACE_SCAN(("%s: SIOCSIWSCAN : ISCAN\n", dev->name)); - if (dev_wlc_ioctl_off) { - WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__)); - return -EINVAL; - } - #if defined(CSCAN) WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__)); return -EINVAL; @@ -4642,7 +3745,7 @@ wl_iw_iscan_set_scan( #if defined(SOFTAP) - if (ap_cfg_running && !apsta_enable) { + if (ap_cfg_running) { WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); goto set_scan_end; } @@ -4773,43 +3876,6 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) } #endif -#ifdef BCMWAPI_WPI -static inline int -_wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, - size_t len, int uppercase) -{ - size_t i; - char *pos = buf, *end = buf + buf_size; - int ret; - if (buf_size == 0) - return 0; - for (i = 0; i < len; i++) { - ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", - data[i]); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return pos - buf; - } - pos += ret; - } - end[-1] = '\0'; - return pos - buf; -} - -/** - * wpa_snprintf_hex - Print data as a hex string into a buffer - * @buf: Memory area to use as the output buffer - * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) - * @data: Data to be printed - * @len: Length of data in bytes - * Returns: Number of bytes written - */ -static int -wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 0); -} -#endif /* BCMWAPI_WPI */ static int wl_iw_handle_scanresults_ies(char **event_p, char *end, @@ -4818,10 +3884,6 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, #if WIRELESS_EXT > 17 struct iw_event iwe; char *event; -#ifdef BCMWAPI_WPI - char *buf; - int custom_event_len; -#endif event = *event_p; if (bi->ie_length) { @@ -4858,39 +3920,6 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, } } -#ifdef BCMWAPI_WPI - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - ptr_len = bi->ie_length; - - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) { - WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__)); -#ifdef WAPI_IE_USE_GENIE - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); -#else /* using CUSTOM event */ - iwe.cmd = IWEVCUSTOM; - custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2); - iwe.u.data.length = custom_event_len; - - buf = kmalloc(custom_event_len+1, GFP_KERNEL); - if (buf == NULL) - { - WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len)); - break; - } - - memcpy(buf, "wapi_ie=", 8); - wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1); - wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1); - wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len); - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf); - kfree(buf); -#endif /* WAPI_IE_USE_GENIE */ - break; - } -#endif /* BCMWAPI_WPI */ - *event_p = event; } #endif @@ -4911,7 +3940,6 @@ wl_iw_get_scan_prep( wl_bss_info_t *bi = NULL; char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; int ret = 0; - uint8 channel; if (!list) { WL_ERROR(("%s: Null list pointer", __FUNCTION__)); @@ -4954,16 +3982,9 @@ wl_iw_get_scan_prep( iwe.cmd = SIOCGIWFREQ; -#if 1 - channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; - iwe.u.freq.m = wf_channel2mhz(channel, - channel <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); -#else iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); -#endif iwe.u.freq.e = 6; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); @@ -5046,10 +4067,6 @@ wl_iw_get_scan( return -EINVAL; } - if (dev_wlc_ioctl_off) { - WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__)); - return -EINVAL; - } if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) return error; @@ -5229,20 +4246,15 @@ wl_iw_iscan_get_scan( WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length)); - if (dev_wlc_ioctl_off) { - WL_ERROR(("%s: wl driver going down!\n", __FUNCTION__)); - return -EINVAL; - } - #if defined(SOFTAP) - if (ap_cfg_running && !apsta_enable) { - WL_ERROR(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); + if (ap_cfg_running) { + WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); return -EINVAL; } #endif if (!extra) { - WL_ERROR(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name)); + WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name)); return -EINVAL; } @@ -5309,10 +4321,8 @@ wl_iw_iscan_get_scan( if (event + ETHER_ADDR_LEN + bi->SSID_len + - IW_EV_UINT_LEN + IW_EV_FREQ_LEN + IW_EV_QUAL_LEN >= end) { - WL_ERROR(("%s: buffer to big!\n", __FUNCTION__)); + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + IW_EV_QUAL_LEN >= end) return -E2BIG; - } iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; @@ -5366,20 +4376,14 @@ wl_iw_iscan_get_scan( if (bi->rateset.count) { - if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) { - WL_ERROR(("%s: buffer to big!\n", __FUNCTION__)); + if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) return -E2BIG; - } value = event + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; -#ifdef HTC_KlocWork - for (j = 0; j < bi->rateset.count && j < WL_NUMRATES; j++) { -#else for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { -#endif iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, @@ -5406,8 +4410,7 @@ wl_iw_iscan_get_scan( g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED; #endif - WL_DEFAULT(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter)); - + WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter)); return 0; } @@ -5525,16 +4528,6 @@ wl_iw_set_essid( #endif memcpy(g_ssid.SSID, extra, g_ssid.SSID_len); -#ifdef SOFTAP - if ( apsta_enable && ap_net_dev ) { - printf("%s: stop the ap part of apsta concurrent\n", __FUNCTION__); - if (dev_iw_write_cfg1_bss_var(dev, 0) < 0) { - WL_ERROR(("%s line %d fail to set bss down\n", \ - __FUNCTION__, __LINE__)); - } - } -#endif - #ifdef CONFIG_PRESCANNED memcpy(join_params->ssid.SSID, g_ssid.SSID, g_ssid.SSID_len); join_params->ssid.SSID_len = g_ssid.SSID_len; @@ -5593,9 +4586,7 @@ wl_iw_get_essid( { wlc_ssid_t ssid; int error; -#ifdef HTC_KlocWork - memset(&ssid, 0, sizeof(ssid)); -#endif + WL_TRACE(("%s: SIOCGIWESSID\n", dev->name)); if (!extra) @@ -5638,9 +4629,6 @@ wl_iw_set_nick( return -E2BIG; memcpy(iw->nickname, extra, dwrq->length); -#ifdef HTC_KlocWork - if(dwrq->length >= 1) -#endif iw->nickname[dwrq->length - 1] = '\0'; return 0; @@ -5679,9 +4667,7 @@ wl_iw_set_rate( int error, rate, i, error_bg, error_a; WL_TRACE(("%s: SIOCSIWRATE\n", dev->name)); -#ifdef HTC_KlocWork - memset(&rateset,0,sizeof(rateset)); -#endif + if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) return error; @@ -5738,7 +4724,7 @@ wl_iw_get_rate( char *extra ) { - int error = 0, rate = 0; /* HTC_KlocWork */ + int error, rate; WL_TRACE(("%s: SIOCGIWRATE\n", dev->name)); @@ -5893,10 +4879,11 @@ wl_iw_get_txpow( char *extra ) { - int error, disable = 0, txpwrdbm; /* HTC_KlocWork */ + int error, disable, txpwrdbm; uint8 result; WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name)); + if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) || (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm))) return error; @@ -5966,7 +4953,7 @@ wl_iw_get_retry( char *extra ) { - int error, lrl = 0, srl = 0; /* HTC_KlocWork */ + int error, lrl, srl; WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name)); @@ -6109,7 +5096,7 @@ wl_iw_get_encode( ) { wl_wsec_key_t key; - int error, val, wsec = 0, auth = 0; /* HTC_KlocWork */ + int error, val, wsec, auth; WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name)); @@ -6192,7 +5179,7 @@ wl_iw_get_power( char *extra ) { - int error, pm = 0; /* HTC_KlocWork */ + int error, pm; WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name)); @@ -6215,11 +5202,6 @@ wl_iw_set_wpaie( char *extra ) { -#if defined(BCMWAPI_WPI) - uchar buf[WLC_IOCTL_SMLEN] = {0}; - uchar *p = buf; - int wapi_ie_size; -#endif /* BCMWAPI_WPI */ WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name)); @@ -6235,15 +5217,6 @@ wl_iw_set_wpaie( } #endif -#if defined(BCMWAPI_WPI) - if (extra[0] == DOT11_MNG_WAPI_ID) - { - wapi_ie_size = iwp->length; - memcpy(p, extra, iwp->length); - dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size); - } - else -#endif /* BCMWAPI_WPI */ dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); return 0; @@ -6360,14 +5333,6 @@ wl_iw_set_encodeext( case IW_ENCODE_ALG_CCMP: key.algo = CRYPTO_ALGO_AES_CCM; break; -#ifdef BCMWAPI_WPI - case IW_ENCODE_ALG_SM4: - key.algo = CRYPTO_ALGO_SMS4; - if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - key.flags &= ~WL_PRIMARY_KEY; - } - break; -#endif default: break; } @@ -6385,7 +5350,7 @@ wl_iw_set_encodeext( #if WIRELESS_EXT > 17 struct { pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID-1]; + pmkid_t foo[MAXPMKID-1]; } pmkid_list; static int @@ -6526,10 +5491,6 @@ wl_iw_create_wpaauth_wsec(struct net_device *dev) wsec = TKIP_ENABLED; else if (iw->pcipher & IW_AUTH_CIPHER_CCMP) wsec = AES_ENABLED; -#ifdef BCMWAPI_WPI - else if (iw->pcipher & IW_AUTH_CIPHER_SMS4) - wsec = SMS4_ENABLED; -#endif else wsec = 0; @@ -6540,10 +5501,6 @@ wl_iw_create_wpaauth_wsec(struct net_device *dev) wsec |= TKIP_ENABLED; else if (iw->gcipher & IW_AUTH_CIPHER_CCMP) wsec |= AES_ENABLED; -#ifdef BCMWAPI_WPI - else if (iw->gcipher & IW_AUTH_CIPHER_SMS4) - wsec |= SMS4_ENABLED; -#endif if (wsec == 0 && iw->privacy_invoked) @@ -6588,7 +5545,7 @@ wl_iw_set_wpaauth( paramid, paramval)); #if defined(SOFTAP) - if (ap_cfg_running && !apsta_enable) { + if (ap_cfg_running) { WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); return 0; } @@ -6597,7 +5554,15 @@ wl_iw_set_wpaauth( switch (paramid) { case IW_AUTH_WPA_VERSION: - iw->wpaversion = paramval; + if (paramval & IW_AUTH_WPA_VERSION_DISABLED) + val = WPA_AUTH_DISABLED; + else if (paramval & (IW_AUTH_WPA_VERSION_WPA)) + val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; + else if (paramval & IW_AUTH_WPA_VERSION_WPA2) + val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; + WL_ERROR(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); + if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) + return error; break; case IW_AUTH_CIPHER_PAIRWISE: @@ -6615,7 +5580,27 @@ wl_iw_set_wpaauth( break; case IW_AUTH_KEY_MGMT: - if (paramval & IW_AUTH_KEY_MGMT_PSK) { + if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) + return error; + + if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { + if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA_AUTH_PSK; + else + val = WPA_AUTH_UNSPECIFIED; + if (paramval & 0x04) + val |= WPA2_AUTH_FT; + } + else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { + if (paramval & IW_AUTH_KEY_MGMT_PSK) + val = WPA2_AUTH_PSK; + else + val = WPA2_AUTH_UNSPECIFIED; + if (paramval & 0x04) + val |= WPA2_AUTH_FT; + } + + else if (paramval & IW_AUTH_KEY_MGMT_PSK) { if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA) val = WPA_AUTH_PSK; else if (iw->wpaversion == IW_AUTH_WPA_VERSION_WPA2) @@ -6630,12 +5615,6 @@ wl_iw_set_wpaauth( else val = WPA_AUTH_DISABLED; } -#ifdef BCMWAPI_WPI - else if (paramval & IW_AUTH_KEY_MGMT_WAPI_PSK) - val = WAPI_AUTH_PSK; - else if (paramval & IW_AUTH_KEY_MGMT_WAPI_CERT) - val = WAPI_AUTH_UNSPECIFIED; -#endif else val = WPA_AUTH_DISABLED; @@ -6702,33 +5681,6 @@ wl_iw_set_wpaauth( return error; break; -#endif -#ifdef BCMWAPI_WPI - case IW_AUTH_WAPI_ENABLED: - if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) - return error; - if (paramval) { - val |= SMS4_ENABLED; - if ((error = dev_wlc_intvar_set(dev, "wsec", val))) { - WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n", - __FUNCTION__, val, error)); - return error; - } - if (paramval & IW_AUTH_KEY_MGMT_WAPI_PSK) - val = WAPI_AUTH_PSK; - else if (paramval & IW_AUTH_KEY_MGMT_WAPI_CERT) - val = WAPI_AUTH_UNSPECIFIED; - else - val = WAPI_AUTH_NONE; - if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) { - WL_ERROR(("%s: setting wpa_auth(%d) returned %d\n", - __FUNCTION__, val, error)); - return error; - } - } - - break; - #endif default: break; @@ -6823,15 +5775,11 @@ wl_iw_get_wpaauth( return 0; } #endif -#endif /* #ifndef WL_CFG80211 */ #ifdef SOFTAP static int ap_macmode = MACLIST_MODE_DISABLED; -#if !defined(WL_CFG80211) -static int ap_txpower_default = 0; -#endif static struct mflist ap_black_list; static int @@ -6939,8 +5887,7 @@ dev_iw_write_cfg1_bss_var(struct net_device *dev, int val) -//#ifndef AP_ONLY -#if 1 +#ifndef AP_ONLY static int wl_bssiovar_mkbuf( const char *iovar, @@ -6993,7 +5940,6 @@ wl_bssiovar_mkbuf( -#ifndef WL_CFG80211 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) @@ -7011,40 +5957,14 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss int i; iscan_info_t *iscan = g_iscan; -/* HTC_CSP_START */ - int assoc_inprogress = 0; - int error = 0; - int scan_assoc_retry_cnt = 0; -/* HTC_CSP_END */ - WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan)); -#ifdef HTC_KlocWork - if ((!dev) || (!g_iscan) || (!iscan->iscan_ex_params_p)) { -#else if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) { -#endif WL_ERROR(("%s error exit\n", __FUNCTION__)); err = -1; goto exit; } -/* HTC_CSP_START */ -scan_assoc_retry: - /* check if in assoc */ - error = dev_wlc_intvar_get(dev, "assoc_state", &assoc_inprogress); - if (error) { - printf("assoc_state not support!\n"); - } else { - if (assoc_inprogress && (scan_assoc_retry_cnt < 3)) { - printf("associating, skip %d\n", scan_assoc_retry_cnt); - msleep(1000); - scan_assoc_retry_cnt++; - goto scan_assoc_retry; - } - } -/* HTC_CSP_END */ - #ifdef PNO_SUPPORT if (dhd_dev_get_pno_status(dev)) { @@ -7087,7 +6007,7 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss iscan->list_cur = iscan->list_hdr; iscan->iscan_state = ISCAN_STATE_SCANING; wl_iw_set_event_mask(dev); - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); + mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms)); iscan->timer_on = 1; @@ -7138,7 +6058,7 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *ext) { - int res = 0; + int res; char *extra = NULL; iscan_info_t *iscan = g_iscan; wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; @@ -7173,7 +6093,7 @@ iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, } extra[wrqu->data.length] = 0; - WL_ERROR(("Got str param in iw_point: %s\n", extra)); + WL_ERROR(("Got str param in iw_point:\n %s\n", extra)); str_ptr = extra; @@ -7436,26 +6356,6 @@ wl_iw_set_cscan( #endif -/* HTC_CSP_START */ -#if defined(CSCAN) -static int -wl_iw_get_cscan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char *p = extra; - - p += snprintf(p, MAX_WX_STRING, "%d\n", wifi_get_cscan_enable()? 1: 0); - wrqu->data.length = p - extra + 1; - - return 0; -} -#endif -/* HTC_CSP_END */ - #ifdef CONFIG_WPS2 static int wl_iw_del_wps_probe_req_ie( @@ -7574,8 +6474,7 @@ wl_iw_add_wps_probe_req_ie( } return ret; } -#endif -#endif /* ifndef WL_CFG80211 */ +#endif #ifdef SOFTAP @@ -7596,7 +6495,7 @@ thr_wait_for_2nd_eth_dev(void *data) DAEMONIZE("wl0_eth_wthread"); - WL_SOFTAP(("\n>%s thread started:, PID:%x\n", __FUNCTION__, current->pid)); + WL_SOFTAP(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid)); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) if (!iw) { @@ -7630,7 +6529,7 @@ thr_wait_for_2nd_eth_dev(void *data) goto fail; } - WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n", + WL_SOFTAP(("\n>%s: Thread:'softap ethdev IF:%s is detected!'\n\n", __FUNCTION__, ap_net_dev->name)); ap_cfg_running = TRUE; @@ -7641,50 +6540,38 @@ thr_wait_for_2nd_eth_dev(void *data) wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK"); - /* remove the attach state bit of softap */ - dhd_state_set_flags( iw->pub, DHD_ATTACH_STATE_SOFTAP, 0); - - fail: DHD_OS_WAKE_UNLOCK(iw->pub); - WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__)); + WL_SOFTAP(("\n>%s, thread completed\n", __FUNCTION__)); complete_and_exit(&tsk_ctl->completed, 0); return ret; } #endif +#ifndef AP_ONLY static int last_auto_channel = 6; +#endif static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) { int chosen = 0; - char req_buf[64] = {0}; - wl_uint32_list_t *request = (wl_uint32_list_t *)req_buf; - int rescan = 0; + wl_uint32_list_t request; int retry = 0; int updown = 0; + int ret = 0; wlc_ssid_t null_ssid; int res = 0; - int spec = 0; #ifndef AP_ONLY int iolen = 0; int mkvar_err = 0; int bsscfg_index = 1; char buf[WLC_IOCTL_SMLEN]; #endif -#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */ - int start_channel = 1, end_channel = 14; - int i = 0; -#endif - int isup = 0; - WL_SOFTAP(("Enter %s\n", __FUNCTION__)); - dev_wlc_ioctl(dev, WLC_GET_UP, &isup, sizeof(isup)); - #ifndef AP_ONLY if (ap_cfg_running) { ap->channel = last_auto_channel; @@ -7692,21 +6579,13 @@ get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) } #endif -auto_channel_retry: memset(&null_ssid, 0, sizeof(wlc_ssid_t)); - null_ssid.SSID_len = strlen(ap->ssid); - strncpy(null_ssid.SSID, ap->ssid, null_ssid.SSID_len); - -#ifdef AP_ONLY - res |= dev_wlc_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spec, sizeof(spec)); - res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid)); res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)); - memset(&null_ssid, 0, sizeof(wlc_ssid_t)); +#ifdef AP_ONLY res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid)); #else - res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)); iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); ASSERT(iolen); @@ -7714,78 +6593,56 @@ get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) #endif - request->count = htod32(0); -#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */ - if (ap->channel >> 8) { - start_channel = (ap->channel >> 8) & 0xff; - end_channel = ap->channel & 0xff; - request->count = end_channel - start_channel + 1; - WL_SOFTAP(("request channel: %d to %d ,request->count =%d\n", start_channel, end_channel,request->count)); - for (i = 0; i < request->count; i++) { - request->element[i] = CH20MHZ_CHSPEC((start_channel + i)); - //request->element[i] = (start_channel + i); - printf("request.element[%d]=0x%x\n", i, request->element[i]); - } - } -#endif - res = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, request, sizeof(req_buf)); - if (res < 0) { + request.count = htod32(0); + ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request)); + if (ret < 0) { WL_ERROR(("can't start auto channel scan\n")); goto fail; } get_channel_retry: - bcm_mdelay(500); + bcm_mdelay(350); - res = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen)); - if (res < 0 || dtoh32(chosen) == 0) { - if (retry++ < 6) - goto get_channel_retry; - else { - WL_ERROR(("can't get auto channel sel, err = %d, " - "chosen = %d\n", res, chosen)); - chosen = 6; /*Alan: Set default channel when get auto channel failed*/ + ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen)); + if (ret < 0 || dtoh32(chosen) == 0) { + if (retry++ < 15) { + goto get_channel_retry; + } else { + if (ret < 0) { + WL_ERROR(("can't get auto channel sel, err = %d, " + "chosen = 0x%04X\n", ret, (uint16)chosen)); + goto fail; + } else { + ap->channel = (uint16)last_auto_channel; + WL_ERROR(("auto channel sel timed out. we get channel %d\n", + ap->channel)); + } + } } - } - if ((chosen == start_channel) && (!rescan++)) - { - retry = 0; - goto auto_channel_retry; - } -#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */ - if (ap->channel == 0) { - ap->channel = chosen; - last_auto_channel = chosen; - } else { - WL_SOFTAP(("channel range from %d to %d ,chosen = %d\n", start_channel, end_channel, chosen)); + if (chosen) { + ap->channel = (uint16)chosen & 0x00FF; + WL_SOFTAP(("%s: Got auto channel = %d, attempt:%d\n", + __FUNCTION__, ap->channel, retry)); + } - if (chosen > end_channel) { - if (chosen <= 6) - chosen = end_channel; - else - chosen = start_channel; - } else if (chosen < start_channel) - chosen = start_channel; + if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) { + WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); + goto fail; + } - ap->channel = chosen; - } -#else - ap->channel = chosen; -#endif - if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) { - WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); - goto fail; - } #ifndef AP_ONLY - if (!res) + if (!res || !ret) last_auto_channel = ap->channel; #endif fail : - + if (ret < 0) { + WL_TRACE(("%s: return value %d\n", __FUNCTION__, ret)); + return ret; + } return res; -} +} static int @@ -7799,20 +6656,13 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) int res = 0; int apsta_var = 0; - /* [kenn] temp mark for hidden AP - int closednet = 0; - */ - wl_country_t cspec = {{0}, 0, {0}}; - int band = 0; - int mpc = 0; #ifndef AP_ONLY + int mpc = 0; int iolen = 0; int mkvar_err = 0; int bsscfg_index = 1; char buf[WLC_IOCTL_SMLEN]; - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); #endif - int dtim = 1; if (!dev) { WL_ERROR(("%s: dev is null\n", __FUNCTION__)); @@ -7825,14 +6675,10 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_SOFTAP(("wl_iw: set ap profile:\n")); WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); WL_SOFTAP((" security = '%s'\n", ap->sec)); -/* HTC_CSP_START */ - /* if (ap->key[0] != '\0') - * WL_SOFTAP((" key = '%s'\n", ap->key)); - */ -/* HTC_CSP_END */ + if (ap->key[0] != '\0') + WL_SOFTAP((" key = '%s'\n", ap->key)); WL_SOFTAP((" channel = %d\n", ap->channel)); WL_SOFTAP((" max scb = %d\n", ap->max_scb)); - WL_SOFTAP((" hidden = %d\n", ap->closednet)); #ifdef AP_ONLY if (ap_cfg_running) { @@ -7841,14 +6687,12 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) } #endif - WL_SOFTAP(("%s: ap_cfg_running = %s", __FUNCTION__, (ap_cfg_running)?"TRUE":"FALSE")); if (ap_cfg_running == FALSE) { #ifndef AP_ONLY - dhd_state_set_flags( iw->pub, DHD_ATTACH_STATE_SOFTAP, 1); sema_init(&ap_eth_ctl.sema, 0); mpc = 0; @@ -7883,9 +6727,7 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) iolen = wl_bssiovar_mkbuf("apsta", bsscfg_index, &apsta_var, sizeof(apsta_var)+4, buf, sizeof(buf), &mkvar_err); - if (iolen <= 0) - goto fail; - + ASSERT(iolen); if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) { WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); goto fail; @@ -7893,14 +6735,12 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res)); - -#if 0 mpc = 0; if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { WL_ERROR(("%s fail to set mpc\n", __FUNCTION__)); goto fail; } -#endif + #endif @@ -7909,11 +6749,6 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); goto fail; } - mpc = 0; - if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { - WL_ERROR(("%s fail to set mpc\n", __FUNCTION__)); - goto fail; - } } else { @@ -7933,79 +6768,35 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) if (strlen(ap->country_code)) { - int error = 0; - if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, - ap->country_code, sizeof(ap->country_code))) >= 0) { - WL_SOFTAP(("%s: set country %s OK\n", - __FUNCTION__, ap->country_code)); - cspec.rev = -1; - memcpy(cspec.country_abbrev, ap->country_code, WLC_CNTRY_BUF_SZ); - memcpy(cspec.ccode, ap->country_code, WLC_CNTRY_BUF_SZ); - get_customized_country_code((char *)&cspec.country_abbrev, &cspec); - dhd_bus_country_set(dev, &cspec); - } else { - WL_ERROR(("%s: ERROR:%d setting country %s\n", - __FUNCTION__, error, ap->country_code)); - } + WL_ERROR(("%s: Igonored: Country MUST be specified" + "COUNTRY command with \n", __FUNCTION__)); } else { WL_SOFTAP(("%s: Country code is not specified," " will use Radio's default\n", - __FUNCTION__)); - - } -#ifdef AP_ONLY - /* [kenn] temp mark for hidden AP - closednet = ap->closednet; + __FUNCTION__)); - if ((res = dev_wlc_intvar_set(dev, "closednet", closednet))) { - WL_ERROR(("%s fail to set closednet %d\n\n", __FUNCTION__, ap->closednet)); - goto fail; } - * */ -#else iolen = wl_bssiovar_mkbuf("closednet", bsscfg_index, &ap->closednet, sizeof(ap->closednet)+4, buf, sizeof(buf), &mkvar_err); ASSERT(iolen); if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) { WL_ERROR(("%s failed to set 'closednet'for apsta \n", __FUNCTION__)); - //goto fail; - } - -#endif -/* HTC_CSP_START */ - band = (ap->channel >> 16) ? WLC_BAND_5G : WLC_BAND_2G; - if (band == WLC_BAND_5G && (res = dev_wlc_ioctl(dev, WLC_SET_BAND, &band, sizeof(band)))) { - WL_ERROR(("%s fail to set band\n", __FUNCTION__)); goto fail; } + -#ifdef CUSTOMER_HW2 /* HTC need limited the selected channel */ - if (((ap->channel >> 8) || (ap->channel == 0)) && (band != WLC_BAND_5G) - && (get_softap_auto_channel(dev, ap) < 0)) { -#else - if ((ap->channel == 0) && (band != WLC_BAND_5G) && (get_softap_auto_channel(dev, ap) < 0)) { -#endif -/* HTC_CSP_END */ - ap->channel = 6; - WL_ERROR(("%s auto channel failed, pick up channel=%d\n", + if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) { + ap->channel = 1; + WL_ERROR(("%s auto channel failed, use channel=%d\n", __FUNCTION__, ap->channel)); } -/* HTC_CSP_START */ - channel = (band != WLC_BAND_5G) ? (ap->channel & 0x0000ffff) : (ap->channel >> 16); - WL_SOFTAP(("set channel = %d, band = %d\n", channel, band)); -/* HTC_CSP_END */ + channel = ap->channel; if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) { WL_ERROR(("%s fail to set channel\n", __FUNCTION__)); - goto fail; } - /* set dtim to 1 */ - if ((res |= dev_wlc_ioctl(dev, WLC_SET_DTIMPRD, &dtim, sizeof(dtim)))) { - WL_ERROR(("%s fail to set channel\n", __FUNCTION__)); - goto fail; - } if (ap_cfg_running == FALSE) { updown = 0; @@ -8076,134 +6867,10 @@ set_ap_cfg(struct net_device *dev, struct ap_profile *ap) DHD_OS_MUTEX_UNLOCK(&wl_softap_lock); net_os_wake_unlock(dev); -#if !defined(WL_CFG80211) - wl_iw_set_event_mask_deauth(dev); -#endif return res; } #endif -#ifndef AP_ONLY -/* - * broadcom, try to enable the apsta concurrent on Android. add this function - * to preinit apsta's ap before wifi-tethering enabling. - */ -static int set_apsta_cfg(struct net_device *dev, struct ap_profile *ap) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - wlc_ssid_t ap_ssid; - int max_assoc = 8; - - int res = 0; - int iolen = 0; - int mkvar_err = 0; - int bsscfg_index = 1; - char buf[WLC_IOCTL_SMLEN]; - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return -1; - } - - net_os_wake_lock(dev); - DHD_OS_MUTEX_LOCK(&wl_softap_lock); - - WL_SOFTAP(("%s: Enter\n", __FUNCTION__)); - WL_SOFTAP(("wl_iw: set ap profile:\n")); - WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); - WL_SOFTAP((" security = '%s'\n", ap->sec)); - if (ap->key[0] != '\0') - WL_SOFTAP((" key = '%s'\n", ap->key)); - WL_SOFTAP((" channel = %d\n", ap->channel)); - WL_SOFTAP((" max scb = %d\n", ap->max_scb)); - - - if (ap_cfg_running == FALSE) { - /* broadcom, the apsta shall be ready when driver loading. */ - dhd_state_set_flags( iw->pub, DHD_ATTACH_STATE_SOFTAP, 1); - sema_init(&ap_eth_ctl.sema, 0); - } else { - - if (!ap_net_dev) { - WL_ERROR(("%s: ap_net_dev is null\n", __FUNCTION__)); - goto fail; - } - - res = wl_iw_softap_deassoc_stations(ap_net_dev, NULL); - - if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { - WL_ERROR(("%s fail to set bss 1 down\n", __FUNCTION__)); - goto fail; - } - - /* clean station interface also */ - { - wlc_ssid_t null_ssid; - memset(&null_ssid, 0, sizeof(wlc_ssid_t)); - WL_SOFTAP(("set null ssid\n")); - if ((res = dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid))) < 0){ - WL_ERROR(("%s fail to set null ssid\n", __FUNCTION__)); - goto fail; - } - } - } - - /* broadcom, channel is unchangable here. */ - - max_assoc = ap->max_scb; - if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) { - WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__)); - goto fail; - } - - ap_ssid.SSID_len = strlen(ap->ssid); - strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); - - iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid), - ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); - if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) { - WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n", \ - res, __FUNCTION__)); - goto fail; - } - - if (ap_cfg_running == FALSE) { - PROC_START(thr_wait_for_2nd_eth_dev, dev, &ap_eth_ctl, 0); - } else { - ap_eth_ctl.thr_pid = -1; - - if (ap_net_dev == NULL) { - WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__)); - goto fail; - } - - WL_ERROR(("%s: %s Configure security & restart AP bss \n", \ - __FUNCTION__, ap_net_dev->name)); - - - if ((res = wl_iw_set_ap_security(ap_net_dev, &my_ap)) < 0) { - WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res)); - goto fail; - } - - /* will be enabled when sta restart again. */ -#if 0 - if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) { - WL_ERROR(("%s fail to set bss up\n", __FUNCTION__)); - goto fail; - } -#endif - } -fail: - WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res)); - - DHD_OS_MUTEX_UNLOCK(&wl_softap_lock); - net_os_wake_unlock(dev); - - return res; -} -#endif static int @@ -8220,15 +6887,12 @@ wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) #endif wl_wsec_key_t key; - WL_SOFTAP(("setting SOFTAP security mode:\n")); + WL_SOFTAP(("\nsetting SOFTAP security mode:\n")); WL_SOFTAP(("wl_iw: set ap profile:\n")); WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); WL_SOFTAP((" security = '%s'\n", ap->sec)); -/* HTC_CSP_START */ - /* if (ap->key[0] != '\0') - * WL_SOFTAP((" key = '%s'\n", ap->key)); - */ -/* HTC_CSP_END */ + if (ap->key[0] != '\0') + WL_SOFTAP((" key = '%s'\n", ap->key)); WL_SOFTAP((" channel = %d\n", ap->channel)); WL_SOFTAP((" max scb = %d\n", ap->max_scb)); @@ -8242,7 +6906,7 @@ wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth); WL_SOFTAP(("=====================\n")); - WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:%d\n", res)); + WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res)); WL_SOFTAP(("=====================\n")); } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) { @@ -8356,7 +7020,7 @@ wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) (uint)output[i*4+3]); ptr += 8; } - printf("%s: passphase = %s\n", __FUNCTION__, key_str_buf); + printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf); psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN); memcpy(psk.key, key_str_buf, psk.key_len); @@ -8407,12 +7071,7 @@ get_parameter_from_string( strsep(str_ptr, "=,"); if (*str_ptr == NULL) { -#ifdef HTC_KlocWork - if (param_str_begin == NULL) { - WL_ERROR(("[HTCKW] get_parameter_from_string: param_str_begin is NULL\n")); - return -1; - } -#endif + parm_str_len = strlen(param_str_begin); } else { param_str_end = *str_ptr-1; @@ -8450,31 +7109,28 @@ get_parameter_from_string( param_max_len = param_max_len >> 1; hstr_2_buf(param_str_begin, buf, param_max_len); - //dhd_print_buf(buf, param_max_len, 0); + dhd_print_buf(buf, param_max_len, 0); } break; default: memcpy(dst, param_str_begin, parm_str_len); *((char *)dst + parm_str_len) = 0; -/* HTC_CSP_START */ - /* WL_DEFAULT((" written as a string:%s\n", (char *)dst)); */ - WL_DEFAULT((" written as a string\n")); -/* HTC_CSP_END */ + WL_ERROR((" written as a string:%s\n", (char *)dst)); break; } return 0; } else { - WL_ERROR(("%s: ERROR: can't find token:%s in str:%s \n", + WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n", __FUNCTION__, token, orig_str)); return -1; } } -int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac) +static int wl_iw_softap_deassoc_stations(struct net_device *dev, u8 *mac) { int i; int res = 0; @@ -8559,7 +7215,6 @@ iwpriv_softap_stop(struct net_device *dev, wrqu->data.length = 0; ap_cfg_running = FALSE; - wl_iw_send_priv_event(priv_dev, "AP_DOWN"); } else WL_ERROR(("%s: was called when SoftAP is OFF : move on\n", __FUNCTION__)); @@ -8628,63 +7283,6 @@ iwpriv_fw_reload(struct net_device *dev, #ifdef SOFTAP -/* HTC_CSP_START */ -#ifndef WL_CFG80211 -static int -iwpriv_settxpower(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - char *params = NULL; - int value; - - WL_TRACE(("%s: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n", - __func__, info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - - if (wrqu->data.length != 0) { - if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) { - kfree(params); - return -EFAULT; - } - - params[wrqu->data.length] = 0; - value = bcm_atoi(params); - - if (ap_txpower_default == 0) { - /* get the default txpower */ - dev_wlc_intvar_get(priv_dev, "qtxpower", &ap_txpower_default); - WL_DEFAULT(("default tx power is %d\n", ap_txpower_default)); - ap_txpower_default |= WL_TXPWR_OVERRIDE; - } - - - if (value == 99) { - /* set to default value */ - value = ap_txpower_default; - } else { - value |= WL_TXPWR_OVERRIDE; - } - - WL_DEFAULT(("set tx power to %d\n", value&(~WL_TXPWR_OVERRIDE))); - dev_wlc_intvar_set(dev, "qtxpower", value); - - } else { - WL_ERROR(("ERROR param length is 0\n")); - return -EFAULT; - } - - kfree(params); - return 0; -} -#endif -/* HTC_CSP_END */ - static int iwpriv_wpasupp_loop_tst(struct net_device *dev, struct iw_request_info *info, @@ -8747,15 +7345,6 @@ iwpriv_en_ap_bss( #ifndef AP_ONLY - if (ap_eth_ctl.thr_pid >= 0) { - if (!wait_for_completion_timeout(&ap_eth_ctl->completed, 2*HZ)) - { - WL_ERROR(("Can't get AP interface!\n")); - return -1; - } - ap_eth_ctl.thr_pid = -1; - } - if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) { WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res)); } @@ -8777,231 +7366,23 @@ iwpriv_en_ap_bss( return res; } -#if !defined(WL_CFG80211) -static int -set_ap_txpower(struct net_device *dev, int *value) -{ - if (ap_txpower_default == 0) { - /* get the default txpower */ - dev_wlc_intvar_get(priv_dev, "qtxpower", &ap_txpower_default); - WL_DEFAULT(("default tx power is %d\n", ap_txpower_default)); - ap_txpower_default |= WL_TXPWR_OVERRIDE; - } - - if (*value == 99) { - /* set to default value */ - *value = ap_txpower_default; - } else { - *value |= WL_TXPWR_OVERRIDE; - } - - WL_DEFAULT(("set tx power to 0x%x\n", *value)); - dev_wlc_intvar_set(dev, "qtxpower", *value); - - return 0; -} -#endif static int get_assoc_sta_list(struct net_device *dev, char *buf, int len) { -/* HTC_CSP_START */ - struct maclist *maclist = (struct maclist *) buf; - int ret; - + WL_TRACE(("%s: dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n", __FUNCTION__, dev, WLC_GET_ASSOCLIST, buf, len)); - maclist->count = 8; - ret = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len); - - if (ret != 0) { - WL_SOFTAP(("get assoc count fail\n")); - maclist->count = 0; - } - else - WL_SOFTAP(("get assoc count %d, ret %d\n", maclist->count, ret)); + return dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len); - return 0; -/* HTC_CSP_END */ } void check_error(int res, const char *msg, const char *func, int line) { if (res != 0) - WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line)); -} - -#if !defined(WL_CFG80211) -static vndr_ie_setbuf_t *ie_setbuf = NULL ; -static int -wl_iw_create_wps_ie(char *buf, int ie_len) -{ - unsigned int pktflag = VNDR_IE_PRBREQ_FLAG; - int iecount; - - if(!ie_setbuf) - ie_setbuf = (vndr_ie_setbuf_t *) kmalloc(VNDR_IE_MAX_LEN + sizeof(vndr_ie_setbuf_t), GFP_KERNEL); - - if (!ie_setbuf) { - WL_ERROR(("memory alloc failure\n")); - return -1; - } - - iecount = 1; - memcpy(&ie_setbuf->vndr_ie_buffer.iecount, &iecount, sizeof(int)); - - /* - * The packet flag bit field indicates the packets that will - * contain this IE - */ - memcpy(&ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag, sizeof(uint32)); - - memcpy(&(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len), buf, ie_len); - - return 0; -} - -static void -wl_iw_add_wps_ie(struct net_device *dev) -{ - int buflen; - strcpy (ie_setbuf->cmd, "add"); - - buflen = ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len - - VNDR_IE_MIN_LEN + sizeof(vndr_ie_setbuf_t) ; - - dev_wlc_bufvar_set(dev, "vndr_ie", (char *)ie_setbuf, buflen); - - return; -} - -static void -wl_iw_del_wps_ie(struct net_device *dev) -{ - int buflen; - if (!ie_setbuf) - return; - /* Copy the vndr_ie SET command ("add"/"del") to the buffer */ - strcpy (ie_setbuf->cmd, "del"); - - buflen = ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len - - VNDR_IE_MIN_LEN + sizeof(vndr_ie_setbuf_t) ; - - dev_wlc_bufvar_set(dev, "vndr_ie", (char *)ie_setbuf, buflen); - - kfree(ie_setbuf); - ie_setbuf = NULL; - - return; - -} - -static int -wl_iw_set_probe_request_ie(struct net_device *dev, char *buf, int ie_len) -{ - WL_TRACE(("get ie len = %d\n", ie_len)); - -#if 0 - for (i = 0; i < ie_len; i++) { - WL_TRACE((" %02X", *(buf+i))); - } - - WL_ERROR(("\n")); -#endif - - wl_iw_del_wps_ie(dev); - - if (ie_is_wps_ie((uint8 **)(&buf), (uint8 **)(&buf), &ie_len)) { - WL_TRACE(("wps_ie found\n")); - - if (wl_iw_create_wps_ie(buf+1, ie_len-1) != 0) - return -1; - wl_iw_add_wps_ie(dev); - } - return 0; -} -#endif - -#ifdef CUSTOMER_HW2 -static struct mac_list_set mac_list_buf; -static int set_ap_mac_list(struct net_device *dev, void *buf) -{ - struct mac_list_set *mac_list_set = (struct mac_list_set *)buf; - struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list; - struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list; - int mac_mode = mac_list_set->mode; - int length; - int i; - - if (white_maclist->count > 16 || black_maclist->count > 16) { - WL_SOFTAP(("invalid count white: %d black: %d\n", white_maclist->count, black_maclist->count)); - return 0; - } - - if (buf != (char *)&mac_list_buf) { - WL_SOFTAP(("Backup the mac list\n")); - memcpy((char *)&mac_list_buf, buf, sizeof(struct mac_list_set)); - } else - WL_SOFTAP(("recover, don't back up mac list\n")); - - ap_macmode = mac_mode; - if (mac_mode == MACLIST_MODE_DISABLED) { - - bzero(&ap_black_list, sizeof(struct mflist)); - - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); - } else { - scb_val_t scbval; - char mac_buf[256] = {0}; - struct maclist *assoc_maclist = (struct maclist *) mac_buf; - - mac_mode = MACLIST_MODE_ALLOW; - - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); - - length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN; - dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length); - WL_SOFTAP(("White List, length %d:\n", length)); - for (i = 0; i < white_maclist->count; i++) - WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1], white_maclist->ea[i].octet[2], - white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4], white_maclist->ea[i].octet[5])); - - /* set the black list */ - bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list)); - - WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list))); - for (i = 0; i < ap_black_list.count; i++) - WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1], ap_black_list.ea[i].octet[2], - ap_black_list.ea[i].octet[3], ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5])); - - /* deauth if there is associated station not in list */ - assoc_maclist->count = 8; - dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256); - if (assoc_maclist->count) { - int j; - for (i = 0; i < assoc_maclist->count; i++) { - for (j = 0; j < white_maclist->count; j++) { - if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j], ETHER_ADDR_LEN)) { - WL_SOFTAP(("match allow, let it be\n")); - break; - } - } - if (j == white_maclist->count) { - WL_SOFTAP(("match black, deauth it\n")); - scbval.val = htod32(1); - bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN); - dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, - sizeof(scb_val_t)); - } - } - } - } - return 0; + WL_ERROR(("%s, %d function:%s, line:%d\n", msg, res, func, line)); } -#else static int set_ap_mac_list(struct net_device *dev, void *buf) @@ -9062,7 +7443,7 @@ set_ap_mac_list(struct net_device *dev, void *buf) bool assoc_mac_matched = FALSE; WL_SOFTAP(("\n Cheking assoc STA: ")); - //dhd_print_buf(&assoc_maclist->ea[i], 6, 7); + dhd_print_buf(&assoc_maclist->ea[i], 6, 7); WL_SOFTAP(("with the b/w list:")); for (j = 0; j < maclist->count; j++) @@ -9103,7 +7484,6 @@ set_ap_mac_list(struct net_device *dev, void *buf) } #endif -#endif #ifdef SOFTAP @@ -9122,23 +7502,16 @@ wl_iw_process_private_ascii_cmd( WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n", __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET)); - if ( (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) || - (strnicmp(sub_cmd, "APSTA_CFG", strlen("APSTA_CFG")) == 0)) { - /* broadcom, add apsta cfg detection above. */ + if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) { - WL_SOFTAP((" AP_CFG or APSTA_CFG\n")); + WL_SOFTAP((" AP_CFG \n")); if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) { WL_ERROR(("ERROR: SoftAP CFG prams !\n")); ret = -1; } else { -#ifndef AP_ONLY - if ( apsta_enable ) - ret = set_apsta_cfg(dev, &my_ap); - else -#endif - ret = set_ap_cfg(dev, &my_ap); + ret = set_ap_cfg(dev, &my_ap); } } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) { @@ -9182,15 +7555,6 @@ wl_iw_process_private_ascii_cmd( } #endif -extern int dhd_set_pktfilter(dhd_pub_t * dhd, int add, int id, int offset, char *mask, char *pattern); -int wl_iw_set_pktfilter(struct net_device *dev, struct dd_pkt_filter_s *data) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - //printf("%s: add: %d, id: %d, offset: %d, mask: %s, pattern: %s\n", __func__, - // data->add, data->id, data->offset, data->mask, data->pattern); - - return dhd_set_pktfilter((dhd_pub_t *)iw->pub, data->add, data->id, data->offset, data->mask, data->pattern); -} static int wl_iw_set_priv( @@ -9258,18 +7622,14 @@ wl_iw_set_priv( ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0) ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra); -/* HTC_CSP_START */ - else if (strnicmp(extra, "GETBAND", strlen("GETBAND")) == 0) - ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "SETBAND", strlen("SETBAND")) == 0) - ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra); -/* HTC_CSP_END */ - else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0) + else if (strnicmp(extra, DTIM_SKIP_GET_CMD, strlen(DTIM_SKIP_GET_CMD)) == 0) ret = wl_iw_get_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, DTIM_SKIP_SET_CMD, strlen(DTIM_SKIP_SET_CMD)) == 0) ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0) - ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, SETSUSPENDOPT_CMD, strlen(SETSUSPENDOPT_CMD)) == 0) + ret = wl_iw_set_suspend_opt(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, SETSUSPENDMODE_CMD, strlen(SETSUSPENDMODE_CMD)) == 0) + ret = wl_iw_set_suspend_mode(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0) ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra); #if defined(PNO_SUPPORT) @@ -9277,22 +7637,16 @@ wl_iw_set_priv( ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, PNOSETUP_SET_CMD, strlen(PNOSETUP_SET_CMD)) == 0) ret = wl_iw_set_pno_set(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, PNOSETADD_SET_CMD, strlen(PNOSETADD_SET_CMD)) == 0) + ret = wl_iw_set_pno_setadd(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, PNOENABLE_SET_CMD, strlen(PNOENABLE_SET_CMD)) == 0) ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "PFN_REMOVE", strlen("PFN_REMOVE")) == 0) - ret = wl_iw_del_pfn(dev, info, (union iwreq_data *)dwrq, extra); #endif -#if !defined(WL_CFG80211) #if defined(CSCAN) else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0) ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra); -/* HTC_CSP_START */ - else if (strnicmp(extra, "GETCSCAN", strlen("GETCSCAN")) == 0) - ret = wl_iw_get_cscan(dev, info, (union iwreq_data *)dwrq, extra); -/* HTC_CSP_END */ #endif -#endif #ifdef CONFIG_WPS2 else if (strnicmp(extra, WPS_ADD_PROBE_REQ_IE_CMD, strlen(WPS_ADD_PROBE_REQ_IE_CMD)) == 0) @@ -9303,125 +7657,20 @@ wl_iw_set_priv( ret = wl_iw_del_wps_probe_req_ie(dev, info, (union iwreq_data *)dwrq, extra); #endif -#if !defined(WL_CFG80211) -#ifdef CUSTOMER_HW2 /* use powermode set only */ -/* HTC_CSP_START */ - else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) + else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra); - /* DD: we ignore command here. due to BCM embedded coexisted behavior - * in "POWERMODE" command. - */ - /* - else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) { - WL_TRACE_COEX(("%s:got Framwrork cmd: 'BTCOEXMODE'\n", __FUNCTION__)); + else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); - } - */ - else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0) + else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0) ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "GETWIFILOCK", strlen("GETWIFILOCK")) == 0) - ret = wl_iw_get_wifilock_mode(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "WIFICALL", strlen("WIFICALL")) == 0) - ret = wl_iw_set_wifi_call(dev, info, (union iwreq_data *)dwrq, extra); -/* HTC_CSP_END */ -#else - else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) - ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); -#endif -#endif /* !defined(WL_CFG80211) */ - #ifdef SOFTAP else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) { - wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra); } -#if !defined(WL_CFG80211) - else if (strnicmp(extra, "AP_TXPOWER_SET", strlen("AP_TXPOWER_SET")) == 0) { - WL_SOFTAP(("AP_TXPOWER_SET\n")); - set_ap_txpower(dev, (int *)(extra + PROFILE_OFFSET)); - } -#endif else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) { - WL_SOFTAP(("set AP_MAC_LIST_SET\n")); + WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n")); set_ap_mac_list(dev, (extra + PROFILE_OFFSET)); } -#endif -#if defined(WL_CFG80211) - else if (strnicmp(extra, "DEAUTH_STA", strlen("DEAUTH_STA")) == 0) { - wl_iw_softap_deassoc_stations(dev, extra + strlen("DEAUTH_STA") +1); - } -#if 0 - else if (strnicmp(extra, "SCAN_ABORT", strlen("SCAN_ABORT")) == 0) { - void wl_cfg80211_set_scan_abort(struct net_device *dev); - wl_cfg80211_set_scan_abort(dev); - } -#endif -#endif - /* for packet filter rule - */ - else if (strnicmp(extra, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0 || - strnicmp(extra, "RXFILTER-REMOVE", strlen("RXFILTER-REMOVE")) == 0) { -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - struct dd_pkt_filter_s *data = (struct dd_pkt_filter_s *)&extra[32]; - if ((data->id == ALLOW_IPV6_MULTICAST) || (data->id == ALLOW_IPV4_MULTICAST)) - { - - if (strnicmp(extra, "RXFILTER-ADD", strlen("RXFILTER-ADD")) == 0) - { - WL_TRACE(("RXFILTER-ADD MULTICAST filter\n")); - allowMulticast = false; - } - else - { - WL_TRACE(("RXFILTER-REMOVE MULTICAST filter\n")); - allowMulticast = true; - } - } -#endif -/* HTC_CSP_END */ - wl_iw_set_pktfilter(dev, (struct dd_pkt_filter_s *)&extra[32]); - } -/* HTC_CSP_START */ -#ifdef BCM4329_LOW_POWER - else if (strnicmp(extra, "GATEWAY-ADD", strlen("GATEWAY-ADD")) == 0) { - int i; - WL_TRACE(("Driver GET GATEWAY-ADD CMD!!!\n")); - sscanf(extra+12,"%d",&i); - sprintf( gatewaybuf, "%02x%02x%02x%02x", - i & 0xff, ((i >> 8) & 0xff), ((i >> 16) & 0xff), ((i >> 24) & 0xff) - ); - - if (strcmp(gatewaybuf, "00000000") == 0) - sprintf( gatewaybuf, "FFFFFFFF"); - - WL_TRACE(("gatewaybuf: %s",gatewaybuf)); - - if (screen_off && !hasDLNA && !allowMulticast) - dhd_set_keepalive(1); - } -#endif -/* HTC_CSP_END */ - else if (strnicmp(extra, "SCAN_MINRSSI", strlen("SCAN_MINRSSI")) == 0) { - wl_iw_scan_minrssi(dev, info, (union iwreq_data *)dwrq, extra); - } -#ifdef WLC_E_RSSI_LOW - else if (strnicmp(extra, "LOW_RSSI_IND_SET", strlen("LOW_RSSI_IND_SET")) == 0) { - WL_TRACE(("set LOW_RSSI_IND_SET\n")); - wl_iw_low_rssi_set(dev, info, (union iwreq_data *)dwrq, extra); - } -#endif -#if !defined(WL_CFG80211) - else if (strnicmp(extra, "SET_PRB_REQ", strlen("SET_PRB_REQ")) == 0) { - WL_TRACE(("SET_PRB_REQ\n")); - wl_iw_set_probe_request_ie(dev, (extra + PROFILE_OFFSET), dwrq->length-PROFILE_OFFSET); - } -/* HTC_CSP_START */ - else if (strnicmp(extra, "SET_PROJECT", strlen("SET_PROJECT")) == 0) { - WL_TRACE(("SET_PROJECT\n")); - wl_iw_set_project(dev, info, (union iwreq_data *)dwrq, extra); - } -/* HTC_CSP_END */ #endif else { WL_ERROR(("Unknown PRIVATE command %s - ignored\n", extra)); @@ -9444,25 +7693,6 @@ wl_iw_set_priv( return ret; } -#ifdef WL_CFG80211 -/* Try to keep the priv part of wext still can work when cfg80211 is enabled */ -static const iw_handler wl_iw_handler[] = -{ - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_priv, -}; -#else static const iw_handler wl_iw_handler[] = { (iw_handler) wl_iw_config_commit, @@ -9543,7 +7773,6 @@ static const iw_handler wl_iw_handler[] = (iw_handler) wl_iw_set_pmksa, #endif }; -#endif #if WIRELESS_EXT > 12 static const iw_handler wl_iw_priv_handler[] = { @@ -9589,24 +7818,14 @@ static const iw_handler wl_iw_priv_handler[] = { NULL, (iw_handler)iwpriv_fw_reload, - -/* HTC_CSP_START */ -#ifndef WL_CFG80211 - NULL, - (iw_handler)iwpriv_settxpower, -#endif -/* HTC_CSP_END */ - NULL, (iw_handler)iwpriv_set_ap_sta_disassoc, #endif -#ifndef WL_CFG80211 #if defined(CSCAN) NULL, (iw_handler)iwpriv_set_cscan -#endif -#endif +#endif }; static const struct iw_priv_args wl_iw_priv_args[] = @@ -9704,16 +7923,7 @@ static const struct iw_priv_args wl_iw_priv_args[] = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, "WL_FW_RELOAD" }, -/* HTC_CSP_START */ - { - WL_SET_AP_TXPWR, - IW_PRIV_TYPE_CHAR | 256, - 0, - "AP_TX_POWER" - }, -/* HTC_CSP_END */ #endif -#ifndef WL_CFG80211 #if defined(CSCAN) { WL_COMBO_SCAN, @@ -9721,7 +7931,6 @@ static const struct iw_priv_args wl_iw_priv_args[] = 0, "CSCAN" }, -#endif #endif }; @@ -9979,7 +8188,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) uint32 datalen = ntoh32(e->datalen); uint32 status = ntoh32(e->status); uint32 toto; - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); memset(&wrqu, 0, sizeof(wrqu)); memset(extra, 0, sizeof(extra)); @@ -9994,10 +8202,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) switch (event_type) { - case WLC_E_RELOAD: - WL_ERROR(("%s: Firmware ERROR %d\n", __FUNCTION__, status)); - net_os_send_hang_message(dev); - goto wl_iw_event_end; #if defined(SOFTAP) case WLC_E_PRUNE: if (ap_cfg_running) { @@ -10006,9 +8210,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) macaddr[0], macaddr[1], macaddr[2], macaddr[3], macaddr[4], macaddr[5])); - if (status) { - printf("reach max!!\n"); - } + if (ap_macmode) { int i; @@ -10044,16 +8246,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) #if defined(SOFTAP) WL_SOFTAP(("STA connect received %d\n", event_type)); if (ap_cfg_running) { -/* HTC_CSP_START */ - char *macaddr = (char *)&e->addr; - char mac_buf[32] = {0}; - sprintf(mac_buf, "STA_JOIN %02X:%02X:%02X:%02X:%02X:%02X", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - WL_SOFTAP(("join received, %02X:%02X:%02X:%02X:%02X:%02X!\n", - macaddr[0],macaddr[1],macaddr[2],macaddr[3],macaddr[4],macaddr[5])); - wl_iw_send_priv_event(priv_dev, mac_buf); -/* HTC_CSP_END */ + wl_iw_send_priv_event(priv_dev, "STA_JOIN"); goto wl_iw_event_end; } #endif @@ -10073,16 +8266,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) #if defined(SOFTAP) WL_SOFTAP(("STA disconnect received %d\n", event_type)); if (ap_cfg_running) { -/* HTC_CSP_START */ - char *macaddr = (char *)&e->addr; - char mac_buf[32] = {0}; - sprintf(mac_buf, "STA_LEAVE %02X:%02X:%02X:%02X:%02X:%02X", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - WL_SOFTAP(("leave received, %02X:%02X:%02X:%02X:%02X:%02X!\n", - macaddr[0],macaddr[1],macaddr[2],macaddr[3],macaddr[4],macaddr[5])); - wl_iw_send_priv_event(priv_dev, mac_buf); -/* HTC_CSP_END */ + wl_iw_send_priv_event(priv_dev, "STA_LEAVE"); goto wl_iw_event_end; } #endif @@ -10093,10 +8277,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) break; case WLC_E_LINK: case WLC_E_NDIS_LINK: - if(block_ap_event) { - printf("Block ap event\n"); - break; - } cmd = SIOCGIWAP; if (!(flags & WLC_EVENT_MSG_LINK)) { @@ -10112,19 +8292,12 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) wl_iw_send_priv_event(priv_dev, "AP_DOWN"); } else { WL_TRACE(("STA_Link Down\n")); - /* HTC_CSP_START */ - // for Auto Test System log parsing - printf(KERN_INFO "[ATS][disconnect][complete]\n"); - /* HTC_CSP_END */ g_ss_cache_ctrl.m_link_down = 1; } #else g_ss_cache_ctrl.m_link_down = 1; #endif - /* HTC_CSP_START */ - WL_DEFAULT(("[wl_iw_event] Link Down,%d\n", event_type)); - iw_link_state = 0; - /* HTC_CSP_END */ + WL_TRACE(("Link Down\n")); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); @@ -10145,22 +8318,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) WL_SOFTAP(("AP UP %d\n", event_type)); wl_iw_send_priv_event(priv_dev, "AP_UP"); - } else -#endif - { + } else { WL_TRACE(("STA_LINK_UP\n")); - iw_link_state = 1; - if ( apsta_enable && ap_net_dev ) { - printf("%s: schedule to restart the apsta ap part\n", __FUNCTION__); - schedule_delayed_work(&restart_apsta, 5*HZ); - } } - WL_DEFAULT(("Link UP\n")); +#else +#endif + WL_TRACE(("Link UP\n")); } -/* HTC_CSP_START */ - WAKE_LOCK_TIMEOUT(iw->pub, 15); -/* HTC_CSP_END */ wrqu.addr.sa_family = ARPHRD_ETHER; break; case WLC_E_ACTION_FRAME: @@ -10199,6 +8364,21 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) break; } + + case WLC_E_ASSOC_REQ_IE: + cmd = IWEVASSOCREQIE; + wrqu.data.length = datalen; + if (datalen < sizeof(extra)) + memcpy(extra, data, datalen); + break; + + case WLC_E_ASSOC_RESP_IE: + cmd = IWEVASSOCRESPIE; + wrqu.data.length = datalen; + if (datalen < sizeof(extra)) + memcpy(extra, data, datalen); + break; + case WLC_E_PMKID_CACHE: { if (data) { @@ -10228,25 +8408,9 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) } #endif -#ifdef WLC_E_RSSI_LOW - case WLC_E_RSSI_LOW: - printf("Recevied RSSI LOW event!\n"); - /* HTC_CSP_START */ - net_os_send_rssilow_message(dev); - /* HTC_CSP_END */ - break; -#endif - -#ifdef WLC_E_TX_STAT_ERROR - case WLC_E_TX_STAT_ERROR: - printk("Recevied TX state error event!\n"); - break; -#endif - case WLC_E_SCAN_COMPLETE: #if defined(WL_IW_USE_ISCAN) if (!g_iscan) { - WL_ERROR(("Event WLC_E_SCAN_COMPLETE on g_iscan NULL!")); goto wl_iw_event_end; } @@ -10268,43 +8432,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) #endif break; - case WLC_E_ASSOCREQ_IE: - printf("WLC_E_ASSOCREQ_IE, %d\n", datalen); - if (datalen > IW_CUSTOM_MAX) - break; - - - if (status) - cmd = IWEVASSOCRESPIE; - else - cmd = IWEVASSOCREQIE; - memcpy(extra, data, datalen); - wrqu.data.length = datalen; - break; -/* HTC_CSP_START */ - case WLC_E_LOAD_IND: - printf("WLC_E_LOAD_IND, %d\n", datalen); - if (datalen > IW_CUSTOM_MAX) - break; - - if (status) { - printf("HIGH INDICATE!!\n"); -#if 0 -/*#ifdef CONFIG_PERFLOCK*/ - if (!is_perf_lock_active(&wlan_perf_lock)) - perf_lock(&wlan_perf_lock); -#endif - } else { - printf("LOW INDICATE!!\n"); -#if 0 -/*#ifdef CONFIG_PERFLOCK*/ - if (is_perf_lock_active(&wlan_perf_lock)) - perf_unlock(&wlan_perf_lock); -#endif - } - - break; -/* HTC_CSP_END */ + case WLC_E_PFN_NET_FOUND: { wl_pfn_net_info_t *netinfo; @@ -10313,42 +8441,18 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) WL_ERROR(("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n", __FUNCTION__, PNO_EVENT_UP, netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.SSID_len)); -/* HTC_CSP_START */ - WAKE_LOCK_TIMEOUT(iw->pub, 30); - //cmd = IWEVCUSTOM; - //memset(&wrqu, 0, sizeof(wrqu)); - //strcpy(extra, PNO_EVENT_UP); - //wrqu.data.length = strlen(extra); -/* HTC_CSP_END */ - + cmd = IWEVCUSTOM; + memset(&wrqu, 0, sizeof(wrqu)); + strcpy(extra, PNO_EVENT_UP); + wrqu.data.length = strlen(extra); } break; - case WLC_E_SET_SSID: - { - if (status != WLC_E_STATUS_SUCCESS){ - printf("%s: WLC_E_SET_SSID, connect to AP failed, restart AP.\n", __FUNCTION__); -#ifdef SOFTAP - if ( apsta_enable && ap_net_dev ) { - printf("%s: schedule to restart the apsta ap part\n", __FUNCTION__); - schedule_delayed_work(&restart_apsta, HZ); - } -#endif - } - } - break; default: WL_TRACE(("Unknown Event %d: ignoring\n", event_type)); break; } -#ifdef DHD_BCM_WIFI_HDMI - - if (cmd && dhd_bcm_whdmi_enable && strncmp(dev->name, - DHD_WHDMI_SOFTAP_IF_NAME, DHD_WHDMI_SOFTAP_IF_NAME_LEN) == 0) { - - } else -#endif if (cmd) { if (cmd == SIOCGIWSCAN) wireless_send_event(dev, cmd, &wrqu, NULL); @@ -10472,13 +8576,12 @@ wl_iw_bt_flag_set( rtnl_lock(); #endif -/* HTC_CSP_START */ -#if 0 + #if defined(BT_DHCP_eSCO_FIX) + set_btc_esco_params(dev, set); #endif -#endif -/* HTC_CSP_END */ + #if defined(BT_DHCP_USE_FLAGS) WL_TRACE_COEX(("WI-FI priority boost via bt flags, set:%d\n", set)); @@ -10520,9 +8623,6 @@ _bt_dhcp_sysioc_thread(void *data) while (down_interruptible(&tsk_ctl->sema) == 0) { - if (wl_iw_force_exit) - break; - SMP_RD_BARRIER_DEPENDS(); if (tsk_ctl->terminated) { break; @@ -10539,7 +8639,7 @@ _bt_dhcp_sysioc_thread(void *data) WL_TRACE_COEX(("%s bt_dhcp stm: started \n", __FUNCTION__)); g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW; mod_timer(&g_bt->timer, - jiffies + BT_DHCP_OPPORTUNITY_WINDOW_TIME*HZ/1000); + jiffies + msecs_to_jiffies(BT_DHCP_OPPORTUNITY_WINDOW_TIME)); g_bt->timer_on = 1; break; @@ -10556,7 +8656,7 @@ _bt_dhcp_sysioc_thread(void *data) if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE); g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; - mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); + mod_timer(&g_bt->timer, jiffies + msecs_to_jiffies(BT_DHCP_FLAG_FORCE_TIME)); g_bt->timer_on = 1; break; @@ -10645,334 +8745,6 @@ wl_iw_bt_init(struct net_device *dev) } #endif -#ifdef SOFTAP -void -wl_iw_apsta_restart(struct work_struct *work) -{ - struct net_device *dev = priv_dev; - struct ap_profile *ap = &my_ap; - wlc_ssid_t ap_ssid; - int max_assoc = 8; - int res = 0; - int iolen = 0; - int mkvar_err = 0; - int bsscfg_index = 1; - char buf[WLC_IOCTL_SMLEN]; - wl_iw_t *iw; - - WL_SOFTAP(("Enter %s...\n", __FUNCTION__)); - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return; - } - - net_os_wake_lock(dev); - DHD_OS_MUTEX_LOCK(&wl_softap_lock); - - ap_cfg_running = TRUE; - - WL_SOFTAP(("wl_iw: set apsta profile:\n")); - WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); - WL_SOFTAP((" security = '%s'\n", ap->sec)); - if (ap->key[0] != '\0') - WL_SOFTAP((" key = '%s'\n", ap->key)); - WL_SOFTAP((" channel = %d\n", ap->channel)); - WL_SOFTAP((" max scb = %d\n", ap->max_scb)); - - iw = *(wl_iw_t **)netdev_priv(dev); - - dhd_state_set_flags( iw->pub, DHD_ATTACH_STATE_SOFTAP, 1); - sema_init(&ap_eth_ctl.sema, 0); - - max_assoc = ap->max_scb; - if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) { - WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__)); - goto fail; - } - - ap_ssid.SSID_len = strlen(ap->ssid); - strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); - - iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid), - ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); - if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) { - WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n", \ - res, __FUNCTION__)); - goto fail; - } - - ap_eth_ctl.thr_pid = -1; - - if (ap_net_dev == NULL) { - WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__)); - goto fail; - } - - WL_ERROR(("%s: %s Configure security & restart AP bss \n", \ - __FUNCTION__, ap_net_dev->name)); - - if ((res = wl_iw_set_ap_security(ap_net_dev, ap)) < 0) { - WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res)); - goto fail; - } - - if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) { - WL_ERROR(("%s fail to set bss up\n", __FUNCTION__)); - goto fail; - } - -fail: - WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res)); - WL_SOFTAP(("%s: SOFTAP - ENABLE BSS \n", __FUNCTION__)); - - DHD_OS_MUTEX_UNLOCK(&wl_softap_lock); - net_os_wake_unlock(dev); -} -#endif - -#ifdef WL_PROTECT -static void -wl_iw_sta_restart(struct net_device *dev) -{ - union iwreq_data wrqu; - char extra[IW_CUSTOM_MAX + 1]; - int cmd = 0; - - WL_TRACE(("Enter %s\n", __FUNCTION__)); - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return; - } - - dhd_net_if_lock(dev); - -/* HTC_CSP_START */ - if (dev_wlc_ioctl_off == 1) { - dhd_net_if_unlock(dev); - return; - } -/* HTC_CSP_END */ - -#if defined(WL_IW_USE_ISCAN) - g_iscan->iscan_state = ISCAN_STATE_IDLE; -#endif - - dhd_dev_reset(dev, 1); - -#if defined(BCMLXSDMMC) - sdioh_stop(NULL); -#endif - - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); - - bcm_mdelay(100); - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); - -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 0); -#endif - - dhd_dev_reset(dev, 0); - -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 1); -#endif - - dhd_dev_init_ioctl(dev); - - bcm_mdelay(300); - - printf("iw_link_state = %d\n", iw_link_state); - if (iw_link_state) { - cmd = SIOCGIWAP; - bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - bzero(&extra, ETHER_ADDR_LEN); - wireless_send_event(dev, cmd, &wrqu, extra); - iw_link_state = 0; - } - - dhd_net_if_unlock(dev); - WL_ERROR(("%s: WIFI_RECOVERY \n", __FUNCTION__)); - wl_iw_send_priv_event(dev, "WIFI_RECOVERY"); - return; -} - -static void wl_iw_ap_restart(void) -{ - WL_SOFTAP(("Enter %s...\n", __FUNCTION__)); - - ap_cfg_running = FALSE; - ap_net_dev = NULL; - - set_ap_cfg(priv_dev, &my_ap); - - WL_SOFTAP(("SOFTAP - ENABLE BSS \n")); - -#ifndef AP_ONLY - if (ap_net_dev == NULL) { - printf("ERROR: SOFTAP net_dev* is NULL !!!\n"); - } else { - iwpriv_en_ap_bss(ap_net_dev, NULL, NULL, NULL); - } -#endif - - if (ap_macmode) { - WL_SOFTAP(("start restore mac filter!\n")); -#ifndef AP_ONLY - set_ap_mac_list(ap_net_dev, (char *)&mac_list_buf); -#else - set_ap_mac_list(priv_dev, (char *)&mac_list_buf); -#endif - } -} - -static void wl_iw_restart(struct net_device *dev) -{ - wl_iw_sta_restart(dev); - -/* HTC_CSP_START */ - if (dev_wlc_ioctl_off == 1) { - return; - } -/* HTC_CSP_END */ - if ( ap_cfg_running ) - wl_iw_ap_restart(); - - dhd_reset_hang_was_sent(dev); - -} - -static int -_wl_protect_sysioc_thread(void *data) -{ - static int wlp_fail_count = 0; - int isup; - int ret = 0; - wl_iw_t *iw; - tsk_ctl_t *tsk_ctl = (tsk_ctl_t *)data; - - DAEMONIZE("wlp_sysioc"); - - if (!priv_dev) { - WL_ERROR(("%s: priv_dev is null\n", __FUNCTION__)); - tsk_ctl->thr_pid = -1; - complete(&tsk_ctl->completed); - return -1; - } - - iw = *(wl_iw_t **)netdev_priv(priv_dev); - - if (!iw) { - WL_ERROR(("%s: wl is null\n", __FUNCTION__)); - tsk_ctl->thr_pid = -1; - complete(&tsk_ctl->completed); - return -1; - } - - complete(&tsk_ctl->completed); - - while (down_interruptible(&tsk_ctl->sema) == 0) { - - if (wl_iw_force_exit) - break; - - SMP_RD_BARRIER_DEPENDS(); - if (tsk_ctl->terminated) { - break; - } - - if (g_wl_protect->timer_on) { - g_wl_protect->timer_on = 0; - del_timer_sync(&g_wl_protect->timer); - } - - if ( g_wl_protect->reset_now ){ - g_wl_protect->reset_now = 0; - wl_iw_restart(priv_dev); - } else { - if ((ret = dev_wlc_ioctl(priv_dev, WLC_GET_UP, &isup, sizeof(isup))) != 0) - wlp_fail_count++; - else - wlp_fail_count = 0; - - if (wlp_fail_count == WL_MAX_FAIL_COUNT) { - wl_iw_restart(priv_dev); - } - } - - mod_timer(&g_wl_protect->timer, jiffies + WL_PROTECT_TIME*HZ/1000); - g_wl_protect->timer_on = 1; - - } - - if (g_wl_protect->timer_on) { - g_wl_protect->timer_on = 0; - del_timer_sync(&g_wl_protect->timer); - } - complete_and_exit(&tsk_ctl->completed, 0); -} - -static void -wl_iw_protect_timerfunc(ulong data) -{ - wlp_info_t *wlp_local = (wlp_info_t *)data; - wlp_local->timer_on = 0; - WL_TRACE(("%s\n", __FUNCTION__)); - - up(&wlp_local->tsk_ctl.sema); -} - -static int -wl_iw_protect_init(void) -{ - wlp_info_t *wl_protect = NULL; - - wl_protect = kmalloc(sizeof(wlp_info_t), GFP_KERNEL); - if (!wl_protect) - return -ENOMEM; - - memset(wl_protect, 0, sizeof(wlp_info_t)); - wl_protect->tsk_ctl.thr_pid = -1; - g_wl_protect = wl_protect; - - - init_timer(&wl_protect->timer); - wl_protect->timer.data = (ulong)wl_protect; - wl_protect->timer.function = wl_iw_protect_timerfunc; - wl_protect->timer_on = 0; - - PROC_START(_wl_protect_sysioc_thread, wl_protect, &wl_protect->tsk_ctl, 0); - if (wl_protect->tsk_ctl.thr_pid < 0 ) { - WL_ERROR(("Failed in %s\n", __FUNCTION__)); - return -ENOMEM; - } - - return 0; -} - -static void -wl_iw_protect_release(void) -{ - wlp_info_t *local = g_wl_protect; - - if (!local) { - return; - } - - if (local->tsk_ctl.thr_pid >= 0) { - PROC_STOP(&local->tsk_ctl); - } - - kfree(local); - g_wl_protect = NULL; -} - -#endif //WL_PROTECT - int wl_iw_attach(struct net_device *dev, void * dhdp) { @@ -11028,10 +8800,9 @@ wl_iw_attach(struct net_device *dev, void * dhdp) #ifdef CONFIG_WPS2 g_wps_probe_req_ie = NULL; g_wps_probe_req_ie_len = 0; -#endif +#endif -#ifndef WL_CFG80211 - iscan->timer_ms = 3000; + iscan->timer_ms = 8000; init_timer(&iscan->timer); iscan->timer.data = (ulong)iscan; iscan->timer.function = wl_iw_timerfunc; @@ -11039,7 +8810,6 @@ wl_iw_attach(struct net_device *dev, void * dhdp) PROC_START(_iscan_sysioc_thread, iscan, &iscan->tsk_ctl, 0); if (iscan->tsk_ctl.thr_pid < 0) return -ENOMEM; -#endif #endif iw = *(wl_iw_t **)netdev_priv(dev); @@ -11057,7 +8827,7 @@ wl_iw_attach(struct net_device *dev, void * dhdp) memset(g_scan, 0, G_SCAN_RESULTS); g_scan_specified_ssid = 0; -#if !defined(CSCAN) && !defined(WL_CFG80211) +#if !defined(CSCAN) wl_iw_init_ss_cache_ctrl(); #endif @@ -11066,15 +8836,7 @@ wl_iw_attach(struct net_device *dev, void * dhdp) wl_iw_bt_init(dev); #endif -#ifdef WL_PROTECT - wl_iw_protect_init(); -#endif -/* HTC_CSP_START */ -#if !defined(WL_CFG80211) - // perf_lock_init(&wl_wificall_perf_lock, PERF_LOCK_HIGHEST, "wifi-call"); - mutex_init(&wl_wificall_mutex); -#endif/* !defined(WL_CFG80211) */ -/* HTC_CSP_END */ + return 0; } @@ -11087,11 +8849,9 @@ wl_iw_detach(void) if (!iscan) return; -#ifndef WL_CFG80211 if (iscan->tsk_ctl.thr_pid >= 0) { PROC_STOP(&iscan->tsk_ctl); } -#endif DHD_OS_MUTEX_LOCK(&wl_cache_lock); while (iscan->list_hdr) { buf = iscan->list_hdr->next; @@ -11115,50 +8875,20 @@ wl_iw_detach(void) g_wps_probe_req_ie = NULL; g_wps_probe_req_ie_len = 0; } -#endif -#if !defined(CSCAN) && !defined(WL_CFG80211) +#endif +#if !defined(CSCAN) wl_iw_release_ss_cache_ctrl(); #endif #ifdef COEX_DHCP wl_iw_bt_release(); #endif -#ifdef WL_PROTECT - wl_iw_protect_release(); -#endif - #ifdef SOFTAP if (ap_cfg_running) { WL_TRACE(("\n%s AP is going down\n", __FUNCTION__)); wl_iw_send_priv_event(priv_dev, "AP_DOWN"); } - cancel_delayed_work_sync(&restart_apsta); #endif -/* HTC_CSP_START */ -#if !defined(WL_CFG80211) - mutex_lock(&wl_wificall_mutex); - if (1 == wl_iw_is_during_wifi_call()) { - printf("remove wlan during wifi call.\n"); - - dhdhtc_set_power_control(0, DHDHTC_POWER_CTRL_WIFI_PHONE); - dhdhtc_update_wifi_power_mode(screen_off); - dhdhtc_update_dtim_listen_interval(screen_off); - // perf_unlock(&wl_wificall_perf_lock); - wl_iw_wifi_call = 0; - } - mutex_unlock(&wl_wificall_mutex); - // perf_lock_deinit(&wl_wificall_perf_lock); - - /* delete buffered wps ie if any */ - if (ie_setbuf) { - kfree(ie_setbuf); - ie_setbuf = NULL; - } -#endif/* !defined(WL_CFG80211) */ - - priv_dev = NULL; -/* HTC_CSP_END */ - wl_iw_force_exit = 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_iw.h b/drivers/net/wireless/bcmdhd/wl_iw.h index b2a8d93e..9cdb53df 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.h +++ b/drivers/net/wireless/bcmdhd/wl_iw.h @@ -47,13 +47,15 @@ #define BAND_SET_CMD "SETBAND" #define DTIM_SKIP_GET_CMD "DTIMSKIPGET" #define DTIM_SKIP_SET_CMD "DTIMSKIPSET" -#define SETSUSPEND_CMD "SETSUSPENDOPT" +#define SETSUSPENDOPT_CMD "SETSUSPENDOPT" +#define SETSUSPENDMODE_CMD "SETSUSPENDMODE" #define PNOSSIDCLR_SET_CMD "PNOSSIDCLR" #define PNOSETUP_SET_CMD "PNOSETUP " +#define PNOSETADD_SET_CMD "PNOSETADD" #define PNOENABLE_SET_CMD "PNOFORCE" #define PNODEBUG_SET_CMD "PNODEBUG" -#define TXPOWER_SET_CMD "TXPOWER" +#define TXPOWER_SET_CMD "TXPOWER" #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" @@ -96,11 +98,8 @@ struct cntry_locales_custom { #define AP_LPB_CMD (SIOCIWFIRSTPRIV+23) #define WL_AP_STOP (SIOCIWFIRSTPRIV+25) #define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27) -/* HTC_CSP_START */ -#define WL_SET_AP_TXPWR (SIOCIWFIRSTPRIV+29) -/* HTC_CSP_END */ -#define WL_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+31) -#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+33) +#define WL_AP_STA_DISASSOC (SIOCIWFIRSTPRIV+29) +#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+31) #define G_SCAN_RESULTS 8*1024 @@ -162,7 +161,35 @@ typedef enum broadcast_first_scan { BROADCAST_SCAN_FIRST_RESULT_READY, BROADCAST_SCAN_FIRST_RESULT_CONSUMED } broadcast_first_scan_t; +#ifdef SOFTAP +#define SSID_LEN 33 +#define SEC_LEN 16 +#define KEY_LEN 65 +#define PROFILE_OFFSET 32 +struct ap_profile { + uint8 ssid[SSID_LEN]; + uint8 sec[SEC_LEN]; + uint8 key[KEY_LEN]; + uint32 channel; + uint32 preamble; + uint32 max_scb; + uint32 closednet; + char country_code[WLC_CNTRY_BUF_SZ]; +}; + +#define MACLIST_MODE_DISABLED 0 +#define MACLIST_MODE_DENY 1 +#define MACLIST_MODE_ALLOW 2 +struct mflist { + uint count; + struct ether_addr ea[16]; +}; +struct mac_list_set { + uint32 mode; + struct mflist mac_list; +}; +#endif #if WIRELESS_EXT > 12 #include @@ -177,14 +204,11 @@ void wl_iw_detach(void); extern int net_os_wake_lock(struct net_device *dev); extern int net_os_wake_unlock(struct net_device *dev); -extern int dhd_os_wake_force_unlock(dhd_pub_t *pub); extern int net_os_wake_lock_timeout(struct net_device *dev); -extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); +extern int net_os_wake_lock_ctrl_timeout_enable(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); -extern int net_os_set_suspend(struct net_device *dev, int val); +extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int net_os_set_dtim_skip(struct net_device *dev, int val); -extern int net_os_set_packet_filter(struct net_device *dev, int val); -extern int net_os_send_hang_message(struct net_device *dev); extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) @@ -203,6 +227,18 @@ extern void get_customized_country_code(char *country_iso_code, wl_country_t *cs iwe_stream_add_point(stream, ends, iwe, extra) #endif +extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); +extern int dhd_pno_clean(dhd_pub_t *dhd); +extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, + ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_pno_get_status(dhd_pub_t *dhd); +extern int dhd_dev_pno_reset(struct net_device *dev); +extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, + int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); +extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); +extern int dhd_dev_get_pno_status(struct net_device *dev); +extern int dhd_get_dtim_skip(dhd_pub_t *dhd); + void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); #define PNO_TLV_PREFIX 'S' @@ -271,7 +307,6 @@ extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num); -extern int wl_iw_get_onoff(void); #define NETDEV_PRIV(dev) (*(wl_iw_t **)netdev_priv(dev)) @@ -279,6 +314,6 @@ extern int wl_iw_get_onoff(void); #define WPS_ADD_PROBE_REQ_IE_CMD "ADD_WPS_PROBE_REQ_IE " #define WPS_DEL_PROBE_REQ_IE_CMD "DEL_WPS_PROBE_REQ_IE " #define WPS_PROBE_REQ_IE_CMD_LENGTH 21 -#endif +#endif #endif diff --git a/drivers/net/wireless/bcmdhd/wl_linux_mon.c b/drivers/net/wireless/bcmdhd/wl_linux_mon.c index 0486af4d..f44b4b04 100644 --- a/drivers/net/wireless/bcmdhd/wl_linux_mon.c +++ b/drivers/net/wireless/bcmdhd/wl_linux_mon.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux_mon.c 278714 2011-08-19 19:25:22Z $ + * $Id: wl_linux_mon.c 303266 2011-12-16 00:15:23Z $ */ #include diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index 778a5182..51a80645 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -53,21 +53,13 @@ s32 wldev_ioctl( s32 ret = 0; struct wl_ioctl ioc; - memset(&ioc, 0, sizeof(ioc)); ioc.cmd = cmd; ioc.buf = arg; ioc.len = len; ioc.set = set; -#if 0 - if (arg != NULL) { - WLDEV_ERROR(("iovar:%s ioc->len%d cmd->%d type->%s\n", - (char *)arg, ioc.len, cmd, set ? "set": "get")); - } -#endif - ret = dhd_ioctl_entry_local(dev, &ioc, cmd); - + ret = dhd_ioctl_entry_local(dev, &ioc, cmd); return ret; } @@ -198,6 +190,7 @@ s32 wldev_mkiovar_bsscfg( return iolen; } + s32 wldev_iovar_getbuf_bsscfg( struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync) @@ -327,6 +320,8 @@ int wldev_set_band( if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), 1); + if (!error) + dhd_bus_band_set(dev, band); } return error; } @@ -356,20 +351,71 @@ int wldev_set_country( __FUNCTION__, error)); return error; } - } - cspec.rev = -1; - memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); - memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); - get_customized_country_code((char *)&cspec.country_abbrev, &cspec); - error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), - smbuf, sizeof(smbuf), NULL); - if (error < 0) { - WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", + + cspec.rev = -1; + memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); + memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); + get_customized_country_code((char *)&cspec.country_abbrev, &cspec); + error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec), + smbuf, sizeof(smbuf), NULL); + if (error < 0) { + WLDEV_ERROR(("%s: set country for %s as %s rev %d failed\n", + __FUNCTION__, country_code, cspec.ccode, cspec.rev)); + return error; + } + dhd_bus_country_set(dev, &cspec); + WLDEV_ERROR(("%s: set country for %s as %s rev %d\n", __FUNCTION__, country_code, cspec.ccode, cspec.rev)); - return error; } - dhd_bus_country_set(dev, &cspec); - printk(KERN_INFO "[WLAN] %s: set country for %s as %s rev %d\n", - __func__, country_code, cspec.ccode, cspec.rev); return 0; } + +/* + * softap channel autoselect + */ +int wldev_get_auto_channel(struct net_device *dev, int *chan) +{ + int chosen = 0; + wl_uint32_list_t request; + int retry = 0; + int updown = 0; + int ret = 0; + wlc_ssid_t null_ssid; + + memset(&null_ssid, 0, sizeof(wlc_ssid_t)); + ret |= wldev_ioctl(dev, WLC_UP, &updown, sizeof(updown), true); + + ret |= wldev_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid), true); + + request.count = htod32(0); + ret = wldev_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request), true); + if (ret < 0) { + WLDEV_ERROR(("can't start auto channel scan:%d\n", ret)); + goto fail; + } + + while (retry++ < 15) { + + bcm_mdelay(350); + + ret = wldev_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen), false); + + if ((ret == 0) && (dtoh32(chosen) != 0)) { + *chan = (uint16)chosen & 0x00FF; /* covert chanspec --> chan number */ + printf("%s: Got channel = %d, attempt:%d\n", + __FUNCTION__, *chan, retry); + break; + } + } + + if ((ret = wldev_ioctl(dev, WLC_DOWN, &updown, sizeof(updown), true)) < 0) { + WLDEV_ERROR(("%s fail to WLC_DOWN ioctl err =%d\n", __FUNCTION__, ret)); + goto fail; + } + +fail : + if (ret < 0) { + WLDEV_ERROR(("%s: return value %d\n", __FUNCTION__, ret)); + } + return ret; +} diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 0d87b625..dd3c899d 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -40,14 +40,14 @@ s32 wldev_ioctl( */ s32 wldev_iovar_getbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex *buf_sync); + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); /** Set named IOVARs, this function calls wl_dev_ioctl with * WLC_SET_VAR IOCTL code */ s32 wldev_iovar_setbuf( struct net_device *dev, s8 *iovar_name, - void *param, s32 paramlen, void *buf, s32 buflen, struct mutex *buf_sync); + void *param, s32 paramlen, void *buf, s32 buflen, struct mutex* buf_sync); s32 wldev_iovar_setint( struct net_device *dev, s8 *iovar, s32 val); @@ -68,14 +68,14 @@ s32 wldev_mkiovar_bsscfg( */ s32 wldev_iovar_getbuf_bsscfg( struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, - void *buf, s32 buflen, s32 bsscfg_idx, struct mutex *buf_sync); + void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); /** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with * WLC_SET_VAR IOCTL code */ s32 wldev_iovar_setbuf_bsscfg( struct net_device *dev, s8 *iovar_name, void *param, s32 paramlen, - void *buf, s32 buflen, s32 bsscfg_idx, struct mutex *buf_sync); + void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync); s32 wldev_iovar_getint_bsscfg( struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx); @@ -85,6 +85,7 @@ s32 wldev_iovar_setint_bsscfg( extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); +extern void dhd_bus_band_set(struct net_device *dev, uint band); extern int wldev_set_country(struct net_device *dev, char *country_code); extern int net_os_wake_lock(struct net_device *dev); extern int net_os_wake_unlock(struct net_device *dev); @@ -92,7 +93,7 @@ extern int net_os_wake_lock_timeout(struct net_device *dev); extern int net_os_wake_lock_timeout_enable(struct net_device *dev, int val); extern int net_os_set_dtim_skip(struct net_device *dev, int val); extern int net_os_set_suspend_disable(struct net_device *dev, int val); -extern int net_os_set_suspend(struct net_device *dev, int val); +extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left); @@ -107,4 +108,6 @@ int wldev_get_band(struct net_device *dev, uint *pband); int wldev_set_band(struct net_device *dev, uint band); +int wldev_get_auto_channel(struct net_device *dev, int *chan); + #endif /* __WLDEV_COMMON_H__ */ diff --git a/include/linux/export.h b/include/linux/export.h new file mode 100644 index 00000000..696c0f48 --- /dev/null +++ b/include/linux/export.h @@ -0,0 +1,89 @@ +#ifndef _LINUX_EXPORT_H +#define _LINUX_EXPORT_H +/* + * Export symbols from the kernel to modules. Forked from module.h + * to reduce the amount of pointless cruft we feed to gcc when only + * exporting a simple symbol or two. + * + * If you feel the need to add #include to this file + * then you are doing something wrong and should go away silently. + */ + +/* Some toolchains use a `_' prefix for all user symbols. */ +#ifdef CONFIG_SYMBOL_PREFIX +#define MODULE_SYMBOL_PREFIX CONFIG_SYMBOL_PREFIX +#else +#define MODULE_SYMBOL_PREFIX "" +#endif + +struct kernel_symbol +{ + unsigned long value; + const char *name; +}; + +#ifdef MODULE +extern struct module __this_module; +#define THIS_MODULE (&__this_module) +#else +#define THIS_MODULE ((struct module *)0) +#endif + +#ifdef CONFIG_MODULES + +#ifndef __GENKSYMS__ +#ifdef CONFIG_MODVERSIONS +/* Mark the CRC weak since genksyms apparently decides not to + * generate a checksums for some symbols */ +#define __CRC_SYMBOL(sym, sec) \ + extern void *__crc_##sym __attribute__((weak)); \ + static const unsigned long __kcrctab_##sym \ + __used \ + __attribute__((section("___kcrctab" sec "+" #sym), unused)) \ + = (unsigned long) &__crc_##sym; +#else +#define __CRC_SYMBOL(sym, sec) +#endif + +/* For every exported symbol, place a struct in the __ksymtab section */ +#define __EXPORT_SYMBOL(sym, sec) \ + extern typeof(sym) sym; \ + __CRC_SYMBOL(sym, sec) \ + static const char __kstrtab_##sym[] \ + __attribute__((section("__ksymtab_strings"), aligned(1))) \ + = MODULE_SYMBOL_PREFIX #sym; \ + static const struct kernel_symbol __ksymtab_##sym \ + __used \ + __attribute__((section("___ksymtab" sec "+" #sym), unused)) \ + = { (unsigned long)&sym, __kstrtab_##sym } + +#define EXPORT_SYMBOL(sym) \ + __EXPORT_SYMBOL(sym, "") + +#define EXPORT_SYMBOL_GPL(sym) \ + __EXPORT_SYMBOL(sym, "_gpl") + +#define EXPORT_SYMBOL_GPL_FUTURE(sym) \ + __EXPORT_SYMBOL(sym, "_gpl_future") + +#ifdef CONFIG_UNUSED_SYMBOLS +#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") +#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") +#else +#define EXPORT_UNUSED_SYMBOL(sym) +#define EXPORT_UNUSED_SYMBOL_GPL(sym) +#endif + +#endif /* __GENKSYMS__ */ + +#else /* !CONFIG_MODULES... */ + +#define EXPORT_SYMBOL(sym) +#define EXPORT_SYMBOL_GPL(sym) +#define EXPORT_SYMBOL_GPL_FUTURE(sym) +#define EXPORT_UNUSED_SYMBOL(sym) +#define EXPORT_UNUSED_SYMBOL_GPL(sym) + +#endif /* CONFIG_MODULES */ + +#endif /* _LINUX_EXPORT_H */ diff --git a/include/linux/module.h b/include/linux/module.h index d9ca2d5d..5c0da678 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -34,12 +35,6 @@ #define MODULE_NAME_LEN MAX_PARAM_PREFIX_LEN -struct kernel_symbol -{ - unsigned long value; - const char *name; -}; - struct modversion_info { unsigned long crc; @@ -578,6 +573,10 @@ int unregister_module_notifier(struct notifier_block * nb); extern void print_modules(void); +#ifdef CONFIG_WIMAX +extern bool find_wimax_modules(void); +#endif + extern void module_update_tracepoints(void); extern int module_get_iter_tracepoints(struct tracepoint_iter *iter); diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 0634b8f0..89a84219 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -6,7 +6,7 @@ * Copyright 2006-2010 Johannes Berg * Copyright 2008 Michael Wu * Copyright 2008 Luis Carlos Cobo - * Copyright 2008 Michael Buesch + * Copyright 2008 Michael Buesch * Copyright 2008, 2009 Luis R. Rodriguez * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe @@ -156,14 +156,23 @@ * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX * or %NL80211_ATTR_MAC. * - * @NL80211_CMD_GET_BEACON: retrieve beacon information (returned in a - * %NL80222_CMD_NEW_BEACON message) - * @NL80211_CMD_SET_BEACON: set the beacon on an access point interface - * using the %NL80211_ATTR_BEACON_INTERVAL, %NL80211_ATTR_DTIM_PERIOD, - * %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL attributes. - * @NL80211_CMD_NEW_BEACON: add a new beacon to an access point interface, - * parameters are like for %NL80211_CMD_SET_BEACON. - * @NL80211_CMD_DEL_BEACON: remove the beacon, stop sending it + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL + * attributes. For drivers that generate the beacon and probe responses + * internally, the following attributes must be provided: %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters + * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that + * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, + * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, + * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, + * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, + * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, + * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. + * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP + * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface + * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP * * @NL80211_CMD_GET_STATION: Get station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. @@ -231,6 +240,8 @@ * * @NL80211_CMD_GET_SCAN: get scan results * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * probe requests at CCK rate or not. * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to * NL80211_CMD_GET_SCAN and on the "scan" multicast group) * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, @@ -247,7 +258,8 @@ * passed, all channels allowed for the current regulatory domain * are used. Extra IEs can also be passed from the userspace by * using the %NL80211_ATTR_IE attribute. - * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ENOENT + * if scheduled scan is not running. * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan * results available. * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has @@ -357,6 +369,11 @@ * %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE and * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT. + * Background scan period can optionally be + * specified in %NL80211_ATTR_BG_SCAN_PERIOD, + * if not specified default background scan configuration + * in driver is used and if period value is 0, bg scan will be disabled. + * This attribute is ignored if driver does not support roam scan. * It is also sent as an event, with the BSSID and response IEs when the * connection is established or failed to be established. This can be * determined by the STATUS_CODE attribute. @@ -424,6 +441,8 @@ * specified using %NL80211_ATTR_DURATION. When called, this operation * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the * TX status event pertaining to the TX request. + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * management frames at CCK rate or not in 2GHz band. * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this * command may be used with the corresponding cookie to cancel the wait * time if it is known that it is no longer necessary. @@ -483,6 +502,52 @@ * more background information, see * http://wireless.kernel.org/en/users/Documentation/WoWLAN. * + * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver + * the necessary information for supporting GTK rekey offload. This + * feature is typically used during WoWLAN. The configuration data + * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and + * contains the data in sub-attributes). After rekeying happened, + * this command may also be sent by the driver as an MLME event to + * inform userspace of the new replay counter. + * + * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace + * of PMKSA caching dandidates. + * + * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). + * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. + * + * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP + * (or GO) interface (i.e. hostapd) to ask for unexpected frames to + * implement sending deauth to stations that send unexpected class 3 + * frames. Also used as the event sent by the kernel when such a frame + * is received. + * For the event, the %NL80211_ATTR_MAC attribute carries the TA and + * other attributes like the interface index are present. + * If used as the command it must have an interface index and you can + * only unsubscribe from the event by closing the socket. Subscription + * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events. + * + * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the + * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame + * and wasn't already in a 4-addr VLAN. The event will be sent similarly + * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener. + * + * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface + * by sending a null data frame to it and reporting when the frame is + * acknowleged. This is used to allow timing out inactive clients. Uses + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a + * direct reply with an %NL80211_ATTR_COOKIE that is later used to match + * up the event with the request. The event includes the same data and + * has %NL80211_ATTR_ACK set if the frame was ACKed. + * + * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from + * other BSSes when any interfaces are in AP mode. This helps implement + * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME + * messages. Note that per PHY only one application may register. + * + * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether + * No Acknowledgement Policy should be applied. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -507,8 +572,10 @@ enum nl80211_commands { NL80211_CMD_GET_BEACON, NL80211_CMD_SET_BEACON, - NL80211_CMD_NEW_BEACON, - NL80211_CMD_DEL_BEACON, + NL80211_CMD_START_AP, + NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, + NL80211_CMD_STOP_AP, + NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP, NL80211_CMD_GET_STATION, NL80211_CMD_SET_STATION, @@ -605,6 +672,23 @@ enum nl80211_commands { NL80211_CMD_SCHED_SCAN_RESULTS, NL80211_CMD_SCHED_SCAN_STOPPED, + NL80211_CMD_SET_REKEY_OFFLOAD, + + NL80211_CMD_PMKSA_CANDIDATE, + + NL80211_CMD_TDLS_OPER, + NL80211_CMD_TDLS_MGMT, + + NL80211_CMD_UNEXPECTED_FRAME, + + NL80211_CMD_PROBE_CLIENT, + + NL80211_CMD_REGISTER_BEACONS, + + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + + NL80211_CMD_SET_NOACK_MAP, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -625,6 +709,8 @@ enum nl80211_commands { #define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE #define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + /* source-level API compatibility */ #define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG #define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG @@ -745,8 +831,14 @@ enum nl80211_commands { * * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can + * scan with a single scheduled scan request, a wiphy attribute. * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements * that can be added to a scan request + * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information + * elements that can be added to a scheduled scan request + * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be + * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute. * * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive @@ -827,18 +919,20 @@ enum nl80211_commands { * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT * event (u16) * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating - * that protected APs should be used. + * that protected APs should be used. This is also used with NEW_BEACON to + * indicate that the BSS is to use protection. * - * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT and ASSOCIATE to - * indicate which unicast key ciphers will be used with the connection + * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON + * to indicate which unicast key ciphers will be used with the connection * (an array of u32). - * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT and ASSOCIATE to indicate - * which group key cipher will be used with the connection (a u32). - * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT and ASSOCIATE to indicate - * which WPA version(s) the AP we want to associate with is using + * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which group key cipher will be used with the connection (a + * u32). + * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which WPA version(s) the AP we want to associate with is using * (a u32 with flags from &enum nl80211_wpa_versions). - * @NL80211_ATTR_AKM_SUITES: Used with CONNECT and ASSOCIATE to indicate - * which key management algorithm(s) to use (an array of u32). + * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which key management algorithm(s) to use (an array of u32). * * @NL80211_ATTR_REQ_IE: (Re)association request information elements as * sent out by the card, for ROAM and successful CONNECT events. @@ -978,8 +1072,8 @@ enum nl80211_commands { * driving the peer link management state machine. * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. * - * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, - * the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy + * capabilities, the supported WoWLAN triggers * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to * indicate which WoW triggers should be enabled. This is also * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN @@ -987,6 +1081,24 @@ enum nl80211_commands { * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan * cycles, in msecs. + + * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more + * sets of attributes to match during scheduled scans. Only BSSs + * that match any of the sets will be reported. These are + * pass-thru filter rules. + * For a match to succeed, the BSS must match all attributes of a + * set. Since not every hardware supports matching all types of + * attributes, there is no guarantee that the reported BSSs are + * fully complying with the match sets and userspace needs to be + * able to ignore them by itself. + * Thus, the implementation is somewhat hardware-dependent, but + * this is only an optimization and the userspace application + * needs to handle all the non-filtered results anyway. + * If the match attributes don't make sense when combined with + * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID + * is included in the probe request, but the match attributes + * will never let it go through), -EINVAL may be returned. + * If ommited, no filtering is done. * * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported * interface combinations. In each nested item, it contains attributes @@ -996,6 +1108,162 @@ enum nl80211_commands { * are managed in software: interfaces of these types aren't subject to * any restrictions in their number or combinations. * + * @%NL80211_ATTR_REKEY_DATA: nested attribute containing the information + * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data. + * + * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan, + * nested array attribute containing an entry for each band, with the entry + * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but + * without the length restriction (at most %NL80211_MAX_SUPP_RATES). + * + * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon + * and Probe Response (when response to wildcard Probe Request); see + * &enum nl80211_hidden_ssid, represented as a u32 + * + * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame. + * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to + * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the + * driver (or firmware) replies to Probe Request frames. + * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association + * Response frames. This is used with %NL80211_CMD_NEW_BEACON and + * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into + * (Re)Association Response frames when the driver (or firmware) replies to + * (Re)Association Request frames. + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working + * as AP. + * + * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of + * roaming to another AP in the same ESS if the signal lever is low. + * + * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching + * candidate information, see &enum nl80211_pmksa_candidate_attr. + * + * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not + * for management frames transmission. In order to avoid p2p probe/action + * frames are being transmitted at CCK rate in 2GHz band, the user space + * applications use this attribute. + * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and + * %NL80211_CMD_FRAME commands. + * + * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup + * request, link setup confirm, link teardown, etc.). Values are + * described in the TDLS (802.11z) specification. + * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a + * TDLS conversation between two devices. + * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see + * &enum nl80211_tdls_operation, represented as a u8. + * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate + * as a TDLS peer sta. + * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown + * procedures should be performed by sending TDLS packets via + * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be + * used for asking the driver to perform a TDLS operation. + * + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices + * that have AP support to indicate that they have the AP SME integrated + * with support for the features listed in this attribute, see + * &enum nl80211_ap_sme_features. + * + * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells + * the driver to not wait for an acknowledgement. Note that due to this, + * it will also not give a status callback nor return a cookie. This is + * mostly useful for probe responses to save airtime. + * + * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from + * &enum nl80211_feature_flags and is advertised in wiphy information. + * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe + * + * requests while operating in AP-mode. + * This attribute holds a bitmap of the supported protocols for + * offloading (see &enum nl80211_probe_resp_offload_support_attr). + * + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working + * as AP. + * + * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of + * roaming to another AP in the same ESS if the signal lever is low. + * + * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching + * candidate information, see &enum nl80211_pmksa_candidate_attr. + * + * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not + * for management frames transmission. In order to avoid p2p probe/action + * frames are being transmitted at CCK rate in 2GHz band, the user space + * applications use this attribute. + * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and + * %NL80211_CMD_FRAME commands. + * + * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup + * request, link setup confirm, link teardown, etc.). Values are + * described in the TDLS (802.11z) specification. + * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a + * TDLS conversation between two devices. + * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see + * &enum nl80211_tdls_operation, represented as a u8. + * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate + * as a TDLS peer sta. + * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown + * procedures should be performed by sending TDLS packets via + * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be + * used for asking the driver to perform a TDLS operation. + * + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices + * that have AP support to indicate that they have the AP SME integrated + * with support for the features listed in this attribute, see + * &enum nl80211_ap_sme_features. + * + * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells + * the driver to not wait for an acknowledgement. Note that due to this, + * it will also not give a status callback nor return a cookie. This is + * mostly useful for probe responses to save airtime. + * + * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from + * &enum nl80211_feature_flags and is advertised in wiphy information. + * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe + * + * requests while operating in AP-mode. + * This attribute holds a bitmap of the supported protocols for + * offloading (see &enum nl80211_probe_resp_offload_support_attr). + * + * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire + * probe-response frame. The DA field in the 802.11 header is zero-ed out, + * to be filled by the FW. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the + * ATTR_HT_CAPABILITY to which attention should be paid. + * Currently, only mac80211 NICs support this feature. + * The values that may be configured are: + * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 + * AMPDU density and AMPDU factor. + * All values are treated as suggestions and may be ignored + * by the driver as required. The actual values may be seen in + * the station debugfs ht_caps file. + * + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * + * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be + * used by the drivers which has MLME in firmware and does not have support + * to report per station tx/rx activity to free up the staion entry from + * the list. This needs to be used when the driver advertises the + * capability to timeout the stations. + * + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * + * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds + * or 0 to disable background scan. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1194,6 +1462,59 @@ enum nl80211_attrs { NL80211_ATTR_INTERFACE_COMBINATIONS, NL80211_ATTR_SOFTWARE_IFTYPES, + NL80211_ATTR_REKEY_DATA, + + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + + NL80211_ATTR_SCAN_SUPP_RATES, + + NL80211_ATTR_HIDDEN_SSID, + + NL80211_ATTR_IE_PROBE_RESP, + NL80211_ATTR_IE_ASSOC_RESP, + + NL80211_ATTR_STA_WME, + NL80211_ATTR_SUPPORT_AP_UAPSD, + + NL80211_ATTR_ROAM_SUPPORT, + + NL80211_ATTR_SCHED_SCAN_MATCH, + NL80211_ATTR_MAX_MATCH_SETS, + + NL80211_ATTR_PMKSA_CANDIDATE, + + NL80211_ATTR_TX_NO_CCK_RATE, + + NL80211_ATTR_TDLS_ACTION, + NL80211_ATTR_TDLS_DIALOG_TOKEN, + NL80211_ATTR_TDLS_OPERATION, + NL80211_ATTR_TDLS_SUPPORT, + NL80211_ATTR_TDLS_EXTERNAL_SETUP, + + NL80211_ATTR_DEVICE_AP_SME, + + NL80211_ATTR_DONT_WAIT_FOR_ACK, + + NL80211_ATTR_FEATURE_FLAGS, + + NL80211_ATTR_PROBE_RESP_OFFLOAD, + + NL80211_ATTR_PROBE_RESP, + + NL80211_ATTR_DFS_REGION, + + NL80211_ATTR_DISABLE_HT, + NL80211_ATTR_HT_CAPABILITY_MASK, + + NL80211_ATTR_NOACK_MAP, + + NL80211_ATTR_INACTIVITY_TIMEOUT, + + NL80211_ATTR_RX_SIGNAL_DBM, + + NL80211_ATTR_BG_SCAN_PERIOD, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1228,8 +1549,10 @@ enum nl80211_attrs { #define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES #define NL80211_ATTR_KEY NL80211_ATTR_KEY #define NL80211_ATTR_KEYS NL80211_ATTR_KEYS +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS #define NL80211_MAX_SUPP_RATES 32 +#define NL80211_MAX_SUPP_HT_RATES 77 #define NL80211_MAX_SUPP_REG_RULES 32 #define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 @@ -1291,6 +1614,11 @@ enum nl80211_iftype { * @NL80211_STA_FLAG_WME: station is WME/QoS capable * @NL80211_STA_FLAG_MFP: station uses management frame protection * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated + * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should + * only be used in managed mode (even in the flags mask). Note that the + * flag can't be changed, it is only valid while adding a station, and + * attempts to change it will silently be ignored (rather than rejected + * as errors.) * @NL80211_STA_FLAG_MAX: highest station flag number currently defined * @__NL80211_STA_FLAG_AFTER_LAST: internal use */ @@ -1301,6 +1629,7 @@ enum nl80211_sta_flags { NL80211_STA_FLAG_WME, NL80211_STA_FLAG_MFP, NL80211_STA_FLAG_AUTHENTICATED, + NL80211_STA_FLAG_TDLS_PEER, /* keep last */ __NL80211_STA_FLAG_AFTER_LAST, @@ -1403,6 +1732,8 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute * containing info as possible, see &enum nl80211_sta_bss_param * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected + * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. + * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -1424,6 +1755,8 @@ enum nl80211_sta_info { NL80211_STA_INFO_RX_BITRATE, NL80211_STA_INFO_BSS_PARAM, NL80211_STA_INFO_CONNECTED_TIME, + NL80211_STA_INFO_STA_FLAGS, + NL80211_STA_INFO_BEACON_LOSS, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -1652,6 +1985,26 @@ enum nl80211_reg_rule_attr { NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 }; +/** + * enum nl80211_sched_scan_match_attr - scheduled scan match attributes + * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, + * only report BSS with matching SSID. + * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter + * attribute number currently defined + * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use + */ +enum nl80211_sched_scan_match_attr { + __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID, + + NL80211_ATTR_SCHED_SCAN_MATCH_SSID, + + /* keep last */ + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, + NL80211_SCHED_SCAN_MATCH_ATTR_MAX = + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1 +}; + /** * enum nl80211_reg_rule_flags - regulatory rule flags * @@ -1677,6 +2030,21 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_IBSS = 1<<8, }; +/** + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC_: Country follows DFS master rules from FCC + * @NL80211_DFS_FCC_: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP_: Country follows DFS master rules from JP/MKK/Telec + */ +enum nl80211_dfs_regions { + NL80211_DFS_UNSET = 0, + NL80211_DFS_FCC = 1, + NL80211_DFS_ETSI = 2, + NL80211_DFS_JP = 3, +}; + /** * enum nl80211_survey_info - survey information * @@ -1803,6 +2171,24 @@ enum nl80211_mntr_flags { * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a * source mesh point for path selection elements. * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between + * root announcements are transmitted. + * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS. This is done via Root + * Announcement frames. + * + * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which a mesh STA can send only one Action frame containing a + * PERR element. + * + * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding + * or forwarding entity (default is TRUE - forwarding entity) + * + * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the + * threshold for average signal strength of candidate station to establish + * a peer link. + * * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use @@ -1824,6 +2210,11 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, NL80211_MESHCONF_HWMP_ROOTMODE, NL80211_MESHCONF_ELEMENT_TTL, + NL80211_MESHCONF_HWMP_RANN_INTERVAL, + NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, + NL80211_MESHCONF_FORWARDING, + NL80211_MESHCONF_RSSI_THRESHOLD, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -2033,9 +2424,6 @@ enum nl80211_mfp { enum nl80211_wpa_versions { NL80211_WPA_VERSION_1 = 1 << 0, NL80211_WPA_VERSION_2 = 1 << 1, -/* HTC_CSP_START */ - NL80211_WAPI_VERSION_1 = 1 << 2, -/* HTC_CSP_END */ }; /** @@ -2100,12 +2488,15 @@ enum nl80211_key_attributes { * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with * 1 = 500 kbps) but without the IE length restriction (at most * %NL80211_MAX_SUPP_RATES in a single array). + * @NL80211_TXRATE_MCS: HT (MCS) rates allowed for TX rate selection + * in an array of MCS numbers. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ enum nl80211_tx_rate_attributes { __NL80211_TXRATE_INVALID, NL80211_TXRATE_LEGACY, + NL80211_TXRATE_MCS, /* keep last */ __NL80211_TXRATE_AFTER_LAST, @@ -2242,6 +2633,16 @@ struct nl80211_wowlan_pattern_support { * * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute * carrying a &struct nl80211_wowlan_pattern_support. + * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be + * used when setting, used only to indicate that GTK rekeying is supported + * by the device (flag) + * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if + * done by the device) (flag) + * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request + * packet (flag) + * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) + * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released + * (on devices that have rfkill in the device) (flag) * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number */ @@ -2251,6 +2652,11 @@ enum nl80211_wowlan_triggers { NL80211_WOWLAN_TRIG_DISCONNECT, NL80211_WOWLAN_TRIG_MAGIC_PKT, NL80211_WOWLAN_TRIG_PKT_PATTERN, + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED, + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE, + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, + NL80211_WOWLAN_TRIG_RFKILL_RELEASE, /* keep last */ NUM_NL80211_WOWLAN_TRIG, @@ -2364,4 +2770,146 @@ enum nl80211_plink_state { MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 }; +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 + +/** + * enum nl80211_rekey_data - attributes for GTK rekey offload + * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes + * @NL80211_REKEY_DATA_KEK: key encryption key (binary) + * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) + * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) + * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) + */ +enum nl80211_rekey_data { + __NL80211_REKEY_DATA_INVALID, + NL80211_REKEY_DATA_KEK, + NL80211_REKEY_DATA_KCK, + NL80211_REKEY_DATA_REPLAY_CTR, + + /* keep last */ + NUM_NL80211_REKEY_DATA, + MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1 +}; + +/** + * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID + * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in + * Beacon frames) + * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element + * in Beacon frames + * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID + * element in Beacon frames but zero out each byte in the SSID + */ +enum nl80211_hidden_ssid { + NL80211_HIDDEN_SSID_NOT_IN_USE, + NL80211_HIDDEN_SSID_ZERO_LEN, + NL80211_HIDDEN_SSID_ZERO_CONTENTS +}; + +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format + * is the same as the AC bitmap in the QoS info field. + * @NL80211_STA_WME_MAX_SP: max service period. the format is the same + * as the MAX_SP field in the QoS info field (but already shifted down). + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +enum nl80211_sta_wme_attr { + __NL80211_STA_WME_INVALID, + NL80211_STA_WME_UAPSD_QUEUES, + NL80211_STA_WME_MAX_SP, + + /* keep last */ + __NL80211_STA_WME_AFTER_LAST, + NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +}; + +/** + * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates + * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes + * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher + * priority) + * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets) + * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag) + * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes + * (internal) + * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute + * (internal) + */ +enum nl80211_pmksa_candidate_attr { + __NL80211_PMKSA_CANDIDATE_INVALID, + NL80211_PMKSA_CANDIDATE_INDEX, + NL80211_PMKSA_CANDIDATE_BSSID, + NL80211_PMKSA_CANDIDATE_PREAUTH, + + /* keep last */ + NUM_NL80211_PMKSA_CANDIDATE, + MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 +}; + +/** + * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION + * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request + * @NL80211_TDLS_SETUP: Setup TDLS link + * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established + * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link + * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link + */ +enum nl80211_tdls_operation { + NL80211_TDLS_DISCOVERY_REQ, + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, +}; + +/* + * enum nl80211_ap_sme_features - device-integrated AP features + * Reserved for future use, no bits are defined in + * NL80211_ATTR_DEVICE_AP_SME yet. +enum nl80211_ap_sme_features { +}; + */ + +/** + * enum nl80211_feature_flags - device/driver features + * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back + * TX status to the socket error queue when requested with the + * socket option. + * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. + */ +enum nl80211_feature_flags { + NL80211_FEATURE_SK_TX_STATUS = 1 << 0, + NL80211_FEATURE_HT_IBSS = 1 << 1, + NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, +}; + +/** + * enum nl80211_probe_resp_offload_support_attr - optional supported + * protocols for probe-response offloading by the driver/FW. + * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. + * Each enum value represents a bit in the bitmap of supported + * protocols. Typically a subset of probe-requests belonging to a + * supported protocol will be excluded from offload and uploaded + * to the host. + * + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u + */ +enum nl80211_probe_resp_offload_support_attr { + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, +}; + #endif /* __LINUX_NL80211_H */ diff --git a/include/net/cfg80211-wext.h b/include/net/cfg80211-wext.h new file mode 100644 index 00000000..25baddc4 --- /dev/null +++ b/include/net/cfg80211-wext.h @@ -0,0 +1,55 @@ +#ifndef __NET_CFG80211_WEXT_H +#define __NET_CFG80211_WEXT_H +/* + * 802.11 device and configuration interface -- wext handlers + * + * Copyright 2006-2010 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include + +/* + * Temporary wext handlers & helper functions + * + * These are used only by drivers that aren't yet fully + * converted to cfg80211. + */ +int cfg80211_wext_giwname(struct net_device *dev, + struct iw_request_info *info, + char *name, char *extra); +int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info, + u32 *mode, char *extra); +int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info, + u32 *mode, char *extra); +int cfg80211_wext_siwscan(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra); +int cfg80211_wext_giwscan(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra); +int cfg80211_wext_giwrange(struct net_device *dev, + struct iw_request_info *info, + struct iw_point *data, char *extra); +int cfg80211_wext_siwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_giwrts(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *rts, char *extra); +int cfg80211_wext_siwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_giwfrag(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *frag, char *extra); +int cfg80211_wext_giwretry(struct net_device *dev, + struct iw_request_info *info, + struct iw_param *retry, char *extra); + +#endif /* __NET_CFG80211_WEXT_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 396e8fc8..721b1fcd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -338,6 +338,36 @@ struct survey_info { s8 noise; }; +/** + * struct cfg80211_crypto_settings - Crypto settings + * @wpa_versions: indicates which, if any, WPA versions are enabled + * (from enum nl80211_wpa_versions) + * @cipher_group: group key cipher suite (or 0 if unset) + * @n_ciphers_pairwise: number of AP supported unicast ciphers + * @ciphers_pairwise: unicast key cipher suites + * @n_akm_suites: number of AKM suites + * @akm_suites: AKM suites + * @control_port: Whether user space controls IEEE 802.1X port, i.e., + * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is + * required to assume that the port is unauthorized until authorized by + * user space. Otherwise, port is marked authorized by default. + * @control_port_ethertype: the control port protocol that should be + * allowed through even on unauthorized ports + * @control_port_no_encrypt: TRUE to prevent encryption of control port + * protocol frames. + */ +struct cfg80211_crypto_settings { + u32 wpa_versions; + u32 cipher_group; + int n_ciphers_pairwise; + u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES]; + int n_akm_suites; + u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; + bool control_port; + __be16 control_port_ethertype; + bool control_port_no_encrypt; +}; + /** * struct beacon_parameters - beacon parameters * @@ -351,11 +381,38 @@ struct survey_info { * @dtim_period: DTIM period or zero if not changed * @head_len: length of @head * @tail_len: length of @tail + * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from + * user space) + * @ssid_len: length of @ssid + * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames + * @crypto: crypto settings + * @privacy: the BSS uses privacy + * @auth_type: Authentication type (algorithm) + * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL + * @beacon_ies_len: length of beacon_ies in octets + * @proberesp_ies: extra information element(s) to add into Probe Response + * frames or %NULL + * @proberesp_ies_len: length of proberesp_ies in octets + * @assocresp_ies: extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @assocresp_ies_len: length of assocresp_ies in octets */ struct beacon_parameters { u8 *head, *tail; int interval, dtim_period; int head_len, tail_len; + const u8 *ssid; + size_t ssid_len; + enum nl80211_hidden_ssid hidden_ssid; + struct cfg80211_crypto_settings crypto; + bool privacy; + enum nl80211_auth_type auth_type; + const u8 *beacon_ies; + size_t beacon_ies_len; + const u8 *proberesp_ies; + size_t proberesp_ies_len; + const u8 *assocresp_ies; + size_t assocresp_ies_len; }; /** @@ -426,6 +483,7 @@ struct station_parameters { * @STATION_INFO_RX_BITRATE: @rxrate fields are filled * @STATION_INFO_BSS_PARAM: @bss_param filled * @STATION_INFO_CONNECTED_TIME: @connected_time filled + * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -444,7 +502,8 @@ enum station_info_flags { STATION_INFO_SIGNAL_AVG = 1<<13, STATION_INFO_RX_BITRATE = 1<<14, STATION_INFO_BSS_PARAM = 1<<15, - STATION_INFO_CONNECTED_TIME = 1<<16 + STATION_INFO_CONNECTED_TIME = 1<<16, + STATION_INFO_ASSOC_REQ_IES = 1<<17 }; /** @@ -536,6 +595,11 @@ struct sta_bss_parameters { * This number should increase every time the list of stations * changes, i.e. when a station is added or removed, so that * userspace can tell whether it got a consistent snapshot. + * @assoc_req_ies: IEs from (Re)Association Request. + * This is used only when in AP mode with drivers that do not use + * user space MLME/SME implementation. The information is provided for + * the cfg80211_new_sta() calls to notify user space of the IEs. + * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. */ struct station_info { u32 filled; @@ -558,6 +622,14 @@ struct station_info { struct sta_bss_parameters bss_param; int generation; + + const u8 *assoc_req_ies; + size_t assoc_req_ies_len; + + /* + * Note: Add a new enum station_info_flags value for each new field and + * use it to check which fields are initialized. + */ }; /** @@ -777,9 +849,11 @@ struct cfg80211_ssid { * @n_channels: total number of channels to scan * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets + * @rates: bitmap of rates to advertise for each band * @wiphy: the wiphy this was for * @dev: the interface * @aborted: (internal) scan request was notified as aborted + * @no_cck: used to send probe requests at non CCK rate in 2GHz band */ struct cfg80211_scan_request { struct cfg80211_ssid *ssids; @@ -788,15 +862,27 @@ struct cfg80211_scan_request { const u8 *ie; size_t ie_len; + u32 rates[IEEE80211_NUM_BANDS]; + /* internal */ struct wiphy *wiphy; struct net_device *dev; bool aborted; + bool no_cck; /* keep last */ struct ieee80211_channel *channels[0]; }; +/** + * struct cfg80211_match_set - sets of attributes to match + * + * @ssid: SSID to be matched + */ +struct cfg80211_match_set { + struct cfg80211_ssid ssid; +}; + /** * struct cfg80211_sched_scan_request - scheduled scan request description * @@ -806,6 +892,11 @@ struct cfg80211_scan_request { * @interval: interval between each scheduled scan cycle * @ie: optional information element(s) to add into Probe Request or %NULL * @ie_len: length of ie in octets + * @match_sets: sets of parameters to be matched for a scan result + * entry to be considered valid and to be passed to the host + * (others are filtered out). + * If ommited, all results are passed. + * @n_match_sets: number of match sets * @wiphy: the wiphy this was for * @dev: the interface * @channels: channels to scan @@ -817,6 +908,8 @@ struct cfg80211_sched_scan_request { u32 interval; const u8 *ie; size_t ie_len; + struct cfg80211_match_set *match_sets; + int n_match_sets; /* internal */ struct wiphy *wiphy; @@ -892,36 +985,6 @@ struct cfg80211_bss { const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); -/** - * struct cfg80211_crypto_settings - Crypto settings - * @wpa_versions: indicates which, if any, WPA versions are enabled - * (from enum nl80211_wpa_versions) - * @cipher_group: group key cipher suite (or 0 if unset) - * @n_ciphers_pairwise: number of AP supported unicast ciphers - * @ciphers_pairwise: unicast key cipher suites - * @n_akm_suites: number of AKM suites - * @akm_suites: AKM suites - * @control_port: Whether user space controls IEEE 802.1X port, i.e., - * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is - * required to assume that the port is unauthorized until authorized by - * user space. Otherwise, port is marked authorized by default. - * @control_port_ethertype: the control port protocol that should be - * allowed through even on unauthorized ports - * @control_port_no_encrypt: TRUE to prevent encryption of control port - * protocol frames. - */ -struct cfg80211_crypto_settings { - u32 wpa_versions; - u32 cipher_group; - int n_ciphers_pairwise; - u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES]; - int n_akm_suites; - u32 akm_suites[NL80211_MAX_NR_AKM_SUITES]; - bool control_port; - __be16 control_port_ethertype; - bool control_port_no_encrypt; -}; - /** * struct cfg80211_auth_request - Authentication request data * @@ -1716,9 +1779,16 @@ struct wiphy_wowlan_support { * this variable determines its size * @max_scan_ssids: maximum number of SSIDs the device can scan for in * any given scan + * @max_sched_scan_ssids: maximum number of SSIDs the device can scan + * for in any given scheduled scan + * @max_match_sets: maximum number of match sets the device can handle + * when performing a scheduled scan, 0 if filtering is not + * supported. * @max_scan_ie_len: maximum length of user-controlled IEs device can * add to probe request frames transmitted during a scan, must not * include fixed IEs like supported rates + * @max_sched_scan_ie_len: same as max_scan_ie_len, but for scheduled + * scans * @coverage_class: current coverage class * @fw_version: firmware version for ethtool reporting * @hw_version: hardware version for ethtool reporting @@ -1770,7 +1840,10 @@ struct wiphy { int bss_priv_size; u8 max_scan_ssids; + u8 max_sched_scan_ssids; + u8 max_match_sets; u16 max_scan_ie_len; + u16 max_sched_scan_ie_len; int n_cipher_suites; const u32 *cipher_suites; diff --git a/include/net/regulatory.h b/include/net/regulatory.h index 356d6e3d..a5f79933 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -3,11 +3,19 @@ /* * regulatory support structures * - * Copyright 2008-2009 Luis R. Rodriguez + * Copyright 2008-2009 Luis R. Rodriguez * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ @@ -40,6 +48,10 @@ enum environment_cap { * 99 - built by driver but a specific alpha2 cannot be determined * 98 - result of an intersection between two regulatory domains * 97 - regulatory domain has not yet been configured + * @dfs_region: If CRDA responded with a regulatory domain that requires + * DFS master operation on a known DFS region (NL80211_DFS_*), + * dfs_region represents that region. Drivers can use this and the + * @alpha2 to adjust their device's DFS parameters as required. * @intersect: indicates whether the wireless core should intersect * the requested regulatory domain with the presently set regulatory * domain. @@ -59,6 +71,7 @@ struct regulatory_request { int wiphy_idx; enum nl80211_reg_initiator initiator; char alpha2[2]; + u8 dfs_region; bool intersect; bool processed; enum environment_cap country_ie_env; @@ -85,6 +98,7 @@ struct ieee80211_reg_rule { struct ieee80211_regdomain { u32 n_reg_rules; char alpha2[2]; + u8 dfs_region; struct ieee80211_reg_rule reg_rules[]; }; diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 1f1ef70f..8e2a668c 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -159,3 +159,14 @@ config LIB80211_DEBUG from lib80211. If unsure, say N. + +config CFG80211_ALLOW_RECONNECT + bool "Allow reconnect while already connected" + depends on CFG80211 + default n + help + cfg80211 stack doesn't allow to connect if you are already + connected. This option allows to make a connection in this case. + + Select this option ONLY for wlan drivers that are specifically + built for such purposes. diff --git a/net/wireless/core.h b/net/wireless/core.h index 83516455..4ff1c639 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -408,6 +408,7 @@ void cfg80211_sme_failed_assoc(struct wireless_dev *wdev); bool cfg80211_sme_failed_reassoc(struct wireless_dev *wdev); /* internal helpers */ +bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr); @@ -447,6 +448,9 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, enum nl80211_channel_type channel_type); u16 cfg80211_calculate_bitrate(struct rate_info *rate); +int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, + const u8 *rates, unsigned int n_rates, + u32 *mask); int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, u32 beacon_int); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index f310a0d9..1d946461 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -23,6 +23,12 @@ #include "nl80211.h" #include "reg.h" +static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type); +static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, + struct genl_info *info, + struct cfg80211_crypto_settings *settings, + int cipher_limit); + static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info); static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, @@ -92,7 +98,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_KEY_IDX] = { .type = NLA_U8 }, [NL80211_ATTR_KEY_CIPHER] = { .type = NLA_U32 }, [NL80211_ATTR_KEY_DEFAULT] = { .type = NLA_FLAG }, - [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, + [NL80211_ATTR_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, [NL80211_ATTR_KEY_TYPE] = { .type = NLA_U32 }, [NL80211_ATTR_BEACON_INTERVAL] = { .type = NLA_U32 }, @@ -175,6 +181,16 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, + [NL80211_ATTR_REKEY_DATA] = { .type = NLA_NESTED }, + [NL80211_ATTR_SCAN_SUPP_RATES] = { .type = NLA_NESTED }, + [NL80211_ATTR_HIDDEN_SSID] = { .type = NLA_U32 }, + [NL80211_ATTR_IE_PROBE_RESP] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_IE_ASSOC_RESP] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_TX_NO_CCK_RATE] = { .type = NLA_FLAG }, + [NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG }, + [NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED }, }; /* policy for the key attributes */ @@ -182,7 +198,7 @@ static const struct nla_policy nl80211_key_policy[NL80211_KEY_MAX + 1] = { [NL80211_KEY_DATA] = { .type = NLA_BINARY, .len = WLAN_MAX_KEY_LEN }, [NL80211_KEY_IDX] = { .type = NLA_U8 }, [NL80211_KEY_CIPHER] = { .type = NLA_U32 }, - [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 8 }, + [NL80211_KEY_SEQ] = { .type = NLA_BINARY, .len = 16 }, [NL80211_KEY_DEFAULT] = { .type = NLA_FLAG }, [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, [NL80211_KEY_TYPE] = { .type = NLA_U32 }, @@ -205,6 +221,12 @@ nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, }; +static const struct nla_policy +nl80211_match_policy[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1] = { + [NL80211_ATTR_SCHED_SCAN_MATCH_SSID] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_SSID_LEN }, +}; + /* ifidx get helper */ static int nl80211_get_ifidx(struct netlink_callback *cb) { @@ -682,8 +704,14 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.coverage_class); NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS, dev->wiphy.max_scan_ssids); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + dev->wiphy.max_sched_scan_ssids); NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCAN_IE_LEN, dev->wiphy.max_scan_ie_len); + NLA_PUT_U16(msg, NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + dev->wiphy.max_sched_scan_ie_len); + NLA_PUT_U8(msg, NL80211_ATTR_MAX_MATCH_SETS, + dev->wiphy.max_match_sets); if (dev->wiphy.flags & WIPHY_FLAG_IBSS_RSN) NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_IBSS_RSN); @@ -1961,7 +1989,10 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) struct beacon_parameters params; int haveinfo = 0, err; - if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) + if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL]) || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]) || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_PROBE_RESP]) || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE_ASSOC_RESP])) return -EINVAL; if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && @@ -1987,6 +2018,49 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (err) return err; + /* + * In theory, some of these attributes could be required for + * NEW_BEACON, but since they were not used when the command was + * originally added, keep them optional for old user space + * programs to work with drivers that do not need the additional + * information. + */ + if (info->attrs[NL80211_ATTR_SSID]) { + params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); + params.ssid_len = + nla_len(info->attrs[NL80211_ATTR_SSID]); + if (params.ssid_len == 0 || + params.ssid_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; + } + + if (info->attrs[NL80211_ATTR_HIDDEN_SSID]) { + params.hidden_ssid = nla_get_u32( + info->attrs[NL80211_ATTR_HIDDEN_SSID]); + if (params.hidden_ssid != + NL80211_HIDDEN_SSID_NOT_IN_USE && + params.hidden_ssid != + NL80211_HIDDEN_SSID_ZERO_LEN && + params.hidden_ssid != + NL80211_HIDDEN_SSID_ZERO_CONTENTS) + return -EINVAL; + } + + params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; + + if (info->attrs[NL80211_ATTR_AUTH_TYPE]) { + params.auth_type = nla_get_u32( + info->attrs[NL80211_ATTR_AUTH_TYPE]); + if (!nl80211_valid_auth_type(params.auth_type)) + return -EINVAL; + } else + params.auth_type = NL80211_AUTHTYPE_AUTOMATIC; + + err = nl80211_crypto_settings(rdev, info, ¶ms.crypto, + NL80211_MAX_NR_CIPHER_SUITES); + if (err) + return err; + call = rdev->ops->add_beacon; break; case NL80211_CMD_SET_BEACON: @@ -2017,6 +2091,25 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) if (!haveinfo) return -EINVAL; + if (info->attrs[NL80211_ATTR_IE]) { + params.beacon_ies = nla_data(info->attrs[NL80211_ATTR_IE]); + params.beacon_ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); + } + + if (info->attrs[NL80211_ATTR_IE_PROBE_RESP]) { + params.proberesp_ies = + nla_data(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); + params.proberesp_ies_len = + nla_len(info->attrs[NL80211_ATTR_IE_PROBE_RESP]); + } + + if (info->attrs[NL80211_ATTR_IE_ASSOC_RESP]) { + params.assocresp_ies = + nla_data(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); + params.assocresp_ies_len = + nla_len(info->attrs[NL80211_ATTR_IE_ASSOC_RESP]); + } + err = call(&rdev->wiphy, dev, ¶ms); if (!err && params.interval) wdev->beacon_interval = params.interval; @@ -2213,6 +2306,10 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, } nla_nest_end(msg, sinfoattr); + if (sinfo->filled & STATION_INFO_ASSOC_REQ_IES) + NLA_PUT(msg, NL80211_ATTR_IE, sinfo->assoc_req_ies_len, + sinfo->assoc_req_ies); + return genlmsg_end(msg, hdr); nla_put_failure: @@ -2240,6 +2337,7 @@ static int nl80211_dump_station(struct sk_buff *skb, } while (1) { + memset(&sinfo, 0, sizeof(sinfo)); err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, mac_addr, &sinfo); if (err == -ENOENT) @@ -3301,7 +3399,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) struct nlattr *attr; struct wiphy *wiphy; int err, tmp, n_ssids = 0, n_channels, i; - enum ieee80211_band band; size_t ie_len; if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) @@ -3321,6 +3418,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) if (!n_channels) return -EINVAL; } else { + enum ieee80211_band band; n_channels = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) @@ -3381,6 +3479,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) i++; } } else { + enum ieee80211_band band; + /* all channels */ for (band = 0; band < IEEE80211_NUM_BANDS; band++) { int j; @@ -3426,9 +3526,32 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) nla_data(info->attrs[NL80211_ATTR_IE]), request->ie_len); } + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + if (wiphy->bands[i]) + request->rates[i] = + (1 << wiphy->bands[i]->n_bitrates) - 1; + if (info->attrs[NL80211_ATTR_SCAN_SUPP_RATES]) { + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_SCAN_SUPP_RATES], + tmp) { + enum ieee80211_band band = nla_type(attr); + if (band < 0 || band >= IEEE80211_NUM_BANDS) { + err = -EINVAL; + goto out_free; + } + err = ieee80211_get_ratemask(wiphy->bands[band], + nla_data(attr), + nla_len(attr), + &request->rates[band]); + if (err) + goto out_free; + } + } request->dev = dev; request->wiphy = &rdev->wiphy; + request->no_cck = + nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]); rdev->scan_req = request; err = rdev->ops->scan(&rdev->wiphy, dev, request); @@ -3453,10 +3576,11 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, struct net_device *dev = info->user_ptr[1]; struct nlattr *attr; struct wiphy *wiphy; - int err, tmp, n_ssids = 0, n_channels, i; + int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i; u32 interval; enum ieee80211_band band; size_t ie_len; + struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || !rdev->ops->sched_scan_start) @@ -3492,7 +3616,16 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, tmp) n_ssids++; - if (n_ssids > wiphy->max_scan_ssids) + if (n_ssids > wiphy->max_sched_scan_ssids) + return -EINVAL; + + if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], + tmp) + n_match_sets++; + + if (n_match_sets > wiphy->max_match_sets) return -EINVAL; if (info->attrs[NL80211_ATTR_IE]) @@ -3500,7 +3633,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, else ie_len = 0; - if (ie_len > wiphy->max_scan_ie_len) + if (ie_len > wiphy->max_sched_scan_ie_len) return -EINVAL; mutex_lock(&rdev->sched_scan_mtx); @@ -3512,6 +3645,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, request = kzalloc(sizeof(*request) + sizeof(*request->ssids) * n_ssids + + sizeof(*request->match_sets) * n_match_sets + sizeof(*request->channels) * n_channels + ie_len, GFP_KERNEL); if (!request) { @@ -3529,6 +3663,18 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, request->ie = (void *)(request->channels + n_channels); } + if (n_match_sets) { + if (request->ie) + request->match_sets = (void *)(request->ie + ie_len); + else if (request->ssids) + request->match_sets = + (void *)(request->ssids + n_ssids); + else + request->match_sets = + (void *)(request->channels + n_channels); + } + request->n_match_sets = n_match_sets; + i = 0; if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { /* user specified, bail out if channel not found */ @@ -3593,6 +3739,31 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, } } + i = 0; + if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { + nla_for_each_nested(attr, + info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], + tmp) { + struct nlattr *ssid; + + nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, + nla_data(attr), nla_len(attr), + nl80211_match_policy); + ssid = tb[NL80211_ATTR_SCHED_SCAN_MATCH_SSID]; + if (ssid) { + if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { + err = -EINVAL; + goto out_free; + } + memcpy(request->match_sets[i].ssid.ssid, + nla_data(ssid), nla_len(ssid)); + request->match_sets[i].ssid.ssid_len = + nla_len(ssid); + } + i++; + } + } + if (info->attrs[NL80211_ATTR_IE]) { request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); memcpy((void *)request->ie, @@ -3870,22 +4041,6 @@ static bool nl80211_valid_wpa_versions(u32 wpa_versions) NL80211_WPA_VERSION_2)); } -static bool nl80211_valid_akm_suite(u32 akm) -{ - return akm == WLAN_AKM_SUITE_8021X || - akm == WLAN_AKM_SUITE_PSK; -} - -static bool nl80211_valid_cipher_suite(u32 cipher) -{ - return cipher == WLAN_CIPHER_SUITE_WEP40 || - cipher == WLAN_CIPHER_SUITE_WEP104 || - cipher == WLAN_CIPHER_SUITE_TKIP || - cipher == WLAN_CIPHER_SUITE_CCMP || - cipher == WLAN_CIPHER_SUITE_AES_CMAC; -} - - static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -4018,15 +4173,17 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, memcpy(settings->ciphers_pairwise, data, len); for (i = 0; i < settings->n_ciphers_pairwise; i++) - if (!nl80211_valid_cipher_suite( - settings->ciphers_pairwise[i])) + if (!cfg80211_supported_cipher_suite( + &rdev->wiphy, + settings->ciphers_pairwise[i])) return -EINVAL; } if (info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]) { settings->cipher_group = nla_get_u32(info->attrs[NL80211_ATTR_CIPHER_SUITE_GROUP]); - if (!nl80211_valid_cipher_suite(settings->cipher_group)) + if (!cfg80211_supported_cipher_suite(&rdev->wiphy, + settings->cipher_group)) return -EINVAL; } @@ -4039,7 +4196,7 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, if (info->attrs[NL80211_ATTR_AKM_SUITES]) { void *data; - int len, i; + int len; data = nla_data(info->attrs[NL80211_ATTR_AKM_SUITES]); len = nla_len(info->attrs[NL80211_ATTR_AKM_SUITES]); @@ -4052,10 +4209,6 @@ static int nl80211_crypto_settings(struct cfg80211_registered_device *rdev, return -EINVAL; memcpy(settings->akm_suites, data, len); - - for (i = 0; i < settings->n_akm_suites; i++) - if (!nl80211_valid_akm_suite(settings->akm_suites[i])) - return -EINVAL; } return 0; @@ -4301,25 +4454,11 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); struct ieee80211_supported_band *sband = wiphy->bands[ibss.channel->band]; - int i, j; - - if (n_rates == 0) - return -EINVAL; - - for (i = 0; i < n_rates; i++) { - int rate = (rates[i] & 0x7f) * 5; - bool found = false; - - for (j = 0; j < sband->n_bitrates; j++) { - if (sband->bitrates[j].bitrate == rate) { - found = true; - ibss.basic_rates |= BIT(j); - break; - } - } - if (!found) - return -EINVAL; - } + int err; + err = ieee80211_get_ratemask(sband, rates, n_rates, + &ibss.basic_rates); + if (err) + return err; } if (info->attrs[NL80211_ATTR_MCAST_RATE] && diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 90b73d1f..092775af 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1781,6 +1781,7 @@ static void restore_alpha2(char *alpha2, bool reset_user) static void restore_regulatory_settings(bool reset_user) { char alpha2[2]; + char world_alpha2[2]; struct reg_beacon *reg_beacon, *btmp; struct regulatory_request *reg_request, *tmp; LIST_HEAD(tmp_reg_req_list); @@ -1831,11 +1832,13 @@ static void restore_regulatory_settings(bool reset_user) /* First restore to the basic regulatory settings */ cfg80211_regdomain = cfg80211_world_regdom; + world_alpha2[0] = cfg80211_regdomain->alpha2[0]; + world_alpha2[1] = cfg80211_regdomain->alpha2[1]; mutex_unlock(®_mutex); mutex_unlock(&cfg80211_mutex); - regulatory_hint_core(cfg80211_regdomain->alpha2); + regulatory_hint_core(world_alpha2); /* * This restores the ieee80211_regdom module parameter diff --git a/net/wireless/scan.c b/net/wireless/scan.c index ae0c2256..0aa09bdf 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -17,7 +17,7 @@ #include "nl80211.h" #include "wext-compat.h" -#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ) +#define IEEE80211_SCAN_RESULT_EXPIRE (3 * HZ) void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak) { @@ -862,6 +862,8 @@ int cfg80211_wext_siwscan(struct net_device *dev, if (wreq->scan_type == IW_SCAN_TYPE_PASSIVE) creq->n_ssids = 0; } + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + creq->rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1; rdev->scan_req = creq; err = rdev->ops->scan(wiphy, dev, creq); diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 38bda6ce..cf4be212 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -658,12 +658,12 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie, if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION && wdev->iftype != NL80211_IFTYPE_P2P_CLIENT)) return; -/*HTC_WIFI_START*/ -/*we need send hang to supplicant + +#ifndef CONFIG_CFG80211_ALLOW_RECONNECT if (wdev->sme_state != CFG80211_SME_CONNECTED) return; -*/ -/*HTC_WIFI_END*/ +#endif + if (wdev->current_bss) { cfg80211_unhold_bss(wdev->current_bss); cfg80211_put_bss(&wdev->current_bss->pub); @@ -759,6 +759,7 @@ int __cfg80211_connect(struct cfg80211_registered_device *rdev, int err; ASSERT_WDEV_LOCK(wdev); + #ifndef CONFIG_CFG80211_ALLOW_RECONNECT if (wdev->sme_state != CFG80211_SME_IDLE) return -EALREADY; diff --git a/net/wireless/util.c b/net/wireless/util.c index 18e22bef..e5cbbcc3 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -150,12 +150,19 @@ void ieee80211_set_bitrate_flags(struct wiphy *wiphy) set_mandatory_flags_band(wiphy->bands[band], band); } +bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher) +{ + int i; + for (i = 0; i < wiphy->n_cipher_suites; i++) + if (cipher == wiphy->cipher_suites[i]) + return true; + return false; +} + int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, struct key_params *params, int key_idx, bool pairwise, const u8 *mac_addr) { - int i; - if (key_idx > 5) return -EINVAL; @@ -225,10 +232,7 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, } } - for (i = 0; i < rdev->wiphy.n_cipher_suites; i++) - if (params->cipher == rdev->wiphy.cipher_suites[i]) - break; - if (i == rdev->wiphy.n_cipher_suites) + if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher)) return -EINVAL; return 0; @@ -996,7 +1000,6 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { - all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) @@ -1026,3 +1029,32 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, return -EBUSY; } + +int ieee80211_get_ratemask(struct ieee80211_supported_band *sband, + const u8 *rates, unsigned int n_rates, + u32 *mask) +{ + int i, j; + if (n_rates == 0 || n_rates > NL80211_MAX_SUPP_RATES) + return -EINVAL; + *mask = 0; + for (i = 0; i < n_rates; i++) { + int rate = (rates[i] & 0x7f) * 5; + bool found = false; + for (j = 0; j < sband->n_bitrates; j++) { + if (sband->bitrates[j].bitrate == rate) { + found = true; + *mask |= BIT(j); + break; + } + } + if (!found) + return -EINVAL; + } + /* + * mask must have at least one bit set here since we + * didn't accept a 0-length rates array nor allowed + * entries in the array that didn't exist + */ + return 0; +}