Merge branches 'pci/irq', 'pci/misc', 'pci/resource' and 'pci/virtualization' into...
authorBjorn Helgaas <bhelgaas@google.com>
Wed, 5 Aug 2015 01:54:05 +0000 (20:54 -0500)
committerBjorn Helgaas <bhelgaas@google.com>
Wed, 5 Aug 2015 01:54:05 +0000 (20:54 -0500)
* pci/irq:
  PCI/MSI: Free legacy IRQ when enabling MSI/MSI-X
  PCI: Add helpers to manage pci_dev->irq and pci_dev->irq_managed
  PCI, x86: Implement pcibios_alloc_irq() and pcibios_free_irq()
  PCI: Add pcibios_alloc_irq() and pcibios_free_irq()

* pci/misc:
  PCI: Remove unused "pci_probe" flags
  PCI: Add VPD function 0 quirk for Intel Ethernet devices
  PCI: Add dev_flags bit to access VPD through function 0
  PCI / ACPI: Fix pci_acpi_optimize_delay() comment
  PCI: Remove a broken link in quirks.c
  PCI: Remove useless redundant code
  PCI: Simplify pci_find_(ext_)capability() return value checks
  PCI: Move PCI_FIND_CAP_TTL to pci.h and use it in quirks
  PCI: Add pcie_downstream_port() (true for Root and Switch Downstream Ports)
  PCI: Fix pcie_port_device_resume() comment
  PCI: Shift PCI_CLASS_NOT_DEFINED consistently with other classes
  PCI: Revert aeb30016fec3 ("PCI: add Intel USB specific reset method")
  PCI: Fix TI816X class code quirk
  PCI: Fix generic NCR 53c810 class code quirk
  PCI: Use PCI_CLASS_SERIAL_USB instead of bare number
  PCI: Add quirk for Intersil/Techwell TW686[4589] AV capture cards
  PCI: Remove Intel Cherrytrail D3 delays

* pci/resource:
  PCI: Call pci_read_bridge_bases() from core instead of arch code

* pci/virtualization:
  PCI: Restore ACS configuration as part of pci_restore_state()

25 files changed:
arch/alpha/kernel/pci.c
arch/arm64/boot/dts/apm/apm-storm.dtsi
arch/frv/mb93090-mb00/pci-vdk.c
arch/ia64/pci/pci.c
arch/microblaze/pci/pci-common.c
arch/mips/pci/pci.c
arch/mn10300/unit-asb2305/pci.c
arch/powerpc/kernel/pci-common.c
arch/x86/include/asm/pci_x86.h
arch/x86/pci/common.c
arch/x86/pci/intel_mid_pci.c
arch/x86/pci/irq.c
arch/xtensa/kernel/pci.c
drivers/acpi/pci_irq.c
drivers/parisc/dino.c
drivers/parisc/lba_pci.c
drivers/pci/host/pci-xgene-msi.c
drivers/pci/host/pci-xgene.c
drivers/pci/host/pcie-designware.c
drivers/pci/host/pcie-xilinx.c
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/probe.c
include/linux/pci.h

index 82f738e..cded02c 100644 (file)
@@ -242,12 +242,7 @@ pci_restore_srm_config(void)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
-                  (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               pci_read_bridge_bases(bus);
-       } 
+       struct pci_dev *dev;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
                pdev_save_srm_config(dev);
index 0689c3f..b49482e 100644 (file)
                                0xe0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
                        ranges = <0x01000000 0x00 0x00000000 0xe0 0x10000000 0x00 0x00010000   /* io */
-                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000>; /* mem */
+                                 0x02000000 0x00 0x80000000 0xe1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xf0 0x00000000 0xf0 0x00000000 0x10 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f2c0000 0x0 0x00010000   /* Controller registers */
                                0xd0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xd1 0x80000000 0x00 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0xd0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xd1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xd8 0x00000000 0xd8 0x00000000 0x08 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg =  < 0x00 0x1f2d0000 0x0 0x00010000   /* Controller registers */
                                 0x90 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0x90 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0x91 0x80000000 0x0 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0x90 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0x91 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0x94 0x00000000 0x94 0x00000000 0x04 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f500000 0x0 0x00010000   /* Controller registers */
                                0xa0 0xd0000000 0x0 0x00040000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xa0 0x10000000 0x0 0x00010000   /* io   */
