PCI: vmd: Free up IRQs on suspend path [Linux 4.9.156]

This Linux kernel change "PCI: vmd: Free up IRQs on suspend path" is included in the Linux 4.9.156 release. This change is authored by Scott Bauer <scott.bauer [at] intel.com> on Fri Aug 11 14:54:32 2017 -0600. The commit for this change in Linux stable tree is b666676 (patch) which is from upstream commit e2b1820. 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 e2b1820.

PCI: vmd: Free up IRQs on suspend path

commit e2b1820bd5d0962d6f271b0d47c3a0e38647df2f upstream.

Free up the IRQs we request on the suspend path and reallocate them on the
resume path.

Fixes this error:

  CPU 111 disable failed: CPU has 9 vectors assigned and there are only 0 available.
  Error taking CPU111 down: -34
  Non-boot CPUs are not disabled
  Enabling non-boot CPUs ...

Signed-off-by: Scott Bauer <[email protected]>
Signed-off-by: Bjorn Helgaas <[email protected]>
Acked-by: Keith Busch <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Reviewed-by: Jon Derrick <[email protected]>
Signed-off-by: Sushma Kalakota <[email protected]>

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

 drivers/pci/host/vmd.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c
index 0e7f8f3..9a60098 100644
--- a/drivers/pci/host/vmd.c
+++ b/drivers/pci/host/vmd.c
@@ -731,6 +731,11 @@ static void vmd_remove(struct pci_dev *dev)
 static int vmd_suspend(struct device *dev)
 {
    struct pci_dev *pdev = to_pci_dev(dev);
+   struct vmd_dev *vmd = pci_get_drvdata(pdev);
+   int i;
+
+   for (i = 0; i < vmd->msix_count; i++)
+                devm_free_irq(dev, pci_irq_vector(pdev, i), &vmd->irqs[i]);

    pci_save_state(pdev);
    return 0;
@@ -739,6 +744,16 @@ static int vmd_suspend(struct device *dev)
 static int vmd_resume(struct device *dev)
 {
    struct pci_dev *pdev = to_pci_dev(dev);
+   struct vmd_dev *vmd = pci_get_drvdata(pdev);
+   int err, i;
+
+   for (i = 0; i < vmd->msix_count; i++) {
+       err = devm_request_irq(dev, pci_irq_vector(pdev, i),
+                      vmd_irq, IRQF_NO_THREAD,
+                      "vmd", &vmd->irqs[i]);
+       if (err)
+           return err;
+   }

    pci_restore_state(pdev);
    return 0;

Leave a Reply

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