--- sle12.orig/drivers/xen/xen-pciback/pci_stub.c +++ sle12/drivers/xen/xen-pciback/pci_stub.c @@ -1502,6 +1502,44 @@ parse_error: fs_initcall(pcistub_init); #endif +#ifdef CONFIG_PCI_IOV +static int pci_stub_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct device *dev = data; + struct pci_dev *pdev = to_pci_dev(dev); + + switch (action) { + case BUS_NOTIFY_UNBIND_DRIVER: + for (;;) { + struct pcistub_device *psdev; + unsigned long flags; + bool found = false; + + spin_lock_irqsave(&pcistub_devices_lock, flags); + + list_for_each_entry(psdev, &pcistub_devices, dev_list) + if (!psdev->pdev && psdev->dev != pdev + && pci_physfn(psdev->dev) == pdev) { + found = true; + break; + } + spin_unlock_irqrestore(&pcistub_devices_lock, flags); + if (!found) + break; + device_release_driver(&psdev->dev->dev); + } + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block pci_stub_nb = { + .notifier_call = pci_stub_notifier, +}; +#endif + static int __init xen_pcibk_init(void) { int err; @@ -1523,6 +1561,10 @@ static int __init xen_pcibk_init(void) err = xen_pcibk_xenbus_register(); if (err) pcistub_exit(); +#ifdef CONFIG_PCI_IOV + else + bus_register_notifier(&pci_bus_type, &pci_stub_nb); +#endif return err; }