return acp_hw_runtime_resume(dev);
}
+static void acp_disable_msi_on_resume(struct pci_dev *pdev)
+{
+ u16 control;
+
+ if (!pdev->msi_cap)
+ return;
+
+ pci_read_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, &control);
+ if (control & PCI_MSI_FLAGS_ENABLE) {
+ dev_warn(&pdev->dev,
+ "ACP: MSI unexpectedly enabled after resume (flags=0x%04x), disabling\n",
+ control);
+ control &= ~PCI_MSI_FLAGS_ENABLE;
+ pci_write_config_word(pdev, pdev->msi_cap + PCI_MSI_FLAGS, control);
+ }
+}
+
static int snd_acp_resume(struct device *dev)
{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ /*
+ * BIOS/firmware may re-enable MSI in PCI config space during
+ * system resume even though this driver only uses legacy INTx
+ * interrupts. If MSI is left enabled with stale address/data
+ * registers, the device will write interrupts to a bogus address
+ * causing IOMMU IO_PAGE_FAULT and interrupt delivery failure.
+ * Explicitly clear the MSI Enable bit before reinitializing
+ * the ACP hardware.
+ */
+ acp_disable_msi_on_resume(pdev);
return acp_hw_resume(dev);
}