| From d4ebbbc05860388c2602625fe1511021874fc6c0 Mon Sep 17 00:00:00 2001 |
| From: Stanislaw Gruszka <sgruszka@redhat.com> |
| Date: Thu, 23 Dec 2010 12:38:21 +0100 |
| Subject: [PATCH] iwlagn: enable only rfkill interrupt when device is down |
| |
| commit 554d1d027b19265c4aa3f718b3126d2b86e09a08 upstream. |
| |
| 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> |
| Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c |
| index 07a9a02..2e55ed5 100644 |
| --- a/drivers/net/wireless/iwlwifi/iwl-agn.c |
| +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c |
| @@ -2761,9 +2761,10 @@ static void iwl_mac_stop(struct ieee80211_hw *hw) |
| |
| flush_workqueue(priv->workqueue); |
| |
| - /* enable interrupts again in order to receive rfkill changes */ |
| + /* User space software may expect getting rfkill changes |
| + * even if interface is down */ |
| iwl_write32(priv, CSR_INT, 0xFFFFFFFF); |
| - iwl_enable_interrupts(priv); |
| + iwl_enable_rfkill_int(priv); |
| |
| IWL_DEBUG_MAC80211(priv, "leave\n"); |
| } |
| @@ -3667,14 +3668,14 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) |
| * 8. Enable interrupts and read RFKILL state |
| *********************************************/ |
| |
| - /* enable interrupts if needed: hw bug w/a */ |
| + /* enable rfkill interrupt: hw bug w/a */ |
| pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); |
| if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { |
| pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; |
| pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); |
| } |
| |
| - iwl_enable_interrupts(priv); |
| + iwl_enable_rfkill_int(priv); |
| |
| /* If platform's RF_KILL switch is NOT set to KILL */ |
| 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 51a67fb..7fff002 100644 |
| --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h |
| +++ b/drivers/net/wireless/iwlwifi/iwl-helpers.h |
| @@ -160,6 +160,12 @@ static inline void iwl_disable_interrupts(struct iwl_priv *priv) |
| IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); |
| } |
| |
| +static inline void iwl_enable_rfkill_int(struct iwl_priv *priv) |
| +{ |
| + IWL_DEBUG_ISR(priv, "Enabling rfkill interrupt\n"); |
| + iwl_write32(priv, CSR_INT_MASK, CSR_INT_BIT_RF_KILL); |
| +} |
| + |
| static inline void iwl_enable_interrupts(struct iwl_priv *priv) |
| { |
| IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); |
| -- |
| 1.7.4.4 |
| |