qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC v6-based v1 2/5] mdev: drop management information and


From: Jike Song
Subject: [Qemu-devel] [RFC v6-based v1 2/5] mdev: drop management information and utilize driver-core instead
Date: Tue, 16 Aug 2016 16:14:14 +0800

From: Xiao Guangrong <address@hidden>

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]