-                                 0x02000000 0x0 0x80000000 0xa1 0x80000000 0x0 0x80000000>; /* mem  */
+                       ranges = <0x01000000 0x00 0x00000000 0xa0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xa1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xb0 0x00000000 0xb0 0x00000000 0x10 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
                        reg = < 0x00 0x1f510000 0x0 0x00010000   /* Controller registers */
                                0xc0 0xd0000000 0x0 0x00200000>; /* PCI config space */
                        reg-names = "csr", "cfg";
-                       ranges = <0x01000000 0x0 0x00000000 0xc0 0x10000000 0x0 0x00010000   /* io  */
-                                 0x02000000 0x0 0x80000000 0xc1 0x80000000 0x0 0x80000000>; /* mem */
+                       ranges = <0x01000000 0x00 0x00000000 0xc0 0x10000000 0x00 0x00010000   /* io  */
+                                 0x02000000 0x00 0x80000000 0xc1 0x80000000 0x00 0x80000000   /* mem */
+                                 0x43000000 0xc8 0x00000000 0xc8 0x00000000 0x08 0x00000000>; /* mem */
                        dma-ranges = <0x42000000 0x80 0x00000000 0x80 0x00000000 0x00 0x80000000
                                      0x42000000 0x00 0x00000000 0x00 0x00000000 0x80 0x00000000>;
                        interrupt-map-mask = <0x0 0x0 0x0 0x7>;
index f211839..f9c86c4 100644 (file)
@@ -294,8 +294,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        printk("### PCIBIOS_FIXUP_BUS(%d)\n",bus->number);
 #endif
 
