[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#637240: (Solved) Re: brcmsmac: "firmware bug" warning when connecting, hang when unloading brcmsmac driver unless near AP



Camaleón wrote:

> Yes, I can install whatever kernel version you require or run any 
> tests/patches you need.

Excellent.  Please test v3.2.4 from unstable.  (It includes the
following patch.)

Thanks,
Jonathan

commit 4bc34a5c5c4e
Author: Stanislaw Gruszka <sgruszka@redhat.com>
Date:   Tue Jan 17 12:38:50 2012 +0100

    brcmsmac: fix tx queue flush infinite loop

    commit f96b08a7e6f69c0f0a576554df3df5b1b519c479 upstream.

    This patch workaround live deadlock problem caused by infinite loop
    in brcms_c_wait_for_tx_completion(). I do not consider the patch as
    the proper fix, which should fix the real reason of tx queue flush
    failure, but patch helps with system lockup.

    Reference:
    https://bugzilla.kernel.org/show_bug.cgi?id=42576

    Reported-and-tested-by: Patrick <ragamuffin@datacomm.ch>
    Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
    Signed-off-by: John W. Linville <linville@tuxdriver.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 510e9bb52287..453f58e5667f 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -8217,13 +8217,21 @@ int brcms_c_get_curband(struct brcms_c_info *wlc)
 
 void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop)
 {
+	int timeout = 20;
+
 	/* flush packet queue when requested */
 	if (drop)
 		brcmu_pktq_flush(&wlc->pkt_queue->q, false, NULL, NULL);
 
 	/* wait for queue and DMA fifos to run dry */
-	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0)
+	while (!pktq_empty(&wlc->pkt_queue->q) || brcms_txpktpendtot(wlc) > 0) {
 		brcms_msleep(wlc->wl, 1);
+
+		if (--timeout == 0)
+			break;
+	}
+
+	WARN_ON_ONCE(timeout == 0);
 }
 
 void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval)



Reply to: