Merge tag 'pci-v4.17-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[muen/linux.git] / drivers / pci / probe.c
index 3c365dc..ac91b6f 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * probe.c - PCI detection and setup code
+ * PCI detection and setup code
  */
 
 #include <linux/kernel.h>
@@ -330,6 +330,10 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
        if (dev->non_compliant_bars)
                return;
 
+       /* Per PCIe r4.0, sec 9.3.4.1.11, the VF BARs are all RO Zero */
+       if (dev->is_virtfn)
+               return;
+
        for (pos = 0; pos < howmany; pos++) {
                struct resource *res = &dev->resource[pos];
                reg = PCI_BASE_ADDRESS_0 + (pos << 2);
@@ -541,6 +545,16 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
        INIT_LIST_HEAD(&bridge->windows);
        bridge->dev.release = pci_release_host_bridge_dev;
 
+       /*
+        * We assume we can manage these PCIe features.  Some systems may
+        * reserve these for use by the platform itself, e.g., an ACPI BIOS
+        * may implement its own AER handling and use _OSC to prevent the
+        * OS from interfering.
+        */
+       bridge->native_aer = 1;
+       bridge->native_hotplug = 1;
+       bridge->native_pme = 1;
+
        return bridge;
 }
 EXPORT_SYMBOL(pci_alloc_host_bridge);
@@ -593,7 +607,7 @@ const unsigned char pcie_link_speed[] = {
        PCIE_SPEED_2_5GT,               /* 1 */
        PCIE_SPEED_5_0GT,               /* 2 */
        PCIE_SPEED_8_0GT,               /* 3 */
-       PCI_SPEED_UNKNOWN,              /* 4 */
+       PCIE_SPEED_16_0GT,              /* 4 */
        PCI_SPEED_UNKNOWN,              /* 5 */
        PCI_SPEED_UNKNOWN,              /* 6 */
        PCI_SPEED_UNKNOWN,              /* 7 */
@@ -1231,6 +1245,13 @@ static void pci_read_irq(struct pci_dev *dev)
 {
        unsigned char irq;
 
+       /* VFs are not allowed to use INTx, so skip the config reads */
+       if (dev->is_virtfn) {
+               dev->pin = 0;
+               dev->irq = 0;
+               return;
+       }
+
        pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq);
        dev->pin = irq;
        if (irq)
@@ -1390,6 +1411,43 @@ int pci_cfg_space_size(struct pci_dev *dev)
        return PCI_CFG_SPACE_SIZE;
 }
 
+static u32 pci_class(struct pci_dev *dev)
+{
+       u32 class;
+
+#ifdef CONFIG_PCI_IOV
+       if (dev->is_virtfn)
+               return dev->physfn->sriov->class;
+#endif
+       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+       return class;
+}
+
+static void pci_subsystem_ids(struct pci_dev *dev, u16 *vendor, u16 *device)
+{
+#ifdef CONFIG_PCI_IOV
+       if (dev->is_virtfn) {
+               *vendor = dev->physfn->sriov->subsystem_vendor;
+               *device = dev->physfn->sriov->subsystem_device;
+               return;
+       }
+#endif
+       pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, vendor);
+       pci_read_config_word(dev, PCI_SUBSYSTEM_ID, device);
+}
+
+static u8 pci_hdr_type(struct pci_dev *dev)
+{
+       u8 hdr_type;
+
+#ifdef CONFIG_PCI_IOV
+       if (dev->is_virtfn)
+               return dev->physfn->sriov->hdr_type;
+#endif
+       pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);
+       return hdr_type;
+}
+
 #define LEGACY_IO_RESOURCE     (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
 
 static void pci_msi_setup_pci_dev(struct pci_dev *dev)
@@ -1455,8 +1513,7 @@ int pci_setup_device(struct pci_dev *dev)
        struct pci_bus_region region;
        struct resource *res;
 
-       if (pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type))
-               return -EIO;
+       hdr_type = pci_hdr_type(dev);
 
        dev->sysdata = dev->bus->sysdata;
        dev->dev.parent = dev->bus->bridge;
@@ -1478,7 +1535,8 @@ int pci_setup_device(struct pci_dev *dev)
                     dev->bus->number, PCI_SLOT(dev->devfn),
                     PCI_FUNC(dev->devfn));
 
-       pci_read_config_dword(dev, PCI_CLASS_REVISION, &class);
+       class = pci_class(dev);
+
        dev->revision = class & 0xff;
        dev->class = class >> 8;                    /* upper 3 bytes */
 
@@ -1518,8 +1576,8 @@ int pci_setup_device(struct pci_dev *dev)
                        goto bad;
                pci_read_irq(dev);
                pci_read_bases(dev, 6, PCI_ROM_ADDRESS);
-               pci_read_config_word(dev, PCI_SUBSYSTEM_VENDOR_ID, &dev->subsystem_vendor);
-               pci_read_config_word(dev, PCI_SUBSYSTEM_ID, &dev->subsystem_device);
+
+               pci_subsystem_ids(dev, &dev->subsystem_vendor, &dev->subsystem_device);
 
                /*
                 * Do the ugly legacy mode stuff here rather than broken chip
@@ -2122,6 +2180,9 @@ static void pci_init_capabilities(struct pci_dev *dev)
 
        /* Advanced Error Reporting */
        pci_aer_init(dev);
+
+       if (pci_probe_reset_function(dev) == 0)
+               dev->reset_fn = 1;
 }
 
 /*