diff options
author | Howard Harte <hharte@broadcom.com> | 2009-03-30 17:09:32 -0700 |
---|---|---|
committer | Howard Harte <hharte@broadcom.com> | 2009-03-30 17:09:32 -0700 |
commit | f42f81d9f222732884ecf14adfeaee6a58e8a534 (patch) | |
tree | d57463b317aa94b44441d2f9b7103c872c97a5ba | |
parent | 4d9cbf702872c23734edf9af540852330ca8590a (diff) | |
download | broadcom-f42f81d9f222732884ecf14adfeaee6a58e8a534.tar.gz |
Updated support for Android.
-rw-r--r-- | src/bcmsdio/sys/bcmsdh.c | 26 | ||||
-rw-r--r-- | src/bcmsdio/sys/bcmsdh_sdmmc.c | 263 | ||||
-rw-r--r-- | src/bcmsdio/sys/bcmsdh_sdmmc_linux.c | 77 | ||||
-rw-r--r-- | src/dhd/exe/GNUmakefile | 4 | ||||
-rw-r--r-- | src/dhd/exe/dhdu.c | 4 | ||||
-rwxr-xr-x | src/dhd/linux/Makefile | 28 | ||||
-rw-r--r-- | src/dhd/sys/dhd.h | 45 | ||||
-rw-r--r-- | src/dhd/sys/dhd_bus.h | 31 | ||||
-rw-r--r-- | src/dhd/sys/dhd_cdc.c | 73 | ||||
-rw-r--r-- | src/dhd/sys/dhd_common.c | 69 | ||||
-rw-r--r-- | src/dhd/sys/dhd_linux.c | 136 | ||||
-rw-r--r-- | src/dhd/sys/dhd_proto.h | 32 | ||||
-rw-r--r-- | src/dhd/sys/dhd_sdio.c | 163 | ||||
-rw-r--r-- | src/include/bcmdefs.h | 28 | ||||
-rw-r--r-- | src/include/bcmsdbus.h | 7 | ||||
-rw-r--r-- | src/include/bcmsdh.h | 7 | ||||
-rw-r--r-- | src/include/bcmsdh_sdmmc.h | 5 | ||||
-rw-r--r-- | src/include/epivers.h | 38 | ||||
-rw-r--r-- | src/include/linuxver.h | 4 | ||||
-rw-r--r-- | src/include/proto/802.11.h | 32 | ||||
-rw-r--r-- | src/include/proto/bcmevent.h | 31 | ||||
-rw-r--r-- | src/include/proto/eapol.h | 4 | ||||
-rw-r--r-- | src/include/sbchipc.h | 33 | ||||
-rw-r--r-- | src/include/wlioctl.h | 96 | ||||
-rw-r--r-- | src/wl/sys/wl_iw.c | 1428 | ||||
-rw-r--r-- | src/wl/sys/wl_iw.h | 40 |
26 files changed, 2170 insertions, 534 deletions
diff --git a/src/bcmsdio/sys/bcmsdh.c b/src/bcmsdio/sys/bcmsdh.c index f92da43..afbf5e0 100644 --- a/src/bcmsdio/sys/bcmsdh.c +++ b/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.16.3 2008/12/17 04:22:21 Exp $ + * $Id: bcmsdh.c,v 1.35.2.1.4.8.16.4 2009/03/19 04:09:04 Exp $ */ /* ****************** BCMSDH Interface Functions *************************** */ @@ -182,6 +182,30 @@ bcmsdh_intr_pending(void *sdh) } #endif +#ifdef BCMLXSDMMC +int +bcmsdh_claim_host_and_lock(void *sdh) +{ + bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; + SDIOH_API_RC status; + ASSERT(bcmsdh); + + status = sdioh_claim_host_and_lock(bcmsdh->sdioh); + return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); +} + +int +bcmsdh_release_host_and_unlock(void *sdh) +{ + bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; + SDIOH_API_RC status; + ASSERT(bcmsdh); + + status = sdioh_release_host_and_unlock(bcmsdh->sdioh); + return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); +} +#endif /* BCMLXSDMMC */ + int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) { diff --git a/src/bcmsdio/sys/bcmsdh_sdmmc.c b/src/bcmsdio/sys/bcmsdh_sdmmc.c index ef1a773..c6f5de2 100644 --- a/src/bcmsdio/sys/bcmsdh_sdmmc.c +++ b/src/bcmsdio/sys/bcmsdh_sdmmc.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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: bcmsdh_sdmmc.c,v 1.1.2.8.6.4 2008/12/24 03:52:33 Exp $ + * $Id: bcmsdh_sdmmc.c,v 1.1.2.8.6.10 2009/03/24 23:07:13 Exp $ */ #include <typedefs.h> @@ -49,10 +47,9 @@ extern void sdio_function_cleanup(void); #endif /* BCMSDH_MODULE */ static void IRQHandler(struct sdio_func *func); -#ifdef USE_STOCK_MMC_DRIVER /* Define to use unmodified Linux Kernel mmc driver. */ static void IRQHandlerF2(struct sdio_func *func); -#endif /* USE_STOCK_MMC_DRIVER */ static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); +extern int sdio_reset_comm(struct mmc_card *card); extern PBCMSDH_SDMMC_INSTANCE gInstance; @@ -71,6 +68,35 @@ uint sd_use_dma = TRUE; int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); +int sdioh_claim_host_and_lock(sdioh_info_t *sd) +{ + sdio_claim_host(gInstance->func[0]); + gInstance->host_claimed = 1; + return SDIOH_API_RC_SUCCESS; +} + +int sdioh_release_host_and_unlock(sdioh_info_t *sd) +{ + gInstance->host_claimed = 0; + sdio_release_host(gInstance->func[0]); + return SDIOH_API_RC_SUCCESS; +} + + +void SDIO_CLAIM_HOST(uint32 func) +{ + if (gInstance->host_claimed == 0) { + sdio_claim_host(gInstance->func[func]); + } +} + +void SDIO_RELEASE_HOST(uint32 func) +{ + if (gInstance->host_claimed == 0) { + sdio_release_host(gInstance->func[func]); + } +} + static int sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) { @@ -97,9 +123,10 @@ 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 */ - sdio_claim_host(gInstance->func[1]); + gInstance->host_claimed = 0; + SDIO_CLAIM_HOST(1); err_ret = sdio_enable_func(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); + SDIO_RELEASE_HOST(1); if (err_ret) { sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret)); } @@ -143,7 +170,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) gInstance->sd = sd; /* Claim host controller */ - sdio_claim_host(gInstance->func[1]); + SDIO_CLAIM_HOST(1); sd->client_block_size[1] = 64; err_ret = sdio_set_block_size(gInstance->func[1], 64); @@ -152,10 +179,11 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) } /* Release host controller F1 */ - sdio_release_host(gInstance->func[1]); + SDIO_RELEASE_HOST(1); + if (gInstance->func[2]) { /* Claim host controller F2 */ - sdio_claim_host(gInstance->func[2]); + SDIO_CLAIM_HOST(2); sd->client_block_size[2] = sd_f2_blocksize; err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); @@ -164,21 +192,12 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) sd_f2_blocksize)); } -#ifdef USE_STOCK_MMC_DRIVER - err_ret = sdio_claim_irq(gInstance->func[2], IRQHandlerF2); -#endif /* USE_STOCK_MMC_DRIVER */ - /* Release host controller F2 */ - sdio_release_host(gInstance->func[2]); + SDIO_RELEASE_HOST(2); } sdioh_sdmmc_card_enablefuncs(sd); - /* register and unmask irq */ - sdio_claim_host(gInstance->func[1]); - err_ret = sdio_claim_irq(gInstance->func[1], IRQHandler); - sdio_release_host(gInstance->func[1]); - sd_trace(("%s: Done\n", __FUNCTION__)); return sd; } @@ -191,6 +210,16 @@ sdioh_detach(osl_t *osh, sdioh_info_t *sd) if (sd) { + /* Disable Function 2 */ + SDIO_CLAIM_HOST(2); + sdio_disable_func(gInstance->func[2]); + SDIO_RELEASE_HOST(2); + + /* Disable Function 1 */ + SDIO_CLAIM_HOST(1); + sdio_disable_func(gInstance->func[1]); + SDIO_RELEASE_HOST(1); + /* deregister irq */ sdioh_sdmmc_osfree(sd); @@ -204,9 +233,26 @@ extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) { sd_trace(("%s: Entering\n", __FUNCTION__)); + if (fn == NULL) { + sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__)); + return SDIOH_API_RC_FAIL; + } 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_irq(gInstance->func[2], IRQHandlerF2); + SDIO_RELEASE_HOST(2); + } + + if (gInstance->func[1]) { + SDIO_CLAIM_HOST(1); + sdio_claim_irq(gInstance->func[1], IRQHandler); + SDIO_RELEASE_HOST(1); + } return SDIOH_API_RC_SUCCESS; } @@ -214,6 +260,22 @@ extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *sd) { sd_trace(("%s: Entering\n", __FUNCTION__)); + + if (gInstance->func[1]) { + /* register and unmask irq */ + SDIO_CLAIM_HOST(1); + sdio_release_irq(gInstance->func[1]); + SDIO_RELEASE_HOST(1); + } + + if (gInstance->func[2]) { + /* Claim host controller F2 */ + SDIO_CLAIM_HOST(2); + sdio_release_irq(gInstance->func[2]); + /* Release host controller F2 */ + SDIO_RELEASE_HOST(2); + } + sd->intr_handler_valid = FALSE; sd->intr_handler = NULL; sd->intr_handler_arg = NULL; @@ -632,7 +694,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(gInstance->func[2]); + SDIO_CLAIM_HOST(2); if (*byte & SDIO_FUNC_ENABLE_2) { /* Enable Function 2 */ err_ret = sdio_enable_func(gInstance->func[2]); @@ -648,25 +710,25 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by err_ret)); } } - sdio_release_host(gInstance->func[2]); + SDIO_RELEASE_HOST(2); } } 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(gInstance->func[func]); + SDIO_CLAIM_HOST(func); sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); + SDIO_RELEASE_HOST(func); } } else { /* Claim host controller, perform Fn write, and release */ - sdio_claim_host(gInstance->func[func]); + SDIO_CLAIM_HOST(func); sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); + SDIO_RELEASE_HOST(func); } } else { /* CMD52 Read */ /* Claim host controller, perform Fn read, and release */ - sdio_claim_host(gInstance->func[func]); + SDIO_CLAIM_HOST(func); if (func == 0) { *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret); @@ -674,7 +736,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(gInstance->func[func]); + SDIO_RELEASE_HOST(func); } if (err_ret) { @@ -700,7 +762,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add __FUNCTION__, cmd_type, rw, func, addr, nbytes)); /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); + SDIO_CLAIM_HOST(func); if(rw) { /* CMD52 Write */ if (nbytes == 4) { @@ -721,7 +783,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add } /* Release host controller */ - sdio_release_host(gInstance->func[func]); + SDIO_RELEASE_HOST(func); if (err_ret) { sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", @@ -746,7 +808,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, ASSERT(pkt); /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); + SDIO_CLAIM_HOST(func); for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { uint pkt_len = PKTLEN(sd->osh, pnext); pkt_len += 3; @@ -804,7 +866,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, } /* Release host controller */ - sdio_release_host(gInstance->func[func]); + SDIO_RELEASE_HOST(func); sd_trace(("%s: Exit\n", __FUNCTION__)); return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -838,6 +900,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) { sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, buflen_u)); + return SDIOH_API_RC_FAIL; } /* For a write, copy the buffer data into the packet. */ @@ -864,6 +927,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { sd_err(("%s: PKTGET failed: len %d\n", __FUNCTION__, PKTLEN(sd->osh, pkt))); + return SDIOH_API_RC_FAIL; } /* For a write, copy the buffer data into the packet. */ @@ -897,15 +961,6 @@ sdioh_abort(sdioh_info_t *sd, uint func) { sd_trace(("%s: Enter\n", __FUNCTION__)); - /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); - -#ifndef USE_STOCK_MMC_DRIVER - sdio_abort(gInstance->func[func]); -#endif /* USE_STOCK_MMC_DRIVER */ - - /* Release host controller */ - sdio_release_host(gInstance->func[func]); sd_trace(("%s: Exit\n", __FUNCTION__)); return SDIOH_API_RC_SUCCESS; @@ -966,23 +1021,24 @@ static void IRQHandler(struct sdio_func *func) sdioh_info_t *sd; sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n")); - sd = gInstance->sd; ASSERT(sd != NULL); - + gInstance->host_claimed = 1; if (sd->client_intr_enabled && sd->use_client_ints) { sd->intrcount++; ASSERT(sd->intr_handler); ASSERT(sd->intr_handler_arg); (sd->intr_handler)(sd->intr_handler_arg); } else { - sd_trace(("%s: Not ready for intr: enabled %d, handler %p\n", + sd_err(("bcmsdh_sdmmc: ***IRQHandler\n")); + + sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", __FUNCTION__, sd->client_intr_enabled, sd->intr_handler)); } + gInstance->host_claimed = 0; } -#ifdef USE_STOCK_MMC_DRIVER /* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */ static void IRQHandlerF2(struct sdio_func *func) { @@ -994,7 +1050,6 @@ static void IRQHandlerF2(struct sdio_func *func) ASSERT(sd != NULL); } -#endif /* USE_STOCK_MMC_DRIVER */ #ifdef NOTUSED /* Write client card reg */ @@ -1022,3 +1077,93 @@ sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsiz return SUCCESS; } #endif /* NOTUSED */ + + +void +sdioh_start(int stage) +{ + int ret; + sdioh_info_t *sd = gInstance->sd; + + /* Need to do this stages as we can't enable the interrupt till + downloading of the firmware is complete, other wise polling + sdio access will come in way + */ + if (gInstance->func[0]) { + if (stage == 0) { + + /* Since the power to the chip is killed, we will have + re enumerate the device again. Set the block size + and enable the fucntion 1 for in preparation for + downloading the code + */ + /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux + 2.6.27. The implementation prior to that is buggy, and needs broadcom's + patch for it + */ + if ((ret = sdio_reset_comm(gInstance->func[0]->card))) + sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); + else { + sd->num_funcs = 2; + sd->sd_blockmode = TRUE; + sd->use_client_ints = TRUE; + sd->client_block_size[0] = 64; + + /* Claim host controller */ + SDIO_CLAIM_HOST(1); + + sd->client_block_size[1] = 64; + if (sdio_set_block_size(gInstance->func[1], 64)) { + sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); + } + + /* Release host controller F1 */ + SDIO_RELEASE_HOST(1); + + if (gInstance->func[2]) { + /* Claim host controller F2 */ + SDIO_CLAIM_HOST(2); + + sd->client_block_size[2] = sd_f2_blocksize; + if (sdio_set_block_size(gInstance->func[2], + sd_f2_blocksize)) { + sd_err(("bcmsdh_sdmmc: Failed to set F2 " + "blocksize to %d\n", sd_f2_blocksize)); + } + + /* Release host controller F2 */ + SDIO_RELEASE_HOST(2); + } + + sdioh_sdmmc_card_enablefuncs(sd); + } + } + else if (stage == 1) { + SDIO_CLAIM_HOST(0); + sdio_claim_irq(gInstance->func[2], IRQHandlerF2); + sdio_claim_irq(gInstance->func[1], IRQHandler); + SDIO_RELEASE_HOST(0); + } + } + else + sd_err(("%s Failed\n", __FUNCTION__)); +} + +void +sdioh_stop(void) +{ + /* MSM7201A Android sdio stack has bug with interrupt + So internaly within SDIO stack they are polling + which cause issue when device is turned off. So + unregister interrupt with SDIO stack to stop the + polling + */ + if (gInstance->func[0]) { + SDIO_CLAIM_HOST(0); + sdio_release_irq(gInstance->func[1]); + sdio_release_irq(gInstance->func[2]); + SDIO_RELEASE_HOST(0); + } + else + sd_err(("%s Failed\n", __FUNCTION__)); +} diff --git a/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c b/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c index cb307ff..b3b3bfc 100644 --- a/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c +++ b/src/bcmsdio/sys/bcmsdh_sdmmc_linux.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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: bcmsdh_sdmmc_linux.c,v 1.1.2.5.20.3 2009/01/18 18:18:20 Exp $ + * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.20.5 2009/03/03 08:55:39 Exp $ */ #include <typedefs.h> @@ -69,6 +67,7 @@ PBCMSDH_SDMMC_INSTANCE gInstance; #define BCMSDH_SDMMC_MAX_DEVICES 1 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, @@ -108,6 +107,11 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func) sd_info(("sdio_vendor: 0x%04x\n", func->vendor)); sd_info(("sdio_device: 0x%04x\n", func->device)); sd_info(("Function#: 0x%04x\n", func->num)); + + if (func->num == 2) { + sd_trace(("F2 found, calling bcmsdh_probe...\n")); + bcmsdh_remove(&sdmmc_dev); + } } @@ -235,45 +239,10 @@ int sdio_function_init(void) extern int bcmsdh_remove(struct device *dev); void sdio_function_cleanup(void) { - int err_ret; - - bcmsdh_remove(&sdmmc_dev); - - sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); - - if (gInstance->func[1]) { - /* Disable Interrupt */ - sdio_claim_host(gInstance->func[1]); - err_ret = sdio_release_irq(gInstance->func[1]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed release of F1 IRQ, Err: 0x%08x", err_ret)); - } - - err_ret = sdio_disable_func(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to disable F1, Err: 0x%08x", err_ret)); - } - } + sd_trace(("%s Enter\n", __FUNCTION__)); - /* Disable Function 2 */ - if (gInstance->func[2]) { - sdio_claim_host(gInstance->func[2]); - err_ret = sdio_release_irq(gInstance->func[2]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to release IRQ for F2, Err: 0x%08x", - err_ret)); - } - err_ret = sdio_disable_func(gInstance->func[2]); - sdio_release_host(gInstance->func[2]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to disable F2, Err: 0x%08x", err_ret)); - } - } + sdio_unregister_driver(&bcmsdh_sdmmc_driver); - if (gInstance) { + if (gInstance) kfree(gInstance); - } - - sdio_unregister_driver(&bcmsdh_sdmmc_driver); } diff --git a/src/dhd/exe/GNUmakefile b/src/dhd/exe/GNUmakefile index f7dfa2e..0b90015 100644 --- a/src/dhd/exe/GNUmakefile +++ b/src/dhd/exe/GNUmakefile @@ -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: GNUmakefile,v 1.9.24.4.16.4 2008/12/20 01:35:34 Exp $ +# $Id: GNUmakefile,v 1.9.24.4.16.5 2009/03/03 08:51:47 Exp $ SRCBASE = ../.. @@ -61,7 +61,7 @@ ifneq ($(findstring x86,$(TARGETARCH)),x86) endif # extra warnings -CFLAGS += -Wextra +CFLAGS += -Wextra $(CUSTOM_FLAGS) vpath %.c $(SRCBASE)/shared diff --git a/src/dhd/exe/dhdu.c b/src/dhd/exe/dhdu.c index cee5250..b4bcbdd 100644 --- a/src/dhd/exe/dhdu.c +++ b/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.16.7 2009/01/08 18:31:54 Exp $ + * $Id: dhdu.c,v 1.52.2.10.2.6.16.9 2009/03/12 21:33:24 Exp $ */ /* For backwards compatibility, the absense of the define 'BWL_NO_FILESYSTEM_SUPPORT' @@ -159,6 +159,8 @@ cmd_t dhd_cmds[] = { "get/set dhd tx dpc thread quantum"}, { "senduptq", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, "get/set dhd sendup thread time quantum"}, + { "rxflow", dhd_varint, DHD_GET_VAR, DHD_SET_VAR, + "get/set dhd rx flow control enable flag"}, { "dump", dhd_varstr, DHD_GET_VAR, -1, "dump information"}, { "clearcounts", dhd_var_void, -1, DHD_SET_VAR, diff --git a/src/dhd/linux/Makefile b/src/dhd/linux/Makefile index 323e8be..3418513 100755 --- a/src/dhd/linux/Makefile +++ b/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.12.14 2009/02/20 17:56:01 Exp $ +# $Id: Makefile,v 1.55.2.6.2.10.12.20 2009/03/24 23:07:15 Exp $ # # Try a couple of places for LINUXDIR if not specified @@ -41,9 +41,18 @@ endif endif endif -LINUXVER := $(shell { cat $(LINUXDIR)/Makefile; \ - echo "bcm$$$$:;@echo \$$(KERNELRELEASE)"; } | \ - $(MAKE) --no-print-directory $(if $(ARCH),ARCH=$(ARCH),) -C $(LINUXDIR) -f - bcm$$$$) +# Derive LINUXVER from LINUXDIR +MYKERNEL_RELEASE_KEYWORD:="KERNELRELEASE[[:space:]]*=.*kernel.release" +MYKERNEL_DEFINITION:=$(if \ + $(shell grep $(MYKERNEL_RELEASE_KEYWORD) $(LINUXDIR)/Makefile 2> /dev/null),\ + grep $(MYKERNEL_RELEASE_KEYWORD) $(LINUXDIR)/Makefile,\ + cat $(LINUXDIR)/Makefile) + +LINUXVER:=$(shell ($(MYKERNEL_DEFINITION); echo "show_kernel_version_number$$$$:;@echo \$$(KERNELRELEASE)") 2> /dev/null | $(MAKE) --no-print-directory -k -C $(LINUXDIR) MYUNAME="" -f - show_kernel_version_number$$$$ 2> /dev/null) + +ifeq ($(LINUXVER),) + $(error LINUXVER=$(LINUXVER) is empty) +endif # LINUXVER # check if 2.4 kernel or 2.5+ kernel BCM_KVER:=$(shell echo $(LINUXVER) | cut -c1-3 | sed 's/2\.[56]/2\.6/') @@ -67,14 +76,11 @@ DFLAGS := # basic options (defines in DFLAGS, includes in IFLAGS) DFLAGS += -DLINUX -DSRCBASE=\"$(SRCBASE)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 DFLAGS += -DUNRELEASEDCHIP -ifeq ($(USE_STOCK_MMC_DRIVER),1) - DFLAGS += -DUSE_STOCK_MMC_DRIVER -endif ifeq ($(BCMQT),1) DFLAGS += -DBCMSLTGT -DBCMQT endif ifeq ($(WLTEST),1) - DFLAGS += -DWLTEST -DIOCTL_RESP_TIMEOUT=8000 + DFLAGS += -DWLTEST -DIOCTL_RESP_TIMEOUT=20000 DFLAGS += -DDHD_SPROM endif @@ -90,7 +96,7 @@ DFLAGS += -DCONFIG_WIRELESS_EXT endif ifeq ($(CONFIG_MMC_MSM7X00A),y) -DFLAGS += -Dlinux -DUSE_STOCK_MMC_DRIVER +DFLAGS += -Dlinux DFLAGS += -DDHD_SDALIGN=64 -DMAX_HDR_READ=64 -DDHD_FIRSTREAD=64 endif @@ -170,7 +176,7 @@ DFLAGS += -DBCMSDIO -DBCMSDIOH_STD CFILES += dhd_sdio.c bcmsdh.c bcmsdstd.c bcmsdstd_linux.c bcmsdh_linux.c endif ifneq ($(findstring -sdmmc-,-$(TARGET)-),) -DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS +DFLAGS += -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC -DBCMPLATFORM_BUS -DSDIO_ISR_THREAD CFILES += dhd_sdio.c bcmsdh_sdmmc.c bcmsdh.c bcmsdh_linux.c bcmsdh_sdmmc_linux.c endif ifneq ($(findstring -sdspi-,$(TARGET)-),) @@ -188,7 +194,7 @@ ifneq ($(findstring -intc1,$(shell echo $(LINUXVER))),) DFLAGS += -DSANDGATE2G endif -CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) +CFLAGS += -fshort-wchar $(DFLAGS) $(WFLAGS) $(IFLAGS) $(CUSTOM_FLAGS) LDFLAGS := -r MODULES := dhd.o diff --git a/src/dhd/sys/dhd.h b/src/dhd/sys/dhd.h index 67d13ed..74c4ae1 100644 --- a/src/dhd/sys/dhd.h +++ b/src/dhd/sys/dhd.h @@ -6,27 +6,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h,v 1.32.4.7.2.4.28.14 2009/01/08 01:41:03 Exp $ + * $Id: dhd.h,v 1.32.4.7.2.4.28.18 2009/03/06 21:20:39 Exp $ */ /**************** @@ -113,6 +111,7 @@ typedef struct dhd_pub { ulong rx_ctlpkts; /* Control frames processed from dongle */ ulong rx_ctlerrs; /* Errors in processing rx control frames */ ulong rx_dropped; /* Packets dropped locally (no memory) */ + ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */ ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */ ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */ @@ -138,10 +137,10 @@ WDF_DECLARE_CONTEXT_TYPE_WITH_NAME(wdf_device_info_t, dhd_get_wdf_device_info) #endif /* NDIS60 */ -typedef struct _dhd_if_event { - char ifidx; - char action; -} dhd_if_event; +typedef struct dhd_if_event { + uint8 ifidx; + uint8 action; +} dhd_if_event_t; /* * Exported from dhd OS modules (dhd_linux/dhd_ndis) @@ -204,14 +203,14 @@ 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, uint ifidx, void *handle, char *name); -extern void dhd_del_if(struct dhd_info *dhd, uint ifidx); +extern int dhd_add_if(struct dhd_info *dhd, uint8 ifidx, void *handle, char *name); +extern void dhd_del_if(struct dhd_info *dhd, uint8 ifidx); /* Send pakcet to dongle via data channel */ extern int dhd_sendpkt(dhd_pub_t *dhdp, uint ifidx, void *pkt); /* Send event to host */ -extern void dhd_sendup_event(dhd_pub_t *dhdp, void *pkt); +extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); /* diff --git a/src/dhd/sys/dhd_bus.h b/src/dhd/sys/dhd_bus.h index a53d180..ebc508b 100644 --- a/src/dhd/sys/dhd_bus.h +++ b/src/dhd/sys/dhd_bus.h @@ -6,27 +6,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_bus.h,v 1.4.6.3.2.3.20.3 2009/01/08 01:30:43 Exp $ + * $Id: dhd_bus.h,v 1.4.6.3.2.3.20.4 2009/02/03 21:40:44 Exp $ */ #ifndef _dhd_bus_h_ @@ -85,5 +83,6 @@ extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_par extern void *dhd_bus_pub(struct dhd_bus *bus); extern void *dhd_bus_txq(struct dhd_bus *bus); +extern uint dhd_bus_hdrlen(struct dhd_bus *bus); #endif /* _dhd_bus_h_ */ diff --git a/src/dhd/sys/dhd_cdc.c b/src/dhd/sys/dhd_cdc.c index bba3dbd..74a72a1 100644 --- a/src/dhd/sys/dhd_cdc.c +++ b/src/dhd/sys/dhd_cdc.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c,v 1.22.4.2.4.8.2.6 2009/01/16 02:39:00 Exp $ + * $Id: dhd_cdc.c,v 1.22.4.2.4.8.2.9 2009/02/25 07:27:58 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 @@ -480,10 +478,49 @@ dhd_prot_dstats(dhd_pub_t *dhd) } void +dhd_preinit_ioctls(dhd_pub_t *dhd) +{ + uint up = 0; + uint roamvar = 1; + char eventmask[WL_EVENTING_MASK_LEN]; + char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ + + /* Force STA UP */ + dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up)); + + /* 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)); + + /* Setup event_msgs */ + bzero(eventmask, sizeof(eventmask)); + setbit(eventmask, WLC_E_SET_SSID); + setbit(eventmask, WLC_E_PRUNE); + setbit(eventmask, WLC_E_AUTH); + setbit(eventmask, WLC_E_REASSOC); + setbit(eventmask, WLC_E_REASSOC_IND); + setbit(eventmask, WLC_E_DEAUTH_IND); + setbit(eventmask, WLC_E_DISASSOC_IND); + setbit(eventmask, WLC_E_DISASSOC); + setbit(eventmask, WLC_E_JOIN); + setbit(eventmask, WLC_E_ASSOC_IND); + setbit(eventmask, WLC_E_PSK_SUP); + setbit(eventmask, WLC_E_LINK); + setbit(eventmask, WLC_E_NDIS_LINK); + setbit(eventmask, WLC_E_MIC_ERROR); + setbit(eventmask, WLC_E_PMKID_CACHE); + setbit(eventmask, WLC_E_TXFAIL); + setbit(eventmask, WLC_E_JOIN_START); + setbit(eventmask, WLC_E_SCAN_COMPLETE); + + bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); +} + +void dhd_prot_init(dhd_pub_t *dhd) { char buf[128]; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); /* Get the device MAC address */ @@ -491,6 +528,8 @@ dhd_prot_init(dhd_pub_t *dhd) dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf)); memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); + dhd_preinit_ioctls(dhd); + /* Always assumes wl for now */ dhd->iswl = TRUE; diff --git a/src/dhd/sys/dhd_common.c b/src/dhd/sys/dhd_common.c index 4538764..d6e2ee0 100644 --- a/src/dhd/sys/dhd_common.c +++ b/src/dhd/sys/dhd_common.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c,v 1.5.6.8.2.8.2.18 2009/01/16 02:39:00 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.8.2.21 2009/02/11 01:23:12 Exp $ */ #include <typedefs.h> #include <osl.h> @@ -41,6 +39,9 @@ int dhd_msg_level; + /* Definitions to provide path to the firmware and nvram + *example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt" + */ char firmware_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; @@ -102,8 +103,6 @@ dhd_common_init(void) * first time that the driver is initialized vs subsequent initializations. */ dhd_msg_level = DHD_ERROR_VAL; - firmware_path[0] = '\0'; - nvram_path[0] = '\0'; } static int @@ -143,8 +142,8 @@ dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) dhdp->tx_ctlpkts, dhdp->tx_ctlerrs); bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld \n", dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors); - bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld\n", - dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped); + bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n", + dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped, dhdp->rx_flushed); bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld\n", dhdp->rx_readahead_cnt, dhdp->tx_realloc); bcm_bprintf(strbuf, "\n"); @@ -224,6 +223,7 @@ dhd_doiovar(dhd_pub_t * dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const c dhd_pub->rx_dropped = 0; dhd_pub->rx_readahead_cnt = 0; dhd_pub->tx_realloc = 0; + dhd_pub->rx_flushed = 0; memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats)); dhd_bus_clearcounts(dhd_pub); break; @@ -719,7 +719,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, { /* check whether packet is a BRCM event pkt */ bcm_event_t *pvt_data = (bcm_event_t *)pktdata; - void *event_data; + char *event_data; uint32 type, status; uint16 flags; @@ -737,18 +737,25 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, /* memcpy since BRCM event pkt may be unaligned. */ memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t)); - type = ntoh32(event->event_type); - flags = ntoh16(event->flags); - status = ntoh32(event->status); + type = ntoh32_ua((void *)&event->event_type); + flags = ntoh16_ua((void *)&event->flags); + status = ntoh32_ua((void *)&event->status); switch (type) { case WLC_E_IF: { - dhd_if_event *ifevent = (dhd_if_event *)event_data; - - if (ifevent->action == WLC_E_IF_ADD) - dhd_add_if(dhd, ifevent->ifidx, NULL, event->ifname); - else - dhd_del_if(dhd, ifevent->ifidx); + dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; + + 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); + else + dhd_del_if(dhd, ifevent->ifidx); + } else { + DHD_ERROR(("%s: Invalid ifidx %d for %s\n", + __FUNCTION__, ifevent->ifidx, event->ifname)); + } } break; case WLC_E_LINK: @@ -756,7 +763,7 @@ wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, case WLC_E_DEAUTH_IND: case WLC_E_DISASSOC: case WLC_E_DISASSOC_IND: - DHD_EVENT(("%s: Link event %d, flags %x, status %x\n", + DHD_ERROR(("%s: Link event %d, flags %x, status %x\n", __FUNCTION__, type, flags, status)); default: *ifidx = dhd_ifname2idx(dhd, event->ifname); diff --git a/src/dhd/sys/dhd_linux.c b/src/dhd/sys/dhd_linux.c index 3efbeb1..968c474 100644 --- a/src/dhd/sys/dhd_linux.c +++ b/src/dhd/sys/dhd_linux.c @@ -4,27 +4,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c,v 1.65.4.9.2.13.6.22 2009/01/18 00:27:49 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.13.6.29 2009/02/11 23:00:23 Exp $ */ #include <typedefs.h> @@ -231,9 +229,6 @@ static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR #ifdef CONFIG_WIRELESS_EXT -#if WIRELESS_EXT < 21 -static -#endif /* WIRELESS_EXT < 21 */ struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); #endif /* CONFIG_WIRELESS_EXT */ @@ -247,7 +242,7 @@ static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol); static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); #endif /* TOE */ -static int iw_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, +static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event_ptr, void **data_ptr); int @@ -445,6 +440,11 @@ dhd_op_if(dhd_if_t *ifp) switch (ifp->state) { case WLC_E_IF_ADD: + if (ifp->net != NULL) { + netif_stop_queue(ifp->net); + unregister_netdev(ifp->net); + free_netdev(ifp->net); + } /* Allocate etherdev, including space for private structure */ if (!(ifp->net = alloc_etherdev(0))) { DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); @@ -461,9 +461,11 @@ dhd_op_if(dhd_if_t *ifp) } break; case WLC_E_IF_DEL: - netif_stop_queue(ifp->net); - unregister_netdev(ifp->net); - ret = DHD_DEL_IF; + if (ifp->net != NULL) { + netif_stop_queue(ifp->net); + unregister_netdev(ifp->net); + ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ + } break; default: DHD_ERROR(("%s: bad op %d\n", __FUNCTION__, ifp->state)); @@ -608,7 +610,7 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net) ifidx = dhd_net2idx(dhd, net); if (ifidx == DHD_BAD_IF) { - DHD_TRACE(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); + DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); return -ENODEV; } @@ -724,7 +726,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) /* Process special event packets and then discard them */ if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) - iw_wl_host_event(dhd, &ifidx, + dhd_wl_host_event(dhd, &ifidx, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) skb->mac_header, #else @@ -764,17 +766,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) } void -dhd_sendup_event(dhd_pub_t *dhdp, void *pkt) -{ - dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); - int ifidx; - wl_event_msg_t event; - void *data; - - iw_wl_host_event(dhd, &ifidx, PKTDATA(dhdp->osh, pkt), &event, &data); -} - -void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) { uint ifidx; @@ -1298,8 +1289,8 @@ dhd_open(struct net_device *net) ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); - if (ifidx == DHD_BAD_IF) - return -1; + + ASSERT(ifidx == 0); /* download image and nvram to the dongle */ if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, @@ -1362,7 +1353,7 @@ dhd_osl_detach(osl_t *osh) } int -dhd_add_if(dhd_info_t *dhd, uint ifidx, void *handle, char *name) +dhd_add_if(dhd_info_t *dhd, uint8 ifidx, void *handle, char *name) { dhd_if_t *ifp; @@ -1398,7 +1389,7 @@ dhd_add_if(dhd_info_t *dhd, uint ifidx, void *handle, char *name) } void -dhd_del_if(dhd_info_t *dhd, uint ifidx) +dhd_del_if(dhd_info_t *dhd, uint8 ifidx) { dhd_if_t *ifp; @@ -1465,6 +1456,14 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) goto fail; } +#ifdef CONFIG_WIRELESS_EXT + /* Attach and link in the iw */ + if (wl_iw_attach(net) != 0) { + DHD_ERROR(("wl_iw_attach failed\n")); + goto fail; + } +#endif + /* Set up the watchdog timer */ init_timer(&dhd->timer); dhd->timer.data = (ulong)dhd; @@ -1523,17 +1522,22 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) struct net_device *net; uint8 temp_ethaddr[6] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 }; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); ASSERT(dhd && dhd->iflist[ifidx]); ASSERT(dhd->iflist[ifidx]->net); ASSERT(!dhd->iflist[ifidx]->net->open); - *temp_ethaddr = ifidx; /* Ok, link into the network layer... */ net = dhd->iflist[ifidx]->net; - net->open = dhd_open; - net->stop = dhd_stop; + if (ifidx == 0) { + /* + * device functions for the primary interface only + */ + net->open = dhd_open; + net->stop = dhd_stop; + } else + net->open = net->stop = NULL; net->get_stats = dhd_get_stats; net->do_ioctl = dhd_ioctl_entry; net->hard_start_xmit = dhd_start_xmit; @@ -1545,9 +1549,9 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ #ifdef CONFIG_WIRELESS_EXT -#if WIRELESS_EXT < 21 +#if WIRELESS_EXT < 19 net->get_wireless_stats = dhd_get_wireless_stats; -#endif /* WIRELESS_EXT < 21 */ +#endif /* WIRELESS_EXT < 19 */ #if WIRELESS_EXT > 12 net->wireless_handlers = (struct iw_handler_def *) &wl_iw_handler_def; #endif /* WIRELESS_EXT > 12 */ @@ -1571,19 +1575,6 @@ fail: return BCME_ERROR; } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) -#define KILL_PROC(pid, sig) \ -{ \ - struct task_struct *tsk; \ - tsk = find_task_by_vpid(pid); \ - send_sig(sig, tsk, 1); \ -} -#else -#define KILL_PROC(pid, sig) \ -{ \ - kill_proc(pid, sig, 1); \ -} -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ void dhd_detach(dhd_pub_t *dhdp) { @@ -1629,6 +1620,11 @@ dhd_detach(dhd_pub_t *dhdp) if (dhdp->prot) dhd_prot_detach(dhdp); +#ifdef CONFIG_WIRELESS_EXT + /* Attach and link in the iw */ + wl_iw_detach(); +#endif + free_netdev(ifp->net); MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); } @@ -1867,10 +1863,8 @@ void dhd_os_sdunlock_rxq(dhd_pub_t * pub) { } + #ifdef CONFIG_WIRELESS_EXT -#if WIRELESS_EXT < 21 -static -#endif /* WIRELESS_EXT < 21 */ struct iw_statistics * dhd_get_wireless_stats(struct net_device *dev) { @@ -1887,28 +1881,34 @@ dhd_get_wireless_stats(struct net_device *dev) #endif /* CONFIG_WIRELESS_EXT */ static int -iw_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, wl_event_msg_t *event, void **data_ptr) +dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, + wl_event_msg_t *event, void **data) { - int bcmerror; + int bcmerror = 0; ASSERT(dhd != NULL); - bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data_ptr); + bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data); if (bcmerror != BCME_OK) return (bcmerror); #ifdef CONFIG_WIRELESS_EXT ASSERT(dhd->iflist[*ifidx] != NULL); - wl_iw_event(dhd->iflist[*ifidx]->net, event, NULL); + wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); #endif /* CONFIG_WIRELESS_EXT */ + return (bcmerror); +} + +/* send up locally generated event */ +void +dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) +{ switch (ntoh32(event->event_type)) { default: break; } - - return (bcmerror); } static int diff --git a/src/dhd/sys/dhd_proto.h b/src/dhd/sys/dhd_proto.h index c3b394a..e76788f 100644 --- a/src/dhd/sys/dhd_proto.h +++ b/src/dhd/sys/dhd_proto.h @@ -6,27 +6,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_proto.h,v 1.2.82.1.4.1.24.1 2008/10/31 23:21:16 Exp $ + * $Id: dhd_proto.h,v 1.2.82.1.4.1.24.3 2009/03/10 19:11:47 Exp $ */ #ifndef _dhd_proto_h_ @@ -80,6 +78,8 @@ extern void dhd_prot_dstats(dhd_pub_t *dhdp); extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen); +extern void dhd_preinit_ioctls(dhd_pub_t *dhd); + /******************************** * For version-string expansion * diff --git a/src/dhd/sys/dhd_sdio.c b/src/dhd/sys/dhd_sdio.c index 6495944..73ae9cf 100644 --- a/src/dhd/sys/dhd_sdio.c +++ b/src/dhd/sys/dhd_sdio.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c,v 1.157.2.27.2.36.4.24 2009/01/16 02:39:00 Exp $ + * $Id: dhd_sdio.c,v 1.157.2.27.2.36.4.39 2009/03/24 22:37:18 Exp $ */ #include <typedefs.h> @@ -75,6 +73,7 @@ #endif /* defined(CONFIG_MACH_SANDGATE2G) */ #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ + #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ @@ -112,13 +111,14 @@ #if !ISPOWEROF2(MAX_HDR_READ) #error MAX_HDR_READ is not a power of 2! #endif + #define MAX_RX_DATASZ 2048 /* Maximum milliseconds to wait for F2 to come up */ #define DHD_WAIT_F2RDY 4000 /* Bump up limit on waiting for HT to account for first startup; - * if the image is doing a CRC calcuation before programming the PMU + * if the image is doing a CRC calculation before programming the PMU * for HT availability, it could take a couple hundred ms more, so * max out at a half second (500000us). */ @@ -218,6 +218,9 @@ typedef struct dhd_bus { uint32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ bool use_rxchain; /* If dhd should use PKT chains */ bool sleeping; /* Is SDIO bus sleeping? */ + bool rxflow_enable; /* Is the rx flow control mechanism enable */ + bool rxflow; /* Is rx flow control on */ + uint prev_rxlim_hit; /* Is the previous rx limit exceeded (per dpc schedule) */ bool alp_only; /* Don't use HT clock (ALP only) */ /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ bool usebufpool; @@ -289,7 +292,7 @@ uint dhd_txbound; uint dhd_rxbound; uint dhd_txminmax = DHD_TXMINMAX; -/* overrride the RAM size if possible */ +/* override the RAM size if possible */ #define DONGLE_MIN_MEMSIZE (128 *1024) int dhd_dongle_memsize; @@ -849,6 +852,8 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt) } else { PKTPUSH(osh, pkt, pad); frame = (uint8*)PKTDATA(osh, pkt); + + ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt)); bzero(frame, pad + SDPCM_HDRLEN); } } @@ -1155,10 +1160,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) uint retries = 0; bcmsdh_info_t *sdh = bus->sdh; uint8 doff = 0; - int ret = 0; + int ret = -1; int i; - uint16 pad; - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -1183,7 +1186,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) /* Round send length to next SDIO block */ if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { - pad = bus->blocksize - (len % bus->blocksize); + uint16 pad = bus->blocksize - (len % bus->blocksize); if ((pad <= bus->roundup) && (pad < bus->blocksize)) len += pad; } else if (len % DHD_SDALIGN) { @@ -1196,6 +1199,11 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) ASSERT(ISALIGNED((uintptr)frame, 2)); +#ifdef BCMLXSDMMC + /* Claim SD Host Controller and retain lock. */ + bcmsdh_claim_host_and_lock(sdh); +#endif /* BCMLXSDMMC */ + /* Need to lock here to protect txseq and SDIO tx calls */ dhd_os_sdlock(bus->dhd); @@ -1260,6 +1268,10 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) } dhd_os_sdunlock(bus->dhd); +#ifdef BCMLXSDMMC + /* Release SD Host Controller and unlock. */ + bcmsdh_release_host_and_unlock(bus->sdh); +#endif /* BCMLXSDMMC */ if (ret) bus->dhd->tx_ctlerrs++; @@ -1298,7 +1310,9 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) } else if (pending == TRUE) { DHD_CTL(("%s: cancelled\n", __FUNCTION__)); return -ERESTARTSYS; - } else DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); + } else { + DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); + } if (rxlen) bus->dhd->rx_ctlpkts++; @@ -1636,7 +1650,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch { int bcmerror = 0; int32 int_val = 0; - bool bool_val; + bool bool_val = 0; DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n", __FUNCTION__, actionid, name, params, plen, arg, len, val_size)); @@ -2070,6 +2084,10 @@ exit: } dhd_os_sdunlock(bus->dhd); + + if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE) + dhd_preinit_ioctls((dhd_pub_t *) bus->dhd); + return bcmerror; } @@ -2333,6 +2351,7 @@ void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) { osl_t *osh = bus->dhd->osh; + uint32 local_hostintmask; uint8 saveclk; uint retries; int err; @@ -2347,9 +2366,9 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) /* Enable clock for device interrupts */ dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - /* Disable and clear interrupts at the chip level also */ + /* Disable interrupts at the chip level also */ W_SDREG(0, &bus->regs->hostintmask, retries); - W_SDREG(bus->hostintmask, &bus->regs->intstatus, retries); + local_hostintmask = bus->hostintmask; bus->hostintmask = 0; /* Change our idea of bus state */ @@ -2370,6 +2389,9 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) bcmsdh_intr_disable(bus->sdh); bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); + /* Clear any pending interrupts now that F2 is disabled */ + W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); + /* Turn off the backplane clock (only) */ dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); @@ -2452,7 +2474,6 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) DHD_INFO(("%s: enable 0x%02x, ready 0x%02x\n", __FUNCTION__, enable, ready)); - /* If F2 successfully enabled, set core and enable interrupts */ if (ready == enable) { /* Make sure we're talking to the core. */ @@ -2709,7 +2730,7 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) break; } if (sublen % DHD_SDALIGN) { - DHD_ERROR(("%s: sublen %d not a multiple of %d\n", + DHD_GLOM(("%s: sublen %d not a multiple of %d\n", __FUNCTION__, sublen, DHD_SDALIGN)); usechain = FALSE; } @@ -3063,6 +3084,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */ uint8 *rxbuf; int ifidx = 0; + uint rxcount = 0; /* Total frames read */ #if defined(DHD_DEBUG) || defined(SDTEST) bool sdtest = FALSE; /* To limit message spew from test mode */ @@ -3607,20 +3629,20 @@ deliver: dhd_rx_frame(bus->dhd, ifidx, pkt, 1); dhd_os_sdlock(bus->dhd); } + rxcount = maxframes - rxleft; #ifdef DHD_DEBUG /* Message if we hit the limit */ if (!rxleft && !sdtest) DHD_ERROR(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes)); else #endif /* DHD_DEBUG */ - DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, (maxframes - rxleft))); - - /* Back off rxseq if awaiting rtx, upate rx_seq */ + DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount)); + /* Back off rxseq if awaiting rtx, update rx_seq */ if (bus->rxskip) rxseq--; bus->rx_seq = rxseq; - return (maxframes - rxleft); + return rxcount; } static uint32 @@ -3890,7 +3912,26 @@ clkwait: bool dhd_bus_dpc(struct dhd_bus *bus) { +#ifdef SDIO_ISR_THREAD + bool resched; + +#ifdef BCMLXSDMMC + /* Claim SD Host Controller and retain lock. */ + bcmsdh_claim_host_and_lock(bus->sdh); +#endif /* BCMLXSDMMC */ + + /* Call the DPC directly. */ + DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); + resched = dhdsdio_dpc(bus); + +#ifdef BCMLXSDMMC + /* Release SD Host Controller and unlock. */ + bcmsdh_release_host_and_unlock(bus->sdh); +#endif /* BCMLXSDMMC */ + return resched; +#else return dhdsdio_dpc(bus); +#endif /* SDIO_ISR_THREAD */ } void @@ -3922,8 +3963,13 @@ dhdsdio_isr(void *arg) bcmsdh_intr_disable(sdh); bus->intdis = TRUE; +#if defined(SDIO_ISR_THREAD) + DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); + while (dhdsdio_dpc(bus)); +#else bus->dpc_sched = TRUE; dhd_sched_dpc(bus->dhd); +#endif } @@ -4178,10 +4224,18 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) bus = dhdp->bus; + if (bus->dhd->dongle_reset) + return FALSE; + /* Ignore the timer if simulating bus down */ if (bus->sleeping) return FALSE; +#ifdef BCMLXSDMMC + /* Claim SD Host Controller and retain lock. */ + bcmsdh_claim_host_and_lock(bus->sdh); +#endif /* BCMLXSDMMC */ + dhd_os_sdlock(bus->dhd); /* Poll period: check device if appropriate. */ @@ -4242,6 +4296,11 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) dhd_os_sdunlock(bus->dhd); +#ifdef BCMLXSDMMC + /* Release SD Host Controller and unlock. */ + bcmsdh_release_host_and_unlock(bus->sdh); +#endif /* BCMLXSDMMC */ + return bus->ipend; } @@ -4298,7 +4357,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, /* Init global variables at run-time, not as part of the declaration. * This is required to support init/de-init of the driver. Initialization * of globals as part of the declaration results in non-deterministic - * behaviour since the value of the globals may be different on the + * behavior since the value of the globals may be different on the * first time that the driver is initialized vs subsequent initializations. */ dhd_txbound = DHD_TXBOUND; @@ -4445,7 +4504,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, #ifdef DHD_DEBUG printf("F1 signature read @0x18000000=0x%4x\n", bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4)); -#endif +#endif /* DHD_DEBUG */ /* Force PLL off until si_attach() programs PLL control regs */ @@ -4518,9 +4577,6 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, goto fail; } - /* Let the layers below dhd know the chipid and chiprev for - * controlling sw WAR's for hw PR's - */ bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { @@ -4618,6 +4674,8 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) bus->dhd->busstate = DHD_BUS_DOWN; bus->sleeping = FALSE; + bus->rxflow = FALSE; + bus->prev_rxlim_hit = 0; /* Done with backplane-dependent accesses, can drop clock... */ @@ -4680,10 +4738,13 @@ bool dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, char *firmware_path, char *nvram_path) { + bool ret; bus->firmware_path = firmware_path; bus->nvram_path = nvram_path; - return dhdsdio_download_firmware(bus, osh, bus->sdh); + ret = dhdsdio_download_firmware(bus, osh, bus->sdh); + + return ret; } static bool @@ -4717,6 +4778,9 @@ dhdsdio_release(dhd_bus_t *bus, osl_t *osh) dhdsdio_release_dongle(bus, osh); + /* De-register interrupt handler */ + bcmsdh_intr_dereg(bus->sdh); + MFREE(osh, bus, sizeof(dhd_bus_t)); } @@ -4931,6 +4995,19 @@ process_nvram_vars(char *varbuf, uint len) return buf_len; } +/* + EXAMPLE: nvram_array + nvram_arry format: + name=value + Use carriage return at the end of each assignment, and an empty string with + carriage return at the end of array. + + For example: + unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"}; + Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx. + + Search "EXAMPLE: nvram_array" to see how the array is activated. +*/ void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params) @@ -5061,6 +5138,10 @@ _dhdsdio_download_firmware(struct dhd_bus *bus) goto err; } + /* EXAMPLE: nvram_array */ + /* If a valid nvram_arry is specified as above, it can be passed down to dongle */ + /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */ + /* External nvram takes precedence if specified */ if (dhdsdio_download_nvram(bus)) { DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__)); @@ -5114,3 +5195,9 @@ dhd_bus_txq(struct dhd_bus *bus) { return &bus->txq; } + +uint +dhd_bus_hdrlen(struct dhd_bus *bus) +{ + return SDPCM_HDRLEN; +} diff --git a/src/include/bcmdefs.h b/src/include/bcmdefs.h index 5ea3f7a..5c9dde9 100644 --- a/src/include/bcmdefs.h +++ b/src/include/bcmdefs.h @@ -3,25 +3,23 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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: bcmdefs.h,v 13.38.4.10.2.7 2008/07/01 00:53:19 Exp $ */ diff --git a/src/include/bcmsdbus.h b/src/include/bcmsdbus.h index 4c6ff9b..c649ba3 100644 --- a/src/include/bcmsdbus.h +++ b/src/include/bcmsdbus.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: bcmsdbus.h,v 13.11.14.2.16.1 2008/12/17 05:02:20 Exp $ + * $Id: bcmsdbus.h,v 13.11.14.2.16.2 2009/03/19 04:07:42 Exp $ */ /* @@ -79,6 +79,11 @@ 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/src/include/bcmsdh.h b/src/include/bcmsdh.h index 4165d71..c8f04b4 100644 --- a/src/include/bcmsdh.h +++ b/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.16.2 2008/12/17 04:33:18 Exp $ + * $Id: bcmsdh.h,v 13.35.14.7.16.3 2009/03/19 04:07:42 Exp $ */ #ifndef _bcmsdh_h_ @@ -69,6 +69,11 @@ extern int bcmsdh_intr_dereg(void *sdh); extern bool bcmsdh_intr_pending(void *sdh); #endif +#ifdef BCMLXSDMMC +extern int bcmsdh_claim_host_and_lock(void *sdh); +extern int bcmsdh_release_host_and_unlock(void *sdh); +#endif /* BCMLXSDMMC */ + /* Register a callback to be called if and when bcmsdh detects * device removal. No-op in the case of non-removable/hardwired devices. */ diff --git a/src/include/bcmsdh_sdmmc.h b/src/include/bcmsdh_sdmmc.h index 2189239..e900971 100644 --- a/src/include/bcmsdh_sdmmc.h +++ b/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.2 2008/09/03 00:22:37 Exp $ + * $Id: bcmsdh_sdmmc.h,v 13.1.2.2.6.1 2009/03/19 04:07:42 Exp $ */ #ifndef __BCMSDH_SDMMC_H__ @@ -116,6 +116,7 @@ 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[3]; -}BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; + uint32 host_claimed; +} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; #endif /* __BCMSDH_SDMMC_H__ */ diff --git a/src/include/epivers.h b/src/include/epivers.h index b4a101e..1298982 100644 --- a/src/include/epivers.h +++ b/src/include/epivers.h @@ -1,25 +1,23 @@ /* * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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 $ * @@ -33,18 +31,18 @@ #define EPI_MINOR_VERSION 217 -#define EPI_RC_NUMBER 12 +#define EPI_RC_NUMBER 24 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 217, 12, 0 +#define EPI_VERSION 4, 217, 24, 0 -#define EPI_VERSION_NUM 0x04d90c00 +#define EPI_VERSION_NUM 0x04d91800 -#define EPI_VERSION_STR "4.217.12.0" -#define EPI_ROUTER_VERSION_STR "4.217.12.0" +#define EPI_VERSION_STR "4.217.24.0" +#define EPI_ROUTER_VERSION_STR "4.217.24.0" #endif diff --git a/src/include/linuxver.h b/src/include/linuxver.h index bea6416..9883e6c 100644 --- a/src/include/linuxver.h +++ b/src/include/linuxver.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linuxver.h,v 13.38.8.1.22.1 2009/01/18 00:25:30 Exp $ + * $Id: linuxver.h,v 13.38.8.1.22.2 2009/03/19 04:05:38 Exp $ */ @@ -430,7 +430,7 @@ pci_restore_state(struct pci_dev *dev, u32 *buffer) { \ struct task_struct *tsk; \ tsk = find_task_by_vpid(pid); \ - send_sig(sig, tsk, 1); \ + if (tsk) send_sig(sig, tsk, 1); \ } #else #define KILL_PROC(pid, sig) \ diff --git a/src/include/proto/802.11.h b/src/include/proto/802.11.h index 270601f..4d3562b 100644 --- a/src/include/proto/802.11.h +++ b/src/include/proto/802.11.h @@ -1,29 +1,27 @@ /* * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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. * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h,v 9.219.4.1.4.5.20.3 2008/12/07 21:15:40 Exp $ + * $Id: 802.11.h,v 9.219.4.1.4.5.20.6 2009/03/05 21:13:45 Exp $ */ @@ -1008,6 +1006,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_management_notification { #define DOT11_ACTION_CAT_BLOCKACK 3 #define DOT11_ACTION_CAT_PUBLIC 4 #define DOT11_ACTION_CAT_HT 7 +#define DOT11_ACTION_CAT_VS 127 #define DOT11_ACTION_NOTIFICATION 0x11 #define DOT11_ACTION_ID_M_REQ 0 @@ -1364,6 +1363,7 @@ typedef struct vndr_ie vndr_ie_t; #define VNDR_IE_MAX_LEN 256 + #define WPA_VERSION 1 #define WPA_OUI "\x00\x50\xF2" diff --git a/src/include/proto/bcmevent.h b/src/include/proto/bcmevent.h index 054b797..13d8210 100644 --- a/src/include/proto/bcmevent.h +++ b/src/include/proto/bcmevent.h @@ -3,30 +3,28 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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. * * * Dependencies: proto/bcmeth.h * - * $Id: bcmevent.h,v 9.34.4.1.2.3.2.4 2008/12/11 00:12:47 Exp $ + * $Id: bcmevent.h,v 9.34.4.1.2.3.2.5 2009/02/20 18:31:41 Exp $ * */ @@ -149,6 +147,7 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event { #define WLC_E_STATUS_SUPPRESS 12 #define WLC_E_STATUS_NOCHANS 13 #define WLC_E_STATUS_CCXFASTRM 14 +#define WLC_E_STATUS_CS_ABORT 15 #define WLC_E_REASON_INITIAL_ASSOC 0 diff --git a/src/include/proto/eapol.h b/src/include/proto/eapol.h index 6226191..bbc4172 100644 --- a/src/include/proto/eapol.h +++ b/src/include/proto/eapol.h @@ -7,7 +7,7 @@ * * Copyright (C) 2002 Broadcom Corporation * - * $Id: eapol.h,v 9.18.260.1.2.1.20.3 2008/12/31 00:37:15 Exp $ + * $Id: eapol.h,v 9.18.260.1.2.1.20.4 2009/02/03 01:26:12 Exp $ */ #ifndef _eapol_h_ @@ -95,7 +95,7 @@ typedef BWL_PRE_PACKED_STRUCT struct { unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ - unsigned char rsc[DOT11_WPA_KEY_RSC_LEN]; /* Key RSC */ + unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ unsigned short data_len; /* Key Data Length */ diff --git a/src/include/sbchipc.h b/src/include/sbchipc.h index 48a076b..f6456b9 100644 --- a/src/include/sbchipc.h +++ b/src/include/sbchipc.h @@ -5,29 +5,27 @@ * 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.7 2008/10/08 21:58:33 Exp $ + * $Id: sbchipc.h,v 13.103.2.5.4.7.4.1 2009/01/21 23:56:57 Exp $ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS 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. */ @@ -707,6 +705,9 @@ typedef volatile struct { #define PST_INTPEND 0x0040 #define PST_SBCLKST 0x0030 +#define PST_SBCLKST_ILP 0x0010 +#define PST_SBCLKST_ALP 0x0020 +#define PST_SBCLKST_HT 0x0030 #define PST_ALPAVAIL 0x0008 #define PST_HTAVAIL 0x0004 #define PST_RESINIT 0x0003 diff --git a/src/include/wlioctl.h b/src/include/wlioctl.h index 3a7e4a0..9f9dd04 100644 --- a/src/include/wlioctl.h +++ b/src/include/wlioctl.h @@ -6,27 +6,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h,v 1.601.4.15.2.15.2.6 2009/01/13 01:12:41 Exp $ + * $Id: wlioctl.h,v 1.601.4.15.2.15.2.10 2009/03/10 18:49:43 Exp $ */ @@ -42,6 +40,17 @@ +#ifdef WIFI_ACT_FRAME +typedef struct wl_action_frame { + struct ether_addr da; + uint16 len; + uint8 data[1040]; +} wl_action_frame_t; + +#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) + +#endif + #define BWL_DEFAULT_PACKING @@ -112,6 +121,39 @@ typedef struct wlc_ssid { #define WL_BSSTYPE_INDEP 0 #define WL_BSSTYPE_ANY 2 +typedef struct wl_scan_params { + wlc_ssid_t ssid; + struct ether_addr bssid; + int8 bss_type; + int8 scan_type; + int32 nprobes; + int32 active_time; + int32 passive_time; + int32 home_time; + int32 channel_num; + uint16 channel_list[1]; +} wl_scan_params_t; + +#define WL_SCAN_PARAMS_FIXED_SIZE 64 + + +#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff +#define WL_SCAN_PARAMS_NSSID_SHIFT 16 + +#define WL_SCAN_ACTION_START 1 +#define WL_SCAN_ACTION_CONTINUE 2 + +#define ISCAN_REQ_VERSION 1 + + +typedef struct wl_iscan_params { + uint32 version; + uint16 action; + uint16 scan_duration; + wl_scan_params_t params; +} wl_iscan_params_t; + +#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) typedef struct wl_scan_results { uint32 buflen; @@ -152,6 +194,25 @@ typedef struct wl_uint32_list { } wl_uint32_list_t; +typedef struct wl_assoc_params { + struct ether_addr bssid; + int32 chanspec_num; + chanspec_t chanspec_list[1]; +} wl_assoc_params_t; +#define WL_ASSOC_PARAMS_FIXED_SIZE (sizeof(wl_assoc_params_t) - sizeof(chanspec_t)) + + +typedef wl_assoc_params_t wl_reassoc_params_t; +#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE + + +typedef struct wl_join_params { + wlc_ssid_t ssid; + wl_assoc_params_t params; +} wl_join_params_t; +#define WL_JOIN_PARAMS_FIXED_SIZE (sizeof(wl_join_params_t) - sizeof(chanspec_t)) + + typedef enum sup_auth_status { WLC_SUP_DISCONNECTED = 0, @@ -1156,8 +1217,7 @@ typedef struct { enum { PFN_LIST_ORDER, - PFN_RSSI, - PFN_AUTO_CONNECT + PFN_RSSI }; enum { diff --git a/src/wl/sys/wl_iw.c b/src/wl/sys/wl_iw.c index beffa24..51d5289 100644 --- a/src/wl/sys/wl_iw.c +++ b/src/wl/sys/wl_iw.c @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.51.4.9.2.8.6.3 2009/01/18 00:30:44 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.8.6.33 2009/03/12 17:56:57 Exp $ */ @@ -38,6 +36,7 @@ #include <linux/if_arp.h> #include <asm/uaccess.h> +#include <dhdioctl.h> typedef void wlc_info_t; typedef void wl_info_t; @@ -52,8 +51,20 @@ typedef const struct si_pub si_t; #include <wl_iw.h> +#include <linux/rtnetlink.h> + +#define WL_IW_USE_ISCAN 1 + +#define WL_IW_IOCTL_CALL(func_call) \ + do { \ + func_call; \ + } while (0) + extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, char* stringBuf, uint buflen); +static int dev_dhd_ioctl(struct net_device *dev, int cmd, void *arg, int len); +extern void sdioh_start(int); +extern void sdioh_stop(void); uint wl_msg_level = WL_ERROR_VAL; @@ -88,6 +99,79 @@ extern int dhd_wait_pend8021x(struct net_device *dev); #define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) #endif +static void *g_scan = NULL; +#define G_SCAN_RESULTS 8*1024 +#define WE_ADD_EVENT_FIX 0x80 +static uint g_scan_specified_ssid; + + +static wlc_ssid_t g_ssid; + + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define DAEMONIZE(a) daemonize(a); \ + allow_signal(SIGKILL); \ + allow_signal(SIGTERM); +#else +#define RAISE_RX_SOFTIRQ() \ + cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) +#define DAEMONIZE(a) daemonize(); \ + do { if (a) \ + strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ + } while (0); +#endif + +#if defined(WL_IW_USE_ISCAN) + +#define ISCAN_STATE_IDLE 0 +#define ISCAN_STATE_SCANING 1 + + +#define WLC_IW_ISCAN_MAXLEN 2048 +typedef struct iscan_buf { + struct iscan_buf * next; + char iscan_buf[WLC_IW_ISCAN_MAXLEN]; +} iscan_buf_t; + +typedef struct iscan_info { + struct net_device *dev; + struct timer_list timer; + uint32 timer_ms; + uint32 timer_on; + int iscan_state; + iscan_buf_t * list_hdr; + iscan_buf_t * list_cur; + + + long sysioc_pid; + struct semaphore sysioc_sem; + struct completion sysioc_exited; + + uint32 scan_flag; + + char ioctlbuf[WLC_IOCTL_SMLEN]; +} iscan_info_t; +iscan_info_t *g_iscan = NULL; +static void wl_iw_timerfunc(ulong data); +static void wl_iw_event_mask(struct net_device *dev, int set); +static int +wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); +#endif +static int +wl_iw_set_scan( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +); +static int +wl_iw_get_scan( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra +); + static void swap_key_from_BE( wl_wsec_key_t *key ) @@ -146,6 +230,39 @@ dev_wlc_ioctl( return ret; } +static int +dev_dhd_ioctl( + struct net_device *dev, + int cmd, + void *arg, + int len +) +{ + struct ifreq ifr; + dhd_ioctl_t ioc; + mm_segment_t fs; + int ret; + + memset(&ioc, 0, sizeof(ioc)); + ioc.cmd = cmd; + ioc.buf = arg; + ioc.len = len; + ioc.driver = DHD_IOCTL_MAGIC; + + strcpy(ifr.ifr_name, dev->name); + ifr.ifr_data = (caddr_t) &ioc; + + + dev_open(dev); + + fs = get_fs(); + set_fs(get_ds()); + ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); + set_fs(fs); + + return ret; +} + static int @@ -164,6 +281,43 @@ dev_wlc_intvar_set( return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len)); } +#if defined(WL_IW_USE_ISCAN) +static int +dev_iw_iovar_setbuf( + struct net_device *dev, + char *iovar, + void *param, + int paramlen, + void *bufptr, + int buflen) +{ + int iolen; + + iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); + ASSERT(iolen); + + return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); +} + +static int +dev_iw_iovar_getbuf( + struct net_device *dev, + char *iovar, + void *param, + int paramlen, + void *bufptr, + int buflen) +{ + int iolen; + + iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); + ASSERT(iolen); + + return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen)); +} +#endif + + #if WIRELESS_EXT > 17 static int dev_wlc_bufvar_set( @@ -229,6 +383,300 @@ dev_wlc_intvar_get( } +#if WIRELESS_EXT > 12 +static int +wl_iw_set_active_scan( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int as = 0; + int error = 0; + char *p = extra; + +#if defined(WL_IW_USE_ISCAN) + if (g_iscan->iscan_state == ISCAN_STATE_IDLE) +#endif + error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as)); +#if defined(WL_IW_USE_ISCAN) + else + g_iscan->scan_flag = as; +#endif + p += snprintf(p, MAX_WX_STRING, "OK"); + + wrqu->data.length = p - extra + 1; + return error; +} + +static int +wl_iw_set_passive_scan( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int ps = 1; + int error = 0; + char *p = extra; + +#if defined(WL_IW_USE_ISCAN) + if (g_iscan->iscan_state == ISCAN_STATE_IDLE) { +#endif + + + if (g_scan_specified_ssid == 0) { + error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps)); + } +#if defined(WL_IW_USE_ISCAN) + } + else + g_iscan->scan_flag = ps; +#endif + + p += snprintf(p, MAX_WX_STRING, "OK"); + + wrqu->data.length = p - extra + 1; + return error; +} + +static int +wl_iw_get_macaddr( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int error; + char buf[128]; + struct ether_addr *id; + char *p = extra; + + + strcpy(buf, "cur_etheraddr"); + error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf)); + id = (struct ether_addr *) buf; + p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", + id->octet[0], id->octet[1], id->octet[2], + id->octet[3], id->octet[4], id->octet[5]); + wrqu->data.length = p - extra + 1; + + return error; +} + + +int +wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) +{ + int i, c; + char *p = ssid_buf; + + if (ssid_len > 32) ssid_len = 32; + + for (i = 0; i < ssid_len; i++) { + c = (int)ssid[i]; + if (c == '\\') { + *p++ = '\\'; + *p++ = '\\'; + } else if (isprint((uchar)c)) { + *p++ = (char)c; + } else { + p += sprintf(p, "\\x%02X", c); + } + } + *p = '\0'; + + return p - ssid_buf; +} + +static int +wl_iw_get_link_speed( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int link_speed; + int error; + char *p = extra; + + error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed)); + + link_speed *= 500000; + + p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000); + + wrqu->data.length = p - extra + 1; + + return error; +} + +static int +wl_iw_get_rssi( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int rssi; + int error; + wlc_ssid_t ssid; + char *p = extra; + char ssidbuf[SSID_FMT_BUF_LEN]; + scb_val_t scb_val; + + scb_val.val = 0; + error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); + + rssi = dtoh32(scb_val.val); + error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)); + + ssid.SSID_len = dtoh32(ssid.SSID_len); + + if (!ssid.SSID_len) + return 0; + + wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len)); + p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi); + wrqu->data.length = p - extra + 1; + + return error; +} + +struct wl_ctrl { + struct timer_list *timer; + struct net_device *dev; + long sysioc_pid; + struct semaphore sysioc_sem; + struct completion sysioc_exited; +}; + +int g_onoff = 0; + +static int +_wl_control_sysioc_thread(void *data) +{ + struct wl_ctrl *wl_ctl = (struct wl_ctrl *)data; + char buffer[20]; + int len, onoff = 1; + + DAEMONIZE("wlcontrol_sysioc"); + + WL_TRACE(("%s Entered\n", __FUNCTION__)); + + while (down_interruptible(&wl_ctl->sysioc_sem) == 0) { + + WL_TRACE(("%s Turning off wifi dev = 0x%x\n", __FUNCTION__, + (unsigned int)wl_ctl->dev)); + + len = strlen("devreset") + 1; + strcpy(buffer, "devreset"); + memcpy(&buffer[len], &onoff, sizeof(onoff)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + + dev_dhd_ioctl(wl_ctl->dev, DHD_SET_VAR, buffer, len + sizeof(onoff)); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif + + + + + + + + g_onoff = 1; + + break; + } + WL_TRACE(("%s Exited\n", __FUNCTION__)); + + complete_and_exit(&wl_ctl->sysioc_exited, 0); + KILL_PROC(wl_ctl->sysioc_pid, SIGTERM); +} + +static void +wl_iw_stop_timerfunc(ulong data) +{ + struct wl_ctrl * wl_ctl = (struct wl_ctrl *)data; + + WL_TRACE(("%s\n", __FUNCTION__)); + + del_timer(wl_ctl->timer); + + up(&wl_ctl->sysioc_sem); +} + +static int +wl_iw_control_wl( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra, + int onoff +) +{ + char buffer[20]; + static struct timer_list timer; + int len, ret = 0; + static struct wl_ctrl wl_ctl; + + WL_TRACE(("%s -- onoff = %d, dev = 0x%x\n", __FUNCTION__, onoff, (unsigned int)dev)); + + if (onoff) + { + + + wl_ctl.timer = &timer; + wl_ctl.dev = dev; + sema_init(&wl_ctl.sysioc_sem, 0); + init_completion(&wl_ctl.sysioc_exited); + + + wl_ctl.sysioc_pid = kernel_thread(_wl_control_sysioc_thread, &wl_ctl, 0); + + if (wl_ctl.sysioc_pid < 0) + return -ENOMEM; + + timer.data = (ulong)&wl_ctl; + timer.function = wl_iw_stop_timerfunc; + init_timer(&timer); + timer.expires = jiffies + 2000 * HZ / 1000; + add_timer(&timer); + } + else + { + + + + + + + + len = strlen("devreset") + 1; + strcpy(buffer, "devreset"); + memcpy(&buffer[len], &onoff, sizeof(onoff)); + + ret = dev_dhd_ioctl(dev, DHD_SET_VAR, buffer, len + sizeof(onoff)); + + + + + } + + return ret; +} +#endif + #if WIRELESS_EXT < 13 struct iw_request_info { @@ -628,6 +1076,7 @@ wl_iw_set_wap( ) { int error = -EINVAL; + wl_join_params_t join_params; WL_TRACE(("%s: SIOCSIWAP\n", dev->name)); @@ -644,13 +1093,22 @@ wl_iw_set_wap( dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); return 0; } + + - - if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, awrq->sa_data, ETHER_ADDR_LEN))) { + memset(&join_params, 0, sizeof(join_params)); + + memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len); + join_params.ssid.SSID_len = htod32(g_ssid.SSID_len); + memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN); + + if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params)))) { WL_ERROR(("Invalid ioctl data.\n")); return error; } + + memset(&g_ssid, 0, sizeof(g_ssid)); return 0; } @@ -728,6 +1186,7 @@ wl_iw_get_aplist( struct iw_quality qual[IW_MAX_AP]; wl_bss_info_t *bi = NULL; int error, i; + uint buflen = dwrq->length; WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); @@ -735,12 +1194,12 @@ wl_iw_get_aplist( return -EINVAL; - list = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); + list = kmalloc(buflen, GFP_KERNEL); if (!list) return -ENOMEM; - memset(list, 0, WLC_IOCTL_MAXLEN); - list->buflen = htod32(WLC_IOCTL_MAXLEN); - if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, WLC_IOCTL_MAXLEN))) { + memset(list, 0, buflen); + list->buflen = htod32(buflen); + if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { WL_ERROR(("%d: Scan results error %d\n", __LINE__, error)); kfree(list); return error; @@ -753,7 +1212,7 @@ wl_iw_get_aplist( for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + - WLC_IOCTL_MAXLEN)); + buflen)); if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) @@ -787,12 +1246,298 @@ wl_iw_get_aplist( return 0; } -#if WIRELESS_EXT > 13 +#ifdef WL_IW_USE_ISCAN +static int +wl_iw_iscan_get_aplist( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra +) +{ + wl_scan_results_t *list; + iscan_buf_t * buf; + iscan_info_t *iscan = g_iscan; + + struct sockaddr *addr = (struct sockaddr *) extra; + struct iw_quality qual[IW_MAX_AP]; + wl_bss_info_t *bi = NULL; + int i; + + WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); + + if (!extra) + return -EINVAL; + + if ((!iscan) || (iscan->sysioc_pid < 0)) { + return wl_iw_get_aplist(dev, info, dwrq, extra); + } + + buf = iscan->list_hdr; + + while (buf) { + list = &((wl_iscan_results_t*)buf->iscan_buf)->results; + ASSERT(list->version == WL_BSS_INFO_VERSION); + + bi = NULL; + for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { + bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) + : list->bss_info; + ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + + WLC_IW_ISCAN_MAXLEN)); + + + if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) + continue; + + + memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); + addr[dwrq->length].sa_family = ARPHRD_ETHER; + qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); + qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); + qual[dwrq->length].noise = 0x100 + bi->phy_noise; + + +#if WIRELESS_EXT > 18 + qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; +#else + qual[dwrq->length].updated = 7; +#endif + + dwrq->length++; + } + buf = buf->next; + } + if (dwrq->length) { + memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); + + dwrq->flags = 1; + } + + return 0; +} + +static int +wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) +{ + int err = 0; + + memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); + params->bss_type = DOT11_BSSTYPE_ANY; + params->scan_type = -1; + params->nprobes = -1; + params->active_time = -1; + params->passive_time = -1; + params->home_time = -1; + params->channel_num = 0; + + params->nprobes = htod32(params->nprobes); + params->active_time = htod32(params->active_time); + params->passive_time = htod32(params->passive_time); + params->home_time = htod32(params->home_time); + if (ssid && ssid->SSID_len) + memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t)); + + return err; +} + +static int +wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) +{ + int params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); + wl_iscan_params_t *params; + int err = 0; + + if (ssid && ssid->SSID_len) { + params_size += sizeof(wlc_ssid_t); + } + params = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); + if (params == NULL) { + return -ENOMEM; + } + memset(params, 0, params_size); + ASSERT(params_size < WLC_IOCTL_SMLEN); + + err = wl_iw_iscan_prep(¶ms->params, ssid); + + if (!err) { + params->version = htod32(ISCAN_REQ_VERSION); + params->action = htod16(action); + params->scan_duration = htod16(0); + + + (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", params, params_size, + iscan->ioctlbuf, WLC_IOCTL_SMLEN); + } + + kfree(params); + return err; +} + +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); + } +} +static void wl_iw_event_mask(struct net_device *dev, int set) +{ + char eventmask[WL_EVENTING_MASK_LEN]; + char iovbuf[WL_EVENTING_MASK_LEN + 12]; + + dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf)); + bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); + if (set) + setbit(eventmask, WLC_E_SCAN_COMPLETE); + else + clrbit(eventmask, WLC_E_SCAN_COMPLETE); + dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, + iovbuf, sizeof(iovbuf)); + +} + +static uint32 +wl_iw_iscan_get(iscan_info_t *iscan) +{ + iscan_buf_t * buf; + iscan_buf_t * ptr; + wl_iscan_results_t * list_buf; + wl_iscan_results_t list; + wl_scan_results_t *results; + uint32 status; + + + if (iscan->list_cur) { + buf = iscan->list_cur; + iscan->list_cur = buf->next; + } + else { + buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL); + if (!buf) + return WL_SCAN_RESULTS_ABORTED; + buf->next = NULL; + if (!iscan->list_hdr) + iscan->list_hdr = buf; + else { + ptr = iscan->list_hdr; + while (ptr->next) { + ptr = ptr->next; + } + ptr->next = buf; + } + } + memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); + list_buf = (wl_iscan_results_t*)buf->iscan_buf; + results = &list_buf->results; + results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; + results->version = 0; + results->count = 0; + + memset(&list, 0, sizeof(list)); + list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); + (void) dev_iw_iovar_getbuf( + iscan->dev, + "iscanresults", + &list, + WL_ISCAN_RESULTS_FIXED_SIZE, + buf->iscan_buf, + WLC_IW_ISCAN_MAXLEN); + results->buflen = dtoh32(results->buflen); + results->version = dtoh32(results->version); + results->count = dtoh32(results->count); + WL_TRACE(("results->count = %d\n", results->count)); + + WL_TRACE(("results->buflen = %d\n", results->buflen)); + status = dtoh32(list_buf->status); + return status; +} + +static int +_iscan_sysioc_thread(void *data) +{ + uint32 status; + iscan_info_t *iscan = (iscan_info_t *)data; + + DAEMONIZE("iscan_sysioc"); + + status = WL_SCAN_RESULTS_PARTIAL; + while (down_interruptible(&iscan->sysioc_sem) == 0) { + if (iscan->timer_on) { + del_timer(&iscan->timer); + iscan->timer_on = 0; + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + status = wl_iw_iscan_get(iscan); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif + + switch (status) { + case WL_SCAN_RESULTS_PARTIAL: + WL_TRACE(("iscanresults incomplete\n")); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + + wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif + + iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; + add_timer(&iscan->timer); + iscan->timer_on = 1; + break; + case WL_SCAN_RESULTS_SUCCESS: + WL_TRACE(("iscanresults complete\n")); + iscan->iscan_state = ISCAN_STATE_IDLE; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + wl_iw_event_mask(iscan->dev, 0); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif + break; + case WL_SCAN_RESULTS_PENDING: + WL_TRACE(("iscanresults pending\n")); + + iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; + add_timer(&iscan->timer); + iscan->timer_on = 1; + break; + case WL_SCAN_RESULTS_ABORTED: + WL_TRACE(("iscanresults aborted\n")); + iscan->iscan_state = ISCAN_STATE_IDLE; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_lock(); +#endif + wl_iw_event_mask(iscan->dev, 0); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) + rtnl_unlock(); +#endif + break; + default: + WL_TRACE(("iscanresults returned unknown status %d\n", status)); + break; + } + } + complete_and_exit(&iscan->sysioc_exited, 0); +} +#endif + static int wl_iw_set_scan( struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, + union iwreq_data *wrqu, char *extra ) { @@ -801,14 +1546,83 @@ wl_iw_set_scan( WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name)); - ssid.SSID_len = 0; + memset(&ssid, 0, sizeof(ssid)); + g_scan_specified_ssid = 0; +#if WIRELESS_EXT > 17 + + if (wrqu->data.length == sizeof(struct iw_scan_req)) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + struct iw_scan_req *req = (struct iw_scan_req *)extra; + ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); + memcpy(ssid.SSID, req->essid, ssid.SSID_len); + ssid.SSID_len = htod32(ssid.SSID_len); + g_scan_specified_ssid = 1; + WL_TRACE(("Specific scan ssid=%s len=%d\n", ssid.SSID, ssid.SSID_len)); + } + } +#endif (void) dev_wlc_ioctl(dev, WLC_SCAN, &ssid, sizeof(ssid)); return 0; } +#ifdef WL_IW_USE_ISCAN +static int +wl_iw_iscan_set_scan( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + wlc_ssid_t ssid; + iscan_info_t *iscan = g_iscan; + + WL_TRACE(("%s: SIOCSIWSCAN\n", dev->name)); + + + if ((!iscan) || (iscan->sysioc_pid < 0)) { + return wl_iw_set_scan(dev, info, wrqu, extra); + } + if (iscan->iscan_state == ISCAN_STATE_SCANING) { + return 0; + } + + + memset(&ssid, 0, sizeof(ssid)); + + g_scan_specified_ssid = 0; +#if WIRELESS_EXT > 17 + + if (wrqu->data.length == sizeof(struct iw_scan_req)) { + if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { + int as = 0; + struct iw_scan_req *req = (struct iw_scan_req *)extra; + ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); + 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)); + return wl_iw_set_scan(dev, info, wrqu, extra); + } + } +#endif + + 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)); + wl_iw_event_mask(dev, 1); + wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); + iscan->timer.expires = jiffies + iscan->timer_ms*HZ/1000; + add_timer(&iscan->timer); + iscan->timer_on = 1; + + return 0; +} +#endif + #if WIRELESS_EXT > 17 static bool ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len) @@ -855,6 +1669,137 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) } #endif +static uint +wl_iw_get_scan_prep( + wl_scan_results_t *list, + struct iw_request_info *info, + char *extra, + __u16 max_size) +{ + int i, j; + 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; + + ASSERT(list); + + + + for (i = 0; i < list->count && i < IW_MAX_AP; i++) + { + ASSERT(list->version == WL_BSS_INFO_VERSION); + + bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; + + + iwe.cmd = SIOCGIWAP; + iwe.u.ap_addr.sa_family = ARPHRD_ETHER; + memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); + + iwe.u.data.length = dtoh32(bi->SSID_len); + iwe.cmd = SIOCGIWESSID; + iwe.u.data.flags = 1; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); + + + if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { + iwe.cmd = SIOCGIWMODE; + if (dtoh16(bi->capability) & DOT11_CAP_ESS) + iwe.u.mode = IW_MODE_INFRA; + else + iwe.u.mode = IW_MODE_ADHOC; + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); + } + + + iwe.cmd = SIOCGIWFREQ; + iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), + CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? + WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); + iwe.u.freq.e = 6; + event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); + + + iwe.cmd = IWEVQUAL; + iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); + iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); + 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; + } + } + + 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) + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; + else + iwe.u.data.flags = IW_ENCODE_DISABLED; + iwe.u.data.length = 0; + event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); + + + if (bi->rateset.count) { + value = event + IW_EV_LCP_LEN; + iwe.cmd = SIOCGIWRATE; + + iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; + for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { + iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; + value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, + IW_EV_PARAM_LEN); + } + event = value; + } + } + + if ((ret = (event - extra)) < 0) { + WL_ERROR(("==> Wrong size\n")); + ret = 0; + } + WL_TRACE(("%s: size=%d bytes prepared\n", __FUNCTION__, event - extra)); + return ret; + +} + static int wl_iw_get_scan( struct net_device *dev, @@ -864,16 +1809,24 @@ wl_iw_get_scan( ) { channel_info_t ci; - wl_scan_results_t *list; - struct iw_event iwe; - wl_bss_info_t *bi = NULL; - int error, i, j; - char *event = extra, *end = extra + IW_SCAN_MAX_DATA, *value; + wl_scan_results_t *list_merge; + wl_scan_results_t *list = (wl_scan_results_t *) g_scan; + int error; + uint buflen_from_user = dwrq->length; + uint len = G_SCAN_RESULTS; + __u16 len_ret; +#if defined(WL_IW_USE_ISCAN) + iscan_info_t *iscan = g_iscan; + iscan_buf_t * p_buf; +#endif - WL_TRACE(("%s: SIOCGIWSCAN\n", dev->name)); + WL_TRACE(("%s: wl_iw_get_scan\n", dev->name)); + WL_TRACE(("%d: buflen_from_user\n", buflen_from_user)); - if (!extra) + if (!extra) { + WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name)); return -EINVAL; + } if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) @@ -883,27 +1836,127 @@ wl_iw_get_scan( return -EAGAIN; - list = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL); - if (!list) - return -ENOMEM; - memset(list, 0, WLC_IOCTL_MAXLEN); - list->buflen = htod32(WLC_IOCTL_MAXLEN); - if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, WLC_IOCTL_MAXLEN))) { - kfree(list); - return error; + if (g_scan_specified_ssid) { + + list = kmalloc(len, GFP_KERNEL); + if (!list) { + WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name)); + return -ENOMEM; + } + } + + memset(list, 0, len); + list->buflen = htod32(len); + if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) { + WL_TRACE(("%s: %s : Scan_results too big %d\n", dev->name, __FUNCTION__, len)); + dwrq->length = len; + if (g_scan_specified_ssid) + kfree(list); + return 0; } list->buflen = dtoh32(list->buflen); list->version = dtoh32(list->version); list->count = dtoh32(list->count); - ASSERT(list->version == WL_BSS_INFO_VERSION); + + if (g_scan_specified_ssid) { + WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count)); + len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); + kfree(list); + +#if defined(WL_IW_USE_ISCAN) + p_buf = iscan->list_hdr; + + while (p_buf != iscan->list_cur) { + list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; + WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); + if (list_merge->count > 0) + len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, + extra+len_ret, buflen_from_user -len_ret); + p_buf = p_buf->next; + } +#else + list_merge = (wl_scan_results_t *) g_scan; + WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); + if (list_merge->count > 0) + len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret, + buflen_from_user -len_ret); +#endif + } + else { + list = (wl_scan_results_t *) g_scan; + len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); + } + + + if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user) + len = len_ret; + + dwrq->length = len; + dwrq->flags = 0; + + WL_TRACE(("%s return to WE dwrq->length=%d bytes\n", __FUNCTION__, dwrq->length)); + return 0; +} + +#if defined(WL_IW_USE_ISCAN) +static int +wl_iw_iscan_get_scan( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *extra +) +{ + wl_scan_results_t *list; + struct iw_event iwe; + wl_bss_info_t *bi = NULL; + int ii, j; + int apcnt; + char *event = extra, *end = extra + dwrq->length, *value; + iscan_info_t *iscan = g_iscan; + iscan_buf_t * p_buf; + + WL_TRACE(("%s: SIOCGIWSCAN GET\n", dev->name)); + + if (!extra) { + WL_TRACE(("%s: SIOCGIWSCAN GET bad parameter\n", dev->name)); + return -EINVAL; + } + + + if ((!iscan) || (iscan->sysioc_pid < 0)) { + return wl_iw_get_scan(dev, info, dwrq, extra); + } + + + + if (g_scan_specified_ssid) { + return wl_iw_get_scan(dev, info, dwrq, extra); + } + + WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name)); + apcnt = 0; + p_buf = iscan->list_hdr; + + while (p_buf != iscan->list_cur) { + list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; + + if (list->version != WL_BSS_INFO_VERSION) { + WL_ERROR(("list->version %d != WL_BSS_INFO_VERSION\n", list->version)); + } - for (i = 0; i < list->count && i < IW_MAX_AP; i++) { + bi = NULL; + for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) { bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + - WLC_IOCTL_MAXLEN)); + WLC_IW_ISCAN_MAXLEN)); + if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + + IW_EV_QUAL_LEN >= end) + return -E2BIG; + iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); @@ -949,6 +2002,8 @@ wl_iw_get_scan( 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); @@ -958,6 +2013,9 @@ wl_iw_get_scan( 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; + iwe.cmd = IWEVGENIE; iwe.u.data.length = ie->len + 2; event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); @@ -969,6 +2027,8 @@ wl_iw_get_scan( 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, @@ -991,6 +2051,9 @@ done: if (bi->rateset.count) { + if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) + return -E2BIG; + value = event + IW_EV_LCP_LEN; iwe.cmd = SIOCGIWRATE; @@ -1002,12 +2065,13 @@ done: } event = value; } - } - - kfree(list); + } + p_buf = p_buf->next; + } dwrq->length = event - extra; dwrq->flags = 0; + WL_TRACE(("%s return to WE dwrq->length=%d bytes\n", __FUNCTION__, dwrq->length)); return 0; } @@ -1021,24 +2085,26 @@ wl_iw_set_essid( char *extra ) { - wlc_ssid_t ssid; int error; WL_TRACE(("%s: SIOCSIWESSID\n", dev->name)); + + memset(&g_ssid, 0, sizeof(g_ssid)); + if (dwrq->length && extra) { #if WIRELESS_EXT > 20 - ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length); + g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length); #else - ssid.SSID_len = MIN(sizeof(ssid.SSID), dwrq->length-1); + g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1); #endif - memcpy(ssid.SSID, extra, ssid.SSID_len); + memcpy(g_ssid.SSID, extra, g_ssid.SSID_len); } else { - ssid.SSID_len = 0; + g_ssid.SSID_len = 0; } - ssid.SSID_len = htod32(ssid.SSID_len); - if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid)))) + g_ssid.SSID_len = htod32(g_ssid.SSID_len); + if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &g_ssid, sizeof(g_ssid)))) return error; return 0; @@ -1069,7 +2135,6 @@ wl_iw_get_essid( memcpy(extra, ssid.SSID, ssid.SSID_len); - extra[ssid.SSID_len] = '\0'; dwrq->length = ssid.SSID_len; @@ -1831,16 +2896,20 @@ wl_iw_set_wpaauth( if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) - val |= WEP_ENABLED; + val = WEP_ENABLED; if (paramval & IW_AUTH_CIPHER_TKIP) - val |= TKIP_ENABLED; + val = TKIP_ENABLED; if (paramval & IW_AUTH_CIPHER_CCMP) - val |= AES_ENABLED; + val = AES_ENABLED; - if (paramid == IW_AUTH_CIPHER_PAIRWISE) - val |= iw->pwsec; - else + if (paramid == IW_AUTH_CIPHER_PAIRWISE) { + iw->pwsec = val; val |= iw->gwsec; + } + else { + iw->gwsec = val; + val |= iw->pwsec; + } if ((error = dev_wlc_intvar_set(dev, "wsec", val))) return error; @@ -1876,10 +2945,12 @@ wl_iw_set_wpaauth( case IW_AUTH_80211_AUTH_ALG: WL_ERROR(("Setting the D11auth %d\n", paramval)); - if (paramval & IW_AUTH_ALG_OPEN_SYSTEM) + if (paramval == IW_AUTH_ALG_OPEN_SYSTEM) val = 0; - else if (paramval & IW_AUTH_ALG_SHARED_KEY) + else if (paramval == IW_AUTH_ALG_SHARED_KEY) val = 1; + else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY)) + val = 2; else error = 1; if (!error && (error = dev_wlc_intvar_set(dev, "auth", val))) @@ -1888,6 +2959,8 @@ wl_iw_set_wpaauth( case IW_AUTH_WPA_ENABLED: if (paramval == 0) { + iw->pwsec = 0; + iw->gwsec = 0; if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) return error; if (val & (TKIP_ENABLED | AES_ENABLED)) { @@ -2036,6 +3109,62 @@ wl_iw_get_wpaauth( } #endif +static int +wl_iw_set_priv( + struct net_device *dev, + struct iw_request_info *info, + struct iw_point *dwrq, + char *ext +) +{ + int ret = 0; + char * extra; + + if (!(extra = kmalloc(dwrq->length, GFP_KERNEL))) + return -ENOMEM; + + if (copy_from_user(extra, dwrq->pointer, dwrq->length)) { + kfree(extra); + return -EFAULT; + } + + WL_TRACE(("%s: SIOCSIWPRIV, requst = %s ==> ", + dev->name, extra)); + + + if (g_onoff) { + g_onoff = 0; + wl_iw_control_wl(dev, info, (union iwreq_data *)dwrq, extra, 0); + } + + if (dwrq->length && extra) { + if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) + ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) + ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0) + ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0) + ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0) + ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, "STOP", strlen("STOP")) == 0) + ret = wl_iw_control_wl(dev, info, (union iwreq_data *)dwrq, extra, 1); + } + + if (extra) { + if (copy_to_user(dwrq->pointer, extra, dwrq->length)) { + kfree(extra); + return -EFAULT; + } + + kfree(extra); + } + WL_TRACE(("\n")); + + return ret; +} + static const iw_handler wl_iw_handler[] = { (iw_handler) wl_iw_config_commit, @@ -2050,7 +3179,7 @@ static const iw_handler wl_iw_handler[] = (iw_handler) NULL, (iw_handler) NULL, (iw_handler) wl_iw_get_range, - (iw_handler) NULL, + (iw_handler) wl_iw_set_priv, (iw_handler) NULL, (iw_handler) NULL, (iw_handler) NULL, @@ -2065,10 +3194,19 @@ static const iw_handler wl_iw_handler[] = #else (iw_handler) NULL, #endif +#if defined(WL_IW_USE_ISCAN) + (iw_handler) wl_iw_iscan_get_aplist, +#else (iw_handler) wl_iw_get_aplist, +#endif #if WIRELESS_EXT > 13 +#if defined(WL_IW_USE_ISCAN) + (iw_handler) wl_iw_iscan_set_scan, + (iw_handler) wl_iw_iscan_get_scan, +#else (iw_handler) wl_iw_set_scan, (iw_handler) wl_iw_get_scan, +#endif #else (iw_handler) NULL, (iw_handler) NULL, @@ -2111,14 +3249,61 @@ static const iw_handler wl_iw_handler[] = }; #if WIRELESS_EXT > 12 +static const iw_handler wl_iw_priv_handler[] = { + NULL, + (iw_handler)wl_iw_set_active_scan, + NULL, + (iw_handler)wl_iw_get_rssi, + NULL, + (iw_handler)wl_iw_set_passive_scan, + NULL, + (iw_handler)wl_iw_get_link_speed, + NULL, + (iw_handler)wl_iw_get_macaddr +}; + +static const struct iw_priv_args wl_iw_priv_args[] = { + { + WL_IW_SET_ACTIVE_SCAN, + 0, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + "SCAN-ACTIVE" + }, + { + WL_IW_GET_RSSI, + 0, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + "RSSI" + }, + { + WL_IW_SET_PASSIVE_SCAN, + 0, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + "SCAN-PASSIVE" + }, + { + WL_IW_GET_LINK_SPEED, + 0, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + "LINKSPEED" + }, + { + WL_IW_GET_CURR_MACADDR, + 0, + IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, + "Macaddr" + } +}; + const struct iw_handler_def wl_iw_handler_def = { .num_standard = ARRAYSIZE(wl_iw_handler), - .num_private = 0, - .num_private_args = 0, .standard = (iw_handler *) wl_iw_handler, - .private = NULL, - .private_args = NULL, + .num_private = ARRAYSIZE(wl_iw_priv_handler), + .num_private_args = ARRAY_SIZE(wl_iw_priv_args), + .private = (iw_handler *)wl_iw_priv_handler, + .private_args = (void *) wl_iw_priv_args, + #if WIRELESS_EXT >= 19 get_wireless_stats: dhd_get_wireless_stats, #endif @@ -2172,6 +3357,11 @@ wl_iw_ioctl( #if WIRELESS_EXT > 13 case SIOCGIWSCAN: +#if defined(WL_IW_USE_ISCAN) + if (g_iscan) + max_tokens = wrq->u.data.length; + else +#endif max_tokens = IW_SCAN_MAX_DATA; break; #endif @@ -2186,6 +3376,9 @@ wl_iw_ioctl( max_tokens = IW_MAX_SPY; break; + case SIOCSIWPRIV: + max_tokens = wrq->u.data.length; + break; } if (max_tokens && wrq->u.data.pointer) { @@ -2332,34 +3525,42 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) memset(&wrqu, 0, sizeof(wrqu)); memset(extra, 0, sizeof(extra)); - memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; + switch (event_type) { case WLC_E_TXFAIL: cmd = IWEVTXDROP; + memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); + wrqu.addr.sa_family = ARPHRD_ETHER; break; #if WIRELESS_EXT > 14 case WLC_E_JOIN: case WLC_E_ASSOC_IND: case WLC_E_REASSOC_IND: + memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); + wrqu.addr.sa_family = ARPHRD_ETHER; cmd = IWEVREGISTERED; break; case WLC_E_DEAUTH_IND: case WLC_E_DISASSOC_IND: cmd = SIOCGIWAP; - wrqu.data.length = strlen(extra); bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); + wrqu.addr.sa_family = ARPHRD_ETHER; bzero(&extra, ETHER_ADDR_LEN); break; case WLC_E_LINK: case WLC_E_NDIS_LINK: cmd = SIOCGIWAP; - wrqu.data.length = strlen(extra); if (!(flags & WLC_EVENT_MSG_LINK)) { + bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); } + else { + + memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); + } + wrqu.addr.sa_family = ARPHRD_ETHER; break; #endif #if WIRELESS_EXT > 17 @@ -2407,6 +3608,17 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) } #endif #endif + +#if defined(WL_IW_USE_ISCAN) + case WLC_E_SCAN_COMPLETE: + cmd = SIOCGIWSCAN; + WL_TRACE(("event WLC_E_SCAN_COMPLETE\n")); + if ((g_iscan) && (g_iscan->sysioc_pid >= 0)) + up(&g_iscan->sysioc_sem); + break; + +#endif + default: break; @@ -2514,3 +3726,75 @@ 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) +{ +#if defined(WL_IW_USE_ISCAN) + iscan_info_t *iscan = NULL; + + if (!dev) + return 0; + + iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); + if (!iscan) + return -ENOMEM; + memset(iscan, 0, sizeof(iscan_info_t)); + iscan->sysioc_pid = -1; + + g_iscan = iscan; + iscan->dev = dev; + iscan->iscan_state = ISCAN_STATE_IDLE; + g_iscan->scan_flag = 0; + + + iscan->timer_ms = 3000; + init_timer(&iscan->timer); + iscan->timer.data = (ulong)iscan; + iscan->timer.function = wl_iw_timerfunc; + + sema_init(&iscan->sysioc_sem, 0); + init_completion(&iscan->sysioc_exited); + iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); + if (iscan->sysioc_pid < 0) + return -ENOMEM; +#endif + + g_scan = NULL; + + + g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL); + if (!g_scan) + return -ENOMEM; + + memset(g_scan, 0, G_SCAN_RESULTS); + g_scan_specified_ssid = 0; + + return 0; +} + +void wl_iw_detach(void) +{ +#if defined(WL_IW_USE_ISCAN) + iscan_buf_t *buf; + iscan_info_t *iscan = g_iscan; + + if (!iscan) + return; + if (iscan->sysioc_pid >= 0) { + KILL_PROC(iscan->sysioc_pid, SIGTERM); + wait_for_completion(&iscan->sysioc_exited); + } + + while (iscan->list_hdr) { + buf = iscan->list_hdr->next; + kfree(iscan->list_hdr); + iscan->list_hdr = buf; + } + kfree(iscan); + g_iscan = NULL; +#endif + + if (g_scan) + kfree(g_scan); + + g_scan = NULL; +} diff --git a/src/wl/sys/wl_iw.h b/src/wl/sys/wl_iw.h index 15bb923..aff061c 100644 --- a/src/wl/sys/wl_iw.h +++ b/src/wl/sys/wl_iw.h @@ -3,27 +3,25 @@ * * Copyright (C) 1999-2008, Broadcom Corporation * - * All Rights Reserved. - * - * Unless you and Broadcom execute a separate written software license + * 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, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL"), with the + * 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, regardless of the - * license terms of these 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. + * 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. * - * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY - * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM - * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.h,v 1.5.34.1.20.1 2009/01/18 00:30:44 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.20.4 2009/02/20 05:22:23 Exp $ */ @@ -45,6 +43,14 @@ #define WL_IW_RSSI_VERY_GOOD -58 #define WL_IW_RSSI_EXCELLENT -57 #define WL_IW_RSSI_INVALID 0 +#define MAX_WX_STRING 80 +#define SSID_FMT_BUF_LEN ((4 * 32) + 1) +#define isprint(c) bcm_isprint(c) +#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1) +#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3) +#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5) +#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7) +#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9) typedef struct wl_iw { char nickname[IW_ESSID_MAX_SIZE]; @@ -68,6 +74,8 @@ 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); +void wl_iw_detach(void); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) #define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ |