diff mbox series

[v7,13/26] PCI: hotplug: Add support of immovable BARs to pci_assign_resource()

Message ID 20200129152937.311162-14-s.miroshnichenko@yadro.com (mailing list archive)
State Superseded, archived
Delegated to: Bjorn Helgaas
Headers show
Series PCI: Allow BAR movement during boot and hotplug | expand

Commit Message

Sergei Miroshnichenko Jan. 29, 2020, 3:29 p.m. UTC
The PCI_FIXED and other immovable BARs must be assigned after the bridge
windows of parent bridge and before "usual" BARs, but currently they are
assigned the last by the pdev_assign_fixed_resources().

Let the immovable BARs be handled by pci_assign_resource() in the same way
as it does for movable ones, assigning them in correct order, unifying the
code.

Allow matching IORESOURCE_PCI_FIXED prefetchable BARs to non-prefetchable
windows, so they follow the same rules as immovable BARs.

Signed-off-by: Sergei Miroshnichenko <s.miroshnichenko@yadro.com>
---
 drivers/pci/pci.h       |  2 ++
 drivers/pci/setup-bus.c | 25 ++++++++++++++++++-------
 drivers/pci/setup-res.c |  5 ++++-
 3 files changed, 24 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index ddd6fd33f9c3..3ffbee2c3243 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -293,6 +293,8 @@  void pci_bus_put(struct pci_bus *bus);
 bool pci_dev_bar_movable(struct pci_dev *dev, struct resource *res);
 void pci_bus_update_realloc_range(struct pci_bus *bus);
 
+int assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r);
+
 /* PCIe link information */
 #define PCIE_SPEED2STR(speed) \
 	((speed) == PCIE_SPEED_16_0GT ? "16 GT/s" : \
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 71babb968830..cdbf4afe1334 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -1356,21 +1356,31 @@  void pci_bus_size_bridges(struct pci_bus *bus)
 }
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
-static void assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
+int assign_fixed_resource_on_bus(struct pci_bus *b, struct resource *r)
 {
 	int i;
 	struct resource *parent_r;
-	unsigned long mask = IORESOURCE_IO | IORESOURCE_MEM |
-			     IORESOURCE_PREFETCH;
+	unsigned long mask = IORESOURCE_TYPE_BITS;
 
 	pci_bus_for_each_resource(b, parent_r, i) {
 		if (!parent_r)
 			continue;
 
-		if ((r->flags & mask) == (parent_r->flags & mask) &&
-		    resource_contains(parent_r, r))
-			request_resource(parent_r, r);
+		if ((r->flags & mask) != (parent_r->flags & mask))
+			continue;
+
+		if (parent_r->flags & IORESOURCE_PREFETCH &&
+		    !(r->flags & IORESOURCE_PREFETCH))
+			continue;
+
+		if (resource_contains(parent_r, r)) {
+			if (!request_resource(parent_r, r))
+				return 0;
+		}
 	}
+
+	dev_err(&b->dev, "failed to assign immovable %pR\n", r);
+	return -EBUSY;
 }
 
 /*
@@ -1410,7 +1420,8 @@  void __pci_bus_assign_resources(const struct pci_bus *bus,
 		if (!pci_dev_bars_enabled(dev))
 			continue;
 
-		pdev_assign_fixed_resources(dev);
+		if (!pci_can_move_bars)
+			pdev_assign_fixed_resources(dev);
 
 		b = dev->subordinate;
 		if (!b)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 3582ae68840b..a7d81816d1ea 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -339,7 +339,10 @@  int pci_assign_resource(struct pci_dev *dev, int resno)
 	resource_size_t align, size;
 	int ret;
 
-	if (res->flags & IORESOURCE_PCI_FIXED)
+	if (pci_can_move_bars && !pci_dev_bar_movable(dev, res) &&
+	    resno < PCI_ROM_RESOURCE && res->start)
+		return assign_fixed_resource_on_bus(dev->bus, res);
+	else if (!pci_can_move_bars && res->flags & IORESOURCE_PCI_FIXED)
 		return 0;
 
 	res->flags |= IORESOURCE_UNSET;