net: wireless: bcmdhd: Fix FW hang recovery
Dmitry Shmidt [Mon, 2 Apr 2012 17:23:59 +0000 (10:23 -0700)]
- Reduce IOCTL responce timeout to 2 sec (from 20)
- Fix pending status in case of timeout
- Pass error code from dhd_is_associated() call
- Call cfg80211_disconnected() if no timeout detected

Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>

drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_dbg.h
drivers/net/wireless/bcmdhd/dhd_proto.h
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/wl_cfg80211.c

index ab3f574..db5822b 100644 (file)
@@ -509,7 +509,7 @@ extern uint dhd_bus_status(dhd_pub_t *dhdp);
 extern int  dhd_bus_start(dhd_pub_t *dhdp);
 extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size);
 extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line);
-extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf);
+extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval);
 extern uint dhd_bus_chip_id(dhd_pub_t *dhdp);
 
 #if defined(KEEP_ALIVE)
index e951128..1e7a067 100644 (file)
@@ -305,7 +305,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le
        dhd_os_proto_block(dhd_pub);
 
        ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len);
-       if (!ret)
+       if (ret)
                dhd_os_check_hang(dhd_pub, ifindex, ret);
 
        dhd_os_proto_unblock(dhd_pub);
@@ -1729,10 +1729,10 @@ fail:
 /*
  * returns = TRUE if associated, FALSE if not associated
  */
-bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf)
+bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval)
 {
        char bssid[6], zbuf[6];
-       int ret = -1;
+       int ret;
 
        bzero(bssid, 6);
        bzero(zbuf, 6);
@@ -1740,6 +1740,9 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf)
        ret  = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, (char *)&bssid, ETHER_ADDR_LEN, FALSE, 0);
        DHD_TRACE((" %s WLC_GET_BSSID ioctl res = %d\n", __FUNCTION__, ret));
 
+       if (retval)
+               *retval = ret;
+
        if (ret == BCME_NOTASSOCIATED) {
                DHD_TRACE(("%s: not associated! res:%d\n", __FUNCTION__, ret));
        }
@@ -1776,7 +1779,7 @@ dhd_get_dtim_skip(dhd_pub_t *dhd)
                bcn_li_dtim = dhd->dtim_skip;
 
        /* Check if associated */
-       if (dhd_is_associated(dhd, NULL) == FALSE) {
+       if (dhd_is_associated(dhd, NULL, NULL) == FALSE) {
                DHD_TRACE(("%s NOT assoc ret %d\n", __FUNCTION__, ret));
                goto exit;
        }
@@ -1889,7 +1892,7 @@ dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled)
        memset(iovbuf, 0, sizeof(iovbuf));
 
 #ifndef WL_SCHED_SCAN
-       if ((pfn_enabled) && (dhd_is_associated(dhd, NULL) == TRUE)) {
+       if ((pfn_enabled) && (dhd_is_associated(dhd, NULL, NULL) == TRUE)) {
                DHD_ERROR(("%s pno is NOT enable : called in assoc mode , ignore\n", __FUNCTION__));
                return ret;
        }
index a195cbe..01be6a1 100644 (file)
@@ -29,8 +29,8 @@
 
 #if defined(DHD_DEBUG)
 
-#define DHD_ERROR(args)               do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
-                                                               printf args;} while (0)
+#define DHD_ERROR(args)                do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
+                                                       printf args;} while (0)
 #define DHD_TRACE(args)                do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0)
 #define DHD_INFO(args)         do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0)
 #define DHD_DATA(args)         do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0)
index e0a54ad..bb1d736 100644 (file)
@@ -34,7 +34,7 @@
 #include <wlioctl.h>
 
 #ifndef IOCTL_RESP_TIMEOUT
-#define IOCTL_RESP_TIMEOUT  20000 /* In milli second */
+#define IOCTL_RESP_TIMEOUT  2000 /* In milli second */
 #endif
 
 /*
index 49deee1..e4fd2ed 100644 (file)
@@ -1455,7 +1455,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
 {
        int timeleft;
        uint rxlen = 0;
-       bool pending;
+       bool pending = FALSE;
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
index ca4d243..178a231 100644 (file)
@@ -2844,11 +2844,11 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 #endif
        } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS) {
                u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
+               err = -ENODEV;
                if (!wl_get_drv_status(wl, CONNECTED, dev) ||
-                       (dhd_is_associated(dhd, NULL) == FALSE)) {
+                       (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
 
-                       WL_ERR(("NOT assoc\n"));
-                       err = -ENODEV;
+                       WL_ERR(("NOT assoc: %d\n", err));
                        goto get_station_err;
                }
                if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
@@ -2881,9 +2881,9 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                WL_DBG(("RSSI %d dBm\n", rssi));
 
 get_station_err:
-               if (err) {
+               if (err && (err != -ETIMEDOUT) && (err != -EIO)) {
                        /* Disconnect due to zero BSSID or error to get RSSI */
-                       WL_ERR(("force cfg80211_disconnected\n"));
+                       WL_ERR(("force cfg80211_disconnected: %d\n", err));
                        wl_clr_drv_status(wl, CONNECTED, dev);
                        cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
                        wl_link_down(wl);