From a9da9373003fe863935060838275037fe46dfbd5 Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Wilk Date: Thu, 30 Nov 2017 10:31:58 -0500 Subject: [PATCH] xen/pcifront: Walk the PCI bus after XenStore notification Prior to this patch we would only update the 'struct pci_dev' if a PCI hotplug (new device) event would happen. This works fine if the device is part of the guest config, that is: pci=["0a:11.1"] or such. Unfortunatly if you are doing PCI hotplug: xm pci-attach vnuma 0a:11.1 There are two events we need to stamp the 'struct pci_dev' with the PXM node information: - ACPI hotplug to inject the PCI device. - XenBus entries being created And those are created in the wrong order - first is the ACPI hotplug event, followed by the XenBus update. That means 'pcifront_hvm_notifier' gets called when the ACPI hotplug even has started, but XenBus hasn't been yet created so the scan from there returns NULL. Later on we get an XenBus notification (pcifront_hvm_xenbus_probe), update our internal list, and then the PCI notifier would find it. The one way to make this work is to listen to an extra event: BUS_NOTIFY_BOUND_DRIVER That is signaled once the driver has loaded itself and is ready. When the 'pcifront_hvm_notifier' gets that information it can walk over the PCI bus and stamp all the 'struct pci_dev' with the updated PXM data. In other words the operations are now: - ACPI hotplug to inject the PCI device. - udev is called, modprobe is invoked - XenBus entries being created - driver is finished - pcifront_hvm_notifier is called, figures out which 'struct pci_dev' needs its PXM update and updates. OraBug: 27200813 Reviewed-by: Boris Ostrovsky Signed-off-by: Konrad Rzeszutek Wilk --- drivers/pci/xen-pcifront.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index accc00d9815d..10bc3e26eb02 100644 --- a/drivers/pci/xen-pcifront.c +++ b/drivers/pci/xen-pcifront.c @@ -1207,7 +1207,7 @@ static int pcifront_hvm_notifier(struct notifier_block *nb, struct device *dev = data; struct pci_dev *pci_dev = to_pci_dev(dev); - if (action == BUS_NOTIFY_ADD_DEVICE) { + if (action == BUS_NOTIFY_BOUND_DRIVER) { mutex_lock(&pcifront_devs_mutex); pcifront_hvm_set_node(pci_dev, NULL); mutex_unlock(&pcifront_devs_mutex); @@ -1344,6 +1344,8 @@ static int pcifront_hvm_add(struct xenbus_device *xdev) return err; } +static void walk_pcifront_hvm(void); + static int pcifront_hvm_xenbus_probe(struct xenbus_device *xdev, const struct xenbus_device_id *id) { @@ -1351,8 +1353,11 @@ static int pcifront_hvm_xenbus_probe(struct xenbus_device *xdev, mutex_lock(&pcifront_devs_mutex); err = pcifront_hvm_add(xdev); - mutex_unlock(&pcifront_devs_mutex); + if (!err) + walk_pcifront_hvm(); + + mutex_unlock(&pcifront_devs_mutex); return err; } @@ -1401,13 +1406,11 @@ static struct xenbus_driver xenpci_driver_hvm = { .otherend_changed = pcifront_hvm_backend_changed, }; -static void __init walk_pcifront_hvm(void) +static void walk_pcifront_hvm(void) { if (!xen_hvm_domain()) return; - mutex_lock(&pcifront_devs_mutex); - /* * PCI devices may have been added during guest init, which means * the pcifront_hvm_notifier would have gotten called - but the @@ -1422,7 +1425,6 @@ static void __init walk_pcifront_hvm(void) list_for_each_entry(root_bus, &pci_root_buses, node) pci_walk_bus(root_bus, pcifront_hvm_set_node, NULL); } - mutex_unlock(&pcifront_devs_mutex); }; static struct xenbus_driver *pcifront_driver = &xenpci_driver; @@ -1450,7 +1452,6 @@ static int __init pcifront_init(void) bus_unregister_notifier(&pci_bus_type, notifier); return rc; } - walk_pcifront_hvm(); return 0; } -- 2.50.1