From 4fc11e138b2f0f6cb920dbd3364d3541e6bf90c0 Mon Sep 17 00:00:00 2001 From: Greg Goldman Date: Mon, 1 Nov 2010 16:58:08 -0700 Subject: [PATCH] net: wireless: bcm4329: Update to version 4.218.248-11 Check for 'driver start' failure, Set keep-alive feature forever Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/dhd.h | 6 ++ drivers/net/wireless/bcm4329/dhd_common.c | 74 +++++++++++++++- drivers/net/wireless/bcm4329/dhd_linux.c | 85 +++---------------- .../net/wireless/bcm4329/include/epivers.h | 10 +-- drivers/net/wireless/bcm4329/wl_iw.c | 14 ++- drivers/net/wireless/bcm4329/wl_iw.h | 2 +- 6 files changed, 106 insertions(+), 85 deletions(-) diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index d136517c51a4..59aa9f10ab1f 100644 --- a/drivers/net/wireless/bcm4329/dhd.h +++ b/drivers/net/wireless/bcm4329/dhd.h @@ -351,6 +351,8 @@ typedef enum cust_gpio_modes { } cust_gpio_modes_t; extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); +extern int net_os_send_hang_message(struct net_device *dev); + /* * Insmod parameters for debug/test */ @@ -400,6 +402,10 @@ extern uint dhd_sdiod_drive_strength; /* Override to force tx queueing all the time */ extern uint dhd_force_tx_queueing; +/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ +#define KEEP_ALIVE_PERIOD 55000 +#define NULL_PKT_STR "null_pkt" + #ifdef SDTEST /* Echo packet generator (SDIO), pkts/s */ extern uint dhd_pktgen; diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c index 1da80f40f985..dbd4b922a262 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.4 2010/09/22 21:21:15 Exp $ + * $Id: dhd_common.c,v 1.5.6.8.2.6.6.69.4.10 2010/10/29 19:58:08 Exp $ */ #include #include @@ -71,6 +71,11 @@ extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen); void dhd_iscan_lock(void); void dhd_iscan_unlock(void); +#if defined(KEEP_ALIVE) +extern bool ap_fw_loaded; +int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on); +#endif /* KEEP_ALIVE */ + /* Packet alignment for most efficient SDIO (can change based on platform) */ #ifndef DHD_SDALIGN #define DHD_SDALIGN 32 @@ -1392,6 +1397,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* PKT_FILTER_SUPPORT */ +#if defined(KEEP_ALIVE) + { + /* Set Keep Alive : be sure to use FW with -keepalive */ + int res; + + if (ap_fw_loaded == FALSE) { + if ((res = dhd_keep_alive_onoff(dhd, 1)) < 0) + DHD_ERROR(("%s set keeplive failed %d\n", \ + __FUNCTION__, res)); + } + } +#endif + dhd_os_proto_unblock(dhd); return 0; @@ -1446,7 +1464,7 @@ dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete) dhd_pub_t *dhd = dhd_bus_pub(dhdp); dhd_iscan_lock(); - /* If iscan_delete is null then delete the entire + /* If iscan_delete is null then delete the entire * chain or else delete specific one provided */ if (!iscan_delete) { @@ -1885,6 +1903,11 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort 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)); + return err; + } + bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -1933,6 +1956,53 @@ int dhd_pno_get_status(dhd_pub_t *dhd) #endif /* PNO_SUPPORT */ +#if defined(KEEP_ALIVE) +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(CSCAN) /* Androd ComboSCAN support */ diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 0b52e0373e3e..e95e3b1e0f08 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104 2010/08/20 19:15:40 Exp $ + * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.104.4.27 2010/10/29 02:31:24 Exp $ */ #ifdef CONFIG_WIFI_CONTROL_FUNC @@ -305,11 +305,6 @@ 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 55000 -#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 */ @@ -527,57 +522,6 @@ static void dhd_set_packet_filter(int value, dhd_pub_t *dhd) } -#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) @@ -590,10 +534,6 @@ 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)); @@ -621,15 +561,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) 4, iovbuf, sizeof(iovbuf)); dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); #ifdef CUSTOMER_HW2 - /* Disable build-in roaming to allowed ext supplicant to take of roaming */ + /* Disable build-in roaming during suspend */ 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 */ @@ -652,11 +588,6 @@ 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, 0)) < 0) - DHD_ERROR(("%s result:%d\n", __FUNCTION__, ioc_res)); -#endif } } @@ -2978,20 +2909,26 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd) int dhd_dev_reset(struct net_device *dev, uint8 flag) { + int ret; + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); /* Turning off watchdog */ if (flag) dhd_os_wd_timer(&dhd->pub, 0); - dhd_bus_devreset(&dhd->pub, flag); + ret = dhd_bus_devreset(&dhd->pub, flag); + if (ret) { + DHD_ERROR(("%s: dhd_bus_devreset: %d\n", __FUNCTION__, ret)); + return ret; + } /* Turning on watchdog back */ if (!flag) dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); - DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); + DHD_ERROR(("%s: WLAN OFF DONE:\n", __FUNCTION__)); - return 1; + return ret; } int net_os_set_suspend_disable(struct net_device *dev, int val) diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h index b2a7eb0c8138..002aff6897de 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 10 +#define EPI_INCREMENTAL_NUMBER 11 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 4, 218, 248, 10 +#define EPI_VERSION 4, 218, 248, 11 -#define EPI_VERSION_NUM 0x04daf80a +#define EPI_VERSION_NUM 0x04daf80b -#define EPI_VERSION_STR "4.218.248.10" -#define EPI_ROUTER_VERSION_STR "4.219.248.10" +#define EPI_VERSION_STR "4.218.248.11" +#define EPI_ROUTER_VERSION_STR "4.219.248.11" #endif diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c index 525d3909e7ae..66d8d2b54aa8 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ b/drivers/net/wireless/bcm4329/wl_iw.c @@ -97,7 +97,7 @@ typedef const struct si_pub si_t; #define WL_SOFTAP(x) printk x static struct net_device *priv_dev; static bool ap_cfg_running = FALSE; -static bool ap_fw_loaded = FALSE; +bool ap_fw_loaded = FALSE; struct net_device *ap_net_dev = NULL; struct semaphore ap_eth_sema; static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap); @@ -1468,7 +1468,7 @@ wl_control_wl_start(struct net_device *dev) sdioh_start(NULL, 0); #endif - dhd_dev_reset(dev, 0); + ret = dhd_dev_reset(dev, 0); #if defined(BCMLXSDMMC) sdioh_start(NULL, 1); @@ -1558,7 +1558,15 @@ wl_iw_control_wl_on( WL_TRACE(("Enter %s \n", __FUNCTION__)); - ret = wl_control_wl_start(dev); + if ((ret = wl_control_wl_start(dev)) == BCME_SDIO_ERROR) { + WL_ERROR(("%s failed first attemp\n", __FUNCTION__)); + bcm_mdelay(100); + if ((ret = wl_control_wl_start(dev)) == BCME_SDIO_ERROR) { + WL_ERROR(("%s failed second attemp\n", __FUNCTION__)); + net_os_send_hang_message(dev); + return ret; + } + } wl_iw_send_priv_event(dev, "START"); diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h index 5335b5661cdd..3b45792979af 100644 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ b/drivers/net/wireless/bcm4329/wl_iw.h @@ -196,7 +196,6 @@ 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 int net_os_send_hang_message(struct net_device *dev); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) #define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ @@ -231,6 +230,7 @@ extern int dhd_dev_get_pno_status(struct net_device *dev); #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 typedef struct cmd_tlv { char prefix; -- 2.34.1