From d5b9284a583a7bb073633dbddb4cbb25d1fc0c67 Mon Sep 17 00:00:00 2001 From: Dmitry Shmidt Date: Wed, 26 Oct 2011 13:57:26 -0700 Subject: [PATCH] net: wireless: bcm4329: Prohibit FW access in case of FW crash Signed-off-by: Dmitry Shmidt --- drivers/net/wireless/bcm4329/dhd.h | 3 ++- drivers/net/wireless/bcm4329/dhd_cdc.c | 17 +++++++++++++++-- drivers/net/wireless/bcm4329/dhd_linux.c | 15 +++++++++++---- drivers/net/wireless/bcm4329/dhd_sdio.c | 3 ++- 4 files changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h index 95b334fd62f2..0b2e9c23e3ca 100644 --- a/drivers/net/wireless/bcm4329/dhd.h +++ b/drivers/net/wireless/bcm4329/dhd.h @@ -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 */ diff --git a/drivers/net/wireless/bcm4329/dhd_cdc.c b/drivers/net/wireless/bcm4329/dhd_cdc.c index 61f6a6f393a9..4bec0b606dc9 100644 --- a/drivers/net/wireless/bcm4329/dhd_cdc.c +++ b/drivers/net/wireless/bcm4329/dhd_cdc.c @@ -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; } diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c index 5c1384bdc215..3ec1f3f108d4 100644 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ b/drivers/net/wireless/bcm4329/dhd_linux.c @@ -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"); } } diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c index 1380dd389cf6..e9093e810624 100644 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ b/drivers/net/wireless/bcm4329/dhd_sdio.c @@ -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; } } -- 2.11.0