-       pci_read_bridge_bases(bus);
-
        if (bus->number == 0) {
                struct pci_dev *dev;
                list_for_each_entry(dev, &bus->devices, bus_list) {
index 7cc3be9..d89b601 100644 (file)
@@ -533,10 +533,9 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
-       if (b->self) {
-               pci_read_bridge_bases(b);
+       if (b->self)
                pcibios_fixup_bridge_resources(b->self);
-       }
+
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
        platform_pci_fixup_bus(b);
index ae838ed..6b8b752 100644 (file)
@@ -863,14 +863,7 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases. This is -not- called when generating the PCI tree from
-        * the OF device-tree.
-        */
-       if (bus->self != NULL)
-               pci_read_bridge_bases(bus);
-
-       /* Now fixup the bus bus */
+       /* Fixup the bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index b8a0bf5..c6996cf 100644 (file)
@@ -311,12 +311,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       struct pci_dev *dev = bus->self;
-
-       if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
-           (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
-               pci_read_bridge_bases(bus);
-       }
 }
 
 EXPORT_SYMBOL(PCIBIOS_MIN_IO);
index 3dfe2d3..deaa893 100644 (file)
@@ -324,7 +324,6 @@ void pcibios_fixup_bus(struct pci_bus *bus)
        struct pci_dev *dev;
 
        if (bus->self) {
-               pci_read_bridge_bases(bus);
                pcibios_fixup_bridge_resources(bus->self);
        }
 
index b9de34d..02c1d5d 100644 (file)
@@ -1044,13 +1044,7 @@ void pcibios_set_master(struct pci_dev *dev)
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       /* When called from the generic PCI probe, read PCI<->PCI bridge
-        * bases. This is -not- called when generating the PCI tree from
-        * the OF device-tree.
-        */
-       pci_read_bridge_bases(bus);
-
-       /* Now fixup the bus bus */
+       /* Fixup the bus */
        pcibios_setup_bus_self(bus);
 
        /* Now fixup devices on that bus */
index 164e3f8..fa1195d 100644 (file)
@@ -93,8 +93,6 @@ extern raw_spinlock_t pci_config_lock;
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
-extern bool mp_should_keep_irq(struct device *dev);
-
 struct pci_raw_ops {
        int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
                                                int reg, int len, u32 *val);
index 8fd6f44..09d3afc 100644 (file)
@@ -166,7 +166,6 @@ void pcibios_fixup_bus(struct pci_bus *b)
 {
        struct pci_dev *dev;
 
-       pci_read_bridge_bases(b);
        list_for_each_entry(dev, &b->devices, bus_list)
                pcibios_fixup_device_resources(dev);
 }
@@ -673,24 +672,22 @@ int pcibios_add_device(struct pci_dev *dev)
        return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+int pcibios_alloc_irq(struct pci_dev *dev)
 {
-       int err;
-
-       if ((err = pci_enable_resources(dev, mask)) < 0)
-               return err;
-
-       if (!pci_dev_msi_enabled(dev))
-               return pcibios_enable_irq(dev);
-       return 0;
+       return pcibios_enable_irq(dev);
 }
 
-void pcibios_disable_device (struct pci_dev *dev)
+void pcibios_free_irq(struct pci_dev *dev)
 {
-       if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
+       if (pcibios_disable_irq)
                pcibios_disable_irq(dev);
 }
 
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       return pci_enable_resources(dev, mask);
+}
+
 int pci_ext_cfg_avail(void)
 {
        if (raw_pci_ext_ops)
index 2706230..22aaefb 100644 (file)
@@ -211,7 +211,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
        struct irq_alloc_info info;
        int polarity;
 
-       if (dev->irq_managed && dev->irq > 0)
+       if (pci_has_managed_irq(dev))
                return 0;
 
        if (intel_mid_identify_cpu() == INTEL_MID_CPU_CHIP_TANGIER)
@@ -234,10 +234,13 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
 
 static void intel_mid_pci_irq_disable(struct pci_dev *dev)
 {
-       if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
-           dev->irq > 0) {
+       if (pci_has_managed_irq(dev)) {
                mp_unmap_irq(dev->irq);
                dev->irq_managed = 0;
+               /*
+                * Don't reset dev->irq here, otherwise
+                * intel_mid_pci_irq_enable() will fail on next call.
+                */
        }
 }
 
index 9bd1154..32e7034 100644 (file)
@@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        struct pci_dev *temp_dev;
                        int irq;
 
-                       if (dev->irq_managed && dev->irq > 0)
+                       if (pci_has_managed_irq(dev))
                                return 0;
 
                        irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
@@ -1230,8 +1230,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
                        }
                        dev = temp_dev;
                        if (irq >= 0) {
-                               dev->irq_managed = 1;
-                               dev->irq = irq;
+                               pci_set_managed_irq(dev, irq);
                                dev_info(&dev->dev, "PCI->APIC IRQ transform: "
                                         "INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
                                return 0;
@@ -1257,24 +1256,10 @@ static int pirq_enable_irq(struct pci_dev *dev)
        return 0;
 }
 
-bool mp_should_keep_irq(struct device *dev)
-{
-       if (dev->power.is_prepared)
-               return true;
-#ifdef CONFIG_PM
-       if (dev->power.runtime_status == RPM_SUSPENDING)
-               return true;
-#endif
-
-       return false;
-}
-
 static void pirq_disable_irq(struct pci_dev *dev)
 {
-       if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
-           dev->irq_managed && dev->irq) {
+       if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
                mp_unmap_irq(dev->irq);
-               dev->irq = 0;
-               dev->irq_managed = 0;
+               pci_reset_managed_irq(dev);
        }
 }
index b848cc3..d27b4dc 100644 (file)
@@ -210,10 +210,6 @@ subsys_initcall(pcibios_init);
 
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-       if (bus->parent) {
-               /* This is a subordinate bridge */
-               pci_read_bridge_bases(bus);
-       }
 }
 
 void pcibios_set_master(struct pci_dev *dev)
index 304eccb..afa16c5 100644 (file)
@@ -412,7 +412,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                return 0;
        }
 
-       if (dev->irq_managed && dev->irq > 0)
+       if (pci_has_managed_irq(dev))
                return 0;
 
        entry = acpi_pci_irq_lookup(dev, pin);
@@ -457,8 +457,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
                kfree(entry);
                return rc;
        }
-       dev->irq = rc;
-       dev->irq_managed = 1;
+       pci_set_managed_irq(dev, rc);
 
        if (link)
                snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
@@ -481,17 +480,9 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        u8 pin;
 
        pin = dev->pin;
-       if (!pin || !dev->irq_managed || dev->irq <= 0)
+       if (!pin || !pci_has_managed_irq(dev))
                return;
 
-       /* Keep IOAPIC pin configuration when suspending */
-       if (dev->dev.power.is_prepared)
-               return;
-#ifdef CONFIG_PM
-       if (dev->dev.power.runtime_status == RPM_SUSPENDING)
-               return;
-#endif
-
        entry = acpi_pci_irq_lookup(dev, pin);
        if (!entry)
                return;
