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

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

 



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@xxxxxxxxx>
---
 drivers/pci/setup-res.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

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);
-- 
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