summaryrefslogtreecommitdiff
path: root/drivers/pci
diff options
context:
space:
mode:
authorNicholas Johnson <nicholas.johnson-opensource@outlook.com.au>2020-01-06 18:48:06 +0300
committerBjorn Helgaas <bhelgaas@google.com>2020-01-30 01:57:28 +0300
commit948675736a77cb951b40bcb646d22dd794f8ed14 (patch)
treea7b8622d6889592c5347a0c5f4134a98c7056000 /drivers/pci
parentae4611f1d7e99eda6916bbc5fc8df26516edf95e (diff)
downloadlinux-948675736a77cb951b40bcb646d22dd794f8ed14.tar.xz
PCI: Allow adjust_bridge_window() to shrink resource if necessary
Remove checks for resource size in adjust_bridge_window(). This is necessary to allow pci_bus_distribute_available_resources() to function when the kernel parameter "pci=hpmemsize=nn[KMG]" is used to allocate resources. Because the kernel parameter sets the size of all hotplug bridges to be the same, there are problems when nested hotplug bridges are encountered. Fitting a downstream hotplug bridge with size X and normal bridges with non-zero size Y into parent hotplug bridge with size X is impossible, and hence the downstream hotplug bridge needs to shrink to fit into its parent. Add check for if bridge is extended or shrunken and reflect that in the call to pci_dbg(). Reset the resource if its new size is zero (if we have run out of a bridge window resource) to prevent the PCI resource assignment code from attempting to assign a zero-sized resource. Link: https://lore.kernel.org/r/PSXP216MB0438D3E2CFE64EBAA32AF691803C0@PSXP216MB0438.KORP216.PROD.OUTLOOK.COM Signed-off-by: Nicholas Johnson <nicholas.johnson-opensource@outlook.com.au> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Reviewed-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/setup-bus.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 742055908656..f2461bf9243d 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1842,16 +1842,24 @@ static void adjust_bridge_window(struct pci_dev *bridge, struct resource *res,
struct list_head *add_list,
resource_size_t new_size)
{
- resource_size_t add_size;
+ resource_size_t add_size, size = resource_size(res);
if (res->parent)
return;
- if (resource_size(res) >= new_size)
+ if (!new_size)
return;
- add_size = new_size - resource_size(res);
- pci_dbg(bridge, "bridge window %pR extended by %pa\n", res, &add_size);
+ if (new_size > size) {
+ add_size = new_size - size;
+ pci_dbg(bridge, "bridge window %pR extended by %pa\n", res,
+ &add_size);
+ } else if (new_size < size) {
+ add_size = size - new_size;
+ pci_dbg(bridge, "bridge window %pR shrunken by %pa\n", res,
+ &add_size);
+ }
+
res->end = res->start + new_size - 1;
remove_from_list(add_list, res);
}