@@ -511,6 +502,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
        dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
        if (gsi >= 0) {
                acpi_unregister_gsi(gsi);
-               dev->irq_managed = 0;
+               pci_reset_managed_irq(dev);
        }
 }
index a0580af..baec33c 100644 (file)
@@ -560,9 +560,6 @@ dino_fixup_bus(struct pci_bus *bus)
        } else if (bus->parent) {
                int i;
 
-               pci_read_bridge_bases(bus);
-
-
                for(i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++) {
                        if((bus->self->resource[i].flags & 
                            (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
index dceb9dd..901e1a3 100644 (file)
@@ -693,7 +693,6 @@ lba_fixup_bus(struct pci_bus *bus)
        if (bus->parent) {
                int i;
                /* PCI-PCI Bridge */
-               pci_read_bridge_bases(bus);
                for (i = PCI_BRIDGE_RESOURCES; i < PCI_NUM_RESOURCES; i++)
                        pci_claim_bridge_resource(bus->self, i);
        } else {
index 2d31d4d..9e1889e 100644 (file)
@@ -582,7 +582,6 @@ error:
 static struct platform_driver xgene_msi_driver = {
        .driver = {
                .name = "xgene-msi",
-               .owner = THIS_MODULE,
                .of_match_table = xgene_msi_match_table,
        },
        .probe = xgene_msi_probe,
index a9dfb70..55fe865 100644 (file)
@@ -321,8 +321,16 @@ static int xgene_pcie_map_ranges(struct xgene_pcie_port *port,
                                return ret;
                        break;
                case IORESOURCE_MEM:
-                       xgene_pcie_setup_ob_reg(port, res, OMR1BARL, res->start,
-                                               res->start - window->offset);
+                       if (res->flags & IORESOURCE_PREFETCH)
+                               xgene_pcie_setup_ob_reg(port, res, OMR2BARL,
+                                                       res->start,
+                                                       res->start -
+                                                       window->offset);
+                       else
+                               xgene_pcie_setup_ob_reg(port, res, OMR1BARL,
+                                                       res->start,
+                                                       res->start -
+                                                       window->offset);
                        break;
                case IORESOURCE_BUS:
                        break;
index 69486be..b48b8a2 100644 (file)
@@ -388,7 +388,7 @@ int dw_pcie_host_init(struct pcie_port *pp)
                addrp = of_get_address(np, index, NULL, NULL);
                pp->cfg0_mod_base = of_read_number(addrp, ns);
                pp->cfg1_mod_base = pp->cfg0_mod_base + pp->cfg0_size;
-       } else {
+       } else if (!pp->va_cfg0_base) {
                dev_err(pp->dev, "missing *config* reg space\n");
        }
 
index f1a06a0..dcb9b57 100644 (file)
@@ -449,14 +449,17 @@ static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
                        return IRQ_HANDLED;
                }
 
-               /* Clear interrupt FIFO register 1 */
-               pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
-                          XILINX_PCIE_REG_RPIFR1);
-
-               /* Handle INTx Interrupt */
-               val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
-                       XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
-               generic_handle_irq(irq_find_mapping(port->irq_domain, val));
+               if (!(val & XILINX_PCIE_RPIFR1_MSI_INTR)) {
+                       /* Clear interrupt FIFO register 1 */
+                       pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
+                                  XILINX_PCIE_REG_RPIFR1);
+
+                       /* Handle INTx Interrupt */
+                       val = ((val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
+                               XILINX_PCIE_RPIFR1_INTR_SHIFT) + 1;
+                       generic_handle_irq(irq_find_mapping(port->irq_domain,
+                                                           val));
+               }
        }
 
        if (status & XILINX_PCIE_INTR_MSI) {
index f66be86..bb74238 100644 (file)
@@ -665,6 +665,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec)
        pci_msi_set_enable(dev, 1);
        dev->msi_enabled = 1;
 
+       pcibios_free_irq(dev);
        dev->irq = entry->irq;
        return 0;
 }
@@ -792,9 +793,9 @@ static int msix_capability_init(struct pci_dev *dev,
        /* Set MSI-X enabled bits and unmask the function */
        pci_intx_for_msi(dev, 0);
        dev->msix_enabled = 1;
-
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_MASKALL, 0);
 
+       pcibios_free_irq(dev);
        return 0;
 
 out_avail:
@@ -909,6 +910,7 @@ void pci_msi_shutdown(struct pci_dev *dev)
 
        /* Restore dev->irq to its default pin-assertion irq */
        dev->irq = desc->msi_attrib.default_irq;
+       pcibios_alloc_irq(dev);
 }
 
 void pci_disable_msi(struct pci_dev *dev)
@@ -1009,6 +1011,7 @@ void pci_msix_shutdown(struct pci_dev *dev)
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
        pci_intx_for_msi(dev, 1);
        dev->msix_enabled = 0;
+       pcibios_alloc_irq(dev);
 }
 
 void pci_disable_msix(struct pci_dev *dev)
index 3cb2210..52a880c 100644 (file)
@@ -388,18 +388,31 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
        return error;
 }
 
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+       return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
+
 static int pci_device_probe(struct device *dev)
 {
-       int error = 0;
-       struct pci_driver *drv;
-       struct pci_dev *pci_dev;
+       int error;
+       struct pci_dev *pci_dev = to_pci_dev(dev);
+       struct pci_driver *drv = to_pci_driver(dev->driver);
+
+       error = pcibios_alloc_irq(pci_dev);
+       if (error < 0)
+               return error;
 
-       drv = to_pci_driver(dev->driver);
-       pci_dev = to_pci_dev(dev);
        pci_dev_get(pci_dev);
        error = __pci_device_probe(drv, pci_dev);
-       if (error)
+       if (error) {
+               pcibios_free_irq(pci_dev);
                pci_dev_put(pci_dev);
+       }
 
        return error;
 }
