|
@@ -461,3 +461,76 @@ void __init xen_setup_pirqs(void)
|
|
|
}
|
|
|
}
|
|
|
#endif
|
|
|
+
|
|
|
+struct xen_device_domain_owner {
|
|
|
+ domid_t domain;
|
|
|
+ struct pci_dev *dev;
|
|
|
+ struct list_head list;
|
|
|
+};
|
|
|
+
|
|
|
+static DEFINE_SPINLOCK(dev_domain_list_spinlock);
|
|
|
+static struct list_head dev_domain_list = LIST_HEAD_INIT(dev_domain_list);
|
|
|
+
|
|
|
+static struct xen_device_domain_owner *find_device(struct pci_dev *dev)
|
|
|
+{
|
|
|
+ struct xen_device_domain_owner *owner;
|
|
|
+
|
|
|
+ list_for_each_entry(owner, &dev_domain_list, list) {
|
|
|
+ if (owner->dev == dev)
|
|
|
+ return owner;
|
|
|
+ }
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+int xen_find_device_domain_owner(struct pci_dev *dev)
|
|
|
+{
|
|
|
+ struct xen_device_domain_owner *owner;
|
|
|
+ int domain = -ENODEV;
|
|
|
+
|
|
|
+ spin_lock(&dev_domain_list_spinlock);
|
|
|
+ owner = find_device(dev);
|
|
|
+ if (owner)
|
|
|
+ domain = owner->domain;
|
|
|
+ spin_unlock(&dev_domain_list_spinlock);
|
|
|
+ return domain;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(xen_find_device_domain_owner);
|
|
|
+
|
|
|
+int xen_register_device_domain_owner(struct pci_dev *dev, uint16_t domain)
|
|
|
+{
|
|
|
+ struct xen_device_domain_owner *owner;
|
|
|
+
|
|
|
+ owner = kzalloc(sizeof(struct xen_device_domain_owner), GFP_KERNEL);
|
|
|
+ if (!owner)
|
|
|
+ return -ENODEV;
|
|
|
+
|
|
|
+ spin_lock(&dev_domain_list_spinlock);
|
|
|
+ if (find_device(dev)) {
|
|
|
+ spin_unlock(&dev_domain_list_spinlock);
|
|
|
+ kfree(owner);
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
|
+ owner->domain = domain;
|
|
|
+ owner->dev = dev;
|
|
|
+ list_add_tail(&owner->list, &dev_domain_list);
|
|
|
+ spin_unlock(&dev_domain_list_spinlock);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(xen_register_device_domain_owner);
|
|
|
+
|
|
|
+int xen_unregister_device_domain_owner(struct pci_dev *dev)
|
|
|
+{
|
|
|
+ struct xen_device_domain_owner *owner;
|
|
|
+
|
|
|
+ spin_lock(&dev_domain_list_spinlock);
|
|
|
+ owner = find_device(dev);
|
|
|
+ if (!owner) {
|
|
|
+ spin_unlock(&dev_domain_list_spinlock);
|
|
|
+ return -ENODEV;
|
|
|
+ }
|
|
|
+ list_del(&owner->list);
|
|
|
+ spin_unlock(&dev_domain_list_spinlock);
|
|
|
+ kfree(owner);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(xen_unregister_device_domain_owner);
|