kernel/brcmsmac-fix-tx-queue-flush-infinite-loop.patch
John W. Linville a43c59fbee mac80211: fix debugfs key->station symlink
brcmsmac: fix tx queue flush infinite loop
mac80211: Use the right headroom size for mesh mgmt frames
mac80211: fix work removal on deauth request
b43: add option to avoid duplicating device support with brcmsmac
mac80211: update oper_channel on ibss join
mac80211: set bss_conf.idle when vif is connected
iwlwifi: fix PCI-E transport "inta" race
2012-01-30 10:41:26 -05:00

52 lines
1.7 KiB
Diff

From f96b08a7e6f69c0f0a576554df3df5b1b519c479 Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgruszka@redhat.com>
Date: Tue, 17 Jan 2012 12:38:50 +0100
Subject: [PATCH 2/8] brcmsmac: fix tx queue flush infinite loop
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>
Cc: stable@vger.kernel.org # 3.2+
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
---
drivers/net/wireless/brcm80211/brcmsmac/main.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index f7ed340..f6affc6 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -7981,13 +7981,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)
--
1.7.4.4