From 88922c12f55095e7d8a0c91a9fd4446975ef4304 Mon Sep 17 00:00:00 2001 From: tytung Date: Tue, 13 Dec 2011 01:08:16 +0800 Subject: [PATCH] drivers: net: wireless: backported bcm4329 from tuna kernel --- drivers/net/wireless/bcm4329/Makefile | 2 +- drivers/net/wireless/bcm4329/bcmsdh_linux.c | 14 +- .../net/wireless/bcm4329/bcmsdh_sdmmc_linux.c | 10 +- drivers/net/wireless/bcm4329/dhd.h | 36 +- drivers/net/wireless/bcm4329/dhd_cdc.c | 17 +- drivers/net/wireless/bcm4329/dhd_common.c | 131 ++++++- .../net/wireless/bcm4329/dhd_custom_gpio.c | 95 ++++- drivers/net/wireless/bcm4329/dhd_linux.c | 221 ++++++++++-- drivers/net/wireless/bcm4329/dhd_sdio.c | 3 +- .../net/wireless/bcm4329/include/epivers.h | 10 +- .../net/wireless/bcm4329/include/wlioctl.h | 25 +- drivers/net/wireless/bcm4329/wl_iw.c | 324 +++++++++++++----- drivers/net/wireless/bcm4329/wl_iw.h | 61 +++- include/linux/wireless.h | 4 +- include/linux/wlan_plat.h | 1 + 15 files changed, 758 insertions(+), 196 deletions(-) diff --git a/drivers/net/wireless/bcm4329/Makefile b/drivers/net/wireless/bcm4329/Makefile index 3f49a643..5a662be7 100644 --- a/drivers/net/wireless/bcm4329/Makefile +++ b/drivers/net/wireless/bcm4329/Makefile @@ -7,7 +7,7 @@ DHDCFLAGS = -DLINUX -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD -DBCMWPA2 \ -DDHD_USE_STATIC_BUF -DMMC_SDIO_ABORT -DDHD_DEBUG_TRAP -DSOFTAP \ -DEMBEDDED_PLATFORM -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT \ -DGET_CUSTOM_MAC_ENABLE -DSET_RANDOM_MAC_SOFTAP -DCSCAN -DHW_OOB \ - -DKEEP_ALIVE \ + -DKEEP_ALIVE -DPNO_SUPPORT \ -Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include DHDOFILES = dhd_linux.o linux_osl.o bcmutils.o dhd_common.o dhd_custom_gpio.o \ diff --git a/drivers/net/wireless/bcm4329/bcmsdh_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_linux.c index cdb2c5e1..6d6097b7 100644 --- a/drivers/net/wireless/bcm4329/bcmsdh_linux.c +++ b/drivers/net/wireless/bcm4329/bcmsdh_linux.c @@ -301,7 +301,7 @@ int bcmsdh_remove(struct device *dev) MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); osl_detach(osh); -#if !defined(BCMLXSDMMC) +#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY) dev_set_drvdata(dev, NULL); #endif /* !defined(BCMLXSDMMC) */ @@ -636,7 +636,7 @@ int bcmsdh_register_oob_intr(void * dhdp) if (error) return -ENODEV; - set_irq_wake(sdhcinfo->oob_irq, 1); + enable_irq_wake(sdhcinfo->oob_irq); sdhcinfo->oob_irq_registered = TRUE; } @@ -661,10 +661,12 @@ void bcmsdh_unregister_oob_intr(void) { SDLX_MSG(("%s: Enter\n", __FUNCTION__)); - set_irq_wake(sdhcinfo->oob_irq, 0); - disable_irq(sdhcinfo->oob_irq); /* just in case.. */ - free_irq(sdhcinfo->oob_irq, NULL); - sdhcinfo->oob_irq_registered = FALSE; + if (sdhcinfo->oob_irq_registered) { + disable_irq_wake(sdhcinfo->oob_irq); + disable_irq(sdhcinfo->oob_irq); /* just in case.. */ + free_irq(sdhcinfo->oob_irq, NULL); + sdhcinfo->oob_irq_registered = FALSE; + } } #endif /* defined(OOB_INTR_ONLY) */ /* Module parameters specific to each host-controller driver */ diff --git a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c index 8992a426..5a1a46c9 100644 --- a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c @@ -82,7 +82,6 @@ PBCMSDH_SDMMC_INSTANCE gInstance; extern int bcmsdh_probe(struct device *dev); extern int bcmsdh_remove(struct device *dev); -struct device sdmmc_dev; static int bcmsdh_sdmmc_probe(struct sdio_func *func, const struct sdio_device_id *id) @@ -102,7 +101,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, if(func->device == 0x4) { /* 4318 */ gInstance->func[2] = NULL; sd_trace(("NIC found, calling bcmsdh_probe...\n")); - ret = bcmsdh_probe(&sdmmc_dev); + ret = bcmsdh_probe(&func->dev); } } @@ -110,7 +109,7 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, if (func->num == 2) { sd_trace(("F2 found, calling bcmsdh_probe...\n")); - ret = bcmsdh_probe(&sdmmc_dev); + ret = bcmsdh_probe(&func->dev); } return ret; @@ -126,7 +125,7 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func) if (func->num == 2) { sd_trace(("F2 found, calling bcmsdh_remove...\n")); - bcmsdh_remove(&sdmmc_dev); + bcmsdh_remove(&func->dev); } } @@ -250,10 +249,8 @@ int sdio_function_init(void) if (!gInstance) return -ENOMEM; - bzero(&sdmmc_dev, sizeof(sdmmc_dev)); error = sdio_register_driver(&bcmsdh_sdmmc_driver); - return error; } @@ -265,7 +262,6 @@ void sdio_function_cleanup(void) { sd_trace(("%s Enter\n", __FUNCTION__)); - sdio_unregister_driver(&bcmsdh_sdmmc_driver); if (gInstance) diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index 1ddf1ff6..0b2e9c23 100644 --- a/drivers/net/wireless/bcm4329/dhd.h +++ b/drivers/net/wireless/bcm4329/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.7 2010/11/12 22:48:36 Exp $ + * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.9 2011/01/14 22:40:45 Exp $ */ /**************** @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -143,7 +144,7 @@ typedef struct dhd_pub { 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 */ - ulong fc_packets; /* Number of flow control pkts recvd */ + ulong fc_packets; /* Number of flow control pkts recvd */ /* Last error return */ int bcmerror; @@ -155,6 +156,7 @@ typedef struct dhd_pub { /* Suspend disable flag and "in suspend" flag */ int suspend_disable_flag; /* "1" to disable all extra powersaving during suspend */ int in_suspend; /* flag set to 1 when early suspend called */ + int hang_was_sent; /* flag that message was send at least once */ #ifdef PNO_SUPPORT int pno_enable; /* pno status : "1" is pno enable */ #endif /* PNO_SUPPORT */ @@ -164,7 +166,7 @@ typedef struct dhd_pub { char * pktfilter[100]; int pktfilter_count; - uint8 country_code[WLC_CNTRY_BUF_SZ]; + wl_country_t dhd_cspec; /* Current Locale info */ char eventmask[WL_EVENTING_MASK_LEN]; } dhd_pub_t; @@ -179,7 +181,7 @@ typedef struct dhd_pub { wait_event_interruptible_timeout(a, FALSE, HZ/100); \ } \ } while (0) - #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30) + #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 200) #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0) #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) @@ -214,6 +216,20 @@ typedef struct dhd_pub { #define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ +inline static void NETIF_ADDR_LOCK(struct net_device *dev) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) + netif_addr_lock_bh(dev); +#endif +} + +inline static void NETIF_ADDR_UNLOCK(struct net_device *dev) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)) + netif_addr_unlock_bh(dev); +#endif +} + /* Wakelock Functions */ extern int dhd_os_wake_lock(dhd_pub_t *pub); extern int dhd_os_wake_unlock(dhd_pub_t *pub); @@ -434,4 +450,16 @@ extern char nv_path[MOD_PARAM_PATHLEN]; extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); +/* dhd_commn arp offload wrapers */ +extern void dhd_arp_cleanup(dhd_pub_t *dhd); +int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen); +void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr); + +#define DHD_UNICAST_FILTER_NUM 0 +#define DHD_BROADCAST_FILTER_NUM 1 +#define DHD_MULTICAST4_FILTER_NUM 2 +#define DHD_MULTICAST6_FILTER_NUM 3 +extern int net_os_set_packet_filter(struct net_device *dev, int val); +extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); + #endif /* _dhd_h_ */ diff --git a/drivers/net/wireless/bcm4329/dhd_cdc.c b/drivers/net/wireless/bcm4329/dhd_cdc.c index 61f6a6f3..4bec0b60 100644 --- a/drivers/net/wireless/bcm4329/dhd_cdc.c +++ b/drivers/net/wireless/bcm4329/dhd_cdc.c @@ -150,7 +150,8 @@ dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) memcpy(prot->buf, buf, len); if ((ret = dhdcdc_msg(dhd)) < 0) { - DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret)); + if (!dhd->hang_was_sent) + DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret)); goto done; } @@ -205,6 +206,18 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len)); + if (dhd->busstate == DHD_BUS_DOWN) { + DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); + return -EIO; + } + + /* don't talk to the dongle if fw is about to be reloaded */ + if (dhd->hang_was_sent) { + DHD_ERROR(("%s: HANG was sent up earlier. Not talking to the chip\n", + __FUNCTION__)); + return -EIO; + } + memset(msg, 0, sizeof(cdc_ioctl_t)); msg->cmd = htol32(cmd); @@ -251,7 +264,7 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) dhd_prot_t *prot = dhd->prot; int ret = -1; - if (dhd->busstate == DHD_BUS_DOWN) { + if ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent) { DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); return ret; } diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c index 4331d39a..f7cd372d 100644 --- a/drivers/net/wireless/bcm4329/dhd_common.c +++ b/drivers/net/wireless/bcm4329/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.20 2010/12/20 23:37:28 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.25 2011-02-11 21:16:02 Exp $ */ #include #include @@ -992,6 +992,9 @@ dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_ wl_pkt_filter_enable_t enable_parm; wl_pkt_filter_enable_t * pkt_filterp; + if (!arg) + return; + if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; @@ -1065,6 +1068,9 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) char *arg_save = 0, *arg_org = 0; #define BUF_SIZE 2048 + if (!arg) + return; + if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); goto fail; @@ -1220,6 +1226,82 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable) } #endif + +void dhd_arp_cleanup(dhd_pub_t *dhd) +{ +#ifdef ARP_OFFLOAD_SUPPORT + int ret = 0; + int iov_len = 0; + char iovbuf[128]; + + if (dhd == NULL) return; + + dhd_os_proto_block(dhd); + + iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf)); + if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0) + DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); + + iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf)); + if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len)) < 0) + DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); + + dhd_os_proto_unblock(dhd); + +#endif /* ARP_OFFLOAD_SUPPORT */ +} + +void dhd_arp_offload_add_ip(dhd_pub_t *dhd, u32 ipaddr) +{ +#ifdef ARP_OFFLOAD_SUPPORT + int iov_len = 0; + char iovbuf[32]; + int retcode; + + dhd_os_proto_block(dhd); + + iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf)); + retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, iov_len); + + dhd_os_proto_unblock(dhd); + + if (retcode) + DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n", + __FUNCTION__, retcode)); + else + DHD_TRACE(("%s: ARP ipaddr entry added\n", + __FUNCTION__)); +#endif /* ARP_OFFLOAD_SUPPORT */ +} + + +int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen) +{ +#ifdef ARP_OFFLOAD_SUPPORT + int retcode; + int iov_len = 0; + + if (!buf) + return -1; + + dhd_os_proto_block(dhd); + + iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen); + retcode = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, buflen); + + dhd_os_proto_unblock(dhd); + + if (retcode) { + DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n", + __FUNCTION__, retcode)); + + return -1; + } +#endif /* ARP_OFFLOAD_SUPPORT */ + return 0; +} + + int dhd_preinit_ioctls(dhd_pub_t *dhd) { @@ -1287,9 +1369,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #endif /* SET_RANDOM_MAC_SOFTAP */ /* Set Country code */ - if (dhd->country_code[0] != 0) { - if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY, - dhd->country_code, sizeof(dhd->country_code)) < 0) { + if (dhd->dhd_cspec.ccode[0] != 0) { + bcm_mkiovar("country", (char *)&dhd->dhd_cspec, \ + sizeof(wl_country_t), iovbuf, sizeof(iovbuf)); + if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) { DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__)); } } @@ -1896,6 +1979,7 @@ int dhd_pno_clean(dhd_pub_t *dhd) int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) { char iovbuf[128]; + uint8 bssid[6]; int ret = -1; if ((!dhd) && ((pfn_enabled != 0) || (pfn_enabled != 1))) { @@ -1903,6 +1987,20 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) return ret; } + memset(iovbuf, 0, sizeof(iovbuf)); + + /* Check if disassoc to enable pno */ + if ((pfn_enabled) && \ + ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_GET_BSSID, \ + (char *)&bssid, ETHER_ADDR_LEN)) == BCME_NOTASSOCIATED)) { + DHD_TRACE(("%s pno enable called in disassoc mode\n", __FUNCTION__)); + } + else if (pfn_enabled) { + DHD_ERROR(("%s pno enable called in assoc mode ret=%d\n", \ + __FUNCTION__, ret)); + return ret; + } + /* Enable/disable PNO */ if ((ret = bcm_mkiovar("pfn", (char *)&pfn_enabled, 4, iovbuf, sizeof(iovbuf))) > 0) { if ((ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf))) < 0) { @@ -1921,7 +2019,8 @@ int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled) /* Function to execute combined scan */ int -dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) +dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, \ + int pno_repeat, int pno_freq_expo_max) { int err = -1; char iovbuf[128]; @@ -1966,12 +2065,23 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) pfn_param.version = htod32(PFN_VERSION); pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT)); + /* check and set extra pno params */ + if ((pno_repeat != 0) || (pno_freq_expo_max != 0)) { + pfn_param.flags |= htod16(ENABLE << ENABLE_ADAPTSCAN_BIT); + pfn_param.repeat_scan = htod32(pno_repeat); + pfn_param.max_freq_adjust = htod32(pno_freq_expo_max); + } + /* set up pno scan fr */ if (scan_fr != 0) pfn_param.scan_freq = htod32(scan_fr); - if (pfn_param.scan_freq > PNO_SCAN_MAX_FW) { - DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW)); + if (pfn_param.scan_freq > PNO_SCAN_MAX_FW_SEC) { + DHD_ERROR(("%s pno freq above %d sec\n", __FUNCTION__, PNO_SCAN_MAX_FW_SEC)); + return err; + } + if (pfn_param.scan_freq < PNO_SCAN_MIN_FW_SEC) { + DHD_ERROR(("%s pno freq less %d sec\n", __FUNCTION__, PNO_SCAN_MIN_FW_SEC)); return err; } @@ -1983,8 +2093,6 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE); pfn_element.auth = (DOT11_OPEN_SYSTEM); - pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY); - pfn_element.wsec = htod32(0); pfn_element.infra = htod32(1); memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID, ssids_local[i].SSID_len); @@ -2000,8 +2108,9 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) return err; } else - DHD_ERROR(("%s set OK with PNO time=%d\n", __FUNCTION__, \ - pfn_param.scan_freq)); + DHD_ERROR(("%s set OK with PNO time=%d repeat=%d max_adjust=%d\n", \ + __FUNCTION__, pfn_param.scan_freq, \ + pfn_param.repeat_scan, pfn_param.max_freq_adjust)); } else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err)); } diff --git a/drivers/net/wireless/bcm4329/dhd_custom_gpio.c b/drivers/net/wireless/bcm4329/dhd_custom_gpio.c index 8c6ec470..4d32863e 100644 --- a/drivers/net/wireless/bcm4329/dhd_custom_gpio.c +++ b/drivers/net/wireless/bcm4329/dhd_custom_gpio.c @@ -20,7 +20,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * -* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.1 2010/09/02 23:13:16 Exp $ +* $Id: dhd_custom_gpio.c,v 1.1.4.8.4.4 2011/01/20 20:23:09 Exp $ */ @@ -47,6 +47,7 @@ int wifi_set_carddetect(int on); int wifi_set_power(int on, unsigned long msec); int wifi_get_irq_number(unsigned long *irq_flags_ptr); int wifi_get_mac_addr(unsigned char *buf); +void *wifi_get_country_code(char *ccode); #endif #if defined(OOB_INTR_ONLY) @@ -177,3 +178,95 @@ dhd_custom_get_mac_address(unsigned char *buf) return ret; } #endif /* GET_CUSTOM_MAC_ENABLE */ + +/* Customized Locale table : OPTIONAL feature */ +const struct cntry_locales_custom translate_custom_table[] = { +/* Table should be filled out based on custom platform regulatory requirement */ +#ifdef EXAMPLE_TABLE + {"", "XY", 4}, /* universal */ + {"US", "US", 69}, /* input ISO "US" to : US regrev 69 */ + {"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */ + {"EU", "EU", 5}, /* European union countries */ + {"AT", "EU", 5}, + {"BE", "EU", 5}, + {"BG", "EU", 5}, + {"CY", "EU", 5}, + {"CZ", "EU", 5}, + {"DK", "EU", 5}, + {"EE", "EU", 5}, + {"FI", "EU", 5}, + {"FR", "EU", 5}, + {"DE", "EU", 5}, + {"GR", "EU", 5}, + {"HU", "EU", 5}, + {"IE", "EU", 5}, + {"IT", "EU", 5}, + {"LV", "EU", 5}, + {"LI", "EU", 5}, + {"LT", "EU", 5}, + {"LU", "EU", 5}, + {"MT", "EU", 5}, + {"NL", "EU", 5}, + {"PL", "EU", 5}, + {"PT", "EU", 5}, + {"RO", "EU", 5}, + {"SK", "EU", 5}, + {"SI", "EU", 5}, + {"ES", "EU", 5}, + {"SE", "EU", 5}, + {"GB", "EU", 5}, /* input ISO "GB" to : EU regrev 05 */ + {"IL", "IL", 0}, + {"CH", "CH", 0}, + {"TR", "TR", 0}, + {"NO", "NO", 0}, + {"KR", "XY", 3}, + {"AU", "XY", 3}, + {"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */ + {"TW", "XY", 3}, + {"AR", "XY", 3}, + {"MX", "XY", 3} +#endif /* EXAMPLE_TABLE */ +}; + + +/* Customized Locale convertor +* input : ISO 3166-1 country abbreviation +* output: customized cspec +*/ +void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) +{ +#ifdef CUSTOMER_HW2 + struct cntry_locales_custom *cloc_ptr; + + if (!cspec) + return; + + cloc_ptr = wifi_get_country_code(country_iso_code); + if (cloc_ptr) { + strlcpy(cspec->ccode, cloc_ptr->custom_locale, WLC_CNTRY_BUF_SZ); + cspec->rev = cloc_ptr->custom_locale_rev; + } + return; +#else + int size, i; + + size = ARRAYSIZE(translate_custom_table); + + if (cspec == 0) + return; + + if (size == 0) + return; + + for (i = 0; i < size; i++) { + if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) { + memcpy(cspec->ccode, translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ); + cspec->rev = translate_custom_table[i].custom_locale_rev; + return; + } + } + memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ); + cspec->rev = translate_custom_table[0].custom_locale_rev; + return; +#endif +} diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index f14f5e81..9365e360 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -22,12 +22,9 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.35 2010/11/17 03:13:21 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.40 2011/02/03 19:55:18 Exp $ */ -#ifdef CONFIG_WIFI_CONTROL_FUNC -#include -#endif #include #include #include @@ -43,6 +40,7 @@ #include #include #include +#include #include #include @@ -62,14 +60,14 @@ #ifdef CONFIG_HAS_WAKELOCK #include #endif -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) +#ifdef CUSTOMER_HW2 +#include +#ifdef CONFIG_WIFI_CONTROL_FUNC #include - +static struct wifi_platform_data *wifi_control_data = NULL; +#endif struct semaphore wifi_control_sem; -struct dhd_bus *g_bus; - -static struct wifi_platform_data *wifi_control_data = NULL; static struct resource *wifi_irqres = NULL; int wifi_get_irq_number(unsigned long *irq_flags_ptr) @@ -88,18 +86,22 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr) int wifi_set_carddetect(int on) { printk("%s = %d\n", __FUNCTION__, on); +#ifdef CONFIG_WIFI_CONTROL_FUNC if (wifi_control_data && wifi_control_data->set_carddetect) { wifi_control_data->set_carddetect(on); } +#endif return 0; } int wifi_set_power(int on, unsigned long msec) { printk("%s = %d\n", __FUNCTION__, on); +#ifdef CONFIG_WIFI_CONTROL_FUNC if (wifi_control_data && wifi_control_data->set_power) { wifi_control_data->set_power(on); } +#endif if (msec) mdelay(msec); return 0; @@ -108,9 +110,11 @@ int wifi_set_power(int on, unsigned long msec) int wifi_set_reset(int on, unsigned long msec) { DHD_TRACE(("%s = %d\n", __FUNCTION__, on)); +#ifdef CONFIG_WIFI_CONTROL_FUNC if (wifi_control_data && wifi_control_data->set_reset) { wifi_control_data->set_reset(on); } +#endif if (msec) mdelay(msec); return 0; @@ -121,20 +125,38 @@ int wifi_get_mac_addr(unsigned char *buf) DHD_TRACE(("%s\n", __FUNCTION__)); if (!buf) return -EINVAL; +#ifdef CONFIG_WIFI_CONTROL_FUNC if (wifi_control_data && wifi_control_data->get_mac_addr) { return wifi_control_data->get_mac_addr(buf); } +#endif return -EOPNOTSUPP; } +void *wifi_get_country_code(char *ccode) +{ + DHD_TRACE(("%s\n", __FUNCTION__)); +#ifdef CONFIG_WIFI_CONTROL_FUNC + if (!ccode) + return NULL; + if (wifi_control_data && wifi_control_data->get_country_code) { + return wifi_control_data->get_country_code(ccode); + } +#endif + return NULL; +} + static int wifi_probe(struct platform_device *pdev) { +#ifdef CONFIG_WIFI_CONTROL_FUNC struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); + wifi_control_data = wifi_ctrl; +#endif + DHD_TRACE(("## %s\n", __FUNCTION__)); wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); - wifi_control_data = wifi_ctrl; wifi_set_power(1, 0); /* Power On */ wifi_set_carddetect(1); /* CardDetect (0->1) */ @@ -145,26 +167,34 @@ static int wifi_probe(struct platform_device *pdev) static int wifi_remove(struct platform_device *pdev) { +#ifdef CONFIG_WIFI_CONTROL_FUNC struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); - DHD_TRACE(("## %s\n", __FUNCTION__)); wifi_control_data = wifi_ctrl; - +#endif + DHD_TRACE(("## %s\n", __FUNCTION__)); wifi_set_power(0, 0); /* Power Off */ wifi_set_carddetect(0); /* CardDetect (1->0) */ up(&wifi_control_sem); return 0; } + static int wifi_suspend(struct platform_device *pdev, pm_message_t state) { DHD_TRACE(("##> %s\n", __FUNCTION__)); +#if defined(OOB_INTR_ONLY) + bcmsdh_oob_intr_set(0); +#endif /* (OOB_INTR_ONLY) */ return 0; } static int wifi_resume(struct platform_device *pdev) { DHD_TRACE(("##> %s\n", __FUNCTION__)); +#if defined(OOB_INTR_ONLY) + bcmsdh_oob_intr_set(1); +#endif /* (OOB_INTR_ONLY) */ return 0; } @@ -189,8 +219,14 @@ void wifi_del_dev(void) DHD_TRACE(("## Unregister platform_driver_register\n")); platform_driver_unregister(&wifi_device); } -#endif /* defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ +#endif /* defined(CUSTOMER_HW2) */ +static int dhd_device_event(struct notifier_block *this, unsigned long event, + void *ptr); + +static struct notifier_block dhd_notifier = { + .notifier_call = dhd_device_event +}; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) #include @@ -283,7 +319,6 @@ typedef struct dhd_info { int wl_count; int wl_packet; - int hang_was_sent; /* flag that message was send at least once */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) struct mutex wl_start_lock; /* mutex when START called to prevent any other Linux calls */ #endif @@ -313,7 +348,7 @@ struct semaphore dhd_registration_sem; #define DHD_REGISTRATION_TIMEOUT 12000 /* msec : allowed time to finished dhd registration */ #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ /* load firmware and/or nvram values from the filesystem */ -module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0); +module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); /* Error bits */ @@ -764,13 +799,13 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) ASSERT(dhd && dhd->iflist[ifidx]); dev = dhd->iflist[ifidx]->net; - netif_addr_lock_bh(dev); + NETIF_ADDR_LOCK(dev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) cnt = netdev_mc_count(dev); #else cnt = dev->mc_count; #endif - netif_addr_unlock_bh(dev); + NETIF_ADDR_UNLOCK(dev); /* Determine initial value of allmulti flag */ allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; @@ -790,7 +825,7 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) memcpy(bufp, &cnt, sizeof(cnt)); bufp += sizeof(cnt); - netif_addr_lock_bh(dev); + NETIF_ADDR_LOCK(dev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) netdev_for_each_mc_addr(ha, dev) { if (!cnt) @@ -800,12 +835,12 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) cnt--; } #else - for (mclist = dev->mc_list;(mclist && (cnt > 0)); cnt--, mclist = mclist->next) { + for (mclist = dev->mc_list; (mclist && (cnt > 0)); cnt--, mclist = mclist->next) { memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); bufp += ETHER_ADDR_LEN; } #endif - netif_addr_unlock_bh(dev); + NETIF_ADDR_UNLOCK(dev); memset(&ioc, 0, sizeof(ioc)); ioc.cmd = WLC_SET_VAR; @@ -1484,7 +1519,8 @@ dhd_dpc_thread(void *data) dhd_os_wake_unlock(&dhd->pub); } } else { - dhd_bus_stop(dhd->pub.bus, TRUE); + if (dhd->pub.up) + dhd_bus_stop(dhd->pub.bus, TRUE); dhd_os_wake_unlock(&dhd->pub); } } @@ -1742,6 +1778,14 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) dhd_os_wake_lock(&dhd->pub); + /* send to dongle only if we are not waiting for reload already */ + if (dhd->pub.hang_was_sent) { + DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); + dhd_os_wake_lock_timeout_enable(&dhd->pub); + dhd_os_wake_unlock(&dhd->pub); + return OSL_ERROR(BCME_DONGLE_DOWN); + } + ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); @@ -1885,7 +1929,7 @@ dhd_stop(struct net_device *net) #else DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation ...\n", __FUNCTION__)); #endif /* !defined(IGNORE_ETH0_DOWN) */ - + dhd->pub.hang_was_sent = 0; OLD_MOD_DEC_USE_COUNT; return 0; } @@ -1898,6 +1942,15 @@ dhd_open(struct net_device *net) uint32 toe_ol; #endif int ifidx; + int32 ret = 0; + dhd_os_wake_lock(&dhd->pub); + /* Update FW path if it was changed */ + if ((firmware_path != NULL) && (firmware_path[0] != '\0')) { + if (firmware_path[strlen(firmware_path)-1] == '\n') + firmware_path[strlen(firmware_path)-1] = '\0'; + strcpy(fw_path, firmware_path); + firmware_path[0] = '\0'; + } /* Force start if ifconfig_up gets called before START command */ wl_control_wl_start(net); @@ -1905,9 +1958,15 @@ dhd_open(struct net_device *net) ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); + if (ifidx == DHD_BAD_IF) { + ret = -1; + goto exit; + } + if ((dhd->iflist[ifidx]) && (dhd->iflist[ifidx]->state == WLC_E_IF_DEL)) { DHD_ERROR(("%s: Error: called when IF already deleted\n", __FUNCTION__)); - return -1; + ret = -1; + goto exit; } if (ifidx == 0) { /* do it only for primary eth0 */ @@ -1929,7 +1988,9 @@ dhd_open(struct net_device *net) dhd->pub.up = 1; OLD_MOD_INC_USE_COUNT; - return 0; +exit: + dhd_os_wake_unlock(&dhd->pub); + return ret; } osl_t * @@ -2005,6 +2066,7 @@ dhd_del_if(dhd_info_t *dhd, int ifidx) up(&dhd->sysioc_sem); } + dhd_pub_t * dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) { @@ -2147,9 +2209,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) */ memcpy(netdev_priv(net), &dhd, sizeof(dhd)); -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) - g_bus = bus; -#endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) register_pm_notifier(&dhd_sleep_pm_notifier); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ @@ -2161,6 +2220,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) register_early_suspend(&dhd->early_suspend); #endif + register_inetaddr_notifier(&dhd_notifier); + return &dhd->pub; fail: @@ -2186,12 +2247,15 @@ dhd_bus_start(dhd_pub_t *dhdp) DHD_TRACE(("%s: \n", __FUNCTION__)); + dhd_os_sdlock(dhdp); + /* try to download image and nvram to the dongle */ if (dhd->pub.busstate == DHD_BUS_DOWN) { if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, fw_path, nv_path))) { DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", __FUNCTION__, fw_path, nv_path)); + dhd_os_sdunlock(dhdp); return -1; } } @@ -2201,8 +2265,9 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); /* Bring up the bus */ - if ((ret = dhd_bus_init(&dhd->pub, TRUE)) != 0) { + if ((ret = dhd_bus_init(&dhd->pub, FALSE)) != 0) { DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret)); + dhd_os_sdunlock(dhdp); return ret; } #if defined(OOB_INTR_ONLY) @@ -2211,6 +2276,7 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd->wd_timer_valid = FALSE; del_timer_sync(&dhd->timer); DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__)); + dhd_os_sdunlock(dhdp); return -ENODEV; } @@ -2223,9 +2289,12 @@ dhd_bus_start(dhd_pub_t *dhdp) dhd->wd_timer_valid = FALSE; del_timer_sync(&dhd->timer); DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__)); + dhd_os_sdunlock(dhdp); return -ENODEV; } + dhd_os_sdunlock(dhdp); + #ifdef EMBEDDED_PLATFORM bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf)); @@ -2257,9 +2326,12 @@ dhd_bus_start(dhd_pub_t *dhdp) /* enable dongle roaming event */ setbit(dhdp->eventmask, WLC_E_ROAM); - dhdp->pktfilter_count = 1; + dhdp->pktfilter_count = 4; /* Setup filter to allow only unicast */ dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00"; + dhdp->pktfilter[1] = NULL; + dhdp->pktfilter[2] = NULL; + dhdp->pktfilter[3] = NULL; #endif /* EMBEDDED_PLATFORM */ /* Bus is ready, do any protocol initialization */ @@ -2313,6 +2385,48 @@ static struct net_device_ops dhd_ops_virt = { }; #endif +static int dhd_device_event(struct notifier_block *this, unsigned long event, + void *ptr) +{ + struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; + dhd_info_t *dhd; + dhd_pub_t *dhd_pub; + + if (!ifa) + return NOTIFY_DONE; + + dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev); + dhd_pub = &dhd->pub; + +#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 31)) + if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) { +#else + if (ifa->ifa_dev->dev->open == &dhd_open) { +#endif + switch (event) { + case NETDEV_UP: + DHD_TRACE(("%s: [%s] Up IP: 0x%x\n", + __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); + + dhd_arp_cleanup(dhd_pub); + break; + + case NETDEV_DOWN: + DHD_TRACE(("%s: [%s] Down IP: 0x%x\n", + __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); + + dhd_arp_cleanup(dhd_pub); + break; + + default: + DHD_TRACE(("%s: [%s] Event: %lu\n", + __FUNCTION__, ifa->ifa_label, event)); + break; + } + } + return NOTIFY_DONE; +} + int dhd_net_attach(dhd_pub_t *dhdp, int ifidx) { @@ -2386,6 +2500,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2], dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]); + #if defined(CONFIG_WIRELESS_EXT) #if defined(CONFIG_FIRST_SCAN) #ifdef SOFTAP @@ -2451,6 +2566,8 @@ dhd_detach(dhd_pub_t *dhdp) dhd_if_t *ifp; int i; + unregister_inetaddr_notifier(&dhd_notifier); + #if defined(CONFIG_HAS_EARLYSUSPEND) if (dhd->early_suspend.suspend) unregister_early_suspend(&dhd->early_suspend); @@ -2985,6 +3102,35 @@ int net_os_set_dtim_skip(struct net_device *dev, int val) return 0; } +int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + char *filterp = NULL; + int ret = 0; + + if (!dhd || (num == DHD_UNICAST_FILTER_NUM)) + return ret; + if (num >= dhd->pub.pktfilter_count) + return -EINVAL; + if (add_remove) { + switch (num) { + case DHD_BROADCAST_FILTER_NUM: + filterp = "101 0 0 0 0xFFFFFFFFFFFF 0xFFFFFFFFFFFF"; + break; + case DHD_MULTICAST4_FILTER_NUM: + filterp = "102 0 0 0 0xFFFFFF 0x01005E"; + break; + case DHD_MULTICAST6_FILTER_NUM: + filterp = "103 0 0 0 0xFFFF 0x3333"; + break; + default: + return -EINVAL; + } + } + dhd->pub.pktfilter[num] = filterp; + return ret; +} + int net_os_set_packet_filter(struct net_device *dev, int val) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -3038,11 +3184,12 @@ dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled) /* Linux wrapper to call common dhd_pno_set */ int -dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) +dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, + ushort scan_fr, int pno_repeat, int pno_freq_expo_max) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr)); + return (dhd_pno_set(&dhd->pub, ssids_local, nssid, scan_fr, pno_repeat, pno_freq_expo_max)); } /* Linux wrapper to get pno status */ @@ -3062,28 +3209,28 @@ int net_os_send_hang_message(struct net_device *dev) int ret = 0; if (dhd) { - if (!dhd->hang_was_sent) { - dhd->hang_was_sent = 1; + if (!dhd->pub.hang_was_sent) { + dhd->pub.hang_was_sent = 1; ret = wl_iw_send_priv_event(dev, "HANG"); } } return ret; } -void dhd_bus_country_set(struct net_device *dev, char *country_code) +void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); if (dhd && dhd->pub.up) - strncpy(dhd->pub.country_code, country_code, WLC_CNTRY_BUF_SZ); + memcpy(&dhd->pub.dhd_cspec, cspec, sizeof(wl_country_t)); } char *dhd_bus_country_get(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - if (dhd && (dhd->pub.country_code[0] != 0)) - return dhd->pub.country_code; + if (dhd && (dhd->pub.dhd_cspec.ccode[0] != 0)) + return dhd->pub.dhd_cspec.ccode; return NULL; } diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index 1380dd38..e9093e81 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -1281,7 +1281,8 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__)); ret = 0; } else { - DHD_INFO(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__)); + if (!bus->dhd->hang_was_sent) + DHD_ERROR(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__)); ret = -1; } } diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index 00e3cac1..cd66a950 100644 --- a/drivers/net/wireless/bcm4329/include/epivers.h +++ b/drivers/net/wireless/bcm4329/include/epivers.h @@ -33,16 +33,16 @@ #define EPI_RC_NUMBER 248 -#define EPI_INCREMENTAL_NUMBER 20 +#define EPI_INCREMENTAL_NUMBER 23 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 248, 20 +#define EPI_VERSION 4, 218, 248, 23 -#define EPI_VERSION_NUM 0x04daf814 +#define EPI_VERSION_NUM 0x04daf817 -#define EPI_VERSION_STR "4.218.248.20" -#define EPI_ROUTER_VERSION_STR "4.219.248.20" +#define EPI_VERSION_STR "4.218.248.23" +#define EPI_ROUTER_VERSION_STR "4.219.248.23" #endif diff --git a/drivers/net/wireless/bcm4329/include/wlioctl.h b/drivers/net/wireless/bcm4329/include/wlioctl.h index cd7725a7..00c61f10 100644 --- a/drivers/net/wireless/bcm4329/include/wlioctl.h +++ b/drivers/net/wireless/bcm4329/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.1 2010/11/17 03:09:28 Exp $ + * $Id: wlioctl.h,v 1.601.4.15.2.14.2.62.4.3 2011/02/09 23:31:02 Exp $ */ @@ -254,6 +254,11 @@ typedef struct wl_join_params { #define WLC_CNTRY_BUF_SZ 4 +typedef struct wl_country { + char country_abbrev[WLC_CNTRY_BUF_SZ]; + int32 rev; + char ccode[WLC_CNTRY_BUF_SZ]; +} wl_country_t; typedef enum sup_auth_status { @@ -857,7 +862,7 @@ typedef struct wl_ioctl { #define PM_MAX 1 #define PM_FAST 2 -#define LISTEN_INTERVAL 20 +#define LISTEN_INTERVAL 10 #define INTERFERE_NONE 0 #define NON_WLAN 1 @@ -1309,12 +1314,16 @@ enum { #define ENABLE_BKGRD_SCAN_BIT 2 #define IMMEDIATE_SCAN_BIT 3 #define AUTO_CONNECT_BIT 4 +#define ENABLE_BD_SCAN_BIT 5 +#define ENABLE_ADAPTSCAN_BIT 6 #define SORT_CRITERIA_MASK 0x01 #define AUTO_NET_SWITCH_MASK 0x02 #define ENABLE_BKGRD_SCAN_MASK 0x04 #define IMMEDIATE_SCAN_MASK 0x08 #define AUTO_CONNECT_MASK 0x10 +#define ENABLE_BD_SCAN_MASK 0x20 +#define ENABLE_ADAPTSCAN_MASK 0x40 #define PFN_VERSION 1 @@ -1327,6 +1336,8 @@ typedef struct wl_pfn_param { int32 lost_network_timeout; int16 flags; int16 rssi_margin; + int32 repeat_scan; + int32 max_freq_adjust; } wl_pfn_param_t; typedef struct wl_pfn { @@ -1336,14 +1347,12 @@ typedef struct wl_pfn { int32 auth; uint32 wpa_auth; int32 wsec; -#ifdef WLPFN_AUTO_CONNECT - union { - wl_wsec_key_t sec_key; - wsec_pmk_t wpa_sec_key; - } pfn_security; -#endif } wl_pfn_t; +#define PNO_SCAN_MAX_FW 508*1000 +#define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 +#define PNO_SCAN_MIN_FW_SEC 10 + #define TOE_TX_CSUM_OL 0x00000001 #define TOE_RX_CSUM_OL 0x00000002 diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 8460804c..434e584f 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.69 2010/12/21 03:00:08 Exp $ + * $Id: wl_iw.c,v 1.51.4.9.2.6.4.142.4.78 2011/02/11 21:27:52 Exp $ */ @@ -54,6 +54,7 @@ typedef const struct si_pub si_t; #define WL_INFORM(x) #define WL_WSEC(x) #define WL_SCAN(x) +#define WL_PNO(x) #define WL_TRACE_COEX(x) #include @@ -115,10 +116,6 @@ static int g_onoff = G_WLAN_SET_ON; wl_iw_extra_params_t g_wl_iw_params; static struct mutex wl_cache_lock; -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY -static bool use_non_dfs_channels = true; -#endif - extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, char* stringBuf, uint buflen); #include @@ -161,12 +158,13 @@ extern int dhd_wait_pend8021x(struct net_device *dev); #endif static void *g_scan = NULL; -static volatile uint g_scan_specified_ssid; -static wlc_ssid_t g_specific_ssid; +static volatile uint g_scan_specified_ssid; +static wlc_ssid_t g_specific_ssid; static wlc_ssid_t g_ssid; -static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl; +bool btcoex_is_sco_active(struct net_device *dev); +static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl; #if defined(CONFIG_FIRST_SCAN) static volatile uint g_first_broadcast_scan; static volatile uint g_first_counter_scans; @@ -594,6 +592,36 @@ wl_iw_set_passive_scan( return error; } + +static int +wl_iw_set_txpower( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int error = 0; + char *p = extra; + int txpower = -1; + + txpower = bcm_atoi(extra + strlen(TXPOWER_SET_CMD) + 1); + if ((txpower >= 0) && (txpower <= 127)) { + txpower |= WL_TXPWR_OVERRIDE; + txpower = htod32(txpower); + + error = dev_wlc_intvar_set(dev, "qtxpower", txpower); + p += snprintf(p, MAX_WX_STRING, "OK"); + WL_TRACE(("%s: set TXpower 0x%X is OK\n", __FUNCTION__, txpower)); + } else { + WL_ERROR(("%s: set tx power failed\n", __FUNCTION__)); + p += snprintf(p, MAX_WX_STRING, "FAIL"); + } + + wrqu->data.length = p - extra + 1; + return error; +} + static int wl_iw_get_macaddr( struct net_device *dev, @@ -619,31 +647,6 @@ wl_iw_get_macaddr( return error; } -static int -wl_iw_set_country_code(struct net_device *dev, char *ccode) -{ - char country_code[WLC_CNTRY_BUF_SZ]; - int ret = -1; - - WL_TRACE(("%s\n", __FUNCTION__)); - if (!ccode) - ccode = dhd_bus_country_get(dev); - strncpy(country_code, ccode, sizeof(country_code)); - if (ccode && (country_code[0] != 0)) { -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY - if (use_non_dfs_channels && !strncmp(country_code, "US", 2)) - strncpy(country_code, "Q2", WLC_CNTRY_BUF_SZ); - if (!use_non_dfs_channels && !strncmp(country_code, "Q2", 2)) - strncpy(country_code, "US", WLC_CNTRY_BUF_SZ); -#endif - ret = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, &country_code, sizeof(country_code)); - if (ret >= 0) { - WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code)); - dhd_bus_country_set(dev, &country_code[0]); - } - } - return ret; -} static int wl_iw_set_country( @@ -658,25 +661,39 @@ wl_iw_set_country( char *p = extra; int country_offset; int country_code_size; + wl_country_t cspec = {{0}, 0, {0}}; + char smbuf[WLC_IOCTL_SMLEN]; - WL_TRACE(("%s\n", __FUNCTION__)); + cspec.rev = -1; memset(country_code, 0, sizeof(country_code)); + memset(smbuf, 0, sizeof(smbuf)); country_offset = strcspn(extra, " "); country_code_size = strlen(extra) - country_offset; if (country_offset != 0) { - strncpy(country_code, extra + country_offset + 1, + strncpy(country_code, extra + country_offset +1, MIN(country_code_size, sizeof(country_code))); - error = wl_iw_set_country_code(dev, country_code); - if (error >= 0) { + + + memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ); + memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ); + + get_customized_country_code((char *)&cspec.country_abbrev, &cspec); + + if ((error = dev_iw_iovar_setbuf(dev, "country", &cspec, \ + sizeof(cspec), smbuf, sizeof(smbuf))) >= 0) { p += snprintf(p, MAX_WX_STRING, "OK"); - WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code)); + WL_ERROR(("%s: set country for %s as %s rev %d is OK\n", \ + __FUNCTION__, country_code, cspec.ccode, cspec.rev)); + dhd_bus_country_set(dev, &cspec); goto exit; } } - WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error)); + WL_ERROR(("%s: set country for %s as %s rev %d failed\n", \ + __FUNCTION__, country_code, cspec.ccode, cspec.rev)); + p += snprintf(p, MAX_WX_STRING, "FAIL"); exit: @@ -738,26 +755,40 @@ wl_iw_set_power_mode( #endif -static bool btcoex_is_sco_active(struct net_device *dev) +bool btcoex_is_sco_active(struct net_device *dev) { int ioc_res = 0; bool res = false; - int temp = 0; + int sco_id_cnt = 0; + int param27; + int i; - ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 4, &temp); + for (i = 0; i < 12; i++) { - if (ioc_res == 0) { - WL_TRACE_COEX(("%s: read btc_params[4] = %x\n", __FUNCTION__, temp)); + ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); - if ((temp > 0xea0) && (temp < 0xed8)) { - WL_TRACE_COEX(("%s: BT SCO/eSCO is ACTIVE\n", __FUNCTION__)); - res = true; - } else { - WL_TRACE_COEX(("%s: BT SCO/eSCO is NOT detected\n", __FUNCTION__)); + WL_TRACE_COEX(("%s, sample[%d], btc params: 27:%x\n", + __FUNCTION__, i, param27)); + + if (ioc_res < 0) { + WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__)); + break; } - } else { - WL_ERROR(("%s ioc read btc params error\n", __FUNCTION__)); + + if ((param27 & 0x6) == 2) { + sco_id_cnt++; + } + + if (sco_id_cnt > 2) { + WL_TRACE_COEX(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", + __FUNCTION__, sco_id_cnt, i)); + res = true; + break; + } + + msleep(5); } + return res; } @@ -1043,21 +1074,6 @@ wl_iw_set_suspend( return ret; } -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY -static int -wl_iw_set_dfs_channels( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - use_non_dfs_channels = *(extra + strlen(SETDFSCHANNELS_CMD) + 1) - '0'; - use_non_dfs_channels = (use_non_dfs_channels != 0) ? false : true; - wl_iw_set_country_code(dev, NULL); - return 0; -} -#endif int wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) @@ -1343,9 +1359,10 @@ wl_iw_set_pno_set( int nssid = 0; cmd_tlv_t *cmd_tlv_temp; char *str_ptr; - char *str_ptr_end; int tlv_size_left; int pno_time; + int pno_repeat; + int pno_freq_expo_max; #ifdef PNO_SET_DEBUG int i; @@ -1359,6 +1376,10 @@ wl_iw_set_pno_set( 'G', 'O', 'O', 'G', 'T', '1','E', + 'R', + '2', + 'M', + '2', 0x00 }; #endif @@ -1402,6 +1423,7 @@ wl_iw_set_pno_set( cmd_tlv_temp = (cmd_tlv_t *)str_ptr; memset(ssids_local, 0, sizeof(ssids_local)); + pno_repeat = pno_freq_expo_max = 0; if ((cmd_tlv_temp->prefix == PNO_TLV_PREFIX) && \ (cmd_tlv_temp->version == PNO_TLV_VERSION) && \ @@ -1422,9 +1444,28 @@ wl_iw_set_pno_set( goto exit_proc; } str_ptr++; - pno_time = simple_strtoul(str_ptr, &str_ptr_end, 16); - WL_ERROR((" got %d bytes left pno_time %d or %#x\n", \ - tlv_size_left, pno_time, pno_time)); + pno_time = simple_strtoul(str_ptr, &str_ptr, 16); + WL_PNO(("%s: pno_time=%d\n", __FUNCTION__, pno_time)); + + if (str_ptr[0] != 0) { + if ((str_ptr[0] != PNO_TLV_FREQ_REPEAT)) { + WL_ERROR(("%s pno repeat : corrupted field\n", \ + __FUNCTION__)); + goto exit_proc; + } + str_ptr++; + pno_repeat = simple_strtoul(str_ptr, &str_ptr, 16); + WL_PNO(("%s :got pno_repeat=%d\n", __FUNCTION__, pno_repeat)); + if (str_ptr[0] != PNO_TLV_FREQ_EXPO_MAX) { + WL_ERROR(("%s FREQ_EXPO_MAX corrupted field size\n", \ + __FUNCTION__)); + goto exit_proc; + } + str_ptr++; + pno_freq_expo_max = simple_strtoul(str_ptr, &str_ptr, 16); + WL_PNO(("%s: pno_freq_expo_max=%d\n", \ + __FUNCTION__, pno_freq_expo_max)); + } } } else { @@ -1432,7 +1473,7 @@ wl_iw_set_pno_set( goto exit_proc; } - res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time); + res = dhd_dev_pno_set(dev, ssids_local, nssid, pno_time, pno_repeat, pno_freq_expo_max); exit_proc: net_os_wake_unlock(dev); @@ -1719,6 +1760,79 @@ int hstr_2_buf(const char *txt, u8 *buf, int len) return 0; } +#if defined(SOFTAP) && defined(SOFTAP_TLV_CFG) + +static int wl_iw_softap_cfg_tlv( + struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, + char *extra +) +{ + int res = -1; + char *str_ptr; + int tlv_size_left; + + +#define SOFTAP_TLV_DEBUG 1 +#ifdef SOFTAP_TLV_DEBUG +char softap_cmd_example[] = { + + 'S', 'O', 'F', 'T', 'A', 'P', 'S', 'E', 'T', ' ', + + SOFTAP_TLV_PREFIX, SOFTAP_TLV_VERSION, + SOFTAP_TLV_SUBVERSION, SOFTAP_TLV_RESERVED, + + TLV_TYPE_SSID, 9, 'B', 'R', 'C', 'M', ',', 'G', 'O', 'O', 'G', + + TLV_TYPE_SECUR, 4, 'O', 'P', 'E', 'N', + + TLV_TYPE_KEY, 4, 0x31, 0x32, 0x33, 0x34, + + TLV_TYPE_CHANNEL, 4, 0x06, 0x00, 0x00, 0x00 +}; +#endif + + +#ifdef SOFTAP_TLV_DEBUG + { + int i; + if (!(extra = kmalloc(sizeof(softap_cmd_example) +10, GFP_KERNEL))) + return -ENOMEM; + memcpy(extra, softap_cmd_example, sizeof(softap_cmd_example)); + wrqu->data.length = sizeof(softap_cmd_example); + print_buf(extra, wrqu->data.length, 16); + for (i = 0; i < wrqu->data.length; i++) + printf("%c ", extra[i]); + printf("\n"); + } +#endif + + WL_ERROR(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", + __FUNCTION__, info->cmd, info->flags, + wrqu->data.pointer, wrqu->data.length)); + + if (g_onoff == G_WLAN_SET_OFF) { + WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); + return -1; + } + + if (wrqu->data.length < (strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t))) { + WL_ERROR(("%s argument=%d less %d\n", __FUNCTION__, + wrqu->data.length, strlen(SOFTAP_SET_CMD) + sizeof(cmd_tlv_t))); + return -1; + } + + str_ptr = extra + strlen(SOFTAP_SET_CMD)+1; + tlv_size_left = wrqu->data.length - (strlen(SOFTAP_SET_CMD)+1); + + memset(&my_ap, 0, sizeof(my_ap)); + + return res; +} +#endif + + #ifdef SOFTAP int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) { @@ -3686,6 +3800,7 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1); wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len); event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf); + kfree(buf); #endif break; } @@ -5727,7 +5842,7 @@ wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nss WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type)); WL_SCAN(("\n###################\n")); } -#endif +#endif if (params_size > WLC_IOCTL_MEDLEN) { WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \ @@ -5767,6 +5882,11 @@ static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info return -1; } +#ifdef PNO_SET_DEBUG + wl_iw_set_pno_set(dev, info, wrqu, extra); + return 0; +#endif + if (wrqu->data.length != 0) { char *str_ptr; @@ -6294,16 +6414,8 @@ static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) } if (strlen(ap->country_code)) { - int error = 0; - if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, - ap->country_code, sizeof(ap->country_code))) >= 0) { - WL_SOFTAP(("%s: set country %s OK\n", - __FUNCTION__, ap->country_code)); - dhd_bus_country_set(dev, &ap->country_code[0]); - } else { - WL_ERROR(("%s: ERROR:%d setting country %s\n", - __FUNCTION__, error, ap->country_code)); - } + WL_ERROR(("%s: Igonored: Country MUST be specified \ + COUNTRY command with \n", __FUNCTION__)); } else { WL_SOFTAP(("%s: Country code is not specified," " will use Radio's default\n", @@ -7113,10 +7225,8 @@ static int wl_iw_set_priv( ret = wl_iw_set_dtim_skip(dev, info, (union iwreq_data *)dwrq, extra); else if (strnicmp(extra, SETSUSPEND_CMD, strlen(SETSUSPEND_CMD)) == 0) ret = wl_iw_set_suspend(dev, info, (union iwreq_data *)dwrq, extra); -#ifdef CONFIG_US_NON_DFS_CHANNELS_ONLY - else if (strnicmp(extra, SETDFSCHANNELS_CMD, strlen(SETDFSCHANNELS_CMD)) == 0) - ret = wl_iw_set_dfs_channels(dev, info, (union iwreq_data *)dwrq, extra); -#endif + else if (strnicmp(extra, TXPOWER_SET_CMD, strlen(TXPOWER_SET_CMD)) == 0) + ret = wl_iw_set_txpower(dev, info, (union iwreq_data *)dwrq, extra); #if defined(PNO_SUPPORT) else if (strnicmp(extra, PNOSSIDCLR_SET_CMD, strlen(PNOSSIDCLR_SET_CMD)) == 0) ret = wl_iw_set_pno_reset(dev, info, (union iwreq_data *)dwrq, extra); @@ -7126,21 +7236,40 @@ static int wl_iw_set_priv( ret = wl_iw_set_pno_enable(dev, info, (union iwreq_data *)dwrq, extra); #endif #if defined(CSCAN) - else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0) + else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0) ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra); -#endif +#endif #ifdef CUSTOMER_HW2 else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) + else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) { + WL_TRACE_COEX(("%s:got Framwrork cmd: 'BTCOEXMODE'\n", __FUNCTION__)); ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); + } #else else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); #endif else if (strnicmp(extra, "GETPOWER", strlen("GETPOWER")) == 0) ret = wl_iw_get_power_mode(dev, info, (union iwreq_data *)dwrq, extra); + else if (strnicmp(extra, RXFILTER_START_CMD, strlen(RXFILTER_START_CMD)) == 0) + ret = net_os_set_packet_filter(dev, 1); + else if (strnicmp(extra, RXFILTER_STOP_CMD, strlen(RXFILTER_STOP_CMD)) == 0) + ret = net_os_set_packet_filter(dev, 0); + else if (strnicmp(extra, RXFILTER_ADD_CMD, strlen(RXFILTER_ADD_CMD)) == 0) { + int filter_num = *(extra + strlen(RXFILTER_ADD_CMD) + 1) - '0'; + ret = net_os_rxfilter_add_remove(dev, TRUE, filter_num); + } + else if (strnicmp(extra, RXFILTER_REMOVE_CMD, strlen(RXFILTER_REMOVE_CMD)) == 0) { + int filter_num = *(extra + strlen(RXFILTER_REMOVE_CMD) + 1) - '0'; + ret = net_os_rxfilter_add_remove(dev, FALSE, filter_num); + } #ifdef SOFTAP +#ifdef SOFTAP_TLV_CFG + else if (strnicmp(extra, SOFTAP_SET_CMD, strlen(SOFTAP_SET_CMD)) == 0) { + wl_iw_softap_cfg_tlv(dev, info, (union iwreq_data *)dwrq, extra); + } +#endif else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) { wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra); } else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) { @@ -7661,9 +7790,10 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) uint32 datalen = ntoh32(e->datalen); uint32 status = ntoh32(e->status); uint32 toto; +#if defined(ROAM_NOT_USED) static uint32 roam_no_success = 0; static bool roam_no_success_send = FALSE; - +#endif memset(&wrqu, 0, sizeof(wrqu)); memset(extra, 0, sizeof(extra)); @@ -7734,10 +7864,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) break; case WLC_E_ROAM: if (status == WLC_E_STATUS_SUCCESS) { - memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - cmd = SIOCGIWAP; + WL_ASSOC(("%s: WLC_E_ROAM: success\n", __FUNCTION__)); +#if defined(ROAM_NOT_USED) + roam_no_success_send = FALSE; + roam_no_success = 0; +#endif + goto wl_iw_event_end; } +#if defined(ROAM_NOT_USED) else if (status == WLC_E_STATUS_NO_NETWORKS) { roam_no_success++; if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) { @@ -7752,6 +7886,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) goto wl_iw_event_end; } } +#endif break; case WLC_E_DEAUTH_IND: case WLC_E_DISASSOC_IND: @@ -7807,8 +7942,10 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) wl_iw_send_priv_event(priv_dev, "AP_UP"); } else { WL_TRACE(("STA_LINK_UP\n")); +#if defined(ROAM_NOT_USED) roam_no_success_send = FALSE; roam_no_success = 0; +#endif } #endif WL_TRACE(("Link UP\n")); @@ -7936,7 +8073,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) #endif #if WIRELESS_EXT > 14 - memset(extra, 0, sizeof(extra)); if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) { cmd = IWEVCUSTOM; diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index 928291fe..ee6c6999 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ b/drivers/net/wireless/bcm4329/wl_iw.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.h,v 1.5.34.1.6.36.4.15 2010/11/17 03:13:51 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.6.36.4.18 2011/02/10 19:33:12 Exp $ */ @@ -52,7 +52,11 @@ #define PNOSETUP_SET_CMD "PNOSETUP " #define PNOENABLE_SET_CMD "PNOFORCE" #define PNODEBUG_SET_CMD "PNODEBUG" -#define SETDFSCHANNELS_CMD "SETDFSCHANNELS" +#define TXPOWER_SET_CMD "TXPOWER" +#define RXFILTER_START_CMD "RXFILTER-START" +#define RXFILTER_STOP_CMD "RXFILTER-STOP" +#define RXFILTER_ADD_CMD "RXFILTER-ADD" +#define RXFILTER_REMOVE_CMD "RXFILTER-REMOVE" #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" @@ -62,6 +66,12 @@ typedef struct wl_iw_extra_params { int target_channel; } wl_iw_extra_params_t; +struct cntry_locales_custom { + char iso_abbrev[WLC_CNTRY_BUF_SZ]; + char custom_locale[WLC_CNTRY_BUF_SZ]; + int32 custom_locale_rev; +}; + #define WL_IW_RSSI_MINVAL -200 #define WL_IW_RSSI_NO_SIGNAL -91 #define WL_IW_RSSI_VERY_LOW -80 @@ -133,13 +143,13 @@ typedef struct wl_iw_ss_cache { } wl_iw_ss_cache_t; typedef struct wl_iw_ss_cache_ctrl { - wl_iw_ss_cache_t *m_cache_head; - int m_link_down; - int m_timer_expired; - char m_active_bssid[ETHER_ADDR_LEN]; - uint m_prev_scan_mode; - uint m_cons_br_scan_cnt; - struct timer_list *m_timer; + wl_iw_ss_cache_t *m_cache_head; + int m_link_down; + int m_timer_expired; + char m_active_bssid[ETHER_ADDR_LEN]; + uint m_prev_scan_mode; + uint m_cons_br_scan_cnt; + struct timer_list *m_timer; } wl_iw_ss_cache_ctrl_t; typedef enum broadcast_first_scan { @@ -165,7 +175,7 @@ struct ap_profile { }; -#define MACLIST_MODE_DISABLED 0 +#define MACLIST_MODE_DISABLED 0 #define MACLIST_MODE_DENY 1 #define MACLIST_MODE_ALLOW 2 struct mflist { @@ -198,8 +208,7 @@ extern int net_os_wake_lock_timeout_enable(struct net_device *dev); extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val); extern int net_os_set_dtim_skip(struct net_device *dev, int val); -extern int net_os_set_packet_filter(struct net_device *dev, int val); -extern void dhd_bus_country_set(struct net_device *dev, char *country_code); +extern void get_customized_country_code(char *country_iso_code, wl_country_t *cspec); extern char *dhd_bus_country_get(struct net_device *dev); extern int dhd_get_dtim_skip(dhd_pub_t *dhd); @@ -221,13 +230,15 @@ extern int dhd_get_dtim_skip(dhd_pub_t *dhd); extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); extern int dhd_pno_clean(dhd_pub_t *dhd); -extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr); +extern int dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, \ + ushort scan_fr, int pno_repeat, int pno_freq_expo_max); extern int dhd_pno_get_status(dhd_pub_t *dhd); extern int dhd_dev_pno_reset(struct net_device *dev); extern int dhd_dev_pno_set(struct net_device *dev, wlc_ssid_t* ssids_local, \ - int nssid, ushort scan_fr); + int nssid, ushort scan_fr, int pno_repeat, int pno_freq_expo_max); extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); +extern void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec); #define PNO_TLV_PREFIX 'S' #define PNO_TLV_VERSION '1' @@ -235,8 +246,9 @@ extern int dhd_dev_get_pno_status(struct net_device *dev); #define PNO_TLV_RESERVED '0' #define PNO_TLV_TYPE_SSID_IE 'S' #define PNO_TLV_TYPE_TIME 'T' -#define PNO_EVENT_UP "PNO_EVENT" -#define PNO_SCAN_MAX_FW 508 +#define PNO_TLV_FREQ_REPEAT 'R' +#define PNO_TLV_FREQ_EXPO_MAX 'M' +#define PNO_EVENT_UP "PNO_EVENT" typedef struct cmd_tlv { char prefix; @@ -245,6 +257,19 @@ typedef struct cmd_tlv { char reserved; } cmd_tlv_t; +#ifdef SOFTAP_TLV_CFG +#define SOFTAP_SET_CMD "SOFTAPSET " +#define SOFTAP_TLV_PREFIX 'A' +#define SOFTAP_TLV_VERSION '1' +#define SOFTAP_TLV_SUBVERSION '0' +#define SOFTAP_TLV_RESERVED '0' + +#define TLV_TYPE_SSID 'S' +#define TLV_TYPE_SECUR 'E' +#define TLV_TYPE_KEY 'K' +#define TLV_TYPE_CHANNEL 'C' +#endif + #if defined(CSCAN) typedef struct cscan_tlv { @@ -279,6 +304,6 @@ extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num); -#endif +#endif -#endif +#endif diff --git a/include/linux/wireless.h b/include/linux/wireless.h index 5b4c6c77..e6827eed 100644 --- a/include/linux/wireless.h +++ b/include/linux/wireless.h @@ -346,6 +346,8 @@ #define SIOCIWFIRST 0x8B00 #define SIOCIWLAST SIOCIWLASTPRIV /* 0x8BFF */ #define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) +#define IW_HANDLER(id, func) \ + [IW_IOCTL_IDX(id)] = func /* Odd : get (world access), even : set (root access) */ #define IW_IS_SET(cmd) (!((cmd) & 0x1)) @@ -648,7 +650,7 @@ * 32 bit bitmasks. Note : 32 bits = 0x20 = 2^5. */ #define IW_EVENT_CAPA_BASE(cmd) ((cmd >= SIOCIWFIRSTPRIV) ? \ (cmd - SIOCIWFIRSTPRIV + 0x60) : \ - (cmd - SIOCSIWCOMMIT)) + (cmd - SIOCIWFIRST)) #define IW_EVENT_CAPA_INDEX(cmd) (IW_EVENT_CAPA_BASE(cmd) >> 5) #define IW_EVENT_CAPA_MASK(cmd) (1 << (IW_EVENT_CAPA_BASE(cmd) & 0x1F)) /* Event capability constants - event autogenerated by the kernel diff --git a/include/linux/wlan_plat.h b/include/linux/wlan_plat.h index 3b1e2e05..40ec3482 100644 --- a/include/linux/wlan_plat.h +++ b/include/linux/wlan_plat.h @@ -21,6 +21,7 @@ struct wifi_platform_data { int (*set_carddetect)(int val); void *(*mem_prealloc)(int section, unsigned long size); int (*get_mac_addr)(unsigned char *buf); + void *(*get_country_code)(char *ccode); }; #endif