diff options
-rw-r--r-- | arch/x86/include/asm/xen/pci.h | 16 | ||||
-rw-r--r-- | arch/x86/pci/xen.c | 73 |
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) |
17 | void __init xen_setup_pirqs(void); | 17 | void __init xen_setup_pirqs(void); |
18 | int xen_find_device_domain_owner(struct pci_dev *dev); | ||
19 | int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain); | ||
20 | int xen_unregister_device_domain_owner(struct pci_dev *dev); | ||
18 | #else | 21 | #else |
19 | static inline void __init xen_setup_pirqs(void) | 22 | static inline void __init xen_setup_pirqs(void) |
20 | { | 23 | { |
21 | } | 24 | } |
25 | static inline int xen_find_device_domain_owner(struct pci_dev *dev) | ||
26 | { | ||
27 | return -1; | ||
28 | } | ||
29 | static inline int xen_register_device_domain_owner(struct pci_dev *dev, | ||
30 | uint16_t domain) | ||
31 | { | ||
32 | return -1; | ||
33 | } | ||
34 | static 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 | |||
465 | struct xen_device_domain_owner { | ||
466 | domid_t domain; | ||
467 | struct pci_dev *dev; | ||
468 | struct list_head list; | ||
469 | }; | ||
470 | |||
471 | static DEFINE_SPINLOCK(dev_domain_list_spinlock); | ||
472 | static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list); | ||
473 | |||
474 | static 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 | |||
485 | int 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 | } | ||
497 | EXPORT_SYMBOL_GPL(xen_find_device_domain_owner); | ||
498 | |||
499 | int 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 | } | ||
519 | EXPORT_SYMBOL_GPL(xen_register_device_domain_owner); | ||
520 | |||
521 | int 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 | } | ||
536 | EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner); | ||