diff mbox series

[v9,21/26] PCI: Rescan the bus to resize a BAR

Message ID 20201218174011.340514-22-s.miroshnichenko@yadro.com
State New
Headers show
Series PCI: Allow BAR movement during boot and hotplug | expand

Commit Message

Sergei Miroshnichenko Dec. 18, 2020, 5:40 p.m. UTC
BAR resizing can be blocked by another BAR, so trigger a bus rescan to be
able to move BARs, increasing the probability of finding a good layout.

Signed-off-by: Sergei Miroshnichenko <s.miroshnichenko@yadro.com>
---
 drivers/pci/setup-res.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 28ec3d8c79c8..83a491f6a2c2 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -480,6 +480,9 @@  int pci_resize_resource(struct pci_dev *dev, int resno, int size)
 	u32 sizes;
 	u16 cmd;
 
+	if (pci_dev_bar_fixed(dev, res))
+		return -EOPNOTSUPP;
+
 	/* Make sure the resource isn't assigned before resizing it. */
 	if (!(res->flags & IORESOURCE_UNSET))
 		return -EBUSY;
@@ -506,7 +509,15 @@  int pci_resize_resource(struct pci_dev *dev, int resno, int size)
 	res->end = res->start + pci_rebar_size_to_bytes(size) - 1;
 
 	/* Check if the new config works by trying to assign everything. */
-	if (dev->bus->self) {
+	if (pci_can_move_bars) {
+		pci_rescan_bus(dev->bus);
+
+		if (!res->flags || (res->flags & IORESOURCE_UNSET) || !res->parent) {
+			pci_err(dev, "BAR %d resize failed\n", resno);
+			ret = -1;
+			goto error_resize;
+		}
+	} else if (dev->bus->self) {
 		ret = pci_reassign_bridge_resources(dev->bus->self, res->flags);
 		if (ret)
 			goto error_resize;
@@ -516,6 +527,8 @@  int pci_resize_resource(struct pci_dev *dev, int resno, int size)
 error_resize:
 	pci_rebar_set_size(dev, resno, old);
 	res->end = res->start + pci_rebar_size_to_bytes(old) - 1;
+	if (pci_can_move_bars)
+		pci_rescan_bus(dev->bus);
 	return ret;
 }
 EXPORT_SYMBOL(pci_resize_resource);