aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2010-12-23 06:38:21 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-04 14:15:08 -0500
commit554d1d027b19265c4aa3f718b3126d2b86e09a08 (patch)
tree5f8439d45b8ed972201dfcbdc8dd88533e88cd97 /drivers/net/wireless
parentb51aff057c9d0ef6c529dc25fd9f775faf7b6c63 (diff)
iwlagn: enable only rfkill interrupt when device is down
Since commit 6cd0b1cb872b3bf9fc5de4536404206ab74bafdd "iwlagn: fix hw-rfkill while the interface is down", we enable interrupts when device is not ready to receive them. However hardware, when it is in some inconsistent state, can generate other than rfkill interrupts and crash the system. I can reproduce crash with "kernel BUG at drivers/net/wireless/iwlwifi/iwl-agn.c:1010!" message, when forcing firmware restarts. To fix only enable rfkill interrupt when down device and after probe. I checked patch on laptop with 5100 device, rfkill change is still passed to user space when device is down. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Cc: stable@kernel.org Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-helpers.h6
2 files changed, 11 insertions, 4 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c2636a7ab9ee..e0ec40ed43b7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3530,9 +3530,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw)
3530 3530
3531 flush_workqueue(priv->workqueue); 3531 flush_workqueue(priv->workqueue);
3532 3532
3533 /* enable interrupts again in order to receive rfkill changes */ 3533 /* User space software may expect getting rfkill changes
3534 * even if interface is down */
3534 iwl_write32(priv, CSR_INT, 0xFFFFFFFF); 3535 iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
3535 iwl_enable_interrupts(priv); 3536 iwl_enable_rfkill_int(priv);
3536 3537
3537 IWL_DEBUG_MAC80211(priv, "leave\n"); 3538 IWL_DEBUG_MAC80211(priv, "leave\n");
3538} 3539}
@@ -4515,14 +4516,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
4515 * 8. Enable interrupts and read RFKILL state 4516 * 8. Enable interrupts and read RFKILL state
4516 *********************************************/ 4517 *********************************************/
4517 4518
4518 /* enable interrupts if needed: hw bug w/a */ 4519 /* enable rfkill interrupt: hw bug w/a */
4519 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); 4520 pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
4520 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { 4521 if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
4521 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; 4522 pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
4522 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); 4523 pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
4523 } 4524 }
4524 4525
4525 iwl_enable_interrupts(priv); 4526 iwl_enable_rfkill_int(priv);
4526 4527
4527 /* If platform's RF_KILL switch is NOT set to KILL */ 4528 /* If platform's RF_KILL switch is NOT set to KILL */
4528 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) 4529 if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)
diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h
index 1aaef70deaec..19f5586d362a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-helpers.h
+++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h
@@ -163,6 +163,12 @@ static inline void iwl_disable_interrupts(struct iwl_priv *priv)
163 IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); 163 IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
164} 164}
165 165
166static inline void iwl_enable_rfkill_int(struct iwl_priv *priv)
167{
168 IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n");
169 iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL);
170}
171
166static inline void iwl_enable_interrupts(struct iwl_priv *priv) 172static inline void iwl_enable_interrupts(struct iwl_priv *priv)
167{ 173{
168 IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); 174 IWL_DEBUG_ISR(priv, "Enabling interrupts\n");