All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-08  0:55 ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc, linux-s390,
	Halil Pasic, Rafael J. Wysocki, Rodrigo Vivi
  Cc: Christoph Hellwig

This is a "v3" of the previous posted full conversion:
  https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com

Without the trailing patches that are running into complications:
 - The CCW conversion has some complicated remarks
 - AP is waiting for some locking stuff to get worked out
 - No feedback on GT
 - The license change topic for removing vfio_mdev.c

Getting the baseline functionality merged will allow Intel's IDXD mdev
driver to advance. It has already been RFC posted in the new format:

https://lore.kernel.org/kvm/162164243591.261970.3439987543338120797.stgit@djiang5-desk3.ch.intel.com/

This series includes base infrastructure and the sample conversions. The
remaining four issues can be sorted out one by one.

The major change in v3 is to enhance the driver core support for binding
based on the request from Christoph Hellwig and Dan Williams. Based on
some light analysis this looks broadly useful:

https://lore.kernel.org/kvm/20210428233856.GY1370958@nvidia.com/

====

The mdev bus's core part for managing the lifecycle of devices is mostly
as one would expect for a driver core bus subsystem.

However instead of having a normal 'struct device_driver' and binding the
actual mdev drivers through the standard driver core mechanisms it open
codes this with the struct mdev_parent_ops and provides a single driver
that shims between the VFIO core's struct vfio_device and the actual
device driver.

Instead, allow mdev drivers implement an actual struct mdev_driver and
directly call vfio_register_group_dev() in the probe() function for the
mdev. Arrange to bind the created mdev_device to the mdev_driver that is
provided by the end driver.

The actual execution flow doesn't change much, eg what was
parent_ops->create is now device_driver->probe and it is called at almost
the exact same time - except under the normal control of the driver core.

Ultimately converting all the drivers unlocks a fair number of additional
VFIO simplifications and cleanups.

v3:
 - Use device_driver_attach() from the driver core
 - 5 new patches to make device_driver_attach() exported and usable for this
 - Remove trailing patches for now
v2: https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
 - Keep && m in samples kconfig
 - Restore accidently squashed removeal of vfio_mdev.c
 - Remove indirections to call bus_register()/bus_unregister()
 - Reflow long doc lines
v1: https://lore.kernel.org/r/0-v1-d88406ed308e+418-vfio3_jgg@nvidia.com

Jason Gunthorpe (10):
  driver core: Do not continue searching for drivers if deferred probe
    is used
  driver core: Pull required checks into driver_probe_device()
  driver core: Flow the return code from ->probe() through to sysfs bind
  driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
  driver core: Export device_driver_attach()
  vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  vfio/mdev: Allow the mdev_parent_ops to specify the device driver to
    bind
  vfio/mtty: Convert to use vfio_register_group_dev()
  vfio/mdpy: Convert to use vfio_register_group_dev()
  vfio/mbochs: Convert to use vfio_register_group_dev()

 Documentation/s390/vfio-ap.rst   |   1 -
 arch/s390/Kconfig                |   2 +-
 drivers/base/base.h              |   1 -
 drivers/base/bus.c               |   6 +-
 drivers/base/dd.c                | 116 ++++++++++++-------
 drivers/gpu/drm/i915/Kconfig     |   2 +-
 drivers/vfio/mdev/Kconfig        |   7 --
 drivers/vfio/mdev/Makefile       |   3 +-
 drivers/vfio/mdev/mdev_core.c    |  46 ++++++--
 drivers/vfio/mdev/mdev_driver.c  |  10 ++
 drivers/vfio/mdev/mdev_private.h |   2 +
 drivers/vfio/mdev/vfio_mdev.c    |  24 +---
 include/linux/device.h           |   2 +
 include/linux/mdev.h             |   2 +
 samples/Kconfig                  |   6 +-
 samples/vfio-mdev/mbochs.c       | 163 +++++++++++++++------------
 samples/vfio-mdev/mdpy.c         | 159 ++++++++++++++------------
 samples/vfio-mdev/mtty.c         | 185 ++++++++++++++-----------------
 18 files changed, 397 insertions(+), 340 deletions(-)

