diff options
54 files changed, 2407 insertions, 3075 deletions
diff --git a/bcm4329/src/GNUmakefile.inc b/bcm4329/src/GNUmakefile.inc index 3ca3bdd..ae08afe 100644 --- a/bcm4329/src/GNUmakefile.inc +++ b/bcm4329/src/GNUmakefile.inc @@ -4,7 +4,7 @@ # and sources(windows style makefile). it doesn't depend on # Makerules.env except to get SRCBASE if not yet defined. # -# $Id: GNUmakefile.inc,v 1.103.50.1 2009/05/20 19:39:45 Exp $ +# $Id: GNUmakefile.inc,v 1.103.50.2 2009/08/18 18:42:30 Exp $ SHELL=bash export SHELL @@ -540,11 +540,15 @@ define calculate_dependencies | sed '\''s?$*\.o[ :]*?$@ &?g'\'' >$@' endef +# OTHER_SOURCES_PROCESSED removes recursive build of OTHER_SOURCES, when that +# switch is set from cmd line ifdef OTHER_SOURCES +ifndef OTHER_SOURCES_PROCESSED all clean :: $(OTHER_SOURCES) @echo "Go through OTHER_SOURCES: $(OTHER_SOURCES)" - $(foreach SRCFILE,$(OTHER_SOURCES),$(MAKE) SRCFILE=$(SRCFILE) TTYPE=$(TTYPE) $@; ) -endif + $(foreach SRCFILE,$(OTHER_SOURCES),$(MAKE) SRCFILE=$(SRCFILE) TTYPE=$(TTYPE) OTHER_SOURCES_PROCESSED=true $@; ) +endif # OTHER_SOURCES_PROCESSED +endif # OTHER_SOURCES vpath %.Lib $(LIBVPATH) vpath %.LIB $(LIBVPATH) diff --git a/bcm4329/src/Makerules.env b/bcm4329/src/Makerules.env index dbe4c39..189f053 100644 --- a/bcm4329/src/Makerules.env +++ b/bcm4329/src/Makerules.env @@ -59,7 +59,7 @@ endif export TARGETENV # TARGETOS defaults to HOSTOS in most cases -ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "linuxarm_omap" "linuxmips" "sun4" "cygwin32" "win32" "macos"), ) +ifneq ($(findstring "$(TARGETENV)", "freebsd" "linux" "linuxarm" "linuxarm_le" "android" "linuxmips" "sun4" "cygwin32" "win32" "macos"), ) TARGETOS = $(HOSTOS) endif ifeq ($(TARGETENV), bcmmips) @@ -91,9 +91,6 @@ ifndef TARGETARCH ifneq ($(findstring "$(TARGETENV)", "linuxarm" "nucleusarm"), ) TARGETARCH = arm endif - ifneq ($(findstring "$(TARGETENV)", "linuxarm_omap"), ) - TARGETARCH = arm_omap - endif ifneq ($(findstring "$(TARGETENV)", "bcmmips" "linuxmips"), ) TARGETARCH = mips endif diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh.c b/bcm4329/src/bcmsdio/sys/bcmsdh.c index 68295ba..4c62610 100644 --- a/bcm4329/src/bcmsdio/sys/bcmsdh.c +++ b/bcm4329/src/bcmsdio/sys/bcmsdh.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.8 2009/06/09 00:58:13 Exp $ + * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.11 2009/10/20 09:48:20 Exp $ */ /* ****************** BCMSDH Interface Functions *************************** */ @@ -55,6 +55,19 @@ struct bcmsdh_info /* local copy of bcm sd handler */ bcmsdh_info_t * l_bcmsdh = NULL; +#if defined(OOB_INTR_ONLY) && defined(HW_OOB) + +extern int +sdioh_enable_hw_oob_intr(void *sdioh, bool enable); + +void +bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable) +{ + sdioh_enable_hw_oob_intr(sdh->sdioh, enable); +} + +#endif + bcmsdh_info_t * bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq) { @@ -89,14 +102,11 @@ bcmsdh_detach(osl_t *osh, void *sdh) { bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - ASSERT(bcmsdh); - - if (bcmsdh->sdioh) { - sdioh_detach(osh, bcmsdh->sdioh); - bcmsdh->sdioh = NULL; - } - - if (bcmsdh) { + if (bcmsdh != NULL) { + if (bcmsdh->sdioh) { + sdioh_detach(osh, bcmsdh->sdioh); + bcmsdh->sdioh = NULL; + } MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t)); } @@ -288,7 +298,7 @@ bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length) uint8 *tmp_buf, *tmp_ptr; uint8 *ptr; bool ascii = func & ~0xf; - func &= 0xf; + func &= 0x7; if (!bcmsdh) bcmsdh = l_bcmsdh; @@ -341,7 +351,7 @@ bcmsdh_reg_read(void *sdh, uint32 addr, uint size) { bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; SDIOH_API_RC status; - uint32 word; + uint32 word = 0; uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr)); diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c index 81b15b6..8ddffc6 100644 --- a/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c +++ b/bcm4329/src/bcmsdio/sys/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c,v 1.42.10.10.2.6 2009/04/10 19:13:00 Exp $ + * $Id: bcmsdh_linux.c,v 1.42.10.10.2.8 2009/10/15 22:48:28 Exp $ */ /** @@ -41,6 +41,13 @@ #include <bcmdefs.h> #include <bcmdevs.h> +#if defined(OOB_INTR_ONLY) +#include <linux/irq.h> +extern void dhdsdio_isr(void * args); +#include <bcmutils.h> +#include <dngl_stats.h> +#include <dhd.h> +#endif /* defined(OOB_INTR_ONLY) */ #if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270) #if !defined(BCMPLATFORM_BUS) #define BCMPLATFORM_BUS @@ -67,6 +74,7 @@ struct bcmsdh_hc { void *regs; /* SDIO Host Controller address */ bcmsdh_info_t *sdh; /* SDIO Host Controller handle */ void *ch; + unsigned int oob_irq; }; static bcmsdh_hc_t *sdhcinfo = NULL; @@ -176,6 +184,13 @@ int bcmsdh_probe(struct device *dev) return -ENXIO; #endif /* BCMLXSDMMC */ +#if defined(OOB_INTR_ONLY) + irq = dhd_customer_oob_irq_map(); + if (irq < 0) { + SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); + return 1; + } +#endif /* defined(OOB_INTR_ONLY) */ /* allocate SDIO Host Controller state info */ if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) { SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); @@ -206,7 +221,11 @@ int bcmsdh_probe(struct device *dev) } #endif /* BCMLXSDMMC */ sdhc->sdh = sdh; + sdhc->oob_irq = irq; + /* chain SDIO Host Controller info together */ + sdhc->next = sdhcinfo; + sdhcinfo = sdhc; /* Read the vendor/device ID from the CIS */ vendevid = bcmsdh_query_device(sdh); @@ -218,10 +237,6 @@ int bcmsdh_probe(struct device *dev) goto err; } - /* chain SDIO Host Controller info together */ - sdhc->next = sdhcinfo; - sdhcinfo = sdhc; - return 0; /* error handling */ @@ -244,6 +259,9 @@ int bcmsdh_remove(struct device *dev) bcmsdh_hc_t *sdhc, *prev; osl_t *osh; + sdhc = sdhcinfo; + drvinfo.detach(sdhc->ch); + bcmsdh_detach(sdhc->osh, sdhc->sdh); /* find the SDIO Host Controller state for this pdev and take it out from the list */ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { if (sdhc->dev == (void *)dev) { @@ -260,9 +278,6 @@ int bcmsdh_remove(struct device *dev) return 0; } - drvinfo.detach(sdhc->ch); - - bcmsdh_detach(sdhc->osh, sdhc->sdh); /* release SDIO Host Controller info */ osh = sdhc->osh; @@ -516,6 +531,63 @@ bcmsdh_unregister(void) #endif /* BCMPLATFORM_BUS */ } +#if defined(OOB_INTR_ONLY) +static irqreturn_t wlan_oob_irq(int irq, void *dev_id) +{ + dhd_pub_t *dhdp; + + dhdp = (dhd_pub_t *)sdhcinfo->dev->driver_data; + + if (dhdp == NULL) { + disable_irq(sdhcinfo->oob_irq); + SDLX_MSG(("Out of band GPIO interrupt fired way too early\n")); + return IRQ_HANDLED; + } + + WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25); + + dhdsdio_isr((void *)dhdp->bus); + + return IRQ_HANDLED; +} + +int bcmsdh_register_oob_intr(void * dhdp) +{ + int error = 0; + + SDLX_MSG(("%s Enter\n", __FUNCTION__)); + + sdhcinfo->dev->driver_data = dhdp; + + set_irq_wake(sdhcinfo->oob_irq, 1); + + /* Refer to customer Host IRQ docs about proper irqflags definition */ + error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, IRQF_TRIGGER_FALLING, + "bcmsdh_sdmmc", NULL); + + if (error) + return -ENODEV; + + return 0; +} + +void bcmsdh_unregister_oob_intr(void) +{ + SDLX_MSG(("%s: Enter\n", __FUNCTION__)); + + set_irq_wake(sdhcinfo->oob_irq, 0); + disable_irq(sdhcinfo->oob_irq); /* just in case.. */ + free_irq(sdhcinfo->oob_irq, NULL); +} + +void bcmsdh_oob_intr_set(bool enable) +{ + if (enable) + enable_irq(sdhcinfo->oob_irq); + else + disable_irq(sdhcinfo->oob_irq); +} +#endif /* defined(OOB_INTR_ONLY) */ /* Module parameters specific to each host-controller driver */ extern uint sd_msglevel; /* Debug message level */ diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c index 9f75672..a13a35c 100644 --- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c +++ b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.19 2009/06/09 00:57:07 Exp $ + * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.27 2009/10/28 19:42:29 Exp $ */ #include <typedefs.h> @@ -35,10 +35,16 @@ #include <sdiovar.h> /* ioctl/iovars */ #include <linux/mmc/core.h> -#include <linux/mmc/card.h> #include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_ids.h> +#include <dngl_stats.h> +#include <dhd.h> + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) +#include <linux/suspend.h> +extern volatile bool dhd_mmc_suspend; +#endif #include "bcmsdh_sdmmc.h" #ifndef BCMSDH_MODULE @@ -46,8 +52,10 @@ extern int sdio_function_init(void); extern void sdio_function_cleanup(void); #endif /* BCMSDH_MODULE */ +#if !defined(OOB_INTR_ONLY) static void IRQHandler(struct sdio_func *func); static void IRQHandlerF2(struct sdio_func *func); +#endif static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); extern int sdio_reset_comm(struct mmc_card *card); @@ -63,22 +71,15 @@ uint sd_clock = 1; /* Default to SD Clock turned ON */ uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */ uint sd_msglevel = 0x01; uint sd_use_dma = TRUE; +DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); +DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); +DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); +DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); #define DMA_ALIGN_MASK 0x03 int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); - -void SDIO_CLAIM_HOST(uint32 func) -{ - sdio_claim_host(gInstance->func[func]); -} - -void SDIO_RELEASE_HOST(uint32 func) -{ - sdio_release_host(gInstance->func[func]); -} - static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) { @@ -105,10 +106,9 @@ sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); /* Enable Function 1 */ - gInstance->host_claimed = 0; - SDIO_CLAIM_HOST(1); + sdio_claim_host(gInstance->func[1]); err_ret = sdio_enable_func(gInstance->func[1]); - SDIO_RELEASE_HOST(1); + sdio_release_host(gInstance->func[1]); if (err_ret) { sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret)); } @@ -152,7 +152,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) gInstance->sd = sd; /* Claim host controller */ - SDIO_CLAIM_HOST(1); + sdio_claim_host(gInstance->func[1]); sd->client_block_size[1] = 64; err_ret = sdio_set_block_size(gInstance->func[1], 64); @@ -161,11 +161,11 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) } /* Release host controller F1 */ - SDIO_RELEASE_HOST(1); + sdio_release_host(gInstance->func[1]); if (gInstance->func[2]) { /* Claim host controller F2 */ - SDIO_CLAIM_HOST(2); + sdio_claim_host(gInstance->func[2]); sd->client_block_size[2] = sd_f2_blocksize; err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); @@ -175,7 +175,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) } /* Release host controller F2 */ - SDIO_RELEASE_HOST(2); + sdio_release_host(gInstance->func[2]); } sdioh_sdmmc_card_enablefuncs(sd); @@ -193,14 +193,14 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd) if (sd) { /* Disable Function 2 */ - SDIO_CLAIM_HOST(2); + sdio_claim_host(gInstance->func[2]); sdio_disable_func(gInstance->func[2]); - SDIO_RELEASE_HOST(2); + sdio_release_host(gInstance->func[2]); /* Disable Function 1 */ - SDIO_CLAIM_HOST(1); + sdio_claim_host(gInstance->func[1]); sdio_disable_func(gInstance->func[1]); - SDIO_RELEASE_HOST(1); + sdio_release_host(gInstance->func[1]); /* deregister irq */ sdioh_sdmmc_osfree(sd); @@ -210,6 +210,67 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd) return SDIOH_API_RC_SUCCESS; } +#if defined(OOB_INTR_ONLY) && defined(HW_OOB) +#define _SDIO_CCCR_IENx 0x04 /* Function/Master Interrupt Enable */ + +extern SDIOH_API_RC +sdioh_enable_func_intr(uint32 func) +{ + uint8 reg; + int err; + + if (gInstance->func[0]) { + sdio_claim_host(gInstance->func[0]); + reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err); + if (err) { + sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); + sdio_release_host(gInstance->func[0]); + return SDIOH_API_RC_FAIL; + } + reg |= 1 << func; /* enable function-x interrupt */ + reg |= 1; /* Master interrupt enable */ + sdio_writeb(gInstance->func[0], reg, _SDIO_CCCR_IENx, &err); + sdio_release_host(gInstance->func[0]); + if (err) { + sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); + return SDIOH_API_RC_FAIL; + } + } + + return SDIOH_API_RC_SUCCESS; + +} + +extern SDIOH_API_RC +sdioh_disable_func_intr(uint32 func) +{ + uint8 reg; + int err; + + if (gInstance->func[0]) { + sdio_claim_host(gInstance->func[0]); + reg = sdio_readb(gInstance->func[0], _SDIO_CCCR_IENx, &err); + if (err) { + sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); + sdio_release_host(gInstance->func[0]); + return SDIOH_API_RC_FAIL; + } + reg &= ~(1 << func); + /* Disable master interrupt with the last function interrupt */ + if (!(reg & 0xFE)) + reg = 0; + sdio_writeb(gInstance->func[0], reg, _SDIO_CCCR_IENx, &err); + sdio_release_host(gInstance->func[0]); + if (err) { + sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); + return SDIOH_API_RC_FAIL; + } + } + return SDIOH_API_RC_SUCCESS; + +} +#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ + /* Configure callback to client when we recieve client interrupt */ extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) @@ -219,22 +280,26 @@ sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__)); return SDIOH_API_RC_FAIL; } +#if !defined(OOB_INTR_ONLY) sd->intr_handler = fn; sd->intr_handler_arg = argh; sd->intr_handler_valid = TRUE; /* register and unmask irq */ if (gInstance->func[2]) { - SDIO_CLAIM_HOST(2); + sdio_claim_host(gInstance->func[2]); sdio_claim_irq(gInstance->func[2], IRQHandlerF2); - SDIO_RELEASE_HOST(2); + sdio_release_host(gInstance->func[2]); } if (gInstance->func[1]) { - SDIO_CLAIM_HOST(1); + sdio_claim_host(gInstance->func[1]); sdio_claim_irq(gInstance->func[1], IRQHandler); - SDIO_RELEASE_HOST(1); + sdio_release_host(gInstance->func[1]); } +#elif defined(HW_OOB) + sdioh_enable_func_intr(2); +#endif /* defined(OOB_INTR_ONLY) */ return SDIOH_API_RC_SUCCESS; } @@ -243,24 +308,28 @@ sdioh_interrupt_deregister(sdioh_info_t *sd) { sd_trace(("%s: Entering\n", __FUNCTION__)); +#if !defined(OOB_INTR_ONLY) if (gInstance->func[1]) { /* register and unmask irq */ - SDIO_CLAIM_HOST(1); + sdio_claim_host(gInstance->func[1]); sdio_release_irq(gInstance->func[1]); - SDIO_RELEASE_HOST(1); + sdio_release_host(gInstance->func[1]); } if (gInstance->func[2]) { /* Claim host controller F2 */ - SDIO_CLAIM_HOST(2); + sdio_claim_host(gInstance->func[2]); sdio_release_irq(gInstance->func[2]); /* Release host controller F2 */ - SDIO_RELEASE_HOST(2); + sdio_release_host(gInstance->func[2]); } sd->intr_handler_valid = FALSE; sd->intr_handler = NULL; sd->intr_handler_arg = NULL; +#elif defined(HW_OOB) + sdioh_disable_func_intr(2); +#endif /* !defined(OOB_INTR_ONLY) */ return SDIOH_API_RC_SUCCESS; } @@ -591,6 +660,25 @@ exit: return bcmerror; } +#if defined(OOB_INTR_ONLY) && defined(HW_OOB) + +SDIOH_API_RC +sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) +{ + SDIOH_API_RC status; + uint8 data; + + if (enable) + data = 3; /* enable hw oob interrupt */ + else + data = 4; /* disable hw oob interrupt */ + + status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data); + return status; +} +#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ + + extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) { @@ -669,6 +757,8 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); + DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); + DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); if(rw) { /* CMD52 Write */ if (func == 0) { /* Can only directly write to some F0 registers. Handle F2 enable @@ -676,7 +766,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by */ if (regaddr == SDIOD_CCCR_IOEN) { if (gInstance->func[2]) { - SDIO_CLAIM_HOST(2); + sdio_claim_host(gInstance->func[2]); if (*byte & SDIO_FUNC_ENABLE_2) { /* Enable Function 2 */ err_ret = sdio_enable_func(gInstance->func[2]); @@ -692,25 +782,40 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by err_ret)); } } - SDIO_RELEASE_HOST(2); + sdio_release_host(gInstance->func[2]); } - } else if (regaddr < 0xF0) { + } +#if defined(MMC_SDIO_ABORT) + /* to allow abort command through F1 */ + else if (regaddr == SDIOD_CCCR_IOABORT) { + 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_f0_writeb(gInstance->func[func], *byte, + regaddr, &err_ret); + sdio_release_host(gInstance->func[func]); + } +#endif /* MMC_SDIO_ABORT */ + else if (regaddr < 0xF0) { sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr)); } else { /* Claim host controller, perform F0 write, and release */ - SDIO_CLAIM_HOST(func); + sdio_claim_host(gInstance->func[func]); sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - SDIO_RELEASE_HOST(func); + sdio_release_host(gInstance->func[func]); } } else { /* Claim host controller, perform Fn write, and release */ - SDIO_CLAIM_HOST(func); + sdio_claim_host(gInstance->func[func]); sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - SDIO_RELEASE_HOST(func); + sdio_release_host(gInstance->func[func]); } } else { /* CMD52 Read */ /* Claim host controller, perform Fn read, and release */ - SDIO_CLAIM_HOST(func); + sdio_claim_host(gInstance->func[func]); if (func == 0) { *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret); @@ -718,7 +823,7 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret); } - SDIO_RELEASE_HOST(func); + sdio_release_host(gInstance->func[func]); } if (err_ret) { @@ -733,7 +838,7 @@ extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, uint32 *word, uint nbytes) { - int err_ret; + int err_ret = SDIOH_API_RC_FAIL; if (func == 0) { sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); @@ -743,8 +848,10 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", __FUNCTION__, cmd_type, rw, func, addr, nbytes)); + DHD_PM_RESUME_WAIT(sdioh_request_word_wait); + DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); /* Claim host controller */ - SDIO_CLAIM_HOST(func); + sdio_claim_host(gInstance->func[func]); if(rw) { /* CMD52 Write */ if (nbytes == 4) { @@ -765,7 +872,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add } /* Release host controller */ - SDIO_RELEASE_HOST(func); + sdio_release_host(gInstance->func[func]); if (err_ret) { sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", @@ -788,9 +895,11 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, sd_trace(("%s: Enter\n", __FUNCTION__)); ASSERT(pkt); + DHD_PM_RESUME_WAIT(sdioh_request_packet_wait); + DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); /* Claim host controller */ - SDIO_CLAIM_HOST(func); + sdio_claim_host(gInstance->func[func]); for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { uint pkt_len = PKTLEN(sd->osh, pnext); pkt_len += 3; @@ -848,7 +957,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, } /* Release host controller */ - SDIO_RELEASE_HOST(func); + sdio_release_host(gInstance->func[func]); sd_trace(("%s: Exit\n", __FUNCTION__)); return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -875,11 +984,17 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u sd_trace(("%s: Enter\n", __FUNCTION__)); + DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait); + DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); /* Case 1: we don't have a packet. */ if (pkt == NULL) { sd_data(("%s: Creating new %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", buflen_u)); +#ifdef DHD_USE_STATIC_BUF + if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) { +#else if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) { +#endif /* DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buflen_u)); return SDIOH_API_RC_FAIL; @@ -896,8 +1011,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (!write) { bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); } - +#ifdef DHD_USE_STATIC_BUF + PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); +#else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); +#endif /* DHD_USE_STATIC_BUF */ } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { /* Case 2: We have a packet, but it is unaligned. */ @@ -906,7 +1024,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u sd_data(("%s: Creating aligned %s Packet, len=%d\n", __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt))); +#ifdef DHD_USE_STATIC_BUF + if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { +#else if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { +#endif /* DHD_USE_STATIC_BUF */ sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, PKTLEN(sd->osh, pkt))); return SDIOH_API_RC_FAIL; @@ -927,8 +1049,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u PKTDATA(sd->osh, pkt), PKTLEN(sd->osh, mypkt)); } - +#ifdef DHD_USE_STATIC_BUF + PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); +#else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); +#endif /* DHD_USE_STATIC_BUF */ } else { /* case 3: We have a packet and it is aligned. */ sd_data(("%s: Aligned %s Packet, direct DMA\n", __FUNCTION__, write ? "Tx" : "Rx")); @@ -943,6 +1068,10 @@ sdioh_abort(sdioh_info_t *sd, uint func) { sd_trace(("%s: Enter\n", __FUNCTION__)); +#if defined(MMC_SDIO_ABORT) + /* issue abort cmd52 command through F1 */ + sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, &t_func); +#endif /* defined(MMC_SDIO_ABORT) */ sd_trace(("%s: Exit\n", __FUNCTION__)); return SDIOH_API_RC_SUCCESS; @@ -997,6 +1126,7 @@ sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize return SUCCESS; } +#if !defined(OOB_INTR_ONLY) /* bcmsdh_sdmmc interrupt handler */ static void IRQHandler(struct sdio_func *func) { @@ -1007,7 +1137,7 @@ static void IRQHandler(struct sdio_func *func) ASSERT(sd != NULL); sdio_release_host(gInstance->func[0]); - gInstance->host_claimed = 1; + if (sd->use_client_ints) { sd->intrcount++; ASSERT(sd->intr_handler); @@ -1019,7 +1149,6 @@ static void IRQHandler(struct sdio_func *func) sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", __FUNCTION__, sd->client_intr_enabled, sd->intr_handler)); } - gInstance->host_claimed = 0; sdio_claim_host(gInstance->func[0]); } @@ -1035,6 +1164,7 @@ static void IRQHandlerF2(struct sdio_func *func) ASSERT(sd != NULL); } +#endif /* !defined(OOB_INTR_ONLY) */ #ifdef NOTUSED /* Write client card reg */ @@ -1121,11 +1251,17 @@ sdioh_start(sdioh_info_t *si, int stage) sdioh_sdmmc_card_enablefuncs(sd); } } else { +#if !defined(OOB_INTR_ONLY) sdio_claim_host(gInstance->func[0]); sdio_claim_irq(gInstance->func[2], IRQHandlerF2); sdio_claim_irq(gInstance->func[1], IRQHandler); sdio_release_host(gInstance->func[0]); - +#else /* defined(OOB_INTR_ONLY) */ +#if defined(HW_OOB) + sdioh_enable_func_intr(2); +#endif + bcmsdh_oob_intr_set(TRUE); +#endif /* !defined(OOB_INTR_ONLY) */ } } else @@ -1144,10 +1280,17 @@ sdioh_stop(sdioh_info_t *si) polling */ if (gInstance->func[0]) { +#if !defined(OOB_INTR_ONLY) sdio_claim_host(gInstance->func[0]); sdio_release_irq(gInstance->func[1]); sdio_release_irq(gInstance->func[2]); sdio_release_host(gInstance->func[0]); +#else /* defined(OOB_INTR_ONLY) */ +#if defined(HW_OOB) + sdioh_disable_func_intr(2); +#endif + bcmsdh_oob_intr_set(FALSE); +#endif /* !defined(OOB_INTR_ONLY) */ } else sd_err(("%s Failed\n", __FUNCTION__)); diff --git a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c index 46fe1f9..3643d1c 100644 --- a/bcm4329/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c +++ b/bcm4329/src/bcmsdio/sys/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,v 1.1.2.5.6.7 2009/05/22 00:31:44 Exp $ + * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.10 2009/10/14 04:32:13 Exp $ */ #include <typedefs.h> @@ -49,6 +49,9 @@ #include <bcmsdh_sdmmc.h> +#include <dhd_dbg.h> + + extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); @@ -73,6 +76,7 @@ extern int bcmsdh_probe(struct device *dev); extern int bcmsdh_remove(struct device *dev); struct device sdmmc_dev; + static int bcmsdh_sdmmc_probe(struct sdio_func *func, const struct sdio_device_id *id) { @@ -89,7 +93,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, if(func->device == 0x4) { /* 4318 */ gInstance->func[2] = NULL; sd_trace(("NIC found, calling bcmsdh_probe...\n")); - bcmsdh_probe(&sdmmc_dev); + ret = bcmsdh_probe(&sdmmc_dev); } } @@ -97,7 +101,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, if (func->num == 2) { sd_trace(("F2 found, calling bcmsdh_probe...\n")); - bcmsdh_probe(&sdmmc_dev); + ret = bcmsdh_probe(&sdmmc_dev); } return ret; @@ -165,6 +169,13 @@ sdioh_sdmmc_osfree(sdioh_info_t *sd) sdos = (struct sdos_info *)sd->sdos_info; MFREE(sd->osh, sdos, sizeof(struct sdos_info)); } +#if defined(OOB_INTR_ONLY) +int +sdioh_mmc_irq(int irq) +{ + return (MSM_GPIO_TO_INT(irq)); +} +#endif /* defined(OOB_INTR_ONLY) */ /* Interrupt enable/disable */ SDIOH_API_RC @@ -178,19 +189,22 @@ sdioh_interrupt_set(sdioh_info_t *sd, bool enable) sdos = (struct sdos_info *)sd->sdos_info; ASSERT(sdos); +#if !defined(OOB_INTR_ONLY) if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__)); return SDIOH_API_RC_FAIL; } +#endif /* !defined(OOB_INTR_ONLY) */ /* Ensure atomicity for enable/disable calls */ spin_lock_irqsave(&sdos->lock, flags); sd->client_intr_enabled = enable; - if (enable) + if (enable) { sdioh_sdmmc_devintr_on(sd); - else + } else { sdioh_sdmmc_devintr_off(sd); + } spin_unlock_irqrestore(&sdos->lock, flags); @@ -233,7 +247,10 @@ int sdio_function_init(void) if (!gInstance) return -ENOMEM; + bzero(&sdmmc_dev, sizeof(sdmmc_dev)); error = sdio_register_driver(&bcmsdh_sdmmc_driver); + + return error; } @@ -245,6 +262,7 @@ void sdio_function_cleanup(void) { sd_trace(("%s Enter\n", __FUNCTION__)); + sdio_unregister_driver(&bcmsdh_sdmmc_driver); if (gInstance) diff --git a/bcm4329/src/bcmsdio/sys/bcmsdstd.c b/bcm4329/src/bcmsdio/sys/bcmsdstd.c index 2665716..51ff4af 100644 --- a/bcm4329/src/bcmsdio/sys/bcmsdstd.c +++ b/bcm4329/src/bcmsdio/sys/bcmsdstd.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: bcmsdstd.c,v 1.64.4.1.4.4.2.10 2009/05/22 00:31:44 Exp $ + * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.14 2009/10/08 20:05:30 Exp $ */ #include <typedefs.h> @@ -35,7 +35,6 @@ #include <sdioh.h> /* SDIO Host Controller Specification */ #include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */ #include <sdiovar.h> /* ioctl/iovars */ - #include <pcicfg.h> @@ -853,9 +852,10 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint len++; tmpbuf = buffer; if ((localbuf = (uint8 *)MALLOC(sd->osh, len)) == NULL) { - sd_err(("out of memory, malloced %d bytes\n", - MALLOCED(sd->osh))); - return SDIOH_API_RC_FAIL; + sd_err(("out of memory, malloced %d bytes\n", + MALLOCED(sd->osh))); + sdstd_unlock(sd); + return SDIOH_API_RC_FAIL; } bcopy(buffer, localbuf, len); buffer = localbuf; @@ -1313,6 +1313,20 @@ sdstd_host_init(sdioh_info_t *sd) num_slots &= 7; num_slots++; /* map bits to num slots according to spec */ + if (OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) == + ((SDIOH_FPGA_ID << 16) | VENDOR_BROADCOM)) { + sd_err(("%s: Found Broadcom Standard SDIO Host Controller FPGA\n", __FUNCTION__)); + /* Set BAR0 Window to SDIOSTH core */ + OSL_PCI_WRITE_CONFIG(sd->osh, PCI_BAR0_WIN, 4, 0x18001000); + + /* Set defaults particular to this controller. */ + detect_slots = TRUE; + num_slots = 1; + first_bar = 0; + + sd->sd_blockmode = FALSE; + } + /* Map in each slot on the board and query it to see if a * card is inserted. Use the first populated slot found. */ @@ -2781,7 +2795,8 @@ sd_map_dma(sdioh_info_t * sd) { if (sd->sd_use_dma == FALSE) return; - if ((sd->dma_buf = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, &sd->dma_phys, 0x12)) == NULL) { + if ((sd->dma_buf = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, &sd->dma_phys, + 0x12, 12)) == NULL) { sd_err(("%s: DMA_ALLOC failed. Disabling DMA support.\n", __FUNCTION__)); sd->sd_use_dma = FALSE; } diff --git a/bcm4329/src/bcmsdio/sys/bcmspibrcm.c b/bcm4329/src/bcmsdio/sys/bcmspibrcm.c deleted file mode 100644 index dc6f0f5..0000000 --- a/bcm4329/src/bcmsdio/sys/bcmspibrcm.c +++ /dev/null @@ -1,1726 +0,0 @@ -/* - * Broadcom BCMSDH to gSPI Protocol Conversion Layer - * - * Copyright (C) 2009, Broadcom Corporation - * All Rights Reserved. - * - * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; - * the contents of this file may not be disclosed to third parties, copied - * or duplicated in any form, in whole or in part, without the prior - * written permission of Broadcom Corporation. - * - * $Id: bcmspibrcm.c,v 1.11.2.10.2.9.6.11 2009/05/21 13:21:57 Exp $ - */ - -#define HSMODE - -#include <typedefs.h> - -#include <bcmdevs.h> -#include <bcmendian.h> -#include <bcmutils.h> -#include <osl.h> -#include <hndsoc.h> -#include <siutils.h> -#include <sbchipc.h> -#include <sbsdio.h> -#include <spid.h> - -#include <bcmsdbus.h> /* bcmsdh to/from specific controller APIs */ -#include <sdiovar.h> /* ioctl/iovars */ -#include <sdio.h> - -#include <pcicfg.h> - - -#include <bcmspibrcm.h> -#include <bcmspi.h> - -#define F0_RESPONSE_DELAY 16 -#define F1_RESPONSE_DELAY 16 -#define F2_RESPONSE_DELAY F0_RESPONSE_DELAY - -#define CMDLEN 4 - -#define DWORDMODE_ON (sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 2) && (sd->dwordmode == TRUE) - -/* Globals */ -uint sd_msglevel = 0; - -uint sd_hiok = FALSE; /* Use hi-speed mode if available? */ -uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */ -uint sd_f2_blocksize = 64; /* Default blocksize */ - - -uint sd_divisor = 2; -uint sd_power = 1; /* Default to SD Slot powered ON */ -uint sd_clock = 1; /* Default to SD Clock turned ON */ -uint sd_crc = 0; /* Default to SPI CRC Check turned OFF */ - -uint8 spi_outbuf[SPI_MAX_PKT_LEN]; -uint8 spi_inbuf[SPI_MAX_PKT_LEN]; - -/* 128bytes buffer is enough to clear data-not-available and program response-delay F0 bits - * assuming we will not exceed F0 response delay > 100 bytes at 48MHz. - */ -#define BUF2_PKT_LEN 128 -uint8 spi_outbuf2[BUF2_PKT_LEN]; -uint8 spi_inbuf2[BUF2_PKT_LEN]; - -/* Prototypes */ -static bool bcmspi_test_card(sdioh_info_t *sd); -static bool bcmspi_host_device_init_adapt(sdioh_info_t *sd); -static int bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode); -static int bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg, - uint32 *data, uint32 datalen); -static int bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 *data); -static int bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 data); -static int bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, - uint8 *data); -static int bcmspi_driver_init(sdioh_info_t *sd); -static int bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, - uint32 addr, int nbytes, uint32 *data); -static int bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, - uint32 *data); -static void bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer); -static int bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg); - -/* - * Public entry points & extern's - */ -extern sdioh_info_t * -sdioh_attach(osl_t *osh, void *bar0, uint irq) -{ - sdioh_info_t *sd; - - sd_trace(("%s\n", __FUNCTION__)); - if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { - sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); - return NULL; - } - bzero((char *)sd, sizeof(sdioh_info_t)); - sd->osh = osh; - if (spi_osinit(sd) != 0) { - sd_err(("%s: spi_osinit() failed\n", __FUNCTION__)); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - - sd->bar0 = bar0; - sd->irq = irq; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - sd->intr_handler_valid = FALSE; - - /* Set defaults */ - sd->use_client_ints = TRUE; - sd->sd_use_dma = FALSE; /* DMA Not supported */ - - /* Spi device default is 16bit mode, change to 4 when device is changed to 32bit - * mode - */ - sd->wordlen = 2; - - if (!spi_hw_attach(sd)) { - sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__)); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - - if (bcmspi_driver_init(sd) != SUCCESS) { - sd_err(("%s: bcmspi_driver_init() failed()\n", __FUNCTION__)); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - - if (spi_register_irq(sd, irq) != SUCCESS) { - sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq)); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - - sd_trace(("%s: Done\n", __FUNCTION__)); - - return sd; -} - -extern SDIOH_API_RC -sdioh_detach(osl_t *osh, sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - if (sd) { - sd_err(("%s: detaching from hardware\n", __FUNCTION__)); - spi_free_irq(sd->irq, sd); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - } - return SDIOH_API_RC_SUCCESS; -} - -/* Configure callback to client when we recieve client interrupt */ -extern SDIOH_API_RC -sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - sd->intr_handler = fn; - sd->intr_handler_arg = argh; - sd->intr_handler_valid = TRUE; - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_deregister(sdioh_info_t *sd) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - sd->intr_handler_valid = FALSE; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - *onoff = sd->client_intr_enabled; - return SDIOH_API_RC_SUCCESS; -} - -#if defined(DHD_DEBUG) -extern bool -sdioh_interrupt_pending(sdioh_info_t *sd) -{ - return 0; -} -#endif - -extern SDIOH_API_RC -sdioh_query_device(sdioh_info_t *sd) -{ - /* Return a BRCM ID appropriate to the dongle class */ - return (sd->num_funcs > 1) ? BCM4329_D11NDUAL_ID : BCM4318_D11G_ID; -} - -/* Provide dstatus bits of spi-transaction for dhd layers. */ -extern uint32 -sdioh_get_dstatus(sdioh_info_t *sd) -{ - return sd->card_dstatus; -} - -extern void -sdioh_chipinfo(sdioh_info_t *sd, uint32 chip, uint32 chiprev) -{ - sd->chip = chip; - sd->chiprev = chiprev; -} - -extern void -sdioh_dwordmode(sdioh_info_t *sd, bool set) -{ - uint8 reg = 0; - int status; - - if ((status = sdioh_request_byte(sd, SDIOH_READ, SPI_FUNC_0, SPID_STATUS_ENABLE, ®)) != - SUCCESS) { - sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__)); - return; - } - - if (set) { - reg |= DWORD_PKT_LEN_EN; - sd->dwordmode = TRUE; - sd->client_block_size[SPI_FUNC_2] = 4096; /* h2spi's limit is 4KB, we support 8KB */ - } else { - reg &= ~DWORD_PKT_LEN_EN; - sd->dwordmode = FALSE; - sd->client_block_size[SPI_FUNC_2] = 2048; - } - - if ((status = sdioh_request_byte(sd, SDIOH_WRITE, SPI_FUNC_0, SPID_STATUS_ENABLE, ®)) != - SUCCESS) { - sd_err(("%s: Failed to set dwordmode in gSPI\n", __FUNCTION__)); - return; - } -} - - -uint -sdioh_query_iofnum(sdioh_info_t *sd) -{ - return sd->num_funcs; -} - -/* IOVar table */ -enum { - IOV_MSGLEVEL = 1, - IOV_BLOCKMODE, - IOV_BLOCKSIZE, - IOV_DMA, - IOV_USEINTS, - IOV_NUMINTS, - IOV_NUMLOCALINTS, - IOV_HOSTREG, - IOV_DEVREG, - IOV_DIVISOR, - IOV_SDMODE, - IOV_HISPEED, - IOV_HCIREGS, - IOV_POWER, - IOV_CLOCK, - IOV_SPIERRSTATS, - IOV_RESP_DELAY_ALL -}; - -const bcm_iovar_t sdioh_iovars[] = { - {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, - {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ - {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, - {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, - {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, - {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, - {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, - {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, - {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, - {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, - {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}, - {"spi_errstats", IOV_SPIERRSTATS, 0, IOVT_BUFFER, sizeof(struct spierrstats_t) }, - {"spi_respdelay", IOV_RESP_DELAY_ALL, 0, IOVT_BOOL, 0 }, - {NULL, 0, 0, 0, 0 } -}; - -int -sdioh_iovar_op(sdioh_info_t *si, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - const bcm_iovar_t *vi = NULL; - int bcmerror = 0; - int val_size; - int32 int_val = 0; - bool bool_val; - uint32 actionid; -/* - sdioh_regs_t *regs; -*/ - - ASSERT(name); - ASSERT(len >= 0); - - /* Get must have return space; Set does not take qualifiers */ - ASSERT(set || (arg && len)); - ASSERT(!set || (!params && !plen)); - - sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name)); - - if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { - bcmerror = BCME_UNSUPPORTED; - goto exit; - } - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) - goto exit; - - /* Set up params so get and set can share the convenience variables */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - val_size = sizeof(int); - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - bool_val = (int_val != 0) ? TRUE : FALSE; - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - switch (actionid) { - case IOV_GVAL(IOV_MSGLEVEL): - int_val = (int32)sd_msglevel; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MSGLEVEL): - sd_msglevel = int_val; - break; - - case IOV_GVAL(IOV_BLOCKSIZE): - if ((uint32)int_val > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - int_val = (int32)si->client_block_size[int_val]; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_DMA): - int_val = (int32)si->sd_use_dma; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DMA): - si->sd_use_dma = (bool)int_val; - break; - - case IOV_GVAL(IOV_USEINTS): - int_val = (int32)si->use_client_ints; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_USEINTS): - break; - - case IOV_GVAL(IOV_DIVISOR): - int_val = (uint32)sd_divisor; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DIVISOR): - sd_divisor = int_val; - if (!spi_start_clock(si, (uint16)sd_divisor)) { - sd_err(("%s: set clock failed\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - } - break; - - case IOV_GVAL(IOV_POWER): - int_val = (uint32)sd_power; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_POWER): - sd_power = int_val; - break; - - case IOV_GVAL(IOV_CLOCK): - int_val = (uint32)sd_clock; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_CLOCK): - sd_clock = int_val; - break; - - case IOV_GVAL(IOV_SDMODE): - int_val = (uint32)sd_sdmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDMODE): - sd_sdmode = int_val; - break; - - case IOV_GVAL(IOV_HISPEED): - int_val = (uint32)sd_hiok; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_HISPEED): - sd_hiok = int_val; - - if (!bcmspi_set_highspeed_mode(si, (bool)sd_hiok)) { - sd_err(("%s: Failed changing highspeed mode to %d.\n", - __FUNCTION__, sd_hiok)); - bcmerror = BCME_ERROR; - return ERROR; - } - break; - - case IOV_GVAL(IOV_NUMINTS): - int_val = (int32)si->intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_NUMLOCALINTS): - int_val = (int32)si->local_intrcount; - bcopy(&int_val, arg, val_size); - break; - case IOV_GVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data; - - if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - - int_val = (int)data; - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data = (uint8)sd_ptr->value; - - if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - break; - } - - - case IOV_GVAL(IOV_SPIERRSTATS): - { - bcopy(&si->spierrstats, arg, sizeof(struct spierrstats_t)); - break; - } - - case IOV_SVAL(IOV_SPIERRSTATS): - { - bzero(&si->spierrstats, sizeof(struct spierrstats_t)); - break; - } - - case IOV_GVAL(IOV_RESP_DELAY_ALL): - int_val = (int32)si->resp_delay_all; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_RESP_DELAY_ALL): - si->resp_delay_all = (bool)int_val; - int_val = STATUS_ENABLE|INTR_WITH_STATUS; - if (si->resp_delay_all) - int_val |= RESP_DELAY_ALL; - else { - if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_RESPONSE_DELAY, 1, - F1_RESPONSE_DELAY) != SUCCESS) { - sd_err(("%s: Unable to set response delay.\n", __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - break; - } - } - - if (bcmspi_card_regwrite(si, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, int_val) - != SUCCESS) { - sd_err(("%s: Unable to set response delay.\n", __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - break; - } - break; - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } -exit: - - return bcmerror; -} - -extern SDIOH_API_RC -sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - SDIOH_API_RC status; - /* No lock needed since sdioh_request_byte does locking */ - status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - /* No lock needed since sdioh_request_byte does locking */ - SDIOH_API_RC status; - - if ((fnc_num == SPI_FUNC_1) && (addr == SBSDIO_FUNC1_FRAMECTRL)) { - uint8 dummy_data; - status = sdioh_cfg_read(sd, fnc_num, addr, &dummy_data); - if (status) { - sd_err(("sdioh_cfg_read() failed.\n")); - return status; - } - } - - status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) -{ - uint32 count; - int offset; - uint32 cis_byte; - uint16 *cis = (uint16 *)cisd; - uint bar0 = SI_ENUM_BASE; - int status; - uint8 data; - - sd_trace(("%s: Func %d\n", __FUNCTION__, func)); - - spi_lock(sd); - - /* Set sb window address to 0x18000000 */ - data = (bar0 >> 8) & SBSDIO_SBADDRLOW_MASK; - status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, &data); - if (status == SUCCESS) { - data = (bar0 >> 16) & SBSDIO_SBADDRMID_MASK; - status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, &data); - } else { - sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__)); - spi_unlock(sd); - return (BCME_ERROR); - } - if (status == SUCCESS) { - data = (bar0 >> 24) & SBSDIO_SBADDRHIGH_MASK; - status = bcmspi_card_bytewrite(sd, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, &data); - } else { - sd_err(("%s: Unable to set sb-addr-windows\n", __FUNCTION__)); - spi_unlock(sd); - return (BCME_ERROR); - } - - offset = CC_OTP; /* OTP offset in chipcommon. */ - for (count = 0; count < length/2; count++) { - if (bcmspi_card_regread (sd, SDIO_FUNC_1, offset, 2, &cis_byte) < 0) { - sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__)); - spi_unlock(sd); - return (BCME_ERROR); - } - - *cis = (uint16)cis_byte; - cis++; - offset += 2; - } - - spi_unlock(sd); - - return (BCME_OK); -} - -extern SDIOH_API_RC -sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) -{ - int status; - uint32 cmd_arg; - uint32 dstatus; - uint32 data = (uint32)(*byte); - - spi_lock(sd); - - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */ - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, rw == SDIOH_READ ? 0 : 1); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, rw, func, - regaddr, data)); - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, - cmd_arg, &data, 1)) != SUCCESS) { - spi_unlock(sd); - return status; - } - - if (rw == SDIOH_READ) - *byte = (uint8)data; - - bcmspi_cmd_getdstatus(sd, &dstatus); - if (dstatus) - sd_trace(("dstatus =0x%x\n", dstatus)); - - spi_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, - uint32 *word, uint nbytes) -{ - int status; - - spi_lock(sd); - - if (rw == SDIOH_READ) - status = bcmspi_card_regread(sd, func, addr, nbytes, word); - else - status = bcmspi_card_regwrite(sd, func, addr, nbytes, *word); - - spi_unlock(sd); - return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - -extern SDIOH_API_RC -sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func, - uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) -{ - int len; - int buflen = (int)buflen_u; - bool fifo = (fix_inc == SDIOH_DATA_FIX); - - spi_lock(sd); - - ASSERT(reg_width == 4); - ASSERT(buflen_u < (1 << 30)); - ASSERT(sd->client_block_size[func]); - - sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n", - __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W', - buflen_u, sd->r_cnt, sd->t_cnt, pkt)); - - /* Break buffer down into blocksize chunks. */ - while (buflen > 0) { - len = MIN(sd->client_block_size[func], buflen); - if (bcmspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) { - sd_err(("%s: bcmspi_card_buf %s failed\n", - __FUNCTION__, rw == SDIOH_READ ? "Read" : "Write")); - spi_unlock(sd); - return SDIOH_API_RC_FAIL; - } - buffer += len; - buflen -= len; - if (!fifo) - addr += len; - } - spi_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -/* This function allows write to gspi bus when another rd/wr function is deep down the call stack. - * Its main aim is to have simpler spi writes rather than recursive writes. - * e.g. When there is a need to program response delay on the fly after detecting the SPI-func - * this call will allow to program the response delay. - */ -static int -bcmspi_card_byterewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 byte) -{ - uint32 cmd_arg; - uint32 datalen = 1; - uint32 hostlen; - - cmd_arg = 0; - - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */ - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, datalen); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - - - /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen - * according to the wordlen mode(16/32bit) the device is in. - */ - ASSERT(sd->wordlen == 4 || sd->wordlen == 2); - datalen = ROUNDUP(datalen, sd->wordlen); - - /* Start by copying command in the spi-outbuffer */ - if (sd->wordlen == 4) { /* 32bit spid */ - *(uint32 *)spi_outbuf2 = bcmswap32(cmd_arg); - if (datalen & 0x3) - datalen += (4 - (datalen & 0x3)); - } else if (sd->wordlen == 2) { /* 16bit spid */ - *(uint16 *)spi_outbuf2 = bcmswap16(cmd_arg & 0xffff); - *(uint16 *)&spi_outbuf2[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16); - if (datalen & 0x1) - datalen++; - } else { - sd_err(("%s: Host is %d bit spid, could not create SPI command.\n", - __FUNCTION__, 8 * sd->wordlen)); - return ERROR; - } - - /* for Write, put the data into the output buffer */ - if (datalen != 0) { - if (sd->wordlen == 4) { /* 32bit spid */ - *(uint32 *)&spi_outbuf2[CMDLEN] = bcmswap32(byte); - } else if (sd->wordlen == 2) { /* 16bit spid */ - *(uint16 *)&spi_outbuf2[CMDLEN] = bcmswap16(byte & 0xffff); - *(uint16 *)&spi_outbuf2[CMDLEN + 2] = - bcmswap16((byte & 0xffff0000) >> 16); - } - } - - /* +4 for cmd, +4 for dstatus */ - hostlen = datalen + 8; - hostlen += (4 - (hostlen & 0x3)); - spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, hostlen); - - /* Last 4bytes are dstatus. Device is configured to return status bits. */ - if (sd->wordlen == 4) { /* 32bit spid */ - sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]); - } else if (sd->wordlen == 2) { /* 16bit spid */ - sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) | - (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16)); - } else { - sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n", - __FUNCTION__, 8 * sd->wordlen)); - return ERROR; - } - - if (sd->card_dstatus) - sd_trace(("dstatus after byte rewrite = 0x%x\n", sd->card_dstatus)); - - return (BCME_OK); -} - -/* Program the response delay corresponding to the spi function */ -static int -bcmspi_prog_resp_delay(sdioh_info_t *sd, int func, uint8 resp_delay) -{ - if (sd->resp_delay_all == FALSE) - return (BCME_OK); - - if (sd->prev_fun == func) - return (BCME_OK); - - if (F0_RESPONSE_DELAY == F1_RESPONSE_DELAY) - return (BCME_OK); - - bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_RESPONSE_DELAY, resp_delay); - - /* Remember function for which to avoid reprogramming resp-delay in next iteration */ - sd->prev_fun = func; - - return (BCME_OK); - -} - -#define GSPI_RESYNC_PATTERN 0x0 - -/* A resync pattern is a 32bit MOSI line with all zeros. Its a special command in gSPI. - * It resets the spi-bkplane logic so that all F1 related ping-pong buffer logic is - * synchronised and all queued resuests are cancelled. - */ -static int -bcmspi_resync_f1(sdioh_info_t *sd) -{ - uint32 cmd_arg = GSPI_RESYNC_PATTERN, data = 0, datalen = 0; - - - /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen - * according to the wordlen mode(16/32bit) the device is in. - */ - ASSERT(sd->wordlen == 4 || sd->wordlen == 2); - datalen = ROUNDUP(datalen, sd->wordlen); - - /* Start by copying command in the spi-outbuffer */ - *(uint32 *)spi_outbuf2 = cmd_arg; - - /* for Write, put the data into the output buffer */ - *(uint32 *)&spi_outbuf2[CMDLEN] = data; - - /* +4 for cmd, +4 for dstatus */ - spi_sendrecv(sd, spi_outbuf2, spi_inbuf2, datalen + 8); - - /* Last 4bytes are dstatus. Device is configured to return status bits. */ - if (sd->wordlen == 4) { /* 32bit spid */ - sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf2[datalen + CMDLEN ]); - } else if (sd->wordlen == 2) { /* 16bit spid */ - sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN ]) | - (bcmswap16(*(uint16 *)&spi_inbuf2[datalen + CMDLEN + 2]) << 16)); - } else { - sd_err(("%s: Host is %d bit machine, could not read SPI dstatus.\n", - __FUNCTION__, 8 * sd->wordlen)); - return ERROR; - } - - if (sd->card_dstatus) - sd_trace(("dstatus after resync pattern write = 0x%x\n", sd->card_dstatus)); - - return (BCME_OK); -} - -uint32 dstatus_count = 0; - -static int -bcmspi_update_stats(sdioh_info_t *sd, uint32 cmd_arg) -{ - uint32 dstatus = sd->card_dstatus; - struct spierrstats_t *spierrstats = &sd->spierrstats; - int err = SUCCESS; - - sd_trace(("cmd = 0x%x, dstatus = 0x%x\n", cmd_arg, dstatus)); - - /* Store dstatus of last few gSPI transactions */ - spierrstats->dstatus[dstatus_count % NUM_PREV_TRANSACTIONS] = dstatus; - spierrstats->spicmd[dstatus_count % NUM_PREV_TRANSACTIONS] = cmd_arg; - dstatus_count++; - - if (sd->card_init_done == FALSE) - return err; - - if (dstatus & STATUS_DATA_NOT_AVAILABLE) { - spierrstats->dna++; - sd_trace(("Read data not available on F1 addr = 0x%x\n", - GFIELD(cmd_arg, SPI_REG_ADDR))); - /* Clear dna bit */ - bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, DATA_UNAVAILABLE); - } - - if (dstatus & STATUS_UNDERFLOW) { - spierrstats->rdunderflow++; - sd_err(("FIFO underflow happened due to current F2 read command.\n")); - } - - if (dstatus & STATUS_OVERFLOW) { - spierrstats->wroverflow++; - sd_err(("FIFO overflow happened due to current (F1/F2) write command.\n")); - if ((sd->chip == BCM4329_CHIP_ID) && (sd->chiprev == 0)) { - bcmspi_card_byterewrite(sd, SPI_FUNC_0, SPID_INTR_REG, F1_OVERFLOW); - bcmspi_resync_f1(sd); - sd_err(("Recovering from F1 FIFO overflow.\n")); - } else { - err = ERROR_OF; - } - } - - if (dstatus & STATUS_F2_INTR) { - spierrstats->f2interrupt++; - sd_trace(("Interrupt from F2. SW should clear corresponding IntStatus bits\n")); - } - - if (dstatus & STATUS_F3_INTR) { - spierrstats->f3interrupt++; - sd_err(("Interrupt from F3. SW should clear corresponding IntStatus bits\n")); - } - - if (dstatus & STATUS_HOST_CMD_DATA_ERR) { - spierrstats->hostcmddataerr++; - sd_err(("Error in CMD or Host data, detected by CRC/Checksum (optional)\n")); - } - - if (dstatus & STATUS_F2_PKT_AVAILABLE) { - spierrstats->f2pktavailable++; - sd_trace(("Packet is available/ready in F2 TX FIFO\n")); - sd_trace(("Packet length = %d\n", sd->dwordmode ? - ((dstatus & STATUS_F2_PKT_LEN_MASK) >> (STATUS_F2_PKT_LEN_SHIFT - 2)) : - ((dstatus & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT))); - } - - if (dstatus & STATUS_F3_PKT_AVAILABLE) { - spierrstats->f3pktavailable++; - sd_err(("Packet is available/ready in F3 TX FIFO\n")); - sd_err(("Packet length = %d\n", - (dstatus & STATUS_F3_PKT_LEN_MASK) >> STATUS_F3_PKT_LEN_SHIFT)); - } - - return err; -} - -extern int -sdioh_abort(sdioh_info_t *sd, uint func) -{ - return 0; -} - -int -sdioh_start(sdioh_info_t *sd, int stage) -{ - return SUCCESS; -} - -int -sdioh_stop(sdioh_info_t *sd) -{ - return SUCCESS; -} - - - -/* - * Private/Static work routines - */ -static int -bcmspi_host_init(sdioh_info_t *sd) -{ - - /* Default power on mode */ - sd->sd_mode = SDIOH_MODE_SPI; - sd->polled_mode = TRUE; - sd->host_init_done = TRUE; - sd->card_init_done = FALSE; - sd->adapter_slot = 1; - - return (SUCCESS); -} - -static int -get_client_blocksize(sdioh_info_t *sd) -{ - uint32 regdata[2]; - int status; - - /* Find F1/F2/F3 max packet size */ - if ((status = bcmspi_card_regread(sd, 0, SPID_F1_INFO_REG, - 8, regdata)) != SUCCESS) { - return status; - } - - sd_trace(("pkt_size regdata[0] = 0x%x, regdata[1] = 0x%x\n", - regdata[0], regdata[1])); - - sd->client_block_size[1] = (regdata[0] & F1_MAX_PKT_SIZE) >> 2; - sd_trace(("Func1 blocksize = %d\n", sd->client_block_size[1])); - ASSERT(sd->client_block_size[1] == BLOCK_SIZE_F1); - - sd->client_block_size[2] = ((regdata[0] >> 16) & F2_MAX_PKT_SIZE) >> 2; - sd_trace(("Func2 blocksize = %d\n", sd->client_block_size[2])); - ASSERT(sd->client_block_size[2] == BLOCK_SIZE_F2); - - sd->client_block_size[3] = (regdata[1] & F3_MAX_PKT_SIZE) >> 2; - sd_trace(("Func3 blocksize = %d\n", sd->client_block_size[3])); - ASSERT(sd->client_block_size[3] == BLOCK_SIZE_F3); - - return 0; -} - -static int -bcmspi_client_init(sdioh_info_t *sd) -{ - uint32 status_en_reg = 0; - sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot)); - -#ifdef HSMODE - if (!spi_start_clock(sd, (uint16)sd_divisor)) { - sd_err(("spi_start_clock failed\n")); - return ERROR; - } -#else - /* Start at ~400KHz clock rate for initialization */ - if (!spi_start_clock(sd, 128)) { - sd_err(("spi_start_clock failed\n")); - return ERROR; - } -#endif /* HSMODE */ - - if (!bcmspi_host_device_init_adapt(sd)) { - sd_err(("bcmspi_host_device_init_adapt failed\n")); - return ERROR; - } - - if (!bcmspi_test_card(sd)) { - sd_err(("bcmspi_test_card failed\n")); - return ERROR; - } - - sd->num_funcs = SPI_MAX_IOFUNCS; - - get_client_blocksize(sd); - - /* Apply resync pattern cmd with all zeros to reset spi-bkplane F1 logic */ - bcmspi_resync_f1(sd); - - sd->dwordmode = FALSE; - - bcmspi_card_regread(sd, 0, SPID_STATUS_ENABLE, 1, &status_en_reg); - - sd_trace(("%s: Enabling interrupt with dstatus \n", __FUNCTION__)); - status_en_reg |= INTR_WITH_STATUS; - - - if (bcmspi_card_regwrite(sd, SPI_FUNC_0, SPID_STATUS_ENABLE, 1, - status_en_reg & 0xff) != SUCCESS) { - sd_err(("%s: Unable to set response delay for all fun's.\n", __FUNCTION__)); - return ERROR; - } - - -#ifndef HSMODE - /* After configuring for High-Speed mode, set the desired clock rate. */ - if (!spi_start_clock(sd, 4)) { - sd_err(("spi_start_clock failed\n")); - return ERROR; - } -#endif /* HSMODE */ - - sd->card_init_done = TRUE; - - - return SUCCESS; -} - -static int -bcmspi_set_highspeed_mode(sdioh_info_t *sd, bool hsmode) -{ - uint32 regdata; - int status; - - if ((status = bcmspi_card_regread(sd, 0, SPID_CONFIG, - 4, ®data)) != SUCCESS) - return status; - - sd_trace(("In %s spih-ctrl = 0x%x \n", __FUNCTION__, regdata)); - - - if (hsmode == TRUE) { - sd_trace(("Attempting to enable High-Speed mode.\n")); - - if (regdata & HIGH_SPEED_MODE) { - sd_trace(("Device is already in High-Speed mode.\n")); - return status; - } else { - regdata |= HIGH_SPEED_MODE; - sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG)); - if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG, - 4, regdata)) != SUCCESS) { - return status; - } - } - } else { - sd_trace(("Attempting to disable High-Speed mode.\n")); - - if (regdata & HIGH_SPEED_MODE) { - regdata &= ~HIGH_SPEED_MODE; - sd_trace(("Writing %08x to device at %08x\n", regdata, SPID_CONFIG)); - if ((status = bcmspi_card_regwrite(sd, 0, SPID_CONFIG, - 4, regdata)) != SUCCESS) - return status; - } - else { - sd_trace(("Device is already in Low-Speed mode.\n")); - return status; - } - } - - spi_controller_highspeed_mode(sd, hsmode); - - return TRUE; -} - -#define bcmspi_find_curr_mode(sd) { \ - sd->wordlen = 2; \ - status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, ®data); \ - regdata &= 0xff; \ - if ((regdata == 0xad) || (regdata == 0x5b) || \ - (regdata == 0x5d) || (regdata == 0x5a)) \ - break; \ - sd->wordlen = 4; \ - status = bcmspi_card_regread_fixedaddr(sd, 0, SPID_TEST_READ, 4, ®data); \ - regdata &= 0xff; \ - if ((regdata == 0xad) || (regdata == 0x5b) || \ - (regdata == 0x5d) || (regdata == 0x5a)) \ - break; \ - sd_trace(("Silicon testability issue: regdata = 0x%x." \ - " Expected 0xad, 0x5a, 0x5b or 0x5d.\n", regdata)); \ - OSL_DELAY(100000); \ -} - -#define INIT_ADAPT_LOOP 100 - -/* Adapt clock-phase-speed-bitwidth between host and device */ -static bool -bcmspi_host_device_init_adapt(sdioh_info_t *sd) -{ - uint32 wrregdata, regdata = 0; - int status; - int i; - - /* Due to a silicon testability issue, the first command from the Host - * to the device will get corrupted (first bit will be lost). So the - * Host should poll the device with a safe read request. ie: The Host - * should try to read F0 addr 0x14 using the Fixed address mode - * (This will prevent a unintended write command to be detected by device) - */ - for (i = 0; i < INIT_ADAPT_LOOP; i++) { - /* If device was not power-cycled it will stay in 32bit mode with - * response-delay-all bit set. Alternate the iteration so that - * read either with or without response-delay for F0 to succeed. - */ - bcmspi_find_curr_mode(sd); - sd->resp_delay_all = (i & 0x1) ? TRUE : FALSE; - - bcmspi_find_curr_mode(sd); - sd->dwordmode = TRUE; - - bcmspi_find_curr_mode(sd); - sd->dwordmode = FALSE; - } - - /* Bail out, device not detected */ - if (i == INIT_ADAPT_LOOP) - return FALSE; - - /* Softreset the spid logic */ - if ((sd->dwordmode) || (sd->wordlen == 4)) { - bcmspi_card_regwrite(sd, 0, SPID_RESET_BP, 1, RESET_ON_WLAN_BP_RESET|RESET_SPI); - bcmspi_card_regread(sd, 0, SPID_RESET_BP, 1, ®data); - sd_trace(("reset reg read = 0x%x\n", regdata)); - sd_trace(("dwordmode = %d, wordlen = %d, resp_delay_all = %d\n", sd->dwordmode, - sd->wordlen, sd->resp_delay_all)); - /* Restore default state after softreset */ - sd->wordlen = 2; - sd->dwordmode = FALSE; - } - - if (sd->wordlen == 4) { - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, ®data)) != - SUCCESS) - return FALSE; - if (regdata == TEST_RO_DATA_32BIT_LE) { - sd_trace(("Spid is already in 32bit LE mode. Value read = 0x%x\n", - regdata)); - sd_trace(("Spid power was left on.\n")); - } else { - sd_err(("Spid power was left on but signature read failed." - " Value read = 0x%x\n", regdata)); - return FALSE; - } - } else { - sd->wordlen = 2; - -#define CTRL_REG_DEFAULT 0x00010430 /* according to the host m/c */ - - wrregdata = (CTRL_REG_DEFAULT); - sd->resp_delay_all = TRUE; - if (sd->resp_delay_all == TRUE) { - /* Enable response delay for all */ - wrregdata |= (RESP_DELAY_ALL << 16); - /* Program response delay value */ - wrregdata &= 0xffff00ff; - wrregdata |= (F1_RESPONSE_DELAY << 8); - sd->prev_fun = SPI_FUNC_1; - bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata); - } - - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, ®data)) != SUCCESS) - return FALSE; - sd_trace(("(we are still in 16bit mode) 32bit READ LE regdata = 0x%x\n", regdata)); - -#ifndef HSMODE - wrregdata |= (CLOCK_PHASE | CLOCK_POLARITY); - wrregdata &= ~HIGH_SPEED_MODE; - bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata); -#endif /* HSMODE */ - - for (i = 0; i < INIT_ADAPT_LOOP; i++) { - if ((regdata == 0xfdda7d5b) || (regdata == 0xfdda7d5a)) { - sd_trace(("0xfeedbead was leftshifted by 1-bit.\n")); - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, - ®data)) != SUCCESS) - return FALSE; - } - OSL_DELAY(1000); - } - - - /* Change to host controller intr-polarity of active-low */ - wrregdata &= ~INTR_POLARITY; - sd_trace(("(we are still in 16bit mode) 32bit Write LE reg-ctrl-data = 0x%x\n", - wrregdata)); - /* Change to 32bit mode */ - wrregdata |= WORD_LENGTH_32; - bcmspi_card_regwrite(sd, 0, SPID_CONFIG, 4, wrregdata); - - /* Change command/data packaging in 32bit LE mode */ - sd->wordlen = 4; - - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, ®data)) != SUCCESS) - return FALSE; - - if (regdata == TEST_RO_DATA_32BIT_LE) { - sd_trace(("Read spid passed. Value read = 0x%x\n", regdata)); - sd_trace(("Spid had power-on cycle OR spi was soft-resetted \n")); - } else { - sd_err(("Stale spid reg values read as it was kept powered. Value read =" - "0x%x\n", regdata)); - return FALSE; - } - } - - - return TRUE; -} - -static bool -bcmspi_test_card(sdioh_info_t *sd) -{ - uint32 regdata; - int status; - - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_READ, 4, ®data)) != SUCCESS) - return FALSE; - - if (regdata == (TEST_RO_DATA_32BIT_LE)) - sd_trace(("32bit LE regdata = 0x%x\n", regdata)); - else { - sd_trace(("Incorrect 32bit LE regdata = 0x%x\n", regdata)); - return FALSE; - } - - -#define RW_PATTERN1 0xA0A1A2A3 -#define RW_PATTERN2 0x4B5B6B7B - - regdata = RW_PATTERN1; - if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS) - return FALSE; - regdata = 0; - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, ®data)) != SUCCESS) - return FALSE; - if (regdata != RW_PATTERN1) { - sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n", - RW_PATTERN1, regdata)); - return FALSE; - } else - sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata)); - - regdata = RW_PATTERN2; - if ((status = bcmspi_card_regwrite(sd, 0, SPID_TEST_RW, 4, regdata)) != SUCCESS) - return FALSE; - regdata = 0; - if ((status = bcmspi_card_regread(sd, 0, SPID_TEST_RW, 4, ®data)) != SUCCESS) - return FALSE; - if (regdata != RW_PATTERN2) { - sd_err(("Write-Read spid failed. Value wrote = 0x%x, Value read = 0x%x\n", - RW_PATTERN2, regdata)); - return FALSE; - } else - sd_trace(("R/W spid passed. Value read = 0x%x\n", regdata)); - - return TRUE; -} - -static int -bcmspi_driver_init(sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - if ((bcmspi_host_init(sd)) != SUCCESS) { - return ERROR; - } - - if (bcmspi_client_init(sd) != SUCCESS) { - return ERROR; - } - - return SUCCESS; -} - -/* Read device reg */ -static int -bcmspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) -{ - int status; - uint32 cmd_arg, dstatus; - - ASSERT(regsize); - - if (func == 2) - sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n")); - - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */ - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func, - regaddr, *data)); - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) - != SUCCESS) - return status; - - bcmspi_cmd_getdstatus(sd, &dstatus); - if (dstatus) - sd_trace(("dstatus =0x%x\n", dstatus)); - - return SUCCESS; -} - -static int -bcmspi_card_regread_fixedaddr(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) -{ - - int status; - uint32 cmd_arg; - uint32 dstatus; - - ASSERT(regsize); - - if (func == 2) - sd_trace(("Reg access on F2 will generate error indication in dstatus bits.\n")); - - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 0); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0); /* Fixed access */ - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, data, regsize)) - != SUCCESS) - return status; - - sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 0, func, - regaddr, *data)); - - bcmspi_cmd_getdstatus(sd, &dstatus); - sd_trace(("dstatus =0x%x\n", dstatus)); - return SUCCESS; -} - -/* write a device register */ -static int -bcmspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) -{ - int status; - uint32 cmd_arg, dstatus; - - ASSERT(regsize); - - cmd_arg = 0; - - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */ - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, regsize == BLOCK_SIZE_F2 ? 0 : regsize); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, 1, func, - regaddr, data)); - - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, &data, regsize)) - != SUCCESS) - return status; - - bcmspi_cmd_getdstatus(sd, &dstatus); - if (dstatus) - sd_trace(("dstatus =0x%x\n", dstatus)); - - return SUCCESS; -} - -/* write a device register - 1 byte */ -static int -bcmspi_card_bytewrite(sdioh_info_t *sd, int func, uint32 regaddr, uint8 *byte) -{ - int status; - uint32 cmd_arg; - uint32 dstatus; - uint32 data = (uint32)(*byte); - - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); /* Incremental access */ - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, 1); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, 1); - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - sd_trace(("%s: func=%d, regaddr=0x%08x, data=0x%x\n", __FUNCTION__, func, - regaddr, data)); - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, - cmd_arg, &data, 1)) != SUCCESS) { - return status; - } - - bcmspi_cmd_getdstatus(sd, &dstatus); - if (dstatus) - sd_trace(("dstatus =0x%x\n", dstatus)); - - return SUCCESS; -} - -void -bcmspi_cmd_getdstatus(sdioh_info_t *sd, uint32 *dstatus_buffer) -{ - *dstatus_buffer = sd->card_dstatus; -} - -/* 'data' is of type uint32 whereas other buffers are of type uint8 */ -static int -bcmspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd_arg, - uint32 *data, uint32 datalen) -{ - uint32 i, j; - uint8 resp_delay = 0; - int err = SUCCESS; - uint32 hostlen; - uint32 spilen = 0; - uint32 dstatus_idx = 0; - uint16 templen, buslen, len, *ptr = NULL; - - sd_trace(("spi cmd = 0x%x\n", cmd_arg)); - - if (DWORDMODE_ON) { - spilen = GFIELD(cmd_arg, SPI_LEN); - if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_0) || - (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_1)) - dstatus_idx = spilen * 3; - - if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) && - (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) { - spilen = spilen << 2; - dstatus_idx = (spilen % 16) ? (16 - (spilen % 16)) : 0; - /* convert len to mod16 size */ - spilen = ROUNDUP(spilen, 16); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2)); - } - } - - /* Set up and issue the SPI command. MSByte goes out on bus first. Increase datalen - * according to the wordlen mode(16/32bit) the device is in. - */ - if (sd->wordlen == 4) { /* 32bit spid */ - *(uint32 *)spi_outbuf = bcmswap32(cmd_arg); - if (datalen & 0x3) - datalen += (4 - (datalen & 0x3)); - } else if (sd->wordlen == 2) { /* 16bit spid */ - *(uint16 *)spi_outbuf = bcmswap16(cmd_arg & 0xffff); - *(uint16 *)&spi_outbuf[2] = bcmswap16((cmd_arg & 0xffff0000) >> 16); - if (datalen & 0x1) - datalen++; - if (datalen < 4) - datalen = ROUNDUP(datalen, 4); - } else { - sd_err(("Host is %d bit spid, could not create SPI command.\n", - 8 * sd->wordlen)); - return ERROR; - } - - /* for Write, put the data into the output buffer */ - if (GFIELD(cmd_arg, SPI_RW_FLAG) == 1) { - /* We send len field of hw-header always a mod16 size, both from host and dongle */ - if (DWORDMODE_ON) { - if (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) { - ptr = (uint16 *)&data[0]; - templen = *ptr; - /* ASSERT(*ptr == ~*(ptr + 1)); */ - templen = ROUNDUP(templen, 16); - *ptr = templen; - sd_trace(("actual tx len = %d\n", (uint16)(~*(ptr+1)))); - } - } - - if (datalen != 0) { - for (i = 0; i < datalen/4; i++) { - if (sd->wordlen == 4) { /* 32bit spid */ - *(uint32 *)&spi_outbuf[i * 4 + CMDLEN] = - bcmswap32(data[i]); - } else if (sd->wordlen == 2) { /* 16bit spid */ - *(uint16 *)&spi_outbuf[i * 4 + CMDLEN] = - bcmswap16(data[i] & 0xffff); - *(uint16 *)&spi_outbuf[i * 4 + CMDLEN + 2] = - bcmswap16((data[i] & 0xffff0000) >> 16); - } - } - } - } - - /* Append resp-delay number of bytes and clock them out for F0/1/2 reads. */ - if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { - int func = GFIELD(cmd_arg, SPI_FUNCTION); - switch (func) { - case 0: - resp_delay = sd->resp_delay_all ? F0_RESPONSE_DELAY : 0; - break; - case 1: - resp_delay = F1_RESPONSE_DELAY; - break; - case 2: - resp_delay = sd->resp_delay_all ? F2_RESPONSE_DELAY : 0; - break; - default: - ASSERT(0); - break; - } - /* Program response delay */ - bcmspi_prog_resp_delay(sd, func, resp_delay); - } - - /* +4 for cmd and +4 for dstatus */ - hostlen = datalen + 8 + resp_delay; - hostlen += dstatus_idx; - hostlen += (4 - (hostlen & 0x3)); - spi_sendrecv(sd, spi_outbuf, spi_inbuf, hostlen); - - /* for Read, get the data into the input buffer */ - if (datalen != 0) { - if (GFIELD(cmd_arg, SPI_RW_FLAG) == 0) { /* if read cmd */ - for (j = 0; j < datalen/4; j++) { - if (sd->wordlen == 4) { /* 32bit spid */ - data[j] = bcmswap32(*(uint32 *)&spi_inbuf[j * 4 + - CMDLEN + resp_delay]); - } else if (sd->wordlen == 2) { /* 16bit spid */ - data[j] = (bcmswap16(*(uint16 *)&spi_inbuf[j * 4 + - CMDLEN + resp_delay])) | - ((bcmswap16(*(uint16 *)&spi_inbuf[j * 4 + - CMDLEN + resp_delay + 2])) << 16); - } - } - - if ((DWORDMODE_ON) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) { - ptr = (uint16 *)&data[0]; - templen = *ptr; - buslen = len = ~(*(ptr + 1)); - buslen = ROUNDUP(buslen, 16); - /* populate actual len in hw-header */ - if (templen == buslen) - *ptr = len; - } - } - } - - /* Restore back the len field of the hw header */ - if (DWORDMODE_ON) { - if ((GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2) && - (GFIELD(cmd_arg, SPI_RW_FLAG) == 1)) { - ptr = (uint16 *)&data[0]; - *ptr = (uint16)(~*(ptr+1)); - } - } - - dstatus_idx += (datalen + CMDLEN + resp_delay); - /* Last 4bytes are dstatus. Device is configured to return status bits. */ - if (sd->wordlen == 4) { /* 32bit spid */ - sd->card_dstatus = bcmswap32(*(uint32 *)&spi_inbuf[dstatus_idx]); - } else if (sd->wordlen == 2) { /* 16bit spid */ - sd->card_dstatus = (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx]) | - (bcmswap16(*(uint16 *)&spi_inbuf[dstatus_idx + 2]) << 16)); - } else { - sd_err(("Host is %d bit machine, could not read SPI dstatus.\n", - 8 * sd->wordlen)); - return ERROR; - } - if (sd->card_dstatus == 0xffffffff) { - sd_err(("looks like not a GSPI device or device is not powered.\n")); - } - - err = bcmspi_update_stats(sd, cmd_arg); - - return err; - -} - -static int -bcmspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, - uint32 addr, int nbytes, uint32 *data) -{ - int status; - uint32 cmd_arg; - bool write = rw == SDIOH_READ ? 0 : 1; - uint retries = 0; - - bool enable; - uint32 spilen; - - cmd_arg = 0; - - ASSERT(nbytes); - ASSERT(nbytes <= sd->client_block_size[func]); - - if (write) sd->t_cnt++; else sd->r_cnt++; - - if (func == 2) { - /* Frame len check limited by gSPI. */ - if ((nbytes > 2000) && write) { - sd_trace((">2KB write: F2 wr of %d bytes\n", nbytes)); - } - /* ASSERT(nbytes <= 2048); Fix bigger len gspi issue and uncomment. */ - /* If F2 fifo on device is not ready to receive data, don't do F2 transfer */ - if (write) { - uint32 dstatus; - /* check F2 ready with cached one */ - bcmspi_cmd_getdstatus(sd, &dstatus); - if ((dstatus & STATUS_F2_RX_READY) == 0) { - retries = WAIT_F2RXFIFORDY; - enable = 0; - while (retries-- && !enable) { - OSL_DELAY(WAIT_F2RXFIFORDY_DELAY * 1000); - bcmspi_card_regread(sd, SPI_FUNC_0, SPID_STATUS_REG, 4, - &dstatus); - if (dstatus & STATUS_F2_RX_READY) - enable = TRUE; - } - if (!enable) { - struct spierrstats_t *spierrstats = &sd->spierrstats; - spierrstats->f2rxnotready++; - sd_err(("F2 FIFO is not ready to receive data.\n")); - return ERROR; - } - sd_trace(("No of retries on F2 ready %d\n", - (WAIT_F2RXFIFORDY - retries))); - } - } - } - - /* F2 transfers happen on 0 addr */ - addr = (func == 2) ? 0 : addr; - - /* In pio mode buffer is read using fixed address fifo in func 1 */ - if ((func == 1) && (fifo)) - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 0); - else - cmd_arg = SFIELD(cmd_arg, SPI_ACCESS, 1); - - cmd_arg = SFIELD(cmd_arg, SPI_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, SPI_REG_ADDR, addr); - cmd_arg = SFIELD(cmd_arg, SPI_RW_FLAG, write); - spilen = sd->data_xfer_count = MIN(sd->client_block_size[func], nbytes); - if ((sd->dwordmode == TRUE) && (GFIELD(cmd_arg, SPI_FUNCTION) == SPI_FUNC_2)) { - /* convert len to mod4 size */ - spilen = spilen + ((spilen & 0x3) ? (4 - (spilen & 0x3)): 0); - cmd_arg = SFIELD(cmd_arg, SPI_LEN, (spilen >> 2)); - } else - cmd_arg = SFIELD(cmd_arg, SPI_LEN, spilen); - - if ((func == 2) && (fifo == 1)) { - sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", - __FUNCTION__, write ? "Wr" : "Rd", func, "INCR", - addr, nbytes, sd->r_cnt, sd->t_cnt)); - } - - sd_trace(("%s cmd_arg = 0x%x\n", __FUNCTION__, cmd_arg)); - sd_data(("%s: %s func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", - __FUNCTION__, write ? "Wd" : "Rd", func, "INCR", - addr, nbytes, sd->r_cnt, sd->t_cnt)); - - - if ((status = bcmspi_cmd_issue(sd, sd->sd_use_dma, cmd_arg, - data, nbytes)) != SUCCESS) { - sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__, - (write ? "write" : "read"))); - return status; - } - - /* gSPI expects that hw-header-len is equal to spi-command-len */ - if ((func == 2) && (rw == SDIOH_WRITE) && (sd->dwordmode == FALSE)) { - ASSERT((uint16)sd->data_xfer_count == (uint16)(*data & 0xffff)); - ASSERT((uint16)sd->data_xfer_count == (uint16)(~((*data & 0xffff0000) >> 16))); - } - - if ((nbytes > 2000) && !write) { - sd_trace((">2KB read: F2 rd of %d bytes\n", nbytes)); - } - - return SUCCESS; -} - -/* Reset and re-initialize the device */ -int -sdioh_sdio_reset(sdioh_info_t *si) -{ - si->card_init_done = FALSE; - return bcmspi_client_init(si); -} diff --git a/bcm4329/src/dhd/exe/GNUmakefile b/bcm4329/src/dhd/exe/GNUmakefile index fec744d..240189b 100644 --- a/bcm4329/src/dhd/exe/GNUmakefile +++ b/bcm4329/src/dhd/exe/GNUmakefile @@ -49,7 +49,7 @@ CFLAGS += -DBCMSPI #----------------------------------------------------------- # Linux build # -ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le linuxarm_omap android"),) +ifneq ($(findstring $(TARGETENV), "linux linuxmips linuxmips_be linuxarm linuxarm_le android"),) # $(TARGETARCH) is set based on TARGETENV in src/Makerules.* files DHD_OBJS := dhdu.o dhdu_linux.o bcmutils.o miniopt.o @@ -63,10 +63,6 @@ endif # extra warnings CFLAGS += -Wextra $(CUSTOM_FLAGS) -ifeq ($(TARGETENV), linuxarm_omap) -CFLAGS += -DBGBRD -endif - vpath %.c $(SRCBASE)/shared all: $(DHD_EXE) diff --git a/bcm4329/src/dhd/exe/dhdu.c b/bcm4329/src/dhd/exe/dhdu.c index 6fc28b2..5ffd961 100644 --- a/bcm4329/src/dhd/exe/dhdu.c +++ b/bcm4329/src/dhd/exe/dhdu.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: dhdu.c,v 1.52.2.10.2.6.2.10 2009/06/02 21:56:22 Exp $ + * $Id: dhdu.c,v 1.52.2.10.2.6.2.11 2009/09/25 00:32:00 Exp $ */ /* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT' @@ -406,6 +406,7 @@ dhd_list(void *dhd, cmd_t *garb, char **argv) printf("%s\n", buf+row*80); printf("\n"); + free(buf); return (0); } @@ -683,7 +684,7 @@ dhd_sd_blocksize(void *dhd, cmd_t *cmd, char **argv) { int ret; int argc; - char *endptr; + char *endptr = NULL; void *ptr = NULL; int func, size; @@ -769,7 +770,7 @@ dhd_sdreg(void *dhd, cmd_t *cmd, char **argv) int ret; sdreg_t sdreg; uint argc; - char *ptr; + char *ptr = NULL; UNUSED_PARAMETER(cmd); @@ -991,7 +992,7 @@ static int dhd_idletime(void *dhd, cmd_t *cmd, char **argv) { int32 idletime; - char *endptr; + char *endptr = NULL; int err = 0; if (argv[1]) { @@ -1040,7 +1041,7 @@ static int dhd_idleclock(void *dhd, cmd_t *cmd, char **argv) { int32 idleclock; - char *endptr; + char *endptr = NULL; int err = 0; if (argv[1]) { @@ -1784,7 +1785,7 @@ static int dhd_logstamp(void *dhd, cmd_t *cmd, char **argv) { int ret; - char *endptr; + char *endptr = NULL; uint argc; int valn[2] = {0, 0}; @@ -1821,7 +1822,7 @@ dhd_sd_reg(void *dhd, cmd_t *cmd, char **argv) { int ret; sdreg_t sdreg; - char *endptr; + char *endptr = NULL; uint argc; void *ptr = NULL; @@ -1911,8 +1912,8 @@ static int dhd_do_msglevel(void *dhd, cmd_t *cmd, char **argv, dbg_msg_t *dbg_msg) { int ret, i; - uint val, last_val = 0, msglevel, msglevel_add = 0, msglevel_del = 0; - char *endptr; + uint val, last_val = 0, msglevel = 0, msglevel_add = 0, msglevel_del = 0; + char *endptr = NULL; if ((ret = dhd_iovar_getint(dhd, cmd->name, (int*)&msglevel)) < 0) return (ret); @@ -2024,7 +2025,7 @@ dhd_var_setint(void *dhd, cmd_t *cmd, char **argv) int32 val; int len; char *varname; - char *endptr; + char *endptr = NULL; char *p; if (cmd->set == -1) { diff --git a/bcm4329/src/dhd/linux/Makefile b/bcm4329/src/dhd/linux/Makefile index df8f009..89300a1 100644 --- a/bcm4329/src/dhd/linux/Makefile +++ b/bcm4329/src/dhd/linux/Makefile @@ -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: Makefile,v 1.55.2.6.2.10.6.18 2009/06/03 21:51:11 Exp $ +# $Id: Makefile,v 1.55.2.6.2.10.6.24 2009/10/22 18:40:45 Exp $ # # Try a couple of places for LINUXDIR if not specified @@ -54,6 +54,9 @@ ifeq ($(LINUXVER),) $(error LINUXVER=$(LINUXVER) is empty) endif # LINUXVER +$(warning Found LINUXVER=$(LINUXVER)) +$(warning Found LINUXDIR=$(LINUXDIR)) + # check if 2.4 kernel or 2.5+ kernel BCM_KVER:=$(shell echo $(LINUXVER) | cut -c1-3 | sed 's/2\.[56]/2\.6/') @@ -74,7 +77,7 @@ DFLAGS := # basic options (defines in DFLAGS, includes in IFLAGS) -DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 +DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 -DBCMWAPI_WPI DFLAGS += -DUNRELEASEDCHIP ifeq ($(BCMQT),1) DFLAGS += -DBCMSLTGT -DBCMQT @@ -85,7 +88,40 @@ ifeq ($(WLTEST),1) endif -IFLAGS := -I$(LINUXDIR)/include -I$(LINUXDIR)/include/asm/mach-default -I. -I$(SRCBASE)/include -I$(SRCBASE)/shared -I$(SRCBASE)/dhd/sys -I$(SRCBASE)/dongle -I$(SRCBASE)/wl/sys +# Past 2.6.29 kernels, arch specific bits are re-organized in linux kernel. So +# append new include paths to existing ones to get 2.6.29+ kernels compile + +# Default DHDARCH is x86 +ifdef ARCH + DHDARCH ?= $(ARCH) +else + DHDARCH ?= x86 +endif + +ifneq ($(findstring native,$(TARGET)),) + DHDARCH = x86 +endif +ifneq ($(findstring mips,$(TARGET)),) + DHDARCH = mips +endif +ifneq ($(findstring arm,$(TARGET)),) + DHDARCH = arm +endif + +# First include from linux kernel dirs +IFLAGS := -I$(LINUXDIR)/include +IFLAGS += -I$(LINUXDIR)/include/asm/mach-default +# Followed by 2.6.29+ specific paths +IFLAGS += -I$(LINUXDIR)/arch/$(DHDARCH)/include +IFLAGS += -I$(LINUXDIR)/arch/$(DHDARCH)/include/asm/mach-default + +# From current workspace +IFLAGS += -I. +IFLAGS += -I$(SRCBASE)/include +IFLAGS += -I$(SRCBASE)/shared +IFLAGS += -I$(SRCBASE)/dhd/sys +IFLAGS += -I$(SRCBASE)/dongle +IFLAGS += -I$(SRCBASE)/wl/sys ifneq ($(wildcard $(LINUXDIR)/.config),) include $(LINUXDIR)/.config @@ -162,7 +198,7 @@ ifneq ($(findstring -rndis-,-$(TARGET)-),) DFLAGS += -DRNDIS CFILES += dhd_rndis.c endif - + ifneq ($(findstring -usb-,-$(TARGET)-),) DFLAGS += -DBCMDHDUSB CFILES += dhd_usb_linux.c @@ -175,8 +211,15 @@ ifneq ($(findstring -sdstd-,$(TARGET)-),) DFLAGS += -DBCMSDIO -DBCMSDIOH_STD CFILES += dhd_sdio.c bcmsdh.c bcmsdstd.c bcmsdstd_linux.c bcmsdh_linux.c endif +ifneq ($(findstring -oob-,-$(TARGET)-),) +DFLAGS += -DOOB_INTR_ONLY +else +ifneq ($(findstring -sdmmc-,-$(TARGET)-),) +DFLAGS += -DSDIO_ISR_THREAD +endif +endif ifneq ($(findstring -sdmmc-,-$(TARGET)-),) -DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS -DSDIO_ISR_THREAD +DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS CFILES += dhd_sdio.c bcmsdh_sdmmc.c bcmsdh.c bcmsdh_linux.c bcmsdh_sdmmc_linux.c endif ifneq ($(findstring -sdspi-,$(TARGET)-),) @@ -196,6 +239,8 @@ endif CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) $(CUSTOM_FLAGS) + + LDFLAGS := -r MODULES := dhd.o ifeq ($(BCM_KVER), 2.6) @@ -219,8 +264,9 @@ endif TARGETS := \ dhd-cdc-usb dhd-cdc-sdstd \ - dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-usb-apsta \ - dhd-cdc-usb-gpl + dhd-cdc-sdspi-pci dhd-cdc-sdmmc-gpl dhd-cdc-sdmmc-oob-gpl \ + dhd-cdc-usb-apsta dhd-cdc-usb-gpl \ + dhd-cdc-sdstd-apsta TARGETS += \ diff --git a/bcm4329/src/dhd/sys/dhd.h b/bcm4329/src/dhd/sys/dhd.h index 8f15106..004f7a3 100644 --- a/bcm4329/src/dhd/sys/dhd.h +++ b/bcm4329/src/dhd/sys/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,v 1.32.4.7.2.4.14.22 2009/06/04 23:07:40 Exp $ + * $Id: dhd.h,v 1.32.4.7.2.4.14.25 2009/10/27 04:41:56 Exp $ */ /**************** @@ -46,6 +46,9 @@ #include <linux/ethtool.h> #include <asm/uaccess.h> #include <asm/unaligned.h> +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) +#include <linux/wakelock.h> +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ /* The kernel threading is sdio-specific */ #else /* LINUX */ #define ENOMEM 1 @@ -75,6 +78,26 @@ enum dhd_bus_state { DHD_BUS_DATA /* Ready for frame transfers */ }; +enum dhd_bus_wake_state { + WAKE_LOCK_OFF, + WAKE_LOCK_PRIV, + WAKE_LOCK_DPC, + WAKE_LOCK_IOCTL, + WAKE_LOCK_DOWNLOAD, + WAKE_LOCK_TMOUT, + WAKE_LOCK_WATCHDOG, + WAKE_LOCK_LINK_DOWN_TMOUT, + WAKE_LOCK_MAX +}; +enum dhd_prealloc_index { + DHD_PREALLOC_PROT = 0, + DHD_PREALLOC_RXBUF, + DHD_PREALLOC_DATABUF, + DHD_PREALLOC_OSL_BUF +}; +#ifdef DHD_USE_STATIC_BUF +extern void * dhd_os_prealloc(int section, unsigned long size); +#endif /* Common structure for module and instance linkage */ typedef struct dhd_pub { /* Linkage ponters */ @@ -126,6 +149,9 @@ typedef struct dhd_pub { int dongle_error; uint8 country_code[WLC_CNTRY_BUF_SZ]; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + struct wake_lock wakelock[WAKE_LOCK_MAX]; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ } dhd_pub_t; #ifdef NDIS60 @@ -139,9 +165,90 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info) #endif /* NDIS60 */ + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + + #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); + #define _DHD_PM_RESUME_WAIT(a, b) do {\ + int retry = 0; \ + while (dhd_mmc_suspend && retry++ != b) { \ + wait_event_timeout(a, FALSE, HZ/100); \ + } \ + } while (0) + #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30) + #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) + #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0) + #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) + + #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); + #define SPINWAIT_SLEEP(a, exp, us) do { \ + uint countdown = (us) + 9; \ + while ((exp) && (countdown >= 10)) { \ + wait_event_timeout(a, FALSE, HZ/100); \ + countdown -= 10; \ + } \ + } while (0) + + #else + + #define DHD_PM_RESUME_WAIT_INIT(a) + #define DHD_PM_RESUME_WAIT(a) + #define DHD_PM_RESUME_WAIT_FOREVER(a) + #define DHD_PM_RESUME_RETURN_ERROR(a) + #define DHD_PM_RESUME_RETURN + + #define DHD_SPINWAIT_SLEEP_INIT(a) + #define SPINWAIT_SLEEP(a, exp, us) do { \ + uint countdown = (us) + 9; \ + while ((exp) && (countdown >= 10)) { \ + OSL_DELAY(10); \ + countdown -= 10; \ + } \ + } while (0) + + #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ +#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ + +inline static void WAKE_LOCK_INIT(dhd_pub_t * dhdp, int index, char * y) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +} + +inline static void WAKE_LOCK(dhd_pub_t * dhdp, int index) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + wake_lock(&dhdp->wakelock[index]); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +} + +inline static void WAKE_UNLOCK(dhd_pub_t * dhdp, int index) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + wake_unlock(&dhdp->wakelock[index]); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +} + +inline static void WAKE_LOCK_TIMEOUT(dhd_pub_t * dhdp, int index, long time) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_timeout(&dhdp->wakelock[index], time); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +} + +inline static void WAKE_LOCK_DESTROY(dhd_pub_t * dhdp, int index) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + wake_lock_destroy(&dhdp->wakelock[index]); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ +} + + typedef struct dhd_if_event { uint8 ifidx; uint8 action; + uint8 flags; + uint8 bssidx; } dhd_if_event_t; /* @@ -201,15 +308,13 @@ extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); +extern void dhd_customer_gpio_wlan_ctrl(int onoff); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); +#if defined(OOB_INTR_ONLY) +extern int dhd_customer_oob_irq_map(void); +#endif /* defined(OOB_INTR_ONLY) */ extern void dhd_os_sdtxlock(dhd_pub_t * pub); extern void dhd_os_sdtxunlock(dhd_pub_t * pub); -extern void dhd_os_set_irq(unsigned int irq, dhd_pub_t *pub); -extern void dhd_os_enable_irq(dhd_pub_t *pub); -extern void dhd_os_disable_irq(dhd_pub_t *pub); -extern int dhd_os_wake_lock(dhd_pub_t *pub); -extern int dhd_os_wake_unlock(dhd_pub_t *pub); -extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); int setScheduler(struct task_struct *p, int policy, struct sched_param *param); @@ -224,15 +329,24 @@ extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); extern int dhd_timeout_expired(dhd_timeout_t *tmo); extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); +extern uint8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx); extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata, wl_event_msg_t *, void **data_ptr); extern void wl_event_to_host_order(wl_event_msg_t * evt); extern void dhd_common_init(void); -extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr); +extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, + char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx); extern void dhd_del_if(struct dhd_info *dhd, int ifidx); +extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name); +extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); + +extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); +extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); + + /* Send packet to dongle via data channel */ extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); @@ -244,6 +358,12 @@ extern int dhd_bus_start(dhd_pub_t *dhdp); +typedef enum cust_gpio_modes { + WLAN_RESET_ON, + WLAN_RESET_OFF, + WLAN_POWER_ON, + WLAN_POWER_OFF +} cust_gpio_modes_t; /* * Insmod parameters for debug/test */ diff --git a/bcm4329/src/dhd/sys/dhd_cdc.c b/bcm4329/src/dhd/sys/dhd_cdc.c index b28d455..e503b50 100644 --- a/bcm4329/src/dhd/sys/dhd_cdc.c +++ b/bcm4329/src/dhd/sys/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,v 1.22.4.2.4.7.2.18 2009/06/26 07:03:26 Exp $ + * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.30 2009/10/28 21:38:04 Exp $ * * 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 @@ -41,11 +41,6 @@ #include <dhd_bus.h> #include <dhd_dbg.h> -#ifdef EXT_STA -#include <siutils.h> -#include <wlc_cfg.h> -#include <wlc_pub.h> -#endif /* EXT_STA */ /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN @@ -78,12 +73,9 @@ dhdcdc_msg(dhd_pub_t *dhd) { dhd_prot_t *prot = dhd->prot; int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t); - int ret; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - dhd_os_wake_lock(dhd); - /* NOTE : cdc->msg.len holds the desired length of the buffer to be * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area * is actually sent to the dongle @@ -92,10 +84,7 @@ dhdcdc_msg(dhd_pub_t *dhd) len = CDC_MAX_MSG_SIZE; /* Send request */ - ret = dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len); - - dhd_os_wake_unlock(dhd); - return ret; + return dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len); } static int @@ -129,7 +118,7 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) /* Respond "bcmerror" and "bcmerrorstr" with local cache */ - if (cmd == WLC_GET_VAR) + if (cmd == WLC_GET_VAR && buf) { if (!strcmp((char *)buf, "bcmerrorstr")) { @@ -152,7 +141,7 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) CDC_SET_IF_IDX(msg, ifidx); if (buf) - memcpy((void *)(&msg[1]), buf, len); + memcpy(prot->buf, buf, len); if ((ret = dhdcdc_msg(dhd)) < 0) { DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret)); @@ -219,7 +208,7 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) CDC_SET_IF_IDX(msg, ifidx); if (buf) - memcpy((void *)(&msg[1]), buf, len); + memcpy(prot->buf, buf, len); if ((ret = dhdcdc_msg(dhd)) < 0) goto done; @@ -256,6 +245,10 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) dhd_prot_t *prot = dhd->prot; int ret = -1; + if (dhd->busstate == DHD_BUS_DOWN) { + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); + return ret; + } dhd_os_proto_block(dhd); DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -361,11 +354,6 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) if (PKTSUMNEEDED(pktbuf)) h->flags |= BDC_FLAG_SUM_NEEDED; -#ifdef EXT_STA - /* save pkt encryption exemption info for dongle */ - h->flags &= ~BDC_FLAG_EXEMPT; - h->flags |= (WLPKTFLAG_EXEMPT_GET(WLPKTTAG(pktbuf)) & BDC_FLAG_EXEMPT); -#endif /* EXT_STA */ h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); h->flags2 = 0; @@ -461,10 +449,17 @@ dhd_prot_attach(dhd_pub_t *dhd) { dhd_prot_t *cdc; +#ifndef DHD_USE_STATIC_BUF if (!(cdc = (dhd_prot_t *)MALLOC(dhd->osh, sizeof(dhd_prot_t)))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; } +#else + if (!(cdc = (dhd_prot_t *)dhd_os_prealloc(DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) { + DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); + goto fail; + } +#endif /* DHD_USE_STATIC_BUF */ memset(cdc, 0, sizeof(dhd_prot_t)); /* ensure that the msg buf directly follows the cdc msg struct */ @@ -481,8 +476,10 @@ dhd_prot_attach(dhd_pub_t *dhd) return 0; fail: +#ifndef DHD_USE_STATIC_BUF if (cdc != NULL) MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); +#endif return BCME_NOMEM; } @@ -490,7 +487,9 @@ fail: void dhd_prot_detach(dhd_pub_t *dhd) { +#ifndef DHD_USE_STATIC_BUF MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); +#endif dhd->prot = NULL; } @@ -507,17 +506,120 @@ dhd_prot_dstats(dhd_pub_t *dhd) return; } +int dhd_set_suspend(int value, dhd_pub_t *dhd) +{ + int power_mode = PM_MAX; + wl_pkt_filter_enable_t enable_parm; + char iovbuf[32]; + int bcn_li_dtim = 3; +#ifdef CUSTOMER_HW2 + uint roamvar = 1; +#endif /* CUSTOMER_HW2 */ + +#define htod32(i) i + + if (dhd && dhd->up) { + if (value) { + dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, + (char *)&power_mode, sizeof(power_mode)); + /* Enable packet filter, only allow unicast packet to send up */ + enable_parm.id = htod32(100); + enable_parm.enable = htod32(1); + bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, + sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + /* set bcn_li_dtim */ + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); +#ifdef CUSTOMER_HW2 + /* Disable build-in roaming to allowed ext supplicant to take of romaing */ + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); +#endif /* CUSTOMER_HW2 */ + } else { + power_mode = PM_FAST; + dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, + sizeof(power_mode)); + /* disable pkt filter */ + enable_parm.id = htod32(100); + enable_parm.enable = htod32(0); + bcm_mkiovar("pkt_filter_enable", (char *)&enable_parm, + sizeof(wl_pkt_filter_enable_t), iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + /* set bcn_li_dtim */ + bcn_li_dtim = 0; + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, + 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); +#ifdef CUSTOMER_HW2 + roamvar = 0; + bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); +#endif /* CUSTOMER_HW2 */ + } + } + + return 0; +} + +#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) + +/* Convert user's input in hex pattern to byte-size mask */ +static int +wl_pattern_atoh(char *src, char *dst) +{ + int i; + if (strncmp(src, "0x", 2) != 0 && + strncmp(src, "0X", 2) != 0) { + printf("Mask invalid format. Needs to start with 0x\n"); + return -1; + } + src = src + 2; /* Skip past 0x */ + if (strlen(src) % 2 != 0) { + printf("Mask invalid format. Needs to be of even length\n"); + return -1; + } + for (i = 0; *src != '\0'; i++) { + char num[3]; + strncpy(num, src, 2); + num[2] = '\0'; + dst[i] = (uint8)strtoul(num, NULL, 16); + src += 2; + } + return i; +} + int dhd_preinit_ioctls(dhd_pub_t *dhd) { char eventmask[WL_EVENTING_MASK_LEN]; char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - + int ret; uint up = 0; +#ifdef CUSTOMER_HW2 + uint roamvar = 0; +#else uint roamvar = 1; +#endif uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; - int ret; + uint32 glom = 0; + + uint bcn_timeout = 3; + int arpoe = 1; + int arp_ol = 0xf; + int scan_assoc_time = 40; + int scan_unassoc_time = 80; + const char *str; + wl_pkt_filter_t pkt_filter; + wl_pkt_filter_t *pkt_filterp; + int buf_len; + int str_len; + uint32 mask_size; + uint32 pattern_size; + char buf[256]; + uint filter_mode = 1; /* Get the device MAC address */ strcpy(iovbuf, "cur_etheraddr"); @@ -542,19 +644,27 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - /* Force STA UP */ - dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up)); + /* disable glom option per default */ + bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + /* Setup timeout if Beacons are lost and roam is off to report link down */ + if (roamvar) { + bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + } - /* Disable build-in roaming to allowed ext supplicant to take of romaing */ + /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + /* Force STA UP */ + dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up)); + /* Setup event_msgs */ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf)); bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); - /* Setup event_msgs */ setbit(eventmask, WLC_E_SET_SSID); setbit(eventmask, WLC_E_PRUNE); setbit(eventmask, WLC_E_AUTH); @@ -576,6 +686,69 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + + dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, + sizeof(scan_assoc_time)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, + sizeof(scan_unassoc_time)); + + /* Set ARP offload */ + bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + + /* add a default packet filter pattern */ + str = "pkt_filter_add"; + str_len = strlen(str); + strncpy(buf, str, str_len); + buf[ str_len ] = '\0'; + buf_len = str_len + 1; + + pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1); + + /* Parse packet filter id. */ + pkt_filter.id = htod32(100); + + /* Parse filter polarity. */ + pkt_filter.negate_match = htod32(0); + + /* Parse filter type. */ + pkt_filter.type = htod32(0); + + /* Parse pattern filter offset. */ + pkt_filter.u.pattern.offset = htod32(0); + + /* Parse pattern filter mask. */ + mask_size = htod32(wl_pattern_atoh("0xff", + (char *) pkt_filterp->u.pattern.mask_and_pattern)); + + /* Parse pattern filter pattern. */ + pattern_size = htod32(wl_pattern_atoh("0x00", + (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); + + if (mask_size != pattern_size) { + printk("Mask and pattern not the same size\n"); + return -1; + } + + pkt_filter.u.pattern.size_bytes = mask_size; + buf_len += WL_PKT_FILTER_FIXED_LEN; + buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); + + /* Keep-alive attributes are set in local variable (keep_alive_pkt), and + ** then memcpy'ed into buffer (keep_alive_pktp) since there is no + ** guarantee that the buffer is properly aligned. + */ + memcpy((char *)pkt_filterp, &pkt_filter, + WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); + + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len); + + /* set mode to allow pattern */ + bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + return 0; } @@ -583,13 +756,8 @@ int dhd_prot_init(dhd_pub_t *dhd) { int ret = 0; - char buf[128]; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - /* Get the device MAC address */ - strcpy(buf, "cur_etheraddr"); - dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf)); - memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); ret = dhd_preinit_ioctls(dhd); diff --git a/bcm4329/src/dhd/sys/dhd_common.c b/bcm4329/src/dhd/sys/dhd_common.c index c96a0ac..eff07f2 100644 --- a/bcm4329/src/dhd/sys/dhd_common.c +++ b/bcm4329/src/dhd/sys/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,v 1.5.6.8.2.6.6.32 2009/06/04 23:07:41 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.37 2009/10/22 14:47:18 Exp $ */ #include <typedefs.h> #include <osl.h> @@ -90,6 +90,7 @@ const bcm_iovar_t dhd_iovars[] = { {NULL, 0, 0, 0, 0 } }; + void dhd_common_init(void) { @@ -100,16 +101,8 @@ dhd_common_init(void) * first time that the driver is initialized vs subsequent initializations. */ dhd_msg_level = DHD_ERROR_VAL; -#ifdef CONFIG_BCM4329_FW_PATH - strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN-1); -#else fw_path[0] = '\0'; -#endif -#ifdef CONFIG_BCM4329_NVRAM_PATH - strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN-1); -#else nv_path[0] = '\0'; -#endif } static int @@ -312,14 +305,21 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) return FALSE; /* refuse newer (incoming) packet */ /* Evict packet according to discard policy */ p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec); - ASSERT(p); + if (p == NULL) { + DHD_ERROR(("%s: pktq_penq() failed, oldest %d.", + __FUNCTION__, discard_oldest)); + ASSERT(p); + } PKTFREE(dhdp->osh, p, TRUE); } /* Enqueue */ p = pktq_penq(q, prec, pkt); - ASSERT(p); + if (p == NULL) { + DHD_ERROR(("%s: pktq_penq() failed.", __FUNCTION__)); + ASSERT(p); + } return TRUE; } @@ -382,6 +382,8 @@ dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (!buf) return BCME_BADARG; + switch (ioc->cmd) { case DHD_GET_MAGIC: if (buflen < sizeof(int)) @@ -451,7 +453,7 @@ dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) } #ifdef APSTA_PINGTEST -struct ether_addr guest_eas[MAX_GUEST] = {}; +struct ether_addr guest_eas[MAX_GUEST]; #endif #ifdef SHOW_EVENTS @@ -774,13 +776,18 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, char *event_data; uint32 type, status; uint16 flags; + int evlen; - if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) + if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) { + DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__)); return (BCME_ERROR); + } /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ - if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) + if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) { + DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__)); return (BCME_ERROR); + } *data_ptr = &pvt_data[1]; event_data = *data_ptr; @@ -791,17 +798,21 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, type = ntoh32_ua((void *)&event->event_type); flags = ntoh16_ua((void *)&event->flags); status = ntoh32_ua((void *)&event->status); + evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t); switch (type) { case WLC_E_IF: { dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; + DHD_TRACE(("%s: if event\n", __FUNCTION__)); if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) { if (ifevent->action == WLC_E_IF_ADD) dhd_add_if(dhd, ifevent->ifidx, - NULL, event->ifname, pvt_data->eth.ether_dhost); + NULL, event->ifname, + pvt_data->eth.ether_dhost, + ifevent->flags, ifevent->bssidx); else dhd_del_if(dhd, ifevent->ifidx); } else { @@ -809,17 +820,44 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, __FUNCTION__, ifevent->ifidx, event->ifname)); } } + /* send up the if event: btamp user needs it */ + *ifidx = dhd_ifname2idx(dhd, event->ifname); + /* push up to external supp/auth */ + dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); + break; + + +#ifdef P2P + case WLC_E_NDIS_LINK: break; +#endif + /* fall through */ + /* These are what external supplicant/authenticator wants */ case WLC_E_LINK: - case WLC_E_DEAUTH: - case WLC_E_DEAUTH_IND: - case WLC_E_DISASSOC: + case WLC_E_ASSOC_IND: + case WLC_E_REASSOC_IND: case WLC_E_DISASSOC_IND: - DHD_EVENT(("%s: Link event %d, flags %x, status %x\n", - __FUNCTION__, type, flags, status)); + case WLC_E_MIC_ERROR: default: + /* Fall through: this should get _everything_ */ + *ifidx = dhd_ifname2idx(dhd, event->ifname); - DHD_EVENT(("%s: event %d, idx %d\n", __FUNCTION__, type, *ifidx)); + /* push up to external supp/auth */ + dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); + DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n", + __FUNCTION__, type, flags, status)); + + /* put it back to WLC_E_NDIS_LINK */ + if (type == WLC_E_NDIS_LINK) { + uint32 temp; + + temp = ntoh32_ua((void *)&event->event_type); + DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp)); + + temp = ntoh32(WLC_E_NDIS_LINK); + memcpy((void *)(&pvt_data->event.event_type), &temp, + sizeof(pvt_data->event.event_type)); + } break; } diff --git a/bcm4329/src/dhd/sys/dhd_custom_gpio.c b/bcm4329/src/dhd/sys/dhd_custom_gpio.c index d0dc970..4da20ab 100644 --- a/bcm4329/src/dhd/sys/dhd_custom_gpio.c +++ b/bcm4329/src/dhd/sys/dhd_custom_gpio.c @@ -20,7 +20,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * -* $Id: dhd_custom_gpio.c,v 1.1.4.2 2009/04/13 06:09:38 Exp $ +* $Id: dhd_custom_gpio.c,v 1.1.4.3 2009/10/14 04:29:34 Exp $ */ @@ -28,193 +28,96 @@ #include <linuxver.h> #include <osl.h> #include <bcmutils.h> + #include <dngl_stats.h> #include <dhd.h> #include <wlioctl.h> #include <wl_iw.h> -#include <linux/platform_device.h> -#include <linux/wifi_tiwlan.h> - -#include <linux/gpio.h> -#ifdef CONFIG_HAS_WAKELOCK -#include <linux/wakelock.h> -#endif - -static struct wifi_platform_data *wifi_control_data = NULL; -static struct resource *wifi_irqres = NULL; -static dhd_pub_t *wifi_dhd_pub = NULL; -#ifdef MODULE -DECLARE_COMPLETION(sdio_wait); -#endif - -static int wifi_set_carddetect( int on ) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_carddetect) { - wifi_control_data->set_carddetect(on); - } - return 0; -} - -static int wifi_set_power( int on, unsigned long msec ) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_power) { - wifi_control_data->set_power(on); - } - if (msec) - mdelay(msec); - return 0; -} - -static int wifi_set_reset( int on, unsigned long msec ) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_reset) { - wifi_control_data->set_reset(on); - } - if (msec) - mdelay(msec); - return 0; -} - -irqreturn_t dhd_ext_irq_handler( int irq, void *pub, struct pt_regs *cpu_regs ) -{ - printk("%s\n", __FUNCTION__); - dhd_os_disable_irq(pub); - return IRQ_HANDLED; -} - -static int wifi_probe( struct platform_device *pdev ) -{ - struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); - - printk("%s\n", __FUNCTION__); - wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); - if (wifi_irqres) { - printk("wifi_irqres->start = %lu\n", (unsigned long)(wifi_irqres->start)); - printk("wifi_irqres->flags = %lx\n", wifi_irqres->flags); - } - wifi_control_data = wifi_ctrl; - wifi_set_power(1, 0); - wifi_set_reset(0, 0); - wifi_set_carddetect(1); - return 0; -} +#define WL_ERROR(x) printf x +#define WL_TRACE(x) -int dhdsdio_bussleep(struct dhd_bus *bus, bool sleep); +#ifdef CUSTOMER_HW +extern void bcm_wlan_power_off(int); +extern void bcm_wlan_power_on(int); +#endif /* CUSTOMER_HW */ -static int wifi_suspend( struct platform_device *pdev, pm_message_t state ) -{ - int rc = 0; +#if defined(OOB_INTR_ONLY) - printk("%s\n", __FUNCTION__); - if (wifi_dhd_pub && !wifi_dhd_pub->dongle_reset) { - rc = dhdsdio_bussleep(wifi_dhd_pub->bus, 1); - if (!rc) - dhd_os_enable_irq(wifi_dhd_pub); - } - return rc; -} +#if defined(BCMLXSDMMC) +extern int sdioh_mmc_irq(int irq); +#endif /* (BCMLXSDMMC) */ -static int wifi_resume( struct platform_device *pdev ) -{ - int rc = 0; +/* Customer specific Host GPIO defintion */ +static int dhd_oob_gpio_num = -1; /* GG 19 */ - printk("%s\n", __FUNCTION__); - if (wifi_dhd_pub && !wifi_dhd_pub->dongle_reset) { - rc = dhdsdio_bussleep(wifi_dhd_pub->bus, 0); - if (!rc) - dhd_sched_dpc(wifi_dhd_pub); - } - return rc; -} - -static int wifi_remove( struct platform_device *pdev ) -{ - struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); - - printk("%s\n", __FUNCTION__); - wifi_control_data = wifi_ctrl; - wifi_set_carddetect(0); - wifi_set_reset(1, 0); - wifi_set_power(0, 0); - return 0; -} +module_param(dhd_oob_gpio_num, int, 0644); +MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number"); -static struct platform_driver bcm4329_wlan_device = { - .probe = wifi_probe, - .remove = wifi_remove, - .suspend = wifi_suspend, - .resume = wifi_resume, - .driver = { - .name = "bcm4329_wlan", - }, -}; - -int dhd_customer_wifi_complete( void *pub ) +int dhd_customer_oob_irq_map(void) { - int rc = -ENODEV; - - printk("%s\n", __FUNCTION__); - if (!pub) { - printk(KERN_WARNING "%s: No network device\n", __FUNCTION__); - goto end; - } - if (!wifi_irqres || !(wifi_irqres->start)) { - printk(KERN_WARNING "%s: No platform resources\n", __FUNCTION__); - goto end; +int host_oob_irq; +#if defined(CUSTOM_OOB_GPIO_NUM) + if (dhd_oob_gpio_num < 0) { + dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM; } - wifi_dhd_pub = pub; - if ((rc = request_irq(wifi_irqres->start, (irq_handler_t)dhd_ext_irq_handler, wifi_irqres->flags & IRQF_TRIGGER_MASK, wifi_irqres->name, pub))) { - printk(KERN_ERR "%s: Failed to register interrupt handler\n", __FUNCTION__); - goto end; - } - set_irq_wake(wifi_irqres->start, 1); - dhd_os_set_irq(wifi_irqres->start, pub); -end: -#ifdef MODULE - complete(&sdio_wait); #endif - return rc; -} -int dhd_customer_wifi_add_dev( void ) -{ - printk("%s\n", __FUNCTION__); - - if (platform_driver_register(&bcm4329_wlan_device)) - return -ENODEV; -#ifdef MODULE - if (!wait_for_completion_timeout(&sdio_wait, msecs_to_jiffies(10000))) { - printk(KERN_ERR "%s: Timed out waiting for device detect\n", __FUNCTION__); - return -ENODEV; + if (dhd_oob_gpio_num < 0) { + WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n", \ + __FUNCTION__)); + return (dhd_oob_gpio_num); } -#endif - return 0; -} -void dhd_customer_wifi_del_dev( void ) -{ - printk("%s\n", __FUNCTION__); - set_irq_wake(wifi_irqres->start, 0); - free_irq(wifi_irqres->start, wifi_dhd_pub); - platform_driver_unregister( &bcm4329_wlan_device ); + WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", \ + __FUNCTION__, dhd_oob_gpio_num)); + + /* TODO : move it mmc specific code */ + host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num); + return (host_oob_irq); } +#endif /* defined(OOB_INTR_ONLY) */ -/* Customer specific function to insert/remove wlan reset gpio pin */ -void dhd_customer_gpio_wlan_reset( bool onoff ) +/* Customer function to control hw specific wlan gpios */ +void +dhd_customer_gpio_wlan_ctrl(int onoff) { - if (onoff == G_WLAN_SET_OFF) { - printk("%s: assert WLAN RESET\n", __FUNCTION__); - wifi_set_reset(1, 0); - wifi_set_power(0, 0); - } - else { - printk("%s: remove WLAN RESET\n", __FUNCTION__); - wifi_set_power(1, 0); - wifi_set_reset(0, 0); + switch (onoff) { + case WLAN_RESET_OFF: + WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n", + __FUNCTION__)); +#ifdef CUSTOMER_HW + bcm_wlan_power_off(2); +#endif /* CUSTOMER_HW */ + WL_ERROR(("=========== WLAN placed in RESET ========\n")); + break; + + case WLAN_RESET_ON: + WL_TRACE(("%s: callc customer specific GPIO to remove WLAN RESET\n", + __FUNCTION__)); +#ifdef CUSTOMER_HW + bcm_wlan_power_on(2); +#endif /* CUSTOMER_HW */ + WL_ERROR(("=========== WLAN going back to live ========\n")); + break; + + case WLAN_POWER_OFF: + WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n", + __FUNCTION__)); +#ifdef CUSTOMER_HW + bcm_wlan_power_off(1); +#endif /* CUSTOMER_HW */ + break; + + case WLAN_POWER_ON: + WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n", + __FUNCTION__)); +#ifdef CUSTOMER_HW + bcm_wlan_power_on(1); +#endif /* CUSTOMER_HW */ + /* Lets customer power to get stable */ + OSL_DELAY(500); + break; } } diff --git a/bcm4329/src/dhd/sys/dhd_dbg.h b/bcm4329/src/dhd/sys/dhd_dbg.h index 8ec6d33..581b17d 100644 --- a/bcm4329/src/dhd/sys/dhd_dbg.h +++ b/bcm4329/src/dhd/sys/dhd_dbg.h @@ -1,6 +1,5 @@ /* * Debug/trace/assert driver definitions for Dongle Host Driver. - * basically copied from WL driver. * * Copyright (C) 1999-2009, Broadcom Corporation * diff --git a/bcm4329/src/dhd/sys/dhd_linux.c b/bcm4329/src/dhd/sys/dhd_linux.c index aacc4fb..e5f84c0 100644 --- a/bcm4329/src/dhd/sys/dhd_linux.c +++ b/bcm4329/src/dhd/sys/dhd_linux.c @@ -22,9 +22,12 @@ * software 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,v 1.65.4.9.2.12.2.32 2009/06/26 07:03:26 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.46 2009/10/28 10:35:11 Exp $ */ +#ifdef CONFIG_WIFI_CONTROL_FUNC +#include <linux/platform_device.h> +#endif #include <typedefs.h> #include <linuxver.h> #include <osl.h> @@ -54,12 +57,99 @@ #include <dhd_bus.h> #include <dhd_proto.h> #include <dhd_dbg.h> +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +/* To make sdio host driver ignore card insert/remove information */ +struct wifi_platform_data { + char *name; + int (*set_power)(int val); + int (*set_reset)(int val); + int (*set_carddetect)(int val); + void *(*mem_prealloc)(int section, unsigned long size); +}; -#ifdef CONFIG_HAS_WAKELOCK -#include <linux/wakelock.h> -#endif -#include <linux/freezer.h> +struct semaphore wifi_control_sem; + +struct dhd_bus *g_bus; + +static struct wifi_platform_data *wifi_control_data = NULL; + +static int wifi_probe(struct platform_device *pdev) +{ + struct wifi_platform_data *wifi_ctrl = + (struct wifi_platform_data *)(pdev->dev.platform_data); + + DHD_TRACE(("## %s\n", __FUNCTION__)); + if (wifi_ctrl) { + wifi_control_data = wifi_ctrl; + if (wifi_ctrl->set_power) + wifi_ctrl->set_power(1); /* Power On */ + if (wifi_ctrl->set_carddetect) + wifi_ctrl->set_carddetect(1); /* CardDetect (0->1) */ + } + + up(&wifi_control_sem); + return 0; +} + +static int wifi_remove(struct platform_device *pdev) +{ + struct wifi_platform_data *wifi_ctrl = + (struct wifi_platform_data *)(pdev->dev.platform_data); + + DHD_TRACE(("## %s\n", __FUNCTION__)); + if (wifi_ctrl) { + if (wifi_ctrl->set_carddetect) + wifi_ctrl->set_carddetect(0); /* CardDetect (1->0) */ + if (wifi_ctrl->set_power) + wifi_ctrl->set_power(0); /* Power Off */ + } + up(&wifi_control_sem); + return 0; +} +static int wifi_suspend(struct platform_device *pdev, pm_message_t state) +{ + DHD_TRACE(("##> %s\n", __FUNCTION__)); + return 0; +} +static int wifi_resume(struct platform_device *pdev) +{ + DHD_TRACE(("##> %s\n", __FUNCTION__)); + return 0; +} +static struct platform_driver wifi_device = { + .probe = wifi_probe, + .remove = wifi_remove, + .suspend = wifi_suspend, + .resume = wifi_resume, + .driver = { + .name = "msm_wifi", + } +}; + +int wifi_add_dev(void) +{ + DHD_TRACE(("## Calling platform_driver_register\n")); + return platform_driver_register(&wifi_device); +} + +void wifi_del_dev(void) +{ + DHD_TRACE(("## Unregister platform_driver_register\n")); + platform_driver_unregister(&wifi_device); +} +#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) +#include <linux/suspend.h> +volatile bool dhd_mmc_suspend = FALSE; +DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + +#if defined(OOB_INTR_ONLY) +extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); +#endif /* defined(OOB_INTR_ONLY) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) MODULE_LICENSE("GPL v2"); #endif /* LinuxVer */ @@ -77,6 +167,10 @@ print_tainted() #include <wl_iw.h> #endif /* CONFIG_WIRELESS_EXT */ +#if defined(CONFIG_HAS_EARLYSUSPEND) +#include <linux/earlysuspend.h> +#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ + /* Interface control information */ typedef struct dhd_if { struct dhd_info *info; /* back pointer to dhd_info */ @@ -120,17 +214,6 @@ typedef struct dhd_info { struct semaphore dpc_sem; struct completion dpc_exited; - /* Wakelocks */ -#ifdef CONFIG_HAS_WAKELOCK - struct wake_lock wl_wifi; /* Wifi wakelock */ - struct wake_lock wl_rxwake; /* Wifi rx wakelock */ -#endif - spinlock_t wl_lock; - int wl_count; - int wl_packet; - unsigned int oob_irq; - int oob_irq_flag; - /* Thread to issue ioctl for multicast */ long sysioc_pid; struct semaphore sysioc_sem; @@ -139,6 +222,11 @@ typedef struct dhd_info { bool set_macaddress; struct ether_addr macvalue; wait_queue_head_t ctrl_wait; + atomic_t pend_8021x_cnt; + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif /* CONFIG_HAS_EARLYSUSPEND */ } dhd_info_t; /* Definitions to provide path to the firmware and nvram @@ -147,6 +235,9 @@ typedef struct dhd_info { char firmware_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 +struct semaphore dhd_registration_sem; +#endif /* load firmware and/or nvram values from the filesystem */ module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0); module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); @@ -159,7 +250,7 @@ uint dhd_sysioc = TRUE; module_param(dhd_sysioc, uint, 0); /* Watchdog interval */ -uint dhd_watchdog_ms = 1000; +uint dhd_watchdog_ms = 10; module_param(dhd_watchdog_ms, uint, 0); @@ -256,6 +347,8 @@ struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); #endif /* CONFIG_WIRELESS_EXT */ static void dhd_dpc(ulong data); +/* forward decl */ +extern int dhd_wait_pend8021x(struct net_device *dev); #ifdef TOE #ifndef BDC @@ -268,6 +361,55 @@ static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event_ptr, void **data_ptr); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) +static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) +{ + switch (action) + { + case PM_HIBERNATION_PREPARE: + case PM_SUSPEND_PREPARE: + dhd_mmc_suspend = TRUE; + return NOTIFY_OK; + case PM_POST_HIBERNATION: + case PM_POST_SUSPEND: + dhd_mmc_suspend = FALSE; + return NOTIFY_OK; + } + return 0; +} + +static struct notifier_block dhd_sleep_pm_notifier = { + .notifier_call = dhd_sleep_pm_callback, + .priority = 0 +}; +extern int register_pm_notifier(struct notifier_block *nb); +extern int unregister_pm_notifier(struct notifier_block *nb); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + + +#if defined(CONFIG_HAS_EARLYSUSPEND) +extern int dhd_set_suspend(int value, dhd_pub_t *dhd); + +static void dhd_early_suspend(struct early_suspend *h) +{ + struct dhd_info *dhdp; + dhdp = container_of(h, struct dhd_info, early_suspend); + + DHD_TRACE(("%s: enter\n", __FUNCTION__)); + + dhd_set_suspend(1, &dhdp->pub); +} + +static void dhd_late_resume(struct early_suspend *h) +{ + struct dhd_info *dhdp; + dhdp = container_of(h, struct dhd_info, early_suspend); + + DHD_TRACE(("%s: enter\n", __FUNCTION__)); + + dhd_set_suspend(0, &dhdp->pub); +} +#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ /* * Generalized timeout mechanism. Uses spin sleep with exponential back-off until @@ -647,6 +789,7 @@ int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) { int ret; + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); /* Reject if down */ if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { @@ -660,6 +803,8 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) if (ETHER_ISMULTI(eh->ether_dhost)) dhdp->tx_multicast++; + if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) + atomic_inc(&dhd->pend_8021x_cnt); } /* Look into the packet and update the packet priority */ @@ -670,7 +815,12 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) dhd_prot_hdrpush(dhdp, ifidx, pktbuf); /* Use bus module to send data frame */ +#ifdef BCMDBUS + ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */); +#else + WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25); ret = dhd_bus_txdata(dhdp->bus, pktbuf); +#endif /* BCMDBUS */ return ret; } @@ -687,6 +837,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) /* Reject if down */ if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) { + DHD_ERROR(("%s: xmit rejected due to dhd bus down status \n", __FUNCTION__)); return -ENODEV; } @@ -763,7 +914,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) int i; dhd_if_t *ifp; wl_event_msg_t event; - unsigned long flags; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -819,10 +969,12 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) &data); ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); - if (dhd->iflist[ifidx]) + if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state) ifp = dhd->iflist[ifidx]; - ifp->net->last_rx = jiffies; + if (ifp->net) + ifp->net->last_rx = jiffies; + dhdp->dstats.rx_bytes += skb->len; dhdp->rx_packets++; /* Local count */ @@ -846,15 +998,20 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ } } - spin_lock_irqsave(&dhd->wl_lock, flags); - dhd->wl_packet = 1; - spin_unlock_irqrestore(&dhd->wl_lock, flags); +} + +void +dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx) +{ + /* Linux version has nothing to do */ + return; } void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) { - int ifidx; + uint ifidx; + dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); struct ether_header *eh; uint16 type; @@ -863,6 +1020,9 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); type = ntoh16(eh->ether_type); + if (type == ETHER_TYPE_802_1X) + atomic_dec(&dhd->pend_8021x_cnt); + } static struct net_device_stats * @@ -904,6 +1064,7 @@ static int dhd_watchdog_thread(void *data) { dhd_info_t *dhd = (dhd_info_t *)data; + WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread"); /* This thread doesn't need any user-level access, * so get rid of all our resources @@ -917,15 +1078,15 @@ dhd_watchdog_thread(void *data) } #endif /* DHD_SCHED */ - set_freezable(); - DAEMONIZE("dhd_watchdog"); /* Run until signal received */ while (1) { if (down_interruptible (&dhd->watchdog_sem) == 0) { + WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG); /* Call the bus module watchdog */ dhd_bus_watchdog(&dhd->pub); + WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG); /* Count the tick for reference */ dhd->pub.tickcnt++; @@ -939,6 +1100,7 @@ dhd_watchdog_thread(void *data) break; } + WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG); complete_and_exit(&dhd->watchdog_exited, 0); } @@ -968,6 +1130,7 @@ dhd_dpc_thread(void *data) { dhd_info_t *dhd = (dhd_info_t *)data; + WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread"); /* This thread doesn't need any user-level access, * so get rid of all our resources */ @@ -980,8 +1143,6 @@ dhd_dpc_thread(void *data) } #endif /* DHD_SCHED */ - set_freezable(); - DAEMONIZE("dhd_dpc"); /* Run until signal received */ @@ -989,19 +1150,22 @@ dhd_dpc_thread(void *data) if (down_interruptible(&dhd->dpc_sem) == 0) { /* Call bus dpc unless it indicated down (then clean stop) */ if (dhd->pub.busstate != DHD_BUS_DOWN) { - if (dhd_bus_dpc(dhd->pub.bus)) + WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC); + if (dhd_bus_dpc(dhd->pub.bus)) { up(&dhd->dpc_sem); - else - dhd_os_wake_unlock(&dhd->pub); + WAKE_LOCK_TIMEOUT(&dhd->pub, WAKE_LOCK_TMOUT, 25); + } + WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC); } else { dhd_bus_stop(dhd->pub.bus, TRUE); - dhd_os_wake_unlock(&dhd->pub); } } else break; } + WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC); + complete_and_exit(&dhd->dpc_exited, 0); } @@ -1026,7 +1190,6 @@ dhd_sched_dpc(dhd_pub_t *dhdp) { dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - dhd_os_wake_lock(dhdp); if (dhd->dpc_pid >= 0) { up(&dhd->dpc_sem); return; @@ -1151,6 +1314,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) if (copy_from_user(&info, uaddr, sizeof(info))) return -EFAULT; strncpy(drvname, info.driver, sizeof(info.driver)); + drvname[sizeof(info.driver)-1] = '\0'; /* clear struct for return */ memset(&info, 0, sizeof(info)); @@ -1163,8 +1327,10 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) } /* otherwise, require dongle to be up */ - else if (!dhd->pub.up) + else if (!dhd->pub.up) { + DHD_ERROR(("%s: dongle is not up\n", __FUNCTION__)); return -ENODEV; + } /* finally, report dongle driver type */ else if (dhd->pub.iswl) @@ -1244,6 +1410,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) void *buf = NULL; uint driver = 0; int ifidx; + bool is_set_key_cmd; ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); @@ -1327,10 +1494,26 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) goto done; } + /* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to + * prevent M4 encryption. + */ + is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) || + ((ioc.cmd == WLC_SET_VAR) && + !(strncmp("wsec_key", ioc.buf, 9))) || + ((ioc.cmd == WLC_SET_VAR) && + !(strncmp("bsscfg:wsec_key", ioc.buf, 15)))); + if (is_set_key_cmd) { + dhd_wait_pend8021x(net); + } + WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry"); + WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL); + bcmerror = dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); + WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL); + WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL); done: - if (!bcmerror && ioc.buf) { + if (!bcmerror && buf && ioc.buf) { if (copy_to_user(ioc.buf, buf, buflen)) bcmerror = -EFAULT; } @@ -1344,13 +1527,21 @@ done: static int dhd_stop(struct net_device *net) { +#if !defined(IGNORE_ETH0_DOWN) dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (dhd->pub.up == 0) { + return 0; + } + /* Set state and stop OS transmissions */ dhd->pub.up = 0; netif_stop_queue(net); +#else + DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation ...\n", __FUNCTION__)); +#endif /* !defined(IGNORE_ETH0_DOWN) */ OLD_MOD_DEC_USE_COUNT; return 0; @@ -1364,18 +1555,13 @@ dhd_open(struct net_device *net) uint32 toe_ol; #endif int ifidx; - int ret; ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); ASSERT(ifidx == 0); - /* try to bring up bus */ - if ((ret = dhd_bus_start(&dhd->pub)) != 0) { - DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); - return -1; - } + atomic_set(&dhd->pend_8021x_cnt, 0); memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); @@ -1408,10 +1594,14 @@ dhd_osl_detach(osl_t *osh) DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); } osl_detach(osh); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 + up(&dhd_registration_sem); +#endif } int -dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, uint8 *mac_addr) +dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, + uint8 *mac_addr, uint32 flags, uint8 bssidx) { dhd_if_t *ifp; @@ -1491,9 +1681,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) memset(dhd, 0, sizeof(dhd_info_t)); + /* + * Save the dhd_info into the priv + */ + memcpy(netdev_priv(net), &dhd, sizeof(dhd)); dhd->pub.osh = osh; - if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL) == DHD_BAD_IF) + if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF) goto fail; net->open = NULL; @@ -1507,15 +1701,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) spin_lock_init(&dhd->sdlock); spin_lock_init(&dhd->txqlock); - /* Initialize Wakelock stuff */ - spin_lock_init(&dhd->wl_lock); - dhd->wl_count = 0; - dhd->wl_packet = 0; -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); - wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); -#endif - /* Link to info module */ dhd->pub.info = dhd; @@ -1530,7 +1715,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) } #ifdef CONFIG_WIRELESS_EXT /* Attach and link in the iw */ - if (wl_iw_attach(net) != 0) { + if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { DHD_ERROR(("wl_iw_attach failed\n")); goto fail; } @@ -1583,6 +1768,23 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) */ memcpy(netdev_priv(net), &dhd, sizeof(dhd)); +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) + g_bus = bus; +#endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + register_pm_notifier(&dhd_sleep_pm_notifier); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + /* Init lock suspend to prevent kernel going to suspend */ + WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock"); + WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT, "dhd_wake_lock_link_dw_event"); + +#ifdef CONFIG_HAS_EARLYSUSPEND + dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; + dhd->early_suspend.suspend = dhd_early_suspend; + dhd->early_suspend.resume = dhd_late_resume; + register_early_suspend(&dhd->early_suspend); +#endif + return &dhd->pub; fail: @@ -1607,12 +1809,19 @@ dhd_bus_start(dhd_pub_t *dhdp) /* try to download image and nvram to the dongle */ if (dhd->pub.busstate == DHD_BUS_DOWN) { + WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start"); + WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD); if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, fw_path, nv_path))) { DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", __FUNCTION__, fw_path, nv_path)); + WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD); + WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD); return -1; } + + WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD); + WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD); } /* Start the watchdog timer */ @@ -1624,6 +1833,18 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret)); return ret; } +#if defined(OOB_INTR_ONLY) + /* Host registration for OOB interrupt */ + if (bcmsdh_register_oob_intr(dhdp)) { + del_timer(&dhd->timer); + dhd->wd_timer_valid = FALSE; + DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__)); + return -ENODEV; + } + + /* Enable oob at firmware */ + dhd_enable_oob_intr(dhd->pub.bus, TRUE); +#endif /* defined(OOB_INTR_ONLY) */ /* If bus is not ready, can't come up */ if (dhd->pub.busstate != DHD_BUS_DATA) { @@ -1634,7 +1855,8 @@ dhd_bus_start(dhd_pub_t *dhdp) } /* Bus is ready, do any protocol initialization */ - dhd_prot_init(&dhd->pub); + if ((ret = dhd_prot_init(&dhd->pub)) < 0) + return ret; return 0; } @@ -1719,8 +1941,13 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) goto fail; } - printf("%s: Broadcom Dongle Host Driver\n", net->name); + printf("%s: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", net->name, + dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2], + dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 + up(&dhd_registration_sem); +#endif return 0; fail: @@ -1731,42 +1958,56 @@ fail: void dhd_bus_detach(dhd_pub_t *dhdp) { - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + dhd_info_t *dhd; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - /* Stop the protocol module */ - dhd_prot_stop(&dhd->pub); - - /* Stop the bus module */ - dhd_bus_stop(dhd->pub.bus, TRUE); - - /* Clear the watchdog timer */ - del_timer(&dhd->timer); - dhd->wd_timer_valid = FALSE; + if (dhdp) { + dhd = (dhd_info_t *)dhdp->info; + if (dhd) { + /* Stop the protocol module */ + dhd_prot_stop(&dhd->pub); + + /* Stop the bus module */ + dhd_bus_stop(dhd->pub.bus, TRUE); +#if defined(OOB_INTR_ONLY) + bcmsdh_unregister_oob_intr(); +#endif /* defined(OOB_INTR_ONLY) */ + + /* Clear the watchdog timer */ + del_timer(&dhd->timer); + dhd->wd_timer_valid = FALSE; + } + } } void dhd_detach(dhd_pub_t *dhdp) { - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + dhd_info_t *dhd; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - if (dhd) { - dhd_if_t *ifp; - int i; + if (dhdp) { + dhd = (dhd_info_t *)dhdp->info; + if (dhd) { + dhd_if_t *ifp; + int i; - for (i = 1; i < DHD_MAX_IFS; i++) - if (dhd->iflist[i]) - dhd_del_if(dhd, i); +#if defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&dhd->early_suspend); +#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ - ifp = dhd->iflist[0]; - ASSERT(ifp); - if (ifp->net->open) { - dhd_stop(ifp->net); - unregister_netdev(ifp->net); - } + for (i = 1; i < DHD_MAX_IFS; i++) + if (dhd->iflist[i]) + dhd_del_if(dhd, i); + + ifp = dhd->iflist[0]; + ASSERT(ifp); + if (ifp->net->open) { + dhd_stop(ifp->net); + unregister_netdev(ifp->net); + } if (dhd->watchdog_pid >= 0) @@ -1798,18 +2039,17 @@ dhd_detach(dhd_pub_t *dhdp) wl_iw_detach(); #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) + unregister_pm_notifier(&dhd_sleep_pm_notifier); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ + WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT); + WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT); free_netdev(ifp->net); -#ifdef CONFIG_HAS_WAKELOCK - wake_lock_destroy(&dhd->wl_wifi); - wake_lock_destroy(&dhd->wl_rxwake); -#endif MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); } } - -int dhd_customer_wifi_add_dev(void); -void dhd_customer_wifi_del_dev(void); +} static int __init dhd_module_init(void) @@ -1828,21 +2068,50 @@ dhd_module_init(void) if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0) && dhd_deferred_tx) break; - printk("Invalid module parameters.\n"); + DHD_ERROR(("Invalid module parameters.\n")); return -EINVAL; } while (0); +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) + sema_init(&wifi_control_sem, 0); + wifi_add_dev(); + + /* Waiting callback after platform_driver_register is done or exit with error */ + if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) { + error = 1; + DHD_ERROR(("%s: platform_driver_register callback timeout\n", __FUNCTION__)); + goto fail; + } +#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ + + /* Call customer gpio to turn on power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 + sema_init(&dhd_registration_sem, 0); +#endif + error = dhd_bus_register(); - if (error) - return error; - - error = dhd_customer_wifi_add_dev(); - if (error) { - printk(KERN_ERR "%s: Fail to add wifi device\n", __func__); - dhd_bus_unregister(); - } - else + + if (!error) printf("\n%s\n", dhd_version); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && 1 + /* + * Wait till MMC sdio_register_driver callback called and made driver attach. + * It's needed to make sync up exit from dhd insmod and + * Kernel MMC sdio device callback registration + */ + if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(3000)) != 0) { + error = 1; + DHD_ERROR(("%s: sdio_register_driver failed \n", __FUNCTION__)); + } +#endif + +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +fail: +#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ + return error; } @@ -1850,10 +2119,16 @@ static void __exit dhd_module_cleanup(void) { DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + dhd_bus_unregister(); - dhd_customer_wifi_del_dev(); +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) + wifi_del_dev(); +#endif + /* Call customer gpio to turn off power with WL_REG_ON signal */ + dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); } + module_init(dhd_module_init); module_exit(dhd_module_cleanup); @@ -2007,7 +2282,7 @@ dhd_os_sdlock(dhd_pub_t *pub) if (dhd->threads_only) down(&dhd->sdsem); else - spin_lock_bh(&dhd->sdlock); + spin_lock_bh(&dhd->sdlock); } void @@ -2020,7 +2295,7 @@ dhd_os_sdunlock(dhd_pub_t *pub) if (dhd->threads_only) up(&dhd->sdsem); else - spin_unlock_bh(&dhd->sdlock); + spin_unlock_bh(&dhd->sdlock); } void @@ -2061,6 +2336,29 @@ dhd_os_sdtxunlock(dhd_pub_t *pub) dhd_os_sdunlock(pub); } +#ifdef DHD_USE_STATIC_BUF +void * dhd_os_prealloc(int section, unsigned long size) +{ +#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) + void *alloc_ptr = NULL; + if (wifi_control_data && wifi_control_data->mem_prealloc) + { + alloc_ptr = wifi_control_data->mem_prealloc(section, size); + if (alloc_ptr) + { + DHD_INFO(("success alloc section %d\n", section)); + bzero(alloc_ptr, size); + return alloc_ptr; + } + } + + DHD_ERROR(("can't alloc section %d\n", section)); + return 0; +#else +return MALLOC(0, size); +#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ +} +#endif /* DHD_USE_STATIC_BUF */ #ifdef CONFIG_WIRELESS_EXT struct iw_statistics * dhd_get_wireless_stats(struct net_device *dev) @@ -2148,90 +2446,30 @@ dhd_dev_init_ioctl(struct net_device *dev) dhd_preinit_ioctls(&dhd->pub); } -int dhd_os_wake_lock_timeout(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dhd->wl_lock, flags); - if (dhd) { -#ifdef CONFIG_HAS_WAKELOCK - if (dhd->wl_packet) - wake_lock_timeout(&dhd->wl_rxwake, (HZ >> 1)); -#endif - dhd->wl_packet = 0; - } - ret = dhd->wl_packet; - spin_unlock_irqrestore(&dhd->wl_lock, flags); - /* printk("%s: %d\n", __FUNCTION__, ret); */ - return ret; -} - -int dhd_os_wake_lock(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dhd->wl_lock, flags); - if (dhd) { -#ifdef CONFIG_HAS_WAKELOCK - if (!dhd->wl_count) - wake_lock(&dhd->wl_wifi); -#endif - dhd->wl_count++; - ret = dhd->wl_count; - } - spin_unlock_irqrestore(&dhd->wl_lock, flags); - if (ret > 2) - printk("%s: Warning: %d\n", __FUNCTION__, ret); - return ret; -} - -int dhd_os_wake_unlock(dhd_pub_t *pub) +static int +dhd_get_pend_8021x_cnt(dhd_info_t *dhd) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&dhd->wl_lock, flags); - if (dhd && dhd->wl_count) { - dhd->wl_count--; -#ifdef CONFIG_HAS_WAKELOCK - if (!dhd->wl_count) - wake_unlock(&dhd->wl_wifi); -#endif - ret = dhd->wl_count; - } - spin_unlock_irqrestore(&dhd->wl_lock, flags); - /* printk("%s: %d\n", __FUNCTION__, ret); */ - return ret; + return (atomic_read(&dhd->pend_8021x_cnt)); } -void dhd_os_set_irq(unsigned int irq, dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); +#define MAX_WAIT_FOR_8021X_TX 10 - dhd->oob_irq = irq; - disable_irq(irq); - dhd->oob_irq_flag = 0; -} - -void dhd_os_disable_irq(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - disable_irq_nosync(dhd->oob_irq); - dhd->oob_irq_flag = 0; -} - -void dhd_os_enable_irq(dhd_pub_t *pub) +int +dhd_wait_pend8021x(struct net_device *dev) { - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (!(dhd->oob_irq_flag)) { - dhd->oob_irq_flag = 1; - enable_irq(dhd->oob_irq); + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + int timeout = 10 * HZ / 1000; + int ntimes = MAX_WAIT_FOR_8021X_TX; + int pend = dhd_get_pend_8021x_cnt(dhd); + + while (ntimes && pend) { + if (pend) { + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(timeout); + set_current_state(TASK_RUNNING); + ntimes--; + } + pend = dhd_get_pend_8021x_cnt(dhd); } + return pend; } diff --git a/bcm4329/src/dhd/sys/dhd_sdio.c b/bcm4329/src/dhd/sys/dhd_sdio.c index ec4a9fa..6e43e43 100644 --- a/bcm4329/src/dhd/sys/dhd_sdio.c +++ b/bcm4329/src/dhd/sys/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,v 1.157.2.27.2.33.2.77 2009/06/27 00:46:37 Exp $ + * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.89 2009/10/28 05:49:40 Exp $ */ #include <typedefs.h> @@ -60,8 +60,6 @@ #include <dhdioctl.h> #include <sdiovar.h> -#include <linux/gpio.h> - #define QLEN 256 /* bulk rx and tx queue lengths */ #define FCHI (QLEN - 10) #define FCLOW (FCHI / 2) @@ -140,6 +138,8 @@ */ #define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \ PKTFREE(bus->dhd->osh, pkt, FALSE); +DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); +extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); /* Private data for SDIO bus interaction */ @@ -323,6 +323,13 @@ static bool forcealign; #define ALIGNMENT 4 +#if defined(OOB_INTR_ONLY) && defined(HW_OOB) +extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); +#endif + +#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) +#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD +#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */ #define PKTALIGN(osh, p, len, align) \ do { \ uint datalign; \ @@ -425,6 +432,7 @@ static int dhdsdio_download_nvram(struct dhd_bus *bus); static int dhdsdio_download_code_array(struct dhd_bus *bus); #endif + static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) { @@ -463,6 +471,9 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +#if defined(OOB_INTR_ONLY) + pendok = FALSE; +#endif clkctl = 0; sdh = bus->sdh; @@ -521,7 +532,8 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) /* Otherwise, wait here (polling) for HT Avail */ if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { - SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, + SPINWAIT_SLEEP(sdioh_spinwait_sleep, + ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err)), !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY); } @@ -716,16 +728,8 @@ dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) return BCME_OK; } -int dhdsdio_oob(dhd_bus_t *bus) -{ - sdpcmd_regs_t *regs = bus->regs; - uint retries = 0; - - W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); - return 0; -} - -int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) +int +dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) { bcmsdh_info_t *sdh = bus->sdh; sdpcmd_regs_t *regs = bus->regs; @@ -745,6 +749,7 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) return BCME_BUSY; + /* Disable SDIO interrupts (no longer interested) */ bcmsdh_intr_disable(bus->sdh); @@ -763,21 +768,25 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); /* Isolate the bus */ -#if 0 - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, - SBSDIO_DEVCTL_PADS_ISO, NULL); -#endif + if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) { + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, + SBSDIO_DEVCTL_PADS_ISO, NULL); + } + /* Change state */ bus->sleeping = TRUE; } else { /* Waking up: bus power up is ok, set local state */ + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); + /* Force pad isolation off if possible (in case power never toggled) */ if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10)) bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); + /* Make sure the controller has the bus up */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); @@ -785,7 +794,8 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) W_SDREG(0, ®s->tosbmailboxdata, retries); if (retries <= retry_limit) W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); - else + + if (retries > retry_limit) DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n")); /* Make sure we have SD bus access */ @@ -800,8 +810,39 @@ int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) bcmsdh_intr_enable(bus->sdh); } } + return BCME_OK; } +#if defined(OOB_INTR_ONLY) +void +dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) +{ +#if defined(HW_OOB) + bcmsdh_enable_hw_oob_intr(bus->sdh, enable); +#else + sdpcmd_regs_t *regs = bus->regs; + uint retries = 0; + + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + if (enable == TRUE) { + + /* Tell device to start using OOB wakeup */ + W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); + if (retries > retry_limit) + DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n")); + + } else { + /* Send misc interrupt to indicate OOB not needed */ + W_SDREG(0, ®s->tosbmailboxdata, retries); + if (retries <= retry_limit) + W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); + } + + /* Turn off our contribution to the HT clock request */ + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); +#endif /* defined(HW_OOB) */ +} +#endif /* defined(OOB_INTR_ONLY) */ #define BUS_WAKE(bus) \ do { \ @@ -1466,7 +1507,7 @@ dhd_bus_clearcounts(dhd_pub_t *dhdp) dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0; - bus->rxrtx = bus->rx_toolong = bus->rx_toolong = bus->rxc_errors = 0; + bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0; bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0; bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0; bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0; @@ -1538,6 +1579,11 @@ dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint s uint32 sdaddr; uint dsize; + if (size % 4) { + size += 3; + size &= 0xFFFFFFFC; + } + /* Determine initial transfer parameters */ sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) @@ -1910,11 +1956,11 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch *(char *)arg = 0; bcmstrcat(arg, "\nFunc 0\n"); - bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), 49 * 32); + bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); bcmstrcat(arg, "\nFunc 1\n"); - bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), 49 * 32); + bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); bcmstrcat(arg, "\nFunc 2\n"); - bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), 49 * 32); + bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); break; } @@ -2064,7 +2110,6 @@ dhdsdio_write_vars(dhd_bus_t *bus) /* Compare the org NVRAM with the one read from RAM */ if (memcmp(vbuffer, nvram_ularray, varsize)) { DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__)); - ASSERT(0); } else DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n", __FUNCTION__)); @@ -3674,7 +3719,7 @@ dhdsdio_hostmail(dhd_bus_t *bus) return intstatus; } -static bool +bool dhdsdio_dpc(dhd_bus_t *bus) { bcmsdh_info_t *sdh = bus->sdh; @@ -3892,16 +3937,17 @@ clkwait: resched = TRUE; } - dhd_os_sdunlock(bus->dhd); bus->dpc_sched = resched; /* If we're done for now, turn off clock request. */ - if (bus->idletime == DHD_IDLE_IMMEDIATE) { + if ((bus->clkstate != CLK_PENDING) && bus->idletime == DHD_IDLE_IMMEDIATE) { bus->activity = FALSE; dhdsdio_clkctl(bus, CLK_NONE, FALSE); } - dhd_os_wake_lock_timeout(bus->dhd); /* Keep wake lock for rx */ + + dhd_os_sdunlock(bus->dhd); + return resched; } @@ -3927,6 +3973,11 @@ dhdsdio_isr(void *arg) dhd_bus_t *bus = (dhd_bus_t*)arg; bcmsdh_info_t *sdh = bus->sdh; + if (bus->dhd->busstate == DHD_BUS_DOWN) { + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); + return; + } + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); /* Count the interrupt call */ @@ -3950,13 +4001,13 @@ dhdsdio_isr(void *arg) bus->intdis = TRUE; #if defined(SDIO_ISR_THREAD) - dhd_os_wake_lock(bus->dhd); + DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); while (dhdsdio_dpc(bus)); - dhd_os_wake_unlock(bus->dhd); #else bus->dpc_sched = TRUE; dhd_sched_dpc(bus->dhd); #endif + } #ifdef SDTEST @@ -4326,8 +4377,6 @@ dhdsdio_chipmatch(uint16 chipid) return FALSE; } -int dhd_customer_wifi_complete(void *); - static void * dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh) @@ -4480,11 +4529,9 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); goto fail; } - if (dhd_customer_wifi_complete(bus->dhd)) { - DHD_ERROR(("%s: Platform resorce!!\n", __FUNCTION__)); - goto fail; - } + return bus; + fail: dhdsdio_release(bus, osh); return NULL; @@ -4645,6 +4692,7 @@ dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) { DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +#ifndef DHD_USE_STATIC_BUF if (bus->dhd->maxctl) { bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; if (!(bus->rxbuf = MALLOC(osh, bus->rxblen))) { @@ -4662,6 +4710,22 @@ dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) if (!bus->rxblen) MFREE(osh, bus->rxbuf, bus->rxblen); goto fail; } +#else + if (bus->dhd->maxctl) { + bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; + if (!(bus->rxbuf = dhd_os_prealloc(DHD_PREALLOC_RXBUF, bus->rxblen))) { + DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n", + __FUNCTION__, bus->rxblen)); + goto fail; + } + } + /* Allocate buffer to receive glomed packet */ + if (!(bus->databuf = dhd_os_prealloc(DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) { + DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n", + __FUNCTION__, MAX_DATA_BUF)); + goto fail; + } +#endif /* DHD_USE_STATIC_BUF */ /* Align the buffer */ if ((uintptr)bus->databuf % DHD_SDALIGN) @@ -4759,6 +4823,7 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, ret = dhdsdio_download_firmware(bus, osh, bus->sdh); + return ret; } @@ -4769,12 +4834,12 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) /* Download the firmware */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - dhd_os_wake_lock(bus->dhd); - ret = _dhdsdio_download_firmware(bus); - dhd_os_wake_unlock(bus->dhd); + + ret = _dhdsdio_download_firmware(bus) == 0; + dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); - return !ret; + return ret; } /* Detach and free everything */ @@ -4818,13 +4883,17 @@ dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) return; if (bus->rxbuf) { +#ifndef DHD_USE_STATIC_BUF MFREE(osh, bus->rxbuf, bus->rxblen); +#endif bus->rxctl = bus->rxbuf = NULL; bus->rxlen = 0; } if (bus->databuf) { +#ifndef DHD_USE_STATIC_BUF MFREE(osh, bus->databuf, MAX_DATA_BUF); +#endif bus->databuf = NULL; } } @@ -5066,7 +5135,7 @@ process_nvram_vars(char *varbuf, uint len) return buf_len; } -/* +/* EXAMPLE: nvram_array nvram_arry format: name=value @@ -5123,6 +5192,8 @@ dhdsdio_download_nvram(struct dhd_bus *bus) else { len = strlen(bus->nvram_params); ASSERT(len <= MEMBLOCK); + if (len > MEMBLOCK) + len = MEMBLOCK; memcpy(memblock, bus->nvram_params, len); } @@ -5283,6 +5354,10 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) if (flag == TRUE) { if (!bus->dhd->dongle_reset) { +#if !defined(IGNORE_ETH0_DOWN) + /* Force flow control as protection when stop come before ifconfig_down */ + dhd_txflowcontrol(bus->dhd, 0, ON); +#endif /* !defined(IGNORE_ETH0_DOWN) */ /* save country settinng if was pre-setup with priv ioctl */ dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY, bus->dhd->country_code, sizeof(bus->dhd->country_code)); @@ -5321,8 +5396,18 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) /* Re-init bus, enable F2 transfer */ dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); +#if defined(OOB_INTR_ONLY) + dhd_enable_oob_intr(bus, TRUE); +#endif /* defined(OOB_INTR_ONLY) */ + bus->dhd->dongle_reset = FALSE; bus->dhd->up = TRUE; + +#if !defined(IGNORE_ETH0_DOWN) + /* Restore flow control */ + dhd_txflowcontrol(bus->dhd, 0, OFF); +#endif + DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); } else bcmerror = BCME_SDIO_ERROR; diff --git a/bcm4329/src/include/bcmcdc.h b/bcm4329/src/include/bcmcdc.h index 8cf50bc..641d755 100644 --- a/bcm4329/src/include/bcmcdc.h +++ b/bcm4329/src/include/bcmcdc.h @@ -74,11 +74,7 @@ typedef struct cdc_ioctl { #define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ #define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ -#ifndef EXT_STA #define BDC_FLAG__UNUSED 0x03 /* Unassigned */ -#else -#define BDC_FLAG_EXEMPT 0x03 /* Vista/EXT_STA: use for encryption exemption */ -#endif /* EXT_STA */ #define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ #define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ diff --git a/bcm4329/src/include/bcmdefs.h b/bcm4329/src/include/bcmdefs.h index 2a494b9..ba7a9e4 100644 --- a/bcm4329/src/include/bcmdefs.h +++ b/bcm4329/src/include/bcmdefs.h @@ -20,38 +20,15 @@ * 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: bcmdefs.h,v 13.38.4.10.2.7.6.7 2009/05/21 06:48:31 Exp $ + * $Id: bcmdefs.h,v 13.38.4.10.2.7.6.10 2009/07/03 08:20:51 Exp $ */ #ifndef _bcmdefs_h_ #define _bcmdefs_h_ - - - - - - -#define bcmreclaimed 0 -#define r2_reclaimed 0 -#define _data _data -#define _fn _fn -#define _data _data -#define _fn _fn -#define _fn _fn -#define BCMPREATTACHDATA(_data) _data -#define BCMPREATTACHFN(_fn) _fn -#define CONST const - - - -#define _data _data -#define _fn _fn -#define _fn _fn #define STATIC static - #define SI_BUS 0 #define PCI_BUS 1 #define PCMCIA_BUS 2 diff --git a/bcm4329/src/include/bcmdevs.h b/bcm4329/src/include/bcmdevs.h index 9c0891c..80b2ea8 100644 --- a/bcm4329/src/include/bcmdevs.h +++ b/bcm4329/src/include/bcmdevs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.14 2009/06/09 13:40:43 Exp $ + * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.19 2009/09/18 23:51:17 Exp $ */ diff --git a/bcm4329/src/include/bcmsdbus.h b/bcm4329/src/include/bcmsdbus.h index c933bc1..0e629c0 100644 --- a/bcm4329/src/include/bcmsdbus.h +++ b/bcm4329/src/include/bcmsdbus.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdbus.h,v 13.11.14.2.6.4 2009/04/13 19:00:01 Exp $ + * $Id: bcmsdbus.h,v 13.11.14.2.6.6 2009/10/27 17:20:28 Exp $ */ #ifndef _sdio_api_h_ @@ -74,11 +74,6 @@ extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable); extern bool sdioh_interrupt_pending(sdioh_info_t *si); #endif -#ifdef BCMLXSDMMC -extern int sdioh_claim_host_and_lock(sdioh_info_t *si); -extern int sdioh_release_host_and_unlock(sdioh_info_t *si); -#endif /* BCMLXSDMMC */ - /* read or write one byte using cmd52 */ extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte); diff --git a/bcm4329/src/include/bcmsdh.h b/bcm4329/src/include/bcmsdh.h index 4bcc8bd..f8ab8ab 100644 --- a/bcm4329/src/include/bcmsdh.h +++ b/bcm4329/src/include/bcmsdh.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.h,v 13.35.14.7.6.7 2009/06/03 18:25:31 Exp $ + * $Id: bcmsdh.h,v 13.35.14.7.6.8 2009/10/14 04:22:25 Exp $ */ #ifndef _bcmsdh_h_ @@ -190,6 +190,11 @@ extern void bcmsdh_unregister(void); extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); extern void bcmsdh_device_remove(void * sdh); +#if defined(OOB_INTR_ONLY) +extern int bcmsdh_register_oob_intr(void * dhdp); +extern void bcmsdh_unregister_oob_intr(void); +extern void bcmsdh_oob_intr_set(bool enable); +#endif /* defined(OOB_INTR_ONLY) */ /* Function to pass device-status bits to DHD. */ extern uint32 bcmsdh_get_dstatus(void *sdh); diff --git a/bcm4329/src/include/bcmsdh_sdmmc.h b/bcm4329/src/include/bcmsdh_sdmmc.h index 2333c74..b572f34 100644 --- a/bcm4329/src/include/bcmsdh_sdmmc.h +++ b/bcm4329/src/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,v 13.1.2.1.8.5 2009/04/09 03:21:12 Exp $ + * $Id: bcmsdh_sdmmc.h,v 13.1.2.1.8.7 2009/10/27 18:22:52 Exp $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -117,7 +117,6 @@ extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd); typedef struct _BCMSDH_SDMMC_INSTANCE { sdioh_info_t *sd; struct sdio_func *func[SDIOD_MAX_IOFUNCS]; - uint32 host_claimed; } BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; #endif /* __BCMSDH_SDMMC_H__ */ diff --git a/bcm4329/src/include/bcmspibrcm.h b/bcm4329/src/include/bcmspibrcm.h deleted file mode 100644 index a422373..0000000 --- a/bcm4329/src/include/bcmspibrcm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer - * - * Copyright (C) 2009, Broadcom Corporation - * All Rights Reserved. - * - * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; - * the contents of this file may not be disclosed to third parties, copied - * or duplicated in any form, in whole or in part, without the prior - * written permission of Broadcom Corporation. - * - * $Id: bcmspibrcm.h,v 1.4.4.1.4.3.6.1 2008/09/27 17:03:25 Exp $ - */ - -/* global msglevel for debug messages - bitvals come from sdiovar.h */ - -#define sd_err(x) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_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 */ - void *bar0; /* BAR0 for PCI Device */ - osl_t *osh; /* osh handler */ - void *controller; /* Pointer to SPI Controller's private data struct */ - - uint lockcount; /* nest count of 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 */ - bool initialized; /* card initialized */ - uint32 target_dev; /* Target device ID */ - uint32 intmask; /* Current active interrupts */ - void *sdos_info; /* Pointer to per-OS private data */ - - uint32 controller_type; /* Host controller type */ - uint8 version; /* Host Controller Spec Compliance Version */ - uint irq; /* Client irq */ - uint32 intrcount; /* Client interrupts */ - uint32 local_intrcount; /* Controller interrupts */ - bool host_init_done; /* Controller initted */ - bool card_init_done; /* Client SDIO interface initted */ - bool polled_mode; /* polling for command completion */ - - bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - /* 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; - - 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 diff --git a/bcm4329/src/include/bcmutils.h b/bcm4329/src/include/bcmutils.h index b34550f..93bf25f 100644 --- a/bcm4329/src/include/bcmutils.h +++ b/bcm4329/src/include/bcmutils.h @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.h,v 13.184.4.6.2.1.18.17 2009/06/18 02:31:37 Exp $ + * $Id: bcmutils.h,v 13.184.4.6.2.1.18.22 2009/10/28 18:25:39 Exp $ */ @@ -123,8 +123,12 @@ struct spktq { + struct ether_addr; +extern int ether_isbcast(const void *ea); +extern int ether_isnulladdr(const void *ea); + #define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) diff --git a/bcm4329/src/include/bcmwifi.h b/bcm4329/src/include/bcmwifi.h index f5a5874..8f5f3dc 100644 --- a/bcm4329/src/include/bcmwifi.h +++ b/bcm4329/src/include/bcmwifi.h @@ -22,7 +22,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmwifi.h,v 1.15 2007/11/19 22:23:04 Exp $ + * $Id: bcmwifi.h,v 1.15.30.1 2009/08/15 00:51:27 Exp $ */ @@ -84,17 +84,30 @@ typedef uint16 chanspec_t; ((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_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK) -#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK) #define CHSPEC_BAND(chspec) (chspec & WL_CHANSPEC_BAND_MASK) +#ifdef WL20MHZ_ONLY + +#define CHSPEC_CTL_SB(chspec) WL_CHANSPEC_CTL_SB_NONE +#define CHSPEC_BW(chspec) WL_CHANSPEC_BW_20 +#define CHSPEC_IS10(chspec) 0 +#define CHSPEC_IS20(chspec) 1 +#ifndef CHSPEC_IS40 +#define CHSPEC_IS40(chspec) 0 +#endif + +#else + +#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK) +#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK) #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_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) diff --git a/bcm4329/src/include/dhdioctl.h b/bcm4329/src/include/dhdioctl.h index 866c362..ee78c3d 100644 --- a/bcm4329/src/include/dhdioctl.h +++ b/bcm4329/src/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,v 13.7.8.1.4.1.16.2 2009/02/03 18:36:10 Exp $ + * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.4 2009/09/05 16:50:35 Exp $ */ #ifndef _dhdioctl_h_ @@ -118,4 +118,5 @@ typedef struct dhd_pktgen { /* require default structure packing */ #include <packed_section_end.h> + #endif /* _dhdioctl_h_ */ diff --git a/bcm4329/src/include/epivers.h b/bcm4329/src/include/epivers.h index bc5e933..e16e102 100644 --- a/bcm4329/src/include/epivers.h +++ b/bcm4329/src/include/epivers.h @@ -31,18 +31,18 @@ #define EPI_MINOR_VERSION 218 -#define EPI_RC_NUMBER 97 +#define EPI_RC_NUMBER 161 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 97, 0 +#define EPI_VERSION 4, 218, 161, 0 -#define EPI_VERSION_NUM 0x04da6100 +#define EPI_VERSION_NUM 0x04daa100 -#define EPI_VERSION_STR "4.218.97.0" -#define EPI_ROUTER_VERSION_STR "4.219.97.0" +#define EPI_VERSION_STR "4.218.161.0" +#define EPI_ROUTER_VERSION_STR "4.219.161.0" #endif diff --git a/bcm4329/src/include/epivers.h.in b/bcm4329/src/include/epivers.h.in deleted file mode 100644 index 8dc37fa..0000000 --- a/bcm4329/src/include/epivers.h.in +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 1999-2009, 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: epivers.h.in,v 13.25 2005/10/28 18:35:33 Exp $ - * -*/ - - -#ifndef _epivers_h_ -#define _epivers_h_ - -#define EPI_MAJOR_VERSION @EPI_MAJOR_VERSION@ - -#define EPI_MINOR_VERSION @EPI_MINOR_VERSION@ - -#define EPI_RC_NUMBER @EPI_RC_NUMBER@ - -#define EPI_INCREMENTAL_NUMBER @EPI_INCREMENTAL_NUMBER@ - -#define EPI_BUILD_NUMBER @EPI_BUILD_NUMBER@ - -#define EPI_VERSION @EPI_VERSION@ - -#define EPI_VERSION_NUM @EPI_VERSION_NUM@ - - -#define EPI_VERSION_STR "@EPI_VERSION_STR@" -#define EPI_ROUTER_VERSION_STR "@EPI_ROUTER_VERSION_STR@" - -#endif diff --git a/bcm4329/src/include/epivers.sh b/bcm4329/src/include/epivers.sh deleted file mode 100644 index b0659e0..0000000 --- a/bcm4329/src/include/epivers.sh +++ /dev/null @@ -1,121 +0,0 @@ -#! /bin/bash -# -# Create the epivers.h file from epivers.h.in -# -# $Id: epivers.sh,v 13.19 2008/01/04 03:47:32 Exp $ - -# Check for the in file, if not there we're probably in the wrong directory -if [ ! -f epivers.h.in ]; then - echo No epivers.h.in found - exit 1 -fi - -if [ -f epivers.h ]; then - # If the out file already exists, increment its build number - build=`grep EPI_BUILD_NUMBER epivers.h | sed -e "s,.*BUILD_NUMBER[ ]*,,"` - build=`expr ${build} + 1` - echo build=${build} - sed -e "s,.*_BUILD_NUMBER.*,#define EPI_BUILD_NUMBER ${build}," \ - < epivers.h > epivers.h.new - mv epivers.h epivers.h.prev - mv epivers.h.new epivers.h -else - # Otherwise create a new file. - - # CVS will insert the cvs tag name when this file is checked out. - # If this is a tagged build, use the tag to supply the numbers - # Tag should be in the form - # <NAME>_REL_<MAJ>_<MINOR> - # or - # <NAME>_REL_<MAJ>_<MINOR>_RC<RCNUM> - # or - # <NAME>_REL_<MAJ>_<MINOR>_RC<RCNUM>_<INCREMENTAL> - # - - CVSTAG="$Name: ROMTERM_REL_4_218_97 $" - - # Remove leading cvs "Name: " and trailing " $" - CVSTAG=${CVSTAG/#*: /} - CVSTAG=${CVSTAG/% $/} - - # TAG env var is supplied by calling makefile or build process - # - # If the checkout is from a branch tag, cvs checkout or export does - # not replace rcs keywords. In such instances TAG env variable can - # be used (by uncommenting following line). TAG env variable format - # itself needs to be validated for number of fields before being used. - # (e.g: HEAD is not a valid tag, which results in all '0' values below) - # - # TAG=${TAG:-${CVSTAG}} - - TAG=${CVSTAG/HEAD/} - - # Split the tag into an array on underbar or whitespace boundaries. - IFS="_ " tag=(${TAG}) - unset IFS - - tagged=1 - if [ ${#tag[*]} -eq 0 ]; then - tag=(`date '+TOT REL %Y %m %d 0 %y'`); - tagged=0 - fi - - # Allow environment variable to override values. - # Missing values default to 0 - # - maj=${EPI_MAJOR_VERSION:-${tag[2]:-0}} - min=${EPI_MINOR_VERSION:-${tag[3]:-0}} - rcnum=${EPI_RC_NUMBER:-${tag[4]:-0}} - incremental=${EPI_INCREMENTAL_NUMBER:-${tag[5]:-0}} - build=${EPI_BUILD_NUMBER:-0} - - # Strip 'RC' from front of rcnum if present - rcnum=${rcnum/#RC/} - - # strip leading zero off the number (otherwise they look like octal) - maj=${maj/#0/} - min=${min/#0/} - min_router=${min} - rcnum=${rcnum/#0/} - incremental=${incremental/#0/} - build=${build/#0/} - - # some numbers may now be null. replace with with zero. - maj=${maj:-0} - min=${min:-0} - rcnum=${rcnum:-0} - incremental=${incremental:-0} - build=${build:-0} - - if [ ${tagged} -eq 1 ]; then - vernum=`printf "0x%02x%02x%02x%02x" ${maj} ${min} ${rcnum} ${incremental}` - else - vernum=`printf "0x00%02x%02x%02x" ${tag[7]} ${min} ${rcnum}` - fi - - - # PR17029: increment minor number for tagged router builds - # with an even minor revision - if [ ${tagged} -eq 1 -a `expr \( \( ${min} + 1 \) % 2 \)` -eq 1 ]; then - min_router=`expr ${min} + 1` - fi - - - # OK, go do it - - echo "maj=${maj}, min=${min}, rc=${rcnum}, inc=${incremental}, build=${build}" - echo "Router maj=${maj}, min=${min_router}, rc=${rcnum}, inc=${incremental}, build=${build}" - - sed \ - -e "s;@EPI_MAJOR_VERSION@;${maj};" \ - -e "s;@EPI_MINOR_VERSION@;${min};" \ - -e "s;@EPI_RC_NUMBER@;${rcnum};" \ - -e "s;@EPI_INCREMENTAL_NUMBER@;${incremental};" \ - -e "s;@EPI_BUILD_NUMBER@;${build};" \ - -e "s;@EPI_VERSION@;${maj}, ${min}, ${rcnum}, ${incremental};" \ - -e "s;@EPI_VERSION_STR@;${maj}.${min}.${rcnum}.${incremental};" \ - -e "s;@EPI_ROUTER_VERSION_STR@;${maj}.${min_router}.${rcnum}.${incremental};" \ - -e "s;@EPI_VERSION_NUM@;${vernum};" \ - < epivers.h.in > epivers.h - -fi diff --git a/bcm4329/src/include/hndpmu.h b/bcm4329/src/include/hndpmu.h index f764881..afd78d7 100644 --- a/bcm4329/src/include/hndpmu.h +++ b/bcm4329/src/include/hndpmu.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.h,v 13.14.4.3.4.3.8.5 2009/06/25 16:07:18 Exp $ + * $Id: hndpmu.h,v 13.14.4.3.4.3.8.6 2009/09/14 09:21:45 Exp $ */ #ifndef _hndpmu_h_ diff --git a/bcm4329/src/include/linux_osl.h b/bcm4329/src/include/linux_osl.h index e7b23dd..98afe9c 100644 --- a/bcm4329/src/include/linux_osl.h +++ b/bcm4329/src/include/linux_osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.h,v 13.131.30.1 2008/12/16 00:25:42 Exp $ + * $Id: linux_osl.h,v 13.131.30.5 2009/10/27 04:42:45 Exp $ */ @@ -108,7 +108,7 @@ extern uint osl_malloc_failed(osl_t *osh); #define DMA_CONSISTENT_ALIGN PAGE_SIZE -#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah) \ +#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah, alignbits) \ osl_dma_alloc_consistent((osh), (size), (pap)) #define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) @@ -233,6 +233,10 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); #define PKTGET(osh, len, send) osl_pktget((osh), (len)) #define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) +#ifdef DHD_USE_STATIC_BUF +#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) +#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) +#endif #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) #define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) #define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) @@ -245,10 +249,18 @@ extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); #define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) #define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) #define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced +#define PKTSETPOOL(osh, skb, x, y) do {} while (0) +#define PKTPOOL(osh, skb) FALSE +#define PKTPOOLLEN(osh, pktp) (0) +#define PKTPOOLAVAIL(osh, pktp) (0) +#define PKTPOOLADD(osh, pktp, p) BCME_ERROR +#define PKTPOOLGET(osh, pktp) NULL #define PKTLIST_DUMP(osh, buf) extern void *osl_pktget(osl_t *osh, uint len); extern void osl_pktfree(osl_t *osh, void *skb, bool send); +extern void *osl_pktget_static(osl_t *osh, uint len); +extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); extern void *osl_pktdup(osl_t *osh, void *skb); diff --git a/bcm4329/src/include/proto/802.11.h b/bcm4329/src/include/proto/802.11.h index 364f725..217bd6c 100644 --- a/bcm4329/src/include/proto/802.11.h +++ b/bcm4329/src/include/proto/802.11.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h,v 9.219.4.1.4.5.6.9 2009/05/21 05:54:11 Exp $ + * $Id: 802.11.h,v 9.219.4.1.4.5.6.10 2009/07/09 10:15:09 Exp $ */ diff --git a/bcm4329/src/include/proto/bcmevent.h b/bcm4329/src/include/proto/bcmevent.h index ecccbe3..1791478 100644 --- a/bcm4329/src/include/proto/bcmevent.h +++ b/bcm4329/src/include/proto/bcmevent.h @@ -24,7 +24,7 @@ * * Dependencies: proto/bcmeth.h * - * $Id: bcmevent.h,v 9.34.4.1.20.12 2009/05/24 17:00:58 Exp $ + * $Id: bcmevent.h,v 9.34.4.1.20.16 2009/09/25 23:52:38 Exp $ * */ @@ -131,7 +131,9 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event { #define WLC_E_ACTION_FRAME 58 #define WLC_E_ACTION_FRAME_COMPLETE 59 -#define WLC_E_LAST 60 +#define WLC_E_ESCAN_RESULT 69 +#define WLC_E_WAKE_EVENT 70 +#define WLC_E_LAST 71 diff --git a/bcm4329/src/include/proto/ethernet.h b/bcm4329/src/include/proto/ethernet.h index ea4f233..05530d5 100644 --- a/bcm4329/src/include/proto/ethernet.h +++ b/bcm4329/src/include/proto/ethernet.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: ethernet.h,v 9.45.56.1 2008/11/20 00:51:28 Exp $ + * $Id: ethernet.h,v 9.45.56.3 2009/08/15 00:51:27 Exp $ */ @@ -124,23 +124,21 @@ BWL_PRE_PACKED_STRUCT struct ether_addr { ((short*)d)[2] = ((short*)s)[2]; } -#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ - ((uint8 *)(ea))[1] & \ - ((uint8 *)(ea))[2] & \ - ((uint8 *)(ea))[3] & \ - ((uint8 *)(ea))[4] & \ - ((uint8 *)(ea))[5]) == 0xff) - static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; - -#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ - ((uint8 *)(ea))[1] | \ - ((uint8 *)(ea))[2] | \ - ((uint8 *)(ea))[3] | \ - ((uint8 *)(ea))[4] | \ - ((uint8 *)(ea))[5]) == 0) +#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ + ((uint8 *)(ea))[1] & \ + ((uint8 *)(ea))[2] & \ + ((uint8 *)(ea))[3] & \ + ((uint8 *)(ea))[4] & \ + ((uint8 *)(ea))[5]) == 0xff) +#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ + ((uint8 *)(ea))[1] | \ + ((uint8 *)(ea))[2] | \ + ((uint8 *)(ea))[3] | \ + ((uint8 *)(ea))[4] | \ + ((uint8 *)(ea))[5]) == 0) diff --git a/bcm4329/src/include/sbchipc.h b/bcm4329/src/include/sbchipc.h index 7427521..80e6e56 100644 --- a/bcm4329/src/include/sbchipc.h +++ b/bcm4329/src/include/sbchipc.h @@ -5,7 +5,7 @@ * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, * gpio interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h,v 13.103.2.5.4.5.2.8 2009/01/21 23:56:32 Exp $ + * $Id: sbchipc.h,v 13.103.2.5.4.5.2.9 2009/07/03 14:23:21 Exp $ * * Copyright (C) 1999-2009, Broadcom Corporation * @@ -823,54 +823,11 @@ typedef volatile struct { -#define PMU1_PLL0_PLLCTL0 0 -#define PMU1_PLL0_PC0_P1DIV_MASK 0x00f00000 -#define PMU1_PLL0_PC0_P1DIV_SHIFT 20 -#define PMU1_PLL0_PC0_P2DIV_MASK 0x0f000000 -#define PMU1_PLL0_PC0_P2DIV_SHIFT 24 - - -#define PMU1_PLL0_PLLCTL1 1 -#define PMU1_PLL0_PC1_M1DIV_MASK 0x000000ff -#define PMU1_PLL0_PC1_M1DIV_SHIFT 0 -#define PMU1_PLL0_PC1_M2DIV_MASK 0x0000ff00 -#define PMU1_PLL0_PC1_M2DIV_SHIFT 8 -#define PMU1_PLL0_PC1_M3DIV_MASK 0x00ff0000 -#define PMU1_PLL0_PC1_M3DIV_SHIFT 16 -#define PMU1_PLL0_PC1_M4DIV_MASK 0xff000000 -#define PMU1_PLL0_PC1_M4DIV_SHIFT 24 - #define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 #define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) #define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) -#define PMU1_PLL0_PLLCTL2 2 -#define PMU1_PLL0_PC2_M5DIV_MASK 0x000000ff -#define PMU1_PLL0_PC2_M5DIV_SHIFT 0 -#define PMU1_PLL0_PC2_M6DIV_MASK 0x0000ff00 -#define PMU1_PLL0_PC2_M6DIV_SHIFT 8 -#define PMU1_PLL0_PC2_NDIV_MODE_MASK 0x000e0000 -#define PMU1_PLL0_PC2_NDIV_MODE_SHIFT 17 -#define PMU1_PLL0_PC2_NDIV_MODE_MASH 1 -#define PMU1_PLL0_PC2_NDIV_MODE_MFB 2 -#define PMU1_PLL0_PC2_NDIV_INT_MASK 0x1ff00000 -#define PMU1_PLL0_PC2_NDIV_INT_SHIFT 20 - - -#define PMU1_PLL0_PLLCTL3 3 -#define PMU1_PLL0_PC3_NDIV_FRAC_MASK 0x00ffffff -#define PMU1_PLL0_PC3_NDIV_FRAC_SHIFT 0 - - -#define PMU1_PLL0_PLLCTL4 4 - - -#define PMU1_PLL0_PLLCTL5 5 -#define PMU1_PLL0_PC5_CLK_DRV_MASK 0xffffff00 -#define PMU1_PLL0_PC5_CLK_DRV_SHIFT 8 - - #define PMU2_PHY_PLL_PLLCTL 4 #define PMU2_SI_PLL_PLLCTL 10 @@ -1044,58 +1001,6 @@ typedef volatile struct { #define CST4315_CBUCK_MODE_BURST 0x00000400 #define CST4315_CBUCK_MODE_LPBURST 0x00000c00 - -#define RES4319_CBUCK_LPOM 1 -#define RES4319_CBUCK_BURST 2 -#define RES4319_CBUCK_PWM 3 -#define RES4319_CLDO_PU 4 -#define RES4319_PALDO_PU 5 -#define RES4319_ILP_REQUEST 6 -#define RES4319_LNLDO1_PU 9 -#define RES4319_OTP_PU 10 -#define RES4319_LNLDO2_PU 12 -#define RES4319_XTAL_PU 13 -#define RES4319_ALP_AVAIL 14 -#define RES4319_RX_PWRSW_PU 15 -#define RES4319_TX_PWRSW_PU 16 -#define RES4319_RFPLL_PWRSW_PU 17 -#define RES4319_LOGEN_PWRSW_PU 18 -#define RES4319_AFE_PWRSW_PU 19 -#define RES4319_BBPLL_PWRSW_PU 20 -#define RES4319_HT_AVAIL 21 - -#define CST4319_SPI_CPULESSUSB 0x00000001 -#define CST4319_SPI_CLK_POL 0x00000002 -#define CST4319_SPI_CLK_PH 0x00000008 -#define CST4319_SPROM_OTP_SEL_MASK 0x000000c0 -#define CST4319_SPROM_OTP_SEL_SHIFT 6 -#define CST4319_DEFCIS_SEL 0x00000000 -#define CST4319_SPROM_SEL 0x00000040 -#define CST4319_OTP_SEL 0x00000080 -#define CST4319_OTP_PWRDN 0x000000c0 -#define CST4319_SDIO_USB_MODE 0x00000100 -#define CST4319_REMAP_SEL_MASK 0x00000600 -#define CST4319_ILPDIV_EN 0x00000800 -#define CST4319_XTAL_PD_POL 0x00001000 -#define CST4319_LPO_SEL 0x00002000 -#define CST4319_RES_INIT_MODE 0x0000c000 -#define CST4319_PALDO_EXTPNP 0x00010000 -#define CST4319_CBUCK_MODE_MASK 0x00060000 -#define CST4319_CBUCK_MODE_BURST 0x00020000 -#define CST4319_CBUCK_MODE_LPBURST 0x00060000 -#define CST4319_RCAL_VALID 0x01000000 -#define CST4319_RCAL_VALUE_MASK 0x3e000000 -#define CST4319_RCAL_VALUE_SHIFT 25 - -#define PMU1_PLL0_CHIPCTL0 0 -#define PMU1_PLL0_CHIPCTL1 1 -#define PMU1_PLL0_CHIPCTL2 2 -#define CCTL_4319USB_XTAL_SEL_MASK 0x00180000 -#define CCTL_4319USB_XTAL_SEL_SHIFT 19 -#define CCTL_4319USB_48MHZ_PLL_SEL 1 -#define CCTL_4319USB_24MHZ_PLL_SEL 2 - - #define PMU_MAX_TRANSITION_DLY 15000 diff --git a/bcm4329/src/include/sbhnddma.h b/bcm4329/src/include/sbhnddma.h index 4ccc36f..2aeee9e 100644 --- a/bcm4329/src/include/sbhnddma.h +++ b/bcm4329/src/include/sbhnddma.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbhnddma.h,v 13.11.250.5 2008/05/07 20:23:46 Exp $ + * $Id: sbhnddma.h,v 13.11.250.5.16.1 2009/07/21 14:04:51 Exp $ */ @@ -61,8 +61,9 @@ typedef volatile struct { } dma32dd_t; -#define D32MAXRINGSZ 4096 -#define D32RINGALIGN 4096 +#define D32RINGALIGN_BITS 12 +#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) +#define D32RINGALIGN (1 << D32RINGALIGN_BITS) #define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) @@ -188,8 +189,9 @@ typedef volatile struct { } dma64dd_t; -#define D64MAXRINGSZ 8192 -#define D64RINGALIGN 8192 +#define D64RINGALIGN_BITS 13 +#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) +#define D64RINGALIGN (1 << D64RINGALIGN_BITS) #define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) diff --git a/bcm4329/src/include/sdio.h b/bcm4329/src/include/sdio.h index e849267..d20d69c 100644 --- a/bcm4329/src/include/sdio.h +++ b/bcm4329/src/include/sdio.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdio.h,v 13.24.4.1.4.1 2008/05/06 22:57:29 Exp $ + * $Id: sdio.h,v 13.24.4.1.4.1.16.1 2009/08/12 01:08:02 Exp $ */ #ifndef _SDIO_H @@ -80,6 +80,9 @@ typedef volatile struct { #define SDIOD_CCCR_POWER_CONTROL 0x12 #define SDIOD_CCCR_SPEED_CONTROL 0x13 +/* Broadcom extensions (corerev >= 1) */ +#define SDIOD_CCCR_BRCM_SEPINT 0xf2 + /* cccr_sdio_rev */ #define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */ #define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */ @@ -134,6 +137,11 @@ typedef volatile struct { #define SDIO_SPEED_SHS 0x01 /* supports high-speed [clocking] mode (RO) */ #define SDIO_SPEED_EHS 0x02 /* enable high-speed [clocking] mode (RW) */ +/* brcm sepint */ +#define SDIO_SEPINT_MASK 0x01 /* route sdpcmdev intr onto separate pad (chip-specific) */ +#define SDIO_SEPINT_OE 0x02 /* 1 asserts output enable for above pad */ +#define SDIO_SEPINT_ACT_HI 0x04 /* use active high interrupt level instead of active low */ + /* FBR structure for function 1-7, FBR addresses and register offsets */ typedef volatile struct { uint8 devctr; /* device interface, CSA control */ @@ -162,7 +170,7 @@ typedef volatile struct { #define SDIOD_FBR_SIZE 0x100 /* Macro to calculate FBR register base */ -#define SDIOD_FBR_BASE(n) (n * 0x100) +#define SDIOD_FBR_BASE(n) ((n) * 0x100) /* Function register offsets */ #define SDIOD_FBR_DEVCTR 0x00 /* basic info for function */ @@ -282,13 +290,13 @@ typedef volatile struct { /* build SD_CMD_IO_RW_DIRECT Argument */ #define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \ - (((rw & 1) << 31) | ((func & 0x7) << 28) | ((raw & 1) << 27) | \ - ((addr & 0x1FFFF) << 9) | (data & 0xFF)) + ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \ + (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF)) /* build SD_CMD_IO_RW_EXTENDED Argument */ #define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \ - (((rw & 1) << 31) | ((func & 0x7) << 28) | ((blk & 1) << 27) | \ - ((inc_addr & 1) << 26) | ((addr & 0x1FFFF) << 9) | (count & 0x1FF)) + ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \ + (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF)) /* SDIO response parameters */ #define SD_RSP_NO_NONE 0 diff --git a/bcm4329/src/include/sdioh.h b/bcm4329/src/include/sdioh.h index 6681c7c..960e30c 100644 --- a/bcm4329/src/include/sdioh.h +++ b/bcm4329/src/include/sdioh.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdioh.h,v 13.13.18.1.16.1 2008/08/26 23:49:40 Exp $ + * $Id: sdioh.h,v 13.13.18.1.16.2 2009/07/28 17:54:46 Exp $ */ #ifndef _SDIOH_H @@ -211,7 +211,7 @@ #define SW_RESET_DAT_M BITFIELD_MASK(1) /* Bit 2 DAT Line Reset */ #define SW_RESET_DAT_S 2 -/* SD_IntStatus: Offset 0x030, size = 2 bytes */ +/* SD_IntrStatus: Offset 0x030, size = 2 bytes */ /* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */ #define INTSTAT_CMD_COMPLETE_M BITFIELD_MASK(1) /* Bit 0 */ #define INTSTAT_CMD_COMPLETE_S 0 @@ -277,7 +277,7 @@ /* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */ /* SD_ClockCntrl : Offset 0x02C , size = bytes */ -/* SD_SoftwarewReset_TimeoutCntrl : Offset 0x02E , size = bytes */ +/* SD_SoftwareReset_TimeoutCntrl : Offset 0x02E , size = bytes */ /* SD_IntrStatus : Offset 0x030 , size = bytes */ /* SD_ErrorIntrStatus : Offset 0x032 , size = bytes */ /* SD_IntrStatusEnable : Offset 0x034 , size = bytes */ diff --git a/bcm4329/src/include/siutils.h b/bcm4329/src/include/siutils.h index eae4895..7be09d5 100644 --- a/bcm4329/src/include/siutils.h +++ b/bcm4329/src/include/siutils.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.h,v 13.197.4.2.4.3.8.8 2009/06/25 16:07:18 Exp $ + * $Id: siutils.h,v 13.197.4.2.4.3.8.12 2009/09/22 13:28:16 Exp $ */ @@ -132,6 +132,7 @@ extern void *si_osh(si_t *sih); extern void si_setosh(si_t *sih, osl_t *osh); extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); extern void *si_coreregs(si_t *sih); +extern void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val); extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); diff --git a/bcm4329/src/include/spid.h b/bcm4329/src/include/spid.h deleted file mode 100644 index 0c04153..0000000 --- a/bcm4329/src/include/spid.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * SPI device spec header file - * - * Copyright (C) 2009, Broadcom Corporation - * All Rights Reserved. - * - * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom Corporation; - * the contents of this file may not be disclosed to third parties, copied - * or duplicated in any form, in whole or in part, without the prior - * written permission of Broadcom Corporation. - * - * $Id: spid.h,v 1.7.10.1.16.3 2009/04/09 19:23:14 Exp $ - */ - -#ifndef _SPI_H -#define _SPI_H - -/* - * Brcm SPI Device Register Map. - * - */ - -typedef volatile struct { - uint8 config; /* 0x00, len, endian, clock, speed, polarity, wakeup */ - uint8 response_delay; /* 0x01, read response delay in bytes (corerev < 3) */ - uint8 status_enable; /* 0x02, status-enable, intr with status, response_delay - * function selection, command/data error check - */ - uint8 reset_bp; /* 0x03, reset on wlan/bt backplane reset (corerev >= 1) */ - uint16 intr_reg; /* 0x04, Intr status register */ - uint16 intr_en_reg; /* 0x06, Intr mask register */ - uint32 status_reg; /* 0x08, RO, Status bits of last spi transfer */ - uint16 f1_info_reg; /* 0x0c, RO, enabled, ready for data transfer, blocksize */ - uint16 f2_info_reg; /* 0x0e, RO, enabled, ready for data transfer, blocksize */ - uint16 f3_info_reg; /* 0x10, RO, enabled, ready for data transfer, blocksize */ - uint32 test_read; /* 0x14, RO 0xfeedbead signature */ - uint32 test_rw; /* 0x18, RW */ - uint8 resp_delay_f0; /* 0x1c, read resp delay bytes for F0 (corerev >= 3) */ - uint8 resp_delay_f1; /* 0x1d, read resp delay bytes for F1 (corerev >= 3) */ - uint8 resp_delay_f2; /* 0x1e, read resp delay bytes for F2 (corerev >= 3) */ - uint8 resp_delay_f3; /* 0x1f, read resp delay bytes for F3 (corerev >= 3) */ -} spi_regs_t; - -/* SPI device register offsets */ -#define SPID_CONFIG 0x00 -#define SPID_RESPONSE_DELAY 0x01 -#define SPID_STATUS_ENABLE 0x02 -#define SPID_RESET_BP 0x03 /* (corerev >= 1) */ -#define SPID_INTR_REG 0x04 /* 16 bits - Interrupt status */ -#define SPID_INTR_EN_REG 0x06 /* 16 bits - Interrupt mask */ -#define SPID_STATUS_REG 0x08 /* 32 bits */ -#define SPID_F1_INFO_REG 0x0C /* 16 bits */ -#define SPID_F2_INFO_REG 0x0E /* 16 bits */ -#define SPID_F3_INFO_REG 0x10 /* 16 bits */ -#define SPID_TEST_READ 0x14 /* 32 bits */ -#define SPID_TEST_RW 0x18 /* 32 bits */ -#define SPID_RESP_DELAY_F0 0x1c /* 8 bits (corerev >= 3) */ -#define SPID_RESP_DELAY_F1 0x1d /* 8 bits (corerev >= 3) */ -#define SPID_RESP_DELAY_F2 0x1e /* 8 bits (corerev >= 3) */ -#define SPID_RESP_DELAY_F3 0x1f /* 8 bits (corerev >= 3) */ - -/* Bit masks for SPID_CONFIG device register */ -#define WORD_LENGTH_32 0x1 /* 0/1 16/32 bit word length */ -#define ENDIAN_BIG 0x2 /* 0/1 Little/Big Endian */ -#define CLOCK_PHASE 0x4 /* 0/1 clock phase delay */ -#define CLOCK_POLARITY 0x8 /* 0/1 Idle state clock polarity is low/high */ -#define HIGH_SPEED_MODE 0x10 /* 1/0 High Speed mode / Normal mode */ -#define INTR_POLARITY 0x20 /* 1/0 Interrupt active polarity is high/low */ -#define WAKE_UP 0x80 /* 0/1 Wake-up command from Host to WLAN */ - -/* Bit mask for SPID_RESPONSE_DELAY device register */ -#define RESPONSE_DELAY_MASK 0xFF /* Configurable rd response delay in multiples of 8 bits */ - -/* Bit mask for SPID_STATUS_ENABLE device register */ -#define STATUS_ENABLE 0x1 /* 1/0 Status sent/not sent to host after read/write */ -#define INTR_WITH_STATUS 0x2 /* 0/1 Do-not / do-interrupt if status is sent */ -#define RESP_DELAY_ALL 0x4 /* Applicability of resp delay to F1 or all func's read */ -#define DWORD_PKT_LEN_EN 0x8 /* Packet len denoted in dwords instead of bytes */ -#define CMD_ERR_CHK_EN 0x20 /* Command error check enable */ -#define DATA_ERR_CHK_EN 0x40 /* Data error check enable */ - -/* Bit mask for SPID_RESET_BP device register */ -#define RESET_ON_WLAN_BP_RESET 0x4 /* enable reset for WLAN backplane */ -#define RESET_ON_BT_BP_RESET 0x8 /* enable reset for BT backplane */ -#define RESET_SPI 0x80 /* reset the above enabled logic */ - -/* Bit mask for SPID_INTR_REG device register */ -#define DATA_UNAVAILABLE 0x0001 /* Requested data not available; Clear by writing a "1" */ -#define F2_F3_FIFO_RD_UNDERFLOW 0x0002 -#define F2_F3_FIFO_WR_OVERFLOW 0x0004 -#define COMMAND_ERROR 0x0008 /* Cleared by writing 1 */ -#define DATA_ERROR 0x0010 /* Cleared by writing 1 */ -#define F2_PACKET_AVAILABLE 0x0020 -#define F3_PACKET_AVAILABLE 0x0040 -#define F1_OVERFLOW 0x0080 /* Due to last write. Bkplane has pending write requests */ -#define MISC_INTR0 0x0100 -#define MISC_INTR1 0x0200 -#define MISC_INTR2 0x0400 -#define MISC_INTR3 0x0800 -#define MISC_INTR4 0x1000 -#define F1_INTR 0x2000 -#define F2_INTR 0x4000 -#define F3_INTR 0x8000 - -/* Bit mask for 32bit SPID_STATUS_REG device register */ -#define STATUS_DATA_NOT_AVAILABLE 0x00000001 -#define STATUS_UNDERFLOW 0x00000002 -#define STATUS_OVERFLOW 0x00000004 -#define STATUS_F2_INTR 0x00000008 -#define STATUS_F3_INTR 0x00000010 -#define STATUS_F2_RX_READY 0x00000020 -#define STATUS_F3_RX_READY 0x00000040 -#define STATUS_HOST_CMD_DATA_ERR 0x00000080 -#define STATUS_F2_PKT_AVAILABLE 0x00000100 -#define STATUS_F2_PKT_LEN_MASK 0x000FFE00 -#define STATUS_F2_PKT_LEN_SHIFT 9 -#define STATUS_F3_PKT_AVAILABLE 0x00100000 -#define STATUS_F3_PKT_LEN_MASK 0xFFE00000 -#define STATUS_F3_PKT_LEN_SHIFT 21 - -/* Bit mask for 16 bits SPID_F1_INFO_REG device register */ -#define F1_ENABLED 0x0001 -#define F1_RDY_FOR_DATA_TRANSFER 0x0002 -#define F1_MAX_PKT_SIZE 0x01FC - -/* Bit mask for 16 bits SPID_F2_INFO_REG device register */ -#define F2_ENABLED 0x0001 -#define F2_RDY_FOR_DATA_TRANSFER 0x0002 -#define F2_MAX_PKT_SIZE 0x3FFC - -/* Bit mask for 16 bits SPID_F3_INFO_REG device register */ -#define F3_ENABLED 0x0001 -#define F3_RDY_FOR_DATA_TRANSFER 0x0002 -#define F3_MAX_PKT_SIZE 0x3FFC - -/* Bit mask for 32 bits SPID_TEST_READ device register read in 16bit LE mode */ -#define TEST_RO_DATA_32BIT_LE 0xFEEDBEAD - -/* Maximum number of I/O funcs */ -#define SPI_MAX_IOFUNCS 4 - -#define SPI_MAX_PKT_LEN (2048*4) - -/* Misc defines */ -#define SPI_FUNC_0 0 -#define SPI_FUNC_1 1 -#define SPI_FUNC_2 2 -#define SPI_FUNC_3 3 - -#define WAIT_F2RXFIFORDY 100 -#define WAIT_F2RXFIFORDY_DELAY 20 - -#endif /* _SPI_H */ diff --git a/bcm4329/src/include/wlioctl.h b/bcm4329/src/include/wlioctl.h index 30564aa..751d5cd 100644 --- a/bcm4329/src/include/wlioctl.h +++ b/bcm4329/src/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,v 1.601.4.15.2.14.2.37 2009/06/22 11:24:10 Exp $ + * $Id: wlioctl.h,v 1.601.4.15.2.14.2.53 2009/10/27 06:18:20 Exp $ */ @@ -133,11 +133,15 @@ typedef struct wlc_ssid { #define WL_BSSTYPE_INDEP 0 #define WL_BSSTYPE_ANY 2 + +#define WL_SCANFLAGS_PASSIVE 0x01 +#define WL_SCANFLAGS_PROHIBITED 0x04 + typedef struct wl_scan_params { wlc_ssid_t ssid; struct ether_addr bssid; int8 bss_type; - int8 scan_type; + int8 scan_type; int32 nprobes; int32 active_time; int32 passive_time; @@ -154,6 +158,7 @@ typedef struct wl_scan_params { #define WL_SCAN_ACTION_START 1 #define WL_SCAN_ACTION_CONTINUE 2 +#define WL_SCAN_ACTION_ABORT 3 #define ISCAN_REQ_VERSION 1 @@ -182,6 +187,27 @@ typedef struct wl_scan_results { #define WL_SCAN_RESULTS_PENDING 2 #define WL_SCAN_RESULTS_ABORTED 3 +#define ESCAN_REQ_VERSION 1 + +typedef struct wl_escan_params { + uint32 version; + uint16 action; + uint16 sync_id; + wl_scan_params_t params; +} wl_escan_params_t; + +#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) + +typedef struct wl_escan_result { + uint32 buflen; + uint32 version; + uint16 sync_id; + uint16 bss_count; + wl_bss_info_t bss_info[1]; +} wl_escan_result_t; + +#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) + typedef struct wl_iscan_results { uint32 status; @@ -208,6 +234,7 @@ typedef struct wl_uint32_list { typedef struct wl_assoc_params { struct ether_addr bssid; + uint16 bssid_cnt; int32 chanspec_num; chanspec_t chanspec_list[1]; } wl_assoc_params_t; @@ -322,6 +349,8 @@ typedef struct { #define BRCM_AUTH_PSK 0x0100 #define BRCM_AUTH_DPT 0x0200 +#define WPA_AUTH_PFN_ANY 0xffffffff + #define MAXPMKID 16 @@ -762,6 +791,7 @@ typedef struct wl_ioctl { #define WLC_PHY_TYPE_G 2 #define WLC_PHY_TYPE_N 4 #define WLC_PHY_TYPE_LP 5 +#define WLC_PHY_TYPE_SSN 6 #define WLC_PHY_TYPE_NULL 0xf @@ -1156,7 +1186,6 @@ typedef struct { uint32 pktengrxdmcast; } wl_cnt_t; - typedef struct { uint16 version; uint16 length; @@ -1173,6 +1202,7 @@ typedef struct { uint32 rxmcs5_40M; uint32 rxmcs6_40M; uint32 rxmcs7_40M; + uint32 rxmcs32_40M; uint32 txfrmsnt_20Mlo; uint32 txfrmsnt_20Mup; @@ -1181,6 +1211,14 @@ typedef struct { uint32 rx_20ul; } wl_cnt_ext_t; +#define WL_RXDIV_STATS_T_VERSION 1 +typedef struct { + uint16 version; + uint16 length; + + uint32 rxant[4]; +} wl_rxdiv_stats_t; + #define WL_DELTA_STATS_T_VERSION 1 typedef struct { @@ -1291,10 +1329,12 @@ typedef struct wl_pfn { int32 auth; int32 wpa_auth; int32 wsec; +#ifdef WLPFN_AUTO_CONNECT union { wl_wsec_key_t sec_key; wsec_pmk_t wpa_sec_key; } pfn_security; +#endif } wl_pfn_t; @@ -1468,10 +1508,15 @@ typedef struct wl_pkteng { struct ether_addr src; } wl_pkteng_t; +#define NUM_80211b_RATES 4 +#define NUM_80211ag_RATES 8 +#define NUM_80211n_RATES 32 +#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) typedef struct wl_pkteng_stats { uint32 lostfrmcnt; int32 rssi; int32 snr; + uint16 rxpktcnt[NUM_80211_RATES+1]; } wl_pkteng_stats_t; #define WL_WOWL_MAGIC (1 << 0) diff --git a/bcm4329/src/shared/aiutils.c b/bcm4329/src/shared/aiutils.c index 00e96a8..1962711 100644 --- a/bcm4329/src/shared/aiutils.c +++ b/bcm4329/src/shared/aiutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aiutils.c,v 1.6.4.7.4.1 2008/11/03 15:16:48 Exp $ + * $Id: aiutils.c,v 1.6.4.7.4.5 2009/09/25 00:32:01 Exp $ */ #include <typedefs.h> @@ -36,6 +36,11 @@ #include "siutils_priv.h" +STATIC uint32 +get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st, + uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh); + + /* EROM parsing */ static uint32 @@ -71,7 +76,7 @@ get_erom_ent(si_t *sih, uint32 *eromptr, uint32 mask, uint32 match) return ent; } -static uint32 +STATIC uint32 get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st, uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh) { @@ -422,6 +427,15 @@ ai_setint(si_t *sih, int siflag) { } +void +ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val) +{ + si_info_t *sii = SI_INFO(sih); + aidmp_t *ai = sii->curwrap; + W_REG(sii->osh, (uint32 *)((uint8 *)ai+offset), val); + return; +} + uint ai_corevendor(si_t *sih) { @@ -482,6 +496,9 @@ ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ASSERT(regoff < SI_CORE_SIZE); ASSERT((val & ~mask) == 0); + if (coreidx >= SI_MAXCORES) + return 0; + if (BUSTYPE(sih->bustype) == SI_BUS) { /* If internal bus, we can always get at everything */ fast = TRUE; diff --git a/bcm4329/src/shared/bcmutils.c b/bcm4329/src/shared/bcmutils.c index 2741824..9805ee6 100644 --- a/bcm4329/src/shared/bcmutils.c +++ b/bcm4329/src/shared/bcmutils.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.c,v 1.210.4.5.2.4.6.9 2009/05/22 20:49:24 Exp $ + * $Id: bcmutils.c,v 1.210.4.5.2.4.6.16 2009/10/28 18:25:42 Exp $ */ #include <typedefs.h> @@ -45,6 +45,7 @@ #ifdef BCMDRIVER + /* copy a pkt buffer chain into a buffer */ uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) @@ -665,7 +666,8 @@ bcmstrncat(char *dest, const char *src, uint size) * Returns: Pointer to the next token found. NULL when no more tokens are found. ***************************************************************************** */ -char* bcmstrtok(char **string, const char *delimiters, char *tokdelim) +char * +bcmstrtok(char **string, const char *delimiters, char *tokdelim) { unsigned char *str; unsigned long map[8]; @@ -742,7 +744,8 @@ char* bcmstrtok(char **string, const char *delimiters, char *tokdelim) * t1 > t2, when ignoring case sensitivity. ***************************************************************************** */ -int bcmstricmp(const char *s1, const char *s2) +int +bcmstricmp(const char *s1, const char *s2) { char dc, sc; @@ -775,7 +778,8 @@ int bcmstricmp(const char *s1, const char *s2) * t1 > t2, when ignoring case sensitivity. ***************************************************************************** */ -int bcmstrnicmp(const char* s1, const char* s2, int cnt) +int +bcmstrnicmp(const char* s1, const char* s2, int cnt) { char dc, sc; @@ -810,18 +814,14 @@ bcm_ether_atoe(char *p, struct ether_addr *ea) return (i == 6); } + #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) /* registry routine buffer preparation utility functions: * parameter order is like strncpy, but returns count * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) */ ulong -wchar2ascii( - char *abuf, - ushort *wbuf, - ushort wbuflen, - ulong abuflen -) +wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) { ulong copyct = 1; ushort i; diff --git a/bcm4329/src/shared/bcmwifi.c b/bcm4329/src/shared/bcmwifi.c index b460d7f..641a4fd 100644 --- a/bcm4329/src/shared/bcmwifi.c +++ b/bcm4329/src/shared/bcmwifi.c @@ -22,7 +22,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmwifi.c,v 1.18.24.2 2008/08/01 21:52:06 Exp $ + * $Id: bcmwifi.c,v 1.18.24.2.4.1 2009/09/25 00:32:01 Exp $ */ @@ -83,7 +83,7 @@ wf_chspec_ntoa(chanspec_t chspec, char *buf) chanspec_t wf_chspec_aton(char *a) { - char *endp; + char *endp = NULL; uint channel, band, bw, ctl_sb; char c; diff --git a/bcm4329/src/shared/hndpmu.c b/bcm4329/src/shared/hndpmu.c index 90116de..25712ac 100644 --- a/bcm4329/src/shared/hndpmu.c +++ b/bcm4329/src/shared/hndpmu.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.c,v 1.95.2.17.4.11.2.39 2009/06/25 16:07:18 Exp $ + * $Id: hndpmu.c,v 1.95.2.17.4.11.2.50 2009/10/26 14:45:51 Exp $ */ #include <typedefs.h> @@ -70,7 +70,7 @@ void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) { chipcregs_t *cc; - uint origidx, intr_val; + uint origidx, intr_val = 0; sdiod_drive_str_t *str_tab = NULL; uint32 str_mask = 0; uint32 str_shift = 0; diff --git a/bcm4329/src/shared/linux_osl.c b/bcm4329/src/shared/linux_osl.c index 7fb59e4..4cf658b 100644 --- a/bcm4329/src/shared/linux_osl.c +++ b/bcm4329/src/shared/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,v 1.125.12.3.8.2 2009/06/18 02:31:41 Exp $ + * $Id: linux_osl.c,v 1.125.12.3.8.5 2009/10/27 04:43:04 Exp $ */ @@ -41,6 +41,28 @@ #define OS_HANDLE_MAGIC 0x1234abcd #define BCM_MEM_FILENAME_LEN 24 +#ifdef DHD_USE_STATIC_BUF +#define MAX_STATIC_BUF_NUM 16 +#define STATIC_BUF_SIZE (PAGE_SIZE*2) +#define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE) +typedef struct bcm_static_buf { + struct semaphore static_sem; + unsigned char *buf_ptr; + unsigned char buf_use[MAX_STATIC_BUF_NUM]; +} bcm_static_buf_t; + +static bcm_static_buf_t *bcm_static_buf = 0; + +#define MAX_STATIC_PKT_NUM 8 +typedef struct bcm_static_pkt { + struct sk_buff *skb_4k[MAX_STATIC_PKT_NUM]; + struct sk_buff *skb_8k[MAX_STATIC_PKT_NUM]; + struct semaphore osl_pkt_sem; + unsigned char pkt_use[MAX_STATIC_PKT_NUM*2]; +} bcm_static_pkt_t; +static bcm_static_pkt_t *bcm_static_skb = 0; + +#endif typedef struct bcm_mem_link { struct bcm_mem_link *prev; struct bcm_mem_link *next; @@ -121,6 +143,7 @@ osl_error(int bcmerror) return linuxbcmerrormap[-bcmerror]; } +void * dhd_os_prealloc(int section, unsigned long size); osl_t * osl_attach(void *pdev, uint bustype, bool pkttag) { @@ -159,6 +182,39 @@ osl_attach(void *pdev, uint bustype, bool pkttag) break; } +#ifdef DHD_USE_STATIC_BUF + + + if (!bcm_static_buf) { + if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(3, STATIC_BUF_SIZE+ + STATIC_BUF_TOTAL_LEN))) { + printk("can not alloc static buf!\n"); + } + else + printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); + + + init_MUTEX(&bcm_static_buf->static_sem); + + + bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; + + } + + if (!bcm_static_skb) + { + int i; + void *skb_buff_ptr = 0; + bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); + skb_buff_ptr = dhd_os_prealloc(4, 0); + + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); + for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) + bcm_static_skb->pkt_use[i] = 0; + + init_MUTEX(&bcm_static_skb->osl_pkt_sem); + } +#endif return osh; } @@ -168,6 +224,14 @@ osl_detach(osl_t *osh) if (osh == NULL) return; +#ifdef DHD_USE_STATIC_BUF + if (bcm_static_buf) { + bcm_static_buf = 0; + } + if (bcm_static_skb) { + bcm_static_skb = 0; + } +#endif ASSERT(osh->magic == OS_HANDLE_MAGIC); kfree(osh); } @@ -220,6 +284,90 @@ osl_pktfree(osl_t *osh, void *p, bool send) } } +#ifdef DHD_USE_STATIC_BUF +void* +osl_pktget_static(osl_t *osh, uint len) +{ + int i = 0; + struct sk_buff *skb; + + + if (len > (PAGE_SIZE*2)) + { + printk("Do we really need this big skb??\n"); + return osl_pktget(osh, len); + } + + + down(&bcm_static_skb->osl_pkt_sem); + if (len <= PAGE_SIZE) + { + + for (i = 0; i < MAX_STATIC_PKT_NUM; i++) + { + if (bcm_static_skb->pkt_use[i] == 0) + break; + } + + if (i != MAX_STATIC_PKT_NUM) + { + bcm_static_skb->pkt_use[i] = 1; + up(&bcm_static_skb->osl_pkt_sem); + + skb = bcm_static_skb->skb_4k[i]; + skb->tail = skb->data + len; + skb->len = len; + + return skb; + } + } + + + for (i = 0; i < MAX_STATIC_PKT_NUM; i++) + { + if (bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] == 0) + break; + } + + if (i != MAX_STATIC_PKT_NUM) + { + bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] = 1; + up(&bcm_static_skb->osl_pkt_sem); + skb = bcm_static_skb->skb_8k[i]; + skb->tail = skb->data + len; + skb->len = len; + + return skb; + } + + + + up(&bcm_static_skb->osl_pkt_sem); + printk("all static pkt in use!\n"); + return osl_pktget(osh, len); +} + + +void +osl_pktfree_static(osl_t *osh, void *p, bool send) +{ + int i; + + for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) + { + if (p == bcm_static_skb->skb_4k[i]) + { + down(&bcm_static_skb->osl_pkt_sem); + bcm_static_skb->pkt_use[i] = 0; + up(&bcm_static_skb->osl_pkt_sem); + + + return; + } + } + return osl_pktfree(osh, p, send); +} +#endif uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size) { @@ -307,6 +455,40 @@ osl_malloc(osl_t *osh, uint size) if (osh) ASSERT(osh->magic == OS_HANDLE_MAGIC); +#ifdef DHD_USE_STATIC_BUF + if (bcm_static_buf) + { + int i = 0; + if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) + { + down(&bcm_static_buf->static_sem); + + for (i = 0; i < MAX_STATIC_BUF_NUM; i++) + { + if (bcm_static_buf->buf_use[i] == 0) + break; + } + + if (i == MAX_STATIC_BUF_NUM) + { + up(&bcm_static_buf->static_sem); + printk("all static buff in use!\n"); + goto original; + } + + bcm_static_buf->buf_use[i] = 1; + up(&bcm_static_buf->static_sem); + + bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); + if (osh) + osh->malloced += size; + + return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); + } + } +original: +#endif + if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { if (osh) osh->failed++; @@ -321,6 +503,28 @@ osl_malloc(osl_t *osh, uint size) void osl_mfree(osl_t *osh, void *addr, uint size) { +#ifdef DHD_USE_STATIC_BUF + if (bcm_static_buf) + { + if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr \ + <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) + { + int buf_idx = 0; + + buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; + + down(&bcm_static_buf->static_sem); + bcm_static_buf->buf_use[buf_idx] = 0; + up(&bcm_static_buf->static_sem); + + if (osh) { + ASSERT(osh->magic == OS_HANDLE_MAGIC); + osh->malloced -= size; + } + return; + } + } +#endif if (osh) { ASSERT(osh->magic == OS_HANDLE_MAGIC); osh->malloced -= size; diff --git a/bcm4329/src/shared/miniopt.c b/bcm4329/src/shared/miniopt.c index de00b6c..44199ea 100644 --- a/bcm4329/src/shared/miniopt.c +++ b/bcm4329/src/shared/miniopt.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: miniopt.c,v 1.1.6.3 2009/01/14 23:52:06 Exp $ + * $Id: miniopt.c,v 1.1.6.4 2009/09/25 00:32:01 Exp $ */ /* ---- Include Files ---------------------------------------------------- */ @@ -62,7 +62,7 @@ int miniopt(miniopt_t *t, char **argv) { int keylen; - char *p, *eq, *valstr, *endptr; + char *p, *eq, *valstr, *endptr = NULL; int err = 0; t->consumed = 0; diff --git a/bcm4329/src/shared/sbutils.c b/bcm4329/src/shared/sbutils.c index cbe4438..567e94e 100644 --- a/bcm4329/src/shared/sbutils.c +++ b/bcm4329/src/shared/sbutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbutils.c,v 1.662.4.10.2.7 2008/08/06 03:43:24 Exp $ + * $Id: sbutils.c,v 1.662.4.10.2.7.4.1 2009/09/25 00:32:01 Exp $ */ #include <typedefs.h> @@ -363,6 +363,9 @@ sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) ASSERT(regoff < SI_CORE_SIZE); ASSERT((val & ~mask) == 0); + if (coreidx >= SI_MAXCORES) + return 0; + if (BUSTYPE(sii->pub.bustype) == SI_BUS) { /* If internal bus, we can always get at everything */ fast = TRUE; diff --git a/bcm4329/src/shared/siutils.c b/bcm4329/src/shared/siutils.c index 988dda1..df34986 100644 --- a/bcm4329/src/shared/siutils.c +++ b/bcm4329/src/shared/siutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.c,v 1.662.4.4.4.16.4.20 2009/06/25 16:07:18 Exp $ + * $Id: siutils.c,v 1.662.4.4.4.16.4.25 2009/09/22 13:32:03 Exp $ */ #include <typedefs.h> @@ -661,10 +661,6 @@ si_setcore(si_t *sih, uint coreid, uint coreunit) { uint idx; - if (!sih) { - printk("%s: Null, %u, %u\n", __func__, coreid, coreunit); - return NULL; - } idx = si_findcoreidx(sih, coreid, coreunit); if (!GOODIDX(idx)) return (NULL); @@ -808,6 +804,19 @@ si_iscoreup(si_t *sih) } } +void +si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val) +{ + /* only for 4319, no requirement for SOCI_SB */ + if (CHIPTYPE(sih->socitype) == SOCI_AI) { + ai_write_wrap_reg(sih, offset, val); + } + else + return; + + return; +} + uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) { @@ -1013,7 +1022,7 @@ si_sdio_init(si_t *sih) { si_info_t *sii = SI_INFO(sih); - if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || \ + if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || (sih->buscoretype == SDIOD_CORE_ID)) { uint idx; sdpcmd_regs_t *sdpregs; diff --git a/bcm4329/src/shared/siutils_priv.h b/bcm4329/src/shared/siutils_priv.h index 1192168..1ec59aa 100644 --- a/bcm4329/src/shared/siutils_priv.h +++ b/bcm4329/src/shared/siutils_priv.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils_priv.h,v 1.3.10.5 2008/08/06 06:28:10 Exp $ + * $Id: siutils_priv.h,v 1.3.10.5.4.2 2009/09/22 13:28:16 Exp $ */ #ifndef _siutils_priv_h_ @@ -207,6 +207,7 @@ extern void ai_core_disable(si_t *sih, uint32 bits); extern int ai_numaddrspaces(si_t *sih); extern uint32 ai_addrspace(si_t *sih, uint asidx); extern uint32 ai_addrspacesize(si_t *sih, uint asidx); +extern void ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val); #endif /* _siutils_priv_h_ */ diff --git a/bcm4329/src/wl/sys/wl_iw.c b/bcm4329/src/wl/sys/wl_iw.c index edca173..768373b 100644 --- a/bcm4329/src/wl/sys/wl_iw.c +++ b/bcm4329/src/wl/sys/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.51.4.9.2.6.4.38 2009/06/29 18:54:46 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.6.4.57 2009/10/27 04:43:46 Exp $ */ @@ -36,6 +36,8 @@ #include <linux/if_arp.h> #include <asm/uaccess.h> +#include <dngl_stats.h> +#include <dhd.h> #include <dhdioctl.h> typedef void wlc_info_t; @@ -43,6 +45,9 @@ typedef void wl_info_t; typedef const struct si_pub si_t; #include <wlioctl.h> +#include <proto/ethernet.h> +#include <dngl_stats.h> +#include <dhd.h> #define WL_ERROR(x) #define WL_TRACE(x) #define WL_ASSOC(x) @@ -51,11 +56,13 @@ typedef const struct si_pub si_t; #include <wl_iw.h> + #include <linux/rtnetlink.h> #define WL_IW_USE_ISCAN 1 #define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1 + #define WL_IW_IOCTL_CALL(func_call) \ do { \ func_call; \ @@ -66,7 +73,7 @@ static int g_onoff = G_WLAN_SET_ON; extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, char* stringBuf, uint buflen); #include <bcmsdbus.h> -extern void dhd_customer_gpio_wlan_reset(bool onoff); +extern void dhd_customer_gpio_wlan_ctrl(int onoff); extern uint dhd_dev_reset(struct net_device *dev, uint8 flag); extern void dhd_dev_init_ioctl(struct net_device *dev); @@ -154,6 +161,34 @@ typedef struct iscan_info { char ioctlbuf[WLC_IOCTL_SMLEN]; } iscan_info_t; + +static void wl_iw_bt_flag_set(struct net_device *dev, bool set); +static void wl_iw_bt_release(void); + +typedef enum bt_coex_status { + BT_DHCP_IDLE = 0, + BT_DHCP_START, + BT_DHCP_OPPORTUNITY_WINDOW, + BT_DHCP_FLAG_FORCE_TIMEOUT +} coex_status_t; +#define BT_DHCP_OPPORTUNITY_WINDOW_TIEM 2500 +#define BT_DHCP_FLAG_FORCE_TIME 5500 + +typedef struct bt_info { + struct net_device *dev; + struct timer_list timer; + uint32 timer_ms; + uint32 timer_on; + int bt_state; + + + long bt_pid; + struct semaphore bt_sem; + struct completion bt_exited; +} bt_info_t; + +bt_info_t *g_bt = NULL; +static void wl_iw_bt_timerfunc(ulong data); iscan_info_t *g_iscan = NULL; static void wl_iw_timerfunc(ulong data); static void wl_iw_set_event_mask(struct net_device *dev); @@ -243,6 +278,28 @@ dev_wlc_ioctl( } +static int +dev_wlc_intvar_get_reg( + struct net_device *dev, + char *name, + uint reg, + int *retval) +{ + union { + char buf[WLC_IOCTL_SMLEN]; + int val; + } var; + int error; + + uint len; + len = bcm_mkiovar(name, (char *)(®), sizeof(reg), (char *)(&var), sizeof(var.buf)); + ASSERT(len); + error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len); + + *retval = dtoh32(var.val); + return (error); +} + @@ -306,7 +363,7 @@ dev_wlc_bufvar_set( char *name, char *buf, int len) { - char ioctlbuf[WLC_IOCTL_SMLEN]; + char ioctlbuf[MAX_WLIW_IOCTL_LEN]; uint buflen; buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf)); @@ -491,6 +548,103 @@ exit: return error; } +static int +wl_iw_set_btcoex_dhcp( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int error = 0; + char *p = extra; + uint val; +#ifdef CUSTOMER_HW2 + static int pm = PM_FAST; + int pm_local = PM_OFF; +#endif + char powermode_val = 0; + char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; + char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; + char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; + + char buf_reg66val_defualt[8] = { 66, 00, 00, 00, 0x88, 0x13, 0x00, 0x00 }; + char buf_reg41val_defualt[8] = { 41, 00, 00, 00, 0x13, 0x00, 0x00, 0x00 }; + char buf_reg68val_defualt[8] = { 68, 00, 00, 00, 0x14, 0x00, 0x00, 0x00 }; + + char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; + + + strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1); + + + dev_wlc_intvar_get_reg(dev, "btc_params", 68, &val); + + if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { + + WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); + +#ifdef CUSTOMER_HW2 + + dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)); + + dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); +#endif + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg66va_dhcp_on[0], sizeof(buf_reg66va_dhcp_on)); + + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg41va_dhcp_on[0], sizeof(buf_reg41va_dhcp_on)); + + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg68va_dhcp_on[0], sizeof(buf_reg68va_dhcp_on)); + + + g_bt->bt_state = BT_DHCP_START; + g_bt->timer_on = 1; + add_timer(&g_bt->timer); + WL_TRACE(("%s enable BT DHCP Timer\n", __FUNCTION__)); + + } + else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { + + WL_TRACE(("%s: DHCP session done\n", __FUNCTION__)); + +#ifdef CUSTOMER_HW2 + + dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); +#endif + + WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); + if (g_bt->timer_on) { + del_timer(&g_bt->timer); + g_bt->timer_on = 0; + } + + + dev_wlc_bufvar_set(dev, "btc_flags", \ + (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); + + + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg66val_defualt[0], sizeof(buf_reg66val_defualt)); + + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg41val_defualt[0], sizeof(buf_reg41val_defualt)); + + dev_wlc_bufvar_set(dev, "btc_params", \ + (char *)&buf_reg68val_defualt[0], sizeof(buf_reg68val_defualt)); + } + else { + WL_ERROR(("Unkwown yet power setting, ignored\n")); + } + + p += snprintf(p, MAX_WX_STRING, "OK"); + + wrqu->data.length = p - extra + 1; + + return error; +} int wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) @@ -558,6 +712,7 @@ wl_iw_get_rssi( scb_val.val = 0; + bzero(&ssid, sizeof(ssid)); if (g_onoff == G_WLAN_SET_ON) { error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); rssi = dtoh32(scb_val.val); @@ -606,10 +761,13 @@ _wl_control_sysioc_thread_wl_off(void *data) { struct wl_ctrl *wl_ctl = (struct wl_ctrl *)data; + wl_iw_t *iw = *(wl_iw_t **)netdev_priv(wl_ctl->dev); DAEMONIZE("wlcontrol_sysioc"); WL_TRACE(("%s Entered\n", __FUNCTION__)); + WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_OFF, "sysioc_thread_wl_off"); + WAKE_LOCK(iw->pub, WAKE_LOCK_OFF); while (down_interruptible(&wl_ctl->timer_sem) == 0) { WL_TRACE(("%s Turning off wifi dev\n", __FUNCTION__)); @@ -626,7 +784,7 @@ _wl_control_sysioc_thread_wl_off(void *data) sdioh_stop(NULL); #endif - dhd_customer_gpio_wlan_reset(G_WLAN_SET_OFF); + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); wl_iw_send_priv_event(wl_ctl->dev, "STOP"); @@ -634,6 +792,8 @@ _wl_control_sysioc_thread_wl_off(void *data) } WL_TRACE(("%s Exited\n", __FUNCTION__)); + WAKE_UNLOCK(iw->pub, WAKE_LOCK_OFF); + WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_OFF); complete_and_exit(&wl_ctl->sysioc_exited, 0); KILL_PROC(wl_ctl->sysioc_pid, SIGTERM); @@ -695,7 +855,7 @@ wl_iw_control_wl_on( WL_TRACE(("Enter %s \n", __FUNCTION__)); if (g_onoff == G_WLAN_SET_OFF) { - dhd_customer_gpio_wlan_reset(G_WLAN_SET_ON); + dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); #if defined(BCMLXSDMMC) sdioh_start(NULL, 0); @@ -915,9 +1075,18 @@ wl_iw_get_range( int channels[MAXCHANNEL+1]; wl_uint32_list_t *list = (wl_uint32_list_t *) channels; wl_rateset_t rateset; - int error, i; + int error, i, k; uint sf, ch; + int phytype; + int bw_cap = 0, sgi_tx = 0, nmode = 0; + channel_info_t ci; + uint8 nrate_list2copy = 0; + uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130}, + {14, 29, 43, 58, 87, 116, 130, 144}, + {27, 54, 81, 108, 162, 216, 243, 270}, + {30, 60, 90, 120, 180, 240, 270, 300}}; + WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); if (!extra) @@ -971,7 +1140,36 @@ wl_iw_get_range( rateset.count = dtoh32(rateset.count); range->num_bitrates = rateset.count; for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; + range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000; + dev_wlc_intvar_get(dev, "nmode", &nmode); + dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); + + if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) { + dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap); + dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx); + dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)); + ci.hw_channel = dtoh32(ci.hw_channel); + + if (bw_cap == 0 || + (bw_cap == 2 && ci.hw_channel <= 14)) { + if (sgi_tx == 0) + nrate_list2copy = 0; + else + nrate_list2copy = 1; + } + if (bw_cap == 1 || + (bw_cap == 2 && ci.hw_channel >= 36)) { + if (sgi_tx == 0) + nrate_list2copy = 2; + else + nrate_list2copy = 3; + } + range->num_bitrates += 8; + for (k = 0; i < range->num_bitrates; k++, i++) { + + range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; + } + } if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) @@ -1036,6 +1234,17 @@ wl_iw_get_range( #ifdef BCMWPA2 range->enc_capa |= IW_ENC_CAPA_WPA2; #endif + + + IW_EVENT_CAPA_SET_KERNEL(range->event_capa); + + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); + IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); + IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); + IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); +#ifdef BCMWPA2 + IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); +#endif #endif return 0; @@ -1135,7 +1344,8 @@ wl_iw_set_wap( scb_val_t scbval; bzero(&scbval, sizeof(scb_val_t)); - dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); + + (void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); return 0; } @@ -1369,7 +1579,7 @@ wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); params->bss_type = DOT11_BSSTYPE_ANY; - params->scan_type = -1; + params->scan_type = 0; params->nprobes = -1; params->active_time = -1; params->passive_time = -1; @@ -1423,10 +1633,12 @@ static void wl_iw_timerfunc(ulong data) { iscan_info_t *iscan = (iscan_info_t *)data; - iscan->timer_on = 0; - if (iscan->iscan_state != ISCAN_STATE_IDLE) { - WL_TRACE(("timer trigger\n")); - up(&iscan->sysioc_sem); + if (iscan) { + iscan->timer_on = 0; + if (iscan->iscan_state != ISCAN_STATE_IDLE) { + WL_TRACE(("timer trigger\n")); + up(&iscan->sysioc_sem); + } } } static void wl_iw_set_event_mask(struct net_device *dev) @@ -1544,8 +1756,7 @@ _iscan_sysioc_thread(void *data) rtnl_unlock(); #endif - iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; - add_timer(&iscan->timer); + mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); iscan->timer_on = 1; break; case WL_SCAN_RESULTS_SUCCESS: @@ -1556,8 +1767,7 @@ _iscan_sysioc_thread(void *data) case WL_SCAN_RESULTS_PENDING: WL_TRACE(("iscanresults pending\n")); - iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; - add_timer(&iscan->timer); + mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); iscan->timer_on = 1; break; case WL_SCAN_RESULTS_ABORTED: @@ -1570,6 +1780,11 @@ _iscan_sysioc_thread(void *data) break; } } + + if (iscan->timer_on) { + del_timer(&iscan->timer); + iscan->timer_on = 0; + } complete_and_exit(&iscan->sysioc_exited, 0); } #endif @@ -1899,7 +2114,7 @@ wl_iw_iscan_set_scan( memcpy(ssid.SSID, req->essid, ssid.SSID_len); ssid.SSID_len = htod32(ssid.SSID_len); g_scan_specified_ssid = 1; - dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as)); + (void) dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as)); return wl_iw_set_scan(dev, info, wrqu, extra); } } @@ -1907,9 +2122,11 @@ wl_iw_iscan_set_scan( iscan->list_cur = iscan->list_hdr; iscan->iscan_state = ISCAN_STATE_SCANING; - dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag)); + (void) dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, + &iscan->scan_flag, sizeof(iscan->scan_flag)); wl_iw_set_event_mask(dev); wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); + del_timer(&iscan->timer); iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; add_timer(&iscan->timer); iscan->timer_on = 1; @@ -1964,6 +2181,59 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) } #endif + +static int +wl_iw_handle_scanresults_ies(char **event_p, char *end, + struct iw_request_info *info, wl_bss_info_t *bi) +{ +#if WIRELESS_EXT > 17 + struct iw_event iwe; + char *event; + + event = *event_p; + if (bi->ie_length) { + + bcm_tlv_t *ie; + uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); + int ptr_len = bi->ie_length; + +#ifdef BCMWPA2 + if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); + } + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); +#endif + + while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { + + if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); + break; + } + } + + ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); + ptr_len = bi->ie_length; + while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { + if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { + iwe.cmd = IWEVGENIE; + iwe.u.data.length = ie->len + 2; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); + break; + } + } + + *event_p = event; + } +#endif + + return 0; +} + static uint wl_iw_get_scan_prep( wl_scan_results_t *list, @@ -1975,7 +2245,7 @@ wl_iw_get_scan_prep( struct iw_event iwe; wl_bss_info_t *bi = NULL; char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; - uint ret = 0; + int ret = 0; ASSERT(list); @@ -2023,45 +2293,9 @@ wl_iw_get_scan_prep( iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); -#if WIRELESS_EXT > 17 - if (bi->ie_length) { - - bcm_tlv_t *ie; - uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - int ptr_len = bi->ie_length; -#ifdef BCMWPA2 - if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - } - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); -#endif - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - - if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - break; - } - } + wl_iw_handle_scanresults_ies(&event, end, info, bi); - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - ptr_len = bi->ie_length; - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, - end, &iwe, (char *)ie); - goto done; - } - } - } -done: -#endif iwe.cmd = SIOCGIWENCODE; if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) @@ -2091,8 +2325,7 @@ done: ret = 0; } WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra))); - return ret; - + return (uint)ret; } static int @@ -2332,53 +2565,9 @@ wl_iw_iscan_get_scan( iwe.u.qual.noise = 0x100 + bi->phy_noise; event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); -#if WIRELESS_EXT > 17 - if (bi->ie_length) { - - bcm_tlv_t *ie; - uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - int ptr_len = bi->ie_length; -#ifdef BCMWPA2 - if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { - if (event + ie->len + 2 >= end) - return -E2BIG; - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - } - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); -#endif - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - - if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - if (event + ie->len + 2 >= end) - return -E2BIG; + wl_iw_handle_scanresults_ies(&event, end, info, bi); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - break; - } - } - - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - ptr_len = bi->ie_length; - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - if (event + ie->len + 2 >= end) - return -E2BIG; - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, - event, - end, &iwe, (char *)ie); - goto done; - } - } - } -done: -#endif iwe.cmd = SIOCGIWENCODE; if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) @@ -2610,7 +2799,7 @@ static int wl_iw_get_rate( if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) return error; rate = dtoh32(rate); - vwrq->value = (rate & 0x7f) * 500000; + vwrq->value = rate * 500000; return 0; } @@ -2795,20 +2984,31 @@ wl_iw_set_retry( if (vwrq->flags & IW_RETRY_LIMIT) { + - if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) { +#if WIRELESS_EXT > 20 + if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) || + !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) { +#else + if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) { +#endif lrl = htod32(vwrq->value); if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl)))) return error; } + +#if WIRELESS_EXT > 20 + if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) || + !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) { +#else if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) { +#endif srl = htod32(vwrq->value); if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl)))) return error; } } - return 0; } @@ -2991,7 +3191,7 @@ wl_iw_get_encode( wsec = dtoh32(wsec); auth = dtoh32(auth); - dwrq->length = MIN(IW_ENCODING_TOKEN_MAX, key.len); + dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len); dwrq->flags = key.index + 1; @@ -3063,8 +3263,8 @@ wl_iw_set_wpaie( char *extra ) { - WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name)); - dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); + dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); + return 0; } @@ -3181,6 +3381,9 @@ wl_iw_set_encodeext( break; } swap_key_from_BE(&key); + + dhd_wait_pend8021x(dev); + error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); if (error) return error; @@ -3188,6 +3391,103 @@ wl_iw_set_encodeext( return 0; } +#if WIRELESS_EXT > 17 +#ifdef BCMWPA2 +struct { + pmkid_list_t pmkids; + pmkid_t foo[MAXPMKID-1]; +} pmkid_list; + +static int +wl_iw_set_pmksa( + struct net_device *dev, + struct iw_request_info *info, + struct iw_param *vwrq, + char *extra +) +{ + struct iw_pmksa *iwpmksa; + uint i; + char eabuf[ETHER_ADDR_STR_LEN]; + + WL_TRACE(("%s: SIOCSIWPMKSA\n", dev->name)); + iwpmksa = (struct iw_pmksa *)extra; + bzero((char *)eabuf, ETHER_ADDR_STR_LEN); + + if (iwpmksa->cmd == IW_PMKSA_FLUSH) { + WL_TRACE(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n")); + bzero((char *)&pmkid_list, sizeof(pmkid_list)); + } + + if (iwpmksa->cmd == IW_PMKSA_REMOVE) { + pmkid_list_t pmkid, *pmkidptr; + pmkidptr = &pmkid; + + bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, ETHER_ADDR_LEN); + bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN); + { + uint j; + WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ", + bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID, + eabuf))); + for (j = 0; j < WPA2_PMKID_LEN; j++) + WL_TRACE(("%02x ", pmkidptr->pmkid[0].PMKID[j])); + WL_TRACE(("\n")); + } + + for (i = 0; i < pmkid_list.pmkids.npmkid; i++) + if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID, + ETHER_ADDR_LEN)) + break; + + for (; i < pmkid_list.pmkids.npmkid; i++) { + bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID, + &pmkid_list.pmkids.pmkid[i].BSSID, + ETHER_ADDR_LEN); + bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID, + &pmkid_list.pmkids.pmkid[i].PMKID, + WPA2_PMKID_LEN); + } + pmkid_list.pmkids.npmkid--; + } + + if (iwpmksa->cmd == IW_PMKSA_ADD) { + bcopy(&iwpmksa->bssid.sa_data[0], + &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].BSSID, + ETHER_ADDR_LEN); + bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[pmkid_list.pmkids.npmkid].PMKID, + WPA2_PMKID_LEN); + { + uint j; + uint k; + k = pmkid_list.pmkids.npmkid; + WL_TRACE(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", + bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID, + eabuf))); + for (j = 0; j < WPA2_PMKID_LEN; j++) + WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j])); + WL_TRACE(("\n")); + } + pmkid_list.pmkids.npmkid++; + } + WL_TRACE(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid)); + for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { + uint j; + WL_TRACE(("PMKID[%d]: %s = ", i, + bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID, + eabuf))); + for (j = 0; j < WPA2_PMKID_LEN; j++) + WL_TRACE(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j])); + printf("\n"); + } + WL_TRACE(("\n")); + + dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, sizeof(pmkid_list)); + return 0; +} +#endif +#endif + static int wl_iw_get_encodeext( struct net_device *dev, @@ -3219,6 +3519,9 @@ wl_iw_set_wpaauth( paramid = vwrq->flags & IW_AUTH_INDEX; paramval = vwrq->value; + WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n", + dev->name, paramid, paramval)); + switch (paramid) { case IW_AUTH_WPA_VERSION: @@ -3230,7 +3533,7 @@ wl_iw_set_wpaauth( else if (paramval & IW_AUTH_WPA_VERSION_WPA2) val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; #endif - WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); + WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; break; @@ -3277,7 +3580,7 @@ wl_iw_set_wpaauth( val = WPA2_AUTH_UNSPECIFIED; } #endif - WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); + WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) return error; break; @@ -3287,7 +3590,7 @@ wl_iw_set_wpaauth( case IW_AUTH_80211_AUTH_ALG: - WL_ERROR(("Setting the D11auth %d\n", paramval)); + WL_INFORM(("Setting the D11auth %d\n", paramval)); if (paramval == IW_AUTH_ALG_OPEN_SYSTEM) val = 0; else if (paramval == IW_AUTH_ALG_SHARED_KEY) @@ -3311,7 +3614,7 @@ wl_iw_set_wpaauth( dev_wlc_intvar_set(dev, "wsec", val); } val = 0; - WL_ERROR(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); + WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); dev_wlc_intvar_set(dev, "wpa_auth", 0); return error; } @@ -3329,11 +3632,11 @@ wl_iw_set_wpaauth( #if WIRELESS_EXT > 17 case IW_AUTH_ROAMING_CONTROL: - WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); + WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); break; case IW_AUTH_PRIVACY_INVOKED: - WL_ERROR(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__)); + WL_INFORM(("%s: IW_AUTH_PRIVACY_INVOKED\n", __FUNCTION__)); break; #endif default: @@ -3452,6 +3755,8 @@ wl_iw_get_wpaauth( } #endif + + static int wl_iw_set_priv( struct net_device *dev, @@ -3463,6 +3768,7 @@ wl_iw_set_priv( int ret = 0; char * extra; + wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); if (!(extra = kmalloc(dwrq->length, GFP_KERNEL))) return -ENOMEM; @@ -3476,6 +3782,8 @@ wl_iw_set_priv( if (dwrq->length && extra) { + WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_PRIV, "wl_iw_set_priv"); + WAKE_LOCK(iw->pub, WAKE_LOCK_PRIV); if (g_onoff == G_WLAN_SET_OFF) { wl_iw_control_wl_on(dev, info); @@ -3508,12 +3816,15 @@ wl_iw_set_priv( ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, "STOP", strlen("STOP")) == 0) ret = wl_iw_control_wl_off(dev, info); + else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) + ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); else { snprintf(extra, MAX_WX_STRING, "OK"); dwrq->length = strlen("OK") + 1; WL_TRACE(("Unkown PRIVATE command , ignored\n")); } - + WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV); + WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV); } if (extra) { @@ -3606,7 +3917,7 @@ static const iw_handler wl_iw_handler[] = (iw_handler) wl_iw_set_encodeext, (iw_handler) wl_iw_get_encodeext, #ifdef BCMWPA2 - (iw_handler) NULL, + (iw_handler) wl_iw_set_pmksa, #endif #endif }; @@ -3999,7 +4310,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) cmd = IWEVPMKIDCAND; pmkcandlist = data; - count = pmkcandlist->npmkid_cand; + count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand); + ASSERT(count >= 0); wrqu.data.length = sizeof(struct iw_pmkid_cand); pmkidcand = pmkcandlist->pmkid_cand; while (count) { @@ -4022,7 +4334,8 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) case WLC_E_SCAN_COMPLETE: #if defined(WL_IW_USE_ISCAN) - if ((g_iscan) && (g_iscan->sysioc_pid >= 0)) + if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && + (g_iscan->iscan_state != ISCAN_STATE_IDLE)) up(&g_iscan->sysioc_sem); #else cmd = SIOCGIWSCAN; @@ -4140,8 +4453,150 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat done: return res; } -int wl_iw_attach(struct net_device *dev) +static void +wl_iw_bt_flag_set( + struct net_device *dev, + bool set) { + char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; + char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + + if (set == TRUE) { + + dev_wlc_bufvar_set(dev, "btc_flags", \ + (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on)); + } + else { + + dev_wlc_bufvar_set(dev, "btc_flags", \ + (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif +} + +static void +wl_iw_bt_timerfunc(ulong data) +{ + bt_info_t *bt_local = (bt_info_t *)data; + bt_local->timer_on = 0; + WL_TRACE(("%s\n", __FUNCTION__)); + + up(&bt_local->bt_sem); +} + +static int +_bt_dhcp_sysioc_thread(void *data) +{ + DAEMONIZE("dhcp_sysioc"); + + while (down_interruptible(&g_bt->bt_sem) == 0) { + if (g_bt->timer_on) { + del_timer(&g_bt->timer); + g_bt->timer_on = 0; + } + + switch (g_bt->bt_state) { + case BT_DHCP_START: + + g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW; + mod_timer(&g_bt->timer, jiffies + \ + BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000); + g_bt->timer_on = 1; + break; + case BT_DHCP_OPPORTUNITY_WINDOW: + + WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \ + __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM)); + if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE); + g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; + mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); + g_bt->timer_on = 1; + break; + case BT_DHCP_FLAG_FORCE_TIMEOUT: + + WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \ + __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME)); + + if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE); + g_bt->bt_state = BT_DHCP_IDLE; + g_bt->timer_on = 0; + break; + default: + WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \ + g_bt->bt_state)); + if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE); + g_bt->bt_state = BT_DHCP_IDLE; + g_bt->timer_on = 0; + break; + } + } + + if (g_bt->timer_on) { + del_timer(&g_bt->timer); + g_bt->timer_on = 0; + } + complete_and_exit(&g_bt->bt_exited, 0); +} + +static void +wl_iw_bt_release(void) +{ + bt_info_t *bt_local = g_bt; + + if (!bt_local) { + return; + } + + if (bt_local->bt_pid >= 0) { + KILL_PROC(bt_local->bt_pid, SIGTERM); + wait_for_completion(&bt_local->bt_exited); + } + kfree(bt_local); + g_bt = NULL; +} + +static int +wl_iw_bt_init(struct net_device *dev) +{ + bt_info_t *bt_dhcp = NULL; + + bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL); + if (!bt_dhcp) + return -ENOMEM; + + memset(bt_dhcp, 0, sizeof(bt_info_t)); + bt_dhcp->bt_pid = -1; + g_bt = bt_dhcp; + bt_dhcp->dev = dev; + bt_dhcp->bt_state = BT_DHCP_IDLE; + + + bt_dhcp->timer_ms = 10; + init_timer(&bt_dhcp->timer); + bt_dhcp->timer.data = (ulong)bt_dhcp; + bt_dhcp->timer.function = wl_iw_bt_timerfunc; + + sema_init(&bt_dhcp->bt_sem, 0); + init_completion(&bt_dhcp->bt_exited); + bt_dhcp->bt_pid = kernel_thread(_bt_dhcp_sysioc_thread, bt_dhcp, 0); + if (bt_dhcp->bt_pid < 0) { + WL_ERROR(("Failed in %s\n", __FUNCTION__)); + return -ENOMEM; + } + + return 0; +} + +int wl_iw_attach(struct net_device *dev, void * dhdp) +{ + wl_iw_t *iw; #if defined(WL_IW_USE_ISCAN) iscan_info_t *iscan = NULL; @@ -4172,6 +4627,8 @@ int wl_iw_attach(struct net_device *dev) return -ENOMEM; #endif + iw = *(wl_iw_t **)netdev_priv(dev); + iw->pub = (dhd_pub_t *)dhdp; g_scan = NULL; @@ -4184,6 +4641,10 @@ int wl_iw_attach(struct net_device *dev) wl_iw_init_ss_cache_ctrl(); + + wl_iw_bt_init(dev); + + return 0; } @@ -4215,5 +4676,7 @@ void wl_iw_detach(void) g_scan = NULL; wl_iw_release_ss_cache_ctrl(); + wl_iw_bt_release(); + } diff --git a/bcm4329/src/wl/sys/wl_iw.h b/bcm4329/src/wl/sys/wl_iw.h index b19e22c..64d8fc2 100644 --- a/bcm4329/src/wl/sys/wl_iw.h +++ b/bcm4329/src/wl/sys/wl_iw.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_iw.h,v 1.5.34.1.6.8 2009/06/29 18:54:46 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.6.9 2009/10/14 04:27:31 Exp $ */ @@ -71,6 +71,7 @@ typedef struct wl_iw { struct ether_addr spy_addr[IW_MAX_SPY]; struct iw_quality spy_qual[IW_MAX_SPY]; void *wlinfo; + dhd_pub_t * pub; } wl_iw_t; struct wl_ctrl { @@ -115,7 +116,7 @@ extern const struct iw_handler_def wl_iw_handler_def; extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); -int wl_iw_attach(struct net_device *dev); +int wl_iw_attach(struct net_device *dev, void * dhdp); void wl_iw_detach(void); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) |