From: Greg Goldman Date: Mon, 18 Oct 2010 22:12:55 +0000 (-0700) Subject: net: wireless: bcm4329: Update to Version 4.218.248-10 X-Git-Tag: firefly_0821_release~9833^2~5^2~102 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=41d6f03195cb72aaef0d93126c94e5f3d977103f;p=firefly-linux-kernel-4.4.55.git net: wireless: bcm4329: Update to Version 4.218.248-10 Add KEEP_ALIVE feature, fix 'driver rssi' processing, fix roaming processing Signed-off-by: Dmitry Shmidt --- diff --git a/drivers/net/wireless/bcm4329/bcmsdh_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_linux.c index 559f4819b1b6..3b7da4263fd8 100644 --- a/drivers/net/wireless/bcm4329/bcmsdh_linux.c +++ b/drivers/net/wireless/bcm4329/bcmsdh_linux.c @@ -581,8 +581,6 @@ bcmsdh_unregister(void) #endif /* BCMPLATFORM_BUS */ } - - #if defined(OOB_INTR_ONLY) void bcmsdh_oob_intr_set(bool enable) { @@ -624,6 +622,9 @@ int bcmsdh_register_oob_intr(void * dhdp) SDLX_MSG(("%s Enter\n", __FUNCTION__)); +/* Example of HW_OOB for HW2: please refer to your host specifiction */ +/* sdhcinfo->oob_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; */ + dev_set_drvdata(sdhcinfo->dev, dhdp); if (!sdhcinfo->oob_irq_registered) { diff --git a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c index bda919390587..031367b8f18f 100644 --- a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c @@ -675,7 +675,6 @@ sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) data = 3; /* enable hw oob interrupt */ else data = 4; /* disable hw oob interrupt */ - data |= 4; /* Active HIGH */ status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data); diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index cc7e8cb286b8..4e5ffcbd5237 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 2010/08/20 17:32:48 Exp $ + * $Id: dhd.h,v 1.32.4.7.2.4.14.49.4.1 2010/09/23 02:33:19 Exp $ */ /**************** @@ -86,6 +86,7 @@ enum dhd_bus_wake_state { WAKE_LOCK_TMOUT, WAKE_LOCK_WATCHDOG, WAKE_LOCK_LINK_DOWN_TMOUT, + WAKE_LOCK_PNO_FIND_TMOUT, WAKE_LOCK_SOFTAP_SET, WAKE_LOCK_SOFTAP_STOP, WAKE_LOCK_SOFTAP_START, diff --git a/drivers/net/wireless/bcm4329/dhd_bus.h b/drivers/net/wireless/bcm4329/dhd_bus.h index 9e29fb955444..97af41b313d0 100644 --- a/drivers/net/wireless/bcm4329/dhd_bus.h +++ b/drivers/net/wireless/bcm4329/dhd_bus.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_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $ + * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.7 2010/08/13 01:35:24 Exp $ */ #ifndef _dhd_bus_h_ @@ -63,7 +63,7 @@ extern bool dhd_bus_watchdog(dhd_pub_t *dhd); #ifdef DHD_DEBUG /* Device console input function */ extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen); -#endif +#endif /* DHD_DEBUG */ /* Deferred processing for the bus, return TRUE requests reschedule */ extern bool dhd_bus_dpc(struct dhd_bus *bus); diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c index bea33b6d29af..1da80f40f985 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.3 2010/09/10 21:30:16 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.4 2010/09/22 21:21:15 Exp $ */ #include #include @@ -1909,6 +1909,9 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr) __FUNCTION__, i, err)); return err; } + else + DHD_ERROR(("%s set OK with PNO time=%d\n", __FUNCTION__, \ + pfn_param.scan_freq)); } else DHD_ERROR(("%s failed err=%d\n", __FUNCTION__, err)); } diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index f687b31e3338..fe7cbf116372 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -217,9 +217,10 @@ print_tainted() #include #endif /* defined(CONFIG_WIRELESS_EXT) */ +extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); + #if defined(CONFIG_HAS_EARLYSUSPEND) #include -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); #endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ #ifdef PKT_FILTER_SUPPORT @@ -302,6 +303,11 @@ typedef struct dhd_info { char firmware_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; +#if defined(CONFIG_HAS_EARLYSUSPEND) +#define KEEP_ALIVE +#define KEEP_ALIVE_PERIOD 60000 +#endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) struct semaphore dhd_registration_sem; #define DHD_REGISTRATION_TIMEOUT 8000 /* msec : allowed time to finished dhd registration */ @@ -518,6 +524,59 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) #endif } + +#if defined(KEEP_ALIVE) + +/* wl cmd# ./wl keep_alive 45000 0x6e756c6c5f706b74 */ +#define NULL_PKT_STR "null_pkt" + +static int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on) +{ + char buf[256]; + char *buf_ptr = buf; + wl_keep_alive_pkt_t keep_alive_pkt; + char * str; + int str_len, buf_len; + int res = 0; + int keep_alive_period = KEEP_ALIVE_PERIOD; /* in ms */ + + DHD_TRACE(("%s: ka:%d\n", __FUNCTION__, ka_on)); + + if (ka_on) { /* on suspend */ + keep_alive_pkt.period_msec = keep_alive_period; + + } else { + /* on resume, turn off keep_alive packets */ + keep_alive_pkt.period_msec = 0; + } + + /* IOC var name */ + str = "keep_alive"; + str_len = strlen(str); + strncpy(buf, str, str_len); + buf[str_len] = '\0'; + buf_len = str_len + 1; + + /* set ptr to IOCTL payload after the var name */ + buf_ptr += buf_len; /* include term Z */ + + /* copy Keep-alive attributes from local var keep_alive_pkt */ + str = NULL_PKT_STR; + keep_alive_pkt.len_bytes = strlen(str); + + memcpy(buf_ptr, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN); + buf_ptr += WL_KEEP_ALIVE_FIXED_LEN; + + /* copy packet data */ + memcpy(buf_ptr, str, keep_alive_pkt.len_bytes); + buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes); + + res = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len); + return res; +} +#endif /* defined(KEEP_ALIVE) */ + + #if defined(CONFIG_HAS_EARLYSUSPEND) static int dhd_set_suspend(int value, dhd_pub_t *dhd) { @@ -529,6 +588,10 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) uint roamvar = 1; #endif /* CUSTOMER_HW2 */ +#if defined(KEEP_ALIVE) + int ioc_res; +#endif + DHD_TRACE(("%s: enter, value = %d in_suspend = %d\n", __FUNCTION__, value, dhd->in_suspend)); @@ -536,7 +599,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) if (value && dhd->in_suspend) { /* Kernel suspended */ - DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__)); + DHD_TRACE(("%s: force extra Suspend setting \n", __FUNCTION__)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode)); @@ -544,14 +607,14 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) /* Enable packet filter, only allow unicast packet to send up */ dhd_set_packet_filter(1, dhd); - /* if dtim skip setup as default force it to wake each thrid dtim - * for better power saving. - * Note that side effect is chance to miss BC/MC packet - */ - if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1)) - bcn_li_dtim = 3; - else - bcn_li_dtim = dhd->dtim_skip; + /* if dtim skip setup as default force it to wake each thrid dtim + * for better power saving. + * Note that side effect is chance to miss BC/MC packet + */ + if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1)) + bcn_li_dtim = 3; + else + bcn_li_dtim = dhd->dtim_skip; bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -560,10 +623,15 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); #endif /* CUSTOMER_HW2 */ + +#if defined(KEEP_ALIVE) + if ((ioc_res = dhd_keep_alive_onoff(dhd, 1)) < 0) + DHD_ERROR(("%s result:%d\n", __FUNCTION__, ioc_res)); +#endif } else { /* Kernel resumed */ - DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); + DHD_TRACE(("%s: Remove extra suspend setting \n", __FUNCTION__)); power_mode = PM_FAST; dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, @@ -572,16 +640,21 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) /* disable pkt filter */ dhd_set_packet_filter(0, dhd); - /* restore pre-suspend setting for dtim_skip */ - bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, - 4, iovbuf, sizeof(iovbuf)); + /* restore pre-suspend setting for dtim_skip */ + bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, + 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); + dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); #ifdef CUSTOMER_HW2 roamvar = dhd_roam; bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); #endif /* CUSTOMER_HW2 */ + +#if defined(KEEP_ALIVE) + if ((ioc_res = dhd_keep_alive_onoff(dhd, 0)) < 0) + DHD_ERROR(("%s result:%d\n", __FUNCTION__, ioc_res)); +#endif } } @@ -1869,7 +1942,8 @@ dhd_open(struct net_device *net) #endif int ifidx; - wl_control_wl_start(net); /* start if needed */ + /* Force start if ifconfig_up gets called before START command */ + wl_control_wl_start(net); ifidx = dhd_net2idx(dhd, net); DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); @@ -1879,7 +1953,6 @@ dhd_open(struct net_device *net) return -1; } - if (ifidx == 0) { /* do it only for primary eth0 */ atomic_set(&dhd->pend_8021x_cnt, 0); diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index ff1bdedbc9f3..abe92b7eb09a 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -5809,7 +5809,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) /* Expect app to have torn down any connection before calling */ /* Stop the bus, disable F2 */ dhd_os_sdlock(dhdp); - dhd_bus_stop(bus, FALSE); /* Clean tx/rx buffer pointers, detach from the dongle */ @@ -5817,7 +5816,6 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) bus->dhd->dongle_reset = TRUE; bus->dhd->up = FALSE; - dhd_os_sdunlock(dhdp); DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); @@ -5864,6 +5862,7 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) bcmerror = BCME_SDIO_ERROR; } else bcmerror = BCME_SDIO_ERROR; + dhd_os_sdunlock(dhdp); } else { bcmerror = BCME_NOTDOWN; diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index 92dc32635a25..b2a7eb0c8138 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 6 +#define EPI_INCREMENTAL_NUMBER 10 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 248, 6 +#define EPI_VERSION 4, 218, 248, 10 -#define EPI_VERSION_NUM 0x04daf806 +#define EPI_VERSION_NUM 0x04daf80a -#define EPI_VERSION_STR "4.218.248.6" -#define EPI_ROUTER_VERSION_STR "4.219.248.6" +#define EPI_VERSION_STR "4.218.248.10" +#define EPI_ROUTER_VERSION_STR "4.219.248.10" #endif diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 2cd629cbd1c3..a9f3ee31f1dc 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -1165,15 +1165,15 @@ wl_iw_set_pno_set( wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; int nssid = 0; cmd_tlv_t *cmd_tlv_temp; - char type; char *str_ptr; + char *str_ptr_end; int tlv_size_left; int pno_time; #ifdef PNO_SET_DEBUG int i; char pno_in_example[] = {'P', 'N', 'O', 'S', 'E', 'T', 'U', 'P', ' ', \ - 'S', 0x01, 0x01, 0x00, + 'S', '1', '2', '0', 'S', 0x04, 'B', 'R', 'C', 'M', @@ -1181,8 +1181,8 @@ wl_iw_set_pno_set( 0x04, 'G', 'O', 'O', 'G', 'T', - 0x00, - 0x0A + '1','E', + 0x00 }; #endif @@ -1239,29 +1239,15 @@ wl_iw_set_pno_set( goto exit_proc; } else { - while (tlv_size_left > 0) - { - type = str_ptr[0]; - switch (type) { - case PNO_TLV_TYPE_TIME: - - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &pno_time, \ - sizeof(pno_time), \ - type, sizeof(short), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - - default: - WL_ERROR(("%s get unkwown type %X\n", \ - __FUNCTION__, type)); - goto exit_proc; - break; - } + if ((str_ptr[0] != PNO_TLV_TYPE_TIME) || (tlv_size_left <= 1)) { + WL_ERROR(("%s scan duration corrupted field size %d\n", \ + __FUNCTION__, tlv_size_left)); + 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)); } } else { @@ -1300,19 +1286,24 @@ wl_iw_get_rssi( error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); if (error) { WL_ERROR(("%s: Fails %d\n", __FUNCTION__, error)); - net_os_wake_unlock(dev); - return error; - } - rssi = dtoh32(scb_val.val); + } else { + rssi = dtoh32(scb_val.val); - error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)); - if (!error) { - ssid.SSID_len = dtoh32(ssid.SSID_len); - wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len)); + error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)); + if (!error) { + ssid.SSID_len = dtoh32(ssid.SSID_len); + wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len)); + } } } - p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi); + WL_ASSOC(("%s ssid_len:%d, rssi:%d\n", __FUNCTION__, ssid.SSID_len, rssi)); + + if (error || (ssid.SSID_len == 0)) { + p += snprintf(p, MAX_WX_STRING, "FAIL"); + } else { + p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi); + } wrqu->data.length = p - extra + 1; net_os_wake_unlock(dev); @@ -3431,6 +3422,7 @@ wl_iw_get_scan_prep( wl_bss_info_t *bi = NULL; char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; int ret = 0; + int channel; ASSERT(list); @@ -3468,8 +3460,9 @@ wl_iw_get_scan_prep( iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), - CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? + channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; + iwe.u.freq.m = wf_channel2mhz(channel, + channel <= 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); @@ -7312,10 +7305,14 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) cmd = IWEVREGISTERED; break; case WLC_E_ROAM: - if (status != WLC_E_STATUS_SUCCESS) { + 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; + } + else if (status == WLC_E_STATUS_NO_NETWORKS) { roam_no_success++; - if ((roam_no_success == 3) && (roam_no_success_send == FALSE)) { - + if ((roam_no_success == 5) && (roam_no_success_send == FALSE)) { roam_no_success_send = TRUE; bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); bzero(&extra, ETHER_ADDR_LEN); @@ -7326,10 +7323,6 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) WL_TRACE(("##### ROAMING did not succeeded %d\n", roam_no_success)); goto wl_iw_event_end; } - } else { - memcpy(wrqu.addr.sa_data, &e->addr.octet, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - cmd = SIOCGIWAP; } break; case WLC_E_DEAUTH_IND: diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index 43088cf886bd..5335b5661cdd 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ b/drivers/net/wireless/bcm4329/wl_iw.h @@ -225,9 +225,9 @@ extern int dhd_dev_pno_enable(struct net_device *dev, int pfn_enabled); extern int dhd_dev_get_pno_status(struct net_device *dev); #define PNO_TLV_PREFIX 'S' -#define PNO_TLV_VERSION 1 -#define PNO_TLV_SUBVERSION 1 -#define PNO_TLV_RESERVED 0 +#define PNO_TLV_VERSION '1' +#define PNO_TLV_SUBVERSION '2' +#define PNO_TLV_RESERVED '0' #define PNO_TLV_TYPE_SSID_IE 'S' #define PNO_TLV_TYPE_TIME 'T' #define PNO_EVENT_UP "PNO_EVENT"