diff options
Diffstat (limited to 'arch/x86/pci/xen.c')
-rw-r--r-- | arch/x86/pci/xen.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index e37b407a0ee8..6075f2d65335 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); | ||