OSDN Git Service

net: wireless: bcm4329: Prohibit FW access in case of FW crash
authorDmitry Shmidt <dimitrysh@google.com>
Wed, 26 Oct 2011 20:57:26 +0000 (13:57 -0700)
committerDmitry Shmidt <dimitrysh@google.com>
Wed, 26 Oct 2011 21:01:32 +0000 (14:01 -0700)
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
drivers/net/wireless/bcm4329/dhd.h
drivers/net/wireless/bcm4329/dhd_cdc.c
drivers/net/wireless/bcm4329/dhd_linux.c
drivers/net/wireless/bcm4329/dhd_sdio.c

index 95b334f..0b2e9c2 100644 (file)
@@ -144,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;
@@ -156,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 */
index 61f6a6f..4bec0b6 100644 (file)
@@ -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;
        }
index 5c1384b..3ec1f3f 100644 (file)
@@ -319,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
@@ -1778,6 +1777,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));
 
@@ -1921,7 +1928,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;
 }
@@ -3187,8 +3194,8 @@ 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");
                }
        }
index 1380dd3..e9093e8 100644 (file)
@@ -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;
                }
        }