From 61e83cdde15f8850087d6c57c8576e25b671db59 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:12 -0700 Subject: PCI: Drop temporary variable in pci_assign_unassigned_resources() Drop the "bus" temporary variable. No functional change, but simplifies later patch slightly. [bhelgaas: changelog, make same change in pci_assign_unassigned_bridge_resources() to keep it parallel with pci_assign_unassigned_resources()] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index d254e2379533..cb6bcbb26226 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1458,12 +1458,11 @@ again: * Try to release leaf bridge's resources that doesn't fit resource of * child device under that bridge */ - list_for_each_entry(fail_res, &fail_head, list) { - bus = fail_res->dev->bus; - pci_bus_release_bridge_resources(bus, + list_for_each_entry(fail_res, &fail_head, list) + pci_bus_release_bridge_resources(fail_res->dev->bus, fail_res->flags & type_mask, rel_type); - } + /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; @@ -1522,13 +1521,11 @@ again: * Try to release leaf bridge's resources that doesn't fit resource of * child device under that bridge */ - list_for_each_entry(fail_res, &fail_head, list) { - struct pci_bus *bus = fail_res->dev->bus; - unsigned long flags = fail_res->flags; - - pci_bus_release_bridge_resources(bus, flags & type_mask, + list_for_each_entry(fail_res, &fail_head, list) + pci_bus_release_bridge_resources(fail_res->dev->bus, + fail_res->flags & type_mask, whole_subtree); - } + /* restore size and flags */ list_for_each_entry(fail_res, &fail_head, list) { struct resource *res = fail_res->res; -- cgit v1.2.3-59-g8ed1b From 223d96fc3249b0ffdc30bf77fd90c93f857e9a6e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:13 -0700 Subject: PCI: Look for unassigned resources on per-bus basis When CONFIG_PCI_REALLOC_ENABLE_AUTO=y, pci_realloc_detect() looks at PCI devices to see if any have SR-IOV resources that need to be assigned. If it finds any, it turns on automatic resource reallocation. This patch changes pci_realloc_detect() so it uses pci_walk_bus() on each root bus instead of using for_each_pci_dev(). This is a step toward doing reallocation on a per-bus basis, so we can do it for a hot-added host bridge. [bhelgaas: changelog, rename callback to iov_resources_unassigned(), use boolean for "unassigned"] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 44 +++++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 15 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index cb6bcbb26226..20c09bd652db 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1359,30 +1359,44 @@ static bool __init pci_realloc_enabled(void) return pci_realloc_enable >= user_enabled; } -static void __init pci_realloc_detect(void) -{ #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) - struct pci_dev *dev = NULL; +static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) +{ + int i; + bool *unassigned = data; - if (pci_realloc_enable != undefined) - return; + for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { + struct resource *r = &dev->resource[i]; - for_each_pci_dev(dev) { - int i; + /* Not assigned or rejected by kernel? */ + if (r->flags && !r->start) { + *unassigned = true; + return 1; /* return early from pci_walk_bus() */ + } + } - for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { - struct resource *r = &dev->resource[i]; + return 0; +} - /* Not assigned, or rejected by kernel ? */ - if (r->flags && !r->start) { - pci_realloc_enable = auto_enabled; +static void __init pci_realloc_detect(void) +{ + bool unassigned = false; + struct pci_bus *bus; - return; - } + if (pci_realloc_enable != undefined) + return; + + list_for_each_entry(bus, &pci_root_buses, node) { + pci_walk_bus(bus, iov_resources_unassigned, &unassigned); + if (unassigned) { + pci_realloc_enable = auto_enabled; + return; } } -#endif } +#else +static void __init pci_realloc_detect(void) { } +#endif /* * first try will not touch pci bridge res -- cgit v1.2.3-59-g8ed1b From fa216bf4dbe35e15044b90e7b51509768bab3d9a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:14 -0700 Subject: PCI: Turn on reallocation for unassigned resources with host bridge offset Previously we did not turn on automatic PCI resource reallocation for unassigned IOV resources behind a host bridge with address offset. This patch fixes that bug. The intent was that "!r->start" would check for a BAR containing zero. But that check is incorrect for host bridges that apply an offset, because in that case the resource address is not the same as the bus address. This patch fixes that by converting the resource address back to a bus address before checking for zero. [bhelgaas: changelog] Suggested-by: Benjamin Herrenschmidt Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 20c09bd652db..ed1bd0cdf521 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1367,9 +1367,14 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) for (i = PCI_IOV_RESOURCES; i <= PCI_IOV_RESOURCE_END; i++) { struct resource *r = &dev->resource[i]; + struct pci_bus_region region; /* Not assigned or rejected by kernel? */ - if (r->flags && !r->start) { + if (!r->flags) + continue; + + pcibios_resource_to_bus(dev, ®ion, r); + if (!region.start) { *unassigned = true; return 1; /* return early from pci_walk_bus() */ } -- cgit v1.2.3-59-g8ed1b From 967260cdb13f9c0de3cf56e305b34eb363e41d5b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:15 -0700 Subject: PCI: Enable unassigned resource reallocation on per-bus basis pci_realloc_detect() turns on automatic resource allocation when it finds unassigned SR-IOV resources. Previously it did this on a global basis, so we enabled reallocation if any PCI device anywhere had an unassigned SR-IOV resource. This patch changes pci_realloc_detect() so it looks at a single bus, so we can do this when a host bridge is hot-added. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index ed1bd0cdf521..4aaa8d57443f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1354,9 +1354,9 @@ void __init pci_realloc_get_opt(char *str) else if (!strncmp(str, "on", 2)) pci_realloc_enable = user_enabled; } -static bool __init pci_realloc_enabled(void) +static bool __init pci_realloc_enabled(enum enable_type enable) { - return pci_realloc_enable >= user_enabled; + return enable >= user_enabled; } #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) @@ -1383,24 +1383,26 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) return 0; } -static void __init pci_realloc_detect(void) +static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, + enum enable_type enable_local) { bool unassigned = false; - struct pci_bus *bus; - if (pci_realloc_enable != undefined) - return; + if (enable_local != undefined) + return enable_local; - list_for_each_entry(bus, &pci_root_buses, node) { - pci_walk_bus(bus, iov_resources_unassigned, &unassigned); - if (unassigned) { - pci_realloc_enable = auto_enabled; - return; - } - } + pci_walk_bus(bus, iov_resources_unassigned, &unassigned); + if (unassigned) + return auto_enabled; + + return enable_local; } #else -static void __init pci_realloc_detect(void) { } +static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, + enum enable_type enable_local) +{ + return enable_local; +} #endif /* @@ -1422,10 +1424,12 @@ pci_assign_unassigned_resources(void) unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; int pci_try_num = 1; + enum enable_type enable_local = pci_realloc_enable; + + list_for_each_entry(bus, &pci_root_buses, node) + enable_local = pci_realloc_detect(bus, enable_local); - /* don't realloc if asked to do so */ - pci_realloc_detect(); - if (pci_realloc_enabled()) { + if (pci_realloc_enabled(enable_local)) { int max_depth = pci_get_max_depth(); pci_try_num = max_depth + 1; @@ -1457,9 +1461,9 @@ again: goto enable_and_dump; if (tried_times >= pci_try_num) { - if (pci_realloc_enable == undefined) + if (enable_local == undefined) printk(KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n"); - else if (pci_realloc_enable == auto_enabled) + else if (enable_local == auto_enabled) printk(KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); -- cgit v1.2.3-59-g8ed1b From 55ed83a615730c2578da155bc99b68f4417ffe20 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:16 -0700 Subject: PCI: Assign resources on a per-bus basis Previously, we did resource assignment globally. This patch splits up pci_assign_unassigned_resources() so assignment is done for each root bus in turn. We check each root bus individually to see whether it needs any reassignment, and if it does, we assign resources for just that bus. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 62 ++++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 37 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4aaa8d57443f..4d9ebb4ce015 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1315,21 +1315,6 @@ static int __init pci_bus_get_depth(struct pci_bus *bus) return depth; } -static int __init pci_get_max_depth(void) -{ - int depth = 0; - struct pci_bus *bus; - - list_for_each_entry(bus, &pci_root_buses, node) { - int ret; - - ret = pci_bus_get_depth(bus); - if (ret > depth) - depth = ret; - } - - return depth; -} /* * -1: undefined, will auto detect later @@ -1410,10 +1395,9 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -void __init -pci_assign_unassigned_resources(void) +static void __init +pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { - struct pci_bus *bus; LIST_HEAD(realloc_head); /* list of resources that want additional resources */ struct list_head *add_list = NULL; @@ -1424,17 +1408,17 @@ pci_assign_unassigned_resources(void) unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | IORESOURCE_PREFETCH; int pci_try_num = 1; - enum enable_type enable_local = pci_realloc_enable; - - list_for_each_entry(bus, &pci_root_buses, node) - enable_local = pci_realloc_detect(bus, enable_local); + enum enable_type enable_local; + /* don't realloc if asked to do so */ + enable_local = pci_realloc_detect(bus, pci_realloc_enable); if (pci_realloc_enabled(enable_local)) { - int max_depth = pci_get_max_depth(); + int max_depth = pci_bus_get_depth(bus); pci_try_num = max_depth + 1; - printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", - max_depth, pci_try_num); + dev_printk(KERN_DEBUG, &bus->dev, + "max bus depth: %d pci_try_num: %d\n", + max_depth, pci_try_num); } again: @@ -1446,12 +1430,10 @@ again: add_list = &realloc_head; /* Depth first, calculate sizes and alignments of all subordinate buses. */ - list_for_each_entry(bus, &pci_root_buses, node) - __pci_bus_size_bridges(bus, add_list); + __pci_bus_size_bridges(bus, add_list); /* Depth last, allocate resources and update the hardware. */ - list_for_each_entry(bus, &pci_root_buses, node) - __pci_bus_assign_resources(bus, add_list, &fail_head); + __pci_bus_assign_resources(bus, add_list, &fail_head); if (add_list) BUG_ON(!list_empty(add_list)); tried_times++; @@ -1462,16 +1444,16 @@ again: if (tried_times >= pci_try_num) { if (enable_local == undefined) - printk(KERN_INFO "Some PCI device resources are unassigned, try booting with pci=realloc\n"); + dev_info(&bus->dev, "Some PCI device resources are unassigned, try booting with pci=realloc\n"); else if (enable_local == auto_enabled) - printk(KERN_INFO "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); + dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); goto enable_and_dump; } - printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", - tried_times + 1); + dev_printk(KERN_DEBUG, &bus->dev, + "No. %d try to assign unassigned res\n", tried_times + 1); /* third times and later will not check if it is leaf */ if ((tried_times + 1) > 2) @@ -1502,12 +1484,18 @@ again: enable_and_dump: /* Depth last, update the hardware. */ - list_for_each_entry(bus, &pci_root_buses, node) - pci_enable_bridges(bus); + pci_enable_bridges(bus); /* dump the resource on buses */ - list_for_each_entry(bus, &pci_root_buses, node) - pci_bus_dump_resources(bus); + pci_bus_dump_resources(bus); +} + +void __init pci_assign_unassigned_resources(void) +{ + struct pci_bus *root_bus; + + list_for_each_entry(root_bus, &pci_root_buses, node) + pci_assign_unassigned_root_bus_resources(root_bus); } void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge) -- cgit v1.2.3-59-g8ed1b From 928bea964827d7824b548c1f8e06eccbbc4d0d7d Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:17 -0700 Subject: PCI: Delay enabling bridges until they're needed We currently enable PCI bridges after scanning a bus and assigning resources. This is often done in arch code. This patch changes this so we don't enable a bridge until necessary, i.e., until we enable a PCI device behind the bridge. We do this in the generic pci_enable_device() path, so this also removes the arch-specific code to enable bridges. [bhelgaas: changelog] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- arch/arm/kernel/bios32.c | 5 ----- arch/m68k/platform/coldfire/pci.c | 1 - arch/mips/pci/pci.c | 1 - arch/sh/drivers/pci/pci.c | 1 - drivers/acpi/pci_root.c | 3 --- drivers/parisc/lba_pci.c | 1 - drivers/pci/bus.c | 19 ------------------- drivers/pci/hotplug/acpiphp_glue.c | 1 - drivers/pci/pci.c | 20 ++++++++++++++++++++ drivers/pci/probe.c | 1 - drivers/pci/setup-bus.c | 10 +++------- drivers/pcmcia/cardbus.c | 1 - include/linux/pci.h | 1 - 13 files changed, 23 insertions(+), 42 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c index 261fcc826169..88e14d74b6de 100644 --- a/arch/arm/kernel/bios32.c +++ b/arch/arm/kernel/bios32.c @@ -525,11 +525,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw) * Assign resources. */ pci_bus_assign_resources(bus); - - /* - * Enable bridges - */ - pci_enable_bridges(bus); } /* diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c index b33f97a13e6d..df9679238b6d 100644 --- a/arch/m68k/platform/coldfire/pci.c +++ b/arch/m68k/platform/coldfire/pci.c @@ -319,7 +319,6 @@ static int __init mcf_pci_init(void) pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq); pci_bus_size_bridges(rootbus); pci_bus_assign_resources(rootbus); - pci_enable_bridges(rootbus); return 0; } diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 594e60d6a43b..33e7aa52d9c4 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -113,7 +113,6 @@ static void pcibios_scanbus(struct pci_controller *hose) if (!pci_has_flag(PCI_PROBE_ONLY)) { pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - pci_enable_bridges(bus); } } } diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 102f5d58b037..60ed3e1c4b75 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -69,7 +69,6 @@ static void pcibios_scanbus(struct pci_channel *hose) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); - pci_enable_bridges(bus); } else { pci_free_resource_list(&resources); } diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 5917839321b8..faa1d29c0261 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -527,9 +527,6 @@ static int acpi_pci_root_add(struct acpi_device *device, if (system_state != SYSTEM_BOOTING) { pcibios_resource_survey_bus(root->bus); pci_assign_unassigned_bus_resources(root->bus); - - /* need to after hot-added ioapic is registered */ - pci_enable_bridges(root->bus); } pci_bus_add_devices(root->bus); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 19f6f70c67d3..37e71ff6408d 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -1590,7 +1590,6 @@ lba_driver_probe(struct parisc_device *dev) lba_dump_res(&lba_dev->hba.lmmio_space, 2); #endif } - pci_enable_bridges(lba_bus); /* ** Once PCI register ops has walked the bus, access to config diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index b1ff02ab4f13..fc1b74013743 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -216,24 +216,6 @@ void pci_bus_add_devices(const struct pci_bus *bus) } } -void pci_enable_bridges(struct pci_bus *bus) -{ - struct pci_dev *dev; - int retval; - - list_for_each_entry(dev, &bus->devices, bus_list) { - if (dev->subordinate) { - if (!pci_is_enabled(dev)) { - retval = pci_enable_device(dev); - if (retval) - dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", retval); - pci_set_master(dev); - } - pci_enable_bridges(dev->subordinate); - } - } -} - /** pci_walk_bus - walk devices on/under bus, calling callback. * @top bus whose devices should be walked * @cb callback to be called for each device found @@ -301,4 +283,3 @@ EXPORT_SYMBOL(pci_bus_put); EXPORT_SYMBOL(pci_bus_alloc_resource); EXPORT_SYMBOL_GPL(pci_bus_add_device); EXPORT_SYMBOL(pci_bus_add_devices); -EXPORT_SYMBOL(pci_enable_bridges); diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 59df8575a48c..52dee9d31e1c 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -723,7 +723,6 @@ static int __ref enable_device(struct acpiphp_slot *slot) acpiphp_sanitize_bus(bus); acpiphp_set_hpp_values(bus); acpiphp_set_acpi_region(slot); - pci_enable_bridges(bus); list_for_each_entry(dev, &bus->devices, bus_list) { /* Assume that newly added devices are powered on already. */ diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e37fea6e178d..44a1a8a0ad7b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1145,6 +1145,24 @@ int pci_reenable_device(struct pci_dev *dev) return 0; } +static void pci_enable_bridge(struct pci_dev *dev) +{ + int retval; + + if (!dev) + return; + + pci_enable_bridge(dev->bus->self); + + if (pci_is_enabled(dev)) + return; + retval = pci_enable_device(dev); + if (retval) + dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", + retval); + pci_set_master(dev); +} + static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) { int err; @@ -1165,6 +1183,8 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) if (atomic_inc_return(&dev->enable_cnt) > 1) return 0; /* already enabled */ + pci_enable_bridge(dev->bus->self); + /* only skip sriov related */ for (i = 0; i <= PCI_ROM_RESOURCE; i++) if (dev->resource[i].flags & flags) diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 46ada5c098eb..85c114cd91cc 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -1979,7 +1979,6 @@ unsigned int __ref pci_rescan_bus(struct pci_bus *bus) max = pci_scan_child_bus(bus); pci_assign_unassigned_bus_resources(bus); - pci_enable_bridges(bus); pci_bus_add_devices(bus); return max; diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4d9ebb4ce015..8f86be13678f 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1440,7 +1440,7 @@ again: /* any device complain? */ if (list_empty(&fail_head)) - goto enable_and_dump; + goto dump; if (tried_times >= pci_try_num) { if (enable_local == undefined) @@ -1449,7 +1449,7 @@ again: dev_info(&bus->dev, "Automatically enabled pci realloc, if you have problem, try booting with pci=realloc=off\n"); free_list(&fail_head); - goto enable_and_dump; + goto dump; } dev_printk(KERN_DEBUG, &bus->dev, @@ -1482,10 +1482,7 @@ again: goto again; -enable_and_dump: - /* Depth last, update the hardware. */ - pci_enable_bridges(bus); - +dump: /* dump the resource on buses */ pci_bus_dump_resources(bus); } @@ -1556,7 +1553,6 @@ enable_all: if (retval) dev_err(&bridge->dev, "Error reenabling bridge (%d)\n", retval); pci_set_master(bridge); - pci_enable_bridges(parent); } EXPORT_SYMBOL_GPL(pci_assign_unassigned_bridge_resources); diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 9d3ac998fc1f..b2a98cdbd0d2 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -91,7 +91,6 @@ int __ref cb_alloc(struct pcmcia_socket *s) if (s->tune_bridge) s->tune_bridge(s, bus); - pci_enable_bridges(bus); pci_bus_add_devices(bus); return 0; diff --git a/include/linux/pci.h b/include/linux/pci.h index 0fd1f1582fa1..8cd1e6f30acd 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1043,7 +1043,6 @@ int __must_check pci_bus_alloc_resource(struct pci_bus *bus, resource_size_t, resource_size_t), void *alignf_data); -void pci_enable_bridges(struct pci_bus *bus); /* Proper probing supporting hot-pluggable devices */ int __must_check __pci_register_driver(struct pci_driver *, struct module *, -- cgit v1.2.3-59-g8ed1b From ff35147cf15814e13c62831f6910f8663e4dc91e Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Wed, 24 Jul 2013 15:37:13 -0600 Subject: PCI: Move resource reallocation code to non-__init Resource reallocation is currently done only at boot-time, but will soon be done when host bridge is hot-added. This patch removes the __init annotations so the code will still be present after boot. [bhelgaas: split __init changes out] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/pci/setup-bus.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8f86be13678f..8d1e654256a8 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1297,7 +1297,7 @@ static void pci_bus_dump_resources(struct pci_bus *bus) } } -static int __init pci_bus_get_depth(struct pci_bus *bus) +static int pci_bus_get_depth(struct pci_bus *bus) { int depth = 0; struct pci_dev *dev; @@ -1331,7 +1331,7 @@ enum enable_type { auto_enabled, }; -static enum enable_type pci_realloc_enable __initdata = undefined; +static enum enable_type pci_realloc_enable = undefined; void __init pci_realloc_get_opt(char *str) { if (!strncmp(str, "off", 3)) @@ -1339,13 +1339,13 @@ void __init pci_realloc_get_opt(char *str) else if (!strncmp(str, "on", 2)) pci_realloc_enable = user_enabled; } -static bool __init pci_realloc_enabled(enum enable_type enable) +static bool pci_realloc_enabled(enum enable_type enable) { return enable >= user_enabled; } #if defined(CONFIG_PCI_IOV) && defined(CONFIG_PCI_REALLOC_ENABLE_AUTO) -static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) +static int iov_resources_unassigned(struct pci_dev *dev, void *data) { int i; bool *unassigned = data; @@ -1368,7 +1368,7 @@ static int __init iov_resources_unassigned(struct pci_dev *dev, void *data) return 0; } -static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, +static enum enable_type pci_realloc_detect(struct pci_bus *bus, enum enable_type enable_local) { bool unassigned = false; @@ -1383,7 +1383,7 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, return enable_local; } #else -static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, +static enum enable_type pci_realloc_detect(struct pci_bus *bus, enum enable_type enable_local) { return enable_local; @@ -1395,8 +1395,7 @@ static enum enable_type __init pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -static void __init -pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) +static void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { LIST_HEAD(realloc_head); /* list of resources that want additional resources */ -- cgit v1.2.3-59-g8ed1b From 39772038ea93e85ea4f1307ec9c1f48a063d89a0 Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 22 Jul 2013 14:37:18 -0700 Subject: PCI: Assign resources for hot-added host bridge more aggressively When hot-adding an ACPI host bridge, use pci_assign_unassigned_root_bus_resources() instead of pci_assign_unassigned_bus_resources(). The former is more aggressive and will release and reassign existing resources if necessary. This is safe at hot-add time because no drivers are bound to devices below the new host bridge yet. [bhelgaas: changelog, split __init changes out for reviewability] Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas --- drivers/acpi/pci_root.c | 2 +- drivers/pci/setup-bus.c | 2 +- include/linux/pci.h | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/pci/setup-bus.c') diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index faa1d29c0261..ce04eb28e029 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -526,7 +526,7 @@ static int acpi_pci_root_add(struct acpi_device *device, if (system_state != SYSTEM_BOOTING) { pcibios_resource_survey_bus(root->bus); - pci_assign_unassigned_bus_resources(root->bus); + pci_assign_unassigned_root_bus_resources(root->bus); } pci_bus_add_devices(root->bus); diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8d1e654256a8..94b777d108bb 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -1395,7 +1395,7 @@ static enum enable_type pci_realloc_detect(struct pci_bus *bus, * second and later try will clear small leaf bridge res * will stop till to the max deepth if can not find good one */ -static void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) +void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus) { LIST_HEAD(realloc_head); /* list of resources that want additional resources */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 8cd1e6f30acd..e494c90a00d1 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1003,6 +1003,7 @@ int pci_claim_resource(struct pci_dev *, int); void pci_assign_unassigned_resources(void); void pci_assign_unassigned_bridge_resources(struct pci_dev *bridge); void pci_assign_unassigned_bus_resources(struct pci_bus *bus); +void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus); void pdev_enable_device(struct pci_dev *); int pci_enable_resources(struct pci_dev *, int mask); void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *), -- cgit v1.2.3-59-g8ed1b