From: Xiao Guangrong <guangrong.xiao@xxxxxxxxxxxxxxx> Now mdev has a separate parent device, so quite a few codes and information used for managing mdev, can be removed. Linux driver core will take care of us. Signed-off-by: Xiao Guangrong <guangrong.xiao@xxxxxxxxxxxxxxx> --- drivers/vfio/mdev/mdev_core.c | 164 +++++++++++++++-------------------------- drivers/vfio/mdev/mdev_sysfs.c | 13 ++-- drivers/vfio/mdev/vfio_mpci.c | 23 +++--- include/linux/mdev.h | 15 +--- 4 files changed, 77 insertions(+), 138 deletions(-) diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c index 9138588..a677db7 100644 --- a/drivers/vfio/mdev/mdev_core.c +++ b/drivers/vfio/mdev/mdev_core.c @@ -39,23 +39,42 @@ static void mdev_remove_attribute_group(struct device *dev, sysfs_remove_groups(&dev->kobj, groups); } -/* Should be called holding parent->mdev_list_lock */ +struct mdev_info { + uuid_le uuid; + int instance; +}; + +static int __find_mdev_device(struct device *dev, void *data) +{ + struct mdev_device *mdev = dev_to_mdev(dev); + struct mdev_info *info = data; + + if ((uuid_le_cmp(mdev->uuid, info->uuid) == 0) && + (mdev->instance == info->instance)) + return 1; + + return 0; +} + static struct mdev_device *find_mdev_device(struct parent_device *parent, uuid_le uuid, int instance) { - struct mdev_device *mdev; + struct device *dev; + struct mdev_info info = { + .uuid = uuid, + .instance = instance, + }; - list_for_each_entry(mdev, &parent->mdev_list, next) { - if ((uuid_le_cmp(mdev->uuid, uuid) == 0) && - (mdev->instance == instance)) - return mdev; - } - return NULL; + dev = device_find_child(&parent->dev, &info, __find_mdev_device); + if (!dev) + return NULL; + + return dev_to_mdev(dev); } static int mdev_device_create_ops(struct mdev_device *mdev, char *mdev_params) { - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); int ret; ret = parent->ops->create(mdev, mdev_params); @@ -72,7 +91,7 @@ static int mdev_device_create_ops(struct mdev_device *mdev, char *mdev_params) static int mdev_device_destroy_ops(struct mdev_device *mdev, bool force) { - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); int ret = 0; /* @@ -89,34 +108,6 @@ static int mdev_device_destroy_ops(struct mdev_device *mdev, bool force) return ret; } -static void mdev_release_device(struct kref *kref) -{ - struct mdev_device *mdev = container_of(kref, struct mdev_device, ref); - struct parent_device *parent = mdev->parent; - - list_del(&mdev->next); - mutex_unlock(&parent->mdev_list_lock); - - device_unregister(&mdev->dev); - wake_up(&parent->release_done); -} - -struct mdev_device *mdev_get_device(struct mdev_device *mdev) -{ - kref_get(&mdev->ref); - return mdev; -} -EXPORT_SYMBOL(mdev_get_device); - -void mdev_put_device(struct mdev_device *mdev) -{ - struct parent_device *parent = mdev->parent; - - kref_put_mutex(&mdev->ref, mdev_release_device, - &parent->mdev_list_lock); -} -EXPORT_SYMBOL(mdev_put_device); - /* * mdev_register_device : Register a device * @dev: device structure representing parent device. @@ -145,9 +136,6 @@ int mdev_register_device(struct device *dev, const struct parent_ops *ops) parent->dev.parent = dev; parent->ops = ops; - mutex_init(&parent->mdev_list_lock); - INIT_LIST_HEAD(&parent->mdev_list); - init_waitqueue_head(&parent->release_done); ret = device_register(&parent->dev); if (ret) @@ -176,63 +164,53 @@ add_dev_err: } EXPORT_SYMBOL(mdev_register_device); +static int __mdev_device_destroy(struct device *dev, void *data) +{ + struct mdev_device *mdev = dev_to_mdev(dev); + int ret, force = (unsigned long)data; + + ret = mdev_device_destroy_ops(mdev, force); + + /* can not fail if foce = true. */ + WARN_ON(force && ret); + if (ret) + goto destroy_err; + + device_unregister(&mdev->dev); + +destroy_err: + return ret; +} + /* * mdev_unregister_device : Unregister a parent device - * @dev: device structure representing parent device which is returned by - * mdev_register_device. + * @dev: device structure representing parent device * * Remove device from list of registered parent devices. Give a chance to free * existing mediated devices for given device. */ -void mdev_unregister_device(struct parent_device *parent) +void mdev_unregister_device(struct device *dev) { - struct mdev_device *mdev, *n; - int ret; - + struct parent_device *parent = dev_to_parent_dev(dev); dev_info(&parent->dev, "MDEV: Unregistering\n"); /* * Remove parent from the list and remove create and destroy sysfs * files so that no new mediated device could be created for this parent */ - mdev_remove_sysfs_files(&parent->dev); + mdev_remove_sysfs_files(dev); - mdev_remove_attribute_group(&parent->dev, - parent->ops->dev_attr_groups); + mdev_remove_attribute_group(dev, parent->ops->dev_attr_groups); - mutex_lock(&parent->mdev_list_lock); - list_for_each_entry_safe(mdev, n, &parent->mdev_list, next) { - mdev_device_destroy_ops(mdev, true); - mutex_unlock(&parent->mdev_list_lock); - mdev_put_device(mdev); - mutex_lock(&parent->mdev_list_lock); - } - mutex_unlock(&parent->mdev_list_lock); - - do { - ret = wait_event_interruptible_timeout(parent->release_done, - list_empty(&parent->mdev_list), HZ * 10); - if (ret == -ERESTARTSYS) { - dev_warn(&parent->dev, "Mediated devices are in use, task" - " \"%s\" (%d) " - "blocked until all are released", - current->comm, task_pid_nr(current)); - } - } while (ret <= 0); + device_for_each_child(dev, (void *)true, __mdev_device_destroy); + + device_unregister(dev); } EXPORT_SYMBOL(mdev_unregister_device); /* * Functions required for mdev_sysfs */ -static void mdev_device_release(struct device *dev) -{ - struct mdev_device *mdev = to_mdev_device(dev); - - dev_dbg(&mdev->dev, "MDEV: destroying\n"); - kfree(mdev); -} - int mdev_device_create(struct device *dev, uuid_le uuid, uint32_t instance, char *mdev_params) { @@ -240,7 +218,6 @@ int mdev_device_create(struct device *dev, uuid_le uuid, uint32_t instance, struct mdev_device *mdev; struct parent_device *parent = dev_to_parent_dev(dev); - mutex_lock(&parent->mdev_list_lock); /* Check for duplicate */ mdev = find_mdev_device(parent, uuid, instance); if (mdev) { @@ -256,13 +233,10 @@ int mdev_device_create(struct device *dev, uuid_le uuid, uint32_t instance, memcpy(&mdev->uuid, &uuid, sizeof(uuid_le)); mdev->instance = instance; - mdev->parent = parent; - kref_init(&mdev->ref); mdev->dev.parent = dev; mdev->dev.class = &mdev_class; mdev->dev.bus = &mdev_bus_type; - mdev->dev.release = mdev_device_release; dev_set_name(&mdev->dev, "%pUl-%d", uuid.b, instance); ret = device_register(&mdev->dev); @@ -275,9 +249,6 @@ int mdev_device_create(struct device *dev, uuid_le uuid, uint32_t instance, if (ret) goto create_failed; - list_add(&mdev->next, &parent->mdev_list); - mutex_unlock(&parent->mdev_list_lock); - dev_dbg(&mdev->dev, "MDEV: created\n"); return ret; @@ -286,35 +257,19 @@ create_failed: device_unregister(&mdev->dev); create_err: - mutex_unlock(&parent->mdev_list_lock); return ret; } int mdev_device_destroy(struct device *dev, uuid_le uuid, uint32_t instance) { struct mdev_device *mdev; - int ret; struct parent_device *parent = dev_to_parent_dev(dev); - mutex_lock(&parent->mdev_list_lock); mdev = find_mdev_device(parent, uuid, instance); - if (!mdev) { - ret = -EINVAL; - goto destroy_err; - } - - ret = mdev_device_destroy_ops(mdev, false); - if (ret) - goto destroy_err; - - mutex_unlock(&parent->mdev_list_lock); - mdev_put_device(mdev); - - return ret; + if (!mdev) + return -EINVAL; -destroy_err: - mutex_unlock(&parent->mdev_list_lock); - return ret; + return __mdev_device_destroy(&mdev->dev, (void *)false); } int mdev_device_invalidate_mapping(struct mdev_device *mdev, @@ -440,7 +395,6 @@ int mdev_device_start(struct device *dev, bool start) struct mdev_device *mdev = dev_to_mdev(dev); struct parent_device *parent = dev_to_parent_dev(dev->parent); - mdev_get_device(mdev); if (start && parent->ops->start) ret = parent->ops->start(mdev->uuid); else if (!start && parent->ops->stop) @@ -452,8 +406,6 @@ int mdev_device_start(struct device *dev, bool start) kobject_uevent(&mdev->dev.kobj, start ? KOBJ_ONLINE : KOBJ_OFFLINE); - mdev_put_device(mdev); - return ret; } diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c index 3080edc..bc81c6f 100644 --- a/drivers/vfio/mdev/mdev_sysfs.c +++ b/drivers/vfio/mdev/mdev_sysfs.c @@ -215,17 +215,20 @@ int mdev_create_sysfs_files(struct device *dev) ret = sysfs_create_file(&dev->kobj, &dev_attr_mdev_create.attr); if (ret) { pr_err("Failed to create mdev_create sysfs entry\n"); - goto create_sysfs_failed; + goto create_failed; } ret = sysfs_create_file(&dev->kobj, &dev_attr_mdev_destroy.attr); if (ret) { pr_err("Failed to create mdev_destroy sysfs entry\n"); - sysfs_remove_file(&dev->kobj, &dev_attr_mdev_create.attr); - } else - return ret; + goto destroy_failed; + } -create_sysfs_failed: + return ret; + +destroy_failed: + sysfs_remove_file(&dev->kobj, &dev_attr_mdev_create.attr); +create_failed: sysfs_remove_file(&dev->kobj, &dev_attr_mdev_supported_types.attr); return ret; } diff --git a/drivers/vfio/mdev/vfio_mpci.c b/drivers/vfio/mdev/vfio_mpci.c index 88c0ba6..502aeb7 100644 --- a/drivers/vfio/mdev/vfio_mpci.c +++ b/drivers/vfio/mdev/vfio_mpci.c @@ -38,7 +38,8 @@ static int vfio_mpci_open(void *device_data) { int ret = 0; struct vfio_mdev *vmdev = device_data; - struct parent_device *parent = vmdev->mdev->parent; + struct mdev_device *mdev = vmdev->mdev; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); if (!try_module_get(THIS_MODULE)) return -ENODEV; @@ -83,7 +84,7 @@ static void vfio_mpci_close(void *device_data) static u8 mpci_find_pci_capability(struct mdev_device *mdev, u8 capability) { loff_t pos = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_CONFIG_REGION_INDEX); - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); u16 status; u8 cap_ptr, cap_id = 0xff; @@ -112,7 +113,7 @@ static int mpci_get_irq_count(struct vfio_mdev *vmdev, int irq_type) { loff_t pos = VFIO_PCI_INDEX_TO_OFFSET(VFIO_PCI_CONFIG_REGION_INDEX); struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); if (irq_type == VFIO_PCI_INTX_IRQ_INDEX) { u8 pin; @@ -161,13 +162,14 @@ static long vfio_mpci_unlocked_ioctl(void *device_data, { int ret = 0; struct vfio_mdev *vmdev = device_data; + struct mdev_device *mdev = vmdev->mdev; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); unsigned long minsz; switch (cmd) { case VFIO_DEVICE_GET_INFO: { struct vfio_device_info info; - struct parent_device *parent = vmdev->mdev->parent; minsz = offsetofend(struct vfio_device_info, num_irqs); @@ -258,8 +260,6 @@ static long vfio_mpci_unlocked_ioctl(void *device_data, case VFIO_DEVICE_SET_IRQS: { struct vfio_irq_set hdr; - struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = mdev->parent; u8 *data = NULL, *ptr = NULL; minsz = offsetofend(struct vfio_irq_set, count); @@ -302,8 +302,6 @@ static long vfio_mpci_unlocked_ioctl(void *device_data, } case VFIO_DEVICE_RESET: { - struct parent_device *parent = vmdev->mdev->parent; - if (parent->ops->reset) return parent->ops->reset(vmdev->mdev); @@ -318,7 +316,7 @@ static ssize_t vfio_mpci_read(void *device_data, char __user *buf, { struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); int ret = 0; if (!count) @@ -351,7 +349,7 @@ static ssize_t vfio_mpci_write(void *device_data, const char __user *buf, { struct vfio_mdev *vmdev = device_data; struct mdev_device *mdev = vmdev->mdev; - struct parent_device *parent = mdev->parent; + struct parent_device *parent = dev_to_parent_dev(mdev->dev.parent); int ret = 0; if (!count) @@ -390,7 +388,7 @@ static int mdev_dev_mmio_fault(struct vm_area_struct *vma, struct vm_fault *vmf) return -EINVAL; mdev = vmdev->mdev; - parent = mdev->parent; + parent = dev_to_parent_dev(mdev->dev.parent); pg_prot = vma->vm_page_prot; @@ -482,7 +480,7 @@ int vfio_mpci_probe(struct device *dev) if (IS_ERR(vmdev)) return PTR_ERR(vmdev); - vmdev->mdev = mdev_get_device(mdev); + vmdev->mdev = mdev; vmdev->group = mdev->group; mutex_init(&vmdev->vfio_mdev_lock); @@ -490,7 +488,6 @@ int vfio_mpci_probe(struct device *dev) if (ret) kfree(vmdev); - mdev_put_device(mdev); return ret; } diff --git a/include/linux/mdev.h b/include/linux/mdev.h index 42da41b..8488b27 100644 --- a/include/linux/mdev.h +++ b/include/linux/mdev.h @@ -35,16 +35,12 @@ struct mdev_phys_mapping { struct mdev_device { struct device dev; - struct parent_device *parent; struct iommu_group *group; uuid_le uuid; uint32_t instance; void *driver_data; /* internal only */ - struct kref ref; - struct list_head next; - struct mdev_phys_mapping phys_mappings; }; @@ -157,15 +153,9 @@ struct parent_ops { /* * Parent Device */ - struct parent_device { struct device dev; const struct parent_ops *ops; - - /* internal */ - struct list_head mdev_list; - struct mutex mdev_list_lock; - wait_queue_head_t release_done; }; /** @@ -212,14 +202,11 @@ extern struct bus_type mdev_bus_type; extern int mdev_register_device(struct device *dev, const struct parent_ops *ops); -extern void mdev_unregister_device(struct parent_device *parent); +extern void mdev_unregister_device(struct device *dev); extern int mdev_register_driver(struct mdev_driver *drv, struct module *owner); extern void mdev_unregister_driver(struct mdev_driver *drv); -extern struct mdev_device *mdev_get_device(struct mdev_device *mdev); -extern void mdev_put_device(struct mdev_device *mdev); - extern struct mdev_device *mdev_get_device_by_group(struct iommu_group *group); extern int mdev_device_invalidate_mapping(struct mdev_device *mdev, -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html