@@ -415,6 +428,7 @@ static int pci_device_remove(struct device *dev)
                        drv->remove(pci_dev);
                        pm_runtime_put_noidle(dev);
                }
+               pcibios_free_irq(pci_dev);
                pci_dev->driver = NULL;
        }
 
index 359b954..8037c27 100644 (file)
@@ -1089,6 +1089,9 @@ void pci_restore_state(struct pci_dev *dev)
 
        pci_restore_pcix_state(dev);
        pci_restore_msi_state(dev);
+
+       /* Restore ACS and IOV configuration state */
+       pci_enable_acs(dev);
        pci_restore_iov_state(dev);
 
        dev->state_saved = false;
index 71bd520..0fb0c74 100644 (file)
@@ -826,6 +826,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
                        child->bridge_ctl = bctl;
                }
 
+               /* Read and initialize bridge resources */
+               pci_read_bridge_bases(child);
+
                cmax = pci_scan_child_bus(child);
                if (cmax > subordinate)
                        dev_warn(&dev->dev, "bridge has subordinate %02x but max busn %02x\n",
@@ -886,6 +889,9 @@ int pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, int pass)
 
                if (!is_cardbus) {
                        child->bridge_ctl = bctl;
+
+                       /* Read and initialize bridge resources */
+                       pci_read_bridge_bases(child);
                        max = pci_scan_child_bus(child);
                } else {
                        /*
index 8edb125..66361df 100644 (file)
@@ -965,6 +965,23 @@ static inline int pci_is_managed(struct pci_dev *pdev)
        return pdev->is_managed;
 }
 
+static inline void pci_set_managed_irq(struct pci_dev *pdev, unsigned int irq)
+{
+       pdev->irq = irq;
+       pdev->irq_managed = 1;
+}
+
+static inline void pci_reset_managed_irq(struct pci_dev *pdev)
+{
+       pdev->irq = 0;
+       pdev->irq_managed = 0;
+}
+
+static inline bool pci_has_managed_irq(struct pci_dev *pdev)
+{
+       return pdev->irq_managed && pdev->irq > 0;
+}
+
 void pci_disable_device(struct pci_dev *dev);
 
 extern unsigned int pcibios_max_latency;
@@ -1647,6 +1664,8 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev,
 int pcibios_add_device(struct pci_dev *dev);
 void pcibios_release_device(struct pci_dev *dev);
 void pcibios_penalize_isa_irq(int irq, int active);
+int pcibios_alloc_irq(struct pci_dev *dev);
+void pcibios_free_irq(struct pci_dev *dev);
 
 #ifdef CONFIG_HIBERNATE_CALLBACKS
 extern struct dev_pm_ops pcibios_pm_ops;