]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/pci/probe.c
Merge branch 'pci/resource' into next
[linux-beck.git] / drivers / pci / probe.c
index edb1984201e9702162321c50f33f76ba362bac5a..8004f67c57ec6ae59157714e507f06429127765e 100644 (file)
@@ -15,7 +15,7 @@
 #include <linux/pci-aspm.h>
 #include <linux/aer.h>
 #include <linux/acpi.h>
-#include <asm-generic/pci-bridge.h>
+#include <linux/irqdomain.h>
 #include "pci.h"
 
 #define CARDBUS_LATENCY_TIMER  176     /* secondary latency timer */
@@ -179,6 +179,9 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        u16 orig_cmd;
        struct pci_bus_region region, inverted_region;
 
+       if (dev->non_compliant_bars)
+               return 0;
+
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
        /* No printks while decoding is disabled! */
@@ -672,6 +675,22 @@ static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus)
         * should be called from here.
         */
        d = pci_host_bridge_of_msi_domain(bus);
+       if (!d)
+               d = pci_host_bridge_acpi_msi_domain(bus);
+
+#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+       /*
+        * If no IRQ domain was found via the OF tree, try looking it up
+        * directly through the fwnode_handle.
+        */
+       if (!d) {
+               struct fwnode_handle *fwnode = pci_root_bus_fwnode(bus);
+
+               if (fwnode)
+                       d = irq_find_matching_fwnode(fwnode,
+                                                    DOMAIN_BUS_PCI_MSI);
+       }
+#endif
 
        return d;
 }
@@ -756,6 +775,12 @@ add_dev:
 
        pcibios_add_bus(child);
 
+       if (child->ops->add_bus) {
+               ret = child->ops->add_bus(child);
+               if (WARN_ON(ret < 0))
+                       dev_err(&child->dev, "failed to add bus: %d\n", ret);
+       }
+
        /* Create legacy_io and legacy_mem files for this bus */
        pci_create_legacy_files(child);
 
@@ -1107,14 +1132,11 @@ static int pci_cfg_space_size_ext(struct pci_dev *dev)
        int pos = PCI_CFG_SPACE_SIZE;
 
        if (pci_read_config_dword(dev, pos, &status) != PCIBIOS_SUCCESSFUL)
-               goto fail;
+               return PCI_CFG_SPACE_SIZE;
        if (status == 0xffffffff || pci_ext_cfg_is_aliased(dev))
-               goto fail;
+               return PCI_CFG_SPACE_SIZE;
 
        return PCI_CFG_SPACE_EXP_SIZE;
-
- fail:
-       return PCI_CFG_SPACE_SIZE;
 }
 
 int pci_cfg_space_size(struct pci_dev *dev)
@@ -1127,25 +1149,23 @@ int pci_cfg_space_size(struct pci_dev *dev)
        if (class == PCI_CLASS_BRIDGE_HOST)
                return pci_cfg_space_size_ext(dev);
 
-       if (!pci_is_pcie(dev)) {
-               pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
-               if (!pos)
-                       goto fail;
+       if (pci_is_pcie(dev))
+               return pci_cfg_space_size_ext(dev);
 
-               pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
-               if (!(status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ)))
-                       goto fail;
-       }
+       pos = pci_find_capability(dev, PCI_CAP_ID_PCIX);
+       if (!pos)
+               return PCI_CFG_SPACE_SIZE;
 
-       return pci_cfg_space_size_ext(dev);
+       pci_read_config_dword(dev, pos + PCI_X_STATUS, &status);
+       if (status & (PCI_X_STATUS_266MHZ | PCI_X_STATUS_533MHZ))
+               return pci_cfg_space_size_ext(dev);
 
- fail:
        return PCI_CFG_SPACE_SIZE;
 }
 
 #define LEGACY_IO_RESOURCE     (IORESOURCE_IO | IORESOURCE_PCI_FIXED)
 
-void pci_msi_setup_pci_dev(struct pci_dev *dev)
+static void pci_msi_setup_pci_dev(struct pci_dev *dev)
 {
        /*
         * Disable the MSI hardware to avoid screaming interrupts
@@ -1174,6 +1194,7 @@ void pci_msi_setup_pci_dev(struct pci_dev *dev)
 int pci_setup_device(struct pci_dev *dev)
 {
        u32 class;
+       u16 cmd;
        u8 hdr_type;
        int pos = 0;
        struct pci_bus_region region;
@@ -1212,13 +1233,21 @@ int pci_setup_device(struct pci_dev *dev)
        /* "Unknown power state" */
        dev->current_state = PCI_UNKNOWN;
 
-       pci_msi_setup_pci_dev(dev);
-
        /* Early fixups, before probing the BARs */
        pci_fixup_device(pci_fixup_early, dev);
        /* device class may be changed after fixup */
        class = dev->class >> 8;
 
+       if (dev->non_compliant_bars) {
+               pci_read_config_word(dev, PCI_COMMAND, &cmd);
+               if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) {
+                       dev_info(&dev->dev, "device has non-compliant BARs; disabling IO/MEM decoding\n");
+                       cmd &= ~PCI_COMMAND_IO;
+                       cmd &= ~PCI_COMMAND_MEMORY;
+                       pci_write_config_word(dev, PCI_COMMAND, cmd);
+               }
+       }
+
        switch (dev->hdr_type) {                    /* header type */
        case PCI_HEADER_TYPE_NORMAL:                /* standard header */
                if (class == PCI_CLASS_BRIDGE_PCI)
@@ -1603,8 +1632,8 @@ static void pci_init_capabilities(struct pci_dev *dev)
        /* Enhanced Allocation */
        pci_ea_init(dev);
 
-       /* MSI/MSI-X list */
-       pci_msi_init_pci_dev(dev);
+       /* Setup MSI caps & disable MSI/MSI-X interrupts */
+       pci_msi_setup_pci_dev(dev);
 
        /* Buffers for saving PCIe and PCI-X capabilities */
        pci_allocate_cap_save_buffers(dev);
@@ -1613,7 +1642,7 @@ static void pci_init_capabilities(struct pci_dev *dev)
        pci_pm_init(dev);
 
        /* Vital Product Data */
-       pci_vpd_pci22_init(dev);
+       pci_vpd_init(dev);
 
        /* Alternative Routing-ID Forwarding */
        pci_configure_ari(dev);
@@ -1808,6 +1837,13 @@ static int only_one_child(struct pci_bus *bus)
                return 0;
        if (pci_pcie_type(parent) == PCI_EXP_TYPE_ROOT_PORT)
                return 1;
+
+       /*
+        * PCIe downstream ports are bridges that normally lead to only a
+        * device 0, but if PCI_SCAN_ALL_PCIE_DEVS is set, scan all
+        * possible devices, not just device 0.  See PCIe spec r3.0,
+        * sec 7.3.1.
+        */
        if (parent->has_secondary_link &&
            !pci_has_flag(PCI_SCAN_ALL_PCIE_DEVS))
                return 1;