linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sergey Miroshnichenko <s.miroshnichenko@yadro.com>
To: <linux-pci@vger.kernel.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>, <linux@yadro.com>,
	Sergey Miroshnichenko <s.miroshnichenko@yadro.com>
Subject: [PATCH RFC 1/4] PCI: hotplug: Add parameter to put devices to reset during rescan
Date: Fri, 14 Sep 2018 19:14:01 +0300	[thread overview]
Message-ID: <20180914161404.4685-2-s.miroshnichenko@yadro.com> (raw)
In-Reply-To: <20180914161404.4685-1-s.miroshnichenko@yadro.com>

Introduce a new command line option "pci=pcie_movable_bars" that indicates
support of PCIe hotplug without prior reservation of memory regions by
BIOS/bootloader.

If a new PCIe device has been hot-plugged between two active ones, which
have no (or not big enough) gap between their BARs, allocating new BARs
requires to move BARs of the following working devices:

1)                   dev 4
                       |
                       v
.. |  dev 3  |  dev 3  |  dev 5  |  dev 7  |
.. |  BAR 0  |  BAR 1  |  BAR 0  |  BAR 0  |

2)                             dev 4
                                 |
                                 v
.. |  dev 3  |  dev 3  | -->           --> |  dev 5  |  dev 7  |
.. |  BAR 0  |  BAR 1  | -->           --> |  BAR 0  |  BAR 0  |

3)

.. |  dev 3  |  dev 3  |  dev 4  |  dev 4  |  dev 5  |  dev 7  |
.. |  BAR 0  |  BAR 1  |  BAR 0  |  BAR 1  |  BAR 0  |  BAR 0  |

Not only BARs, but also bridge windows can be updated during a PCIe rescan,
threatening all memory transactions during this procedure, so the PCI
subsystem will instruct the drivers to pause by calling the reset_prepare()
and reset_done() callbacks.

If a device may be affected by BAR movement, the BAR changes tracking must
be implemented in its driver.

Signed-off-by: Sergey Miroshnichenko <s.miroshnichenko@yadro.com>
---
 .../admin-guide/kernel-parameters.txt         |  6 +++
 drivers/pci/pci.c                             |  2 +
 drivers/pci/probe.c                           | 43 +++++++++++++++++++
 include/linux/pci.h                           |  1 +
 4 files changed, 52 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 64a3bf54b974..f8132a709061 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -3311,6 +3311,12 @@
 				bridges without forcing it upstream. Note:
 				this removes isolation between devices and
 				may put more devices in an IOMMU group.
+		pcie_movable_bars	Arrange a space at runtime for BARs of
+				hotplugged PCIe devices - usable if bootloader
+				doesn't reserve memory regions for them. Freeing
+				a space may require moving BARs of active devices
+				to higher addresses, so device drivers will be
+				paused during rescan.
 
 	pcie_aspm=	[PCIE] Forcibly enable or disable PCIe Active State Power
 			Management.
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 1835f3a7aa8d..5f07a59b5924 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -6105,6 +6105,8 @@ static int __init pci_setup(char *str)
 				pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
 			} else if (!strncmp(str, "disable_acs_redir=", 18)) {
 				disable_acs_redir_param = str + 18;
+			} else if (!strncmp(str, "pcie_movable_bars", 17)) {
+				pci_add_flags(PCI_MOVABLE_BARS);
 			} else {
 				printk(KERN_ERR "PCI: Unknown option `%s'\n",
 						str);
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 201f9e5ff55c..bdaafc48dc4c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -3138,6 +3138,45 @@ unsigned int pci_rescan_bus_bridge_resize(struct pci_dev *bridge)
 	return max;
 }
 
