aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/pci
diff options
context:
space:
mode:
authorKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2010-11-08 14:13:35 -0500
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2011-04-14 11:16:54 -0400
commitc55fa78b13b32d3f19e19cd0c8b9378fdc09e521 (patch)
tree8595a0697b1177763ba42b28908e276a03a8725a /arch/x86/pci
parenta6360dd37e1a144ed11e6548371bade559a1e4df (diff)
xen/pci: Add xen_[find|register|unregister]_device_domain_owner functions.
When the Xen PCI backend is told to enable or disable MSI/MSI-X functions, the initial domain performs these operations. The initial domain needs to know which domain (guest) is going to use the PCI device so when it makes the appropiate hypercall to retrieve the MSI/MSI-X vector it will also assign the PCI device to the appropiate domain (guest). This boils down to us needing a mechanism to find, set and unset the domain id that will be using the device. [v2: EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL.] Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'arch/x86/pci')
-rw-r--r--arch/x86/pci/xen.c73
1 files changed, 73 insertions, 0 deletions
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);