a43c59fbee
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
52 lines
1.8 KiB
Diff
52 lines
1.8 KiB
Diff
From b49ba04a3a0382e7314d990707c21094c410425a Mon Sep 17 00:00:00 2001
|
|
From: Johannes Berg <johannes.berg@intel.com>
|
|
Date: Thu, 19 Jan 2012 08:20:57 -0800
|
|
Subject: [PATCH 8/8] iwlwifi: fix PCI-E transport "inta" race
|
|
|
|
When an interrupt comes in, we read the reason
|
|
bits and collect them into "trans_pcie->inta".
|
|
This happens with the spinlock held. However,
|
|
there's a bug resetting this variable -- that
|
|
happens after the spinlock has been released.
|
|
This means that it is possible for interrupts
|
|
to be missed if the reset happens after some
|
|
other interrupt reasons were already added to
|
|
the variable.
|
|
|
|
I found this by code inspection, looking for a
|
|
reason that we sometimes see random commands
|
|
time out. It seems possible that this causes
|
|
such behaviour, but I can't say for sure right
|
|
now since it happens extremely infrequently on
|
|
my test systems.
|
|
|
|
Cc: stable@vger.kernel.org [3.2]
|
|
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
|
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
|
---
|
|
drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c | 4 ++--
|
|
1 files changed, 2 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
|
|
index 752493f..65d1f05 100644
|
|
--- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
|
|
+++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-rx.c
|
|
@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
|
|
}
|
|
#endif
|
|
|
|
- spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
|
-
|
|
/* saved interrupt in inta variable now we can reset trans_pcie->inta */
|
|
trans_pcie->inta = 0;
|
|
|
|
+ spin_unlock_irqrestore(&trans->shrd->lock, flags);
|
|
+
|
|
/* Now service all interrupt bits discovered above. */
|
|
if (inta & CSR_INT_BIT_HW_ERR) {
|
|
IWL_ERR(trans, "Hardware error detected. Restarting.\n");
|
|
--
|
|
1.7.4.4
|
|
|