+/*
+ * Put all devices of the bus and its children to reset
+ */
+static void pci_bus_reset_prepare(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		struct pci_bus *child = dev->subordinate;
+
+		if (child) {
+			pci_bus_reset_prepare(child);
+		} else if (dev->driver &&
+			   dev->driver->err_handler &&
+			   dev->driver->err_handler->reset_prepare) {
+			dev->driver->err_handler->reset_prepare(dev);
+		}
+	}
+}
+
+/*
+ * Complete the reset of all devices for the bus and its children
+ */
+static void pci_bus_reset_done(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		struct pci_bus *child = dev->subordinate;
+
+		if (child) {
+			pci_bus_reset_done(child);
+		} else if (dev->driver && dev->driver->err_handler &&
+			   dev->driver->err_handler->reset_done) {
+			dev->driver->err_handler->reset_done(dev);
+		}
+	}
+}
+
 /**
  * pci_rescan_bus - Scan a PCI bus for devices
  * @bus: PCI bus to scan
@@ -3151,8 +3190,12 @@ unsigned int pci_rescan_bus(struct pci_bus *bus)
 {
 	unsigned int max;
 
+	if (pci_has_flag(PCI_MOVABLE_BARS))
+		pci_bus_reset_prepare(bus);
 	max = pci_scan_child_bus(bus);
 	pci_assign_unassigned_bus_resources(bus);
+	if (pci_has_flag(PCI_MOVABLE_BARS))
+		pci_bus_reset_done(bus);
 	pci_bus_add_devices(bus);
 
 	return max;
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6925828f9f25..a8cb1a367c34 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -847,6 +847,7 @@ enum {
 	PCI_ENABLE_PROC_DOMAINS	= 0x00000010,	/* Enable domains in /proc */
 	PCI_COMPAT_DOMAIN_0	= 0x00000020,	/* ... except domain 0 */
 	PCI_SCAN_ALL_PCIE_DEVS	= 0x00000040,	/* Scan all, not just dev 0 */
+	PCI_MOVABLE_BARS	= 0x00000080,	/* Runtime BAR reassign after hotplug */
 };
 
 /* These external functions are only available when PCI support is enabled */
-- 
2.17.1

  reply	other threads:[~2018-09-14 21:36 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-14 16:14 [PATCH RFC 0/4] PCI: Allow BAR movement during hotplug Sergey Miroshnichenko
2018-09-14 16:14 ` Sergey Miroshnichenko [this message]
2018-09-17  5:28   ` [PATCH RFC 1/4] PCI: hotplug: Add parameter to put devices to reset during rescan Sam Bobroff
2018-09-17 20:55     ` Sergey Miroshnichenko
2018-09-17 22:59       ` Bjorn Helgaas
2018-09-18 14:01         ` Sergey Miroshnichenko
2018-09-18 21:10           ` Bjorn Helgaas
2018-09-17 23:35       ` Oliver
2018-09-18 16:51         ` Sergey Miroshnichenko
2018-09-17 19:00   ` Rajat Jain
2018-09-17 19:38     ` Lukas Wunner
2018-09-17 19:44       ` Rajat Jain
2018-09-17 21:25     ` Sergey Miroshnichenko
2018-09-18 21:22       ` Rajat Jain
2019-01-11 17:24         ` Sergey Miroshnichenko
2018-09-14 16:14 ` [PATCH RFC 2/4] PCI: Release and reassign resources from the root " Sergey Miroshnichenko
2018-09-14 16:14 ` [PATCH RFC 3/4] PCI: Invalidate the released BAR resources Sergey Miroshnichenko
2018-09-14 16:14 ` [PATCH RFC 4/4] PCI: Fix writing invalid BARs during pci_restore_state() Sergey Miroshnichenko
2018-09-18 11:16 ` [PATCH RFC 0/4] PCI: Allow BAR movement during hotplug David Laight
2018-09-18 17:07   ` Sergey Miroshnichenko

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180914161404.4685-2-s.miroshnichenko@yadro.com \
    --to=s.miroshnichenko@yadro.com \
    --cc=bhelgaas@google.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux@yadro.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).