aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/xen/pci.h16
-rw-r--r--arch/x86/pci/xen.c73
2 files changed, 89 insertions, 0 deletions
diff --git a/arch/x86/include/asm/xen/pci.h b/arch/x86/include/asm/xen/pci.h
index aa862098916..4fbda9a3f33 100644
--- a/arch/x86/include/asm/xen/pci.h
+++ b/arch/x86/include/asm/xen/pci.h
@@ -15,10 +15,26 @@ static inline int pci_xen_hvm_init(void)
15#endif 15#endif
16#if defined(CONFIG_XEN_DOM0) 16#if defined(CONFIG_XEN_DOM0)
17void __init xen_setup_pirqs(void); 17void __init xen_setup_pirqs(void);
18int xen_find_device_domain_owner(struct pci_dev *dev);
19int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain);
20int xen_unregister_device_domain_owner(struct pci_dev *dev);
18#else 21#else
19static inline void __init xen_setup_pirqs(void) 22static inline void __init xen_setup_pirqs(void)
20{ 23{
21} 24}
25static inline int xen_find_device_domain_owner(struct pci_dev *dev)
26{
27 return -1;
28}
29static inline int xen_register_device_domain_owner(struct pci_dev *dev,
30 uint16_t domain)
31{
32 return -1;
33}
34static inline int xen_unregister_device_domain_owner(struct pci_dev *dev)
35{
36 return -1;
37}
22#endif 38#endif
23 39
24#if defined(CONFIG_PCI_MSI) 40#if defined(CONFIG_PCI_MSI)
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index e37b407a0ee..6075f2d6533 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -461,3 +461,76 @@ void __init xen_setup_pirqs(void)
461 } 461 }
462} 462}
463#endif 463#endif
464
465struct xen_device_domain_owner {
466 domid_t domain;
467 struct pci_dev *dev;
468 struct list_head list;
469};
470
471static DEFINE_SPINLOCK(dev_domain_list_spinlock);
472static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
473
474static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
475{
476 struct xen_device_domain_owner *owner;
477
478 list_for_each_entry(owner, &dev_domain_list, list) {
479 if (owner->dev == dev)
480 return owner;
481 }
482 return NULL;
483}
484
485int xen_find_device_domain_owner(struct pci_dev *dev)
486{
487 struct xen_device_domain_owner *owner;
488 int domain = -ENODEV;
489
490 spin_lock(&dev_domain_list_spinlock);
491 owner = find_device(dev);
492 if (owner)
493 domain = owner->domain;
494 spin_unlock(&dev_domain_list_spinlock);
495 return domain;
496}
497EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
498
499int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
500{
501 struct xen_device_domain_owner *owner;
502
503 owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
504 if (!owner)
505 return -ENODEV;
506
507 spin_lock(&dev_domain_list_spinlock);
508 if (find_device(dev)) {
509 spin_unlock(&dev_domain_list_spinlock);
510 kfree(owner);
511 return -EEXIST;
512 }
513 owner->domain = domain;
514 owner->dev = dev;
515 list_add_tail(&owner->list, &dev_domain_list);
516 spin_unlock(&dev_domain_list_spinlock);
517 return 0;
518}
519EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
520
521int xen_unregister_device_domain_owner(struct pci_dev *dev)
522{
523 struct xen_device_domain_owner *owner;
524
525 spin_lock(&dev_domain_list_spinlock);
526 owner = find_device(dev);
527 if (!owner) {
528 spin_unlock(&dev_domain_list_spinlock);
529 return -ENODEV;
530 }
531 list_del(&owner->list);
532 spin_unlock(&dev_domain_list_spinlock);
533 kfree(owner);
534 return 0;
535}
536EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);