aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/xen
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen')
-rw-r--r--drivers/xen/xen-pciback/pci_stub.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c
index 8580e53355ec..cc3cbb4435f8 100644
--- a/drivers/xen/xen-pciback/pci_stub.c
+++ b/drivers/xen/xen-pciback/pci_stub.c
@@ -1518,6 +1518,53 @@ parse_error:
1518fs_initcall(pcistub_init); 1518fs_initcall(pcistub_init);
1519#endif 1519#endif
1520 1520
1521#ifdef CONFIG_PCI_IOV
1522static struct pcistub_device *find_vfs(const struct pci_dev *pdev)
1523{
1524 struct pcistub_device *psdev = NULL;
1525 unsigned long flags;
1526 bool found = false;
1527
1528 spin_lock_irqsave(&pcistub_devices_lock, flags);
1529 list_for_each_entry(psdev, &pcistub_devices, dev_list) {
1530 if (!psdev->pdev && psdev->dev != pdev
1531 && pci_physfn(psdev->dev) == pdev) {
1532 found = true;
1533 break;
1534 }
1535 }
1536 spin_unlock_irqrestore(&pcistub_devices_lock, flags);
1537 if (found)
1538 return psdev;
1539 return NULL;
1540}
1541
1542static int pci_stub_notifier(struct notifier_block *nb,
1543 unsigned long action, void *data)
1544{
1545 struct device *dev = data;
1546 const struct pci_dev *pdev = to_pci_dev(dev);
1547
1548 if (action != BUS_NOTIFY_UNBIND_DRIVER)
1549 return NOTIFY_DONE;
1550
1551 if (!pdev->is_physfn)
1552 return NOTIFY_DONE;
1553
1554 for (;;) {
1555 struct pcistub_device *psdev = find_vfs(pdev);
1556 if (!psdev)
1557 break;
1558 device_release_driver(&psdev->dev->dev);
1559 }
1560 return NOTIFY_DONE;
1561}
1562
1563static struct notifier_block pci_stub_nb = {
1564 .notifier_call = pci_stub_notifier,
1565};
1566#endif
1567
1521static int __init xen_pcibk_init(void) 1568static int __init xen_pcibk_init(void)
1522{ 1569{
1523 int err; 1570 int err;
@@ -1539,12 +1586,19 @@ static int __init xen_pcibk_init(void)
1539 err = xen_pcibk_xenbus_register(); 1586 err = xen_pcibk_xenbus_register();
1540 if (err) 1587 if (err)
1541 pcistub_exit(); 1588 pcistub_exit();
1589#ifdef CONFIG_PCI_IOV
1590 else
1591 bus_register_notifier(&pci_bus_type, &pci_stub_nb);
1592#endif
1542 1593
1543 return err; 1594 return err;
1544} 1595}
1545 1596
1546static void __exit xen_pcibk_cleanup(void) 1597static void __exit xen_pcibk_cleanup(void)
1547{ 1598{
1599#ifdef CONFIG_PCI_IOV
1600 bus_unregister_notifier(&pci_bus_type, &pci_stub_nb);
1601#endif
1548 xen_pcibk_xenbus_unregister(); 1602 xen_pcibk_xenbus_unregister();
1549 pcistub_exit(); 1603 pcistub_exit();
1550} 1604}