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
|
||
|
|