iwlwifi: pcie: don’t service an interrupt that was masked [Linux 4.9.187]

This Linux kernel change "iwlwifi: pcie: don’t service an interrupt that was masked" is included in the Linux 4.9.187 release. This change is authored by Emmanuel Grumbach <emmanuel.grumbach [at] intel.com> on Tue May 21 15:10:38 2019 +0300. The commit for this change in Linux stable tree is cb25d56 (patch) which is from upstream commit 3b57a10. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 3b57a10.

iwlwifi: pcie: don't service an interrupt that was masked

commit 3b57a10ca14c619707398dc58fe5ece18c95b20b upstream.

Sometimes the register status can include interrupts that
were masked. We can, for example, get the RF-Kill bit set
in the interrupt status register although this interrupt
was masked. Then if we get the ALIVE interrupt (for example)
that was not masked, we need to *not* service the RF-Kill
interrupt.
Fix this in the MSI-X interrupt handler.

Cc: stable@vger.kernel.org
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 27 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/wireless/intel/iwlwifi/pcie/rx.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
index 25f2a0a..a2ebe46 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c
@@ -1901,10 +1901,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
        return IRQ_NONE;
    }

-   if (iwl_have_debug_level(IWL_DL_ISR))
-       IWL_DEBUG_ISR(trans, "ISR inta_fh 0x%08x, enabled 0x%08x\n",
-                 inta_fh,
+   if (iwl_have_debug_level(IWL_DL_ISR)) {
+       IWL_DEBUG_ISR(trans,
+                 "ISR inta_fh 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
+                 inta_fh, trans_pcie->fh_mask,
                  iwl_read32(trans, CSR_MSIX_FH_INT_MASK_AD));
+       if (inta_fh & ~trans_pcie->fh_mask)
+           IWL_DEBUG_ISR(trans,
+                     "We got a masked interrupt (0x%08x)\n",
+                     inta_fh & ~trans_pcie->fh_mask);
+   }
+
+   inta_fh &= trans_pcie->fh_mask;

    if ((trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX) &&
        inta_fh & MSIX_FH_INT_CAUSES_Q0) {
@@ -1943,11 +1951,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
    }

    /* After checking FH register check HW register */
-   if (iwl_have_debug_level(IWL_DL_ISR))
+   if (iwl_have_debug_level(IWL_DL_ISR)) {
        IWL_DEBUG_ISR(trans,
-                 "ISR inta_hw 0x%08x, enabled 0x%08x\n",
-                 inta_hw,
+                 "ISR inta_hw 0x%08x, enabled (sw) 0x%08x (hw) 0x%08x\n",
+                 inta_hw, trans_pcie->hw_mask,
                  iwl_read32(trans, CSR_MSIX_HW_INT_MASK_AD));
+       if (inta_hw & ~trans_pcie->hw_mask)
+           IWL_DEBUG_ISR(trans,
+                     "We got a masked interrupt 0x%08x\n",
+                     inta_hw & ~trans_pcie->hw_mask);
+   }
+
+   inta_hw &= trans_pcie->hw_mask;

    /* Alive notification via Rx interrupt will do the real work */
    if (inta_hw & MSIX_HW_INT_CAUSES_REG_ALIVE) {

Leave a Reply

Your email address will not be published. Required fields are marked *