diff mbox

[RFC,v6-based,v1,2/5] mdev: drop management information and utilize driver-core instead

Message ID 1471335257-6226-3-git-send-email-jike.song@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Jike Song Aug. 16, 2016, 8:14 a.m. UTC
From: Xiao Guangrong <guangrong.xiao@linux.intel.com>

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@linux.intel.com>
---
 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 mbox

Patch

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,