-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [Intel-gfx] [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-08  0:55 ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc, linux-s390,
	Halil Pasic, Rafael J. Wysocki, Rodrigo Vivi
  Cc: Christoph Hellwig

This is a "v3" of the previous posted full conversion:
  https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com

Without the trailing patches that are running into complications:
 - The CCW conversion has some complicated remarks
 - AP is waiting for some locking stuff to get worked out
 - No feedback on GT
 - The license change topic for removing vfio_mdev.c

Getting the baseline functionality merged will allow Intel's IDXD mdev
driver to advance. It has already been RFC posted in the new format:

https://lore.kernel.org/kvm/162164243591.261970.3439987543338120797.stgit@djiang5-desk3.ch.intel.com/

This series includes base infrastructure and the sample conversions. The
remaining four issues can be sorted out one by one.

The major change in v3 is to enhance the driver core support for binding
based on the request from Christoph Hellwig and Dan Williams. Based on
some light analysis this looks broadly useful:

https://lore.kernel.org/kvm/20210428233856.GY1370958@nvidia.com/

====

The mdev bus's core part for managing the lifecycle of devices is mostly
as one would expect for a driver core bus subsystem.

However instead of having a normal 'struct device_driver' and binding the
actual mdev drivers through the standard driver core mechanisms it open
codes this with the struct mdev_parent_ops and provides a single driver
that shims between the VFIO core's struct vfio_device and the actual
device driver.

Instead, allow mdev drivers implement an actual struct mdev_driver and
directly call vfio_register_group_dev() in the probe() function for the
mdev. Arrange to bind the created mdev_device to the mdev_driver that is
provided by the end driver.

The actual execution flow doesn't change much, eg what was
parent_ops->create is now device_driver->probe and it is called at almost
the exact same time - except under the normal control of the driver core.

Ultimately converting all the drivers unlocks a fair number of additional
VFIO simplifications and cleanups.

v3:
 - Use device_driver_attach() from the driver core
 - 5 new patches to make device_driver_attach() exported and usable for this
 - Remove trailing patches for now
v2: https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
 - Keep && m in samples kconfig
 - Restore accidently squashed removeal of vfio_mdev.c
 - Remove indirections to call bus_register()/bus_unregister()
 - Reflow long doc lines
v1: https://lore.kernel.org/r/0-v1-d88406ed308e+418-vfio3_jgg@nvidia.com

Jason Gunthorpe (10):
  driver core: Do not continue searching for drivers if deferred probe
    is used
  driver core: Pull required checks into driver_probe_device()
  driver core: Flow the return code from ->probe() through to sysfs bind
  driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
  driver core: Export device_driver_attach()
  vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  vfio/mdev: Allow the mdev_parent_ops to specify the device driver to
    bind
  vfio/mtty: Convert to use vfio_register_group_dev()
  vfio/mdpy: Convert to use vfio_register_group_dev()
  vfio/mbochs: Convert to use vfio_register_group_dev()

 Documentation/s390/vfio-ap.rst   |   1 -
 arch/s390/Kconfig                |   2 +-
 drivers/base/base.h              |   1 -
 drivers/base/bus.c               |   6 +-
 drivers/base/dd.c                | 116 ++++++++++++-------
 drivers/gpu/drm/i915/Kconfig     |   2 +-
 drivers/vfio/mdev/Kconfig        |   7 --
 drivers/vfio/mdev/Makefile       |   3 +-
 drivers/vfio/mdev/mdev_core.c    |  46 ++++++--
 drivers/vfio/mdev/mdev_driver.c  |  10 ++
 drivers/vfio/mdev/mdev_private.h |   2 +
 drivers/vfio/mdev/vfio_mdev.c    |  24 +---
 include/linux/device.h           |   2 +
 include/linux/mdev.h             |   2 +
 samples/Kconfig                  |   6 +-
 samples/vfio-mdev/mbochs.c       | 163 +++++++++++++++------------
 samples/vfio-mdev/mdpy.c         | 159 ++++++++++++++------------
 samples/vfio-mdev/mtty.c         | 185 ++++++++++++++-----------------
 18 files changed, 397 insertions(+), 340 deletions(-)

-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  5:51   ` Christoph Hellwig
                     ` (2 more replies)
  -1 siblings, 3 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

Once a driver has been matched and probe() returns with -EPROBE_DEFER the
device is added to a deferred list and will be retried later.

At this point __device_attach_driver() should stop trying other drivers as
we have "matched" this driver and already scheduled another probe to
happen later.

Return the -EPROBE_DEFER from really_probe() instead of squashing it to
zero. This is similar to the code at the top of the function which
directly returns -EPROBE_DEFER.

It is not really a bug as, AFAIK, we don't actually have cases where
multiple drivers can bind.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/base/dd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index ecd7cf848daff7..9d79a139290271 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -656,7 +656,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 		/* Driver requested deferred probing */
 		dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
 		driver_deferred_probe_add_trigger(dev, local_trigger_count);
-		break;
+		goto done;
 	case -ENODEV:
 	case -ENXIO:
 		pr_debug("%s: probe of %s rejects match %d\n",
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 02/10] driver core: Pull required checks into driver_probe_device()
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
  (?)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  5:59   ` Christoph Hellwig
  -1 siblings, 1 reply; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

Checking if the dev is dead or if the dev is already bound is a required
precondition to invoking driver_probe_device(). All the call chains
leading here duplicate these checks.

Add it directly to driver_probe_device() so the precondition is clear and
remove the checks from device_driver_attach() and
__driver_attach_async_helper().

The other call chain going through __device_attach_driver() does have
these same checks but they are inlined into logic higher up the call stack
and can't be removed.

Preserve the sysfs uAPI behavior for store of succeeding if any driver is
already bound, but consistently fail if the device is unregistered or
dead.

Done in preparation for the next patches which will add additional
callers to driver_probe_device().

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/base/dd.c | 27 +++++++++++----------------
 1 file changed, 11 insertions(+), 16 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 9d79a139290271..c1a92cff159873 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -733,8 +733,9 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
  * @drv: driver to bind a device to
  * @dev: device to try to bind to the driver
  *
- * This function returns -ENODEV if the device is not registered,
- * 1 if the device is bound successfully and 0 otherwise.
+ * This function returns -ENODEV if the device is not registered, -EBUSY if it
+ * already has a driver, and 1 if the device is bound successfully and 0
+ * otherwise.
  *
  * This function must be called with @dev lock held.  When called for a
  * USB interface, @dev->parent lock must be held as well.
@@ -745,8 +746,10 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev)
 {
 	int ret = 0;
 
-	if (!device_is_registered(dev))
+	if (dev->p->dead || !device_is_registered(dev))
 		return -ENODEV;
+	if (dev->driver)
+		return -EBUSY;
 
 	dev->can_match = true;
 	pr_debug("bus: '%s': %s: matched device %s with driver %s\n",
@@ -1032,10 +1035,10 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
 	__device_driver_lock(dev, dev->parent);
 
 	/*
-	 * If device has been removed or someone has already successfully
-	 * bound a driver before us just skip the driver probe call.
+	 * If device someone has already successfully bound a driver before us
+	 * just skip the driver probe call.
 	 */
-	if (!dev->p->dead && !dev->driver)
+	if (!dev->driver)
 		ret = driver_probe_device(drv, dev);
 
 	__device_driver_unlock(dev, dev->parent);
@@ -1047,19 +1050,11 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
 {
 	struct device *dev = _dev;
 	struct device_driver *drv;
-	int ret = 0;
+	int ret;
 
 	__device_driver_lock(dev, dev->parent);
-
 	drv = dev->p->async_driver;
-
-	/*
-	 * If device has been removed or someone has already successfully
-	 * bound a driver before us just skip the driver probe call.
-	 */
-	if (!dev->p->dead && !dev->driver)
-		ret = driver_probe_device(drv, dev);
-
+	ret = driver_probe_device(drv, dev);
 	__device_driver_unlock(dev, dev->parent);
 
 	dev_dbg(dev, "driver %s async attach completed: %d\n", drv->name, ret);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (2 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  6:07   ` Christoph Hellwig
  2021-06-08  6:47   ` Greg Kroah-Hartman
  -1 siblings, 2 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

Currently really_probe() returns 1 on success and 0 if the probe() call
fails. This return code arrangement is designed to be useful for
__device_attach_driver() which is walking the device list and trying every
driver. 0 means to keep trying.

However, it is not useful for the other places that call through to
really_probe() that do actually want to see the probe() return code.

For instance bind_store() would be better to return the actual error code
from the driver's probe method, not discarding it and returning -ENODEV.

Reorganize things so that really_probe() always returns an error code on
failure and 0 on success. Move the special code for device list walking
into the walker callback __device_attach_driver() and trigger it based on
an output flag from really_probe(). Update the rest of the API surface to
return a normal -ERR or 0 on success.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/base/bus.c |  6 +----
 drivers/base/dd.c  | 61 ++++++++++++++++++++++++++++++----------------
 2 files changed, 41 insertions(+), 26 deletions(-)

diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 36d0c654ea6124..03591f82251302 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -212,13 +212,9 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
 	dev = bus_find_device_by_name(bus, NULL, buf);
 	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
 		err = device_driver_attach(drv, dev);
-
-		if (err > 0) {
+		if (!err) {
 			/* success */
 			err = count;
-		} else if (err == 0) {
-			/* driver didn't accept device */
-			err = -ENODEV;
 		}
 	}
 	put_device(dev);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c1a92cff159873..7fb58e6219b255 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -513,7 +513,13 @@ static ssize_t state_synced_show(struct device *dev,
 }
 static DEVICE_ATTR_RO(state_synced);
 
-static int really_probe(struct device *dev, struct device_driver *drv)
+enum {
+	/* Set on output if the -ERR has come from a probe() function */
+	PROBEF_DRV_FAILED = 1 << 0,
+};
+
+static int really_probe(struct device *dev, struct device_driver *drv,
+			unsigned int *flags)
 {
 	int ret = -EPROBE_DEFER;
 	int local_trigger_count = atomic_read(&deferred_trigger_count);
@@ -574,12 +580,16 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 
 	if (dev->bus->probe) {
 		ret = dev->bus->probe(dev);
-		if (ret)
+		if (ret) {
+			*flags |= PROBEF_DRV_FAILED;
 			goto probe_failed;
+		}
 	} else if (drv->probe) {
 		ret = drv->probe(dev);
-		if (ret)
+		if (ret) {
+			*flags |= PROBEF_DRV_FAILED;
 			goto probe_failed;
+		}
 	}
 
 	if (device_add_groups(dev, drv->dev_groups)) {
@@ -621,7 +631,6 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 		dev->pm_domain->sync(dev);
 
 	driver_bound(dev);
-	ret = 1;
 	pr_debug("bus: '%s': %s: bound device %s to driver %s\n",
 		 drv->bus->name, __func__, dev_name(dev), drv->name);
 	goto done;
@@ -656,7 +665,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 		/* Driver requested deferred probing */
 		dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
 		driver_deferred_probe_add_trigger(dev, local_trigger_count);
-		goto done;
+		break;
 	case -ENODEV:
 	case -ENXIO:
 		pr_debug("%s: probe of %s rejects match %d\n",
@@ -667,11 +676,6 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 		pr_warn("%s: probe of %s failed with error %d\n",
 			drv->name, dev_name(dev), ret);
 	}
-	/*
-	 * Ignore errors returned by ->probe so that the next driver can try
-	 * its luck.
-	 */
-	ret = 0;
 done:
 	atomic_dec(&probe_count);
 	wake_up_all(&probe_waitqueue);
@@ -681,13 +685,14 @@ static int really_probe(struct device *dev, struct device_driver *drv)
 /*
  * For initcall_debug, show the driver probe time.
  */
-static int really_probe_debug(struct device *dev, struct device_driver *drv)
+static int really_probe_debug(struct device *dev, struct device_driver *drv,
+			      unsigned int *flags)
 {
 	ktime_t calltime, rettime;
 	int ret;
 
 	calltime = ktime_get();
-	ret = really_probe(dev, drv);
+	ret = really_probe(dev, drv, flags);
 	rettime = ktime_get();
 	pr_debug("probe of %s returned %d after %lld usecs\n",
 		 dev_name(dev), ret, ktime_us_delta(rettime, calltime));
@@ -732,17 +737,18 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
  * driver_probe_device - attempt to bind device & driver together
  * @drv: driver to bind a device to
  * @dev: device to try to bind to the driver
+ * @flags: PROBEF flags input/output
  *
  * This function returns -ENODEV if the device is not registered, -EBUSY if it
- * already has a driver, and 1 if the device is bound successfully and 0
- * otherwise.
+ * already has a driver,  and 0 if the device is bound successfully.
  *
  * This function must be called with @dev lock held.  When called for a
  * USB interface, @dev->parent lock must be held as well.
  *
  * If the device has a parent, runtime-resume the parent before driver probing.
  */
-static int driver_probe_device(struct device_driver *drv, struct device *dev)
+static int driver_probe_device(struct device_driver *drv, struct device *dev,
+			       unsigned int *flags)
 {
 	int ret = 0;
 
@@ -761,9 +767,9 @@ static int driver_probe_device(struct device_driver *drv, struct device *dev)
 
 	pm_runtime_barrier(dev);
 	if (initcall_debug)
-		ret = really_probe_debug(dev, drv);
+		ret = really_probe_debug(dev, drv, flags);
 	else
-		ret = really_probe(dev, drv);
+		ret = really_probe(dev, drv, flags);
 	pm_request_idle(dev);
 
 	if (dev->parent)
@@ -847,6 +853,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
 	struct device_attach_data *data = _data;
 	struct device *dev = data->dev;
 	bool async_allowed;
+	int flags = 0;
 	int ret;
 
 	ret = driver_match_device(drv, dev);
@@ -870,7 +877,17 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
 	if (data->check_async && async_allowed != data->want_async)
 		return 0;
 
-	return driver_probe_device(drv, dev);
+	ret = driver_probe_device(drv, dev, &flags);
+	if (ret) {
+		/*
+		 * Ignore errors returned by ->probe so that the next driver can
+		 * try its luck.
+		 */
+		if (flags & PROBEF_DRV_FAILED)
+			return 0;
+		return ret;
+	}
+	return 1;
 }
 
 static void __device_attach_async_helper(void *_dev, async_cookie_t cookie)
@@ -1026,10 +1043,11 @@ static void __device_driver_unlock(struct device *dev, struct device *parent)
  * @dev: Device to attach it to
  *
  * Manually attach driver to a device. Will acquire both @dev lock and
- * @dev->parent lock if needed.
+ * @dev->parent lock if needed. Returns 0 on success, -ERR on failure.
  */
 int device_driver_attach(struct device_driver *drv, struct device *dev)
 {
+	unsigned int flags = 0;
 	int ret = 0;
 
 	__device_driver_lock(dev, dev->parent);
@@ -1039,7 +1057,7 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
 	 * just skip the driver probe call.
 	 */
 	if (!dev->driver)
-		ret = driver_probe_device(drv, dev);
+		ret = driver_probe_device(drv, dev, &flags);
 
 	__device_driver_unlock(dev, dev->parent);
 
@@ -1050,11 +1068,12 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
 {
 	struct device *dev = _dev;
 	struct device_driver *drv;
+	unsigned int flags = 0;
 	int ret;
 
 	__device_driver_lock(dev, dev->parent);
 	drv = dev->p->async_driver;
-	ret = driver_probe_device(drv, dev);
+	ret = driver_probe_device(drv, dev, &flags);
 	__device_driver_unlock(dev, dev->parent);
 
 	dev_dbg(dev, "driver %s async attach completed: %d\n", drv->name, ret);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (3 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  6:14   ` Christoph Hellwig
  2021-06-08  7:37   ` Greg Kroah-Hartman
  -1 siblings, 2 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

EPROBE_DEFER is an internal kernel error code and it should not be leaked
to userspace via the bind_store() sysfs. Userspace doesn't have this
constant and cannot understand it.

Further, it doesn't really make sense to have userspace trigger a deferred
probe via bind_store(), which could eventually succeed, while
simultaneously returning an error back.

Resolve this by preventing EPROBE_DEFER from triggering a deferred probe
and simply relay the whole situation back to userspace as a normal -EAGAIN
code.

Put this in the device_driver_attach() so the EPROBE_DEFER remains
contained to dd.c and the probe() implementations.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/base/dd.c | 39 ++++++++++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 11 deletions(-)

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 7fb58e6219b255..edda7aad43a3f7 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -516,12 +516,17 @@ static DEVICE_ATTR_RO(state_synced);
 enum {
 	/* Set on output if the -ERR has come from a probe() function */
 	PROBEF_DRV_FAILED = 1 << 0,
+	/*
+	 * Set on input to call driver_deferred_probe_add() if -EPROBE_DEFER
+	 * is returned
+	 */
+	PROBEF_SCHEDULE_DEFER = 1 << 1,
 };
 
 static int really_probe(struct device *dev, struct device_driver *drv,
 			unsigned int *flags)
 {
-	int ret = -EPROBE_DEFER;
+	int ret;
 	int local_trigger_count = atomic_read(&deferred_trigger_count);
 	bool test_remove = IS_ENABLED(CONFIG_DEBUG_TEST_DRIVER_REMOVE) &&
 			   !drv->suppress_bind_attrs;
@@ -533,15 +538,18 @@ static int really_probe(struct device *dev, struct device_driver *drv,
 		 * wait_for_device_probe() right after that to avoid any races.
 		 */
 		dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
-		driver_deferred_probe_add(dev);
-		return ret;
+		if (*flags & PROBEF_SCHEDULE_DEFER)
+			driver_deferred_probe_add(dev);
+		return -EPROBE_DEFER;
 	}
 
 	ret = device_links_check_suppliers(dev);
-	if (ret == -EPROBE_DEFER)
-		driver_deferred_probe_add_trigger(dev, local_trigger_count);
-	if (ret)
+	if (ret) {
+		if (ret == -EPROBE_DEFER && *flags & PROBEF_SCHEDULE_DEFER)
+			driver_deferred_probe_add_trigger(dev,
+							  local_trigger_count);
 		return ret;
+	}
 
 	atomic_inc(&probe_count);
 	pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
@@ -664,7 +672,9 @@ static int really_probe(struct device *dev, struct device_driver *drv,
 	case -EPROBE_DEFER:
 		/* Driver requested deferred probing */
 		dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
-		driver_deferred_probe_add_trigger(dev, local_trigger_count);
+		if (*flags & PROBEF_SCHEDULE_DEFER)
+			driver_deferred_probe_add_trigger(dev,
+							  local_trigger_count);
 		break;
 	case -ENODEV:
 	case -ENXIO:
@@ -853,7 +863,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
 	struct device_attach_data *data = _data;
 	struct device *dev = data->dev;
 	bool async_allowed;
-	int flags = 0;
+	int flags = PROBEF_SCHEDULE_DEFER;
 	int ret;
 
 	ret = driver_match_device(drv, dev);
@@ -1043,7 +1053,9 @@ static void __device_driver_unlock(struct device *dev, struct device *parent)
  * @dev: Device to attach it to
  *
  * Manually attach driver to a device. Will acquire both @dev lock and
- * @dev->parent lock if needed. Returns 0 on success, -ERR on failure.
+ * @dev->parent lock if needed. Returns 0 on success, -ERR on failure. If
+ * EPROBE_DEFER is returned from probe() then no background probe is scheduled
+ * and -EAGAIN will be returned.
  */
 int device_driver_attach(struct device_driver *drv, struct device *dev)
 {
@@ -1061,6 +1073,8 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
 
 	__device_driver_unlock(dev, dev->parent);
 
+	if (ret == -EPROBE_DEFER)
+		return -EAGAIN;
 	return ret;
 }
 
@@ -1068,7 +1082,7 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
 {
 	struct device *dev = _dev;
 	struct device_driver *drv;
-	unsigned int flags = 0;
+	unsigned int flags = PROBEF_SCHEDULE_DEFER;
 	int ret;
 
 	__device_driver_lock(dev, dev->parent);
@@ -1083,6 +1097,7 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
 
 static int __driver_attach(struct device *dev, void *data)
 {
+	unsigned int flags = PROBEF_SCHEDULE_DEFER;
 	struct device_driver *drv = data;
 	int ret;
 
@@ -1128,7 +1143,9 @@ static int __driver_attach(struct device *dev, void *data)
 		return 0;
 	}
 
-	device_driver_attach(drv, dev);
+	__device_driver_lock(dev, dev->parent);
+	driver_probe_device(drv, dev, &flags);
+	__device_driver_unlock(dev, dev->parent);
 
 	return 0;
 }
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 05/10] driver core: Export device_driver_attach()
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (4 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  6:19   ` Christoph Hellwig
  -1 siblings, 1 reply; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

This is intended as a replacement API for device_bind_driver(). It has at
least the following benefits:

- Internal locking. Few of the users of device_bind_driver() follow the
  locking rules

- Calls device driver probe() internally. Notably this means that devm
  support for probe works correctly as probe() error will call
  devres_release_all()

- struct device_driver -> dev_groups is supported

- Simplified calling convention, no need to manually call probe().

The general usage is for situations that already know what driver to bind
and need to ensure the bind is synchronized with other logic. Call
device_driver_attach() after device_add().

If probe() returns a failure then this will be preserved up through to the
error return of device_driver_attach().

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/base/base.h    | 1 -
 drivers/base/dd.c      | 3 +++
 include/linux/device.h | 2 ++
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/base/base.h b/drivers/base/base.h
index e5f9b7e656c34b..404db83ee5ecb5 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -152,7 +152,6 @@ extern int driver_add_groups(struct device_driver *drv,
 			     const struct attribute_group **groups);
 extern void driver_remove_groups(struct device_driver *drv,
 				 const struct attribute_group **groups);
-int device_driver_attach(struct device_driver *drv, struct device *dev);
 void device_driver_detach(struct device *dev);
 
 extern char *make_class_name(const char *name, struct kobject *kobj);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index edda7aad43a3f7..9a5792527326b7 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -471,6 +471,8 @@ static void driver_sysfs_remove(struct device *dev)
  * (It is ok to call with no other effort from a driver's probe() method.)
  *
  * This function must be called with the device lock held.
+ *
+ * Callers should prefer to use device_driver_attach() instead.
  */
 int device_bind_driver(struct device *dev)
 {
@@ -1077,6 +1079,7 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
 		return -EAGAIN;
 	return ret;
 }
+EXPORT_SYMBOL_GPL(device_driver_attach);
 
 static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
 {
diff --git a/include/linux/device.h b/include/linux/device.h
index 38a2071cf77685..d03544f04aa9ee 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -847,6 +847,8 @@ static inline void *dev_get_platdata(const struct device *dev)
  * Manual binding of a device to driver. See drivers/base/bus.c
  * for information on use.
  */
+int __must_check device_driver_attach(struct device_driver *drv,
+				      struct device *dev);
 int __must_check device_bind_driver(struct device *dev);
 void device_release_driver(struct device *dev);
 int  __must_check device_attach(struct device *dev);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
@ 2021-06-08  0:55   ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Heiko Carstens,
	intel-gfx, Jani Nikula, Jason Herne, Joonas Lahtinen, kvm,
	Kirti Wankhede, linux-doc, linux-s390, Halil Pasic, Rodrigo Vivi

For some reason the vfio_mdev shim mdev_driver has its own module and
kconfig. As the next patch requires access to it from mdev.ko merge the
two modules together and remove VFIO_MDEV_DEVICE.

A later patch deletes this driver entirely.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 Documentation/s390/vfio-ap.rst   |  1 -
 arch/s390/Kconfig                |  2 +-
 drivers/gpu/drm/i915/Kconfig     |  2 +-
 drivers/vfio/mdev/Kconfig        |  7 -------
 drivers/vfio/mdev/Makefile       |  3 +--
 drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
 drivers/vfio/mdev/mdev_private.h |  2 ++
 drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
 samples/Kconfig                  |  6 +++---
 9 files changed, 23 insertions(+), 40 deletions(-)

diff --git a/Documentation/s390/vfio-ap.rst b/Documentation/s390/vfio-ap.rst
index e15436599086b7..f57ae621f33e89 100644
--- a/Documentation/s390/vfio-ap.rst
+++ b/Documentation/s390/vfio-ap.rst
@@ -514,7 +514,6 @@ These are the steps:
    * S390_AP_IOMMU
    * VFIO
    * VFIO_MDEV
-   * VFIO_MDEV_DEVICE
    * KVM
 
    If using make menuconfig select the following to build the vfio_ap module::
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b4c7c34069f81a..ea63fd22e1198a 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -768,7 +768,7 @@ config VFIO_CCW
 config VFIO_AP
 	def_tristate n
 	prompt "VFIO support for AP devices"
-	depends on S390_AP_IOMMU && VFIO_MDEV_DEVICE && KVM
+	depends on S390_AP_IOMMU && VFIO_MDEV && KVM
 	depends on ZCRYPT
 	help
 		This driver grants access to Adjunct Processor (AP) devices
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 69f57ca9c68d73..9ab1cecd69b2a0 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -126,7 +126,7 @@ config DRM_I915_GVT_KVMGT
 	tristate "Enable KVM/VFIO support for Intel GVT-g"
 	depends on DRM_I915_GVT
 	depends on KVM
-	depends on VFIO_MDEV && VFIO_MDEV_DEVICE
+	depends on VFIO_MDEV
 	default n
 	help
 	  Choose this option if you want to enable KVMGT support for
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig
index 5da27f2100f9bd..763c877a1318bc 100644
--- a/drivers/vfio/mdev/Kconfig
+++ b/drivers/vfio/mdev/Kconfig
@@ -9,10 +9,3 @@ config VFIO_MDEV
 	  See Documentation/driver-api/vfio-mediated-device.rst for more details.
 
 	  If you don't know what do here, say N.
-
-config VFIO_MDEV_DEVICE
-	tristate "VFIO driver for Mediated devices"
-	depends on VFIO && VFIO_MDEV
-	default n
-	help
-	  VFIO based driver for Mediated devices.
diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile
index 101516fdf3753e..ff9ecd80212503 100644
--- a/drivers/vfio/mdev/Makefile
+++ b/drivers/vfio/mdev/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o
+mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o vfio_mdev.o
 
 obj-$(CONFIG_VFIO_MDEV) += mdev.o
-obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 2a85d6fcb7ddd0..ff8c1a84516698 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -360,11 +360,24 @@ int mdev_device_remove(struct mdev_device *mdev)
 
 static int __init mdev_init(void)
 {
-	return mdev_bus_register();
+	int rc;
+
+	rc = mdev_bus_register();
+	if (rc)
+		return rc;
+	rc = mdev_register_driver(&vfio_mdev_driver);
+	if (rc)
+		goto err_bus;
+	return 0;
+err_bus:
+	mdev_bus_unregister();
+	return rc;
 }
 
 static void __exit mdev_exit(void)
 {
+	mdev_unregister_driver(&vfio_mdev_driver);
+
 	if (mdev_bus_compat_class)
 		class_compat_unregister(mdev_bus_compat_class);
 
@@ -378,4 +391,3 @@ MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_SOFTDEP("post: vfio_mdev");
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 6999c89db7b162..afbad7b0a14a17 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -37,6 +37,8 @@ struct mdev_type {
 #define to_mdev_type(_kobj)		\
 	container_of(_kobj, struct mdev_type, kobj)
 
+extern struct mdev_driver vfio_mdev_driver;
+
 int  parent_create_sysfs_files(struct mdev_parent *parent);
 void parent_remove_sysfs_files(struct mdev_parent *parent);
 
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
index 922729071c5a8e..d5b4eede47c1a5 100644
--- a/drivers/vfio/mdev/vfio_mdev.c
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -17,10 +17,6 @@
 
 #include "mdev_private.h"
 
-#define DRIVER_VERSION  "0.1"
-#define DRIVER_AUTHOR   "NVIDIA Corporation"
-#define DRIVER_DESC     "VFIO based driver for Mediated device"
-
 static int vfio_mdev_open(struct vfio_device *core_vdev)
 {
 	struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
@@ -151,7 +147,7 @@ static void vfio_mdev_remove(struct mdev_device *mdev)
 	kfree(vdev);
 }
 
-static struct mdev_driver vfio_mdev_driver = {
+struct mdev_driver vfio_mdev_driver = {
 	.driver = {
 		.name = "vfio_mdev",
 		.owner = THIS_MODULE,
@@ -160,21 +156,3 @@ static struct mdev_driver vfio_mdev_driver = {
 	.probe	= vfio_mdev_probe,
 	.remove	= vfio_mdev_remove,
 };
-
-static int __init vfio_mdev_init(void)
-{
-	return mdev_register_driver(&vfio_mdev_driver);
-}
-
-static void __exit vfio_mdev_exit(void)
-{
-	mdev_unregister_driver(&vfio_mdev_driver);
-}
-
-module_init(vfio_mdev_init)
-module_exit(vfio_mdev_exit)
-
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/samples/Kconfig b/samples/Kconfig
index b5a1a7aa7e23ab..b0503ef058d334 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -154,14 +154,14 @@ config SAMPLE_UHID
 
 config SAMPLE_VFIO_MDEV_MTTY
 	tristate "Build VFIO mtty example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	help
 	  Build a virtual tty sample driver for use as a VFIO
 	  mediated device
 
 config SAMPLE_VFIO_MDEV_MDPY
 	tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	help
 	  Build a virtual display sample driver for use as a VFIO
 	  mediated device.  It is a simple framebuffer and supports
@@ -178,7 +178,7 @@ config SAMPLE_VFIO_MDEV_MDPY_FB
 
 config SAMPLE_VFIO_MDEV_MBOCHS
 	tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	select DMA_SHARED_BUFFER
 	help
 	  Build a virtual display sample driver for use as a VFIO
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [Intel-gfx] [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
@ 2021-06-08  0:55   ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Heiko Carstens,
	intel-gfx, Jani Nikula, Jason Herne, Joonas Lahtinen, kvm,
	Kirti Wankhede, linux-doc, linux-s390, Halil Pasic, Rodrigo Vivi

For some reason the vfio_mdev shim mdev_driver has its own module and
kconfig. As the next patch requires access to it from mdev.ko merge the
two modules together and remove VFIO_MDEV_DEVICE.

A later patch deletes this driver entirely.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 Documentation/s390/vfio-ap.rst   |  1 -
 arch/s390/Kconfig                |  2 +-
 drivers/gpu/drm/i915/Kconfig     |  2 +-
 drivers/vfio/mdev/Kconfig        |  7 -------
 drivers/vfio/mdev/Makefile       |  3 +--
 drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
 drivers/vfio/mdev/mdev_private.h |  2 ++
 drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
 samples/Kconfig                  |  6 +++---
 9 files changed, 23 insertions(+), 40 deletions(-)

diff --git a/Documentation/s390/vfio-ap.rst b/Documentation/s390/vfio-ap.rst
index e15436599086b7..f57ae621f33e89 100644
--- a/Documentation/s390/vfio-ap.rst
+++ b/Documentation/s390/vfio-ap.rst
@@ -514,7 +514,6 @@ These are the steps:
    * S390_AP_IOMMU
    * VFIO
    * VFIO_MDEV
-   * VFIO_MDEV_DEVICE
    * KVM
 
    If using make menuconfig select the following to build the vfio_ap module::
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index b4c7c34069f81a..ea63fd22e1198a 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -768,7 +768,7 @@ config VFIO_CCW
 config VFIO_AP
 	def_tristate n
 	prompt "VFIO support for AP devices"
-	depends on S390_AP_IOMMU && VFIO_MDEV_DEVICE && KVM
+	depends on S390_AP_IOMMU && VFIO_MDEV && KVM
 	depends on ZCRYPT
 	help
 		This driver grants access to Adjunct Processor (AP) devices
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig
index 69f57ca9c68d73..9ab1cecd69b2a0 100644
--- a/drivers/gpu/drm/i915/Kconfig
+++ b/drivers/gpu/drm/i915/Kconfig
@@ -126,7 +126,7 @@ config DRM_I915_GVT_KVMGT
 	tristate "Enable KVM/VFIO support for Intel GVT-g"
 	depends on DRM_I915_GVT
 	depends on KVM
-	depends on VFIO_MDEV && VFIO_MDEV_DEVICE
+	depends on VFIO_MDEV
 	default n
 	help
 	  Choose this option if you want to enable KVMGT support for
diff --git a/drivers/vfio/mdev/Kconfig b/drivers/vfio/mdev/Kconfig
index 5da27f2100f9bd..763c877a1318bc 100644
--- a/drivers/vfio/mdev/Kconfig
+++ b/drivers/vfio/mdev/Kconfig
@@ -9,10 +9,3 @@ config VFIO_MDEV
 	  See Documentation/driver-api/vfio-mediated-device.rst for more details.
 
 	  If you don't know what do here, say N.
-
-config VFIO_MDEV_DEVICE
-	tristate "VFIO driver for Mediated devices"
-	depends on VFIO && VFIO_MDEV
-	default n
-	help
-	  VFIO based driver for Mediated devices.
diff --git a/drivers/vfio/mdev/Makefile b/drivers/vfio/mdev/Makefile
index 101516fdf3753e..ff9ecd80212503 100644
--- a/drivers/vfio/mdev/Makefile
+++ b/drivers/vfio/mdev/Makefile
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
-mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o
+mdev-y := mdev_core.o mdev_sysfs.o mdev_driver.o vfio_mdev.o
 
 obj-$(CONFIG_VFIO_MDEV) += mdev.o
-obj-$(CONFIG_VFIO_MDEV_DEVICE) += vfio_mdev.o
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 2a85d6fcb7ddd0..ff8c1a84516698 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -360,11 +360,24 @@ int mdev_device_remove(struct mdev_device *mdev)
 
 static int __init mdev_init(void)
 {
-	return mdev_bus_register();
+	int rc;
+
+	rc = mdev_bus_register();
+	if (rc)
+		return rc;
+	rc = mdev_register_driver(&vfio_mdev_driver);
+	if (rc)
+		goto err_bus;
+	return 0;
+err_bus:
+	mdev_bus_unregister();
+	return rc;
 }
 
 static void __exit mdev_exit(void)
 {
+	mdev_unregister_driver(&vfio_mdev_driver);
+
 	if (mdev_bus_compat_class)
 		class_compat_unregister(mdev_bus_compat_class);
 
@@ -378,4 +391,3 @@ MODULE_VERSION(DRIVER_VERSION);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR(DRIVER_AUTHOR);
 MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_SOFTDEP("post: vfio_mdev");
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 6999c89db7b162..afbad7b0a14a17 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -37,6 +37,8 @@ struct mdev_type {
 #define to_mdev_type(_kobj)		\
 	container_of(_kobj, struct mdev_type, kobj)
 
+extern struct mdev_driver vfio_mdev_driver;
+
 int  parent_create_sysfs_files(struct mdev_parent *parent);
 void parent_remove_sysfs_files(struct mdev_parent *parent);
 
diff --git a/drivers/vfio/mdev/vfio_mdev.c b/drivers/vfio/mdev/vfio_mdev.c
index 922729071c5a8e..d5b4eede47c1a5 100644
--- a/drivers/vfio/mdev/vfio_mdev.c
+++ b/drivers/vfio/mdev/vfio_mdev.c
@@ -17,10 +17,6 @@
 
 #include "mdev_private.h"
 
-#define DRIVER_VERSION  "0.1"
-#define DRIVER_AUTHOR   "NVIDIA Corporation"
-#define DRIVER_DESC     "VFIO based driver for Mediated device"
-
 static int vfio_mdev_open(struct vfio_device *core_vdev)
 {
 	struct mdev_device *mdev = to_mdev_device(core_vdev->dev);
@@ -151,7 +147,7 @@ static void vfio_mdev_remove(struct mdev_device *mdev)
 	kfree(vdev);
 }
 
-static struct mdev_driver vfio_mdev_driver = {
+struct mdev_driver vfio_mdev_driver = {
 	.driver = {
 		.name = "vfio_mdev",
 		.owner = THIS_MODULE,
@@ -160,21 +156,3 @@ static struct mdev_driver vfio_mdev_driver = {
 	.probe	= vfio_mdev_probe,
 	.remove	= vfio_mdev_remove,
 };
-
-static int __init vfio_mdev_init(void)
-{
-	return mdev_register_driver(&vfio_mdev_driver);
-}
-
-static void __exit vfio_mdev_exit(void)
-{
-	mdev_unregister_driver(&vfio_mdev_driver);
-}
-
-module_init(vfio_mdev_init)
-module_exit(vfio_mdev_exit)
-
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/samples/Kconfig b/samples/Kconfig
index b5a1a7aa7e23ab..b0503ef058d334 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -154,14 +154,14 @@ config SAMPLE_UHID
 
 config SAMPLE_VFIO_MDEV_MTTY
 	tristate "Build VFIO mtty example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	help
 	  Build a virtual tty sample driver for use as a VFIO
 	  mediated device
 
 config SAMPLE_VFIO_MDEV_MDPY
 	tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	help
 	  Build a virtual display sample driver for use as a VFIO
 	  mediated device.  It is a simple framebuffer and supports
@@ -178,7 +178,7 @@ config SAMPLE_VFIO_MDEV_MDPY_FB
 
 config SAMPLE_VFIO_MDEV_MBOCHS
 	tristate "Build VFIO mdpy example mediated device sample code -- loadable modules only"
-	depends on VFIO_MDEV_DEVICE && m
+	depends on VFIO_MDEV && m
 	select DMA_SHARED_BUFFER
 	help
 	  Build a virtual display sample driver for use as a VFIO
-- 
2.31.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 07/10] vfio/mdev: Allow the mdev_parent_ops to specify the device driver to bind
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (6 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  2021-06-08  6:21   ` Christoph Hellwig
  -1 siblings, 1 reply; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: Alex Williamson, Cornelia Huck, kvm, Kirti Wankhede

This allows a mdev driver to opt out of using vfio_mdev.c, instead the
driver will provide a 'struct mdev_driver' and register directly with the
driver core.

Much of mdev_parent_ops becomes unused in this mode:
- create()/remove() are done via the mdev_driver probe()/remove()
- mdev_attr_groups becomes mdev_driver driver.dev_groups
- Wrapper function callbacks are replaced with the same ones from
  struct vfio_device_ops

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 drivers/vfio/mdev/mdev_core.c   | 30 ++++++++++++++++++++++--------
 drivers/vfio/mdev/mdev_driver.c | 10 ++++++++++
 include/linux/mdev.h            |  2 ++
 3 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index ff8c1a84516698..e4581ec093a6a6 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -94,9 +94,11 @@ static void mdev_device_remove_common(struct mdev_device *mdev)
 	mdev_remove_sysfs_files(mdev);
 	device_del(&mdev->dev);
 	lockdep_assert_held(&parent->unreg_sem);
-	ret = parent->ops->remove(mdev);
-	if (ret)
-		dev_err(&mdev->dev, "Remove failed: err=%d\n", ret);
+	if (parent->ops->remove) {
+		ret = parent->ops->remove(mdev);
+		if (ret)
+			dev_err(&mdev->dev, "Remove failed: err=%d\n", ret);
+	}
 
 	/* Balances with device_initialize() */
 	put_device(&mdev->dev);
@@ -127,7 +129,9 @@ int mdev_register_device(struct device *dev, const struct mdev_parent_ops *ops)
 	char *envp[] = { env_string, NULL };
 
 	/* check for mandatory ops */
-	if (!ops || !ops->create || !ops->remove || !ops->supported_type_groups)
+	if (!ops || !ops->supported_type_groups)
+		return -EINVAL;
+	if (!ops->device_driver && (!ops->create || !ops->remove))
 		return -EINVAL;
 
 	dev = get_device(dev);
@@ -256,6 +260,7 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
 	int ret;
 	struct mdev_device *mdev, *tmp;
 	struct mdev_parent *parent = type->parent;
+	struct mdev_driver *drv = parent->ops->device_driver;
 
 	mutex_lock(&mdev_list_lock);
 
@@ -296,14 +301,22 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
 		goto out_put_device;
 	}
 
-	ret = parent->ops->create(mdev);
-	if (ret)
-		goto out_unlock;
+	if (parent->ops->create) {
+		ret = parent->ops->create(mdev);
+		if (ret)
+			goto out_unlock;
+	}
 
 	ret = device_add(&mdev->dev);
 	if (ret)
 		goto out_remove;
 
+	if (!drv)
+		drv = &vfio_mdev_driver;
+	ret = device_driver_attach(&drv->driver, &mdev->dev);
+	if (ret)
+		goto out_del;
+
 	ret = mdev_create_sysfs_files(mdev);
 	if (ret)
 		goto out_del;
@@ -317,7 +330,8 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
 out_del:
 	device_del(&mdev->dev);
 out_remove:
-	parent->ops->remove(mdev);
+	if (parent->ops->remove)
+		parent->ops->remove(mdev);
 out_unlock:
 	up_read(&parent->unreg_sem);
 out_put_device:
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 041699571b7e55..c368ec824e2b5c 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -71,10 +71,20 @@ static int mdev_remove(struct device *dev)
 	return 0;
 }
 
+static int mdev_match(struct device *dev, struct device_driver *drv)
+{
+	/*
+	 * No drivers automatically match. Drivers are only bound by explicit
+	 * device_driver_attach()
+	 */
+	return 0;
+}
+
 struct bus_type mdev_bus_type = {
 	.name		= "mdev",
 	.probe		= mdev_probe,
 	.remove		= mdev_remove,
+	.match		= mdev_match,
 };
 EXPORT_SYMBOL_GPL(mdev_bus_type);
 
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 1fb34ea394ad46..3a38598c260559 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -55,6 +55,7 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype);
  * register the device to mdev module.
  *
  * @owner:		The module owner.
+ * @device_driver:	Which device driver to probe() on newly created devices
  * @dev_attr_groups:	Attributes of the parent device.
  * @mdev_attr_groups:	Attributes of the mediated device.
  * @supported_type_groups: Attributes to define supported types. It is mandatory
@@ -103,6 +104,7 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype);
  **/
 struct mdev_parent_ops {
 	struct module   *owner;
+	struct mdev_driver *device_driver;
 	const struct attribute_group **dev_attr_groups;
 	const struct attribute_group **mdev_attr_groups;
 	struct attribute_group **supported_type_groups;
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 08/10] vfio/mtty: Convert to use vfio_register_group_dev()
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (7 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: kvm, Kirti Wankhede; +Cc: Christoph Hellwig

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of()

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 samples/vfio-mdev/mtty.c | 185 ++++++++++++++++++---------------------
 1 file changed, 83 insertions(+), 102 deletions(-)

diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index b9b24be4abdab7..d2a168420b775d 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -127,6 +127,7 @@ struct serial_port {
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	int irq_fd;
 	struct eventfd_ctx *intx_evtfd;
 	struct eventfd_ctx *msi_evtfd;
@@ -150,6 +151,8 @@ static const struct file_operations vd_fops = {
 	.owner          = THIS_MODULE,
 };
 
+static const struct vfio_device_ops mtty_dev_ops;
+
 /* function prototypes */
 
 static int mtty_trigger_interrupt(struct mdev_state *mdev_state);
@@ -631,22 +634,15 @@ static void mdev_read_base(struct mdev_state *mdev_state)
 	}
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, u8 *buf, size_t count,
+static ssize_t mdev_access(struct mdev_state *mdev_state, u8 *buf, size_t count,
 			   loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state;
 	unsigned int index;
 	loff_t offset;
 	int ret = 0;
 
-	if (!mdev || !buf)
-		return -EINVAL;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state) {
-		pr_err("%s mdev_state not found\n", __func__);
+	if (!buf)
 		return -EINVAL;
-	}
 
 	mutex_lock(&mdev_state->ops_lock);
 
@@ -708,15 +704,18 @@ static ssize_t mdev_access(struct mdev_device *mdev, u8 *buf, size_t count,
 	return ret;
 }
 
-static int mtty_create(struct mdev_device *mdev)
+static int mtty_probe(struct mdev_device *mdev)
 {
 	struct mdev_state *mdev_state;
 	int nr_ports = mdev_get_type_group_id(mdev) + 1;
+	int ret;
 
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
 
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mtty_dev_ops);
+
 	mdev_state->nr_ports = nr_ports;
 	mdev_state->irq_index = -1;
 	mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
@@ -731,7 +730,6 @@ static int mtty_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
 
 	mtty_create_config_space(mdev_state);
 
@@ -739,50 +737,40 @@ static int mtty_create(struct mdev_device *mdev)
 	list_add(&mdev_state->next, &mdev_devices_list);
 	mutex_unlock(&mdev_list_lock);
 
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret) {
+		kfree(mdev_state);
+		return ret;
+	}
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 }
 
-static int mtty_remove(struct mdev_device *mdev)
+static void mtty_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mds, *tmp_mds;
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	int ret = -EINVAL;
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	mutex_lock(&mdev_list_lock);
-	list_for_each_entry_safe(mds, tmp_mds, &mdev_devices_list, next) {
-		if (mdev_state == mds) {
-			list_del(&mdev_state->next);
-			mdev_set_drvdata(mdev, NULL);
-			kfree(mdev_state->vconfig);
-			kfree(mdev_state);
-			ret = 0;
-			break;
-		}
-	}
+	list_del(&mdev_state->next);
 	mutex_unlock(&mdev_list_lock);
 
-	return ret;
+	kfree(mdev_state->vconfig);
+	kfree(mdev_state);
 }
 
-static int mtty_reset(struct mdev_device *mdev)
+static int mtty_reset(struct mdev_state *mdev_stte)
 {
-	struct mdev_state *mdev_state;
-
-	if (!mdev)
-		return -EINVAL;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
-
 	pr_info("%s: called\n", __func__);
 
 	return 0;
 }
 
-static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mtty_read(struct vfio_device *vdev, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -792,7 +780,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret =  mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					   *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -804,7 +792,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -816,7 +804,7 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -839,9 +827,11 @@ static ssize_t mtty_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mtty_write(struct vfio_device *vdev, const char __user *buf,
 		   size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -854,7 +844,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -866,7 +856,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -878,7 +868,7 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (u8 *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (u8 *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -896,19 +886,11 @@ static ssize_t mtty_write(struct mdev_device *mdev, const char __user *buf,
 	return -EFAULT;
 }
 
-static int mtty_set_irqs(struct mdev_device *mdev, uint32_t flags,
+static int mtty_set_irqs(struct mdev_state *mdev_state, uint32_t flags,
 			 unsigned int index, unsigned int start,
 			 unsigned int count, void *data)
 {
 	int ret = 0;
-	struct mdev_state *mdev_state;
-
-	if (!mdev)
-		return -EINVAL;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
 
 	mutex_lock(&mdev_state->ops_lock);
 	switch (index) {
@@ -1024,21 +1006,13 @@ static int mtty_trigger_interrupt(struct mdev_state *mdev_state)
 	return ret;
 }
 
-static int mtty_get_region_info(struct mdev_device *mdev,
+static int mtty_get_region_info(struct mdev_state *mdev_state,
 			 struct vfio_region_info *region_info,
 			 u16 *cap_type_id, void **cap_type)
 {
 	unsigned int size = 0;
-	struct mdev_state *mdev_state;
 	u32 bar_index;
 
-	if (!mdev)
-		return -EINVAL;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
-
 	bar_index = region_info->index;
 	if (bar_index >= VFIO_PCI_NUM_REGIONS)
 		return -EINVAL;
@@ -1073,8 +1047,7 @@ static int mtty_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mtty_get_irq_info(struct mdev_device *mdev,
-			     struct vfio_irq_info *irq_info)
+static int mtty_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	switch (irq_info->index) {
 	case VFIO_PCI_INTX_IRQ_INDEX:
@@ -1098,8 +1071,7 @@ static int mtty_get_irq_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mtty_get_device_info(struct mdev_device *mdev,
-			 struct vfio_device_info *dev_info)
+static int mtty_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
@@ -1108,19 +1080,13 @@ static int mtty_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
+static long mtty_ioctl(struct vfio_device *vdev, unsigned int cmd,
 			unsigned long arg)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	int ret = 0;
 	unsigned long minsz;
-	struct mdev_state *mdev_state;
-
-	if (!mdev)
-		return -EINVAL;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -ENODEV;
 
 	switch (cmd) {
 	case VFIO_DEVICE_GET_INFO:
@@ -1135,7 +1101,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mtty_get_device_info(mdev, &info);
+		ret = mtty_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -1160,7 +1126,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mtty_get_region_info(mdev, &info, &cap_type_id,
+		ret = mtty_get_region_info(mdev_state, &info, &cap_type_id,
 					   &cap_type);
 		if (ret)
 			return ret;
@@ -1184,7 +1150,7 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= mdev_state->dev_info.num_irqs))
 			return -EINVAL;
 
-		ret = mtty_get_irq_info(mdev, &info);
+		ret = mtty_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -1218,25 +1184,25 @@ static long mtty_ioctl(struct mdev_device *mdev, unsigned int cmd,
 				return PTR_ERR(data);
 		}
 
-		ret = mtty_set_irqs(mdev, hdr.flags, hdr.index, hdr.start,
+		ret = mtty_set_irqs(mdev_state, hdr.flags, hdr.index, hdr.start,
 				    hdr.count, data);
 
 		kfree(ptr);
 		return ret;
 	}
 	case VFIO_DEVICE_RESET:
-		return mtty_reset(mdev);
+		return mtty_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mtty_open(struct mdev_device *mdev)
+static int mtty_open(struct vfio_device *vdev)
 {
 	pr_info("%s\n", __func__);
 	return 0;
 }
 
-static void mtty_close(struct mdev_device *mdev)
+static void mtty_close(struct vfio_device *mdev)
 {
 	pr_info("%s\n", __func__);
 }
@@ -1351,18 +1317,31 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mtty_dev_ops = {
+	.name = "vfio-mdev",
+	.open = mtty_open,
+	.release = mtty_close,
+	.read = mtty_read,
+	.write = mtty_write,
+	.ioctl = mtty_ioctl,
+};
+
+static struct mdev_driver mtty_driver = {
+	.driver = {
+		.name = "mtty",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mtty_probe,
+	.remove	= mtty_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner                  = THIS_MODULE,
+	.device_driver		= &mtty_driver,
 	.dev_attr_groups        = mtty_dev_groups,
-	.mdev_attr_groups       = mdev_dev_groups,
 	.supported_type_groups  = mdev_type_groups,
-	.create                 = mtty_create,
-	.remove			= mtty_remove,
-	.open                   = mtty_open,
-	.release                = mtty_close,
-	.read                   = mtty_read,
-	.write                  = mtty_write,
-	.ioctl		        = mtty_ioctl,
 };
 
 static void mtty_device_release(struct device *dev)
@@ -1393,12 +1372,16 @@ static int __init mtty_dev_init(void)
 
 	pr_info("major_number:%d\n", MAJOR(mtty_dev.vd_devt));
 
+	ret = mdev_register_driver(&mtty_driver);
+	if (ret)
+		goto err_cdev;
+
 	mtty_dev.vd_class = class_create(THIS_MODULE, MTTY_CLASS_NAME);
 
 	if (IS_ERR(mtty_dev.vd_class)) {
 		pr_err("Error: failed to register mtty_dev class\n");
 		ret = PTR_ERR(mtty_dev.vd_class);
-		goto failed1;
+		goto err_driver;
 	}
 
 	mtty_dev.dev.class = mtty_dev.vd_class;
@@ -1407,28 +1390,25 @@ static int __init mtty_dev_init(void)
 
 	ret = device_register(&mtty_dev.dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mtty_dev.dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	mutex_init(&mdev_list_lock);
 	INIT_LIST_HEAD(&mdev_devices_list);
+	return 0;
 
-	goto all_done;
-
-failed3:
-
+err_device:
 	device_unregister(&mtty_dev.dev);
-failed2:
+err_class:
 	class_destroy(mtty_dev.vd_class);
-
-failed1:
+err_driver:
+	mdev_unregister_driver(&mtty_driver);
+err_cdev:
 	cdev_del(&mtty_dev.vd_cdev);
 	unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK + 1);
-
-all_done:
 	return ret;
 }
 
@@ -1439,6 +1419,7 @@ static void __exit mtty_dev_exit(void)
 
 	device_unregister(&mtty_dev.dev);
 	idr_destroy(&mtty_dev.vd_idr);
+	mdev_unregister_driver(&mtty_driver);
 	cdev_del(&mtty_dev.vd_cdev);
 	unregister_chrdev_region(mtty_dev.vd_devt, MINORMASK + 1);
 	class_destroy(mtty_dev.vd_class);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 09/10] vfio/mdpy: Convert to use vfio_register_group_dev()
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (8 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: kvm, Kirti Wankhede; +Cc: Christoph Hellwig

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 samples/vfio-mdev/mdpy.c | 159 ++++++++++++++++++++++-----------------
 1 file changed, 88 insertions(+), 71 deletions(-)

diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index e889c1cf8fd1cd..7e9c9df0f05bac 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -85,9 +85,11 @@ static struct class	*mdpy_class;
 static struct cdev	mdpy_cdev;
 static struct device	mdpy_dev;
 static u32		mdpy_count;
+static const struct vfio_device_ops mdpy_dev_ops;
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	u8 *vconfig;
 	u32 bar_mask;
 	struct mutex ops_lock;
@@ -162,11 +164,9 @@ static void handle_pci_cfg_write(struct mdev_state *mdev_state, u16 offset,
 	}
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
-			   loff_t pos, bool is_write)
+static ssize_t mdev_access(struct mdev_state *mdev_state, char *buf,
+			   size_t count, loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	int ret = 0;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -187,8 +187,9 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 			memcpy(buf, mdev_state->memblk, count);
 
 	} else {
-		dev_info(dev, "%s: %s @0x%llx (unhandled)\n",
-			 __func__, is_write ? "WR" : "RD", pos);
+		dev_info(mdev_state->vdev.dev,
+			 "%s: %s @0x%llx (unhandled)\n", __func__,
+			 is_write ? "WR" : "RD", pos);
 		ret = -1;
 		goto accessfailed;
 	}
@@ -202,9 +203,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 	return ret;
 }
 
-static int mdpy_reset(struct mdev_device *mdev)
+static int mdpy_reset(struct mdev_state *mdev_state)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	u32 stride, i;
 
 	/* initialize with gray gradient */
@@ -216,13 +216,14 @@ static int mdpy_reset(struct mdev_device *mdev)
 	return 0;
 }
 
-static int mdpy_create(struct mdev_device *mdev)
+static int mdpy_probe(struct mdev_device *mdev)
 {
 	const struct mdpy_type *type =
 		&mdpy_types[mdev_get_type_group_id(mdev)];
 	struct device *dev = mdev_dev(mdev);
 	struct mdev_state *mdev_state;
 	u32 fbsize;
+	int ret;
 
 	if (mdpy_count >= max_devices)
 		return -ENOMEM;
@@ -230,6 +231,7 @@ static int mdpy_create(struct mdev_device *mdev)
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mdpy_dev_ops);
 
 	mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (mdev_state->vconfig == NULL) {
@@ -250,36 +252,41 @@ static int mdpy_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
-
 	mdev_state->type    = type;
 	mdev_state->memsize = fbsize;
 	mdpy_create_config_space(mdev_state);
-	mdpy_reset(mdev);
+	mdpy_reset(mdev_state);
 
 	mdpy_count++;
+
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret) {
+		kfree(mdev_state);
+		return ret;
+	}
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 }
 
-static int mdpy_remove(struct mdev_device *mdev)
+static void mdpy_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
-	dev_info(dev, "%s\n", __func__);
+	dev_info(&mdev->dev, "%s\n", __func__);
 
-	mdev_set_drvdata(mdev, NULL);
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	vfree(mdev_state->memblk);
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
 
 	mdpy_count--;
-	return 0;
 }
 
-static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mdpy_read(struct vfio_device *vdev, char __user *buf,
 			 size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -289,8 +296,8 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (char *)&val, sizeof(val),
-					   *ppos, false);
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
+					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
 
@@ -301,7 +308,7 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -313,7 +320,7 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -336,9 +343,11 @@ static ssize_t mdpy_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mdpy_write(struct vfio_device *vdev, const char __user *buf,
 			  size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -351,7 +360,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -363,7 +372,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -375,7 +384,7 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -393,9 +402,10 @@ static ssize_t mdpy_write(struct mdev_device *mdev, const char __user *buf,
 	return -EFAULT;
 }
 
-static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+static int mdpy_mmap(struct vfio_device *vdev, struct vm_area_struct *vma)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	if (vma->vm_pgoff != MDPY_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
 		return -EINVAL;
@@ -409,16 +419,10 @@ static int mdpy_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 	return remap_vmalloc_range(vma, mdev_state->memblk, 0);
 }
 
-static int mdpy_get_region_info(struct mdev_device *mdev,
+static int mdpy_get_region_info(struct mdev_state *mdev_state,
 				struct vfio_region_info *region_info,
 				u16 *cap_type_id, void **cap_type)
 {
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
-
 	if (region_info->index >= VFIO_PCI_NUM_REGIONS &&
 	    region_info->index != MDPY_DISPLAY_REGION)
 		return -EINVAL;
@@ -447,15 +451,13 @@ static int mdpy_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mdpy_get_irq_info(struct mdev_device *mdev,
-			     struct vfio_irq_info *irq_info)
+static int mdpy_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	irq_info->count = 0;
 	return 0;
 }
 
-static int mdpy_get_device_info(struct mdev_device *mdev,
-				struct vfio_device_info *dev_info)
+static int mdpy_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = VFIO_PCI_NUM_REGIONS;
@@ -463,11 +465,9 @@ static int mdpy_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mdpy_query_gfx_plane(struct mdev_device *mdev,
+static int mdpy_query_gfx_plane(struct mdev_state *mdev_state,
 				struct vfio_device_gfx_plane_info *plane)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-
 	if (plane->flags & VFIO_GFX_PLANE_TYPE_PROBE) {
 		if (plane->flags == (VFIO_GFX_PLANE_TYPE_PROBE |
 				     VFIO_GFX_PLANE_TYPE_REGION))
@@ -496,14 +496,13 @@ static int mdpy_query_gfx_plane(struct mdev_device *mdev,
 	return 0;
 }
 
-static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
+static long mdpy_ioctl(struct vfio_device *vdev, unsigned int cmd,
 		       unsigned long arg)
 {
 	int ret = 0;
 	unsigned long minsz;
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	switch (cmd) {
 	case VFIO_DEVICE_GET_INFO:
@@ -518,7 +517,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mdpy_get_device_info(mdev, &info);
+		ret = mdpy_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -543,7 +542,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mdpy_get_region_info(mdev, &info, &cap_type_id,
+		ret = mdpy_get_region_info(mdev_state, &info, &cap_type_id,
 					   &cap_type);
 		if (ret)
 			return ret;
@@ -567,7 +566,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= mdev_state->dev_info.num_irqs))
 			return -EINVAL;
 
-		ret = mdpy_get_irq_info(mdev, &info);
+		ret = mdpy_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -590,7 +589,7 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (plane.argsz < minsz)
 			return -EINVAL;
 
-		ret = mdpy_query_gfx_plane(mdev, &plane);
+		ret = mdpy_query_gfx_plane(mdev_state, &plane);
 		if (ret)
 			return ret;
 
@@ -604,12 +603,12 @@ static long mdpy_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		return -EINVAL;
 
 	case VFIO_DEVICE_RESET:
-		return mdpy_reset(mdev);
+		return mdpy_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mdpy_open(struct mdev_device *mdev)
+static int mdpy_open(struct vfio_device *vdev)
 {
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
@@ -617,7 +616,7 @@ static int mdpy_open(struct mdev_device *mdev)
 	return 0;
 }
 
-static void mdpy_close(struct mdev_device *mdev)
+static void mdpy_close(struct vfio_device *vdev)
 {
 	module_put(THIS_MODULE);
 }
@@ -626,8 +625,7 @@ static ssize_t
 resolution_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%dx%d\n",
 		       mdev_state->type->width,
@@ -716,18 +714,30 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mdpy_dev_ops = {
+	.open = mdpy_open,
+	.release = mdpy_close,
+	.read = mdpy_read,
+	.write = mdpy_write,
+	.ioctl = mdpy_ioctl,
+	.mmap = mdpy_mmap,
+};
+
+static struct mdev_driver mdpy_driver = {
+	.driver = {
+		.name = "mdpy",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mdpy_probe,
+	.remove	= mdpy_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
+	.device_driver          = &mdpy_driver,
 	.supported_type_groups	= mdev_type_groups,
-	.create			= mdpy_create,
-	.remove			= mdpy_remove,
-	.open			= mdpy_open,
-	.release		= mdpy_close,
-	.read			= mdpy_read,
-	.write			= mdpy_write,
-	.ioctl			= mdpy_ioctl,
-	.mmap			= mdpy_mmap,
 };
 
 static const struct file_operations vd_fops = {
@@ -752,11 +762,15 @@ static int __init mdpy_dev_init(void)
 	cdev_add(&mdpy_cdev, mdpy_devt, MINORMASK + 1);
 	pr_info("%s: major %d\n", __func__, MAJOR(mdpy_devt));
 
+	ret = mdev_register_driver(&mdpy_driver);
+	if (ret)
+		goto err_cdev;
+
 	mdpy_class = class_create(THIS_MODULE, MDPY_CLASS_NAME);
 	if (IS_ERR(mdpy_class)) {
 		pr_err("Error: failed to register mdpy_dev class\n");
 		ret = PTR_ERR(mdpy_class);
-		goto failed1;
+		goto err_driver;
 	}
 	mdpy_dev.class = mdpy_class;
 	mdpy_dev.release = mdpy_device_release;
@@ -764,19 +778,21 @@ static int __init mdpy_dev_init(void)
 
 	ret = device_register(&mdpy_dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mdpy_dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	return 0;
 
-failed3:
+err_device:
 	device_unregister(&mdpy_dev);
-failed2:
+err_class:
 	class_destroy(mdpy_class);
-failed1:
+err_driver:
+	mdev_unregister_driver(&mdpy_driver);
+err_cdev:
 	cdev_del(&mdpy_cdev);
 	unregister_chrdev_region(mdpy_devt, MINORMASK + 1);
 	return ret;
@@ -788,6 +804,7 @@ static void __exit mdpy_dev_exit(void)
 	mdev_unregister_device(&mdpy_dev);
 
 	device_unregister(&mdpy_dev);
+	mdev_unregister_driver(&mdpy_driver);
 	cdev_del(&mdpy_cdev);
 	unregister_chrdev_region(mdpy_devt, MINORMASK + 1);
 	class_destroy(mdpy_class);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
                   ` (9 preceding siblings ...)
  (?)
@ 2021-06-08  0:55 ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08  0:55 UTC (permalink / raw)
  To: kvm, Kirti Wankhede; +Cc: Christoph Hellwig

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
---
 samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 72 deletions(-)

diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 881ef9a7296f23..6c0f229db36a1a 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -130,6 +130,7 @@ static struct class	*mbochs_class;
 static struct cdev	mbochs_cdev;
 static struct device	mbochs_dev;
 static int		mbochs_used_mbytes;
+static const struct vfio_device_ops mbochs_dev_ops;
 
 struct vfio_region_info_ext {
 	struct vfio_region_info          base;
@@ -160,6 +161,7 @@ struct mbochs_dmabuf {
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	u8 *vconfig;
 	u64 bar_mask[3];
 	u32 memory_bar_mask;
@@ -425,11 +427,9 @@ static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
 		memcpy(buf, mdev_state->edid_blob + offset, count);
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
-			   loff_t pos, bool is_write)
+static ssize_t mdev_access(struct mdev_state *mdev_state, char *buf,
+			   size_t count, loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct page *pg;
 	loff_t poff;
 	char *map;
@@ -478,7 +478,7 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 		put_page(pg);
 
 	} else {
-		dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
+		dev_dbg(mdev_state->vdev.dev, "%s: %s @0x%llx (unhandled)\n",
 			__func__, is_write ? "WR" : "RD", pos);
 		ret = -1;
 		goto accessfailed;
@@ -493,9 +493,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 	return ret;
 }
 
-static int mbochs_reset(struct mdev_device *mdev)
+static int mbochs_reset(struct mdev_state *mdev_state)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	u32 size64k = mdev_state->memsize / (64 * 1024);
 	int i;
 
@@ -506,12 +505,13 @@ static int mbochs_reset(struct mdev_device *mdev)
 	return 0;
 }
 
-static int mbochs_create(struct mdev_device *mdev)
+static int mbochs_probe(struct mdev_device *mdev)
 {
 	const struct mbochs_type *type =
 		&mbochs_types[mdev_get_type_group_id(mdev)];
 	struct device *dev = mdev_dev(mdev);
 	struct mdev_state *mdev_state;
+	int ret = -ENOMEM;
 
 	if (type->mbytes + mbochs_used_mbytes > max_mbytes)
 		return -ENOMEM;
@@ -519,6 +519,7 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);
 
 	mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (mdev_state->vconfig == NULL)
@@ -537,7 +538,6 @@ static int mbochs_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
 	INIT_LIST_HEAD(&mdev_state->dmabufs);
 	mdev_state->next_id = 1;
 
@@ -547,32 +547,38 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
 	mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
 	mbochs_create_config_space(mdev_state);
-	mbochs_reset(mdev);
+	mbochs_reset(mdev_state);
 
 	mbochs_used_mbytes += type->mbytes;
+
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret)
+		goto err_mem;
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 
 err_mem:
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return -ENOMEM;
+	return ret;
 }
 
-static int mbochs_remove(struct mdev_device *mdev)
+static void mbochs_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
 	mbochs_used_mbytes -= mdev_state->type->mbytes;
-	mdev_set_drvdata(mdev, NULL);
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	kfree(mdev_state->pages);
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return 0;
 }
 
-static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mbochs_read(struct vfio_device *vdev, char __user *buf,
 			   size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -582,7 +588,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (char *)&val, sizeof(val),
+			ret =  mdev_access(mdev_state, (char *)&val, sizeof(val),
 					   *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -594,7 +600,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -606,7 +612,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -629,9 +635,11 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mbochs_write(struct vfio_device *vdev, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -644,7 +652,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -656,7 +664,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -668,7 +676,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -754,9 +762,10 @@ static const struct vm_operations_struct mbochs_region_vm_ops = {
 	.fault = mbochs_region_vm_fault,
 };
 
-static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+static int mbochs_mmap(struct vfio_device *vdev, struct vm_area_struct *vma)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
 		return -EINVAL;
@@ -963,7 +972,7 @@ mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
 static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 {
 	struct mdev_state *mdev_state = dmabuf->mdev_state;
-	struct device *dev = mdev_dev(mdev_state->mdev);
+	struct device *dev = mdev_state->vdev.dev;
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct dma_buf *buf;
 
@@ -991,15 +1000,10 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 	return 0;
 }
 
-static int mbochs_get_region_info(struct mdev_device *mdev,
+static int mbochs_get_region_info(struct mdev_state *mdev_state,
 				  struct vfio_region_info_ext *ext)
 {
 	struct vfio_region_info *region_info = &ext->base;
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
 
 	if (region_info->index >= MBOCHS_NUM_REGIONS)
 		return -EINVAL;
@@ -1047,15 +1051,13 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_get_irq_info(struct mdev_device *mdev,
-			       struct vfio_irq_info *irq_info)
+static int mbochs_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	irq_info->count = 0;
 	return 0;
 }
 
-static int mbochs_get_device_info(struct mdev_device *mdev,
-				  struct vfio_device_info *dev_info)
+static int mbochs_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = MBOCHS_NUM_REGIONS;
@@ -1063,11 +1065,9 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_query_gfx_plane(struct mdev_device *mdev,
+static int mbochs_query_gfx_plane(struct mdev_state *mdev_state,
 				  struct vfio_device_gfx_plane_info *plane)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct mbochs_dmabuf *dmabuf;
 	struct mbochs_mode mode;
 	int ret;
@@ -1121,18 +1121,16 @@ static int mbochs_query_gfx_plane(struct mdev_device *mdev,
 done:
 	if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
 	    mdev_state->active_id != plane->dmabuf_id) {
-		dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
-			mdev_state->active_id, plane->dmabuf_id);
+		dev_dbg(mdev_state->vdev.dev, "%s: primary: %d => %d\n",
+			__func__, mdev_state->active_id, plane->dmabuf_id);
 		mdev_state->active_id = plane->dmabuf_id;
 	}
 	mutex_unlock(&mdev_state->ops_lock);
 	return 0;
 }
 
-static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
-				 u32 id)
+static int mbochs_get_gfx_dmabuf(struct mdev_state *mdev_state, u32 id)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	struct mbochs_dmabuf *dmabuf;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1154,9 +1152,11 @@ static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
 	return dma_buf_fd(dmabuf->buf, 0);
 }
 
-static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
-			unsigned long arg)
+static long mbochs_ioctl(struct vfio_device *vdev, unsigned int cmd,
+			 unsigned long arg)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	int ret = 0;
 	unsigned long minsz, outsz;
 
@@ -1173,7 +1173,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_get_device_info(mdev, &info);
+		ret = mbochs_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -1197,7 +1197,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (outsz > sizeof(info))
 			return -EINVAL;
 
-		ret = mbochs_get_region_info(mdev, &info);
+		ret = mbochs_get_region_info(mdev_state, &info);
 		if (ret)
 			return ret;
 
@@ -1220,7 +1220,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= VFIO_PCI_NUM_IRQS))
 			return -EINVAL;
 
-		ret = mbochs_get_irq_info(mdev, &info);
+		ret = mbochs_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -1243,7 +1243,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (plane.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_query_gfx_plane(mdev, &plane);
+		ret = mbochs_query_gfx_plane(mdev_state, &plane);
 		if (ret)
 			return ret;
 
@@ -1260,19 +1260,19 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (get_user(dmabuf_id, (__u32 __user *)arg))
 			return -EFAULT;
 
-		return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
+		return mbochs_get_gfx_dmabuf(mdev_state, dmabuf_id);
 	}
 
 	case VFIO_DEVICE_SET_IRQS:
 		return -EINVAL;
 
 	case VFIO_DEVICE_RESET:
-		return mbochs_reset(mdev);
+		return mbochs_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mbochs_open(struct mdev_device *mdev)
+static int mbochs_open(struct vfio_device *vdev)
 {
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
@@ -1280,9 +1280,10 @@ static int mbochs_open(struct mdev_device *mdev)
 	return 0;
 }
 
-static void mbochs_close(struct mdev_device *mdev)
+static void mbochs_close(struct vfio_device *vdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	struct mbochs_dmabuf *dmabuf, *tmp;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1306,8 +1307,7 @@ static ssize_t
 memory_show(struct device *dev, struct device_attribute *attr,
 	    char *buf)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
 }
@@ -1398,18 +1398,30 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mbochs_dev_ops = {
+	.open = mbochs_open,
+	.release = mbochs_close,
+	.read = mbochs_read,
+	.write = mbochs_write,
+	.ioctl = mbochs_ioctl,
+	.mmap = mbochs_mmap,
+};
+
+static struct mdev_driver mbochs_driver = {
+	.driver = {
+		.name = "mbochs",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mbochs_probe,
+	.remove	= mbochs_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
+	.device_driver		= &mbochs_driver,
 	.supported_type_groups	= mdev_type_groups,
-	.create			= mbochs_create,
-	.remove			= mbochs_remove,
-	.open			= mbochs_open,
-	.release		= mbochs_close,
-	.read			= mbochs_read,
-	.write			= mbochs_write,
-	.ioctl			= mbochs_ioctl,
-	.mmap			= mbochs_mmap,
 };
 
 static const struct file_operations vd_fops = {
@@ -1434,11 +1446,15 @@ static int __init mbochs_dev_init(void)
 	cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK + 1);
 	pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
 
+	ret = mdev_register_driver(&mbochs_driver);
+	if (ret)
+		goto err_cdev;
+
 	mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
 	if (IS_ERR(mbochs_class)) {
 		pr_err("Error: failed to register mbochs_dev class\n");
 		ret = PTR_ERR(mbochs_class);
-		goto failed1;
+		goto err_driver;
 	}
 	mbochs_dev.class = mbochs_class;
 	mbochs_dev.release = mbochs_device_release;
@@ -1446,19 +1462,21 @@ static int __init mbochs_dev_init(void)
 
 	ret = device_register(&mbochs_dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mbochs_dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	return 0;
 
-failed3:
+err_device:
 	device_unregister(&mbochs_dev);
-failed2:
+err_class:
 	class_destroy(mbochs_class);
-failed1:
+err_driver:
+	mdev_unregister_driver(&mbochs_driver);
+err_cdev:
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	return ret;
@@ -1470,6 +1488,7 @@ static void __exit mbochs_dev_exit(void)
 	mdev_unregister_device(&mbochs_dev);
 
 	device_unregister(&mbochs_dev);
+	mdev_unregister_driver(&mbochs_driver);
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	class_destroy(mbochs_class);
-- 
2.31.1


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  0:55 ` [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used Jason Gunthorpe
@ 2021-06-08  5:51   ` Christoph Hellwig
  2021-06-08  6:44   ` Greg Kroah-Hartman
  2021-06-08  7:35   ` Greg Kroah-Hartman
  2 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  5:51 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 02/10] driver core: Pull required checks into driver_probe_device()
  2021-06-08  0:55 ` [PATCH 02/10] driver core: Pull required checks into driver_probe_device() Jason Gunthorpe
@ 2021-06-08  5:59   ` Christoph Hellwig
  2021-06-08 12:21     ` Jason Gunthorpe
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  5:59 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

This looks good as-is, but a suggestions for incremental improvements
below:

> @@ -1032,10 +1035,10 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
>  	__device_driver_lock(dev, dev->parent);
>  
>  	/*
> -	 * If device has been removed or someone has already successfully
> -	 * bound a driver before us just skip the driver probe call.
> +	 * If device someone has already successfully bound a driver before us
> +	 * just skip the driver probe call.
>  	 */
> -	if (!dev->p->dead && !dev->driver)
> +	if (!dev->driver)
>  		ret = driver_probe_device(drv, dev);
>  
>  	__device_driver_unlock(dev, dev->parent);

It is kinda silly to keep the ->driver check here given that one caller
completely ignores the return value, and the other turns a 0 return into
-ENODEV anyway.  So I think this check can go away, turning
device_driver_attach into a trivial wrapper for driver_probe_device
that adds locking, which might be useful to reflect in the naming.

> @@ -1047,19 +1050,11 @@ static void __driver_attach_async_helper(void *_dev, async_cookie_t cookie)
>  {
>  	struct device *dev = _dev;
>  	struct device_driver *drv;
> -	int ret = 0;
> +	int ret;
>  
>  	__device_driver_lock(dev, dev->parent);
> -
>  	drv = dev->p->async_driver;
> -
> -	/*
> -	 * If device has been removed or someone has already successfully
> -	 * bound a driver before us just skip the driver probe call.
> -	 */
> -	if (!dev->p->dead && !dev->driver)
> -		ret = driver_probe_device(drv, dev);
> -
> +	ret = driver_probe_device(drv, dev);
>  	__device_driver_unlock(dev, dev->parent);

And that helper could be used here as well.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08  0:55 ` [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind Jason Gunthorpe
@ 2021-06-08  6:07   ` Christoph Hellwig
  2021-06-08 23:53     ` Jason Gunthorpe
  2021-06-08  6:47   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:07 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

> index 36d0c654ea6124..03591f82251302 100644
> --- a/drivers/base/bus.c
> +++ b/drivers/base/bus.c
> @@ -212,13 +212,9 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
>  	dev = bus_find_device_by_name(bus, NULL, buf);
>  	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
>  		err = device_driver_attach(drv, dev);
> -
> -		if (err > 0) {
> +		if (!err) {
>  			/* success */
>  			err = count;
> -		} else if (err == 0) {
> -			/* driver didn't accept device */
> -			err = -ENODEV;
>  		}
>  	}

I think we can also drop the dev->driver == NULL check above given
that device_driver_attach covers it now.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
  2021-06-08  0:55 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during " Jason Gunthorpe
@ 2021-06-08  6:14   ` Christoph Hellwig
  2021-06-08  7:37   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:14 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:46PM -0300, Jason Gunthorpe wrote:
>  int device_driver_attach(struct device_driver *drv, struct device *dev)
>  {
> @@ -1061,6 +1073,8 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
>  
>  	__device_driver_unlock(dev, dev->parent);
>  
> +	if (ret == -EPROBE_DEFER)
> +		return -EAGAIN;
>  	return ret;

I'd move this check into bind_store() instead.  That would also play
well with my earlier suggestion for a simple locking wrapper around
driver_probe_device which would get passed the flags argument as well.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 05/10] driver core: Export device_driver_attach()
  2021-06-08  0:55 ` [PATCH 05/10] driver core: Export device_driver_attach() Jason Gunthorpe
@ 2021-06-08  6:19   ` Christoph Hellwig
  2021-06-08 12:33     ` Jason Gunthorpe
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:19 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:47PM -0300, Jason Gunthorpe wrote:
> This is intended as a replacement API for device_bind_driver(). It has at
> least the following benefits:
> 
> - Internal locking. Few of the users of device_bind_driver() follow the
>   locking rules
> 
> - Calls device driver probe() internally. Notably this means that devm
>   support for probe works correctly as probe() error will call
>   devres_release_all()
> 
> - struct device_driver -> dev_groups is supported
> 
> - Simplified calling convention, no need to manually call probe().

Btw, it would be nice to convert at least one existing user of
device_bind_driver to show this.  Also maybe Cc all maintainers of
subsystems using device_bind_driver so that they get a headsup and
maybe quickly move over?

> @@ -1077,6 +1079,7 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
>  		return -EAGAIN;
>  	return ret;
>  }
> +EXPORT_SYMBOL_GPL(device_driver_attach);

Ok, this means my earlier suggestions of a locked driver_probe_device
helper needs a different name as we really don't want to expose flags
and always return -EAGAIN here.  So maybe rename driver_probe_device
to __driver_probe_device, have a driver_probe_device around it that
does the locking and keep device_driver_attach for the newly exported
API.

The kerneldoc for device_driver_attach is pretty sparse, it might want a
little brushup as well.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  2021-06-08  0:55   ` [Intel-gfx] " Jason Gunthorpe
@ 2021-06-08  6:20     ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:20 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Heiko Carstens,
	intel-gfx, Jani Nikula, Jason Herne, Joonas Lahtinen, kvm,
	Kirti Wankhede, linux-doc, linux-s390, Halil Pasic, Rodrigo Vivi

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
@ 2021-06-08  6:20     ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:20 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: Tony Krowiak, Jason Herne, kvm, Vasily Gorbik, Jonathan Corbet,
	David Airlie, linux-s390, Heiko Carstens, Cornelia Huck,
	linux-doc, Kirti Wankhede, dri-devel, Halil Pasic,
	Christian Borntraeger, intel-gfx

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 07/10] vfio/mdev: Allow the mdev_parent_ops to specify the device driver to bind
  2021-06-08  0:55 ` [PATCH 07/10] vfio/mdev: Allow the mdev_parent_ops to specify the device driver to bind Jason Gunthorpe
@ 2021-06-08  6:21   ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:21 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: Alex Williamson, Cornelia Huck, kvm, Kirti Wankhede

Looks good,

Reviewed-by: Christoph Hellwig <hch@lst.de>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
@ 2021-06-08  6:22   ` Christoph Hellwig
  -1 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:22 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc, linux-s390,
	Halil Pasic, Rafael J. Wysocki, Rodrigo Vivi, Christoph Hellwig

Btw, you list of CCs is a mess as alsmost no one is CCed on the whole
list can can thus properly review it.

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-08  6:22   ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-08  6:22 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: kvm, linux-doc, David Airlie, dri-devel, Kirti Wankhede,
	Christoph Hellwig, linux-s390, Jonathan Corbet,
	Rafael J. Wysocki, Halil Pasic, Christian Borntraeger, intel-gfx,
	Jason Herne, Vasily Gorbik, Heiko Carstens, Tony Krowiak,
	Greg Kroah-Hartman, Cornelia Huck

Btw, you list of CCs is a mess as alsmost no one is CCed on the whole
list can can thus properly review it.
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  0:55 ` [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used Jason Gunthorpe
  2021-06-08  5:51   ` Christoph Hellwig
@ 2021-06-08  6:44   ` Greg Kroah-Hartman
  2021-06-08 12:16     ` Jason Gunthorpe
  2021-06-08  7:35   ` Greg Kroah-Hartman
  2 siblings, 1 reply; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08  6:44 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:43PM -0300, Jason Gunthorpe wrote:
> Once a driver has been matched and probe() returns with -EPROBE_DEFER the
> device is added to a deferred list and will be retried later.
> 
> At this point __device_attach_driver() should stop trying other drivers as
> we have "matched" this driver and already scheduled another probe to
> happen later.
> 
> Return the -EPROBE_DEFER from really_probe() instead of squashing it to
> zero. This is similar to the code at the top of the function which
> directly returns -EPROBE_DEFER.
> 
> It is not really a bug as, AFAIK, we don't actually have cases where
> multiple drivers can bind.

We _do_ have devices that multiple drivers can bind to.  Are you sure
you did not just break them?

Why are you needing to change this?  What is it helping?  What problem
is this solving?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08  0:55 ` [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind Jason Gunthorpe
  2021-06-08  6:07   ` Christoph Hellwig
@ 2021-06-08  6:47   ` Greg Kroah-Hartman
  2021-06-08 12:30     ` Jason Gunthorpe
  1 sibling, 1 reply; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08  6:47 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:45PM -0300, Jason Gunthorpe wrote:
> Currently really_probe() returns 1 on success and 0 if the probe() call
> fails. This return code arrangement is designed to be useful for
> __device_attach_driver() which is walking the device list and trying every
> driver. 0 means to keep trying.
> 
> However, it is not useful for the other places that call through to
> really_probe() that do actually want to see the probe() return code.
> 
> For instance bind_store() would be better to return the actual error code
> from the driver's probe method, not discarding it and returning -ENODEV.

Why does that matter?  Why does it need to know this?

> Reorganize things so that really_probe() always returns an error code on
> failure and 0 on success. Move the special code for device list walking
> into the walker callback __device_attach_driver() and trigger it based on
> an output flag from really_probe(). Update the rest of the API surface to
> return a normal -ERR or 0 on success.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  drivers/base/bus.c |  6 +----
>  drivers/base/dd.c  | 61 ++++++++++++++++++++++++++++++----------------
>  2 files changed, 41 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/base/bus.c b/drivers/base/bus.c
> index 36d0c654ea6124..03591f82251302 100644
> --- a/drivers/base/bus.c
> +++ b/drivers/base/bus.c
> @@ -212,13 +212,9 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
>  	dev = bus_find_device_by_name(bus, NULL, buf);
>  	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
>  		err = device_driver_attach(drv, dev);
> -
> -		if (err > 0) {
> +		if (!err) {
>  			/* success */
>  			err = count;
> -		} else if (err == 0) {
> -			/* driver didn't accept device */
> -			err = -ENODEV;
>  		}
>  	}
>  	put_device(dev);
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index c1a92cff159873..7fb58e6219b255 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -513,7 +513,13 @@ static ssize_t state_synced_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(state_synced);
>  
> -static int really_probe(struct device *dev, struct device_driver *drv)
> +enum {
> +	/* Set on output if the -ERR has come from a probe() function */
> +	PROBEF_DRV_FAILED = 1 << 0,
> +};
> +
> +static int really_probe(struct device *dev, struct device_driver *drv,
> +			unsigned int *flags)

Ugh, no, please no functions with random "flags" in them, that way lies
madness and unmaintainable code for decades to come.

Especially as I have no idea what this is trying to solve here at all...

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  0:55 ` [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used Jason Gunthorpe
  2021-06-08  5:51   ` Christoph Hellwig
  2021-06-08  6:44   ` Greg Kroah-Hartman
@ 2021-06-08  7:35   ` Greg Kroah-Hartman
  2021-06-08 12:17     ` Jason Gunthorpe
  2 siblings, 1 reply; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08  7:35 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:43PM -0300, Jason Gunthorpe wrote:
> Once a driver has been matched and probe() returns with -EPROBE_DEFER the
> device is added to a deferred list and will be retried later.
> 
> At this point __device_attach_driver() should stop trying other drivers as
> we have "matched" this driver and already scheduled another probe to
> happen later.
> 
> Return the -EPROBE_DEFER from really_probe() instead of squashing it to
> zero. This is similar to the code at the top of the function which
> directly returns -EPROBE_DEFER.
> 
> It is not really a bug as, AFAIK, we don't actually have cases where
> multiple drivers can bind.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  drivers/base/dd.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index ecd7cf848daff7..9d79a139290271 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -656,7 +656,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
>  		/* Driver requested deferred probing */
>  		dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
>  		driver_deferred_probe_add_trigger(dev, local_trigger_count);
> -		break;
> +		goto done;
>  	case -ENODEV:
>  	case -ENXIO:
>  		pr_debug("%s: probe of %s rejects match %d\n",
> -- 
> 2.31.1
> 

Why is lkml not cc:ed on driver core changes like get_maintainer.pl will
say?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
  2021-06-08  0:55 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during " Jason Gunthorpe
  2021-06-08  6:14   ` Christoph Hellwig
@ 2021-06-08  7:37   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08  7:37 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Mon, Jun 07, 2021 at 09:55:46PM -0300, Jason Gunthorpe wrote:
> EPROBE_DEFER is an internal kernel error code and it should not be leaked
> to userspace via the bind_store() sysfs. Userspace doesn't have this
> constant and cannot understand it.
> 
> Further, it doesn't really make sense to have userspace trigger a deferred
> probe via bind_store(), which could eventually succeed, while
> simultaneously returning an error back.
> 
> Resolve this by preventing EPROBE_DEFER from triggering a deferred probe
> and simply relay the whole situation back to userspace as a normal -EAGAIN
> code.
> 
> Put this in the device_driver_attach() so the EPROBE_DEFER remains
> contained to dd.c and the probe() implementations.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  drivers/base/dd.c | 39 ++++++++++++++++++++++++++++-----------
>  1 file changed, 28 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> index 7fb58e6219b255..edda7aad43a3f7 100644
> --- a/drivers/base/dd.c
> +++ b/drivers/base/dd.c
> @@ -516,12 +516,17 @@ static DEVICE_ATTR_RO(state_synced);
>  enum {
>  	/* Set on output if the -ERR has come from a probe() function */
>  	PROBEF_DRV_FAILED = 1 << 0,
> +	/*
> +	 * Set on input to call driver_deferred_probe_add() if -EPROBE_DEFER
> +	 * is returned
> +	 */
> +	PROBEF_SCHEDULE_DEFER = 1 << 1,

I don't understand what "PROBEF" means.  Not good for something that I
am going to be forced to maintain...

Again, "flags" are horrible, but if you do have them, then they should
at least be understandable.

Please try to do this without random flag values.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  6:44   ` Greg Kroah-Hartman
@ 2021-06-08 12:16     ` Jason Gunthorpe
  2021-06-08 13:13       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 12:16 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 08:44:20AM +0200, Greg Kroah-Hartman wrote:
> On Mon, Jun 07, 2021 at 09:55:43PM -0300, Jason Gunthorpe wrote:
> > Once a driver has been matched and probe() returns with -EPROBE_DEFER the
> > device is added to a deferred list and will be retried later.
> > 
> > At this point __device_attach_driver() should stop trying other drivers as
> > we have "matched" this driver and already scheduled another probe to
> > happen later.
> > 
> > Return the -EPROBE_DEFER from really_probe() instead of squashing it to
> > zero. This is similar to the code at the top of the function which
> > directly returns -EPROBE_DEFER.
> > 
> > It is not really a bug as, AFAIK, we don't actually have cases where
> > multiple drivers can bind.
> 
> We _do_ have devices that multiple drivers can bind to.  Are you sure
> you did not just break them?

I asked Cornelia Huck who added this code if she knew who was using it
and she said she added it but never ended up using it. Can you point
at where there are multiple drivers matching the same device?

If multiple drivers are matchable what creates determinism in which
will bind?

And yes, this would break devices with multiple drivers that are using
EPROBE_DEFER to set driver bind ordering. Do you know of any place
doing that?

> Why are you needing to change this?  What is it helping?  What problem
> is this solving?

This special flow works by returning 'success' when the driver bind
actually failed. This is OK in the one call site that continues to
scan but is not OK in the other callsites that don't keep scanning and
want to see error codes.

So after the later patches this becomes quite a bit more complicated
to keep implemented as-is. Better to delete it if it is safe to delete.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08  7:35   ` Greg Kroah-Hartman
@ 2021-06-08 12:17     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 12:17 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 09:35:17AM +0200, Greg Kroah-Hartman wrote:
> On Mon, Jun 07, 2021 at 09:55:43PM -0300, Jason Gunthorpe wrote:
> > Once a driver has been matched and probe() returns with -EPROBE_DEFER the
> > device is added to a deferred list and will be retried later.
> > 
> > At this point __device_attach_driver() should stop trying other drivers as
> > we have "matched" this driver and already scheduled another probe to
> > happen later.
> > 
> > Return the -EPROBE_DEFER from really_probe() instead of squashing it to
> > zero. This is similar to the code at the top of the function which
> > directly returns -EPROBE_DEFER.
> > 
> > It is not really a bug as, AFAIK, we don't actually have cases where
> > multiple drivers can bind.
> > 
> > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> >  drivers/base/dd.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> > 
> > diff --git a/drivers/base/dd.c b/drivers/base/dd.c
> > index ecd7cf848daff7..9d79a139290271 100644
> > +++ b/drivers/base/dd.c
> > @@ -656,7 +656,7 @@ static int really_probe(struct device *dev, struct device_driver *drv)
> >  		/* Driver requested deferred probing */
> >  		dev_dbg(dev, "Driver %s requests probe deferral\n", drv->name);
> >  		driver_deferred_probe_add_trigger(dev, local_trigger_count);
> > -		break;
> > +		goto done;
> >  	case -ENODEV:
> >  	case -ENXIO:
> >  		pr_debug("%s: probe of %s rejects match %d\n",
> 
> Why is lkml not cc:ed on driver core changes like get_maintainer.pl will
> say?

Sorry, this is my error, it was intended to be cc'd but scripting
seems to have malfunctioned in this case. It is what HCH observed too.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 02/10] driver core: Pull required checks into driver_probe_device()
  2021-06-08  5:59   ` Christoph Hellwig
@ 2021-06-08 12:21     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 12:21 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 06:59:10AM +0100, Christoph Hellwig wrote:
> This looks good as-is, but a suggestions for incremental improvements
> below:
> 
> > @@ -1032,10 +1035,10 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
> >  	__device_driver_lock(dev, dev->parent);
> >  
> >  	/*
> > -	 * If device has been removed or someone has already successfully
> > -	 * bound a driver before us just skip the driver probe call.
> > +	 * If device someone has already successfully bound a driver before us
> > +	 * just skip the driver probe call.
> >  	 */
> > -	if (!dev->p->dead && !dev->driver)
> > +	if (!dev->driver)
> >  		ret = driver_probe_device(drv, dev);
> >  
> >  	__device_driver_unlock(dev, dev->parent);
> 
> It is kinda silly to keep the ->driver check here given that one caller
> completely ignores the return value, and the other turns a 0 return into
> -ENODEV anyway. 

Later patches revise this though, I think you noticed it

> So I think this check can go away, turning device_driver_attach into
> a trivial wrapper for driver_probe_device that adds locking, which
> might be useful to reflect in the naming.

I was scared to change this because "0 on already bound" is uAPI in
sysfs at this point.

And what you noticed in bind_store:

       dev = bus_find_device_by_name(bus, NULL, buf);
       if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
               err = device_driver_attach(drv, dev);

Seems troublesome as the driver_lock isn't held for that dev->driver
read.

So I'm inclined to delete the above, keep the check in
device_driver_attach and not change the uAPI?

Or the APIs need to be more complicated to support locked and unlocked
callers/etc

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08  6:47   ` Greg Kroah-Hartman
@ 2021-06-08 12:30     ` Jason Gunthorpe
  2021-06-08 13:16       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 12:30 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 08:47:19AM +0200, Greg Kroah-Hartman wrote:
> On Mon, Jun 07, 2021 at 09:55:45PM -0300, Jason Gunthorpe wrote:
> > Currently really_probe() returns 1 on success and 0 if the probe() call
> > fails. This return code arrangement is designed to be useful for
> > __device_attach_driver() which is walking the device list and trying every
> > driver. 0 means to keep trying.
> > 
> > However, it is not useful for the other places that call through to
> > really_probe() that do actually want to see the probe() return code.
> > 
> > For instance bind_store() would be better to return the actual error code
> > from the driver's probe method, not discarding it and returning -ENODEV.
> 
> Why does that matter?  Why does it need to know this?

Proper return code to userspace are important. Knowing why the driver
probe() fails is certainly helpful for debugging. Is there are reason
to hide them? I think this is an improvement for sysfs bind.

Why this series needs it is because mdev has fixed sys uAPI at this point
that requires carring the return code from device driver probe() to
a mdev sysfs function.

> > -static int really_probe(struct device *dev, struct device_driver *drv)
> > +enum {
> > +	/* Set on output if the -ERR has come from a probe() function */
> > +	PROBEF_DRV_FAILED = 1 << 0,
> > +};
> > +
> > +static int really_probe(struct device *dev, struct device_driver *drv,
> > +			unsigned int *flags)
> 
> Ugh, no, please no functions with random "flags" in them, that way lies
> madness and unmaintainable code for decades to come.

The alternative to this something like this:

static int really_probe(struct device *dev, struct device_driver *drv,
			int *probe_err)

And since we still need the 'do not probe defer' in next patches then
it would have to be this:

static int really_probe(struct device *dev, struct device_driver *drv,
			int *probe_err, bool allow_probe_defer)

And the two new arguments flowed up through several function call
sites.

Do you prefer one of these more?

For your other question PROBEF_ means 'probe flag'.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 05/10] driver core: Export device_driver_attach()
  2021-06-08  6:19   ` Christoph Hellwig
@ 2021-06-08 12:33     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 12:33 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 07:19:33AM +0100, Christoph Hellwig wrote:
> On Mon, Jun 07, 2021 at 09:55:47PM -0300, Jason Gunthorpe wrote:
> > This is intended as a replacement API for device_bind_driver(). It has at
> > least the following benefits:
> > 
> > - Internal locking. Few of the users of device_bind_driver() follow the
> >   locking rules
> > 
> > - Calls device driver probe() internally. Notably this means that devm
> >   support for probe works correctly as probe() error will call
> >   devres_release_all()
> > 
> > - struct device_driver -> dev_groups is supported
> > 
> > - Simplified calling convention, no need to manually call probe().
> 
> Btw, it would be nice to convert at least one existing user of
> device_bind_driver to show this.  Also maybe Cc all maintainers of
> subsystems using device_bind_driver so that they get a headsup and
> maybe quickly move over?

Sure. I would do the MDIO phy, though I cann't test that code, I'm at
least familiar with it..

> > @@ -1077,6 +1079,7 @@ int device_driver_attach(struct device_driver *drv, struct device *dev)
> >  		return -EAGAIN;
> >  	return ret;
> >  }
> > +EXPORT_SYMBOL_GPL(device_driver_attach);
> 
> Ok, this means my earlier suggestions of a locked driver_probe_device
> helper needs a different name as we really don't want to expose flags
> and always return -EAGAIN here.  So maybe rename driver_probe_device
> to __driver_probe_device, have a driver_probe_device around it that
> does the locking and keep device_driver_attach for the newly exported
> API.

I put the squashing to -EAGAIN here specifically because of this
export. EPROBE_DEFER should not be returned to userspace and if I leak
it out to drivers at this point then one of them will eventually do
it wrong, as we saw already in sysfs bind_store

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08 12:16     ` Jason Gunthorpe
@ 2021-06-08 13:13       ` Greg Kroah-Hartman
  2021-06-08 13:53         ` Jason Gunthorpe
  0 siblings, 1 reply; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08 13:13 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 09:16:54AM -0300, Jason Gunthorpe wrote:
> On Tue, Jun 08, 2021 at 08:44:20AM +0200, Greg Kroah-Hartman wrote:
> > On Mon, Jun 07, 2021 at 09:55:43PM -0300, Jason Gunthorpe wrote:
> > > Once a driver has been matched and probe() returns with -EPROBE_DEFER the
> > > device is added to a deferred list and will be retried later.
> > > 
> > > At this point __device_attach_driver() should stop trying other drivers as
> > > we have "matched" this driver and already scheduled another probe to
> > > happen later.
> > > 
> > > Return the -EPROBE_DEFER from really_probe() instead of squashing it to
> > > zero. This is similar to the code at the top of the function which
> > > directly returns -EPROBE_DEFER.
> > > 
> > > It is not really a bug as, AFAIK, we don't actually have cases where
> > > multiple drivers can bind.
> > 
> > We _do_ have devices that multiple drivers can bind to.  Are you sure
> > you did not just break them?
> 
> I asked Cornelia Huck who added this code if she knew who was using it
> and she said she added it but never ended up using it. Can you point
> at where there are multiple drivers matching the same device?

USB storage devices is one set of devices where the drivers have the
ability to both bind to the same device but use a way to figure out the
"best" one to do so.

> If multiple drivers are matchable what creates determinism in which
> will bind?

Magic :)

> And yes, this would break devices with multiple drivers that are using
> EPROBE_DEFER to set driver bind ordering. Do you know of any place
> doing that?

Other than usb-storage and uas, not off the top of my head.  I think
there was some platform drivers using this but I can't find them at the
moment.

> > Why are you needing to change this?  What is it helping?  What problem
> > is this solving?
> 
> This special flow works by returning 'success' when the driver bind
> actually failed. This is OK in the one call site that continues to
> scan but is not OK in the other callsites that don't keep scanning and
> want to see error codes.
> 
> So after the later patches this becomes quite a bit more complicated
> to keep implemented as-is. Better to delete it if it is safe to delete.

I think you need to determine if it is safe first as it is changing the
core functionality in the kernel that a few thousand drivers depend on
:)

So a "proof" is needed before I can remove something like this.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08 12:30     ` Jason Gunthorpe
@ 2021-06-08 13:16       ` Greg Kroah-Hartman
  2021-06-08 14:03         ` Jason Gunthorpe
  0 siblings, 1 reply; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-08 13:16 UTC (permalink / raw)
  To: Jason Gunthorpe; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 09:30:23AM -0300, Jason Gunthorpe wrote:
> On Tue, Jun 08, 2021 at 08:47:19AM +0200, Greg Kroah-Hartman wrote:
> > On Mon, Jun 07, 2021 at 09:55:45PM -0300, Jason Gunthorpe wrote:
> > > Currently really_probe() returns 1 on success and 0 if the probe() call
> > > fails. This return code arrangement is designed to be useful for
> > > __device_attach_driver() which is walking the device list and trying every
> > > driver. 0 means to keep trying.
> > > 
> > > However, it is not useful for the other places that call through to
> > > really_probe() that do actually want to see the probe() return code.
> > > 
> > > For instance bind_store() would be better to return the actual error code
> > > from the driver's probe method, not discarding it and returning -ENODEV.
> > 
> > Why does that matter?  Why does it need to know this?
> 
> Proper return code to userspace are important. Knowing why the driver
> probe() fails is certainly helpful for debugging. Is there are reason
> to hide them? I think this is an improvement for sysfs bind.
> 
> Why this series needs it is because mdev has fixed sys uAPI at this point
> that requires carring the return code from device driver probe() to
> a mdev sysfs function.

What is mdev and what userspace tool requires such a userspace api to
depend on this?

Tools doing manual bind/unbind from userspace are crazy, it's always
been a "look at this neat hack!" type of thing.  To do it "right" you
should always do it correctly within the kernel.

> > > +enum {
> > > +	/* Set on output if the -ERR has come from a probe() function */
> > > +	PROBEF_DRV_FAILED = 1 << 0,
> > > +};
> > > +
> > > +static int really_probe(struct device *dev, struct device_driver *drv,
> > > +			unsigned int *flags)
> > 
> > Ugh, no, please no functions with random "flags" in them, that way lies
> > madness and unmaintainable code for decades to come.
> 
> The alternative to this something like this:
> 
> static int really_probe(struct device *dev, struct device_driver *drv,
> 			int *probe_err)
> 
> And since we still need the 'do not probe defer' in next patches then
> it would have to be this:
> 
> static int really_probe(struct device *dev, struct device_driver *drv,
> 			int *probe_err, bool allow_probe_defer)
> 
> And the two new arguments flowed up through several function call
> sites.
> 
> Do you prefer one of these more?

Random boolean flags as parameters are just as bad.

Make the functions able to be understood when read.

> For your other question PROBEF_ means 'probe flag'.

That was not obvious at all, and not something I would remember the next
time I have to look at this code...

Please use full words, we don't have a limit on restricted characters
anymore, this isn't the 1980's...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used
  2021-06-08 13:13       ` Greg Kroah-Hartman
@ 2021-06-08 13:53         ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 13:53 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 03:13:37PM +0200, Greg Kroah-Hartman wrote:

> > If multiple drivers are matchable what creates determinism in which
> > will bind?
> 
> Magic :)

I suppose you mean something like this code:

        /* Probe the USB device with the driver in hand, but only
         * defer to a generic driver in case the current USB
         * device driver has an id_table or a match function; i.e.,
         * when the device driver was explicitly matched against
         * a device.
         *
         * If the device driver does not have either of these,
         * then we assume that it can bind to any device and is
         * not truly a more specialized/non-generic driver, so a
         * return value of -ENODEV should not force the device
         * to be handled by the generic USB driver, as there
         * can still be another, more specialized, device driver.
         *
         * This accommodates the usbip driver.
         *
         * TODO: What if, in the future, there are multiple
         * specialized USB device drivers for a particular device?
         * In such cases, there is a need to try all matching
         * specialised device drivers prior to setting the
         * use_generic_driver bit.
         */
        error = udriver->probe(udev);
        if (error == -ENODEV && udriver != &usb_generic_driver &&
            (udriver->id_table || udriver->match)) {
                udev->use_generic_driver = 1;
                return -EPROBE_DEFER;
        }

So it does use EPROBE_DEFER to recycle through another attempt at
driver binding. Yikes. Why didn't it return -ENODEV I wonder?

But OK, I can think of no way to find all the cases like this to even
try to do something else at this point, so this has to be
preserved. I'll try to do that, maybe add a comment or two.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08 13:16       ` Greg Kroah-Hartman
@ 2021-06-08 14:03         ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 14:03 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 03:16:51PM +0200, Greg Kroah-Hartman wrote:
> On Tue, Jun 08, 2021 at 09:30:23AM -0300, Jason Gunthorpe wrote:
> > On Tue, Jun 08, 2021 at 08:47:19AM +0200, Greg Kroah-Hartman wrote:
> > > On Mon, Jun 07, 2021 at 09:55:45PM -0300, Jason Gunthorpe wrote:
> > > > Currently really_probe() returns 1 on success and 0 if the probe() call
> > > > fails. This return code arrangement is designed to be useful for
> > > > __device_attach_driver() which is walking the device list and trying every
> > > > driver. 0 means to keep trying.
> > > > 
> > > > However, it is not useful for the other places that call through to
> > > > really_probe() that do actually want to see the probe() return code.
> > > > 
> > > > For instance bind_store() would be better to return the actual error code
> > > > from the driver's probe method, not discarding it and returning -ENODEV.
> > > 
> > > Why does that matter?  Why does it need to know this?
> > 
> > Proper return code to userspace are important. Knowing why the driver
> > probe() fails is certainly helpful for debugging. Is there are reason
> > to hide them? I think this is an improvement for sysfs bind.
> > 
> > Why this series needs it is because mdev has fixed sys uAPI at this point
> > that requires carring the return code from device driver probe() to
> > a mdev sysfs function.
> 
> What is mdev and what userspace tool requires such a userspace api to
> depend on this?

Were you able to see the cover letter? mdev is part of vfio, it is
very ugly, but it has a userspace ecosystem now.

> Tools doing manual bind/unbind from userspace are crazy, it's always
> been a "look at this neat hack!" type of thing.  To do it "right" you
> should always do it correctly within the kernel.

Which is what the later patches do for mdev, but the dual operation of
creating the struct device and connecting to its driver have a
historical requirement to return the error code from driver probe to
the userspace.

v1 of this just did a hacky approach inside mdev to achieve this but
Dan and CH thought it would be more widely useful so asked for this
series to allow the driver core to handle it. This did turn out fairly
nice so I tend to agree - but returning the error code is important.

> Random boolean flags as parameters are just as bad.

Sure, but the function needs different behavior depending on the call
site. 

An alternative is to rework all the call chains to somehow embed the
difference directly and I don't have a clear vision how to do that
that is any nicer than this.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind
  2021-06-08  6:07   ` Christoph Hellwig
@ 2021-06-08 23:53     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-08 23:53 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: Greg Kroah-Hartman, kvm, Rafael J. Wysocki

On Tue, Jun 08, 2021 at 07:07:49AM +0100, Christoph Hellwig wrote:
> > index 36d0c654ea6124..03591f82251302 100644
> > +++ b/drivers/base/bus.c
> > @@ -212,13 +212,9 @@ static ssize_t bind_store(struct device_driver *drv, const char *buf,
> >  	dev = bus_find_device_by_name(bus, NULL, buf);
> >  	if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
> >  		err = device_driver_attach(drv, dev);
> > -
> > -		if (err > 0) {
> > +		if (!err) {
> >  			/* success */
> >  			err = count;
> > -		} else if (err == 0) {
> > -			/* driver didn't accept device */
> > -			err = -ENODEV;
> >  		}
> >  	}
> 
> I think we can also drop the dev->driver == NULL check above given
> that device_driver_attach covers it now.

I'm glad you noticed this because it is wonky today:

static ssize_t bind_store() {
        int err = -ENODEV;

        if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
               err = device_driver_attach() {
                    int ret = 0;
                    __device_driver_lock(dev, dev->parent);
                    if (!dev->p->dead && !dev->driver)
                           ..
                    return ret;
               }
        }
        return err;

Thus if dev->driver == NULL this will usually return -ENODEV unless it
races just right and returns 0. So I fixed it up to always return
-EBUSY and always read dev->driver under the lock.

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  2021-06-08  0:55   ` [Intel-gfx] " Jason Gunthorpe
@ 2021-06-11 12:40     ` Cornelia Huck
  -1 siblings, 0 replies; 53+ messages in thread
From: Cornelia Huck @ 2021-06-11 12:40 UTC (permalink / raw)
  To: Jason Gunthorpe, David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Jonathan Corbet, Daniel Vetter, dri-devel,
	Vasily Gorbik, Heiko Carstens, intel-gfx, Jani Nikula,
	Jason Herne, Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc,
	linux-s390, Halil Pasic, Rodrigo Vivi

On Mon, Jun 07 2021, Jason Gunthorpe <jgg@nvidia.com> wrote:

> For some reason the vfio_mdev shim mdev_driver has its own module and
> kconfig. As the next patch requires access to it from mdev.ko merge the
> two modules together and remove VFIO_MDEV_DEVICE.
>
> A later patch deletes this driver entirely.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  Documentation/s390/vfio-ap.rst   |  1 -
>  arch/s390/Kconfig                |  2 +-
>  drivers/gpu/drm/i915/Kconfig     |  2 +-
>  drivers/vfio/mdev/Kconfig        |  7 -------
>  drivers/vfio/mdev/Makefile       |  3 +--
>  drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
>  drivers/vfio/mdev/mdev_private.h |  2 ++
>  drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
>  samples/Kconfig                  |  6 +++---
>  9 files changed, 23 insertions(+), 40 deletions(-)

I think you missed my earlier

Reviewed-by: Cornelia Huck <cohuck@redhat.com>


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
@ 2021-06-11 12:40     ` Cornelia Huck
  0 siblings, 0 replies; 53+ messages in thread
From: Cornelia Huck @ 2021-06-11 12:40 UTC (permalink / raw)
  To: Jason Gunthorpe, David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Jonathan Corbet, Daniel Vetter, dri-devel,
	Vasily Gorbik, Heiko Carstens, intel-gfx, Jani Nikula,
	Jason Herne, Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc,
	linux-s390, Halil Pasic, Rodrigo Vivi

On Mon, Jun 07 2021, Jason Gunthorpe <jgg@nvidia.com> wrote:

> For some reason the vfio_mdev shim mdev_driver has its own module and
> kconfig. As the next patch requires access to it from mdev.ko merge the
> two modules together and remove VFIO_MDEV_DEVICE.
>
> A later patch deletes this driver entirely.
>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> ---
>  Documentation/s390/vfio-ap.rst   |  1 -
>  arch/s390/Kconfig                |  2 +-
>  drivers/gpu/drm/i915/Kconfig     |  2 +-
>  drivers/vfio/mdev/Kconfig        |  7 -------
>  drivers/vfio/mdev/Makefile       |  3 +--
>  drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
>  drivers/vfio/mdev/mdev_private.h |  2 ++
>  drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
>  samples/Kconfig                  |  6 +++---
>  9 files changed, 23 insertions(+), 40 deletions(-)

I think you missed my earlier

Reviewed-by: Cornelia Huck <cohuck@redhat.com>

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
  2021-06-11 12:40     ` [Intel-gfx] " Cornelia Huck
  (?)
@ 2021-06-14 12:35       ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 12:35 UTC (permalink / raw)
  To: Cornelia Huck, Christoph Hellwig
  Cc: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Jonathan Corbet, Daniel Vetter, dri-devel,
	Vasily Gorbik, Heiko Carstens, intel-gfx, Jani Nikula,
	Jason Herne, Joonas Lahtinen, kvm, Kirti Wankhede, linux-doc,
	linux-s390, Halil Pasic, Rodrigo Vivi

On Fri, Jun 11, 2021 at 02:40:41PM +0200, Cornelia Huck wrote:
> On Mon, Jun 07 2021, Jason Gunthorpe <jgg@nvidia.com> wrote:
> 
> > For some reason the vfio_mdev shim mdev_driver has its own module and
> > kconfig. As the next patch requires access to it from mdev.ko merge the
> > two modules together and remove VFIO_MDEV_DEVICE.
> >
> > A later patch deletes this driver entirely.
> >
> > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> >  Documentation/s390/vfio-ap.rst   |  1 -
> >  arch/s390/Kconfig                |  2 +-
> >  drivers/gpu/drm/i915/Kconfig     |  2 +-
> >  drivers/vfio/mdev/Kconfig        |  7 -------
> >  drivers/vfio/mdev/Makefile       |  3 +--
> >  drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
> >  drivers/vfio/mdev/mdev_private.h |  2 ++
> >  drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
> >  samples/Kconfig                  |  6 +++---
> >  9 files changed, 23 insertions(+), 40 deletions(-)
> 
> I think you missed my earlier
> 
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>

Yes, my mistake, I didn't think there were any tags in the v1 posting

Thanks,
Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
@ 2021-06-14 12:35       ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 12:35 UTC (permalink / raw)
  To: Cornelia Huck, Christoph Hellwig
  Cc: Tony Krowiak, Jason Herne, kvm, Vasily Gorbik, Jonathan Corbet,
	David Airlie, linux-s390, Heiko Carstens, linux-doc,
	Kirti Wankhede, dri-devel, Halil Pasic, Christian Borntraeger,
	Alex Williamson, Rodrigo Vivi, intel-gfx

On Fri, Jun 11, 2021 at 02:40:41PM +0200, Cornelia Huck wrote:
> On Mon, Jun 07 2021, Jason Gunthorpe <jgg@nvidia.com> wrote:
> 
> > For some reason the vfio_mdev shim mdev_driver has its own module and
> > kconfig. As the next patch requires access to it from mdev.ko merge the
> > two modules together and remove VFIO_MDEV_DEVICE.
> >
> > A later patch deletes this driver entirely.
> >
> > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> >  Documentation/s390/vfio-ap.rst   |  1 -
> >  arch/s390/Kconfig                |  2 +-
> >  drivers/gpu/drm/i915/Kconfig     |  2 +-
> >  drivers/vfio/mdev/Kconfig        |  7 -------
> >  drivers/vfio/mdev/Makefile       |  3 +--
> >  drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
> >  drivers/vfio/mdev/mdev_private.h |  2 ++
> >  drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
> >  samples/Kconfig                  |  6 +++---
> >  9 files changed, 23 insertions(+), 40 deletions(-)
> 
> I think you missed my earlier
> 
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>

Yes, my mistake, I didn't think there were any tags in the v1 posting

Thanks,
Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
@ 2021-06-14 12:35       ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 12:35 UTC (permalink / raw)
  To: Cornelia Huck, Christoph Hellwig
  Cc: Tony Krowiak, Jason Herne, kvm, Vasily Gorbik, Jonathan Corbet,
	David Airlie, linux-s390, Heiko Carstens, linux-doc,
	Kirti Wankhede, dri-devel, Halil Pasic, Christian Borntraeger,
	intel-gfx

On Fri, Jun 11, 2021 at 02:40:41PM +0200, Cornelia Huck wrote:
> On Mon, Jun 07 2021, Jason Gunthorpe <jgg@nvidia.com> wrote:
> 
> > For some reason the vfio_mdev shim mdev_driver has its own module and
> > kconfig. As the next patch requires access to it from mdev.ko merge the
> > two modules together and remove VFIO_MDEV_DEVICE.
> >
> > A later patch deletes this driver entirely.
> >
> > Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> >  Documentation/s390/vfio-ap.rst   |  1 -
> >  arch/s390/Kconfig                |  2 +-
> >  drivers/gpu/drm/i915/Kconfig     |  2 +-
> >  drivers/vfio/mdev/Kconfig        |  7 -------
> >  drivers/vfio/mdev/Makefile       |  3 +--
> >  drivers/vfio/mdev/mdev_core.c    | 16 ++++++++++++++--
> >  drivers/vfio/mdev/mdev_private.h |  2 ++
> >  drivers/vfio/mdev/vfio_mdev.c    | 24 +-----------------------
> >  samples/Kconfig                  |  6 +++---
> >  9 files changed, 23 insertions(+), 40 deletions(-)
> 
> I think you missed my earlier
> 
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>

Yes, my mistake, I didn't think there were any tags in the v1 posting

Thanks,
Jason
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
  2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
  (?)
@ 2021-06-14 14:34   ` Kirti Wankhede
  -1 siblings, 0 replies; 53+ messages in thread
From: Kirti Wankhede @ 2021-06-14 14:34 UTC (permalink / raw)
  To: Jason Gunthorpe, David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi
  Cc: Christoph Hellwig

Jason,

I couldn't find patch 1,2,4 and 5 of these series. Can you please keep 
kvm@vger.kernel.org cc for all patches?

Also it will be helpful if you can add version prefix, eg. 'v3' for this 
series, in subject line.

Thanks,
Kirti

On 6/8/2021 6:25 AM, Jason Gunthorpe wrote:
> This is a "v3" of the previous posted full conversion:
>    https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
> 
> Without the trailing patches that are running into complications:
>   - The CCW conversion has some complicated remarks
>   - AP is waiting for some locking stuff to get worked out
>   - No feedback on GT
>   - The license change topic for removing vfio_mdev.c
> 
> Getting the baseline functionality merged will allow Intel's IDXD mdev
> driver to advance. It has already been RFC posted in the new format:
> 
> https://lore.kernel.org/kvm/162164243591.261970.3439987543338120797.stgit@djiang5-desk3.ch.intel.com/
> 
> This series includes base infrastructure and the sample conversions. The
> remaining four issues can be sorted out one by one.
> 
> The major change in v3 is to enhance the driver core support for binding
> based on the request from Christoph Hellwig and Dan Williams. Based on
> some light analysis this looks broadly useful:
> 
> https://lore.kernel.org/kvm/20210428233856.GY1370958@nvidia.com/
> 
> ====
> 
> The mdev bus's core part for managing the lifecycle of devices is mostly
> as one would expect for a driver core bus subsystem.
> 
> However instead of having a normal 'struct device_driver' and binding the
> actual mdev drivers through the standard driver core mechanisms it open
> codes this with the struct mdev_parent_ops and provides a single driver
> that shims between the VFIO core's struct vfio_device and the actual
> device driver.
> 
> Instead, allow mdev drivers implement an actual struct mdev_driver and
> directly call vfio_register_group_dev() in the probe() function for the
> mdev. Arrange to bind the created mdev_device to the mdev_driver that is
> provided by the end driver.
> 
> The actual execution flow doesn't change much, eg what was
> parent_ops->create is now device_driver->probe and it is called at almost
> the exact same time - except under the normal control of the driver core.
> 
> Ultimately converting all the drivers unlocks a fair number of additional
> VFIO simplifications and cleanups.
> 
> v3:
>   - Use device_driver_attach() from the driver core
>   - 5 new patches to make device_driver_attach() exported and usable for this
>   - Remove trailing patches for now
> v2: https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
>   - Keep && m in samples kconfig
>   - Restore accidently squashed removeal of vfio_mdev.c
>   - Remove indirections to call bus_register()/bus_unregister()
>   - Reflow long doc lines
> v1: https://lore.kernel.org/r/0-v1-d88406ed308e+418-vfio3_jgg@nvidia.com
> 
> Jason Gunthorpe (10):
>    driver core: Do not continue searching for drivers if deferred probe
>      is used
>    driver core: Pull required checks into driver_probe_device()
>    driver core: Flow the return code from ->probe() through to sysfs bind
>    driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
>    driver core: Export device_driver_attach()
>    vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
>    vfio/mdev: Allow the mdev_parent_ops to specify the device driver to
>      bind
>    vfio/mtty: Convert to use vfio_register_group_dev()
>    vfio/mdpy: Convert to use vfio_register_group_dev()
>    vfio/mbochs: Convert to use vfio_register_group_dev()
> 
>   Documentation/s390/vfio-ap.rst   |   1 -
>   arch/s390/Kconfig                |   2 +-
>   drivers/base/base.h              |   1 -
>   drivers/base/bus.c               |   6 +-
>   drivers/base/dd.c                | 116 ++++++++++++-------
>   drivers/gpu/drm/i915/Kconfig     |   2 +-
>   drivers/vfio/mdev/Kconfig        |   7 --
>   drivers/vfio/mdev/Makefile       |   3 +-
>   drivers/vfio/mdev/mdev_core.c    |  46 ++++++--
>   drivers/vfio/mdev/mdev_driver.c  |  10 ++
>   drivers/vfio/mdev/mdev_private.h |   2 +
>   drivers/vfio/mdev/vfio_mdev.c    |  24 +---
>   include/linux/device.h           |   2 +
>   include/linux/mdev.h             |   2 +
>   samples/Kconfig                  |   6 +-
>   samples/vfio-mdev/mbochs.c       | 163 +++++++++++++++------------
>   samples/vfio-mdev/mdpy.c         | 159 ++++++++++++++------------
>   samples/vfio-mdev/mtty.c         | 185 ++++++++++++++-----------------
>   18 files changed, 397 insertions(+), 340 deletions(-)
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-14 14:34   ` Kirti Wankhede
  0 siblings, 0 replies; 53+ messages in thread
From: Kirti Wankhede @ 2021-06-14 14:34 UTC (permalink / raw)
  To: Jason Gunthorpe, David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi
  Cc: Christoph Hellwig

Jason,

I couldn't find patch 1,2,4 and 5 of these series. Can you please keep 
kvm@vger.kernel.org cc for all patches?

Also it will be helpful if you can add version prefix, eg. 'v3' for this 
series, in subject line.

Thanks,
Kirti

On 6/8/2021 6:25 AM, Jason Gunthorpe wrote:
> This is a "v3" of the previous posted full conversion:
>    https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
> 
> Without the trailing patches that are running into complications:
>   - The CCW conversion has some complicated remarks
>   - AP is waiting for some locking stuff to get worked out
>   - No feedback on GT
>   - The license change topic for removing vfio_mdev.c
> 
> Getting the baseline functionality merged will allow Intel's IDXD mdev
> driver to advance. It has already been RFC posted in the new format:
> 
> https://lore.kernel.org/kvm/162164243591.261970.3439987543338120797.stgit@djiang5-desk3.ch.intel.com/
> 
> This series includes base infrastructure and the sample conversions. The
> remaining four issues can be sorted out one by one.
> 
> The major change in v3 is to enhance the driver core support for binding
> based on the request from Christoph Hellwig and Dan Williams. Based on
> some light analysis this looks broadly useful:
> 
> https://lore.kernel.org/kvm/20210428233856.GY1370958@nvidia.com/
> 
> ====
> 
> The mdev bus's core part for managing the lifecycle of devices is mostly
> as one would expect for a driver core bus subsystem.
> 
> However instead of having a normal 'struct device_driver' and binding the
> actual mdev drivers through the standard driver core mechanisms it open
> codes this with the struct mdev_parent_ops and provides a single driver
> that shims between the VFIO core's struct vfio_device and the actual
> device driver.
> 
> Instead, allow mdev drivers implement an actual struct mdev_driver and
> directly call vfio_register_group_dev() in the probe() function for the
> mdev. Arrange to bind the created mdev_device to the mdev_driver that is
> provided by the end driver.
> 
> The actual execution flow doesn't change much, eg what was
> parent_ops->create is now device_driver->probe and it is called at almost
> the exact same time - except under the normal control of the driver core.
> 
> Ultimately converting all the drivers unlocks a fair number of additional
> VFIO simplifications and cleanups.
> 
> v3:
>   - Use device_driver_attach() from the driver core
>   - 5 new patches to make device_driver_attach() exported and usable for this
>   - Remove trailing patches for now
> v2: https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
>   - Keep && m in samples kconfig
>   - Restore accidently squashed removeal of vfio_mdev.c
>   - Remove indirections to call bus_register()/bus_unregister()
>   - Reflow long doc lines
> v1: https://lore.kernel.org/r/0-v1-d88406ed308e+418-vfio3_jgg@nvidia.com
> 
> Jason Gunthorpe (10):
>    driver core: Do not continue searching for drivers if deferred probe
>      is used
>    driver core: Pull required checks into driver_probe_device()
>    driver core: Flow the return code from ->probe() through to sysfs bind
>    driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
>    driver core: Export device_driver_attach()
>    vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
>    vfio/mdev: Allow the mdev_parent_ops to specify the device driver to
>      bind
>    vfio/mtty: Convert to use vfio_register_group_dev()
>    vfio/mdpy: Convert to use vfio_register_group_dev()
>    vfio/mbochs: Convert to use vfio_register_group_dev()
> 
>   Documentation/s390/vfio-ap.rst   |   1 -
>   arch/s390/Kconfig                |   2 +-
>   drivers/base/base.h              |   1 -
>   drivers/base/bus.c               |   6 +-
>   drivers/base/dd.c                | 116 ++++++++++++-------
>   drivers/gpu/drm/i915/Kconfig     |   2 +-
>   drivers/vfio/mdev/Kconfig        |   7 --
>   drivers/vfio/mdev/Makefile       |   3 +-
>   drivers/vfio/mdev/mdev_core.c    |  46 ++++++--
>   drivers/vfio/mdev/mdev_driver.c  |  10 ++
>   drivers/vfio/mdev/mdev_private.h |   2 +
>   drivers/vfio/mdev/vfio_mdev.c    |  24 +---
>   include/linux/device.h           |   2 +
>   include/linux/mdev.h             |   2 +
>   samples/Kconfig                  |   6 +-
>   samples/vfio-mdev/mbochs.c       | 163 +++++++++++++++------------
>   samples/vfio-mdev/mdpy.c         | 159 ++++++++++++++------------
>   samples/vfio-mdev/mtty.c         | 185 ++++++++++++++-----------------
>   18 files changed, 397 insertions(+), 340 deletions(-)
> 

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-14 14:34   ` Kirti Wankhede
  0 siblings, 0 replies; 53+ messages in thread
From: Kirti Wankhede @ 2021-06-14 14:34 UTC (permalink / raw)
  To: Jason Gunthorpe, David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi
  Cc: Christoph Hellwig

Jason,

I couldn't find patch 1,2,4 and 5 of these series. Can you please keep 
kvm@vger.kernel.org cc for all patches?

Also it will be helpful if you can add version prefix, eg. 'v3' for this 
series, in subject line.

Thanks,
Kirti

On 6/8/2021 6:25 AM, Jason Gunthorpe wrote:
> This is a "v3" of the previous posted full conversion:
>    https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
> 
> Without the trailing patches that are running into complications:
>   - The CCW conversion has some complicated remarks
>   - AP is waiting for some locking stuff to get worked out
>   - No feedback on GT
>   - The license change topic for removing vfio_mdev.c
> 
> Getting the baseline functionality merged will allow Intel's IDXD mdev
> driver to advance. It has already been RFC posted in the new format:
> 
> https://lore.kernel.org/kvm/162164243591.261970.3439987543338120797.stgit@djiang5-desk3.ch.intel.com/
> 
> This series includes base infrastructure and the sample conversions. The
> remaining four issues can be sorted out one by one.
> 
> The major change in v3 is to enhance the driver core support for binding
> based on the request from Christoph Hellwig and Dan Williams. Based on
> some light analysis this looks broadly useful:
> 
> https://lore.kernel.org/kvm/20210428233856.GY1370958@nvidia.com/
> 
> ====
> 
> The mdev bus's core part for managing the lifecycle of devices is mostly
> as one would expect for a driver core bus subsystem.
> 
> However instead of having a normal 'struct device_driver' and binding the
> actual mdev drivers through the standard driver core mechanisms it open
> codes this with the struct mdev_parent_ops and provides a single driver
> that shims between the VFIO core's struct vfio_device and the actual
> device driver.
> 
> Instead, allow mdev drivers implement an actual struct mdev_driver and
> directly call vfio_register_group_dev() in the probe() function for the
> mdev. Arrange to bind the created mdev_device to the mdev_driver that is
> provided by the end driver.
> 
> The actual execution flow doesn't change much, eg what was
> parent_ops->create is now device_driver->probe and it is called at almost
> the exact same time - except under the normal control of the driver core.
> 
> Ultimately converting all the drivers unlocks a fair number of additional
> VFIO simplifications and cleanups.
> 
> v3:
>   - Use device_driver_attach() from the driver core
>   - 5 new patches to make device_driver_attach() exported and usable for this
>   - Remove trailing patches for now
> v2: https://lore.kernel.org/r/0-v2-7667f42c9bad+935-vfio3_jgg@nvidia.com
>   - Keep && m in samples kconfig
>   - Restore accidently squashed removeal of vfio_mdev.c
>   - Remove indirections to call bus_register()/bus_unregister()
>   - Reflow long doc lines
> v1: https://lore.kernel.org/r/0-v1-d88406ed308e+418-vfio3_jgg@nvidia.com
> 
> Jason Gunthorpe (10):
>    driver core: Do not continue searching for drivers if deferred probe
>      is used
>    driver core: Pull required checks into driver_probe_device()
>    driver core: Flow the return code from ->probe() through to sysfs bind
>    driver core: Don't return EPROBE_DEFER to userspace during sysfs bind
>    driver core: Export device_driver_attach()
>    vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE
>    vfio/mdev: Allow the mdev_parent_ops to specify the device driver to
>      bind
>    vfio/mtty: Convert to use vfio_register_group_dev()
>    vfio/mdpy: Convert to use vfio_register_group_dev()
>    vfio/mbochs: Convert to use vfio_register_group_dev()
> 
>   Documentation/s390/vfio-ap.rst   |   1 -
>   arch/s390/Kconfig                |   2 +-
>   drivers/base/base.h              |   1 -
>   drivers/base/bus.c               |   6 +-
>   drivers/base/dd.c                | 116 ++++++++++++-------
>   drivers/gpu/drm/i915/Kconfig     |   2 +-
>   drivers/vfio/mdev/Kconfig        |   7 --
>   drivers/vfio/mdev/Makefile       |   3 +-
>   drivers/vfio/mdev/mdev_core.c    |  46 ++++++--
>   drivers/vfio/mdev/mdev_driver.c  |  10 ++
>   drivers/vfio/mdev/mdev_private.h |   2 +
>   drivers/vfio/mdev/vfio_mdev.c    |  24 +---
>   include/linux/device.h           |   2 +
>   include/linux/mdev.h             |   2 +
>   samples/Kconfig                  |   6 +-
>   samples/vfio-mdev/mbochs.c       | 163 +++++++++++++++------------
>   samples/vfio-mdev/mdpy.c         | 159 ++++++++++++++------------
>   samples/vfio-mdev/mtty.c         | 185 ++++++++++++++-----------------
>   18 files changed, 397 insertions(+), 340 deletions(-)
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
  2021-06-14 14:34   ` Kirti Wankhede
  (?)
@ 2021-06-14 14:36     ` Jason Gunthorpe
  -1 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 14:36 UTC (permalink / raw)
  To: Kirti Wankhede
  Cc: David Airlie, Tony Krowiak, Alex Williamson,
	Christian Borntraeger, Cornelia Huck, Jonathan Corbet,
	Daniel Vetter, dri-devel, Vasily Gorbik, Greg Kroah-Hartman,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi, Christoph Hellwig

On Mon, Jun 14, 2021 at 08:04:03PM +0530, Kirti Wankhede wrote:
> Jason,
> 
> I couldn't find patch 1,2,4 and 5 of these series. Can you please keep
> kvm@vger.kernel.org cc for all patches?

It is an error, sorry

> Also it will be helpful if you can add version prefix, eg. 'v3' for this
> series, in subject line.

This is not v3, it is a different but related series

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-14 14:36     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 14:36 UTC (permalink / raw)
  To: Kirti Wankhede
  Cc: kvm, linux-doc, David Airlie, dri-devel, Christoph Hellwig,
	linux-s390, Jonathan Corbet, Rafael J. Wysocki, Halil Pasic,
	Christian Borntraeger, intel-gfx, Jason Herne, Vasily Gorbik,
	Heiko Carstens, Alex Williamson, Rodrigo Vivi, Tony Krowiak,
	Greg Kroah-Hartman, Cornelia Huck

On Mon, Jun 14, 2021 at 08:04:03PM +0530, Kirti Wankhede wrote:
> Jason,
> 
> I couldn't find patch 1,2,4 and 5 of these series. Can you please keep
> kvm@vger.kernel.org cc for all patches?

It is an error, sorry

> Also it will be helpful if you can add version prefix, eg. 'v3' for this
> series, in subject line.

This is not v3, it is a different but related series

Jason

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [Intel-gfx] [PATCH 00/10] Allow mdev drivers to directly create the vfio_device
@ 2021-06-14 14:36     ` Jason Gunthorpe
  0 siblings, 0 replies; 53+ messages in thread
From: Jason Gunthorpe @ 2021-06-14 14:36 UTC (permalink / raw)
  To: Kirti Wankhede
  Cc: kvm, linux-doc, David Airlie, dri-devel, Christoph Hellwig,
	linux-s390, Jonathan Corbet, Rafael J. Wysocki, Halil Pasic,
	Christian Borntraeger, intel-gfx, Jason Herne, Vasily Gorbik,
	Heiko Carstens, Tony Krowiak, Greg Kroah-Hartman, Cornelia Huck

On Mon, Jun 14, 2021 at 08:04:03PM +0530, Kirti Wankhede wrote:
> Jason,
> 
> I couldn't find patch 1,2,4 and 5 of these series. Can you please keep
> kvm@vger.kernel.org cc for all patches?

It is an error, sorry

> Also it will be helpful if you can add version prefix, eg. 'v3' for this
> series, in subject line.

This is not v3, it is a different but related series

Jason
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
  2021-06-17 14:22 Allow mdev drivers to directly create the vfio_device (v4) Christoph Hellwig
@ 2021-06-17 14:22 ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-17 14:22 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jason Gunthorpe, Alex Williamson, Kirti Wankhede
  Cc: David Airlie, Tony Krowiak, Christian Borntraeger, Cornelia Huck,
	Jonathan Corbet, Daniel Vetter, dri-devel, Vasily Gorbik,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi

From: Jason Gunthorpe <jgg@nvidia.com>

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 72 deletions(-)

diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 881ef9a7296f..6c0f229db36a 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -130,6 +130,7 @@ static struct class	*mbochs_class;
 static struct cdev	mbochs_cdev;
 static struct device	mbochs_dev;
 static int		mbochs_used_mbytes;
+static const struct vfio_device_ops mbochs_dev_ops;
 
 struct vfio_region_info_ext {
 	struct vfio_region_info          base;
@@ -160,6 +161,7 @@ struct mbochs_dmabuf {
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	u8 *vconfig;
 	u64 bar_mask[3];
 	u32 memory_bar_mask;
@@ -425,11 +427,9 @@ static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
 		memcpy(buf, mdev_state->edid_blob + offset, count);
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
-			   loff_t pos, bool is_write)
+static ssize_t mdev_access(struct mdev_state *mdev_state, char *buf,
+			   size_t count, loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct page *pg;
 	loff_t poff;
 	char *map;
@@ -478,7 +478,7 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 		put_page(pg);
 
 	} else {
-		dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
+		dev_dbg(mdev_state->vdev.dev, "%s: %s @0x%llx (unhandled)\n",
 			__func__, is_write ? "WR" : "RD", pos);
 		ret = -1;
 		goto accessfailed;
@@ -493,9 +493,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 	return ret;
 }
 
-static int mbochs_reset(struct mdev_device *mdev)
+static int mbochs_reset(struct mdev_state *mdev_state)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	u32 size64k = mdev_state->memsize / (64 * 1024);
 	int i;
 
@@ -506,12 +505,13 @@ static int mbochs_reset(struct mdev_device *mdev)
 	return 0;
 }
 
-static int mbochs_create(struct mdev_device *mdev)
+static int mbochs_probe(struct mdev_device *mdev)
 {
 	const struct mbochs_type *type =
 		&mbochs_types[mdev_get_type_group_id(mdev)];
 	struct device *dev = mdev_dev(mdev);
 	struct mdev_state *mdev_state;
+	int ret = -ENOMEM;
 
 	if (type->mbytes + mbochs_used_mbytes > max_mbytes)
 		return -ENOMEM;
@@ -519,6 +519,7 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);
 
 	mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (mdev_state->vconfig == NULL)
@@ -537,7 +538,6 @@ static int mbochs_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
 	INIT_LIST_HEAD(&mdev_state->dmabufs);
 	mdev_state->next_id = 1;
 
@@ -547,32 +547,38 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
 	mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
 	mbochs_create_config_space(mdev_state);
-	mbochs_reset(mdev);
+	mbochs_reset(mdev_state);
 
 	mbochs_used_mbytes += type->mbytes;
+
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret)
+		goto err_mem;
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 
 err_mem:
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return -ENOMEM;
+	return ret;
 }
 
-static int mbochs_remove(struct mdev_device *mdev)
+static void mbochs_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
 	mbochs_used_mbytes -= mdev_state->type->mbytes;
-	mdev_set_drvdata(mdev, NULL);
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	kfree(mdev_state->pages);
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return 0;
 }
 
-static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mbochs_read(struct vfio_device *vdev, char __user *buf,
 			   size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -582,7 +588,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (char *)&val, sizeof(val),
+			ret =  mdev_access(mdev_state, (char *)&val, sizeof(val),
 					   *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -594,7 +600,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -606,7 +612,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -629,9 +635,11 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mbochs_write(struct vfio_device *vdev, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -644,7 +652,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -656,7 +664,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -668,7 +676,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -754,9 +762,10 @@ static const struct vm_operations_struct mbochs_region_vm_ops = {
 	.fault = mbochs_region_vm_fault,
 };
 
-static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+static int mbochs_mmap(struct vfio_device *vdev, struct vm_area_struct *vma)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
 		return -EINVAL;
@@ -963,7 +972,7 @@ mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
 static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 {
 	struct mdev_state *mdev_state = dmabuf->mdev_state;
-	struct device *dev = mdev_dev(mdev_state->mdev);
+	struct device *dev = mdev_state->vdev.dev;
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct dma_buf *buf;
 
@@ -991,15 +1000,10 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 	return 0;
 }
 
-static int mbochs_get_region_info(struct mdev_device *mdev,
+static int mbochs_get_region_info(struct mdev_state *mdev_state,
 				  struct vfio_region_info_ext *ext)
 {
 	struct vfio_region_info *region_info = &ext->base;
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
 
 	if (region_info->index >= MBOCHS_NUM_REGIONS)
 		return -EINVAL;
@@ -1047,15 +1051,13 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_get_irq_info(struct mdev_device *mdev,
-			       struct vfio_irq_info *irq_info)
+static int mbochs_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	irq_info->count = 0;
 	return 0;
 }
 
-static int mbochs_get_device_info(struct mdev_device *mdev,
-				  struct vfio_device_info *dev_info)
+static int mbochs_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = MBOCHS_NUM_REGIONS;
@@ -1063,11 +1065,9 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_query_gfx_plane(struct mdev_device *mdev,
+static int mbochs_query_gfx_plane(struct mdev_state *mdev_state,
 				  struct vfio_device_gfx_plane_info *plane)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct mbochs_dmabuf *dmabuf;
 	struct mbochs_mode mode;
 	int ret;
@@ -1121,18 +1121,16 @@ static int mbochs_query_gfx_plane(struct mdev_device *mdev,
 done:
 	if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
 	    mdev_state->active_id != plane->dmabuf_id) {
-		dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
-			mdev_state->active_id, plane->dmabuf_id);
+		dev_dbg(mdev_state->vdev.dev, "%s: primary: %d => %d\n",
+			__func__, mdev_state->active_id, plane->dmabuf_id);
 		mdev_state->active_id = plane->dmabuf_id;
 	}
 	mutex_unlock(&mdev_state->ops_lock);
 	return 0;
 }
 
-static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
-				 u32 id)
+static int mbochs_get_gfx_dmabuf(struct mdev_state *mdev_state, u32 id)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	struct mbochs_dmabuf *dmabuf;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1154,9 +1152,11 @@ static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
 	return dma_buf_fd(dmabuf->buf, 0);
 }
 
-static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
-			unsigned long arg)
+static long mbochs_ioctl(struct vfio_device *vdev, unsigned int cmd,
+			 unsigned long arg)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	int ret = 0;
 	unsigned long minsz, outsz;
 
@@ -1173,7 +1173,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_get_device_info(mdev, &info);
+		ret = mbochs_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -1197,7 +1197,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (outsz > sizeof(info))
 			return -EINVAL;
 
-		ret = mbochs_get_region_info(mdev, &info);
+		ret = mbochs_get_region_info(mdev_state, &info);
 		if (ret)
 			return ret;
 
@@ -1220,7 +1220,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= VFIO_PCI_NUM_IRQS))
 			return -EINVAL;
 
-		ret = mbochs_get_irq_info(mdev, &info);
+		ret = mbochs_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -1243,7 +1243,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (plane.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_query_gfx_plane(mdev, &plane);
+		ret = mbochs_query_gfx_plane(mdev_state, &plane);
 		if (ret)
 			return ret;
 
@@ -1260,19 +1260,19 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (get_user(dmabuf_id, (__u32 __user *)arg))
 			return -EFAULT;
 
-		return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
+		return mbochs_get_gfx_dmabuf(mdev_state, dmabuf_id);
 	}
 
 	case VFIO_DEVICE_SET_IRQS:
 		return -EINVAL;
 
 	case VFIO_DEVICE_RESET:
-		return mbochs_reset(mdev);
+		return mbochs_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mbochs_open(struct mdev_device *mdev)
+static int mbochs_open(struct vfio_device *vdev)
 {
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
@@ -1280,9 +1280,10 @@ static int mbochs_open(struct mdev_device *mdev)
 	return 0;
 }
 
-static void mbochs_close(struct mdev_device *mdev)
+static void mbochs_close(struct vfio_device *vdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	struct mbochs_dmabuf *dmabuf, *tmp;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1306,8 +1307,7 @@ static ssize_t
 memory_show(struct device *dev, struct device_attribute *attr,
 	    char *buf)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
 }
@@ -1398,18 +1398,30 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mbochs_dev_ops = {
+	.open = mbochs_open,
+	.release = mbochs_close,
+	.read = mbochs_read,
+	.write = mbochs_write,
+	.ioctl = mbochs_ioctl,
+	.mmap = mbochs_mmap,
+};
+
+static struct mdev_driver mbochs_driver = {
+	.driver = {
+		.name = "mbochs",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mbochs_probe,
+	.remove	= mbochs_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
+	.device_driver		= &mbochs_driver,
 	.supported_type_groups	= mdev_type_groups,
-	.create			= mbochs_create,
-	.remove			= mbochs_remove,
-	.open			= mbochs_open,
-	.release		= mbochs_close,
-	.read			= mbochs_read,
-	.write			= mbochs_write,
-	.ioctl			= mbochs_ioctl,
-	.mmap			= mbochs_mmap,
 };
 
 static const struct file_operations vd_fops = {
@@ -1434,11 +1446,15 @@ static int __init mbochs_dev_init(void)
 	cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK + 1);
 	pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
 
+	ret = mdev_register_driver(&mbochs_driver);
+	if (ret)
+		goto err_cdev;
+
 	mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
 	if (IS_ERR(mbochs_class)) {
 		pr_err("Error: failed to register mbochs_dev class\n");
 		ret = PTR_ERR(mbochs_class);
-		goto failed1;
+		goto err_driver;
 	}
 	mbochs_dev.class = mbochs_class;
 	mbochs_dev.release = mbochs_device_release;
@@ -1446,19 +1462,21 @@ static int __init mbochs_dev_init(void)
 
 	ret = device_register(&mbochs_dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mbochs_dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	return 0;
 
-failed3:
+err_device:
 	device_unregister(&mbochs_dev);
-failed2:
+err_class:
 	class_destroy(mbochs_class);
-failed1:
+err_driver:
+	mdev_unregister_driver(&mbochs_driver);
+err_cdev:
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	return ret;
@@ -1470,6 +1488,7 @@ static void __exit mbochs_dev_exit(void)
 	mdev_unregister_device(&mbochs_dev);
 
 	device_unregister(&mbochs_dev);
+	mdev_unregister_driver(&mbochs_driver);
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	class_destroy(mbochs_class);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
  2021-06-15 13:35 ` [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev() Christoph Hellwig
@ 2021-06-15 14:12     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-15 14:12 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Jason Gunthorpe, Alex Williamson, Kirti Wankhede, David Airlie,
	Tony Krowiak, Christian Borntraeger, Cornelia Huck,
	Jonathan Corbet, Daniel Vetter, dri-devel, Vasily Gorbik,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi

On Tue, Jun 15, 2021 at 03:35:19PM +0200, Christoph Hellwig wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
> 
> This is straightforward conversion, the mdev_state is actually serving as
> the vfio_device and we can replace all the mdev_get_drvdata()'s and the
> wonky dead code with a simple container_of().
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
>  1 file changed, 91 insertions(+), 72 deletions(-)

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* Re: [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
@ 2021-06-15 14:12     ` Greg Kroah-Hartman
  0 siblings, 0 replies; 53+ messages in thread
From: Greg Kroah-Hartman @ 2021-06-15 14:12 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: kvm, linux-doc, David Airlie, dri-devel, Kirti Wankhede,
	linux-s390, Jonathan Corbet, Rafael J. Wysocki, Halil Pasic,
	Christian Borntraeger, Jason Gunthorpe, intel-gfx, Jason Herne,
	Vasily Gorbik, Heiko Carstens, Alex Williamson, Rodrigo Vivi,
	Tony Krowiak, Cornelia Huck

On Tue, Jun 15, 2021 at 03:35:19PM +0200, Christoph Hellwig wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
> 
> This is straightforward conversion, the mdev_state is actually serving as
> the vfio_device and we can replace all the mdev_get_drvdata()'s and the
> wonky dead code with a simple container_of().
> 
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> ---
>  samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
>  1 file changed, 91 insertions(+), 72 deletions(-)

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
  2021-06-15 13:35 Allow mdev drivers to directly create the vfio_device (v3) Christoph Hellwig
@ 2021-06-15 13:35 ` Christoph Hellwig
  2021-06-15 14:12     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-15 13:35 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jason Gunthorpe, Alex Williamson, Kirti Wankhede
  Cc: David Airlie, Tony Krowiak, Christian Borntraeger, Cornelia Huck,
	Jonathan Corbet, Daniel Vetter, dri-devel, Vasily Gorbik,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi

From: Jason Gunthorpe <jgg@nvidia.com>

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 72 deletions(-)

diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 881ef9a7296f..6c0f229db36a 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -130,6 +130,7 @@ static struct class	*mbochs_class;
 static struct cdev	mbochs_cdev;
 static struct device	mbochs_dev;
 static int		mbochs_used_mbytes;
+static const struct vfio_device_ops mbochs_dev_ops;
 
 struct vfio_region_info_ext {
 	struct vfio_region_info          base;
@@ -160,6 +161,7 @@ struct mbochs_dmabuf {
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	u8 *vconfig;
 	u64 bar_mask[3];
 	u32 memory_bar_mask;
@@ -425,11 +427,9 @@ static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
 		memcpy(buf, mdev_state->edid_blob + offset, count);
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
-			   loff_t pos, bool is_write)
+static ssize_t mdev_access(struct mdev_state *mdev_state, char *buf,
+			   size_t count, loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct page *pg;
 	loff_t poff;
 	char *map;
@@ -478,7 +478,7 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 		put_page(pg);
 
 	} else {
-		dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
+		dev_dbg(mdev_state->vdev.dev, "%s: %s @0x%llx (unhandled)\n",
 			__func__, is_write ? "WR" : "RD", pos);
 		ret = -1;
 		goto accessfailed;
@@ -493,9 +493,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 	return ret;
 }
 
-static int mbochs_reset(struct mdev_device *mdev)
+static int mbochs_reset(struct mdev_state *mdev_state)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	u32 size64k = mdev_state->memsize / (64 * 1024);
 	int i;
 
@@ -506,12 +505,13 @@ static int mbochs_reset(struct mdev_device *mdev)
 	return 0;
 }
 
-static int mbochs_create(struct mdev_device *mdev)
+static int mbochs_probe(struct mdev_device *mdev)
 {
 	const struct mbochs_type *type =
 		&mbochs_types[mdev_get_type_group_id(mdev)];
 	struct device *dev = mdev_dev(mdev);
 	struct mdev_state *mdev_state;
+	int ret = -ENOMEM;
 
 	if (type->mbytes + mbochs_used_mbytes > max_mbytes)
 		return -ENOMEM;
@@ -519,6 +519,7 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);
 
 	mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (mdev_state->vconfig == NULL)
@@ -537,7 +538,6 @@ static int mbochs_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
 	INIT_LIST_HEAD(&mdev_state->dmabufs);
 	mdev_state->next_id = 1;
 
@@ -547,32 +547,38 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
 	mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
 	mbochs_create_config_space(mdev_state);
-	mbochs_reset(mdev);
+	mbochs_reset(mdev_state);
 
 	mbochs_used_mbytes += type->mbytes;
+
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret)
+		goto err_mem;
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 
 err_mem:
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return -ENOMEM;
+	return ret;
 }
 
-static int mbochs_remove(struct mdev_device *mdev)
+static void mbochs_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
 	mbochs_used_mbytes -= mdev_state->type->mbytes;
-	mdev_set_drvdata(mdev, NULL);
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	kfree(mdev_state->pages);
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return 0;
 }
 
-static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mbochs_read(struct vfio_device *vdev, char __user *buf,
 			   size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -582,7 +588,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (char *)&val, sizeof(val),
+			ret =  mdev_access(mdev_state, (char *)&val, sizeof(val),
 					   *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -594,7 +600,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -606,7 +612,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -629,9 +635,11 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mbochs_write(struct vfio_device *vdev, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -644,7 +652,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -656,7 +664,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -668,7 +676,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -754,9 +762,10 @@ static const struct vm_operations_struct mbochs_region_vm_ops = {
 	.fault = mbochs_region_vm_fault,
 };
 
-static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+static int mbochs_mmap(struct vfio_device *vdev, struct vm_area_struct *vma)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
 		return -EINVAL;
@@ -963,7 +972,7 @@ mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
 static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 {
 	struct mdev_state *mdev_state = dmabuf->mdev_state;
-	struct device *dev = mdev_dev(mdev_state->mdev);
+	struct device *dev = mdev_state->vdev.dev;
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct dma_buf *buf;
 
@@ -991,15 +1000,10 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 	return 0;
 }
 
-static int mbochs_get_region_info(struct mdev_device *mdev,
+static int mbochs_get_region_info(struct mdev_state *mdev_state,
 				  struct vfio_region_info_ext *ext)
 {
 	struct vfio_region_info *region_info = &ext->base;
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
 
 	if (region_info->index >= MBOCHS_NUM_REGIONS)
 		return -EINVAL;
@@ -1047,15 +1051,13 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_get_irq_info(struct mdev_device *mdev,
-			       struct vfio_irq_info *irq_info)
+static int mbochs_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	irq_info->count = 0;
 	return 0;
 }
 
-static int mbochs_get_device_info(struct mdev_device *mdev,
-				  struct vfio_device_info *dev_info)
+static int mbochs_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = MBOCHS_NUM_REGIONS;
@@ -1063,11 +1065,9 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_query_gfx_plane(struct mdev_device *mdev,
+static int mbochs_query_gfx_plane(struct mdev_state *mdev_state,
 				  struct vfio_device_gfx_plane_info *plane)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct mbochs_dmabuf *dmabuf;
 	struct mbochs_mode mode;
 	int ret;
@@ -1121,18 +1121,16 @@ static int mbochs_query_gfx_plane(struct mdev_device *mdev,
 done:
 	if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
 	    mdev_state->active_id != plane->dmabuf_id) {
-		dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
-			mdev_state->active_id, plane->dmabuf_id);
+		dev_dbg(mdev_state->vdev.dev, "%s: primary: %d => %d\n",
+			__func__, mdev_state->active_id, plane->dmabuf_id);
 		mdev_state->active_id = plane->dmabuf_id;
 	}
 	mutex_unlock(&mdev_state->ops_lock);
 	return 0;
 }
 
-static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
-				 u32 id)
+static int mbochs_get_gfx_dmabuf(struct mdev_state *mdev_state, u32 id)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	struct mbochs_dmabuf *dmabuf;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1154,9 +1152,11 @@ static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
 	return dma_buf_fd(dmabuf->buf, 0);
 }
 
-static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
-			unsigned long arg)
+static long mbochs_ioctl(struct vfio_device *vdev, unsigned int cmd,
+			 unsigned long arg)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	int ret = 0;
 	unsigned long minsz, outsz;
 
@@ -1173,7 +1173,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_get_device_info(mdev, &info);
+		ret = mbochs_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -1197,7 +1197,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (outsz > sizeof(info))
 			return -EINVAL;
 
-		ret = mbochs_get_region_info(mdev, &info);
+		ret = mbochs_get_region_info(mdev_state, &info);
 		if (ret)
 			return ret;
 
@@ -1220,7 +1220,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= VFIO_PCI_NUM_IRQS))
 			return -EINVAL;
 
-		ret = mbochs_get_irq_info(mdev, &info);
+		ret = mbochs_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -1243,7 +1243,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (plane.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_query_gfx_plane(mdev, &plane);
+		ret = mbochs_query_gfx_plane(mdev_state, &plane);
 		if (ret)
 			return ret;
 
@@ -1260,19 +1260,19 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (get_user(dmabuf_id, (__u32 __user *)arg))
 			return -EFAULT;
 
-		return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
+		return mbochs_get_gfx_dmabuf(mdev_state, dmabuf_id);
 	}
 
 	case VFIO_DEVICE_SET_IRQS:
 		return -EINVAL;
 
 	case VFIO_DEVICE_RESET:
-		return mbochs_reset(mdev);
+		return mbochs_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mbochs_open(struct mdev_device *mdev)
+static int mbochs_open(struct vfio_device *vdev)
 {
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
@@ -1280,9 +1280,10 @@ static int mbochs_open(struct mdev_device *mdev)
 	return 0;
 }
 
-static void mbochs_close(struct mdev_device *mdev)
+static void mbochs_close(struct vfio_device *vdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	struct mbochs_dmabuf *dmabuf, *tmp;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1306,8 +1307,7 @@ static ssize_t
 memory_show(struct device *dev, struct device_attribute *attr,
 	    char *buf)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
 }
@@ -1398,18 +1398,30 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mbochs_dev_ops = {
+	.open = mbochs_open,
+	.release = mbochs_close,
+	.read = mbochs_read,
+	.write = mbochs_write,
+	.ioctl = mbochs_ioctl,
+	.mmap = mbochs_mmap,
+};
+
+static struct mdev_driver mbochs_driver = {
+	.driver = {
+		.name = "mbochs",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mbochs_probe,
+	.remove	= mbochs_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
+	.device_driver		= &mbochs_driver,
 	.supported_type_groups	= mdev_type_groups,
-	.create			= mbochs_create,
-	.remove			= mbochs_remove,
-	.open			= mbochs_open,
-	.release		= mbochs_close,
-	.read			= mbochs_read,
-	.write			= mbochs_write,
-	.ioctl			= mbochs_ioctl,
-	.mmap			= mbochs_mmap,
 };
 
 static const struct file_operations vd_fops = {
@@ -1434,11 +1446,15 @@ static int __init mbochs_dev_init(void)
 	cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK + 1);
 	pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
 
+	ret = mdev_register_driver(&mbochs_driver);
+	if (ret)
+		goto err_cdev;
+
 	mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
 	if (IS_ERR(mbochs_class)) {
 		pr_err("Error: failed to register mbochs_dev class\n");
 		ret = PTR_ERR(mbochs_class);
-		goto failed1;
+		goto err_driver;
 	}
 	mbochs_dev.class = mbochs_class;
 	mbochs_dev.release = mbochs_device_release;
@@ -1446,19 +1462,21 @@ static int __init mbochs_dev_init(void)
 
 	ret = device_register(&mbochs_dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mbochs_dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	return 0;
 
-failed3:
+err_device:
 	device_unregister(&mbochs_dev);
-failed2:
+err_class:
 	class_destroy(mbochs_class);
-failed1:
+err_driver:
+	mdev_unregister_driver(&mbochs_driver);
+err_cdev:
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	return ret;
@@ -1470,6 +1488,7 @@ static void __exit mbochs_dev_exit(void)
 	mdev_unregister_device(&mbochs_dev);
 
 	device_unregister(&mbochs_dev);
+	mdev_unregister_driver(&mbochs_driver);
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	class_destroy(mbochs_class);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 53+ messages in thread

* [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev()
  2021-06-14 15:08 Allow mdev drivers to directly create the vfio_device (v2 / alternative) Christoph Hellwig
@ 2021-06-14 15:08 ` Christoph Hellwig
  0 siblings, 0 replies; 53+ messages in thread
From: Christoph Hellwig @ 2021-06-14 15:08 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Jason Gunthorpe, Alex Williamson, Kirti Wankhede
  Cc: David Airlie, Tony Krowiak, Christian Borntraeger, Cornelia Huck,
	Jonathan Corbet, Daniel Vetter, dri-devel, Vasily Gorbik,
	Heiko Carstens, intel-gfx, Jani Nikula, Jason Herne,
	Joonas Lahtinen, kvm, linux-doc, linux-s390, Halil Pasic,
	Rafael J. Wysocki, Rodrigo Vivi

From: Jason Gunthorpe <jgg@nvidia.com>

This is straightforward conversion, the mdev_state is actually serving as
the vfio_device and we can replace all the mdev_get_drvdata()'s and the
wonky dead code with a simple container_of().

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
 samples/vfio-mdev/mbochs.c | 163 +++++++++++++++++++++----------------
 1 file changed, 91 insertions(+), 72 deletions(-)

diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 881ef9a7296f..6c0f229db36a 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -130,6 +130,7 @@ static struct class	*mbochs_class;
 static struct cdev	mbochs_cdev;
 static struct device	mbochs_dev;
 static int		mbochs_used_mbytes;
+static const struct vfio_device_ops mbochs_dev_ops;
 
 struct vfio_region_info_ext {
 	struct vfio_region_info          base;
@@ -160,6 +161,7 @@ struct mbochs_dmabuf {
 
 /* State of each mdev device */
 struct mdev_state {
+	struct vfio_device vdev;
 	u8 *vconfig;
 	u64 bar_mask[3];
 	u32 memory_bar_mask;
@@ -425,11 +427,9 @@ static void handle_edid_blob(struct mdev_state *mdev_state, u16 offset,
 		memcpy(buf, mdev_state->edid_blob + offset, count);
 }
 
-static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
-			   loff_t pos, bool is_write)
+static ssize_t mdev_access(struct mdev_state *mdev_state, char *buf,
+			   size_t count, loff_t pos, bool is_write)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct page *pg;
 	loff_t poff;
 	char *map;
@@ -478,7 +478,7 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 		put_page(pg);
 
 	} else {
-		dev_dbg(dev, "%s: %s @0x%llx (unhandled)\n",
+		dev_dbg(mdev_state->vdev.dev, "%s: %s @0x%llx (unhandled)\n",
 			__func__, is_write ? "WR" : "RD", pos);
 		ret = -1;
 		goto accessfailed;
@@ -493,9 +493,8 @@ static ssize_t mdev_access(struct mdev_device *mdev, char *buf, size_t count,
 	return ret;
 }
 
-static int mbochs_reset(struct mdev_device *mdev)
+static int mbochs_reset(struct mdev_state *mdev_state)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	u32 size64k = mdev_state->memsize / (64 * 1024);
 	int i;
 
@@ -506,12 +505,13 @@ static int mbochs_reset(struct mdev_device *mdev)
 	return 0;
 }
 
-static int mbochs_create(struct mdev_device *mdev)
+static int mbochs_probe(struct mdev_device *mdev)
 {
 	const struct mbochs_type *type =
 		&mbochs_types[mdev_get_type_group_id(mdev)];
 	struct device *dev = mdev_dev(mdev);
 	struct mdev_state *mdev_state;
+	int ret = -ENOMEM;
 
 	if (type->mbytes + mbochs_used_mbytes > max_mbytes)
 		return -ENOMEM;
@@ -519,6 +519,7 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state = kzalloc(sizeof(struct mdev_state), GFP_KERNEL);
 	if (mdev_state == NULL)
 		return -ENOMEM;
+	vfio_init_group_dev(&mdev_state->vdev, &mdev->dev, &mbochs_dev_ops);
 
 	mdev_state->vconfig = kzalloc(MBOCHS_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (mdev_state->vconfig == NULL)
@@ -537,7 +538,6 @@ static int mbochs_create(struct mdev_device *mdev)
 
 	mutex_init(&mdev_state->ops_lock);
 	mdev_state->mdev = mdev;
-	mdev_set_drvdata(mdev, mdev_state);
 	INIT_LIST_HEAD(&mdev_state->dmabufs);
 	mdev_state->next_id = 1;
 
@@ -547,32 +547,38 @@ static int mbochs_create(struct mdev_device *mdev)
 	mdev_state->edid_regs.edid_offset = MBOCHS_EDID_BLOB_OFFSET;
 	mdev_state->edid_regs.edid_max_size = sizeof(mdev_state->edid_blob);
 	mbochs_create_config_space(mdev_state);
-	mbochs_reset(mdev);
+	mbochs_reset(mdev_state);
 
 	mbochs_used_mbytes += type->mbytes;
+
+	ret = vfio_register_group_dev(&mdev_state->vdev);
+	if (ret)
+		goto err_mem;
+	dev_set_drvdata(&mdev->dev, mdev_state);
 	return 0;
 
 err_mem:
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return -ENOMEM;
+	return ret;
 }
 
-static int mbochs_remove(struct mdev_device *mdev)
+static void mbochs_remove(struct mdev_device *mdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(&mdev->dev);
 
 	mbochs_used_mbytes -= mdev_state->type->mbytes;
-	mdev_set_drvdata(mdev, NULL);
+	vfio_unregister_group_dev(&mdev_state->vdev);
 	kfree(mdev_state->pages);
 	kfree(mdev_state->vconfig);
 	kfree(mdev_state);
-	return 0;
 }
 
-static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
+static ssize_t mbochs_read(struct vfio_device *vdev, char __user *buf,
 			   size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -582,7 +588,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		if (count >= 4 && !(*ppos % 4)) {
 			u32 val;
 
-			ret =  mdev_access(mdev, (char *)&val, sizeof(val),
+			ret =  mdev_access(mdev_state, (char *)&val, sizeof(val),
 					   *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -594,7 +600,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else if (count >= 2 && !(*ppos % 2)) {
 			u16 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -606,7 +612,7 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 		} else {
 			u8 val;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, false);
 			if (ret <= 0)
 				goto read_err;
@@ -629,9 +635,11 @@ static ssize_t mbochs_read(struct mdev_device *mdev, char __user *buf,
 	return -EFAULT;
 }
 
-static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
+static ssize_t mbochs_write(struct vfio_device *vdev, const char __user *buf,
 			    size_t count, loff_t *ppos)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	unsigned int done = 0;
 	int ret;
 
@@ -644,7 +652,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -656,7 +664,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -668,7 +676,7 @@ static ssize_t mbochs_write(struct mdev_device *mdev, const char __user *buf,
 			if (copy_from_user(&val, buf, sizeof(val)))
 				goto write_err;
 
-			ret = mdev_access(mdev, (char *)&val, sizeof(val),
+			ret = mdev_access(mdev_state, (char *)&val, sizeof(val),
 					  *ppos, true);
 			if (ret <= 0)
 				goto write_err;
@@ -754,9 +762,10 @@ static const struct vm_operations_struct mbochs_region_vm_ops = {
 	.fault = mbochs_region_vm_fault,
 };
 
-static int mbochs_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
+static int mbochs_mmap(struct vfio_device *vdev, struct vm_area_struct *vma)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 
 	if (vma->vm_pgoff != MBOCHS_MEMORY_BAR_OFFSET >> PAGE_SHIFT)
 		return -EINVAL;
@@ -963,7 +972,7 @@ mbochs_dmabuf_find_by_id(struct mdev_state *mdev_state, u32 id)
 static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 {
 	struct mdev_state *mdev_state = dmabuf->mdev_state;
-	struct device *dev = mdev_dev(mdev_state->mdev);
+	struct device *dev = mdev_state->vdev.dev;
 	DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
 	struct dma_buf *buf;
 
@@ -991,15 +1000,10 @@ static int mbochs_dmabuf_export(struct mbochs_dmabuf *dmabuf)
 	return 0;
 }
 
-static int mbochs_get_region_info(struct mdev_device *mdev,
+static int mbochs_get_region_info(struct mdev_state *mdev_state,
 				  struct vfio_region_info_ext *ext)
 {
 	struct vfio_region_info *region_info = &ext->base;
-	struct mdev_state *mdev_state;
-
-	mdev_state = mdev_get_drvdata(mdev);
-	if (!mdev_state)
-		return -EINVAL;
 
 	if (region_info->index >= MBOCHS_NUM_REGIONS)
 		return -EINVAL;
@@ -1047,15 +1051,13 @@ static int mbochs_get_region_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_get_irq_info(struct mdev_device *mdev,
-			       struct vfio_irq_info *irq_info)
+static int mbochs_get_irq_info(struct vfio_irq_info *irq_info)
 {
 	irq_info->count = 0;
 	return 0;
 }
 
-static int mbochs_get_device_info(struct mdev_device *mdev,
-				  struct vfio_device_info *dev_info)
+static int mbochs_get_device_info(struct vfio_device_info *dev_info)
 {
 	dev_info->flags = VFIO_DEVICE_FLAGS_PCI;
 	dev_info->num_regions = MBOCHS_NUM_REGIONS;
@@ -1063,11 +1065,9 @@ static int mbochs_get_device_info(struct mdev_device *mdev,
 	return 0;
 }
 
-static int mbochs_query_gfx_plane(struct mdev_device *mdev,
+static int mbochs_query_gfx_plane(struct mdev_state *mdev_state,
 				  struct vfio_device_gfx_plane_info *plane)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
-	struct device *dev = mdev_dev(mdev);
 	struct mbochs_dmabuf *dmabuf;
 	struct mbochs_mode mode;
 	int ret;
@@ -1121,18 +1121,16 @@ static int mbochs_query_gfx_plane(struct mdev_device *mdev,
 done:
 	if (plane->drm_plane_type == DRM_PLANE_TYPE_PRIMARY &&
 	    mdev_state->active_id != plane->dmabuf_id) {
-		dev_dbg(dev, "%s: primary: %d => %d\n", __func__,
-			mdev_state->active_id, plane->dmabuf_id);
+		dev_dbg(mdev_state->vdev.dev, "%s: primary: %d => %d\n",
+			__func__, mdev_state->active_id, plane->dmabuf_id);
 		mdev_state->active_id = plane->dmabuf_id;
 	}
 	mutex_unlock(&mdev_state->ops_lock);
 	return 0;
 }
 
-static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
-				 u32 id)
+static int mbochs_get_gfx_dmabuf(struct mdev_state *mdev_state, u32 id)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
 	struct mbochs_dmabuf *dmabuf;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1154,9 +1152,11 @@ static int mbochs_get_gfx_dmabuf(struct mdev_device *mdev,
 	return dma_buf_fd(dmabuf->buf, 0);
 }
 
-static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
-			unsigned long arg)
+static long mbochs_ioctl(struct vfio_device *vdev, unsigned int cmd,
+			 unsigned long arg)
 {
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	int ret = 0;
 	unsigned long minsz, outsz;
 
@@ -1173,7 +1173,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (info.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_get_device_info(mdev, &info);
+		ret = mbochs_get_device_info(&info);
 		if (ret)
 			return ret;
 
@@ -1197,7 +1197,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (outsz > sizeof(info))
 			return -EINVAL;
 
-		ret = mbochs_get_region_info(mdev, &info);
+		ret = mbochs_get_region_info(mdev_state, &info);
 		if (ret)
 			return ret;
 
@@ -1220,7 +1220,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		    (info.index >= VFIO_PCI_NUM_IRQS))
 			return -EINVAL;
 
-		ret = mbochs_get_irq_info(mdev, &info);
+		ret = mbochs_get_irq_info(&info);
 		if (ret)
 			return ret;
 
@@ -1243,7 +1243,7 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (plane.argsz < minsz)
 			return -EINVAL;
 
-		ret = mbochs_query_gfx_plane(mdev, &plane);
+		ret = mbochs_query_gfx_plane(mdev_state, &plane);
 		if (ret)
 			return ret;
 
@@ -1260,19 +1260,19 @@ static long mbochs_ioctl(struct mdev_device *mdev, unsigned int cmd,
 		if (get_user(dmabuf_id, (__u32 __user *)arg))
 			return -EFAULT;
 
-		return mbochs_get_gfx_dmabuf(mdev, dmabuf_id);
+		return mbochs_get_gfx_dmabuf(mdev_state, dmabuf_id);
 	}
 
 	case VFIO_DEVICE_SET_IRQS:
 		return -EINVAL;
 
 	case VFIO_DEVICE_RESET:
-		return mbochs_reset(mdev);
+		return mbochs_reset(mdev_state);
 	}
 	return -ENOTTY;
 }
 
-static int mbochs_open(struct mdev_device *mdev)
+static int mbochs_open(struct vfio_device *vdev)
 {
 	if (!try_module_get(THIS_MODULE))
 		return -ENODEV;
@@ -1280,9 +1280,10 @@ static int mbochs_open(struct mdev_device *mdev)
 	return 0;
 }
 
-static void mbochs_close(struct mdev_device *mdev)
+static void mbochs_close(struct vfio_device *vdev)
 {
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state =
+		container_of(vdev, struct mdev_state, vdev);
 	struct mbochs_dmabuf *dmabuf, *tmp;
 
 	mutex_lock(&mdev_state->ops_lock);
@@ -1306,8 +1307,7 @@ static ssize_t
 memory_show(struct device *dev, struct device_attribute *attr,
 	    char *buf)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-	struct mdev_state *mdev_state = mdev_get_drvdata(mdev);
+	struct mdev_state *mdev_state = dev_get_drvdata(dev);
 
 	return sprintf(buf, "%d MB\n", mdev_state->type->mbytes);
 }
@@ -1398,18 +1398,30 @@ static struct attribute_group *mdev_type_groups[] = {
 	NULL,
 };
 
+static const struct vfio_device_ops mbochs_dev_ops = {
+	.open = mbochs_open,
+	.release = mbochs_close,
+	.read = mbochs_read,
+	.write = mbochs_write,
+	.ioctl = mbochs_ioctl,
+	.mmap = mbochs_mmap,
+};
+
+static struct mdev_driver mbochs_driver = {
+	.driver = {
+		.name = "mbochs",
+		.owner = THIS_MODULE,
+		.mod_name = KBUILD_MODNAME,
+		.dev_groups = mdev_dev_groups,
+	},
+	.probe = mbochs_probe,
+	.remove	= mbochs_remove,
+};
+
 static const struct mdev_parent_ops mdev_fops = {
 	.owner			= THIS_MODULE,
-	.mdev_attr_groups	= mdev_dev_groups,
+	.device_driver		= &mbochs_driver,
 	.supported_type_groups	= mdev_type_groups,
-	.create			= mbochs_create,
-	.remove			= mbochs_remove,
-	.open			= mbochs_open,
-	.release		= mbochs_close,
-	.read			= mbochs_read,
-	.write			= mbochs_write,
-	.ioctl			= mbochs_ioctl,
-	.mmap			= mbochs_mmap,
 };
 
 static const struct file_operations vd_fops = {
@@ -1434,11 +1446,15 @@ static int __init mbochs_dev_init(void)
 	cdev_add(&mbochs_cdev, mbochs_devt, MINORMASK + 1);
 	pr_info("%s: major %d\n", __func__, MAJOR(mbochs_devt));
 
+	ret = mdev_register_driver(&mbochs_driver);
+	if (ret)
+		goto err_cdev;
+
 	mbochs_class = class_create(THIS_MODULE, MBOCHS_CLASS_NAME);
 	if (IS_ERR(mbochs_class)) {
 		pr_err("Error: failed to register mbochs_dev class\n");
 		ret = PTR_ERR(mbochs_class);
-		goto failed1;
+		goto err_driver;
 	}
 	mbochs_dev.class = mbochs_class;
 	mbochs_dev.release = mbochs_device_release;
@@ -1446,19 +1462,21 @@ static int __init mbochs_dev_init(void)
 
 	ret = device_register(&mbochs_dev);
 	if (ret)
-		goto failed2;
+		goto err_class;
 
 	ret = mdev_register_device(&mbochs_dev, &mdev_fops);
 	if (ret)
-		goto failed3;
+		goto err_device;
 
 	return 0;
 
-failed3:
+err_device:
 	device_unregister(&mbochs_dev);
-failed2:
+err_class:
 	class_destroy(mbochs_class);
-failed1:
+err_driver:
+	mdev_unregister_driver(&mbochs_driver);
+err_cdev:
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	return ret;
@@ -1470,6 +1488,7 @@ static void __exit mbochs_dev_exit(void)
 	mdev_unregister_device(&mbochs_dev);
 
 	device_unregister(&mbochs_dev);
+	mdev_unregister_driver(&mbochs_driver);
 	cdev_del(&mbochs_cdev);
 	unregister_chrdev_region(mbochs_devt, MINORMASK + 1);
 	class_destroy(mbochs_class);
-- 
2.30.2


^ permalink raw reply	[flat|nested] 53+ messages in thread

end of thread, other threads:[~2021-06-17 14:27 UTC | newest]

Thread overview: 53+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-08  0:55 [PATCH 00/10] Allow mdev drivers to directly create the vfio_device Jason Gunthorpe
2021-06-08  0:55 ` [Intel-gfx] " Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 01/10] driver core: Do not continue searching for drivers if deferred probe is used Jason Gunthorpe
2021-06-08  5:51   ` Christoph Hellwig
2021-06-08  6:44   ` Greg Kroah-Hartman
2021-06-08 12:16     ` Jason Gunthorpe
2021-06-08 13:13       ` Greg Kroah-Hartman
2021-06-08 13:53         ` Jason Gunthorpe
2021-06-08  7:35   ` Greg Kroah-Hartman
2021-06-08 12:17     ` Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 02/10] driver core: Pull required checks into driver_probe_device() Jason Gunthorpe
2021-06-08  5:59   ` Christoph Hellwig
2021-06-08 12:21     ` Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 03/10] driver core: Flow the return code from ->probe() through to sysfs bind Jason Gunthorpe
2021-06-08  6:07   ` Christoph Hellwig
2021-06-08 23:53     ` Jason Gunthorpe
2021-06-08  6:47   ` Greg Kroah-Hartman
2021-06-08 12:30     ` Jason Gunthorpe
2021-06-08 13:16       ` Greg Kroah-Hartman
2021-06-08 14:03         ` Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 04/10] driver core: Don't return EPROBE_DEFER to userspace during " Jason Gunthorpe
2021-06-08  6:14   ` Christoph Hellwig
2021-06-08  7:37   ` Greg Kroah-Hartman
2021-06-08  0:55 ` [PATCH 05/10] driver core: Export device_driver_attach() Jason Gunthorpe
2021-06-08  6:19   ` Christoph Hellwig
2021-06-08 12:33     ` Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 06/10] vfio/mdev: Remove CONFIG_VFIO_MDEV_DEVICE Jason Gunthorpe
2021-06-08  0:55   ` [Intel-gfx] " Jason Gunthorpe
2021-06-08  6:20   ` Christoph Hellwig
2021-06-08  6:20     ` [Intel-gfx] " Christoph Hellwig
2021-06-11 12:40   ` Cornelia Huck
2021-06-11 12:40     ` [Intel-gfx] " Cornelia Huck
2021-06-14 12:35     ` Jason Gunthorpe
2021-06-14 12:35       ` [Intel-gfx] " Jason Gunthorpe
2021-06-14 12:35       ` Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 07/10] vfio/mdev: Allow the mdev_parent_ops to specify the device driver to bind Jason Gunthorpe
2021-06-08  6:21   ` Christoph Hellwig
2021-06-08  0:55 ` [PATCH 08/10] vfio/mtty: Convert to use vfio_register_group_dev() Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 09/10] vfio/mdpy: " Jason Gunthorpe
2021-06-08  0:55 ` [PATCH 10/10] vfio/mbochs: " Jason Gunthorpe
2021-06-08  6:22 ` [PATCH 00/10] Allow mdev drivers to directly create the vfio_device Christoph Hellwig
2021-06-08  6:22   ` [Intel-gfx] " Christoph Hellwig
2021-06-14 14:34 ` Kirti Wankhede
2021-06-14 14:34   ` [Intel-gfx] " Kirti Wankhede
2021-06-14 14:34   ` Kirti Wankhede
2021-06-14 14:36   ` Jason Gunthorpe
2021-06-14 14:36     ` [Intel-gfx] " Jason Gunthorpe
2021-06-14 14:36     ` Jason Gunthorpe
2021-06-14 15:08 Allow mdev drivers to directly create the vfio_device (v2 / alternative) Christoph Hellwig
2021-06-14 15:08 ` [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev() Christoph Hellwig
2021-06-15 13:35 Allow mdev drivers to directly create the vfio_device (v3) Christoph Hellwig
2021-06-15 13:35 ` [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev() Christoph Hellwig
2021-06-15 14:12   ` Greg Kroah-Hartman
2021-06-15 14:12     ` Greg Kroah-Hartman
2021-06-17 14:22 Allow mdev drivers to directly create the vfio_device (v4) Christoph Hellwig
2021-06-17 14:22 ` [PATCH 10/10] vfio/mbochs: Convert to use vfio_register_group_dev() Christoph Hellwig

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.