Message ID | 1385125518-13461-2-git-send-email-michal.kazior@tieto.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
Headers | show |
Michal Kazior <michal.kazior@tieto.com> writes: > ath10k assumed all interrupts were directed to it. > This isn't the case for legacy shared interrupts. > ath10k consumed interrupts for other devices. > > Check device irq status and return IRQ_NONE when > appropriate. > > Signed-off-by: Michal Kazior <michal.kazior@tieto.com> [...] > @@ -2085,6 +2103,9 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) > struct ath10k *ar = arg; > struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); > > + if (!ath10k_pci_irq_pending(ar)) > + return IRQ_NONE; > + > if (ar_pci->num_msi_intrs == 0) { > /* > * IMPORTANT: INTR_CLR regiser has to be set after What if you move ath10k_pci_irq_pending() call after ar_pci->num_msi_intrs == 0 check? That way you could remove the "ar_pci->num_msi_intrs == 0" check from irq_pending() function.
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 8aeb46d..9535eaa 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -269,6 +269,7 @@ enum ath10k_mcast2ucast_mode { #define CORE_CTRL_CPU_INTR_MASK 0x00002000 #define CORE_CTRL_ADDRESS 0x0000 #define PCIE_INTR_ENABLE_ADDRESS 0x0008 +#define PCIE_INTR_CAUSE_ADDRESS 0x000c #define PCIE_INTR_CLR_ADDRESS 0x0014 #define SCRATCH_3_ADDRESS 0x0030 diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 2457c8b..ed752d6 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -2075,6 +2075,24 @@ static irqreturn_t ath10k_pci_msi_fw_handler(int irq, void *arg) return IRQ_HANDLED; } +static bool ath10k_pci_irq_pending(struct ath10k *ar) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + u32 cause; + + /* MSIs are always exclusive */ + if (ar_pci->num_msi_intrs > 0) + return true; + + /* Check if the shared legacy irq is for us */ + cause = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + + PCIE_INTR_CAUSE_ADDRESS); + if (cause & (PCIE_INTR_FIRMWARE_MASK | PCIE_INTR_CE_MASK_ALL)) + return true; + + return false; +} + /* * Top-level interrupt handler for all PCI interrupts from a Target. * When a block of MSI interrupts is allocated, this top-level handler @@ -2085,6 +2103,9 @@ static irqreturn_t ath10k_pci_interrupt_handler(int irq, void *arg) struct ath10k *ar = arg; struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + if (!ath10k_pci_irq_pending(ar)) + return IRQ_NONE; + if (ar_pci->num_msi_intrs == 0) { /* * IMPORTANT: INTR_CLR regiser has to be set after
ath10k assumed all interrupts were directed to it. This isn't the case for legacy shared interrupts. ath10k consumed interrupts for other devices. Check device irq status and return IRQ_NONE when appropriate. Signed-off-by: Michal Kazior <michal.kazior@tieto.com> --- drivers/net/wireless/ath/ath10k/hw.h | 1 + drivers/net/wireless/ath/ath10k/pci.c | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+)