diff options
35 files changed, 1518 insertions, 731 deletions
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 2f801f2..3d06eeb 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -1,33 +1,47 @@ +config BCMDHD + tristate "Broadcom 43xx wireless cards support" + depends on MMC + default m + ---help--- + This module adds support for wireless adapters based on + Broadcom 4329/30 chipset. + + This driver uses the kernel's wireless extensions subsystem. + + If you choose to build a module, it'll be called dhd. Say M if + unsure. + config BCM4330 - tristate "Broadcom 4330 wireless cards support" - depends on WLAN + bool "Broadcom 4330 wireless cards support" + depends on BCMDHD ---help--- This module adds support for wireless adapters based on Broadcom 4330 chipset. config BCM4334 - tristate "Broadcom 4334 wireless cards support" - depends on WLAN + bool "Broadcom 4334 wireless cards support" + depends on BCMDHD + default y ---help--- This module adds support for wireless adapters based on Broadcom 4334 chipset. config BCM43241 - tristate "Broadcom 43241 wireless cards support" - depends on WLAN + bool "Broadcom 43241 wireless cards support" + depends on BCMDHD ---help--- This module adds support for wireless adapters based on Broadcom 43241 chipset. config BCMDHD_FW_PATH - depends on WLAN + depends on BCMDHD string "Firmware path" default "/system/etc/firmware/fw_bcmdhd.bin" ---help--- Path to the firmware file. config BCMDHD_NVRAM_PATH - depends on WLAN + depends on BCMDHD string "NVRAM path" default "/system/etc/wifi/bcmdhd.cal" ---help--- diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index 51115ab..5acd2b0 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -39,6 +39,8 @@ DHDCFLAGS += -DDUAL_ESCAN_RESULT_BUFFER DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API DHDCFLAGS += -DDISABLE_FW_ROAM_SUSPEND +DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 +DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 # For Static Buffer ifeq ($(CONFIG_BROADCOM_WIFI_RESERVED_MEM),y) @@ -84,17 +86,16 @@ ifneq ($(CONFIG_BCM4334),) DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM DHDCFLAGS += -DPROP_TXSTATUS DHDCFLAGS += -DVSDB -DHT40_GO - DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST + DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX + DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=128 DHDCFLAGS += -DDHD_USE_IDLECOUNT DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD DHDCFLAGS += -DVSDB_DYNAMIC_F2_BLKSIZE -DSDIO_F2_BLKSIZE=512 -DVSDB_F2_BLKSIZE=64 DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 -DENABLE_BCN_LI_BCN_WAKEUP -ifeq ($(CONFIG_MACH_M3_JPN_DCM),y) - DHDCFLAGS += -DUSE_WEP_AUTH_SHARED_OPEN -endif +# DHDCFLAGS += -DUSE_WEP_AUTH_SHARED_OPEN DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DWL11U + DHDCFLAGS += -DPASS_ARP_PACKET endif ifneq ($(CONFIG_BCM4330),) @@ -121,7 +122,6 @@ ifneq ($(CONFIG_BCM43241),) endif endif - ############################# # Platform dependent feature ############################# @@ -192,7 +192,7 @@ DHDCFLAGS += -DWLAN_REGION_CODE=$(REGION_CODE) # Others ######### -#EXTRA_LDFLAGS += --strip-debug +EXTRA_LDFLAGS += --strip-debug EXTRA_CFLAGS += $(DHDCFLAGS) -DDHD_DEBUG EXTRA_CFLAGS += -DSRCBASE=\"$(src)\" @@ -212,17 +212,6 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc.o,$(DHDOFILES)) DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif -dhd-y := $(DHDOFILES) -obj-m += dhd.o - -all: - @echo "$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules" - @$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules - -clean: - rm -rf *.o *.ko *.mod.c *~ .*.cmd *.o.cmd .*.o.cmd \ - Module.symvers modules.order .tmp_versions modules.builtin +obj-$(CONFIG_BCMDHD) += dhd.o +dhd-objs += $(DHDOFILES) -install: - @$(MAKE) --no-print-directory -C $(KDIR) \ - SUBDIRS=$(CURDIR) modules_install diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index c743d09..8137701 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -62,12 +62,13 @@ extern int sdio_reset_comm(struct mmc_card *card); extern PBCMSDH_SDMMC_INSTANCE gInstance; -uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ -#if defined(SDIO_F2_BLKSIZE) -uint sd_f2_blocksize = SDIO_F2_BLKSIZE; -#else -uint sd_f2_blocksize = 512; /* Default blocksize */ +#define DEFAULT_SDIO_F2_BLKSIZE 512 +#ifndef CUSTOM_SDIO_F2_BLKSIZE +#define CUSTOM_SDIO_F2_BLKSIZE DEFAULT_SDIO_F2_BLKSIZE #endif + +uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ +uint sd_f2_blocksize = CUSTOM_SDIO_F2_BLKSIZE; uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */ uint sd_power = 1; /* Default to SD Slot powered ON */ @@ -81,6 +82,7 @@ DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); #define DMA_ALIGN_MASK 0x03 +#define MMC_SDIO_ABORT_RETRY_LIMIT 5 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); @@ -792,7 +794,9 @@ extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) { int err_ret; - +#if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; +#endif sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); @@ -826,16 +830,20 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by #if defined(MMC_SDIO_ABORT) /* to allow abort command through F1 */ else if (regaddr == SDIOD_CCCR_IOABORT) { - if (gInstance->func[func]) { - sdio_claim_host(gInstance->func[func]); - /* - * this sdio_f0_writeb() can be replaced with another api - * depending upon MMC driver change. - * As of this time, this is temporaray one - */ - sdio_writeb(gInstance->func[func], - *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); + while (sdio_abort_retry--) { + if (gInstance->func[func]) { + sdio_claim_host(gInstance->func[func]); + /* + * this sdio_f0_writeb() can be replaced with + * another api depending upon MMC driver change. + * As of this time, this is temporaray one + */ + sdio_writeb(gInstance->func[func], + *byte, regaddr, &err_ret); + sdio_release_host(gInstance->func[func]); + } + if (!err_ret) + break; } } #endif /* MMC_SDIO_ABORT */ @@ -884,6 +892,9 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add uint32 *word, uint nbytes) { int err_ret = SDIOH_API_RC_FAIL; +#if defined(MMC_SDIO_ABORT) + int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; +#endif if (func == 0) { sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); @@ -920,8 +931,29 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add sdio_release_host(gInstance->func[func]); if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", +#if defined(MMC_SDIO_ABORT) + /* Any error on CMD53 transaction should abort that function using function 0. */ + while (sdio_abort_retry--) { + if (gInstance->func[0]) { + sdio_claim_host(gInstance->func[0]); + /* + * this sdio_f0_writeb() can be replaced with another api + * depending upon MMC driver change. + * As of this time, this is temporaray one + */ + sdio_writeb(gInstance->func[0], + func, SDIOD_CCCR_IOABORT, &err_ret); + sdio_release_host(gInstance->func[0]); + } + if (!err_ret) + break; + } + if (err_ret) +#endif /* MMC_SDIO_ABORT */ + { + sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n", rw ? "Write" : "Read", err_ret)); + } } return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : 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 36f2a6c..ed37e8c 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 353908 2012-08-29 08:09:02Z $ + * $Id: bcmsdh_sdmmc_linux.c 355594 2012-09-07 10:22:02Z $ */ #include <typedefs.h> @@ -192,7 +192,7 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) if (func->num != 2) return 0; - sd_trace(("%s Enter\n", __FUNCTION__)); + sd_trace_hw4(("%s Enter\n", __FUNCTION__)); if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; @@ -232,7 +232,7 @@ static int bcmsdh_sdmmc_resume(struct device *pdev) struct sdio_func *func = dev_to_sdio_func(pdev); #endif /* defined(OOB_INTR_ONLY) */ #endif /* defined(CUSTOMER_HW4) */ - sd_trace(("%s Enter\n", __FUNCTION__)); + sd_trace_hw4(("%s Enter\n", __FUNCTION__)); dhd_mmc_suspend = FALSE; #if !defined(CUSTOMER_HW4) diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c index e834366..2dbb168 100644..100755 --- a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c @@ -2,13 +2,13 @@ * Broadcom SPI Host Controller Driver - Linux Per-port * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,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/bcmspibrcm.c b/drivers/net/wireless/bcmdhd/bcmspibrcm.c index d5f5754..d5f5754 100644..100755 --- a/drivers/net/wireless/bcmdhd/bcmspibrcm.c +++ b/drivers/net/wireless/bcmdhd/bcmspibrcm.c diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c index 272201b..0646195 100644 --- a/drivers/net/wireless/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/bcmdhd/bcmutils.c @@ -336,13 +336,6 @@ pktq_pdeq_tail(struct pktq *pq, int prec) if ((p = q->head) == NULL) return NULL; -#if defined(CONFIG_MACH_M3_JPN_DCM) - if (!q || !(q->tail)) { - printk(" %s : tail is NULL \n", __func__); - return NULL; - } -#endif - for (prev = NULL; p != q->tail; p = PKTLINK(p)) prev = p; diff --git a/drivers/net/wireless/bcmdhd/bcmwifi.c b/drivers/net/wireless/bcmdhd/bcmwifi.c new file mode 100644 index 0000000..7072217 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/bcmwifi.c @@ -0,0 +1,274 @@ +/* + * Misc utility routines used by kernel or app-level. + * Contents are wifi-specific, used by any kernel or app-level + * software that might want wifi things as it grows. + * + * 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: bcmwifi.c,v 1.31.8.1 2010-08-03 17:47:05 Exp $ + */ + + +#include <typedefs.h> + +#ifdef BCMDRIVER +#include <osl.h> +#include <bcmutils.h> +#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) +#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) +#else +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#ifndef ASSERT +#define ASSERT(exp) +#endif +#endif +#include <bcmwifi.h> + +#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) +#include <bcmstdlib.h> +#endif + + + + + +char * +wf_chspec_ntoa(chanspec_t chspec, char *buf) +{ + const char *band, *bw, *sb; + uint channel; + + band = ""; + bw = ""; + sb = ""; + channel = CHSPEC_CHANNEL(chspec); + + if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || + (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) + band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; + if (CHSPEC_IS40(chspec)) { + if (CHSPEC_SB_UPPER(chspec)) { + sb = "u"; + channel += CH_10MHZ_APART; + } else { + sb = "l"; + channel -= CH_10MHZ_APART; + } + } else if (CHSPEC_IS10(chspec)) { + bw = "n"; + } + + + snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); + return (buf); +} + + +chanspec_t +wf_chspec_aton(char *a) +{ + char *endp = NULL; + uint channel, band, bw, ctl_sb; + char c; + + channel = strtoul(a, &endp, 10); + + + if (endp == a) + return 0; + + if (channel > MAXCHANNEL) + return 0; + + band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); + bw = WL_CHANSPEC_BW_20; + ctl_sb = WL_CHANSPEC_CTL_SB_NONE; + + a = endp; + + c = tolower(a[0]); + if (c == '\0') + goto done; + + + if (c == 'a' || c == 'b') { + band = (c == 'a') ? WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G; + a++; + c = tolower(a[0]); + if (c == '\0') + goto done; + } + + + if (c == 'n') { + bw = WL_CHANSPEC_BW_10; + } else if (c == 'l') { + bw = WL_CHANSPEC_BW_40; + ctl_sb = WL_CHANSPEC_CTL_SB_LOWER; + + if (channel <= (MAXCHANNEL - CH_20MHZ_APART)) + channel += CH_10MHZ_APART; + else + return 0; + } else if (c == 'u') { + bw = WL_CHANSPEC_BW_40; + ctl_sb = WL_CHANSPEC_CTL_SB_UPPER; + + if (channel > CH_20MHZ_APART) + channel -= CH_10MHZ_APART; + else + return 0; + } else { + return 0; + } + +done: + return (channel | band | bw | ctl_sb); +} + + +bool +wf_chspec_malformed(chanspec_t chanspec) +{ + + if (!CHSPEC_IS5G(chanspec) && !CHSPEC_IS2G(chanspec)) + return TRUE; + + if (!CHSPEC_IS40(chanspec) && !CHSPEC_IS20(chanspec)) + return TRUE; + + + if (CHSPEC_IS20_UNCOND(chanspec)) { + if (!CHSPEC_SB_NONE(chanspec)) + return TRUE; + } else { + if (!CHSPEC_SB_UPPER(chanspec) && !CHSPEC_SB_LOWER(chanspec)) + return TRUE; + } + + return FALSE; +} + + +uint8 +wf_chspec_ctlchan(chanspec_t chspec) +{ + uint8 ctl_chan; + + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { + return CHSPEC_CHANNEL(chspec); + } else { + + ASSERT(CHSPEC_BW(chspec) == WL_CHANSPEC_BW_40); + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { + + ctl_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); + } else { + ASSERT(CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_LOWER); + + ctl_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); + } + } + + return ctl_chan; +} + +chanspec_t +wf_chspec_ctlchspec(chanspec_t chspec) +{ + chanspec_t ctl_chspec = 0; + uint8 channel; + + ASSERT(!wf_chspec_malformed(chspec)); + + + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE) { + return chspec; + } else { + if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER) { + channel = UPPER_20_SB(CHSPEC_CHANNEL(chspec)); + } else { + channel = LOWER_20_SB(CHSPEC_CHANNEL(chspec)); + } + ctl_chspec = channel | WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; + ctl_chspec |= CHSPEC_BAND(chspec); + } + return ctl_chspec; +} + + +int +wf_mhz2channel(uint freq, uint start_factor) +{ + int ch = -1; + uint base; + int offset; + + + if (start_factor == 0) { + if (freq >= 2400 && freq <= 2500) + start_factor = WF_CHAN_FACTOR_2_4_G; + else if (freq >= 5000 && freq <= 6000) + start_factor = WF_CHAN_FACTOR_5_G; + } + + if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) + return 14; + + base = start_factor / 2; + + + if ((freq < base) || (freq > base + 1000)) + return -1; + + offset = freq - base; + ch = offset / 5; + + + if (offset != (ch * 5)) + return -1; + + + if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) + return -1; + + return ch; +} + + +int +wf_channel2mhz(uint ch, uint start_factor) +{ + int freq; + + if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || + (ch > 200)) + freq = -1; + else if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) + freq = 2484; + else + freq = ch * 5 + start_factor / 2; + + return freq; +} diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index d9deae8..94cbe91 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 357924 2012-09-20 10:44:32Z $ + * $Id: dhd.h 356711 2012-09-13 15:58:32Z $ */ /**************** @@ -77,17 +77,20 @@ enum dhd_bus_state { DHD_BUS_DATA /* Ready for frame transfers */ }; - +enum dhd_op_flags { /* Firmware requested operation mode */ -#define STA_MASK 0x0001 -#define HOSTAPD_MASK 0x0002 -#define WFD_MASK 0x0004 -#define SOFTAP_FW_MASK 0x0008 -#define CONCURRENT_FW_MASK (STA_MASK | WFD_MASK) -#define P2P_GO_ENABLED 0x0010 -#define P2P_GC_ENABLED 0x0020 -#define CONCURENT_MASK 0x00F0 -#define CONCURRENT_MULTI_CHAN 0x0100 + DHD_FLAG_STA_MODE = BIT(0), /* STA only */ + DHD_FLAG_HOSTAP_MODE = BIT(1), /* SOFTAP only */ + DHD_FLAG_P2P_MODE = BIT(2), /* P2P Only */ + /* STA + P2P */ + DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), + DHD_FLAG_CONCURR_MULTI_CHAN_MODE = BIT(4), /* STA + P2P */ + /* Current P2P mode for P2P connection */ + DHD_FLAG_P2P_GC_MODE = BIT(5), + DHD_FLAG_P2P_GO_MODE = BIT(6), + DHD_FLAG_MBSS_MODE = BIT(7) /* MBSS in future */ +}; + #define MANUFACTRING_FW "WLTEST" /* max sequential rxcntl timeouts to set HANG event */ @@ -95,6 +98,10 @@ enum dhd_bus_state { #define MAX_CNTL_TIMEOUT 2 #endif +#define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ +#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ +#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ + #ifndef POWERUP_MAX_RETRY #define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ #endif @@ -278,7 +285,7 @@ typedef struct dhd_pub { #endif struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; #if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock pno_wakelock; + struct wake_lock pno_wakelock; #endif } dhd_pub_t; @@ -533,7 +540,7 @@ extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); #endif /* PKT_FILTER_SUPPORT */ extern int dhd_get_dtim_skip(dhd_pub_t *dhd); -extern bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd); +extern bool dhd_support_sta_mode(dhd_pub_t *dhd); #ifdef DHD_DEBUG extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); @@ -605,7 +612,7 @@ extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); extern void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); extern void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); #endif /* ARP_OFFLOAD_SUPPORT */ - +extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); typedef enum cust_gpio_modes { WLAN_RESET_ON, @@ -672,15 +679,7 @@ extern uint dhd_sdiod_drive_strength; /* Override to force tx queueing all the time */ extern uint dhd_force_tx_queueing; /* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ -#if defined(CUSTOMER_HW4) -#ifdef KEEP_ALIVE_PACKET_PERIOD_30_SEC -#define KEEP_ALIVE_PERIOD 30000 -#else /* KEEP_ALIVE_PACKET_PERIOD_30_SEC */ -#define KEEP_ALIVE_PERIOD 55000 -#endif /* KEEP_ALIVE_PACKET_PERIOD_30_SEC */ -#else -#define KEEP_ALIVE_PERIOD 55000 -#endif /* CUSTOMER_HW4 */ +#define KEEP_ALIVE_PERIOD 28000 #define NULL_PKT_STR "null_pkt" /* hooks for custom glom setting option via Makefile */ @@ -689,6 +688,21 @@ extern uint dhd_force_tx_queueing; #define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE #endif +/* hooks for custom Roaming Trigger setting via Makefile */ +#define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ +#define DEFAULT_ROAM_TRIGGER_SETTING -1 +#ifndef CUSTOM_ROAM_TRIGGER_SETTING +#define CUSTOM_ROAM_TRIGGER_SETTING DEFAULT_ROAM_TRIGGER_VALUE +#endif + +/* hooks for custom Roaming Romaing setting via Makefile */ +#define DEFAULT_ROAM_DELTA_VALUE 10 /* dBm default roam delta all band */ +#define DEFAULT_ROAM_DELTA_SETTING -1 +#ifndef CUSTOM_ROAM_DELTA_SETTING +#define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE +#endif + + /* hooks for custom dhd_dpc_prio setting option via Makefile */ #define DEFAULT_DHP_DPC_PRIO 1 #ifndef CUSTOM_DPC_PRIO_SETTING diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index 46de6f4..cd44b92 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 357848 2012-09-20 05:38:41Z $ + * $Id: dhd_cdc.c 355825 2012-09-10 03:22:40Z $ * * 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 @@ -892,7 +892,7 @@ _dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) if (PKTLEN(ctx->osh, pktbuf) < (h->dataOffset << 2)) { WLFC_DBGMESG(("%s: rx data too short (%d < %d)\n", __FUNCTION__, - PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); + PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); return BCME_ERROR; } /* pull wl-header */ @@ -958,7 +958,7 @@ _dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, else { /* remove header first */ rc = _dhd_wlfc_pullheader(ctx, p); - if (rc != BCME_OK) { + if (rc != BCME_OK) { WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); /* free the hanger slot */ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); @@ -1794,6 +1794,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) void* p; int fifo_id; + dhd_os_wlfc_block(dhd); if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { #ifdef PROP_TXSTATUS_DEBUG wlfc->stats.signal_only_pkts_freed++; @@ -1801,6 +1802,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) if (success) /* is this a signal-only packet? */ PKTFREE(wlfc->osh, txp, TRUE); + dhd_os_wlfc_unblock(dhd); return; } if (!success) { @@ -1835,6 +1837,7 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) PKTFREE(wlfc->osh, txp, TRUE); } + dhd_os_wlfc_unblock(dhd); return; } @@ -2466,6 +2469,8 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + h->items[i].pkt = NULL; + h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { /* These are already freed from the psq */ @@ -2480,8 +2485,14 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) /* flush remained pkt in hanger queue, not in bus->txq */ for (i = 0; i < h->max_items; i++) { if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { - PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); + if (!dhd->hang_was_sent) { + PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); + } else { + printk("%s: Skip freeing skb %p\n", __func__, h->items[i].pkt); + } h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + h->items[i].pkt = NULL; + h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { /* These are freed from the psq so no need to free again */ h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; @@ -2497,9 +2508,11 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) dhd->wlfc_state; - if (dhd->wlfc_state == NULL) + dhd_os_wlfc_block(dhd); + if (dhd->wlfc_state == NULL) { + dhd_os_wlfc_unblock(dhd); return; - + } #ifdef PROP_TXSTATUS_DEBUG { int i; @@ -2522,6 +2535,7 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) #if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); #endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ + dhd_os_wlfc_unblock(dhd); return; } #endif /* PROP_TXSTATUS */ @@ -2531,8 +2545,10 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) { bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(dhdp); if (dhdp->wlfc_state) dhd_wlfc_dump(dhdp, strbuf); + dhd_os_wlfc_unblock(dhdp); #endif } diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index cc49465..e6a6837 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -80,14 +80,11 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); dhd->op_mode |= val; - WL_ERR(("Set : op_mode=%d\n", dhd->op_mode)); -#if defined(ARP_OFFLOAD_SUPPORT) - if ((dhd->op_mode & CONCURRENT_MULTI_CHAN) != - CONCURRENT_MULTI_CHAN) { - /* IF P2P is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, false); - } + WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode)); +#ifdef ARP_OFFLOAD_SUPPORT + /* IF P2P is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, false); #endif /* ARP_OFFLOAD_SUPPORT */ return 0; @@ -96,8 +93,8 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) { dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - dhd->op_mode &= ~CONCURENT_MASK; - WL_ERR(("Clean : op_mode=%d\n", dhd->op_mode)); + dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE); + WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode)); #if defined(ARP_OFFLOAD_SUPPORT) /* IF P2P is disabled, enable arpoe back for STA mode. */ diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index b985a7c..dab9686 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 357867 2012-09-20 06:57:44Z $ + * $Id: dhd_common.c 356374 2012-09-12 10:37:44Z $ */ #include <typedefs.h> #include <osl.h> @@ -339,7 +339,7 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch else if (int_val & DHD_WL_VAL) wl_cfg80211_enable_trace(FALSE, WL_DBG_DBG); if (!(int_val & DHD_WL_VAL2)) -#endif +#endif /* WL_CFG80211 */ dhd_msg_level = int_val; break; case IOV_GVAL(IOV_BCMERRORSTR): @@ -1855,34 +1855,16 @@ exit: return bcn_li_dtim; } -/* Check if HostAPD or WFD mode setup */ -bool dhd_check_ap_wfd_mode_set(dhd_pub_t *dhd) +/* Check if the mode supports STA MODE */ +bool dhd_support_sta_mode(dhd_pub_t *dhd) { -#if !defined(AP) && defined(WLP2P) - if ((dhd->op_mode & CONCURRENT_FW_MASK) == CONCURRENT_FW_MASK) - return FALSE; -#endif + #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)) { - return TRUE; - } - else -#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; - } + if (!(dhd->op_mode & DHD_FLAG_STA_MODE)) + return FALSE; else -#endif /* WL_ENABLE_P2P_IF */ #endif /* WL_CFG80211 */ - return FALSE; + return TRUE; } #if defined(PNO_SUPPORT) @@ -1927,7 +1909,8 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) +#ifndef WL_SCHED_SCAN + if (!dhd_support_sta_mode(dhd)) return (ret); memset(iovbuf, 0, sizeof(iovbuf)); @@ -1936,6 +1919,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__)); return ret; } +#endif /* !WL_SCHED_SCAN */ /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { @@ -1976,8 +1960,10 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, return err; } - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (err); +#ifndef WL_SCHED_SCAN + if (!dhd_support_sta_mode(dhd)) + return err; +#endif /* !WL_SCHED_SCAN */ /* Check for broadcast ssid */ for (k = 0; k < nssid; k++) { @@ -2094,8 +2080,8 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) int str_len; int res = -1; - if (dhd_check_ap_wfd_mode_set(dhd) == TRUE) - return (res); + if (!dhd_support_sta_mode(dhd)) + return res; DHD_TRACE(("%s execution\n", __FUNCTION__)); diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index 72a3a8e..1683501 100644 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -97,6 +97,7 @@ const struct cntry_locales_custom translate_custom_table[] = { {"SI", "SI", 1}, {"SK", "SK", 1}, {"TR", "TR", 7}, + {"UA", "UA", 2}, {"TW", "TW", 2}, {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */ @@ -107,23 +108,14 @@ const struct cntry_locales_custom translate_custom_table[] = { {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */ {"PK", "XZ", 11}, /* Universal if Country code is PAKISTAN */ #ifdef BCM4334_CHIP - {"RU", "RU", 13}, - {"SG", "SG", 4}, - {"US", "US", 46}, - {"UA", "UA", 8}, - {"CO", "CO", 4}, - {"ID", "ID", 1}, - {"LA", "LA", 1}, - {"LB", "LB", 2}, - {"VN", "VN", 4}, + {"RU", "RU", 5}, + {"SG", "SG", 4}, + {"US", "US", 46} #endif #ifdef BCM4330_CHIP - {"RU", "RU", 13}, - {"US", "US", 5}, - {"UA", "UY", 0}, - {"AD", "AL", 0}, + {"RU", "RU", 1}, + {"US", "US", 5} #endif - {"UA", "UA", 2} }; /* Customized Locale convertor diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index ea31b93..8702a44 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 358099 2012-09-21 04:38:52Z $ + * $Id: dhd_linux.c 358016 2012-09-20 22:36:51Z $ */ #include <typedefs.h> @@ -602,8 +602,8 @@ extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ -#ifdef PKT_FILTER_SUPPORT void dhd_set_packet_filter(dhd_pub_t *dhd) +#ifdef PKT_FILTER_SUPPORT { int i; @@ -613,20 +613,23 @@ void dhd_set_packet_filter(dhd_pub_t *dhd) dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); } } +#endif } void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) { +#ifdef PKT_FILTER_SUPPORT int i; DHD_TRACE(("%s: enter, value = %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_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) { for (i = 0; i < dhd->pktfilter_count; i++) { #ifdef PASS_ARP_PACKET if (value && (i == dhd->pktfilter_count -1) && - !(dhd->op_mode & (P2P_GC_ENABLED | P2P_GO_ENABLED))) { + !(dhd->op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))) { DHD_TRACE_HW4(("Do not turn on ARP white list pkt filter:" "val %d, cnt %d, op_mode 0x%x\n", value, i, dhd->op_mode)); @@ -637,8 +640,8 @@ void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) value, dhd_master_mode); } } -} #endif /* PKT_FILTER_SUPPORT */ +} static int dhd_set_suspend(int value, dhd_pub_t *dhd) { @@ -670,7 +673,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) dhd->early_suspended = 1; #endif /* Kernel suspended */ - DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); + DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, @@ -716,7 +719,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) dhd->early_suspended = 0; #endif /* Kernel resumed */ - DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); + DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY power_mode = PM_FAST; @@ -770,7 +773,7 @@ static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force) /* Set flag when early suspend was called */ dhdp->in_suspend = val; if ((force || !dhdp->suspend_disable_flag) && - (dhd_check_ap_wfd_mode_set(dhdp) == FALSE)) + dhd_support_sta_mode(dhdp)) { ret = dhd_set_suspend(val, dhdp); } @@ -1047,7 +1050,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #ifdef MCAST_LIST_ACCUMULATION DHD_TRACE(("_dhd_set_multicast_list: cnt " "%d " MACDBG "\n", - cnt_iface[i], STR_TO_MACD(ha->addr))); + cnt_iface[i], MAC2STRDBG(ha->addr))); cnt_iface[i]--; #else cnt--; @@ -1534,7 +1537,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) } else /* non-proptxstatus way */ - ret = dhd_bus_txdata(dhdp->bus, pktbuf); + ret = dhd_bus_txdata(dhdp->bus, pktbuf); #else ret = dhd_bus_txdata(dhdp->bus, pktbuf); #endif /* PROP_TXSTATUS */ @@ -1757,11 +1760,11 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) /* Dropping packets before registering net device to avoid kernel panic */ -#ifdef BCMDHDUSB +#ifndef PROP_TXSTATUS_VSDB if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) { #else if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED || !dhd->pub.up) { -#endif /* BCMDHDUSB */ +#endif /* PROP_TXSTATUS_VSDB */ DHD_ERROR(("%s: net device is NOT registered yet. drop packet\n", __FUNCTION__)); PKTFREE(dhdp->osh, pktbuf, TRUE); @@ -1794,10 +1797,10 @@ 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++; #ifdef CUSTOMER_HW4 - if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) { -/* DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n", - pkt_free, caller, free_ptr)); */ - } + /*if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) { + DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n", + pkt_free, caller, free_ptr)); + }*/ #endif PKTFREE(dhdp->osh, pktbuf, TRUE); continue; @@ -1845,7 +1848,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } } else if (dump_data[0] & 1) { DHD_ERROR(("%s: MULTICAST: " MACDBG "\n", - __FUNCTION__, STR_TO_MACD(dump_data))); + __FUNCTION__, MAC2STRDBG(dump_data))); } if (protocol == ETHER_TYPE_802_1X) { @@ -2741,7 +2744,9 @@ dhd_stop(struct net_device *net) #endif #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(&dhd->pub); dhd_wlfc_cleanup(&dhd->pub); + dhd_os_wlfc_unblock(&dhd->pub); #endif /* Stop the protocol module */ @@ -2810,7 +2815,6 @@ dhd_open(struct net_device *net) nvram_path[0] = '\0'; } - dhd->pub.dongle_trap_occured = 0; dhd->pub.hang_was_sent = 0; #if !defined(WL_CFG80211) @@ -3166,6 +3170,11 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #ifdef PROP_TXSTATUS spin_lock_init(&dhd->wlfc_spinlock); +#ifdef PROP_TXSTATUS_VSDB + dhd->pub.wlfc_enabled = FALSE; +#else + dhd->pub.wlfc_enabled = TRUE; +#endif /* PROP_TXSTATUS_VSDB */ #endif /* PROP_TXSTATUS */ /* Initialize other structure content */ @@ -3478,18 +3487,37 @@ dhd_bus_start(dhd_pub_t *dhdp) return 0; } +bool dhd_is_concurrent_mode(dhd_pub_t *dhd) +{ + if (!dhd) + return FALSE; + + if (dhd->op_mode & DHD_FLAG_CONCURR_MULTI_CHAN_MODE) + return TRUE; + else if ((dhd->op_mode & DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) == + DHD_FLAG_CONCURR_SINGLE_CHAN_MODE) + return TRUE; + else + return FALSE; +} + #if !defined(AP) && defined(WLP2P) -/* For Android ICS MR2 release, the concurrent mode is enabled by default and the firmware +/* From Android JerryBean release, the concurrent mode is enabled by default and the firmware * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA * firmware and accordingly enable concurrent mode (Apply P2P settings). SoftAP firmware * would still be named as fw_bcmdhd_apsta. */ -int +uint32 dhd_get_concurrent_capabilites(dhd_pub_t *dhd) { - int ret = 0; + int32 ret = 0; char buf[WLC_IOCTL_SMLEN]; - bool vsdb_supported = false; + bool mchan_supported = FALSE; + /* if dhd->op_mode is already set for HOSTAP, + * that means we only will use the mode as it is + */ + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) + return 0; memset(buf, 0, sizeof(buf)); bcm_mkiovar("cap", 0, 0, buf, sizeof(buf)); if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), @@ -3499,7 +3527,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) return 0; } if (strstr(buf, "vsdb")) { - vsdb_supported = true; + mchan_supported = TRUE; } if (strstr(buf, "p2p") == NULL) { DHD_TRACE(("Chip does not support p2p\n")); @@ -3516,14 +3544,19 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) } else { if (buf[0] == 1) { - /* Chip supports p2p, now lets check for vsdb */ - if (vsdb_supported) - return 2; - else -#ifdef WL_ENABLE_P2P_IF - return 1; + /* By default, chip supports single chan concurrency, + * now lets check for mchan + */ + ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE; + if (mchan_supported) + ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE; +#if defined(WL_ENABLE_P2P_IF) + /* For customer_hw4, although ICS, + * we still support concurrent mode + */ + return ret; #else - return 0; + return 0; #endif } } @@ -3556,7 +3589,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; #endif - int scan_assoc_time = DHD_SCAN_ACTIVE_TIME; + int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; int scan_passive_time = DHD_SCAN_PASSIVE_TIME; char buf[WLC_IOCTL_SMLEN]; @@ -3564,12 +3597,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */ #ifdef ROAM_ENABLE uint roamvar = 0; - int roam_trigger[2] = {-75, WLC_BAND_ALL}; + int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; int roam_scan_period[2] = {10, WLC_BAND_ALL}; - int roam_delta[2] = {10, WLC_BAND_ALL}; #ifdef ROAM_AP_ENV_DETECTION int roam_env_mode = AP_ENV_INDETERMINATE; #endif /* ROAM_AP_ENV_DETECTION */ + int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC int roam_fullscan_period = 60; #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ @@ -3609,8 +3642,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) int interference_mode = 3; #endif #ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd->wlfc_enabled = FALSE; /* enable WLFC only if the firmware is VSDB */ +#else + dhd->wlfc_enabled = TRUE; +#endif /* PROP_TXSTATUS_VSDB */ #endif /* PROP_TXSTATUS */ DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; @@ -3643,11 +3680,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* GET_CUSTOM_MAC_ENABLE */ - if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == HOSTAPD_MASK)) { + if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || + (op_mode == DHD_FLAG_HOSTAP_MODE)) { #ifdef SET_RANDOM_MAC_SOFTAP uint rand_mac; #endif - op_mode = HOSTAPD_MASK; + dhd->op_mode = DHD_FLAG_HOSTAP_MODE; #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif @@ -3682,31 +3720,33 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } else { - int concurrent_capab = 0; - if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || (op_mode == WFD_MASK)) { + uint32 concurrent_mode = 0; + if ((!op_mode && strstr(fw_path, "_p2p") != NULL) || + (op_mode == DHD_FLAG_P2P_MODE)) { #if defined(ARP_OFFLOAD_SUPPORT) arpoe = 0; #endif #ifdef PKT_FILTER_SUPPORT dhd_pkt_filter_enable = FALSE; #endif - op_mode = WFD_MASK; + dhd->op_mode = DHD_FLAG_P2P_MODE; } else - op_mode = STA_MASK; + dhd->op_mode = DHD_FLAG_STA_MODE; #if !defined(AP) && defined(WLP2P) - if ((concurrent_capab = dhd_get_concurrent_capabilites(dhd)) > 0) { - op_mode = STA_MASK | WFD_MASK; - if (concurrent_capab == 2) - op_mode = STA_MASK | WFD_MASK | CONCURRENT_MULTI_CHAN; + if ((concurrent_mode = dhd_get_concurrent_capabilites(dhd))) { +#if defined(ARP_OFFLOAD_SUPPORT) + arpoe = 1; +#endif + dhd->op_mode |= concurrent_mode; } /* Check if we are enabling p2p */ - if (op_mode & WFD_MASK) { + if (dhd->op_mode & DHD_FLAG_P2P_MODE) { 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 for P2P failed ret= %d\n", __FUNCTION__, ret)); } memcpy(&p2p_ea, &dhd->mac, ETHER_ADDR_LEN); @@ -3721,15 +3761,14 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } } #else - (void)concurrent_capab; -#endif + (void)concurrent_mode; +#endif } - dhd->op_mode = op_mode; - DHD_ERROR(("Firmware up: op_mode=%d, " + DHD_ERROR(("Firmware up: op_mode=0x%04x, " "Broadcom Dongle Host Driver mac="MACDBG"\n", dhd->op_mode, - STR_TO_MACD(dhd->mac.octet))); + MAC2STRDBG(dhd->mac.octet))); /* Set Country code */ if (dhd->dhd_cspec.ccode[0] != 0) { bcm_mkiovar("country", (char *)&dhd->dhd_cspec, @@ -3749,12 +3788,18 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ #ifdef ROAM_ENABLE - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), TRUE, 0); - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period, - sizeof(roam_scan_period), TRUE, 0); - dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, sizeof(roam_delta), TRUE, 0); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, + sizeof(roam_trigger), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_SCAN_PERIOD, roam_scan_period, + sizeof(roam_scan_period), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam scan period set failed %d\n", __FUNCTION__, ret)); + if ((dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_DELTA, roam_delta, + sizeof(roam_delta), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam delta set failed %d\n", __FUNCTION__, ret)); bcm_mkiovar("fullroamperiod", (char *)&roam_fullscan_period, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) + DHD_ERROR(("%s: roam fullscan period set failed %d\n", __FUNCTION__, ret)); #ifdef ROAM_AP_ENV_DETECTION if (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER) { bcm_mkiovar("roam_env_detection", (char *)&roam_env_mode, @@ -3783,9 +3828,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if (glom != DEFAULT_GLOM_VALUE) { + DHD_INFO(("%s set glom=0x%X\n", __FUNCTION__, glom)); + 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)); @@ -3819,7 +3866,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #if defined(SOFTAP) if (ap_fw_loaded == FALSE) #endif - if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { + if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { if ((res = dhd_keep_alive_onoff(dhd)) < 0) DHD_ERROR(("%s set keeplive failed %d\n", __FUNCTION__, res)); @@ -3874,7 +3921,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* BCMCCX */ #ifdef WL_CFG80211 setbit(eventmask, WLC_E_ESCAN_RESULT); - if ((dhd->op_mode & WFD_MASK) == WFD_MASK) { + if (dhd->op_mode & DHD_FLAG_P2P_MODE) { setbit(eventmask, WLC_E_ACTION_FRAME_RX); setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE); setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE); @@ -4158,7 +4205,7 @@ static int dhd_device_event(struct notifier_block *this, } #ifdef AOE_IP_ALIAS_SUPPORT - if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { + if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) { /* 0x3a = ':' */ DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", @@ -4176,20 +4223,21 @@ static int dhd_device_event(struct notifier_block *this, __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); dhd->pend_ipaddr = 0; #ifdef AOE_IP_ALIAS_SUPPORT - if ((dhd_pub->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { - if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { - /* 0x3a = ':' */ - DHD_ARPOE(("%s: primary interface is down, AOE clr all\n", - __FUNCTION__)); - dhd_aoe_hostip_clr(&dhd->pub); - dhd_aoe_arp_clr(&dhd->pub); - } else - aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE); - } + if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { + if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { + /* 0x3a = ':' */ + DHD_ARPOE(("%s: primary interface is down," + " AOE clr all\n", __FUNCTION__)); + dhd_aoe_hostip_clr(&dhd->pub); + dhd_aoe_arp_clr(&dhd->pub); + } else + aoe_update_host_ipv4_table(dhd_pub, + ifa->ifa_address, FALSE); + } #else dhd_aoe_hostip_clr(&dhd->pub); dhd_aoe_arp_clr(&dhd->pub); -#endif +#endif /* AOE_IP_ALIAS_SUPPORT */ break; default: @@ -4287,9 +4335,9 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) " MAC: "MACDBG"\n", net->name, #if defined(CUSTOMER_HW4) - STR_TO_MACD(dhd->pub.mac.octet)); + MAC2STRDBG(dhd->pub.mac.octet)); #else - STR_TO_MACD(net->dev_addr)); + MAC2STRDBG(net->dev_addr)); #endif /* CUSTOMER_HW4 */ #if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211) @@ -5149,6 +5197,9 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) #else ret = dhd_suspend_resume_helper(dhd, val, force); #endif +#ifdef WL_CFG80211 + wl_cfg80211_update_power_mode(dev); +#endif } return ret; } @@ -5813,23 +5864,34 @@ extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); int dhd_wlfc_interface_event(struct dhd_info *dhd, ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) { - if (dhd->pub.wlfc_state == NULL) - return BCME_OK; + int ret = BCME_OK; - return dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); + dhd_os_wlfc_block(&dhd->pub); + if (dhd->pub.wlfc_state != NULL) + ret = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data) { - if (dhd->pub.wlfc_state == NULL) - return BCME_OK; + int ret = BCME_OK; - return dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); + dhd_os_wlfc_block(&dhd->pub); + if (dhd->pub.wlfc_state != NULL) + ret = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } int dhd_wlfc_event(struct dhd_info *dhd) { - return dhd_wlfc_enable(&dhd->pub); + int ret; + + dhd_os_wlfc_block(&dhd->pub); + ret = dhd_wlfc_enable(&dhd->pub); + dhd_os_wlfc_unblock(&dhd->pub); + return ret; } #endif /* PROP_TXSTATUS */ diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 0617e16..422ad03 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 357912 2012-09-20 09:42:47Z $ + * $Id: dhd_sdio.c 357859 2012-09-20 06:34:26Z $ */ #include <typedefs.h> @@ -399,14 +399,13 @@ static bool sd1idle; static bool retrydata; #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) -#ifdef BCMSPI -/* At a watermark around 8 the spid hits underflow error. */ -static const uint watermark = 32; -static const uint mesbusyctrl = 0; +#if defined(SDIO_CRC_ERROR_FIX) +static uint watermark = 48; +static uint mesbusyctrl = 80; #else static const uint watermark = 8; static const uint mesbusyctrl = 0; -#endif /* BCMSPI */ +#endif static const uint firstread = DHD_FIRSTREAD; #define HDATLEN (firstread - (SDPCM_HDRLEN)) @@ -417,7 +416,6 @@ static const uint retry_limit = 2; /* Force even SD lengths (some host controllers mess up on odd bytes) */ static bool forcealign; - #define ALIGNMENT 4 #if defined(OOB_INTR_ONLY) && defined(HW_OOB) @@ -1111,11 +1109,12 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); } - else { - if (ht_avail_error == HT_AVAIL_ERROR_MAX) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) + else if (ht_avail_error == HT_AVAIL_ERROR_MAX) { dhd_os_send_hang_message(bus->dhd); - } -return BCME_ERROR; + } +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */ + return BCME_ERROR; } else { ht_avail_error = 0; } @@ -2411,6 +2410,10 @@ enum { IOV_SDALIGN, IOV_DEVRESET, IOV_CPU, +#if defined(SDIO_CRC_ERROR_FIX) + IOV_WATERMARK, + IOV_MESBUSYCTRL, +#endif /* SDIO_CRC_ERROR_FIX */ #ifdef SDTEST IOV_PKTGEN, IOV_EXTLOOP, @@ -2471,6 +2474,10 @@ const bcm_iovar_t dhdsdio_iovars[] = { {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, #endif /* SDTEST */ +#if defined(SDIO_CRC_ERROR_FIX) + {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 }, + {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 }, +#endif /* SDIO_CRC_ERROR_FIX */ {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 }, {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 }, {"kso", IOV_KSO, 0, IOVT_UINT32, 0 }, @@ -3105,7 +3112,8 @@ dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) if (bus->sih->chip == BCM4330_CHIP_ID) { uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; } - else if (bus->sih->chip == BCM4334_CHIP_ID) { + else if (bus->sih->chip == BCM4334_CHIP_ID || + bus->sih->chip == BCM43341_CHIP_ID) { if (enable) { /* Moved to PMU chipcontrol 1 from 4330 */ int_val &= ~gpio_sel; @@ -3575,6 +3583,33 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch break; #endif /* SDTEST */ +#if defined(SDIO_CRC_ERROR_FIX) + case IOV_GVAL(IOV_WATERMARK): + int_val = (int32)watermark; + bcopy(&int_val, arg, val_size); + break; + + case IOV_SVAL(IOV_WATERMARK): + watermark = (uint)int_val; + watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark; + DHD_ERROR(("Setting watermark as 0x%x.\n", watermark)); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL); + break; + + case IOV_GVAL(IOV_MESBUSYCTRL): + int_val = (int32)mesbusyctrl; + bcopy(&int_val, arg, val_size); + break; + + case IOV_SVAL(IOV_MESBUSYCTRL): + mesbusyctrl = (uint)int_val; + mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK) + ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; + DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl)); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + ((uint8)mesbusyctrl | 0x80), NULL); + break; +#endif /* SDIO_CRC_ERROR_FIX */ case IOV_GVAL(IOV_DONGLEISOLATION): int_val = bus->dhd->dongle_isolation; @@ -4078,51 +4113,57 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) if (enforce_mutex) dhd_os_sdlock(bus->dhd); - BUS_WAKE(bus); + if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) { + bus->dhd->busstate = DHD_BUS_DOWN; + bus->hostintmask = 0; + bcmsdh_intr_disable(bus->sdh); + } else { + BUS_WAKE(bus); - if (KSO_ENAB(bus)) { - /* Mask the interrupt */ - dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); - dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); - } + if (KSO_ENAB(bus)) { + /* Mask the interrupt */ + dat = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, NULL); + dat &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_INTEN, dat, NULL); + } - /* Change our idea of bus state */ - bus->dhd->busstate = DHD_BUS_DOWN; + /* Change our idea of bus state */ + bus->dhd->busstate = DHD_BUS_DOWN; - if (KSO_ENAB(bus)) { + if (KSO_ENAB(bus)) { - /* Enable clock for device interrupts */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + /* Enable clock for device interrupts */ + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - /* Disable and clear interrupts at the chip level also */ - W_SDREG(0, &bus->regs->hostintmask, retries); - local_hostintmask = bus->hostintmask; - bus->hostintmask = 0; + /* Disable and clear interrupts at the chip level also */ + W_SDREG(0, &bus->regs->hostintmask, retries); + local_hostintmask = bus->hostintmask; + bus->hostintmask = 0; - /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (!err) { - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - (saveclk | SBSDIO_FORCE_HT), &err); - } - if (err) { - DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); - } + /* Force clocks on backplane to be sure F2 interrupt propagates */ + saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); + if (!err) { + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + (saveclk | SBSDIO_FORCE_HT), &err); + } + if (err) { + DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); + } - /* Turn off the bus (F2), free any pending packets */ - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); + /* Turn off the bus (F2), free any pending packets */ + DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); + bcmsdh_intr_disable(bus->sdh); #ifndef BCMSPI - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); -#endif /* !BCMSPI */ + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); +#endif - /* Clear any pending interrupts now that F2 is disabled */ - W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); - } + /* Clear any pending interrupts now that F2 is disabled */ + W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); + } - /* Turn off the backplane clock (only) */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); + /* Turn off the backplane clock (only) */ + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); + } /* Clear the data packet queues */ pktq_flush(osh, &bus->txq, TRUE, NULL, 0); @@ -4281,8 +4322,19 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) } #endif /* BCMSPI */ W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); +#ifdef SDIO_CRC_ERROR_FIX + if (bus->blocksize < 512) { + mesbusyctrl = watermark = bus->blocksize / 4; + } +#endif /* SDIO_CRC_ERROR_FIX */ bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); +#ifdef SDIO_CRC_ERROR_FIX + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + (uint8)mesbusyctrl|0x80, &err); + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK, NULL); +#endif /* SDIO_CRC_ERROR_FIX */ /* Set bus state according to enable result */ dhdp->busstate = DHD_BUS_DATA; @@ -4843,18 +4895,12 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) free_ptr = pfirst; #endif PKTFREE(bus->dhd->osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf, &reorder_info_len) != 0) { DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); bus->dhd->rx_errors++; PKTFREE(osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } if (reorder_info_len) { @@ -4867,9 +4913,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) reorder_info_len, &ppfirst, &free_buf_count); if (free_buf_count == 0) { - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } continue; } else { @@ -4889,14 +4932,12 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) PKTSETNEXT(osh, list_tail[ifidx], ppfirst); list_tail[ifidx] = pfirst; } - plast = pfirst; } num += (uint8)free_buf_count; } else { /* this packet will go up, link back into chain and count it */ - plast = pfirst; if (list_tail[ifidx] == NULL) { list_head[ifidx] = list_tail[ifidx] = pfirst; @@ -5764,6 +5805,7 @@ dhdsdio_hostmail(dhd_bus_t *bus) if (hmb_data & HMB_DATA_FWHALT) { DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED\n")); dhdsdio_checkdied(bus, NULL, 0); + bus->dhd->busstate = DHD_BUS_DOWN; } #endif /* DHD_DEBUG */ @@ -6041,7 +6083,7 @@ clkwait: /* Resched the DPC if ctrl cmd is pending on bus credit */ if (bus->ctrl_frame_stat) { DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n", - __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); + __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); resched = TRUE; } @@ -6668,6 +6710,8 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4334_CHIP_ID) return TRUE; + if (chipid == BCM43341_CHIP_ID) + return TRUE; if (chipid == BCM43239_CHIP_ID) return TRUE; if (chipid == BCM4324_CHIP_ID) diff --git a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h index 1477516..1477516 100644..100755 --- a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile index eca939f..eca939f 100644..100755 --- a/drivers/net/wireless/bcmdhd/include/Makefile +++ b/drivers/net/wireless/bcmdhd/include/Makefile diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index 99b412a..25cd55b 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 313732 2012-02-08 19:49:00Z $ + * $Id: bcmsdh_sdmmc.h 355594 2012-09-07 10:22:02Z $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -34,6 +34,8 @@ #define sd_data(x) #define sd_ctrl(x) +#define sd_trace_hw4 sd_trace + #define sd_sync_dma(sd, read, nbytes) #define sd_init_dma(sd) #define sd_ack_intr(sd) diff --git a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h index 13d6557..d94e9e4 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h @@ -1,168 +1,168 @@ -/* - * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer - * - * Copyright (C) 1999-2012, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmspibrcm.h 354197 2012-08-30 09:05:59Z $ - */ -#ifndef _BCM_SPI_BRCM_H -#define _BCM_SPI_BRCM_H - -#ifndef SPI_MAX_IOFUNCS -/* Maximum number of I/O funcs */ -#define SPI_MAX_IOFUNCS 4 -#endif -/* global msglevel for debug messages - bitvals come from sdiovar.h */ - -#if defined(DHD_DEBUG) -#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0) -#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0) -#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0) -#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0) -#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0) -#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0) -#else -#define sd_err(x) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) -#endif - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_F1 64 -#define BLOCK_SIZE_F2 2048 -#define BLOCK_SIZE_F3 2048 - -/* internal return code */ -#define SUCCESS 0 -#undef ERROR -#define ERROR 1 -#define ERROR_UF 2 -#define ERROR_OF 3 - -/* private bus modes */ -#define SDIOH_MODE_SPI 0 - -#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ -#define USE_MULTIBLOCK 0x4 - -struct sdioh_info { - uint cfg_bar; /* pci cfg address for bar */ - uint32 caps; /* cached value of capabilities reg */ -#ifndef BCMSPI_ANDROID - void *bar0; /* BAR0 for PCI Device */ -#endif /* !BCMSPI_ANDROID */ - osl_t *osh; /* osh handler */ - void *controller; /* Pointer to SPI Controller's private data struct */ -#ifndef BCMSPI_ANDROID - uint lockcount; /* nest count of spi_lock() calls */ - bool client_intr_enabled; /* interrupt connnected flag */ - bool intr_handler_valid; /* client driver interrupt handler valid */ - sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ - void *intr_handler_arg; /* argument to call interrupt handler */ -#endif /* !BCMSPI_ANDROID */ - bool initialized; /* card initialized */ - uint32 target_dev; /* Target device ID */ - uint32 intmask; /* Current active interrupts */ -#ifndef BCMSPI_ANDROID - void *sdos_info; /* Pointer to per-OS private data */ -#endif /* !BCMSPI_ANDROID */ - uint32 controller_type; /* Host controller type */ - uint8 version; /* Host Controller Spec Compliance Version */ - uint irq; /* Client irq */ - uint32 intrcount; /* Client interrupts */ - uint32 local_intrcount; /* Controller interrupts */ - bool host_init_done; /* Controller initted */ - bool card_init_done; /* Client SDIO interface initted */ - bool polled_mode; /* polling for command completion */ - - bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - /* polling hack in wl_linux.c:wl_timer() */ - int adapter_slot; /* Maybe dealing with multiple slots/controllers */ - int sd_mode; /* SD1/SD4/SPI */ - int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */ - uint32 data_xfer_count; /* Current transfer */ - uint16 card_rca; /* Current Address */ - uint8 num_funcs; /* Supported funcs on client */ - uint32 card_dstatus; /* 32bit device status */ - uint32 com_cis_ptr; - uint32 func_cis_ptr[SPI_MAX_IOFUNCS]; - void *dma_buf; - ulong dma_phys; - int r_cnt; /* rx count */ - int t_cnt; /* tx_count */ - uint32 wordlen; /* host processor 16/32bits */ - uint32 prev_fun; - uint32 chip; - uint32 chiprev; - bool resp_delay_all; - bool dwordmode; - bool resp_delay_new; - - struct spierrstats_t spierrstats; -}; - -/************************************************************ - * Internal interfaces: per-port references into bcmspibrcm.c - */ - -/* Global message bits */ -extern uint sd_msglevel; - -/************************************************************** - * Internal interfaces: bcmspibrcm.c references to per-port code - */ - -/* Interrupt (de)registration routines */ -extern int spi_register_irq(sdioh_info_t *sd, uint irq); -extern void spi_free_irq(uint irq, sdioh_info_t *sd); - -/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ -extern void spi_lock(sdioh_info_t *sd); -extern void spi_unlock(sdioh_info_t *sd); - -/* Allocate/init/free per-OS private data */ -extern int spi_osinit(sdioh_info_t *sd); -extern void spi_osfree(sdioh_info_t *sd); - -#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */ -#define SPI_RW_FLAG_S 31 -#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */ -#define SPI_ACCESS_S 30 -#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */ -#define SPI_FUNCTION_S 28 -#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */ -#define SPI_REG_ADDR_S 11 -#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */ -#define SPI_LEN_S 0 - -#endif /* _BCM_SPI_BRCM_H */ +/*
+ * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
+ *
+ * Copyright (C) 1999-2012, Broadcom Corporation
+ *
+ * Unless you and Broadcom execute a separate written software license
+ * agreement governing use of this software, this software is licensed to you
+ * under the terms of the GNU General Public License version 2 (the "GPL"),
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the
+ * following added to such license:
+ *
+ * As a special exception, the copyright holders of this software give you
+ * permission to link this software with independent modules, and to copy and
+ * distribute the resulting executable under terms of your choice, provided that
+ * you also meet, for each linked independent module, the terms and conditions of
+ * the license of that module. An independent module is a module which is not
+ * derived from this software. The special exception does not apply to any
+ * modifications of the software.
+ *
+ * Notwithstanding the above, under no circumstances may you combine this
+ * software in any way with any other Broadcom software provided under a license
+ * other than the GPL, without Broadcom's express prior written consent.
+ *
+ * $Id: bcmspibrcm.h 354176 2012-08-30 07:34:33Z $
+ */
+#ifndef _BCM_SPI_BRCM_H
+#define _BCM_SPI_BRCM_H
+
+#ifndef SPI_MAX_IOFUNCS
+/* Maximum number of I/O funcs */
+#define SPI_MAX_IOFUNCS 4
+#endif
+/* global msglevel for debug messages - bitvals come from sdiovar.h */
+
+#if defined(DHD_DEBUG)
+#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
+#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
+#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0)
+#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0)
+#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0)
+#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+#define sd_log(x)
+
+#define SDIOH_ASSERT(exp) \
+ do { if (!(exp)) \
+ printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
+ } while (0)
+
+#define BLOCK_SIZE_F1 64
+#define BLOCK_SIZE_F2 2048
+#define BLOCK_SIZE_F3 2048
+
+/* internal return code */
+#define SUCCESS 0
+#undef ERROR
+#define ERROR 1
+#define ERROR_UF 2
+#define ERROR_OF 3
+
+/* private bus modes */
+#define SDIOH_MODE_SPI 0
+
+#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
+#define USE_MULTIBLOCK 0x4
+
+struct sdioh_info {
+ uint cfg_bar; /* pci cfg address for bar */
+ uint32 caps; /* cached value of capabilities reg */
+#ifndef BCMSPI_ANDROID
+ void *bar0; /* BAR0 for PCI Device */
+#endif /* !BCMSPI_ANDROID */
+ osl_t *osh; /* osh handler */
+ void *controller; /* Pointer to SPI Controller's private data struct */
+#ifndef BCMSPI_ANDROID
+ uint lockcount; /* nest count of spi_lock() calls */
+ bool client_intr_enabled; /* interrupt connnected flag */
+ bool intr_handler_valid; /* client driver interrupt handler valid */
+ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
+ void *intr_handler_arg; /* argument to call interrupt handler */
+#endif /* !BCMSPI_ANDROID */
+ bool initialized; /* card initialized */
+ uint32 target_dev; /* Target device ID */
+ uint32 intmask; /* Current active interrupts */
+#ifndef BCMSPI_ANDROID
+ void *sdos_info; /* Pointer to per-OS private data */
+#endif /* !BCMSPI_ANDROID */
+ uint32 controller_type; /* Host controller type */
+ uint8 version; /* Host Controller Spec Compliance Version */
+ uint irq; /* Client irq */
+ uint32 intrcount; /* Client interrupts */
+ uint32 local_intrcount; /* Controller interrupts */
+ bool host_init_done; /* Controller initted */
+ bool card_init_done; /* Client SDIO interface initted */
+ bool polled_mode; /* polling for command completion */
+
+ bool sd_use_dma; /* DMA on CMD53 */
+ bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
+ /* Must be on for sd_multiblock to be effective */
+ bool use_client_ints; /* If this is false, make sure to restore */
+ /* polling hack in wl_linux.c:wl_timer() */
+ int adapter_slot; /* Maybe dealing with multiple slots/controllers */
+ int sd_mode; /* SD1/SD4/SPI */
+ int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */
+ uint32 data_xfer_count; /* Current transfer */
+ uint16 card_rca; /* Current Address */
+ uint8 num_funcs; /* Supported funcs on client */
+ uint32 card_dstatus; /* 32bit device status */
+ uint32 com_cis_ptr;
+ uint32 func_cis_ptr[SPI_MAX_IOFUNCS];
+ void *dma_buf;
+ ulong dma_phys;
+ int r_cnt; /* rx count */
+ int t_cnt; /* tx_count */
+ uint32 wordlen; /* host processor 16/32bits */
+ uint32 prev_fun;
+ uint32 chip;
+ uint32 chiprev;
+ bool resp_delay_all;
+ bool dwordmode;
+ bool resp_delay_new;
+
+ struct spierrstats_t spierrstats;
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmspibrcm.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/**************************************************************
+ * Internal interfaces: bcmspibrcm.c references to per-port code
+ */
+
+/* Interrupt (de)registration routines */
+extern int spi_register_irq(sdioh_info_t *sd, uint irq);
+extern void spi_free_irq(uint irq, sdioh_info_t *sd);
+
+/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
+extern void spi_lock(sdioh_info_t *sd);
+extern void spi_unlock(sdioh_info_t *sd);
+
+/* Allocate/init/free per-OS private data */
+extern int spi_osinit(sdioh_info_t *sd);
+extern void spi_osfree(sdioh_info_t *sd);
+
+#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */
+#define SPI_RW_FLAG_S 31
+#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */
+#define SPI_ACCESS_S 30
+#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */
+#define SPI_FUNCTION_S 28
+#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */
+#define SPI_REG_ADDR_S 11
+#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */
+#define SPI_LEN_S 0
+
+#endif /* _BCM_SPI_BRCM_H */
diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index b735090..cbbd7ef 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -659,12 +659,11 @@ extern void *_bcmutils_dummy_fn; (ea).octet[5] #if !defined(SIMPLE_MAC_PRINT) #define MACDBG "%02x:%02x:%02x:%02x:%02x:%02x" -#define STR_TO_MACD(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] +#define MAC2STRDBG(ea) (ea)[0], (ea)[1], (ea)[2], (ea)[3], (ea)[4], (ea)[5] #else #define MACDBG "%02x:%02x:%02x" -#define STR_TO_MACD(ea) (ea)[0], (ea)[4], (ea)[5] -#endif - +#define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5] +#endif /* SIMPLE_MAC_PRINT */ typedef struct bcm_bit_desc { uint32 bit; diff --git a/drivers/net/wireless/bcmdhd/include/bcmwifi.h b/drivers/net/wireless/bcmdhd/include/bcmwifi.h new file mode 100644 index 0000000..e5207e9 --- /dev/null +++ b/drivers/net/wireless/bcmdhd/include/bcmwifi.h @@ -0,0 +1,165 @@ +/* + * Misc utility routines for WL and Apps + * This header file housing the define and function prototype use by + * both the wl driver, tools & Apps. + * + * 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: bcmwifi.h 277737 2011-08-16 17:54:59Z $ + */ + + +#ifndef _bcmwifi_h_ +#define _bcmwifi_h_ + + + +typedef uint16 chanspec_t; + + +#define CH_UPPER_SB 0x01 +#define CH_LOWER_SB 0x02 +#define CH_EWA_VALID 0x04 +#define CH_20MHZ_APART 4 +#define CH_10MHZ_APART 2 +#define CH_5MHZ_APART 1 +#define CH_MAX_2G_CHANNEL 14 +#define WLC_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL +#define MAXCHANNEL 224 + +#define WL_CHANSPEC_CHAN_MASK 0x00ff +#define WL_CHANSPEC_CHAN_SHIFT 0 + +#define WL_CHANSPEC_CTL_SB_MASK 0x0300 +#define WL_CHANSPEC_CTL_SB_SHIFT 8 +#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 +#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 +#define WL_CHANSPEC_CTL_SB_NONE 0x0300 + +#define WL_CHANSPEC_BW_MASK 0x0C00 +#define WL_CHANSPEC_BW_SHIFT 10 +#define WL_CHANSPEC_BW_10 0x0400 +#define WL_CHANSPEC_BW_20 0x0800 +#define WL_CHANSPEC_BW_40 0x0C00 + +#define WL_CHANSPEC_BAND_MASK 0xf000 +#define WL_CHANSPEC_BAND_SHIFT 12 +#define WL_CHANSPEC_BAND_5G 0x1000 +#define WL_CHANSPEC_BAND_2G 0x2000 +#define INVCHANSPEC 255 + + +#define WF_CHAN_FACTOR_2_4_G 4814 +#define WF_CHAN_FACTOR_5_G 10000 +#define WF_CHAN_FACTOR_4_G 8000 + + +#define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) +#define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ + ((channel) + CH_10MHZ_APART) : 0) +#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) +#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ + WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ + WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) +#define NEXT_20MHZ_CHAN(channel) (((channel) < (MAXCHANNEL - CH_20MHZ_APART)) ? \ + ((channel) + CH_20MHZ_APART) : 0) +#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ + ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ + ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ + WL_CHANSPEC_BAND_5G)) +#define CHSPEC_CHANNEL(chspec) ((uint8)((chspec) & WL_CHANSPEC_CHAN_MASK)) +#define CHSPEC_BAND(chspec) ((chspec) & WL_CHANSPEC_BAND_MASK) + + +#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK) +#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK) + +#ifdef WL11N_20MHZONLY + +#define CHSPEC_IS10(chspec) 0 +#define CHSPEC_IS20(chspec) 1 +#ifndef CHSPEC_IS40 +#define CHSPEC_IS40(chspec) 0 +#endif + +#else + +#define CHSPEC_IS10(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) +#define CHSPEC_IS20(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) +#ifndef CHSPEC_IS40 +#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) +#endif + +#endif + +#define CHSPEC_IS20_UNCOND(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) + +#define CHSPEC_IS5G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) +#define CHSPEC_IS2G(chspec) (((chspec) & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) +#define CHSPEC_SB_NONE(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) +#define CHSPEC_SB_UPPER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) +#define CHSPEC_SB_LOWER(chspec) (((chspec) & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) +#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ + (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ + (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) +#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G(chspec) ? WLC_BAND_5G : WLC_BAND_2G) + +#define CHANSPEC_STR_LEN 8 + + +#define WLC_MAXRATE 108 +#define WLC_RATE_1M 2 +#define WLC_RATE_2M 4 +#define WLC_RATE_5M5 11 +#define WLC_RATE_11M 22 +#define WLC_RATE_6M 12 +#define WLC_RATE_9M 18 +#define WLC_RATE_12M 24 +#define WLC_RATE_18M 36 +#define WLC_RATE_24M 48 +#define WLC_RATE_36M 72 +#define WLC_RATE_48M 96 +#define WLC_RATE_54M 108 + +#define WLC_2G_25MHZ_OFFSET 5 + + +extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); + + +extern chanspec_t wf_chspec_aton(char *a); + + +extern bool wf_chspec_malformed(chanspec_t chanspec); + + +extern uint8 wf_chspec_ctlchan(chanspec_t chspec); + + +extern chanspec_t wf_chspec_ctlchspec(chanspec_t chspec); + + +extern int wf_mhz2channel(uint freq, uint start_factor); + + +extern int wf_channel2mhz(uint channel, uint start_factor); + +#endif diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index b36fa0c..11fff55 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 357867 2012-09-20 06:57:44Z $ + * $Id: dhdioctl.h 354894 2012-09-04 12:34:07Z $ */ #ifndef _dhdioctl_h_ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 2d4b886..60f9838 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -30,26 +30,26 @@ #define EPI_MINOR_VERSION 28 -#define EPI_RC_NUMBER 11 +#define EPI_RC_NUMBER 13 -#define EPI_INCREMENTAL_NUMBER 12 +#define EPI_INCREMENTAL_NUMBER 1 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 28, 11, 12 +#define EPI_VERSION 1, 28, 13, 1 -#define EPI_VERSION_NUM 0x011c0b0c +#define EPI_VERSION_NUM 0x011c0d01 -#define EPI_VERSION_DEV 1.28.11 +#define EPI_VERSION_DEV 1.28.13 /* Driver Version String, ASCII, 32 chars max */ #ifdef BCMINTERNAL -#define EPI_VERSION_STR "1.28.11.12 (r BCMINT)" +#define EPI_VERSION_STR "1.28.13.1 (r BCMINT)" #else #ifdef WLTEST -#define EPI_VERSION_STR "1.28.11.12 (r WLTEST)" +#define EPI_VERSION_STR "1.28.13.1 (r WLTEST)" #else -#define EPI_VERSION_STR "1.28.11.12 (Add_p2pPatch_1012)" +#define EPI_VERSION_STR "1.28.13.1 (r)" #endif #endif /* BCMINTERNAL */ diff --git a/drivers/net/wireless/bcmdhd/include/htsf.h b/drivers/net/wireless/bcmdhd/include/htsf.h new file mode 100644 index 0000000..d875edb --- /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/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h index 206effc..2b6fef6 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h +++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h @@ -376,8 +376,7 @@ typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t; #define P2P_PAF_DEVDIS_RSP 6 #define P2P_PAF_PROVDIS_REQ 7 #define P2P_PAF_PROVDIS_RSP 8 -#define P2P_PAF_SUBTYPE_INVALID 255 - +#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ #define P2P_TYPE_MNREQ P2P_PAF_GON_REQ #define P2P_TYPE_MNRSP P2P_PAF_GON_RSP diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h index 00e44d2..0e9ad7d 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h @@ -120,6 +120,7 @@ #define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ #define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ #define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ +#define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */ /* SBSDIO_FUNC1_CHIPCLKCSR */ diff --git a/drivers/net/wireless/bcmdhd/include/spid.h b/drivers/net/wireless/bcmdhd/include/spid.h index f1ecc22..6d2d403 100644 --- a/drivers/net/wireless/bcmdhd/include/spid.h +++ b/drivers/net/wireless/bcmdhd/include/spid.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: spid.h 354197 2012-08-30 09:05:59Z $ + * $Id: spid.h 354172 2012-08-30 07:19:26Z $ */ #ifndef _SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 5205c07..33811a1 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 357629 2012-09-19 12:51:08Z $ + * $Id: wlioctl.h 357627 2012-09-19 12:42:22Z $ */ #ifndef _wlioctl_h_ diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index ddb8372..d03a095 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 350283 2012-08-12 07:47:25Z $ + * $Id: linux_osl.c 355147 2012-09-05 15:03:49Z $ */ #define LINUX_PORT @@ -191,7 +191,7 @@ osl_attach(void *pdev, uint bustype, bool pkttag) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) gfp_t flags; - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; osh = kmalloc(sizeof(osl_t), flags); #else osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); @@ -288,7 +288,7 @@ osl_detach(osl_t *osh) static struct sk_buff *osl_alloc_skb(unsigned int len) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - gfp_t flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + gfp_t flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; return __dev_alloc_skb(len, flags); #else @@ -373,7 +373,7 @@ osl_ctfpool_init(osl_t *osh, uint numobj, uint size) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) gfp_t flags; - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags); #else osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); @@ -896,7 +896,7 @@ original: #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; if ((addr = kmalloc(size, flags)) == NULL) { #else if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { @@ -1058,7 +1058,7 @@ osl_pktdup(osl_t *osh, void *skb) PKTCTFMAP(osh, skb); #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL; + flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL) #else if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 0470a9c..00b6969 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_android.c 354184 2012-08-30 08:08:08Z $ + * $Id: wl_android.c 358186 2012-09-21 14:36:14Z $ */ #include <linux/module.h> @@ -141,8 +141,6 @@ typedef struct cmd_tlv { #define CMD_COUNTRYREV_GET "GETCOUNTRYREV" #endif /* ROAM_API */ -#define CMD_SETROAMMODE "SETROAMMODE" - #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) #define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL" #define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL" @@ -227,6 +225,10 @@ int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) #endif /* WL_CFG80211 */ extern int dhd_os_check_if_up(void *dhdp); extern void *bcmsdh_get_drvdata(void); +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) +extern int dhd_wlfc_init(dhd_pub_t *dhd); +extern void dhd_wlfc_deinit(dhd_pub_t *dhd); +#endif #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) /* wl_roam.c */ @@ -242,9 +244,7 @@ extern bool ap_fw_loaded; extern char iface_name[IFNAMSIZ]; #endif -#ifndef WIFI_TURNOFF_DELAY #define WIFI_TURNOFF_DELAY 0 -#endif /** * Local (static) functions and variables */ @@ -1241,6 +1241,9 @@ int wl_android_wifi_on(struct net_device *dev) if (dhd_dev_init_ioctl(dev) < 0) ret = -EFAULT; } +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_init(bcmsdh_get_drvdata()); +#endif g_wifi_on = TRUE; } @@ -1262,6 +1265,9 @@ int wl_android_wifi_off(struct net_device *dev) dhd_net_if_lock(dev); if (g_wifi_on) { +#if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) + dhd_wlfc_deinit(bcmsdh_get_drvdata()); +#endif ret = dhd_dev_reset(dev, TRUE); sdioh_stop(NULL); dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); @@ -1413,7 +1419,7 @@ wl_android_sta_diassoc(struct net_device *dev, const char* straddr) bcm_ether_atoe(straddr, &scbval.ea); DHD_INFO(("%s: deauth STA: "MACDBG "\n", __FUNCTION__, - STR_TO_MACD(scbval.ea.octet))); + MAC2STRDBG(scbval.ea.octet))); wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t), true); @@ -1517,29 +1523,6 @@ wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) } #endif /* SUPPORT_AMPDU_MPDU_CMD */ -int wl_android_set_roam_mode(struct net_device *dev, -char *command, int total_len) -{ - int error = 0; - int mode = 0; - - if (sscanf(command, "%*s %d", &mode) != 1) { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "Failed to get Parameter\n")); - return -1; - } - - error = wldev_iovar_setint(dev, "roam_off", mode); - if (error) { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "Failed to set roaming Mode %d, error = %d\n", mode, error)); - return -1; - } else { - DHD_ERROR(("wl_android_set_roam_mode:"\ - "succeeded to set roaming Mode %d, error = %d\n", mode, error)); - } - return error; -} int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { #define PRIVATE_COMMAND_MAX_LEN 8192 @@ -1658,7 +1641,16 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) } else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; +#ifdef WL_HOST_BAND_MGMT + if (wl_cfg80211_set_band(net, band) < 0) { + bytes_written = -1; + goto exit; + } + if (band == WLC_BAND_AUTO) + bytes_written = wldev_set_band(net, band); +#else bytes_written = wldev_set_band(net, band); +#endif /* WL_HOST_BAND_MGMT */ } else if (strnicmp(command, CMD_GETBAND, strlen(CMD_GETBAND)) == 0) { bytes_written = wl_android_get_band(net, command, priv_cmd.total_len); @@ -1874,10 +1866,6 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) bytes_written = wl_android_ch_res_rl(net, false); #endif /* CUSTOMER_HW4 */ - else if (strnicmp(command, CMD_SETROAMMODE, - strlen(CMD_SETROAMMODE)) == 0) - bytes_written = wl_android_set_roam_mode(net, - command, priv_cmd.total_len); else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index a0e8616..87c58ea 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.c 358102 2012-09-21 04:45:06Z $ + * $Id: wl_cfg80211.c 359682 2012-09-28 20:23:14Z $ */ #include <typedefs.h> @@ -59,10 +59,6 @@ #include <wl_cfg80211.h> #include <wl_cfgp2p.h> -#ifdef PROP_TXSTATUS -#include <dhd_wlfc.h> -#endif - #ifdef WL11U #ifndef WL_ENABLE_P2P_IF #error "You should enable WL_ENABLE_P2P_IF and Only supported in JB" @@ -259,6 +255,10 @@ static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx); static s32 wl_cfg80211_resume(struct wiphy *wiphy); +static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, u64 cookie); +static s32 wl_cfg80211_del_station(struct wiphy *wiphy, + struct net_device *ndev, u8* mac_addr); #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); #else @@ -373,9 +373,10 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 roam_done_flag); -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 roam_done_flag); +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); +static s32 wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, @@ -484,11 +485,11 @@ do { \ extern int dhd_wait_pend8021x(struct net_device *dev); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB extern int disable_proptx; extern int dhd_wlfc_init(dhd_pub_t *dhd); extern void dhd_wlfc_deinit(dhd_pub_t *dhd); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ #if (WL_DBG_LEVEL > 0) #define WL_DBG_ESTR_MAX 50 @@ -934,6 +935,37 @@ wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +static s32 +wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec) +{ + u32 channel = chspec & WL_CHANSPEC_CHAN_MASK; + + /* If chspec is not for 40MHz. Do nothing */ + if (!(chspec & WL_CHANSPEC_BW_40)) + return channel; + + if ((channel < 0) || (channel > MAXCHANNEL)) + return -1; + + switch (channel) { + /* 5G Channels */ + case 38: + case 46: + case 151: + case 159: + if (chspec & WL_CHANSPEC_CTL_SB_LOWER) + channel = channel - CH_10MHZ_APART; + else if (chspec & WL_CHANSPEC_CTL_SB_UPPER) + channel = channel + CH_10MHZ_APART; + break; + default: + /* Mhz adjustment not required. Use as is */ + WL_ERR(("Unsupported channel: %d \n", channel)); + } + + return channel; +} + static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) { chanspec_t chspec; @@ -962,7 +994,12 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) else { bss = (struct wl_bss_info *) (wl->extra_buf + 4); chspec = bss->chanspec; - WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); + if (chspec & WL_CHANSPEC_BW_40) { + uint32 channel = wl_cfg80211_40MHz_to_20MHz_Channel(chspec); + chspec = wl_ch_host_to_driver(channel); + } + + WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec)); } return chspec; } @@ -991,26 +1028,24 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, s32 wlif_type = -1; s32 mode = 0; s32 val = 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; struct ether_addr primary_mac; int (*net_attach)(void *dhdp, int ifidx); bool rollback_lock = false; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB s32 up = 1; dhd_pub_t *dhd; -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!wl) return ERR_PTR(-EINVAL); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd = (dhd_pub_t *)(wl->pub); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ /* Use primary I/F for sending cmds down to firmware */ @@ -1081,10 +1116,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return ERR_PTR(-ENOMEM); } -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (!dhd) return ERR_PTR(-ENODEV); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!wl->p2p || !wl->p2p->vir_ifname) return ERR_PTR(-ENODEV); @@ -1101,7 +1136,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); wl_notify_escan_complete(wl, _ndev, true, true); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (!wl->wlfc_on && !disable_proptx) { dhd->wlfc_enabled = true; dhd_wlfc_init(dhd); @@ -1110,7 +1145,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR(("WLC_UP return err:%d\n", err)); wl->wlfc_on = true; } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ /* 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 @@ -1171,13 +1206,11 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, "created net attach done\n", wl->p2p->vir_ifname)); if (mode == WL_MODE_AP) wl_set_drv_status(wl, CONNECTED, _ndev); -#if defined(WL_ENABLE_P2P_IF) if (type == NL80211_IFTYPE_P2P_CLIENT) - dhd_mode = P2P_GC_ENABLED; + dhd_mode = DHD_FLAG_P2P_GC_MODE; else if (type == NL80211_IFTYPE_P2P_GO) - dhd_mode = P2P_GO_ENABLED; + dhd_mode = DHD_FLAG_P2P_GO_MODE; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); -#endif /* (WL_ENABLE_P2P_IF) */ } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -1194,13 +1227,13 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); wl->p2p->vif_created = false; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (dhd->wlfc_enabled && wl->wlfc_on) { dhd->wlfc_enabled = false; dhd_wlfc_deinit(dhd); wl->wlfc_on = false; } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ } } fail: @@ -1246,9 +1279,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) (&wl->iface_disable, msecs_to_jiffies(500)); } wl_set_p2p_status(wl, IF_DELETING); -#if defined(WL_ENABLE_P2P_IF) DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl)); -#endif /* (WL_ENABLE_P2P_IF)) */ /* for GO */ if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { @@ -1307,7 +1338,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, s32 mode = 0; chanspec_t chspec; struct wl_priv *wl = wiphy_priv(wiphy); - + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); WL_DBG(("Enter type %d\n", type)); switch (type) { case NL80211_IFTYPE_MONITOR: @@ -1334,7 +1365,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, default: return -EINVAL; } - + if (!dhd) + return -EINVAL; if (ap) { wl_set_mode_by_netdev(wl, ndev, mode); if (wl->p2p_supported && wl->p2p->vif_created) { @@ -1359,6 +1391,8 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); wl_set_mode_by_netdev(wl, ndev, mode); + dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE; + dhd->op_mode |= DHD_FLAG_P2P_GO_MODE; wl_clr_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); if (mode == WL_MODE_AP) @@ -1429,9 +1463,9 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) struct wl_priv *wl = wlcfg_drv_priv; bool rollback_lock = false; s32 index = 0; -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ if (!ndev || (strlen(ndev->name) == 0)) { WL_ERR(("net is NULL\n")); return 0; @@ -1463,15 +1497,13 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) wl_cfgp2p_clear_management_ie(wl, index); WL_DBG(("index : %d\n", index)); -#ifdef PROP_TXSTATUS +#ifdef PROP_TXSTATUS_VSDB if (dhd->wlfc_enabled && wl->wlfc_on) { - dhd_os_wlfc_block(dhd); dhd->wlfc_enabled = false; dhd_wlfc_deinit(dhd); wl->wlfc_on = false; - dhd_os_wlfc_unblock(dhd); } -#endif /* PROP_TXSTATUS */ +#endif /* PROP_TXSTATUS_VSDB */ wl_clr_drv_status(wl, CONNECTED, ndev); } /* Wake up any waiting thread */ @@ -1573,7 +1605,7 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req u32 n_channels; u16 channel; chanspec_t chanspec; - s32 i = 0, offset; + s32 i = 0, j = 0, offset; char *ptr; wlc_ssid_t ssid; struct wl_priv *wl = wlcfg_drv_priv; @@ -1619,25 +1651,39 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN))) continue; - if (request->channels[i]->band == IEEE80211_BAND_2GHZ) + if (request->channels[i]->band == IEEE80211_BAND_2GHZ) { +#ifdef WL_HOST_BAND_MGMT + if (wl->curr_band == WLC_BAND_5G) { + WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel)); + continue; + } +#endif /* WL_HOST_BAND_MGMT */ chanspec |= WL_CHANSPEC_BAND_2G; - else + } else { +#ifdef WL_HOST_BAND_MGMT + if (wl->curr_band == WLC_BAND_2G) { + WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel)); + continue; + } +#endif /* WL_HOST_BAND_MGMT */ chanspec |= WL_CHANSPEC_BAND_5G; + } chanspec |= WL_CHANSPEC_BW_20; chanspec |= WL_CHANSPEC_CTL_SB_NONE; - params->channel_list[i] = channel; - params->channel_list[i] &= WL_CHANSPEC_CHAN_MASK; - params->channel_list[i] |= chanspec; + params->channel_list[j] = channel; + params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK; + params->channel_list[j] |= chanspec; WL_SCAN(("Chan : %d, Channel spec: %x \n", - channel, params->channel_list[i])); - params->channel_list[i] = wl_chspec_host_to_driver(params->channel_list[i]); + channel, params->channel_list[j])); + params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]); + j++; } } else { WL_SCAN(("Scanning all channels\n")); } - n_channels = i; + n_channels = j; /* Copy ssid array if applicable */ WL_SCAN(("### List of SSIDs to scan ###\n")); if (n_ssids > 0) { @@ -1737,7 +1783,7 @@ static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_DBG(("error (%d)\n", err)); return err; @@ -1794,6 +1840,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, #ifdef USE_INITIAL_2G_SCAN bool is_first_init_2g_scan = false; #endif /* USE_INITIAL_2G_SCAN */ + WL_DBG(("Enter \n")); if (!request || !wl) { @@ -1833,6 +1880,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, #endif /* USE_INITIAL_2G_SCAN */ + /* if scan request is not empty parse scan request paramters */ + if (request != NULL) { n_channels = request->n_channels; n_ssids = request->n_ssids; /* Allocate space for populating ssids in wl_iscan_params struct */ @@ -1844,6 +1893,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, /* Allocate space for populating ssids in wl_iscan_params struct */ params_size += sizeof(struct wlc_ssid) * n_ssids; + } params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL); if (params == NULL) { err = -ENOMEM; @@ -1895,20 +1945,33 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, n_valid_chan = dtoh32(list->count); for (i = 0; i < num_chans; i++) { +#ifdef WL_HOST_BAND_MGMT + int channel_band = 0; +#endif /* WL_HOST_BAND_MGMT */ _freq = request->channels[i]->center_freq; channel = ieee80211_frequency_to_channel(_freq); - /* remove DFS channels */ - if (!(request->channels[i]->flags & +#ifdef WL_HOST_BAND_MGMT + channel_band = (channel > CH_MAX_2G_CHANNEL) ? + WLC_BAND_5G : WLC_BAND_2G; + if ((wl->curr_band != WLC_BAND_AUTO) && + (wl->curr_band != channel_band) && + !IS_P2P_SOCIAL_CHANNEL(channel)) + continue; +#endif /* WL_HOST_BAND_MGMT */ + + /* ignore DFS channels */ + if (request->channels[i]->flags & (IEEE80211_CHAN_RADAR - | IEEE80211_CHAN_PASSIVE_SCAN))) { - 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; - } + | IEEE80211_CHAN_PASSIVE_SCAN)) + continue; + + 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; } } @@ -1969,7 +2032,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING; passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); goto exit; @@ -2183,7 +2246,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len)); passive_scan = wl->active_scan ? 0 : 1; err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan), false); + &passive_scan, sizeof(passive_scan), true); if (unlikely(err)) { WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err)); goto scan_out; @@ -2235,7 +2298,7 @@ scan_out: if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) WL_ERR(("FW is connected with " MACDBG "/n", - STR_TO_MACD(bssid.octet))); + MAC2STRDBG(bssid.octet))); else WL_ERR(("GET BSSID failed with %d\n", ret)); @@ -2302,7 +2365,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l) u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL); retry = htod32(retry); - err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), false); + err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true); if (unlikely(err)) { WL_ERR(("cmd (%d) , error (%d)\n", cmd, err)); return err; @@ -2420,7 +2483,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, - sizeof(join_params), false); + sizeof(join_params), true); if (unlikely(err)) { WL_ERR(("Error (%d)\n", err)); return err; @@ -2903,7 +2966,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, scbval.val = htod32(scbval.val); WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n", - STR_TO_MACD(bssid.octet))); + MAC2STRDBG(bssid.octet))); err = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); if (unlikely(err)) { @@ -3057,8 +3120,8 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, /* increate dwell time to receive probe response or detect Beacon * from target AP at a noisy air only during connect command */ - ext_join_params->scan.active_time = DHD_SCAN_ACTIVE_TIME*8; - ext_join_params->scan.passive_time = DHD_SCAN_PASSIVE_TIME*3; + ext_join_params->scan.active_time = WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS; + ext_join_params->scan.passive_time = WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS; /* Set up join scan parameters */ ext_join_params->scan.scan_type = -1; ext_join_params->scan.nprobes @@ -3641,7 +3704,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, } if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) { WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n", - STR_TO_MACD(mac), STR_TO_MACD(curmacp))); + MAC2STRDBG(mac), MAC2STRDBG(curmacp))); } /* Report the current tx rate */ @@ -3692,6 +3755,24 @@ get_station_err: return err; } +/* Function to update sta power save mode for Kernel wifi stack */ +int wl_cfg80211_update_power_mode(struct net_device *dev) +{ + int pm = -1; + int err; + + err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false); + if (err || (pm == -1)) { + WL_ERR(("error (%d)\n", err)); + } else { + pm = (pm == PM_OFF) ? false : true; + WL_DBG(("%s: %d\n", __func__, pm)); + if (dev->ieee80211_ptr) + dev->ieee80211_ptr->ps = pm; + } + return err; +} + static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, s32 timeout) @@ -3700,6 +3781,9 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; struct wl_priv *wl = wiphy_priv(wiphy); struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev); +#ifndef SUPPORT_PM2_ONLY + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); +#endif CHECK_SYS_UP(wl); @@ -3707,7 +3791,13 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, return err; } + /* android has special hooks to change pm when kernel suspended */ +#ifndef SUPPORT_PM2_ONLY + pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; +#else pm = enabled ? PM_FAST : PM_OFF; +#endif + /* Do not enable the power save after assoc if it is p2p interface */ if (_net_info->pm_block || wl->vsdb_mode) { WL_DBG(("Do not enable the power save\n")); @@ -4003,13 +4093,6 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, } else { ndev = dev; } - - if (!wl->p2p) { - WL_DBG(("wl->p2p is not initialized\n")); - err = BCME_ERROR; - goto exit; - } - #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST if (wl_get_drv_status(wl, SCANNING, ndev)) { wl_notify_escan_complete(wl, ndev, true, true); @@ -4344,7 +4427,6 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, u8 category, action; s32 tx_retry; struct p2p_config_af_params config_af_params; - dhd_pub_t *dhd; #ifdef VSDB ulong off_chan_started_jiffies = 0; #endif @@ -4421,16 +4503,8 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, } else if (category == P2P_AF_CATEGORY) { /* do not configure anything. it will be sent with a default configuration */ } else { - dhd = (dhd_pub_t *)(wl->pub); - if ((dhd->op_mode & HOSTAPD_MASK) == HOSTAPD_MASK) { - WL_ERR(("Unknown Frame: category 0x%x, action 0x%x\n", - category, action)); - wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); - return false; - } else { - WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n", - category, action)); - } + WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n", + category, action)); } /* To make sure to send successfully action frame, we have to turn off mpc */ @@ -4658,8 +4732,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, ieee80211_is_deauth(mgmt->frame_control)) { memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); scb_val.val = mgmt->u.disassoc.reason_code; - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); + if (err < 0) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err)); WL_DBG(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); @@ -5531,6 +5607,51 @@ static s32 wl_cfg80211_hostapd_sec( return 0; } +static s32 +wl_cfg80211_del_station( + struct wiphy *wiphy, + struct net_device *ndev, + u8* mac_addr) +{ + struct net_device *dev; + struct wl_priv *wl = wiphy_priv(wiphy); + scb_val_t scb_val; + s8 eabuf[ETHER_ADDR_STR_LEN]; + + WL_DBG(("Entry\n")); + if (mac_addr == NULL) { + WL_DBG(("mac_addr is NULL ignore it\n")); + return 0; + } + + if (ndev == wl->p2p_net) { + dev = wl_to_prmry_ndev(wl); + } else { + dev = ndev; + } + + if (p2p_is_on(wl)) { + /* Suspend P2P discovery search-listen to prevent it from changing the + * channel. + */ + if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) { + WL_ERR(("Can not disable discovery mode\n")); + return -EFAULT; + } + } + + memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); + scb_val.val = DOT11_RC_DEAUTH_LEAVING; + if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + sizeof(scb_val_t), true)) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON failed\n")); + WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), + scb_val.val)); + wl_delay(400); + return 0; +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) static s32 wl_cfg80211_start_ap( @@ -5661,50 +5782,6 @@ exit: return err; } static s32 -wl_cfg80211_del_station( - struct wiphy *wiphy, - struct net_device *ndev, - u8* mac_addr) -{ - struct net_device *dev; - struct wl_priv *wl = wiphy_priv(wiphy); - scb_val_t scb_val; - s8 eabuf[ETHER_ADDR_STR_LEN]; - - WL_DBG(("Entry\n")); - if (mac_addr == NULL) { - WL_DBG(("mac_addr is NULL ignore it\n")); - return 0; - } - - if (ndev == wl->p2p_net) { - dev = wl_to_prmry_ndev(wl); - } else { - dev = ndev; - } - - if (p2p_is_on(wl)) { - /* Suspend P2P discovery search-listen to prevent it from changing the - * channel. - */ - if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) { - WL_ERR(("Can not disable discovery mode\n")); - return -EFAULT; - } - } - - memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); - scb_val.val = DOT11_RC_DEAUTH_LEAVING; - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, - sizeof(scb_val_t), true); - WL_DBG(("Disconnect STA : %s scb_val.val %d\n", - bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), - scb_val.val)); - wl_delay(400); - return 0; -} - -static s32 wl_cfg80211_change_beacon( struct wiphy *wiphy, struct net_device *dev, @@ -5909,8 +5986,13 @@ static struct cfg80211_ops wl_cfg80211_ops = { .change_beacon = wl_cfg80211_change_beacon, .start_ap = wl_cfg80211_start_ap, .stop_ap = wl_cfg80211_stop_ap, - .del_station = wl_cfg80211_del_station, #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +#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) */ + .del_station = wl_cfg80211_del_station, + .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -6042,7 +6124,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) #ifdef ROAM_CHANNEL_CACHE add_roam_cache(bi); #endif - err = wl_inform_single_bss(wl, bi, 0); + err = wl_inform_single_bss(wl, bi); if (unlikely(err)) break; } @@ -6052,7 +6134,7 @@ static s32 wl_inform_bss(struct wl_priv *wl) return err; } -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 roam_done_flag) +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) { struct wiphy *wiphy = wl_to_wiphy(wl); struct ieee80211_mgmt *mgmt; @@ -6067,7 +6149,6 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r u32 freq; s32 err = 0; gfp_t aflags; - u8 *ie_offset=NULL; if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { WL_DBG(("Beacon is larger than buffer. Discarding\n")); @@ -6108,35 +6189,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r beacon_proberesp->capab_info = cpu_to_le16(bi->capability); wl_rst_ie(wl); -#define WLAN_EID_SSID 0 - ie_offset = ((u8 *) bi) + bi->ie_offset; - - if ( roam_done_flag && ((int)(*(ie_offset)) == WLAN_EID_SSID && ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { - u8 *ie_new_offset = NULL; - uint8 ie_new_length; - - WL_ERR(("Changing the SSID Info\n")); - - ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (ie_new_offset) { - *(ie_new_offset) = WLAN_EID_SSID; - *(ie_new_offset+1) = bi->SSID_len; - memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); - ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; - - /* Copy the remaining IE apart from SSID IE from bi */ - memcpy( ie_new_offset+2 + bi->SSID_len, - ie_offset+2 + *(ie_offset+1), - bi->ie_length - 2 - *(ie_offset+1)); - wl_mrg_ie(wl, ie_new_offset , ie_new_length); - kfree(ie_new_offset); - } else { - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); - } - } else { - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); - } - + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - offsetof(struct wl_cfg80211_bss_info, frame_buf)); notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, @@ -6159,9 +6212,9 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 r return -EINVAL; } WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM" - "mgmt_type 0x%x, mgmt->frame_control=0x%x, frame_len %d\n", bi->SSID, + "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,mgmt->frame_control, + mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type, notif_bss_info->frame_len)); signal = notif_bss_info->rssi * 100; @@ -6284,6 +6337,7 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, struct station_info sinfo; #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !WL_CFG80211_STA_EVENT */ + WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason)); /* if link down, bsscfg is disabled. */ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) { @@ -6465,7 +6519,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, } else { if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) { printk("wl_bss_connect_done succeeded with " MACDBG "\n", - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); wl_bss_connect_done(wl, ndev, e, data, true); WL_DBG(("joined in BSS network \"%s\"\n", ((struct wlc_ssid *) @@ -6496,11 +6550,11 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, printk("link down if %s may call cfg80211_disconnected. " "event : %d, reason=%d from " MACDBG "\n", ndev->name, event, ntoh32(e->reason), - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) { WL_ERR(("BSSID of event is not the connected BSSID" "(ignore it) cur: " MACDBG " event: " MACDBG"\n", - STR_TO_MACD(curbssid), STR_TO_MACD((u8*)(&e->addr)))); + MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr)))); return 0; } wl_clr_drv_status(wl, CONNECTED, ndev); @@ -6696,7 +6750,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, } } -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 roam_done_flag) +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) { struct cfg80211_bss *bss; struct wl_bss_info *bi; @@ -6706,6 +6760,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 ro s32 dtim_period; size_t ie_len; u8 *ie; + u8 *ssidie; u8 *curbssid; s32 err = 0; struct wiphy *wiphy; @@ -6736,7 +6791,14 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 ro err = -EIO; goto update_bss_info_out; } - err = wl_inform_single_bss(wl, bi, roam_done_flag); + + ie = ((u8 *)bi) + bi->ie_offset; + ie_len = bi->ie_length; + ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie, ie_len); + if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0]) + memcpy(ssidie + 2, bi->SSID, bi->SSID_len); + + err = wl_inform_single_bss(wl, bi); if (unlikely(err)) goto update_bss_info_out; @@ -6787,10 +6849,10 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev, 1); + wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); printk("wl_bss_roaming_done succeeded to " MACDBG "\n", - STR_TO_MACD((u8*)(&e->addr))); + MAC2STRDBG((u8*)(&e->addr))); cfg80211_roamed(ndev, @@ -6822,6 +6884,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); if (!sec) { WL_ERR(("sec is NULL\n")); + return -ENODEV; } WL_DBG((" enter\n")); #ifdef ESCAN_RESULT_PATCH @@ -6854,7 +6917,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev, 0); + wl_update_bss_info(wl, ndev); wl_update_pmklist(ndev, wl->pmk_list, err); wl_set_drv_status(wl, CONNECTED, ndev); #ifdef ROAM_AP_ENV_DETECTION @@ -6902,6 +6965,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")); + +#ifndef WL_SCHED_SCAN + mutex_lock(&wl->usr_sync); + /* TODO: Use cfg80211_sched_scan_results(wiphy); */ + cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); + mutex_unlock(&wl->usr_sync); +#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 */ + 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) @@ -7173,7 +7258,9 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr", NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync); - wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false); + if (err < 0) + WL_ERR(("WLC_GET_BSSID error %d\n", err)); memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN); err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid, &mgmt_frame, &mgmt_frame_len, @@ -7836,13 +7923,13 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); dev = ndev; } - if (fw_abort) { + 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 if (!in_atomic()) { + } 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) { @@ -7970,7 +8057,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, s32 channel = CHSPEC_CHANNEL( wl_chspec_driver_to_host(bi->chanspec)); WL_DBG(("ACTION FRAME SCAN : Peer " MACDBG " found, channel : %d\n", - STR_TO_MACD(wl->afx_hdl->tx_dst_addr.octet), channel)); + MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), channel)); wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -7991,6 +8078,10 @@ static s32 wl_escan_handler(struct wl_priv *wl, #else if (p2p_is_on(wl) && p2p_scan(wl)) { #endif +#ifdef WL_HOST_BAND_MGMT + s32 channel = 0; + s32 channel_band = 0; +#endif /* WL_HOST_BAND_MGMT */ /* p2p scan && allow only probe response */ if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) goto exit; @@ -8000,6 +8091,20 @@ static s32 wl_escan_handler(struct wl_priv *wl, " response/beacon\n")); goto exit; } +#ifdef WL_HOST_BAND_MGMT + channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec)); + channel_band = (channel > CH_MAX_2G_CHANNEL) ? + WLC_BAND_5G : WLC_BAND_2G; + + + if ((wl->curr_band == WLC_BAND_5G) && + (channel_band == WLC_BAND_2G)) { + /* Avoid sending the GO results in band conflict */ + if (wl_cfgp2p_retreive_p2pattrib(p2p_ie, + P2P_SEID_GROUP_ID) != NULL) + goto exit; + } +#endif /* WL_HOST_BAND_MGMT */ } for (i = 0; i < list->count; i++) { bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) @@ -8020,7 +8125,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d" " flags 0x%x, new: RSSI %d flags 0x%x\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), i, + bss->SSID, MAC2STRDBG(bi->BSSID.octet), i, bss->RSSI, bss->flags, bi->RSSI, bi->flags)); if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == @@ -8030,7 +8135,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, */ WL_SCAN(("%s("MACDBG"), same onchan" ", RSSI: prev %d new %d\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); bi->RSSI = MAX(bss->RSSI, bi->RSSI); } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) && @@ -8040,7 +8145,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, */ WL_SCAN(("%s("MACDBG"), prev onchan" ", RSSI: prev %d new %d\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), bss->RSSI, bi->RSSI)); bi->RSSI = bss->RSSI; bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL; @@ -8052,7 +8157,7 @@ static s32 wl_escan_handler(struct wl_priv *wl, " is occured(bcast:%d->probresp%d)\n", bss->ie_length, bi->ie_length)); WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n", - bss->SSID, STR_TO_MACD(bi->BSSID.octet), + bss->SSID, MAC2STRDBG(bi->BSSID.octet), prev_len, bi_length)); if (list->buflen - prev_len + bi_length @@ -8249,6 +8354,8 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in WL_ERR(("error" " (%d)\n", err)); break; + } else { + wl_cfg80211_update_power_mode(iter->ndev); } } if (connected_cnt > 1) { @@ -8316,6 +8423,8 @@ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_in WL_ERR(("error" " (%d)\n", err)); break; + } else { + wl_cfg80211_update_power_mode(iter->ndev); } } } @@ -8476,7 +8585,11 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) return -ENODEV; } wl = wlcfg_drv_priv; - if (wl && !wl_get_drv_status(wl, READY, ndev)) { + if (unlikely(!wl)) { + WL_ERR(("wl is invaild\n")); + return -EINVAL; + } + if (!wl_get_drv_status(wl, READY, ndev)) { if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) { #if !defined(WL_ENABLE_P2P_IF) @@ -8494,7 +8607,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) wl->p2p_net->dev_addr[0] |= 0x02; WL_ERR(("%s: p2p_dev_addr="MACDBG "\n", wl->p2p_net->name, - STR_TO_MACD(wl->p2p_net->dev_addr))); + MAC2STRDBG(wl->p2p_net->dev_addr))); } else { WL_ERR(("p2p_net not yet populated." " Couldn't update the MAC Address for p2p0 \n")); @@ -8504,8 +8617,7 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev) wl->p2p_supported = true; } - } else - return -ENODEV; + } wl_set_drv_status(wl, READY, ndev); fail: return err; @@ -8866,7 +8978,8 @@ s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add) s8 eventmask[WL_EVENTING_MASK_LEN]; s32 err = 0; - + if (!ndev) + return -ENODEV; /* Setup event_msgs */ bcm_mkiovar("event_msgs", NULL, 0, iovbuf, sizeof(iovbuf)); @@ -9106,6 +9219,8 @@ s32 wl_update_wiphybands(struct wl_priv *wl) 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; + /* An HT shall support all EQM rates for one spatial stream */ + wiphy->bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; } } @@ -9140,6 +9255,15 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) err = dhd_monitor_init(wl->pub); err = wl_invoke_iscan(wl); + +#ifdef WL_HOST_BAND_MGMT + /* By default the curr_band is initialized to BAND_AUTO */ + if (wl_cfg80211_set_band(ndev, WLC_BAND_AUTO) < 0) { + WL_ERR(("roam_band set failed\n")); + err = -1; + } +#endif /* WL_HOST_BAND_MGMT */ + wl_set_drv_status(wl, READY, ndev); return err; } @@ -9159,6 +9283,7 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ + for_each_ndev(wl, iter, next) wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); @@ -9182,14 +9307,10 @@ 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 #if !defined(CUSTOMER_HW4) - if ((p2p_net) && (p2p_net->flags & IFF_UP)) { - /* p2p0 interface is still UP. Bring it down */ - p2p_net->flags &= ~IFF_UP; - } + if (p2p_net) + dev_close(p2p_net); #endif -#endif /* WL_ENABLE_P2P_IF */ DNGL_FUNC(dhd_cfg80211_down, (wl)); wl_flush_eq(wl); wl_link_down(wl); @@ -9227,14 +9348,15 @@ s32 wl_cfg80211_up(void *para) mutex_lock(&wl->usr_sync); dhd = (dhd_pub_t *)(wl->pub); - if ((dhd->op_mode & HOSTAPD_MASK) != HOSTAPD_MASK) { - wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); + if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) { + err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl)); + if (unlikely(err)) + return err; } err = __wl_cfg80211_up(wl); - if (err) + if (unlikely(err)) WL_ERR(("__wl_cfg80211_up failed\n")); mutex_unlock(&wl->usr_sync); - return err; } @@ -9768,3 +9890,16 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s return err; } #endif /* WL11U */ + +static s32 +wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, u64 cookie) +{ + /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION + * is passed with CMD_FRAME. This callback is supposed to cancel + * the OFFCHANNEL Wait. Since we are already taking care of that + * with the tx_mgmt logic, do nothing here. + */ + + return 0; +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index a712617..35a4f05 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.h 357867 2012-09-20 06:57:44Z $ + * $Id: wl_cfg80211.h 358186 2012-09-21 14:36:14Z $ */ #ifndef _wl_cfg80211_h_ @@ -156,9 +156,11 @@ do { \ #define WL_MIN_DWELL_TIME 100 #define WL_LONG_DWELL_TIME 1000 #define IFACE_MAX_CNT 2 -#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 -#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 -#define WL_AF_TX_MAX_RETRY 5 +#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 +#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 +#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 +#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 +#define WL_AF_TX_MAX_RETRY 5 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ #define WL_CHANNEL_SYNC_RETRY 5 @@ -577,6 +579,13 @@ struct wl_priv { u8 iw_ie[IW_IES_MAX_BUF_LEN]; u32 iw_ie_len; #endif /* WL11U */ + bool sched_scan_running; /* scheduled scan req status */ +#ifdef WL_SCHED_SCAN + struct cfg80211_sched_scan_request *sched_scan_req; /* scheduled scan req */ +#endif /* WL_SCHED_SCAN */ +#ifdef WL_HOST_BAND_MGMT + u8 curr_band; +#endif /* WL_HOST_BAND_MGMT */ }; @@ -839,4 +848,6 @@ extern s32 wl_cfg80211_if_is_group_owner(void); extern chanspec_t wl_ch_host_to_driver(u16 channel); extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); extern void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev); +extern s32 wl_cfg80211_set_band(struct net_device *ndev, int band); +extern int wl_cfg80211_update_power_mode(struct net_device *dev); #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index a0f113e..7a9cbea 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.c 357864 2012-09-20 06:41:42Z $ + * $Id: wl_cfgp2p.c 358702 2012-09-25 06:48:56Z $ * */ #include <typedefs.h> @@ -409,7 +409,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); CFGP2P_DBG(("---wl p2p_ifadd "MACDBG" %s %u\n", - STR_TO_MACD(ifreq.addr.octet), + MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT)); @@ -438,7 +438,7 @@ wl_cfgp2p_ifdisable(struct wl_priv *wl, struct ether_addr *mac) struct net_device *netdev = wl_to_prmry_ndev(wl); CFGP2P_INFO(("------primary idx %d : wl p2p_ifdis "MACDBG"\n", - netdev->ifindex, STR_TO_MACD(mac->octet))); + netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { @@ -459,7 +459,7 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac) struct net_device *netdev = wl_to_prmry_ndev(wl); CFGP2P_INFO(("------primary idx %d : wl p2p_ifdel "MACDBG"\n", - netdev->ifindex, STR_TO_MACD(mac->octet))); + netdev->ifindex, MAC2STRDBG(mac->octet))); ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); if (unlikely(ret < 0)) { @@ -488,7 +488,7 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type, memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet)); CFGP2P_INFO(("---wl p2p_ifchange "MACDBG" %s %u" - " chanspec 0x%04x\n", STR_TO_MACD(ifreq.addr.octet), + " chanspec 0x%04x\n", MAC2STRDBG(ifreq.addr.octet), (if_type == WL_P2P_IF_GO) ? "go" : "client", (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT, ifreq.chspec)); @@ -520,7 +520,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index) u8 getbuf[64]; struct net_device *dev = wl_to_prmry_ndev(wl); - CFGP2P_INFO(("---wl p2p_if "MACDBG"\n", STR_TO_MACD(mac->octet))); + CFGP2P_INFO(("---wl p2p_if "MACDBG"\n", MAC2STRDBG(mac->octet))); ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac), getbuf, sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY), NULL); @@ -1698,11 +1698,6 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, CFGP2P_INFO(("channel : %u , dwell time : %u\n", af_params->channel, af_params->dwell_time)); -#if defined(CONFIG_MACH_M3_JPN_DCM) - if (!wl) - return BCME_ERROR; -#endif - wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); wl_clr_p2p_status(wl, ACTION_TX_NOACK); #define MAX_WAIT_TIME 2000 @@ -2047,10 +2042,16 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int } if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { +#ifdef SUPPORT_PM2_ONLY + if (legacy_ps == PM_MAX) + legacy_ps = PM_FAST; +#endif ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); if (unlikely(ret)) { CFGP2P_ERR(("error (%d)\n", ret)); + } else { + wl_cfg80211_update_power_mode(ndev); } } else @@ -2301,21 +2302,22 @@ 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) { + extern struct wl_priv *wlcfg_drv_priv; struct wireless_dev *wdev = net->ieee80211_ptr; - - if (!wdev) + struct wl_priv *wl = NULL; + wl = wlcfg_drv_priv; + if (!wdev || !wl || !wl->p2p) return -EINVAL; - + WL_TRACE(("Enter\n")); /* 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)); + wl_cfg80211_do_driver_init(net); return 0; } @@ -2346,10 +2348,5 @@ static int wl_cfgp2p_if_stop(struct net_device *net) wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes) & (~(BIT(NL80211_IFTYPE_P2P_CLIENT)| BIT(NL80211_IFTYPE_P2P_GO))); -#if defined(CUSTOMER_HW4) - if (net->flags & IFF_UP) - net->flags &= ~IFF_UP; -#endif - return 0; } diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 808e576..31b8dab 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.h 354184 2012-08-30 08:08:08Z $ + * $Id: wl_cfgp2p.h 358702 2012-09-25 06:48:56Z $ */ #ifndef _wl_cfgp2p_h_ #define _wl_cfgp2p_h_ @@ -46,7 +46,7 @@ typedef enum { /* vendor ies max buffer length for probe response or beacon */ #define VNDR_IES_MAX_BUF_LEN 1400 /* normal vendor ies buffer length */ -#define VNDR_IES_BUF_LEN 512 +#define VNDR_IES_BUF_LEN 512 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ struct p2p_saved_ie { @@ -299,6 +299,9 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); #define SOCIAL_CHAN_1 1 #define SOCIAL_CHAN_2 6 #define SOCIAL_CHAN_3 11 +#define IS_P2P_SOCIAL_CHANNEL(channel) ((channel == SOCIAL_CHAN_1) || \ + (channel == SOCIAL_CHAN_2) || \ + (channel == SOCIAL_CHAN_3)) #define SOCIAL_CHAN_CNT 3 #define AF_PEER_SEARCH_CNT 2 #define WL_P2P_WILDCARD_SSID "DIRECT-" diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c index ef51480..8e0ed4d 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.c +++ b/drivers/net/wireless/bcmdhd/wldev_common.c @@ -327,7 +327,7 @@ int wldev_set_band( int error = -1; if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { - error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), 1); + error = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true); if (!error) dhd_bus_band_set(dev, band); } @@ -353,7 +353,7 @@ int wldev_set_country( if ((error < 0) || (strncmp(country_code, smbuf, WLC_CNTRY_BUF_SZ) != 0)) { bzero(&scbval, sizeof(scb_val_t)); - error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), 1); + error = wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true); if (error < 0) { WLDEV_ERROR(("%s: set country failed due to Disassoc error %d\n", __FUNCTION__, error)); |