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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxx>
---
 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 --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;
-- 
2.24.1




[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux