return 0;
}
+static void ath10k_pci_irq_disable(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ int i;
+
+ ath10k_ce_disable_interrupts(ar);
+
+ /* Regardless how many interrupts were assigned for MSI the first one
+ * is always used for firmware indications (crashes). There's no way to
+ * mask the irq in the device so call disable_irq(). Legacy (shared)
+ * interrupts can be masked on the device though.
+ */
+ if (ar_pci->num_msi_intrs > 0)
+ disable_irq(ar_pci->pdev->irq);
+ else
+ ath10k_pci_disable_and_clear_legacy_irq(ar);
+
+ for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
+ synchronize_irq(ar_pci->pdev->irq + i);
+}
+
+static void ath10k_pci_irq_enable(struct ath10k *ar)
+{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+
+ ath10k_ce_enable_interrupts(ar);
+
+ /* See comment in ath10k_pci_irq_disable() */
+ if (ar_pci->num_msi_intrs > 0)
+ enable_irq(ar_pci->pdev->irq);
+ else
+ ath10k_pci_enable_legacy_irq(ar);
+}
+
static int ath10k_pci_hif_start(struct ath10k *ar)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
goto err_early_irq;
}
- ath10k_ce_enable_interrupts(ar);
+ ath10k_pci_irq_enable(ar);
/* Post buffers once to start things off. */
ret = ath10k_pci_post_rx(ar);
return 0;
err_stop:
- ath10k_ce_disable_interrupts(ar);
+ ath10k_pci_irq_disable(ar);
ath10k_pci_free_irq(ar);
ath10k_pci_kill_tasklet(ar);
err_early_irq:
if (WARN_ON(!ar_pci->started))
return;
- ret = ath10k_ce_disable_interrupts(ar);
- if (ret)
- ath10k_warn("failed to disable CE interrupts: %d\n", ret);
-
+ ath10k_pci_irq_disable(ar);
ath10k_pci_free_irq(ar);
ath10k_pci_kill_tasklet(ar);