[PATCH RFC 22/25] PCI/LUO: Save PCI bus and host bridge states

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

 



From: Jason Miu <jasonmiu@xxxxxxxxxx>

In the LUO prepare phase, saves the PCI bus and host bridge states.

For a PCI bus, save the domain and bus numbers. Save the bridge types.
Save the upstream bus domain and bus numbers so we can verify the
relationship in the later restoration phase.

If the current bridge is a host bridge, save also the PCI bridge
resource. This is not needed by other PCI bridges as the resource is
already preserved by its associated struct pci_dev.

Tested:
  - QEMU VM boot test, preserve device with pci-lu-stub

Signed-off-by: Chris Li <chrisl@xxxxxxxxxx>
---
 drivers/pci/liveupdate.c | 60 +++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 52 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/liveupdate.c b/drivers/pci/liveupdate.c
index 7fda7e4d409adce6bf92ef7af1167f7bda302c7e..be22af7a2db3a9bb06d8e100603a59f11b7fa5f8 100644
--- a/drivers/pci/liveupdate.c
+++ b/drivers/pci/liveupdate.c
@@ -20,9 +20,20 @@ static LIST_HEAD(preserved_buses);
 static LIST_HEAD(probe_devices);
 static LIST_HEAD(probe_buses);
 
+enum pci_bus_ser_bridge_type {
+	PCI_BUS_SER_NULL_BRIDGE, /* virtual bus */
+	PCI_BUS_SER_PCI_HOST_BRIDGE,
+	PCI_BUS_SER_PCI_BRIDGE,
+};
+
 struct pci_bus_ser {
 	u16	domain;
 	u8	number;
+	u16	parent_domain;
+	u8	parent_number;
+	enum pci_bus_ser_bridge_type bridge_type;
+	/* For a root bus, saves the host bridge PCI bridge resource */
+	struct pci_resource_ser resource[PCI_BRIDGE_RESOURCE_NUM];
 };
 
 struct pci_ser {
@@ -162,6 +173,16 @@ static int pci_get_device_path(struct pci_dev *pdev)
 	return (pci_domain_nr(pdev->bus) << 16) | pci_dev_id(pdev);
 }
 
+static void save_device_resource(struct pci_resource_ser *dest,
+				 struct resource *src)
+{
+	strscpy((char *)dest->name, src->name, sizeof(dest->name));
+	dest->start = src->start;
+	dest->end = src->end;
+	dest->flags = src->flags;
+	dest->desc = src->desc;
+}
+
 static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
@@ -205,13 +226,7 @@ static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 		    (strlen(pdev->resource[i].name) == 0))
 			continue;
 
-		s->resource[i].start = pdev->resource[i].start;
-		s->resource[i].end = pdev->resource[i].end;
-		s->resource[i].flags = pdev->resource[i].flags;
-		s->resource[i].desc = pdev->resource[i].desc;
-
-		strscpy((char *)s->resource[i].name, pci_name(pdev),
-			sizeof(s->resource[i].name));
+		save_device_resource(s->resource + i, pdev->resource + i);
 	}
 
 	return 0;
@@ -219,8 +234,37 @@ static int pci_save_device_state(struct device *dev, struct pci_dev_ser *s)
 
 static void pci_save_bus_state(struct pci_bus *bus, struct pci_bus_ser *s)
 {
-	s->number = bus->number;
+	int i;
+
 	s->domain = pci_domain_nr(bus);
+	s->number = bus->number;
+	if (bus->parent) {
+		s->parent_domain = pci_domain_nr(bus->parent);
+		s->parent_number = bus->parent->number;
+	}
+
+	/* This bus is a virtual bus if no physical bridge is being referred. */
+	if (!bus->bridge) {
+		s->bridge_type = PCI_BUS_SER_NULL_BRIDGE;
+		return;
+	}
+
+	if (!pci_is_root_bus(bus)) {
+		s->bridge_type = PCI_BUS_SER_PCI_BRIDGE;
+		return;
+	}
+
+	/* This bridge is a PCI host bridge. Saves its resource. */
+	for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++) {
+		/* This resource region is not claimed, skip. */
+		if ((bus->resource[i] == NULL) ||
+		    (bus->resource[i]->name == NULL) ||
+		    (strlen(bus->resource[i]->name) == 0))
+			continue;
+
+		save_device_resource(s->resource + i, bus->resource[i]);
+	}
+	s->bridge_type = PCI_BUS_SER_PCI_HOST_BRIDGE;
 }
 
 static int pci_call_prepare(struct pci_ser *pci_state,

-- 
2.50.1.487.gc89ff58d15-goog





[Index of Archives]     [Linux IBM ACPI]     [Linux Power Management]     [Linux Kernel]     [Linux Laptop]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Device Mapper]     [Linux Resources]
  Powered by Linux