diff options
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 149 |
1 files changed, 118 insertions, 31 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cefd636681b6..0b2be174d981 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -326,8 +326,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) struct resource *res = &dev->resource[PCI_ROM_RESOURCE]; dev->rom_base_reg = rom; res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | - IORESOURCE_READONLY | IORESOURCE_CACHEABLE | - IORESOURCE_SIZEALIGN; + IORESOURCE_READONLY | IORESOURCE_SIZEALIGN; __pci_read_base(dev, pci_bar_mem32, res, rom); } } @@ -661,6 +660,35 @@ static void pci_set_bus_speed(struct pci_bus *bus) } } +static struct irq_domain *pci_host_bridge_msi_domain(struct pci_bus *bus) +{ + struct irq_domain *d; + + /* + * Any firmware interface that can resolve the msi_domain + * should be called from here. + */ + d = pci_host_bridge_of_msi_domain(bus); + + return d; +} + +static void pci_set_bus_msi_domain(struct pci_bus *bus) +{ + struct irq_domain *d; + + /* + * Either bus is the root, and we must obtain it from the + * firmware, or we inherit it from the bridge device. + */ + if (pci_is_root_bus(bus)) + d = pci_host_bridge_msi_domain(bus); + else + d = dev_get_msi_domain(&bus->self->dev); + + dev_set_msi_domain(&bus->dev, d); +} + static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr) { @@ -714,6 +742,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, bridge->subordinate = child; add_dev: + pci_set_bus_msi_domain(child); ret = device_register(&child->dev); WARN_ON(ret < 0); @@ -826,6 +855,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 +918,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 { /* @@ -997,7 +1032,12 @@ void set_pcie_port_type(struct pci_dev *pdev) else if (type == PCI_EXP_TYPE_UPSTREAM || type == PCI_EXP_TYPE_DOWNSTREAM) { parent = pci_upstream_bridge(pdev); - if (!parent->has_secondary_link) + + /* + * Usually there's an upstream device (Root Port or Switch + * Downstream Port), but we can't assume one exists. + */ + if (parent && !parent->has_secondary_link) pdev->has_secondary_link = 1; } } @@ -1103,7 +1143,7 @@ int pci_cfg_space_size(struct pci_dev *dev) #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) -static void pci_msi_setup_pci_dev(struct pci_dev *dev) +void pci_msi_setup_pci_dev(struct pci_dev *dev) { /* * Disable the MSI hardware to avoid screaming interrupts @@ -1133,7 +1173,6 @@ int pci_setup_device(struct pci_dev *dev) { u32 class; u8 hdr_type; - struct pci_slot *slot; int pos = 0; struct pci_bus_region region; struct resource *res; @@ -1149,10 +1188,7 @@ int pci_setup_device(struct pci_dev *dev) dev->error_state = pci_channel_io_normal; set_pcie_port_type(dev); - list_for_each_entry(slot, &dev->bus->slots, list) - if (PCI_SLOT(dev->devfn) == slot->number) - dev->slot = slot; - + pci_dev_assign_slot(dev); /* Assume 32-bit PCI; let 64-bit PCI cards (which are far rarer) set this higher, assuming the system even supports it. */ dev->dma_mask = 0xffffffff; @@ -1268,13 +1304,51 @@ int pci_setup_device(struct pci_dev *dev) bad: dev_err(&dev->dev, "ignoring class %#08x (doesn't match header type %02x)\n", dev->class, dev->hdr_type); - dev->class = PCI_CLASS_NOT_DEFINED; + dev->class = PCI_CLASS_NOT_DEFINED << 8; } /* We found a fine healthy device, go go go... */ return 0; } +static void pci_configure_mps(struct pci_dev *dev) +{ + struct pci_dev *bridge = pci_upstream_bridge(dev); + int mps, p_mps, rc; + + if (!pci_is_pcie(dev) || !bridge || !pci_is_pcie(bridge)) + return; + + mps = pcie_get_mps(dev); + p_mps = pcie_get_mps(bridge); + + if (mps == p_mps) + return; + + if (pcie_bus_config == PCIE_BUS_TUNE_OFF) { + dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n", + mps, pci_name(bridge), p_mps); + return; + } + + /* + * Fancier MPS configuration is done later by + * pcie_bus_configure_settings() + */ + if (pcie_bus_config != PCIE_BUS_DEFAULT) + return; + + rc = pcie_set_mps(dev, p_mps); + if (rc) { + dev_warn(&dev->dev, "can't set Max Payload Size to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n", + p_mps); + return; + } + + dev_info(&dev->dev, "Max Payload Size set to %d (was %d, max %d)\n", + p_mps, mps, 128 << dev->pcie_mpss); +} + static struct hpp_type0 pci_default_type0 = { .revision = 1, .cache_line_size = 8, @@ -1396,6 +1470,8 @@ static void pci_configure_device(struct pci_dev *dev) struct hotplug_params hpp; int ret; + pci_configure_mps(dev); + memset(&hpp, 0, sizeof(hpp)); ret = pci_get_hp_params(dev, &hpp); if (ret) @@ -1540,10 +1616,24 @@ static void pci_init_capabilities(struct pci_dev *dev) /* Single Root I/O Virtualization */ pci_iov_init(dev); + /* Address Translation Services */ + pci_ats_init(dev); + /* Enable ACS P2P upstream forwarding */ pci_enable_acs(dev); } +static void pci_set_msi_domain(struct pci_dev *dev) +{ + /* + * If no domain has been set through the pcibios_add_device + * callback, inherit the default from the bus device. + */ + if (!dev_get_msi_domain(&dev->dev)) + dev_set_msi_domain(&dev->dev, + dev_get_msi_domain(&dev->bus->dev)); +} + void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) { int ret; @@ -1585,6 +1675,9 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus) ret = pcibios_add_device(dev); WARN_ON(ret < 0); + /* Setup MSI irq domain */ + pci_set_msi_domain(dev); + /* Notifier could use PCI capabilities */ dev->match_driver = false; ret = device_add(&dev->dev); @@ -1791,22 +1884,6 @@ static void pcie_write_mrrs(struct pci_dev *dev) dev_err(&dev->dev, "MRRS was unable to be configured with a safe value. If problems are experienced, try running with pci=pcie_bus_safe\n"); } -static void pcie_bus_detect_mps(struct pci_dev *dev) -{ - struct pci_dev *bridge = dev->bus->self; - int mps, p_mps; - - if (!bridge) - return; - - mps = pcie_get_mps(dev); - p_mps = pcie_get_mps(bridge); - - if (mps != p_mps) - dev_warn(&dev->dev, "Max Payload Size %d, but upstream %s set to %d; if necessary, use \"pci=pcie_bus_safe\" and report a bug\n", - mps, pci_name(bridge), p_mps); -} - static int pcie_bus_configure_set(struct pci_dev *dev, void *data) { int mps, orig_mps; @@ -1814,10 +1891,9 @@ static int pcie_bus_configure_set(struct pci_dev *dev, void *data) if (!pci_is_pcie(dev)) return 0; - if (pcie_bus_config == PCIE_BUS_TUNE_OFF) { - pcie_bus_detect_mps(dev); + if (pcie_bus_config == PCIE_BUS_TUNE_OFF || + pcie_bus_config == PCIE_BUS_DEFAULT) return 0; - } mps = 128 << *(u8 *)data; orig_mps = pcie_get_mps(dev); @@ -1975,6 +2051,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, b->bridge = get_device(&bridge->dev); device_enable_async_suspend(b->bridge); pci_set_bus_of_node(b); + pci_set_bus_msi_domain(b); if (!parent) set_dev_node(b->bridge, pcibus_to_node(b)); @@ -2096,8 +2173,9 @@ void pci_bus_release_busn_res(struct pci_bus *b) res, ret ? "can not be" : "is"); } -struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, - struct pci_ops *ops, void *sysdata, struct list_head *resources) +struct pci_bus *pci_scan_root_bus_msi(struct device *parent, int bus, + struct pci_ops *ops, void *sysdata, + struct list_head *resources, struct msi_controller *msi) { struct resource_entry *window; bool found = false; @@ -2114,6 +2192,8 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, if (!b) return NULL; + b->msi = msi; + if (!found) { dev_info(&b->dev, "No busn resource found for root bus, will use [bus %02x-ff]\n", @@ -2128,6 +2208,13 @@ struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, return b; } + +struct pci_bus *pci_scan_root_bus(struct device *parent, int bus, + struct pci_ops *ops, void *sysdata, struct list_head *resources) +{ + return pci_scan_root_bus_msi(parent, bus, ops, sysdata, resources, + NULL); +} EXPORT_SYMBOL(pci_scan_root_bus); struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, |