From 3ddaed49e7423e8b9aeeff01bdf2b055f353fc55 Mon Sep 17 00:00:00 2001 From: Greg Goldman Date: Mon, 7 Jun 2010 14:48:42 -0700 Subject: [PATCH] network: wireless: bcm4329: Update to Version 4.218.239 Add reading mac address from platform data Add dhd_os_proto_block protection for dhd_preinit_ioctls Revert dhdsdio_clk() changes Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/dhd.h | 3 +- drivers/net/wireless/bcm4329/dhd_cdc.c | 5 +- drivers/net/wireless/bcm4329/dhd_common.c | 8 +- .../net/wireless/bcm4329/dhd_custom_gpio.c | 55 +++- drivers/net/wireless/bcm4329/dhd_sdio.c | 13 +- .../net/wireless/bcm4329/include/epivers.h | 10 +- drivers/net/wireless/bcm4329/wl_iw.c | 244 +++++++++++++++++- drivers/net/wireless/bcm4329/wl_iw.h | 11 +- 8 files changed, 322 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index a6c9ba3d6683..005681eb6bbe 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.43 2010/05/18 05:48:53 Exp $ + * $Id: dhd.h,v 1.32.4.7.2.4.14.44 2010/06/03 21:27:48 Exp $ */ /**************** @@ -273,6 +273,7 @@ extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_customer_gpio_wlan_ctrl(int onoff); +extern int dhd_custom_get_mac_address(unsigned char *buf); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); diff --git a/drivers/net/wireless/bcm4329/dhd_cdc.c b/drivers/net/wireless/bcm4329/dhd_cdc.c index f091e797a92e..464aaf5033dd 100644 --- a/drivers/net/wireless/bcm4329/dhd_cdc.c +++ b/drivers/net/wireless/bcm4329/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.36 2010/04/14 12:09:11 Exp $ + * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.39 2010/06/04 19:08:09 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 @@ -529,6 +529,8 @@ dhd_prot_init(dhd_pub_t *dhd) } memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); + dhd_os_proto_unblock(dhd); + #ifdef EMBEDDED_PLATFORM ret = dhd_preinit_ioctls(dhd); #endif /* EMBEDDED_PLATFORM */ @@ -537,7 +539,6 @@ dhd_prot_init(dhd_pub_t *dhd) dhd->iswl = TRUE; fail: - dhd_os_proto_unblock(dhd); return ret; } diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c index 033498453581..652cf291de2b 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.60 2010/05/26 03:36:55 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.62 2010/06/04 19:08:13 Exp $ */ #include #include @@ -1244,6 +1244,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) struct ether_addr ea_addr; #endif /* GET_CUSTOM_MAC_ENABLE */ + dhd_os_proto_block(dhd); + #ifdef GET_CUSTOM_MAC_ENABLE /* ** Read MAC address from external customer place @@ -1251,7 +1253,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) ** to bring up firmware but unique per board mac address maybe provided ** by customer code */ - ret = wifi_get_mac_addr(ea_addr.octet); + ret = dhd_custom_get_mac_address(ea_addr.octet); if (!ret) { bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf)); @@ -1333,6 +1335,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* PKT_FILTER_SUPPORT */ + dhd_os_proto_unblock(dhd); + return 0; } diff --git a/drivers/net/wireless/bcm4329/dhd_custom_gpio.c b/drivers/net/wireless/bcm4329/dhd_custom_gpio.c index 2dc6e42afd45..ade5e5a27131 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.6 2010/02/19 22:56:49 Exp $ +* $Id: dhd_custom_gpio.c,v 1.1.4.7 2010/06/03 21:27:48 Exp $ */ @@ -42,11 +42,11 @@ extern void bcm_wlan_power_off(int); extern void bcm_wlan_power_on(int); #endif /* CUSTOMER_HW */ - #ifdef CUSTOMER_HW2 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); #endif #if defined(OOB_INTR_ONLY) @@ -55,6 +55,10 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr); extern int sdioh_mmc_irq(int irq); #endif /* (BCMLXSDMMC) */ +#ifdef CUSTOMER_HW3 +#include +#endif + /* Customer specific Host GPIO defintion */ static int dhd_oob_gpio_num = -1; /* GG 19 */ @@ -63,10 +67,12 @@ MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number"); int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr) { - int host_oob_irq; + int host_oob_irq = 0; + #ifdef CUSTOMER_HW2 host_oob_irq = wifi_get_irq_number(irq_flags_ptr); -#else + +#else /* for NOT CUSTOMER_HW2 */ #if defined(CUSTOM_OOB_GPIO_NUM) if (dhd_oob_gpio_num < 0) { dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM; @@ -75,15 +81,22 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr) *irq_flags_ptr = IRQF_TRIGGER_FALLING; if (dhd_oob_gpio_num < 0) { WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n", - __FUNCTION__)); + __FUNCTION__)); return (dhd_oob_gpio_num); } WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", __FUNCTION__, dhd_oob_gpio_num)); - host_oob_irq = sdioh_mmc_irq(dhd_oob_gpio_num); -#endif +#if defined CUSTOMER_HW + host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num); +#elif defined CUSTOMER_HW3 + gpio_request(dhd_oob_gpio_num, "oob irq"); + host_oob_irq = gpio_to_irq(dhd_oob_gpio_num); + gpio_direction_input(dhd_oob_gpio_num); +#endif /* CUSTOMER_HW */ +#endif /* CUSTOMER_HW2 */ + return (host_oob_irq); } #endif /* defined(OOB_INTR_ONLY) */ @@ -136,3 +149,31 @@ dhd_customer_gpio_wlan_ctrl(int onoff) break; } } + +#ifdef GET_CUSTOM_MAC_ENABLE +/* Function to get custom MAC address */ +int +dhd_custom_get_mac_address(unsigned char *buf) +{ + int ret = 0; + + WL_TRACE(("%s Enter\n", __FUNCTION__)); + if (!buf) + return -EINVAL; + + /* Customer access to MAC address stored outside of DHD driver */ +#ifdef CUSTOMER_HW2 + ret = wifi_get_mac_addr(buf); +#endif + +#ifdef EXAMPLE_GET_MAC + /* EXAMPLE code */ + { + struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; + bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); + } +#endif /* EXAMPLE_GET_MAC */ + + return ret; +} +#endif /* GET_CUSTOM_MAC_ENABLE */ diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index e41c8ef8d7f8..e5a05a7d5cec 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.123 2010/05/18 05:48:53 Exp $ + * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.125 2010/06/04 02:52:15 Exp $ */ #include @@ -1072,7 +1072,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) /* Check for existing queue, current flow-control, pending event, or pending clock */ if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || - (bus->clkstate == CLK_PENDING)) { + (bus->clkstate != CLK_AVAIL)) { DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq))); bus->fcqueued++; @@ -1109,7 +1109,7 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) /* Otherwise, send it now */ BUS_WAKE(bus); /* Make sure back plane ht clk is on, no pending allowed */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); #ifndef SDTEST DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__)); @@ -4137,10 +4137,8 @@ dhdsdio_dpc(dhd_bus_t *bus) BUS_WAKE(bus); - /* Make sure backplane clock is on, no pending, - * waste of cycle to wait for the next schedule to send - */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + /* Make sure backplane clock is on */ + dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); if (bus->clkstate == CLK_PENDING) goto clkwait; @@ -4289,6 +4287,7 @@ clkwait: } else if (bus->clkstate == CLK_PENDING) { DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \ I_CHIPACTIVE interrupt", __FUNCTION__)); + resched = TRUE; } else if (bus->intstatus || bus->ipend || (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) || PKT_AVAILABLE()) { /* Read multiple frames */ diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index f27fcc5832b6..1453361cb757 100644 --- a/drivers/net/wireless/bcm4329/include/epivers.h +++ b/drivers/net/wireless/bcm4329/include/epivers.h @@ -31,18 +31,18 @@ #define EPI_MINOR_VERSION 218 -#define EPI_RC_NUMBER 238 +#define EPI_RC_NUMBER 239 #define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 238, 0 +#define EPI_VERSION 4, 218, 239, 0 -#define EPI_VERSION_NUM 0x04daee00 +#define EPI_VERSION_NUM 0x04daef00 -#define EPI_VERSION_STR "4.218.238.0" -#define EPI_ROUTER_VERSION_STR "4.219.238.0" +#define EPI_VERSION_STR "4.218.239.0" +#define EPI_ROUTER_VERSION_STR "4.219.239.0" #endif diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 7ccee377fe01..bccf9691a961 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -4779,6 +4779,239 @@ int get_user_params(char *user_params, struct iw_point *dwrq) } +#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) + +static int +wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) +{ + int num; + int val; + char* str; + char* endptr = NULL; + + if ((list_str == NULL)||(*list_str == NULL)) + return -1; + + str = *list_str; + num = 0; + while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { + val = (int)strtoul(str, &endptr, 0); + if (endptr == str) { + printf("could not parse channel number starting at" + " substring \"%s\" in list:\n%s\n", + str, *list_str); + return -1; + } + str = endptr + strspn(endptr, " ,"); + + if (num == channel_num) { + printf("too many channels (more than %d) in channel list:\n%s\n", + channel_num, *list_str); + return -1; + } + + channel_list[num++] = (uint16)val; + } + *list_str = str; + return num; +} + + + +static int +wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) +{ + char* str, *ptr; + + if ((list_str == NULL) || (*list_str == NULL)) + return -1; + + for (str = *list_str; str != NULL; str = ptr) { + + if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { + *list_str = str + strlen(GET_CHANNEL); + return idx; + } + + if ((ptr = strchr(str, ',')) != NULL) { + *ptr++ = '\0'; + } + + if (strlen(str) > DOT11_MAX_SSID_LEN) { + printf("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN); + return -1; + } + + if (strlen(str) == 0) + ssid[idx].SSID_len = 0; + + if (idx < max) { + strcpy((char*)ssid[idx].SSID, str); + ssid[idx].SSID_len = strlen(str); + } + idx++; + } + return idx; +} + + +static int +wl_iw_combined_scan_set(struct net_device *dev, wl_scan_params_t *params, \ +wlc_ssid_t* ssids_local, int nssid, int nchan) +{ + int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); + int err = 0; + char *p; + int i; + + WL_TRACE(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan)); + + params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); + + if (nssid > 0) { + i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16); + i = ROUNDUP(i, sizeof(uint32)); + if (i + nssid * sizeof(wlc_ssid_t) > params_size) { + printf("additional ssids exceed params_size\n"); + err = -1; + goto exit; + } + + p = (char*)params + i; + memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t)); + p += nssid * sizeof(wlc_ssid_t); + } else { + p = (char*)params->channel_list + nchan * sizeof(uint16); + } + + params->channel_num = htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \ + (nchan & WL_SCAN_PARAMS_COUNT_MASK)); + + params_size = (int) (p - (char*)params + nssid * sizeof(wlc_ssid_t)); + +#define SCAN_DUMP 1 +#ifdef SCAN_DUMP + printf("\n### List of SSIDs to scan ###\n"); + for (i = 0; i < nssid; i++) { + if (!ssids_local[i].SSID_len) + printf("%d: Broadcast scan\n", i); + else + printf("%d: scan for %s size =%d\n", i, \ + ssids_local[i].SSID, ssids_local[i].SSID_len); + } + printf("### List of channels to scan ###\n"); + for (i = 0; i < nchan; i++) + { + printf("%d ", params->channel_list[i]); + } + printf("\nnprobes=%d\n", params->nprobes); + printf("active_time=%d\n", params->active_time); + printf("passive_time=%d\n", params->passive_time); + printf("home_time=%d\n", params->home_time); + printf("\n###################\n"); +#endif + + if ((err = dev_wlc_ioctl(dev, WLC_SCAN, params, params_size))) { + WL_TRACE(("Set SCAN for %s failed with %d\n", __FUNCTION__, error)); + err = -1; + } + +exit: + + return err; +} + + +static int iwpriv_set_scan(struct net_device *dev, struct iw_request_info *info, \ + union iwreq_data *wrqu, char *ext) +{ + int res = 0; + char *extra = NULL; + wl_scan_params_t *params; + int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); + wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; + int nssid = 0; + int nchan = 0; + + WL_TRACE(("\%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 (wrqu->data.length != 0) { + + char *str_ptr; + + if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL))) + return -ENOMEM; + + if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) { + kfree(extra); + return -EFAULT; + } + + extra[wrqu->data.length] = 0; + WL_ERROR(("Got str param in iw_point:\n %s\n", extra)); + + str_ptr = extra; + + if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) { + WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__)); + goto exit_proc; + } + str_ptr += strlen(GET_SSID); + nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \ + WL_SCAN_PARAMS_SSID_MAX); + if (nssid == -1) { + WL_ERROR(("%s wrong ssid list", __FUNCTION__)); + return -1; + } + + params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); + + params = (wl_scan_params_t*)kmalloc(params_size, GFP_KERNEL); + if (params == NULL) { + WL_ERROR(("%s Failed allocate %d bytes \n", __FUNCTION__, params_size)); + return -ENOMEM; + } + memset(params, 0, params_size); + ASSERT(params_size < WLC_IOCTL_MAXLEN); + + wl_iw_iscan_prep(params, NULL); + + if ((nchan = wl_iw_parse_channel_list(&str_ptr, params->channel_list, \ + WL_NUMCHANNELS)) == -1) { + WL_ERROR(("%s missing channel list\n", __FUNCTION__)); + return -1; + } + + get_parmeter_from_string(&str_ptr, \ + GET_NPROBE, PTYPE_INTDEC, ¶ms->nprobes, 2); + + get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, \ + PTYPE_INTDEC, ¶ms->active_time, 3); + + get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, \ + PTYPE_INTDEC, ¶ms->passive_time, 3); + + get_parmeter_from_string(&str_ptr, \ + GET_HOME_DWELL, PTYPE_INTDEC, ¶ms->home_time, 3); + + res = wl_iw_combined_scan_set(dev, params, \ + ssids_local, nssid, nchan); + } else { + WL_ERROR(("IWPRIV argument len = 0 \n")); + return -1; + } + +exit_proc: + + kfree(extra); + + return res; +} + + #ifdef SOFTAP static int thr_wait_for_2nd_eth_dev(void *data) @@ -5824,8 +6057,11 @@ static const iw_handler wl_iw_priv_handler[] = { (iw_handler)iwpriv_softap_stop, NULL, - (iw_handler)iwpriv_fw_reload + (iw_handler)iwpriv_fw_reload, #endif + + NULL, + (iw_handler)iwpriv_set_scan }; static const struct iw_priv_args wl_iw_priv_args[] = { @@ -5922,6 +6158,12 @@ static const struct iw_priv_args wl_iw_priv_args[] = { "WL_FW_RELOAD" }, #endif + { + WL_COMBO_SCAN, + IW_PRIV_TYPE_CHAR | 1024, + 0, + "CSCAN" + }, }; const struct iw_handler_def wl_iw_handler_def = diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index aea656b4f942..7514bafa53e0 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.16 2010/04/19 21:32:10 Exp $ + * $Id: wl_iw.h,v 1.5.34.1.6.18 2010/06/03 02:27:14 Exp $ */ @@ -34,6 +34,13 @@ #include #include +#define WL_SCAN_PARAMS_SSID_MAX 10 +#define GET_SSID "SSID=" +#define GET_CHANNEL "CH=" +#define GET_NPROBE "NPROBE=" +#define GET_ACTIVE_ASSOC_DWELL "ACTIVE=" +#define GET_PASSIVE_ASSOC_DWELL "PASSIVE=" +#define GET_HOME_DWELL "HOME=" #define WL_IW_RSSI_MINVAL -200 #define WL_IW_RSSI_NO_SIGNAL -91 @@ -61,7 +68,7 @@ #define AP_LPB_CMD (SIOCIWFIRSTPRIV+23) #define WL_AP_STOP (SIOCIWFIRSTPRIV+25) #define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27) -#define WL_AP_SPARE2 (SIOCIWFIRSTPRIV+29) +#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29) #define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31) #define G_SCAN_RESULTS (8*1024) #define WE_ADD_EVENT_FIX 0x80 -- 2.34.1