From dff22d2054b5dbb1889f20c03959dd0c494fab8c Mon Sep 17 00:00:00 2001 From: Lorenzo Pieralisi Date: Thu, 9 Jul 2015 11:59:16 +0100 Subject: PCI: Call pci_read_bridge_bases() from core instead of arch code When we scan a PCI bus, we read PCI-PCI bridge window registers with pci_read_bridge_bases() so we can validate the resource hierarchy. Most architectures call pci_read_bridge_bases() from pcibios_fixup_bus(), but PCI-PCI bridges are not arch-specific, so this doesn't need to be in arch-specific code. Call pci_read_bridge_bases() directly from the PCI core instead of from arch code. For alpha and mips, we now call pci_read_bridge_bases() always; previously we only called it if PCI_PROBE_ONLY was set. [bhelgaas: changelog] Signed-off-by: Lorenzo Pieralisi Signed-off-by: Bjorn Helgaas CC: Ralf Baechle CC: James E.J. Bottomley CC: Michael Ellerman CC: Bjorn Helgaas CC: Richard Henderson CC: Benjamin Herrenschmidt CC: David Howells CC: Russell King CC: Tony Luck CC: David S. Miller CC: Ingo Molnar CC: Guenter Roeck CC: Michal Simek CC: Chris Zankel --- arch/powerpc/kernel/pci-common.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index b9de34d44fcb..02c1d5dcee4d 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c @@ -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 */ -- cgit v1.2.3-58-ga151 From 017ffe64e8b8c8db0f50433a71da41c6a4e12710 Mon Sep 17 00:00:00 2001 From: Yijing Wang Date: Fri, 17 Jul 2015 17:16:32 +0800 Subject: PCI: Hold pci_slot_mutex while searching bus->slots list Previously, pci_setup_device() and similar functions searched the pci_bus->slots list without any locking. It was possible for another thread to update the list while we searched it. Add pci_dev_assign_slot() to search the list while holding pci_slot_mutex. [bhelgaas: changelog, fold in CONFIG_SYSFS fix] Tested-by: Guenter Roeck Signed-off-by: Yijing Wang Signed-off-by: Bjorn Helgaas --- arch/powerpc/kernel/pci_of_scan.c | 6 +----- arch/sparc/kernel/pci.c | 6 +----- drivers/pci/probe.c | 6 +----- drivers/pci/slot.c | 11 +++++++++++ include/linux/pci.h | 5 +++++ 5 files changed, 19 insertions(+), 15 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 42e02a2d570b..5e2debfc6ce5 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c @@ -126,7 +126,6 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, { struct pci_dev *dev; const char *type; - struct pci_slot *slot; dev = pci_alloc_dev(bus); if (!dev) @@ -145,10 +144,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, dev->needs_freset = 0; /* pcie fundamental reset required */ 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); dev->vendor = get_int_prop(node, "vendor-id", 0xffff); dev->device = get_int_prop(node, "device-id", 0xffff); dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c index c928bc64b4ba..3a0e1a986bfe 100644 --- a/arch/sparc/kernel/pci.c +++ b/arch/sparc/kernel/pci.c @@ -249,7 +249,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, struct pci_bus *bus, int devfn) { struct dev_archdata *sd; - struct pci_slot *slot; struct platform_device *op; struct pci_dev *dev; const char *type; @@ -290,10 +289,7 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, dev->multifunction = 0; /* maybe a lie? */ 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); dev->vendor = of_getintprop_default(node, "vendor-id", 0xffff); dev->device = of_getintprop_default(node, "device-id", 0xffff); dev->subsystem_vendor = diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index cefd636681b6..2a9ce16cb374 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1133,7 +1133,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 +1148,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; diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c index 4bd3fce93fa4..429d34c348b9 100644 --- a/drivers/pci/slot.c +++ b/drivers/pci/slot.c @@ -194,6 +194,17 @@ static int rename_slot(struct pci_slot *slot, const char *name) return result; } +void pci_dev_assign_slot(struct pci_dev *dev) +{ + struct pci_slot *slot; + + mutex_lock(&pci_slot_mutex); + list_for_each_entry(slot, &dev->bus->slots, list) + if (PCI_SLOT(dev->devfn) == slot->number) + dev->slot = slot; + mutex_unlock(&pci_slot_mutex); +} + static struct pci_slot *get_slot(struct pci_bus *parent, int slot_nr) { struct pci_slot *slot; diff --git a/include/linux/pci.h b/include/linux/pci.h index aaee493174e2..b3ba7fef2916 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -798,6 +798,11 @@ struct pci_slot *pci_create_slot(struct pci_bus *parent, int slot_nr, const char *name, struct hotplug_slot *hotplug); void pci_destroy_slot(struct pci_slot *slot); +#ifdef CONFIG_SYSFS +void pci_dev_assign_slot(struct pci_dev *dev); +#else +static inline void pci_dev_assign_slot(struct pci_dev *dev) { } +#endif int pci_scan_slot(struct pci_bus *bus, int devfn); struct pci_dev *pci_scan_single_device(struct pci_bus *bus, int devfn); void pci_device_add(struct pci_dev *dev, struct pci_bus *bus); -- cgit v1.2.3-58-ga151