]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/pci/pcie/portdrv_core.c
PM: Allow PCI devices to suspend/resume asynchronously
[net-next-2.6.git] / drivers / pci / pcie / portdrv_core.c
index b174188ac1212e4f128190c9a8ee78c3b1ef9962..e73effbe402c55e82be4d8a821b3d39e64f96bac 100644 (file)
@@ -186,16 +186,24 @@ static int pcie_port_enable_msix(struct pci_dev *dev, int *vectors, int mask)
  */
 static int init_service_irqs(struct pci_dev *dev, int *irqs, int mask)
 {
-       int i, irq;
+       int i, irq = -1;
+
+       /* We have to use INTx if MSI cannot be used for PCIe PME. */
+       if ((mask & PCIE_PORT_SERVICE_PME) && pcie_pme_no_msi()) {
+               if (dev->pin)
+                       irq = dev->irq;
+               goto no_msi;
+       }
 
        /* Try to use MSI-X if supported */
        if (!pcie_port_enable_msix(dev, irqs, mask))
                return 0;
+
        /* We're not going to use MSI-X, so try MSI and fall back to INTx */
-       irq = -1;
        if (!pci_enable_msi(dev) || dev->pin)
                irq = dev->irq;
 
+ no_msi:
        for (i = 0; i < PCIE_PORT_DEVICE_MAXSERVICES; i++)
                irqs[i] = irq;
        irqs[PCIE_PORT_SERVICE_VC_SHIFT] = -1;
@@ -277,6 +285,7 @@ static int pcie_device_init(struct pci_dev *pdev, int service, int irq)
                     pci_name(pdev),
                     get_descriptor_id(pdev->pcie_type, service));
        device->parent = &pdev->dev;
+       device_enable_async_suspend(device);
 
        retval = device_register(device);
        if (retval)