linux-s390.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* simplify the mdev interface v8
@ 2022-09-23  9:26 Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 01/14] drm/i915/gvt: fix a memory leak in intel_gvt_init_vgpu_types Christoph Hellwig
                   ` (14 more replies)
  0 siblings, 15 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

Hi all,

this series significantly simplifies the mdev driver interface by
following the patterns for device model interaction used elsewhere in
the kernel.

Changes since v7:
 - rebased to the latests vfio/next branch
 - move the mdev.h include from cio.h to vfio_ccw_private.h
 - don't free the parent in mdev_type_release
 - set the pretty_name for vfio_ap
 - fix the available_instances check in mdev_device_create

Changes since v6:
 - rebased to Linux 6.0-rc2
 - folded in a patch from Eric Farman to fix the placement of the new
   embedded mdev structured in the s390 cio driver

Changes since v5:
 - rebased to the latest vfio/next branch
 - drop the last patch again
 - make sure show_available_instances works properly for the internallly
   tracked case

Changes since v4:
 - move the kobject_put later in mdev_device_release 
 - add a Fixes tag for the first patch
 - add another patch to remove an extra kobject_get/put

Changes since v3:
 - make the sysfs_name and pretty_name fields pointers instead of arrays
 - add an i915 cleanup to prepare for the above

Changes since v2:
 - rebased to vfio/next
 - fix a pre-existing memory leak in i915 instead of making it worse
 - never manipulate if ->available_instances if drv->get_available is
   provided
 - keep a parent reference for the mdev_type
 - keep a few of the sysfs.c helper function around
 - improve the documentation for the parent device lifetime
 - minor spellig / formatting fixes

Changes since v1:
 - embedd the mdev_parent into a different sub-structure in i916
 - remove headers now inclued by mdev.h from individual source files
 - pass an array of mdev_types to mdev_register_parent
 - add additional patches to implement all attributes on the
   mdev_type in the core code

Diffstat:
 Documentation/driver-api/vfio-mediated-device.rst |   26 +-
 Documentation/s390/vfio-ap.rst                    |    2 
 Documentation/s390/vfio-ccw.rst                   |    2 
 drivers/gpu/drm/i915/gvt/aperture_gm.c            |   20 +-
 drivers/gpu/drm/i915/gvt/gvt.h                    |   42 ++--
 drivers/gpu/drm/i915/gvt/kvmgt.c                  |  168 ++++-------------
 drivers/gpu/drm/i915/gvt/vgpu.c                   |  210 +++++++---------------
 drivers/s390/cio/cio.h                            |    1 
 drivers/s390/cio/vfio_ccw_drv.c                   |   12 -
 drivers/s390/cio/vfio_ccw_ops.c                   |   51 -----
 drivers/s390/cio/vfio_ccw_private.h               |    6 
 drivers/s390/crypto/vfio_ap_ops.c                 |   68 +------
 drivers/s390/crypto/vfio_ap_private.h             |    6 
 drivers/vfio/mdev/mdev_core.c                     |  190 ++++---------------
 drivers/vfio/mdev/mdev_driver.c                   |    7 
 drivers/vfio/mdev/mdev_private.h                  |   32 ---
 drivers/vfio/mdev/mdev_sysfs.c                    |  189 ++++++++++---------
 include/linux/mdev.h                              |   77 ++++----
 samples/vfio-mdev/mbochs.c                        |  103 +++-------
 samples/vfio-mdev/mdpy.c                          |  115 +++---------
 samples/vfio-mdev/mtty.c                          |   94 +++------
 21 files changed, 464 insertions(+), 957 deletions(-)

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

* [PATCH 01/14] drm/i915/gvt: fix a memory leak in intel_gvt_init_vgpu_types
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 02/14] drm/i915/gvt: simplify vgpu configuration management Christoph Hellwig
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

gvt->types needs to be freed on error.

Fixes: c90d097ae144 ("drm/i915/gvt: define weight according to vGPU type")
Reported-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
---
 drivers/gpu/drm/i915/gvt/vgpu.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 5c533fbc2c8da..dbb2a971ba5d8 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -142,7 +142,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 
 		if (vgpu_types[i].weight < 1 ||
 					vgpu_types[i].weight > VGPU_MAX_WEIGHT)
-			return -EINVAL;
+			goto out_free_types;
 
 		gvt->types[i].weight = vgpu_types[i].weight;
 		gvt->types[i].resolution = vgpu_types[i].edid;
@@ -167,6 +167,10 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 
 	gvt->num_types = i;
 	return 0;
+
+out_free_types:
+	kfree(gvt->types);
+	return -EINVAL;
 }
 
 void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
-- 
2.30.2


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

* [PATCH 02/14] drm/i915/gvt: simplify vgpu configuration management
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 01/14] drm/i915/gvt: fix a memory leak in intel_gvt_init_vgpu_types Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 03/14] vfio/mdev: make mdev.h standalone includable Christoph Hellwig
                   ` (12 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

Instead of copying the information from the vgpu_types arrays into each
intel_vgpu_type structure, just reference this constant information
with a pointer to the already existing data structure, and pass it into
the low-level VGPU creation helpers intead of copying the data into yet
anothe params data structure.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>
---
 drivers/gpu/drm/i915/gvt/aperture_gm.c |  20 ++--
 drivers/gpu/drm/i915/gvt/gvt.h         |  37 +++---
 drivers/gpu/drm/i915/gvt/kvmgt.c       |  10 +-
 drivers/gpu/drm/i915/gvt/vgpu.c        | 159 ++++++++-----------------
 4 files changed, 81 insertions(+), 145 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
index 3b81a6d35a7b2..076c779f776a6 100644
--- a/drivers/gpu/drm/i915/gvt/aperture_gm.c
+++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c
@@ -240,13 +240,13 @@ static void free_resource(struct intel_vgpu *vgpu)
 }
 
 static int alloc_resource(struct intel_vgpu *vgpu,
-		struct intel_vgpu_creation_params *param)
+		const struct intel_vgpu_config *conf)
 {
 	struct intel_gvt *gvt = vgpu->gvt;
 	unsigned long request, avail, max, taken;
 	const char *item;
 
-	if (!param->low_gm_sz || !param->high_gm_sz || !param->fence_sz) {
+	if (!conf->low_mm || !conf->high_mm || !conf->fence) {
 		gvt_vgpu_err("Invalid vGPU creation params\n");
 		return -EINVAL;
 	}
@@ -255,7 +255,7 @@ static int alloc_resource(struct intel_vgpu *vgpu,
 	max = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
 	taken = gvt->gm.vgpu_allocated_low_gm_size;
 	avail = max - taken;
-	request = MB_TO_BYTES(param->low_gm_sz);
+	request = conf->low_mm;
 
 	if (request > avail)
 		goto no_enough_resource;
@@ -266,7 +266,7 @@ static int alloc_resource(struct intel_vgpu *vgpu,
 	max = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
 	taken = gvt->gm.vgpu_allocated_high_gm_size;
 	avail = max - taken;
-	request = MB_TO_BYTES(param->high_gm_sz);
+	request = conf->high_mm;
 
 	if (request > avail)
 		goto no_enough_resource;
@@ -277,16 +277,16 @@ static int alloc_resource(struct intel_vgpu *vgpu,
 	max = gvt_fence_sz(gvt) - HOST_FENCE;
 	taken = gvt->fence.vgpu_allocated_fence_num;
 	avail = max - taken;
-	request = param->fence_sz;
+	request = conf->fence;
 
 	if (request > avail)
 		goto no_enough_resource;
 
 	vgpu_fence_sz(vgpu) = request;
 
-	gvt->gm.vgpu_allocated_low_gm_size += MB_TO_BYTES(param->low_gm_sz);
-	gvt->gm.vgpu_allocated_high_gm_size += MB_TO_BYTES(param->high_gm_sz);
-	gvt->fence.vgpu_allocated_fence_num += param->fence_sz;
+	gvt->gm.vgpu_allocated_low_gm_size += conf->low_mm;
+	gvt->gm.vgpu_allocated_high_gm_size += conf->high_mm;
+	gvt->fence.vgpu_allocated_fence_num += conf->fence;
 	return 0;
 
 no_enough_resource:
@@ -340,11 +340,11 @@ void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
  *
  */
 int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
-		struct intel_vgpu_creation_params *param)
+		const struct intel_vgpu_config *conf)
 {
 	int ret;
 
-	ret = alloc_resource(vgpu, param);
+	ret = alloc_resource(vgpu, conf);
 	if (ret)
 		return ret;
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 89fab7896fc6a..563ffc2fdfb7a 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -294,15 +294,26 @@ struct intel_gvt_firmware {
 	bool firmware_loaded;
 };
 
+struct intel_vgpu_config {
+	unsigned int low_mm;
+	unsigned int high_mm;
+	unsigned int fence;
+
+	/*
+	 * A vGPU with a weight of 8 will get twice as much GPU as a vGPU with
+	 * a weight of 4 on a contended host, different vGPU type has different
+	 * weight set. Legal weights range from 1 to 16.
+	 */
+	unsigned int weight;
+	enum intel_vgpu_edid edid;
+	const char *name;
+};
+
 #define NR_MAX_INTEL_VGPU_TYPES 20
 struct intel_vgpu_type {
 	char name[16];
+	const struct intel_vgpu_config *conf;
 	unsigned int avail_instance;
-	unsigned int low_gm_size;
-	unsigned int high_gm_size;
-	unsigned int fence;
-	unsigned int weight;
-	enum intel_vgpu_edid resolution;
 };
 
 struct intel_gvt {
@@ -436,19 +447,8 @@ int intel_gvt_load_firmware(struct intel_gvt *gvt);
 /* ring context size i.e. the first 0x50 dwords*/
 #define RING_CTX_SIZE 320
 
-struct intel_vgpu_creation_params {
-	__u64 low_gm_sz;  /* in MB */
-	__u64 high_gm_sz; /* in MB */
-	__u64 fence_sz;
-	__u64 resolution;
-	__s32 primary;
-	__u64 vgpu_id;
-
-	__u32 weight;
-};
-
 int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
-			      struct intel_vgpu_creation_params *param);
+			      const struct intel_vgpu_config *conf);
 void intel_vgpu_reset_resource(struct intel_vgpu *vgpu);
 void intel_vgpu_free_resource(struct intel_vgpu *vgpu);
 void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
@@ -494,7 +494,8 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt);
 
 struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt);
 void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu);
-int intel_gvt_create_vgpu(struct intel_vgpu *vgpu, struct intel_vgpu_type *type);
+int intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
+			  const struct intel_vgpu_config *conf);
 void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
 void intel_gvt_release_vgpu(struct intel_vgpu *vgpu);
 void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 41bba40feef8f..aa329f8bfe420 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -151,10 +151,10 @@ static ssize_t description_show(struct mdev_type *mtype,
 	return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
 		       "fence: %d\nresolution: %s\n"
 		       "weight: %d\n",
-		       BYTES_TO_MB(type->low_gm_size),
-		       BYTES_TO_MB(type->high_gm_size),
-		       type->fence, vgpu_edid_str(type->resolution),
-		       type->weight);
+		       BYTES_TO_MB(type->conf->low_mm),
+		       BYTES_TO_MB(type->conf->high_mm),
+		       type->conf->fence, vgpu_edid_str(type->conf->edid),
+		       type->conf->weight);
 }
 
 static ssize_t name_show(struct mdev_type *mtype,
@@ -1559,7 +1559,7 @@ static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
 		return -EINVAL;
 
 	vgpu->gvt = gvt;
-	return intel_gvt_create_vgpu(vgpu, type);
+	return intel_gvt_create_vgpu(vgpu, type->conf);
 }
 
 static void intel_vgpu_release_dev(struct vfio_device *vfio_dev)
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index dbb2a971ba5d8..1b67328c714f1 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -73,24 +73,21 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
 	drm_WARN_ON(&i915->drm, sizeof(struct vgt_if) != VGT_PVINFO_SIZE);
 }
 
+/*
+ * vGPU type name is defined as GVTg_Vx_y which contains the physical GPU
+ * generation type (e.g V4 as BDW server, V5 as SKL server).
+ *
+ * Depening on the physical SKU resource, we might see vGPU types like
+ * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create different types of
+ * vGPU on same physical GPU depending on available resource. Each vGPU
+ * type will have a different number of avail_instance to indicate how
+ * many vGPU instance can be created for this type.
+ */
 #define VGPU_MAX_WEIGHT 16
 #define VGPU_WEIGHT(vgpu_num)	\
 	(VGPU_MAX_WEIGHT / (vgpu_num))
 
-static const struct {
-	unsigned int low_mm;
-	unsigned int high_mm;
-	unsigned int fence;
-
-	/* A vGPU with a weight of 8 will get twice as much GPU as a vGPU
-	 * with a weight of 4 on a contended host, different vGPU type has
-	 * different weight set. Legal weights range from 1 to 16.
-	 */
-	unsigned int weight;
-	enum intel_vgpu_edid edid;
-	const char *name;
-} vgpu_types[] = {
-/* Fixed vGPU type table */
+static const struct intel_vgpu_config intel_vgpu_configs[] = {
 	{ MB_TO_BYTES(64), MB_TO_BYTES(384), 4, VGPU_WEIGHT(8), GVT_EDID_1024_768, "8" },
 	{ MB_TO_BYTES(128), MB_TO_BYTES(512), 4, VGPU_WEIGHT(4), GVT_EDID_1920_1200, "4" },
 	{ MB_TO_BYTES(256), MB_TO_BYTES(1024), 4, VGPU_WEIGHT(2), GVT_EDID_1920_1200, "2" },
@@ -106,63 +103,34 @@ static const struct {
  */
 int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 {
-	unsigned int num_types;
-	unsigned int i, low_avail, high_avail;
-	unsigned int min_low;
-
-	/* vGPU type name is defined as GVTg_Vx_y which contains
-	 * physical GPU generation type (e.g V4 as BDW server, V5 as
-	 * SKL server).
-	 *
-	 * Depend on physical SKU resource, might see vGPU types like
-	 * GVTg_V4_8, GVTg_V4_4, GVTg_V4_2, etc. We can create
-	 * different types of vGPU on same physical GPU depending on
-	 * available resource. Each vGPU type will have "avail_instance"
-	 * to indicate how many vGPU instance can be created for this
-	 * type.
-	 *
-	 */
-	low_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
-	high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
-	num_types = ARRAY_SIZE(vgpu_types);
+	unsigned int low_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE;
+	unsigned int high_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE;
+	unsigned int num_types = ARRAY_SIZE(intel_vgpu_configs);
+	unsigned int i;
 
 	gvt->types = kcalloc(num_types, sizeof(struct intel_vgpu_type),
 			     GFP_KERNEL);
 	if (!gvt->types)
 		return -ENOMEM;
 
-	min_low = MB_TO_BYTES(32);
 	for (i = 0; i < num_types; ++i) {
-		if (low_avail / vgpu_types[i].low_mm == 0)
-			break;
-
-		gvt->types[i].low_gm_size = vgpu_types[i].low_mm;
-		gvt->types[i].high_gm_size = vgpu_types[i].high_mm;
-		gvt->types[i].fence = vgpu_types[i].fence;
+		const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];
 
-		if (vgpu_types[i].weight < 1 ||
-					vgpu_types[i].weight > VGPU_MAX_WEIGHT)
+		if (low_avail / conf->low_mm == 0)
+			break;
+		if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)
 			goto out_free_types;
 
-		gvt->types[i].weight = vgpu_types[i].weight;
-		gvt->types[i].resolution = vgpu_types[i].edid;
-		gvt->types[i].avail_instance = min(low_avail / vgpu_types[i].low_mm,
-						   high_avail / vgpu_types[i].high_mm);
-
-		if (GRAPHICS_VER(gvt->gt->i915) == 8)
-			sprintf(gvt->types[i].name, "GVTg_V4_%s",
-				vgpu_types[i].name);
-		else if (GRAPHICS_VER(gvt->gt->i915) == 9)
-			sprintf(gvt->types[i].name, "GVTg_V5_%s",
-				vgpu_types[i].name);
+		sprintf(gvt->types[i].name, "GVTg_V%u_%s",
+			GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
+		gvt->types->conf = conf;
+		gvt->types[i].avail_instance = min(low_avail / conf->low_mm,
+						   high_avail / conf->high_mm);
 
 		gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u weight %u res %s\n",
-			     i, gvt->types[i].name,
-			     gvt->types[i].avail_instance,
-			     gvt->types[i].low_gm_size,
-			     gvt->types[i].high_gm_size, gvt->types[i].fence,
-			     gvt->types[i].weight,
-			     vgpu_edid_str(gvt->types[i].resolution));
+			     i, gvt->types[i].name, gvt->types[i].avail_instance,
+			     conf->low_mm, conf->high_mm, conf->fence,
+			     conf->weight, vgpu_edid_str(conf->edid));
 	}
 
 	gvt->num_types = i;
@@ -195,16 +163,16 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
 		gvt->fence.vgpu_allocated_fence_num;
 
 	for (i = 0; i < gvt->num_types; i++) {
-		low_gm_min = low_gm_avail / gvt->types[i].low_gm_size;
-		high_gm_min = high_gm_avail / gvt->types[i].high_gm_size;
-		fence_min = fence_avail / gvt->types[i].fence;
+		low_gm_min = low_gm_avail / gvt->types[i].conf->low_mm;
+		high_gm_min = high_gm_avail / gvt->types[i].conf->high_mm;
+		fence_min = fence_avail / gvt->types[i].conf->fence;
 		gvt->types[i].avail_instance = min(min(low_gm_min, high_gm_min),
 						   fence_min);
 
 		gvt_dbg_core("update type[%d]: %s avail %u low %u high %u fence %u\n",
 		       i, gvt->types[i].name,
-		       gvt->types[i].avail_instance, gvt->types[i].low_gm_size,
-		       gvt->types[i].high_gm_size, gvt->types[i].fence);
+		       gvt->types[i].avail_instance, gvt->types[i].conf->low_mm,
+		       gvt->types[i].conf->high_mm, gvt->types[i].conf->fence);
 	}
 }
 
@@ -365,37 +333,38 @@ void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu)
 	vfree(vgpu);
 }
 
-static int __intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
-				   struct intel_vgpu_creation_params *param)
+int intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
+		const struct intel_vgpu_config *conf)
 {
 	struct intel_gvt *gvt = vgpu->gvt;
 	struct drm_i915_private *dev_priv = gvt->gt->i915;
 	int ret;
 
-	gvt_dbg_core("low %llu MB high %llu MB fence %llu\n",
-			param->low_gm_sz, param->high_gm_sz,
-			param->fence_sz);
+	gvt_dbg_core("low %u MB high %u MB fence %u\n",
+			BYTES_TO_MB(conf->low_mm), BYTES_TO_MB(conf->high_mm),
+			conf->fence);
 
+	mutex_lock(&gvt->lock);
 	ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU,
 		GFP_KERNEL);
 	if (ret < 0)
-		return ret;
+		goto out_unlock;;
 
 	vgpu->id = ret;
-	vgpu->sched_ctl.weight = param->weight;
+	vgpu->sched_ctl.weight = conf->weight;
 	mutex_init(&vgpu->vgpu_lock);
 	mutex_init(&vgpu->dmabuf_lock);
 	INIT_LIST_HEAD(&vgpu->dmabuf_obj_list_head);
 	INIT_RADIX_TREE(&vgpu->page_track_tree, GFP_KERNEL);
 	idr_init_base(&vgpu->object_idr, 1);
-	intel_vgpu_init_cfg_space(vgpu, param->primary);
+	intel_vgpu_init_cfg_space(vgpu, 1);
 	vgpu->d3_entered = false;
 
 	ret = intel_vgpu_init_mmio(vgpu);
 	if (ret)
 		goto out_clean_idr;
 
-	ret = intel_vgpu_alloc_resource(vgpu, param);
+	ret = intel_vgpu_alloc_resource(vgpu, conf);
 	if (ret)
 		goto out_clean_vgpu_mmio;
 
@@ -409,7 +378,7 @@ static int __intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
 	if (ret)
 		goto out_clean_gtt;
 
-	ret = intel_vgpu_init_display(vgpu, param->resolution);
+	ret = intel_vgpu_init_display(vgpu, conf->edid);
 	if (ret)
 		goto out_clean_opregion;
 
@@ -434,6 +403,9 @@ static int __intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
 	if (ret)
 		goto out_clean_sched_policy;
 
+	intel_gvt_update_vgpu_types(gvt);
+	intel_gvt_update_reg_whitelist(vgpu);
+	mutex_unlock(&gvt->lock);
 	return 0;
 
 out_clean_sched_policy:
@@ -452,45 +424,8 @@ static int __intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
 	intel_vgpu_clean_mmio(vgpu);
 out_clean_idr:
 	idr_remove(&gvt->vgpu_idr, vgpu->id);
-	return ret;
-}
-
-/**
- * intel_gvt_create_vgpu - create a virtual GPU
- * @gvt: GVT device
- * @type: type of the vGPU to create
- *
- * This function is called when user wants to create a virtual GPU.
- *
- * Returns:
- * pointer to intel_vgpu, error pointer if failed.
- */
-int intel_gvt_create_vgpu(struct intel_vgpu *vgpu, struct intel_vgpu_type *type)
-{
-	struct intel_gvt *gvt = vgpu->gvt;
-	struct intel_vgpu_creation_params param;
-	int ret;
-
-	param.primary = 1;
-	param.low_gm_sz = type->low_gm_size;
-	param.high_gm_sz = type->high_gm_size;
-	param.fence_sz = type->fence;
-	param.weight = type->weight;
-	param.resolution = type->resolution;
-
-	/* XXX current param based on MB */
-	param.low_gm_sz = BYTES_TO_MB(param.low_gm_sz);
-	param.high_gm_sz = BYTES_TO_MB(param.high_gm_sz);
-
-	mutex_lock(&gvt->lock);
-	ret = __intel_gvt_create_vgpu(vgpu, &param);
-	if (!ret) {
-		/* calculate left instance change for types */
-		intel_gvt_update_vgpu_types(gvt);
-		intel_gvt_update_reg_whitelist(vgpu);
-	}
+out_unlock:
 	mutex_unlock(&gvt->lock);
-
 	return ret;
 }
 
-- 
2.30.2


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

* [PATCH 03/14] vfio/mdev: make mdev.h standalone includable
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 01/14] drm/i915/gvt: fix a memory leak in intel_gvt_init_vgpu_types Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 02/14] drm/i915/gvt: simplify vgpu configuration management Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure Christoph Hellwig
                   ` (11 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Include <linux/device.h> and <linux/uuid.h> so that users of this headers
don't need to do that and remove those includes that aren't needed
any more.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Eric Farman <farman@linux.ibm.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed By: Kirti Wankhede <kwankhede@nvidia.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c      | 2 --
 drivers/s390/cio/vfio_ccw_drv.c       | 1 -
 drivers/s390/crypto/vfio_ap_private.h | 1 -
 drivers/vfio/mdev/mdev_core.c         | 2 --
 drivers/vfio/mdev/mdev_driver.c       | 1 -
 drivers/vfio/mdev/mdev_sysfs.c        | 2 --
 include/linux/mdev.h                  | 3 +++
 samples/vfio-mdev/mbochs.c            | 1 -
 samples/vfio-mdev/mdpy.c              | 1 -
 samples/vfio-mdev/mtty.c              | 2 --
 10 files changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index aa329f8bfe420..68f022c4aafbc 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -34,7 +34,6 @@
  */
 
 #include <linux/init.h>
-#include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/kthread.h>
 #include <linux/sched/mm.h>
@@ -43,7 +42,6 @@
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
 #include <linux/eventfd.h>
-#include <linux/uuid.h>
 #include <linux/mdev.h>
 #include <linux/debugfs.h>
 
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 86d9e428357b0..e9985c63dc6bf 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -12,7 +12,6 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/mdev.h>
 
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index d782cf463eaba..163eeaaf24cee 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -13,7 +13,6 @@
 #define _VFIO_AP_PRIVATE_H_
 
 #include <linux/types.h>
-#include <linux/device.h>
 #include <linux/mdev.h>
 #include <linux/delay.h>
 #include <linux/mutex.h>
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index b8b9e7911e559..2c32923fbad27 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -8,9 +8,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/device.h>
 #include <linux/slab.h>
-#include <linux/uuid.h>
 #include <linux/sysfs.h>
 #include <linux/mdev.h>
 
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 9c2af59809e2e..7bd4bb9850e81 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -7,7 +7,6 @@
  *             Kirti Wankhede <kwankhede@nvidia.com>
  */
 
-#include <linux/device.h>
 #include <linux/iommu.h>
 #include <linux/mdev.h>
 
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 0ccfeb3dda245..4bfbf49aaa66a 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -9,9 +9,7 @@
 
 #include <linux/sysfs.h>
 #include <linux/ctype.h>
-#include <linux/device.h>
 #include <linux/slab.h>
-#include <linux/uuid.h>
 #include <linux/mdev.h>
 
 #include "mdev_private.h"
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 47ad3b104d9e7..a5d8ae6132a20 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -10,6 +10,9 @@
 #ifndef MDEV_H
 #define MDEV_H
 
+#include <linux/device.h>
+#include <linux/uuid.h>
+
 struct mdev_type;
 
 struct mdev_device {
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 6901947e27d2d..985b6e7136219 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -21,7 +21,6 @@
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index bb2af1ec0f7c6..1daab012b5d89 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -17,7 +17,6 @@
  */
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index d151928e4f21d..86843ce3d9a27 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -12,7 +12,6 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <linux/device.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
 #include <linux/poll.h>
@@ -20,7 +19,6 @@
 #include <linux/cdev.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
-#include <linux/uuid.h>
 #include <linux/vfio.h>
 #include <linux/iommu.h>
 #include <linux/sysfs.h>
-- 
2.30.2


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

* [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (2 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 03/14] vfio/mdev: make mdev.h standalone includable Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 05/14] vfio/mdev: simplify mdev_type handling Christoph Hellwig
                   ` (10 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Simplify mdev_{un}register_device by requiring the caller to pass in
a structure allocate as part of the parent device structure.  This
removes the need for a list of parents and the separate mdev_parent
refcount as we can simplify rely on the reference to the parent device.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |  12 +-
 Documentation/s390/vfio-ap.rst                |   2 +-
 Documentation/s390/vfio-ccw.rst               |   2 +-
 drivers/gpu/drm/i915/gvt/gvt.h                |   2 +
 drivers/gpu/drm/i915/gvt/kvmgt.c              |   5 +-
 drivers/s390/cio/vfio_ccw_drv.c               |   5 +-
 drivers/s390/cio/vfio_ccw_ops.c               |   1 -
 drivers/s390/cio/vfio_ccw_private.h           |   4 +
 drivers/s390/crypto/vfio_ap_ops.c             |   5 +-
 drivers/s390/crypto/vfio_ap_private.h         |   1 +
 drivers/vfio/mdev/mdev_core.c                 | 120 ++++--------------
 drivers/vfio/mdev/mdev_private.h              |  23 ----
 drivers/vfio/mdev/mdev_sysfs.c                |   4 +-
 include/linux/mdev.h                          |  15 ++-
 samples/vfio-mdev/mbochs.c                    |   5 +-
 samples/vfio-mdev/mdpy.c                      |   5 +-
 samples/vfio-mdev/mtty.c                      |   6 +-
 17 files changed, 71 insertions(+), 146 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index f47dca6645aae..cd1667608ab5d 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -58,19 +58,19 @@ devices as examples, as these devices are the first devices to use this module::
      |  MDEV CORE    |
      |   MODULE      |
      |   mdev.ko     |
-     | +-----------+ |  mdev_register_device() +--------------+
+     | +-----------+ |  mdev_register_parent() +--------------+
      | |           | +<------------------------+              |
      | |           | |                         |  nvidia.ko   |<-> physical
      | |           | +------------------------>+              |    device
      | |           | |        callbacks        +--------------+
      | | Physical  | |
-     | |  device   | |  mdev_register_device() +--------------+
+     | |  device   | |  mdev_register_parent() +--------------+
      | | interface | |<------------------------+              |
      | |           | |                         |  i915.ko     |<-> physical
      | |           | +------------------------>+              |    device
      | |           | |        callbacks        +--------------+
      | |           | |
-     | |           | |  mdev_register_device() +--------------+
+     | |           | |  mdev_register_parent() +--------------+
      | |           | +<------------------------+              |
      | |           | |                         | ccw_device.ko|<-> physical
      | |           | +------------------------>+              |    device
@@ -125,8 +125,8 @@ vfio_device_ops.
 When a driver wants to add the GUID creation sysfs to an existing device it has
 probe'd to then it should call::
 
-    int mdev_register_device(struct device *dev,
-                             struct mdev_driver *mdev_driver);
+    int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
+			struct mdev_driver *mdev_driver);
 
 This will provide the 'mdev_supported_types/XX/create' files which can then be
 used to trigger the creation of a mdev_device. The created mdev_device will be
@@ -134,7 +134,7 @@ attached to the specified driver.
 
 When the driver needs to remove itself it calls::
 
-    void mdev_unregister_device(struct device *dev);
+    void mdev_unregister_parent(struct mdev_parent *parent);
 
 Which will unbind and destroy all the created mdevs and remove the sysfs files.
 
diff --git a/Documentation/s390/vfio-ap.rst b/Documentation/s390/vfio-ap.rst
index 61a0a3c6c7b4b..00f4a04f6d4c6 100644
--- a/Documentation/s390/vfio-ap.rst
+++ b/Documentation/s390/vfio-ap.rst
@@ -297,7 +297,7 @@ of the VFIO AP mediated device driver::
    |  MDEV CORE  |
    |   MODULE    |
    |   mdev.ko   |
-   | +---------+ | mdev_register_device() +--------------+
+   | +---------+ | mdev_register_parent() +--------------+
    | |Physical | +<-----------------------+              |
    | | device  | |                        |  vfio_ap.ko  |<-> matrix
    | |interface| +----------------------->+              |    device
diff --git a/Documentation/s390/vfio-ccw.rst b/Documentation/s390/vfio-ccw.rst
index 8aad08a8b8a50..ea928a3806f43 100644
--- a/Documentation/s390/vfio-ccw.rst
+++ b/Documentation/s390/vfio-ccw.rst
@@ -156,7 +156,7 @@ Below is a high Level block diagram::
  |  MDEV CORE  |
  |   MODULE    |
  |   mdev.ko   |
- | +---------+ | mdev_register_device() +--------------+
+ | +---------+ | mdev_register_parent() +--------------+
  | |Physical | +<-----------------------+              |
  | | device  | |                        |  vfio_ccw.ko |<-> subchannel
  | |interface| +----------------------->+              |     device
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index 563ffc2fdfb7a..fa4a56b50c828 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -36,6 +36,7 @@
 #include <uapi/linux/pci_regs.h>
 #include <linux/kvm_host.h>
 #include <linux/vfio.h>
+#include <linux/mdev.h>
 
 #include "i915_drv.h"
 #include "intel_gvt.h"
@@ -337,6 +338,7 @@ struct intel_gvt {
 	struct intel_gvt_workload_scheduler scheduler;
 	struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
 	DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
+	struct mdev_parent parent;
 	struct intel_vgpu_type *types;
 	unsigned int num_types;
 	struct intel_vgpu *idle_vgpu;
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 68f022c4aafbc..29531b797010f 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1922,7 +1922,7 @@ static void intel_gvt_clean_device(struct drm_i915_private *i915)
 	if (drm_WARN_ON(&i915->drm, !gvt))
 		return;
 
-	mdev_unregister_device(i915->drm.dev);
+	mdev_unregister_parent(&gvt->parent);
 	intel_gvt_cleanup_vgpu_type_groups(gvt);
 	intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
 	intel_gvt_clean_vgpu_types(gvt);
@@ -2027,7 +2027,8 @@ static int intel_gvt_init_device(struct drm_i915_private *i915)
 	if (ret)
 		goto out_destroy_idle_vgpu;
 
-	ret = mdev_register_device(i915->drm.dev, &intel_vgpu_mdev_driver);
+	ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
+				   &intel_vgpu_mdev_driver);
 	if (ret)
 		goto out_cleanup_vgpu_type_groups;
 
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index e9985c63dc6bf..7d105915bd149 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -221,7 +221,8 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 
 	dev_set_drvdata(&sch->dev, private);
 
-	ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
+	ret = mdev_register_parent(&private->parent, &sch->dev,
+				   &vfio_ccw_mdev_driver);
 	if (ret)
 		goto out_free;
 
@@ -240,7 +241,7 @@ static void vfio_ccw_sch_remove(struct subchannel *sch)
 {
 	struct vfio_ccw_private *private = dev_get_drvdata(&sch->dev);
 
-	mdev_unregister_device(&sch->dev);
+	mdev_unregister_parent(&private->parent);
 
 	dev_set_drvdata(&sch->dev, NULL);
 
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 9f8486c0d3d37..9a0e0c5ffb1a5 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -11,7 +11,6 @@
  */
 
 #include <linux/vfio.h>
-#include <linux/mdev.h>
 #include <linux/nospec.h>
 #include <linux/slab.h>
 
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index 63d9202b29c7f..1a4bfb1b5a808 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -18,6 +18,7 @@
 #include <linux/workqueue.h>
 #include <linux/vfio_ccw.h>
 #include <linux/vfio.h>
+#include <linux/mdev.h>
 #include <asm/crw.h>
 #include <asm/debug.h>
 
@@ -89,6 +90,7 @@ struct vfio_ccw_crw {
  * @io_work: work for deferral process of I/O handling
  * @crw_work: work for deferral process of CRW handling
  * @release_comp: synchronization helper for vfio device release
+ * @parent: parent data structures for mdevs created
  */
 struct vfio_ccw_private {
 	struct vfio_device vdev;
@@ -116,6 +118,8 @@ struct vfio_ccw_private {
 	struct work_struct	crw_work;
 
 	struct completion	release_comp;
+
+	struct mdev_parent	parent;
 } __aligned(8);
 
 int vfio_ccw_sch_quiesce(struct subchannel *sch);
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 161597357a642..724d09a74a8f1 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -1830,7 +1830,8 @@ int vfio_ap_mdev_register(void)
 	if (ret)
 		return ret;
 
-	ret = mdev_register_device(&matrix_dev->device, &vfio_ap_matrix_driver);
+	ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,
+				   &vfio_ap_matrix_driver);
 	if (ret)
 		goto err_driver;
 	return 0;
@@ -1842,7 +1843,7 @@ int vfio_ap_mdev_register(void)
 
 void vfio_ap_mdev_unregister(void)
 {
-	mdev_unregister_device(&matrix_dev->device);
+	mdev_unregister_parent(&matrix_dev->parent);
 	mdev_unregister_driver(&vfio_ap_matrix_driver);
 }
 
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 163eeaaf24cee..35165730f5174 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -52,6 +52,7 @@ struct ap_matrix_dev {
 	struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */
 	struct ap_driver  *vfio_ap_drv;
 	struct mutex guests_lock; /* serializes access to each KVM guest */
+	struct mdev_parent parent;
 };
 
 extern struct ap_matrix_dev *matrix_dev;
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 2c32923fbad27..fa05ac3396950 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -18,8 +18,6 @@
 #define DRIVER_AUTHOR		"NVIDIA Corporation"
 #define DRIVER_DESC		"Mediated device Core Driver"
 
-static LIST_HEAD(parent_list);
-static DEFINE_MUTEX(parent_list_lock);
 static struct class_compat *mdev_bus_compat_class;
 
 static LIST_HEAD(mdev_list);
@@ -61,28 +59,6 @@ struct device *mtype_get_parent_dev(struct mdev_type *mtype)
 }
 EXPORT_SYMBOL(mtype_get_parent_dev);
 
-/* Should be called holding parent_list_lock */
-static struct mdev_parent *__find_parent_device(struct device *dev)
-{
-	struct mdev_parent *parent;
-
-	list_for_each_entry(parent, &parent_list, next) {
-		if (parent->dev == dev)
-			return parent;
-	}
-	return NULL;
-}
-
-void mdev_release_parent(struct kref *kref)
-{
-	struct mdev_parent *parent = container_of(kref, struct mdev_parent,
-						  ref);
-	struct device *dev = parent->dev;
-
-	kfree(parent);
-	put_device(dev);
-}
-
 /* Caller must hold parent unreg_sem read or write lock */
 static void mdev_device_remove_common(struct mdev_device *mdev)
 {
@@ -105,125 +81,73 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
 }
 
 /*
- * mdev_register_device : Register a device
+ * mdev_register_parent: Register a device as parent for mdevs
+ * @parent: parent structure registered
  * @dev: device structure representing parent device.
  * @mdev_driver: Device driver to bind to the newly created mdev
  *
- * Add device to list of registered parent devices.
+ * Registers the @parent stucture as a parent for mdev types and thus mdev
+ * devices.  The caller needs to hold a reference on @dev that must not be
+ * released until after the call to mdev_unregister_parent().
+ *
  * Returns a negative value on error, otherwise 0.
  */
-int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver)
+int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
+		struct mdev_driver *mdev_driver)
 {
-	int ret;
-	struct mdev_parent *parent;
 	char *env_string = "MDEV_STATE=registered";
 	char *envp[] = { env_string, NULL };
+	int ret;
 
 	/* check for mandatory ops */
 	if (!mdev_driver->supported_type_groups)
 		return -EINVAL;
 
-	dev = get_device(dev);
-	if (!dev)
-		return -EINVAL;
-
-	mutex_lock(&parent_list_lock);
-
-	/* Check for duplicate */
-	parent = __find_parent_device(dev);
-	if (parent) {
-		parent = NULL;
-		ret = -EEXIST;
-		goto add_dev_err;
-	}
-
-	parent = kzalloc(sizeof(*parent), GFP_KERNEL);
-	if (!parent) {
-		ret = -ENOMEM;
-		goto add_dev_err;
-	}
-
-	kref_init(&parent->ref);
+	memset(parent, 0, sizeof(*parent));
 	init_rwsem(&parent->unreg_sem);
-
 	parent->dev = dev;
 	parent->mdev_driver = mdev_driver;
 
 	if (!mdev_bus_compat_class) {
 		mdev_bus_compat_class = class_compat_register("mdev_bus");
-		if (!mdev_bus_compat_class) {
-			ret = -ENOMEM;
-			goto add_dev_err;
-		}
+		if (!mdev_bus_compat_class)
+			return -ENOMEM;
 	}
 
 	ret = parent_create_sysfs_files(parent);
 	if (ret)
-		goto add_dev_err;
+		return ret;
 
 	ret = class_compat_create_link(mdev_bus_compat_class, dev, NULL);
 	if (ret)
 		dev_warn(dev, "Failed to create compatibility class link\n");
 
-	list_add(&parent->next, &parent_list);
-	mutex_unlock(&parent_list_lock);
-
 	dev_info(dev, "MDEV: Registered\n");
 	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
-
 	return 0;
-
-add_dev_err:
-	mutex_unlock(&parent_list_lock);
-	if (parent)
-		mdev_put_parent(parent);
-	else
-		put_device(dev);
-	return ret;
 }
-EXPORT_SYMBOL(mdev_register_device);
+EXPORT_SYMBOL(mdev_register_parent);
 
 /*
- * mdev_unregister_device : Unregister a parent device
- * @dev: device structure representing parent device.
- *
- * Remove device from list of registered parent devices. Give a chance to free
- * existing mediated devices for given device.
+ * mdev_unregister_parent : Unregister a parent device
+ * @parent: parent structure to unregister
  */
-
-void mdev_unregister_device(struct device *dev)
+void mdev_unregister_parent(struct mdev_parent *parent)
 {
-	struct mdev_parent *parent;
 	char *env_string = "MDEV_STATE=unregistered";
 	char *envp[] = { env_string, NULL };
 
-	mutex_lock(&parent_list_lock);
-	parent = __find_parent_device(dev);
-
-	if (!parent) {
-		mutex_unlock(&parent_list_lock);
-		return;
-	}
-	dev_info(dev, "MDEV: Unregistering\n");
-
-	list_del(&parent->next);
-	mutex_unlock(&parent_list_lock);
+	dev_info(parent->dev, "MDEV: Unregistering\n");
 
 	down_write(&parent->unreg_sem);
-
-	class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
-
-	device_for_each_child(dev, NULL, mdev_device_remove_cb);
-
+	class_compat_remove_link(mdev_bus_compat_class, parent->dev, NULL);
+	device_for_each_child(parent->dev, NULL, mdev_device_remove_cb);
 	parent_remove_sysfs_files(parent);
 	up_write(&parent->unreg_sem);
 
-	mdev_put_parent(parent);
-
-	/* We still have the caller's reference to use for the uevent */
-	kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
+	kobject_uevent_env(&parent->dev->kobj, KOBJ_CHANGE, envp);
 }
-EXPORT_SYMBOL(mdev_unregister_device);
+EXPORT_SYMBOL(mdev_unregister_parent);
 
 static void mdev_device_release(struct device *dev)
 {
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 7c9fc79f3d838..297f911fdc890 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -13,17 +13,6 @@
 int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
-struct mdev_parent {
-	struct device *dev;
-	struct mdev_driver *mdev_driver;
-	struct kref ref;
-	struct list_head next;
-	struct kset *mdev_types_kset;
-	struct list_head type_list;
-	/* Synchronize device creation/removal with parent unregistration */
-	struct rw_semaphore unreg_sem;
-};
-
 struct mdev_type {
 	struct kobject kobj;
 	struct kobject *devices_kobj;
@@ -48,16 +37,4 @@ void mdev_remove_sysfs_files(struct mdev_device *mdev);
 int mdev_device_create(struct mdev_type *kobj, const guid_t *uuid);
 int  mdev_device_remove(struct mdev_device *dev);
 
-void mdev_release_parent(struct kref *kref);
-
-static inline void mdev_get_parent(struct mdev_parent *parent)
-{
-	kref_get(&parent->ref);
-}
-
-static inline void mdev_put_parent(struct mdev_parent *parent)
-{
-	kref_put(&parent->ref, mdev_release_parent);
-}
-
 #endif /* MDEV_PRIVATE_H */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 4bfbf49aaa66a..b71ffc5594870 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -81,7 +81,7 @@ static void mdev_type_release(struct kobject *kobj)
 
 	pr_debug("Releasing group %s\n", kobj->name);
 	/* Pairs with the get in add_mdev_supported_type() */
-	mdev_put_parent(type->parent);
+	put_device(type->parent->dev);
 	kfree(type);
 }
 
@@ -110,7 +110,7 @@ static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
 	type->kobj.kset = parent->mdev_types_kset;
 	type->parent = parent;
 	/* Pairs with the put in mdev_type_release() */
-	mdev_get_parent(parent);
+	get_device(parent->dev);
 	type->type_group_id = type_group_id;
 
 	ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index a5d8ae6132a20..262512c2a8ffc 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -23,6 +23,16 @@ struct mdev_device {
 	bool active;
 };
 
+/* embedded into the struct device that the mdev devices hang off */
+struct mdev_parent {
+	struct device *dev;
+	struct mdev_driver *mdev_driver;
+	struct kset *mdev_types_kset;
+	struct list_head type_list;
+	/* Synchronize device creation/removal with parent unregistration */
+	struct rw_semaphore unreg_sem;
+};
+
 static inline struct mdev_device *to_mdev_device(struct device *dev)
 {
 	return container_of(dev, struct mdev_device, dev);
@@ -70,8 +80,9 @@ struct mdev_driver {
 
 extern struct bus_type mdev_bus_type;
 
-int mdev_register_device(struct device *dev, struct mdev_driver *mdev_driver);
-void mdev_unregister_device(struct device *dev);
+int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
+		struct mdev_driver *mdev_driver);
+void mdev_unregister_parent(struct mdev_parent *parent);
 
 int mdev_register_driver(struct mdev_driver *drv);
 void mdev_unregister_driver(struct mdev_driver *drv);
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 985b6e7136219..2c4791abbc3d3 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -128,6 +128,7 @@ static dev_t		mbochs_devt;
 static struct class	*mbochs_class;
 static struct cdev	mbochs_cdev;
 static struct device	mbochs_dev;
+static struct mdev_parent mbochs_parent;
 static atomic_t mbochs_avail_mbytes;
 static const struct vfio_device_ops mbochs_dev_ops;
 
@@ -1475,7 +1476,7 @@ static int __init mbochs_dev_init(void)
 	if (ret)
 		goto err_class;
 
-	ret = mdev_register_device(&mbochs_dev, &mbochs_driver);
+	ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver);
 	if (ret)
 		goto err_device;
 
@@ -1496,7 +1497,7 @@ static int __init mbochs_dev_init(void)
 static void __exit mbochs_dev_exit(void)
 {
 	mbochs_dev.bus = NULL;
-	mdev_unregister_device(&mbochs_dev);
+	mdev_unregister_parent(&mbochs_parent);
 
 	device_unregister(&mbochs_dev);
 	mdev_unregister_driver(&mbochs_driver);
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 1daab012b5d89..01f345430b975 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -83,6 +83,7 @@ static dev_t		mdpy_devt;
 static struct class	*mdpy_class;
 static struct cdev	mdpy_cdev;
 static struct device	mdpy_dev;
+static struct mdev_parent mdpy_parent;
 static u32		mdpy_count;
 static const struct vfio_device_ops mdpy_dev_ops;
 
@@ -778,7 +779,7 @@ static int __init mdpy_dev_init(void)
 	if (ret)
 		goto err_class;
 
-	ret = mdev_register_device(&mdpy_dev, &mdpy_driver);
+	ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver);
 	if (ret)
 		goto err_device;
 
@@ -799,7 +800,7 @@ static int __init mdpy_dev_init(void)
 static void __exit mdpy_dev_exit(void)
 {
 	mdpy_dev.bus = NULL;
-	mdev_unregister_device(&mdpy_dev);
+	mdev_unregister_parent(&mdpy_parent);
 
 	device_unregister(&mdpy_dev);
 	mdev_unregister_driver(&mdpy_driver);
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index 86843ce3d9a27..e80baac513811 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -72,6 +72,7 @@ static struct mtty_dev {
 	struct cdev	vd_cdev;
 	struct idr	vd_idr;
 	struct device	dev;
+	struct mdev_parent parent;
 } mtty_dev;
 
 struct mdev_region_info {
@@ -1361,7 +1362,8 @@ static int __init mtty_dev_init(void)
 	if (ret)
 		goto err_class;
 
-	ret = mdev_register_device(&mtty_dev.dev, &mtty_driver);
+	ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,
+				   &mtty_driver);
 	if (ret)
 		goto err_device;
 	return 0;
@@ -1381,7 +1383,7 @@ static int __init mtty_dev_init(void)
 static void __exit mtty_dev_exit(void)
 {
 	mtty_dev.dev.bus = NULL;
-	mdev_unregister_device(&mtty_dev.dev);
+	mdev_unregister_parent(&mtty_dev.parent);
 
 	device_unregister(&mtty_dev.dev);
 	idr_destroy(&mtty_dev.vd_idr);
-- 
2.30.2


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

* [PATCH 05/14] vfio/mdev: simplify mdev_type handling
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (3 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 06/14] vfio/mdev: remove mdev_from_dev Christoph Hellwig
                   ` (9 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Instead of abusing struct attribute_group to control initialization of
struct mdev_type, just define the actual attributes in the mdev_driver,
allocate the mdev_type structures in the caller and pass them to
mdev_register_parent.

This allows the caller to use container_of to get at the containing
structure and thus significantly simplify the code.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |   2 +-
 drivers/gpu/drm/i915/gvt/gvt.h                |   3 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c              | 102 +++---------------
 drivers/gpu/drm/i915/gvt/vgpu.c               |  13 ++-
 drivers/s390/cio/vfio_ccw_drv.c               |   6 +-
 drivers/s390/cio/vfio_ccw_ops.c               |  14 +--
 drivers/s390/cio/vfio_ccw_private.h           |   2 +
 drivers/s390/crypto/vfio_ap_ops.c             |  19 ++--
 drivers/s390/crypto/vfio_ap_private.h         |   2 +
 drivers/vfio/mdev/mdev_core.c                 |  31 ++----
 drivers/vfio/mdev/mdev_driver.c               |   5 +-
 drivers/vfio/mdev/mdev_private.h              |   8 --
 drivers/vfio/mdev/mdev_sysfs.c                |  91 ++++------------
 include/linux/mdev.h                          |  26 +++--
 samples/vfio-mdev/mbochs.c                    |  57 ++++------
 samples/vfio-mdev/mdpy.c                      |  50 ++++-----
 samples/vfio-mdev/mtty.c                      |  60 +++++------
 17 files changed, 165 insertions(+), 326 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index cd1667608ab5d..ff7342d2e332d 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -103,7 +103,7 @@ structure to represent a mediated device's driver::
      struct mdev_driver {
 	     int  (*probe)  (struct mdev_device *dev);
 	     void (*remove) (struct mdev_device *dev);
-	     struct attribute_group **supported_type_groups;
+	     const struct attribute * const *types_attrs;
 	     struct device_driver    driver;
      };
 
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index fa4a56b50c828..db182066d56c9 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -310,8 +310,8 @@ struct intel_vgpu_config {
 	const char *name;
 };
 
-#define NR_MAX_INTEL_VGPU_TYPES 20
 struct intel_vgpu_type {
+	struct mdev_type type;
 	char name[16];
 	const struct intel_vgpu_config *conf;
 	unsigned int avail_instance;
@@ -339,6 +339,7 @@ struct intel_gvt {
 	struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
 	DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
 	struct mdev_parent parent;
+	struct mdev_type **mdev_types;
 	struct intel_vgpu_type *types;
 	unsigned int num_types;
 	struct intel_vgpu *idle_vgpu;
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 29531b797010f..ce6b8cb37be0c 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -117,17 +117,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
 {
-	struct intel_vgpu_type *type;
-	unsigned int num = 0;
-	struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
+	struct intel_vgpu_type *type =
+		container_of(mtype, struct intel_vgpu_type, type);
 
-	type = &gvt->types[mtype_get_type_group_id(mtype)];
-	if (!type)
-		num = 0;
-	else
-		num = type->avail_instance;
-
-	return sprintf(buf, "%u\n", num);
+	return sprintf(buf, "%u\n", type->avail_instance);
 }
 
 static ssize_t device_api_show(struct mdev_type *mtype,
@@ -139,12 +132,8 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
-	struct intel_vgpu_type *type;
-	struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-	type = &gvt->types[mtype_get_type_group_id(mtype)];
-	if (!type)
-		return 0;
+	struct intel_vgpu_type *type =
+		container_of(mtype, struct intel_vgpu_type, type);
 
 	return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
 		       "fence: %d\nresolution: %s\n"
@@ -158,14 +147,7 @@ static ssize_t description_show(struct mdev_type *mtype,
 static ssize_t name_show(struct mdev_type *mtype,
 			 struct mdev_type_attribute *attr, char *buf)
 {
-	struct intel_vgpu_type *type;
-	struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-	type = &gvt->types[mtype_get_type_group_id(mtype)];
-	if (!type)
-		return 0;
-
-	return sprintf(buf, "%s\n", type->name);
+	return sprintf(buf, "%s\n", mtype->sysfs_name);
 }
 
 static MDEV_TYPE_ATTR_RO(available_instances);
@@ -173,7 +155,7 @@ static MDEV_TYPE_ATTR_RO(device_api);
 static MDEV_TYPE_ATTR_RO(description);
 static MDEV_TYPE_ATTR_RO(name);
 
-static struct attribute *gvt_type_attrs[] = {
+static const struct attribute *gvt_type_attrs[] = {
 	&mdev_type_attr_available_instances.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_description.attr,
@@ -181,51 +163,6 @@ static struct attribute *gvt_type_attrs[] = {
 	NULL,
 };
 
-static struct attribute_group *gvt_vgpu_type_groups[] = {
-	[0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
-};
-
-static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
-{
-	int i, j;
-	struct intel_vgpu_type *type;
-	struct attribute_group *group;
-
-	for (i = 0; i < gvt->num_types; i++) {
-		type = &gvt->types[i];
-
-		group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
-		if (!group)
-			goto unwind;
-
-		group->name = type->name;
-		group->attrs = gvt_type_attrs;
-		gvt_vgpu_type_groups[i] = group;
-	}
-
-	return 0;
-
-unwind:
-	for (j = 0; j < i; j++) {
-		group = gvt_vgpu_type_groups[j];
-		kfree(group);
-	}
-
-	return -ENOMEM;
-}
-
-static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
-{
-	int i;
-	struct attribute_group *group;
-
-	for (i = 0; i < gvt->num_types; i++) {
-		group = gvt_vgpu_type_groups[i];
-		gvt_vgpu_type_groups[i] = NULL;
-		kfree(group);
-	}
-}
-
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
 		unsigned long size)
 {
@@ -1547,16 +1484,11 @@ static const struct attribute_group *intel_vgpu_groups[] = {
 static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
 {
 	struct mdev_device *mdev = to_mdev_device(vfio_dev->dev);
-	struct device *pdev = mdev_parent_dev(mdev);
-	struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
-	struct intel_vgpu_type *type;
 	struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
+	struct intel_vgpu_type *type =
+		container_of(mdev->type, struct intel_vgpu_type, type);
 
-	type = &gvt->types[mdev_get_type_group_id(mdev)];
-	if (!type)
-		return -EINVAL;
-
-	vgpu->gvt = gvt;
+	vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt;
 	return intel_gvt_create_vgpu(vgpu, type->conf);
 }
 
@@ -1624,7 +1556,7 @@ static struct mdev_driver intel_vgpu_mdev_driver = {
 	},
 	.probe		= intel_vgpu_probe,
 	.remove		= intel_vgpu_remove,
-	.supported_type_groups	= gvt_vgpu_type_groups,
+	.types_attrs	= gvt_type_attrs,
 };
 
 int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn)
@@ -1923,7 +1855,6 @@ static void intel_gvt_clean_device(struct drm_i915_private *i915)
 		return;
 
 	mdev_unregister_parent(&gvt->parent);
-	intel_gvt_cleanup_vgpu_type_groups(gvt);
 	intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
 	intel_gvt_clean_vgpu_types(gvt);
 
@@ -2023,20 +1954,15 @@ static int intel_gvt_init_device(struct drm_i915_private *i915)
 
 	intel_gvt_debugfs_init(gvt);
 
-	ret = intel_gvt_init_vgpu_type_groups(gvt);
-	if (ret)
-		goto out_destroy_idle_vgpu;
-
 	ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
-				   &intel_vgpu_mdev_driver);
+				   &intel_vgpu_mdev_driver,
+				   gvt->mdev_types, gvt->num_types);
 	if (ret)
-		goto out_cleanup_vgpu_type_groups;
+		goto out_destroy_idle_vgpu;
 
 	gvt_dbg_core("gvt device initialization is done\n");
 	return 0;
 
-out_cleanup_vgpu_type_groups:
-	intel_gvt_cleanup_vgpu_type_groups(gvt);
 out_destroy_idle_vgpu:
 	intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
 	intel_gvt_debugfs_clean(gvt);
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 1b67328c714f1..8fa06d00fd4b9 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -113,13 +113,18 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 	if (!gvt->types)
 		return -ENOMEM;
 
+	gvt->mdev_types = kcalloc(num_types, sizeof(*gvt->mdev_types),
+			     GFP_KERNEL);
+	if (!gvt->mdev_types)
+		goto out_free_types;
+
 	for (i = 0; i < num_types; ++i) {
 		const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];
 
 		if (low_avail / conf->low_mm == 0)
 			break;
 		if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)
-			goto out_free_types;
+			goto out_free_mdev_types;
 
 		sprintf(gvt->types[i].name, "GVTg_V%u_%s",
 			GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
@@ -131,11 +136,16 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 			     i, gvt->types[i].name, gvt->types[i].avail_instance,
 			     conf->low_mm, conf->high_mm, conf->fence,
 			     conf->weight, vgpu_edid_str(conf->edid));
+
+		gvt->mdev_types[i] = &gvt->types[i].type;
+		gvt->mdev_types[i]->sysfs_name = gvt->types[i].name;
 	}
 
 	gvt->num_types = i;
 	return 0;
 
+out_free_mdev_types:
+	kfree(gvt->mdev_types);
 out_free_types:
 	kfree(gvt->types);
 	return -EINVAL;
@@ -143,6 +153,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 
 void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
 {
+	kfree(gvt->mdev_types);
 	kfree(gvt->types);
 }
 
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 7d105915bd149..25a5de08b3902 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -202,7 +202,6 @@ static void vfio_ccw_free_private(struct vfio_ccw_private *private)
 	mutex_destroy(&private->io_mutex);
 	kfree(private);
 }
-
 static int vfio_ccw_sch_probe(struct subchannel *sch)
 {
 	struct pmcw *pmcw = &sch->schib.pmcw;
@@ -221,8 +220,11 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 
 	dev_set_drvdata(&sch->dev, private);
 
+	private->mdev_type.sysfs_name = "io";
+	private->mdev_types[0] = &private->mdev_type;
 	ret = mdev_register_parent(&private->parent, &sch->dev,
-				   &vfio_ccw_mdev_driver);
+				   &vfio_ccw_mdev_driver,
+				   private->mdev_types, 1);
 	if (ret)
 		goto out_free;
 
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 9a0e0c5ffb1a5..c37e712a4b069 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -69,23 +69,13 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
-static struct attribute_group mdev_type_group = {
-	.name  = "io",
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-	&mdev_type_group,
-	NULL,
-};
-
 static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
 {
 	struct vfio_ccw_private *private =
@@ -646,5 +636,5 @@ struct mdev_driver vfio_ccw_mdev_driver = {
 	},
 	.probe = vfio_ccw_mdev_probe,
 	.remove = vfio_ccw_mdev_remove,
-	.supported_type_groups  = mdev_type_groups,
+	.types_attrs = mdev_types_attrs,
 };
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index 1a4bfb1b5a808..52caa721ec06c 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -120,6 +120,8 @@ struct vfio_ccw_private {
 	struct completion	release_comp;
 
 	struct mdev_parent	parent;
+	struct mdev_type	mdev_type;
+	struct mdev_type	*mdev_types[1];
 } __aligned(8);
 
 int vfio_ccw_sch_quiesce(struct subchannel *sch);
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 724d09a74a8f1..24d131c502ca3 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -816,23 +816,13 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *vfio_ap_mdev_type_attrs[] = {
+static const struct attribute *vfio_ap_mdev_type_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
-static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
-	.name = VFIO_AP_MDEV_TYPE_HWVIRT,
-	.attrs = vfio_ap_mdev_type_attrs,
-};
-
-static struct attribute_group *vfio_ap_mdev_type_groups[] = {
-	&vfio_ap_mdev_hwvirt_type_group,
-	NULL,
-};
-
 #define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
 			 "already assigned to %s"
 
@@ -1817,7 +1807,7 @@ static struct mdev_driver vfio_ap_matrix_driver = {
 	},
 	.probe = vfio_ap_mdev_probe,
 	.remove = vfio_ap_mdev_remove,
-	.supported_type_groups = vfio_ap_mdev_type_groups,
+	.types_attrs = vfio_ap_mdev_type_attrs,
 };
 
 int vfio_ap_mdev_register(void)
@@ -1830,8 +1820,11 @@ int vfio_ap_mdev_register(void)
 	if (ret)
 		return ret;
 
+	matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT;
+	matrix_dev->mdev_types[0] = &matrix_dev->mdev_type;
 	ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,
-				   &vfio_ap_matrix_driver);
+				   &vfio_ap_matrix_driver,
+				   matrix_dev->mdev_types, 1);
 	if (ret)
 		goto err_driver;
 	return 0;
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 35165730f5174..441dc8dda380b 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -53,6 +53,8 @@ struct ap_matrix_dev {
 	struct ap_driver  *vfio_ap_drv;
 	struct mutex guests_lock; /* serializes access to each KVM guest */
 	struct mdev_parent parent;
+	struct mdev_type mdev_type;
+	struct mdev_type *mdev_types[];
 };
 
 extern struct ap_matrix_dev *matrix_dev;
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index fa05ac3396950..2d95a497fd3b2 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -29,26 +29,6 @@ struct device *mdev_parent_dev(struct mdev_device *mdev)
 }
 EXPORT_SYMBOL(mdev_parent_dev);
 
-/*
- * Return the index in supported_type_groups that this mdev_device was created
- * from.
- */
-unsigned int mdev_get_type_group_id(struct mdev_device *mdev)
-{
-	return mdev->type->type_group_id;
-}
-EXPORT_SYMBOL(mdev_get_type_group_id);
-
-/*
- * Used in mdev_type_attribute sysfs functions to return the index in the
- * supported_type_groups that the sysfs is called from.
- */
-unsigned int mtype_get_type_group_id(struct mdev_type *mtype)
-{
-	return mtype->type_group_id;
-}
-EXPORT_SYMBOL(mtype_get_type_group_id);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
@@ -85,6 +65,8 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
  * @parent: parent structure registered
  * @dev: device structure representing parent device.
  * @mdev_driver: Device driver to bind to the newly created mdev
+ * @types: Array of supported mdev types
+ * @nr_types: Number of entries in @types
  *
  * Registers the @parent stucture as a parent for mdev types and thus mdev
  * devices.  The caller needs to hold a reference on @dev that must not be
@@ -93,20 +75,19 @@ static int mdev_device_remove_cb(struct device *dev, void *data)
  * Returns a negative value on error, otherwise 0.
  */
 int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
-		struct mdev_driver *mdev_driver)
+		struct mdev_driver *mdev_driver, struct mdev_type **types,
+		unsigned int nr_types)
 {
 	char *env_string = "MDEV_STATE=registered";
 	char *envp[] = { env_string, NULL };
 	int ret;
 
-	/* check for mandatory ops */
-	if (!mdev_driver->supported_type_groups)
-		return -EINVAL;
-
 	memset(parent, 0, sizeof(*parent));
 	init_rwsem(&parent->unreg_sem);
 	parent->dev = dev;
 	parent->mdev_driver = mdev_driver;
+	parent->types = types;
+	parent->nr_types = nr_types;
 
 	if (!mdev_bus_compat_class) {
 		mdev_bus_compat_class = class_compat_register("mdev_bus");
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 7bd4bb9850e81..1da1ecf76a0d5 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -56,10 +56,9 @@ EXPORT_SYMBOL_GPL(mdev_bus_type);
  **/
 int mdev_register_driver(struct mdev_driver *drv)
 {
-	/* initialize common driver fields */
+	if (!drv->types_attrs)
+		return -EINVAL;
 	drv->driver.bus = &mdev_bus_type;
-
-	/* register with core */
 	return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(mdev_register_driver);
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index 297f911fdc890..ba1b2dbddc0bc 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -13,14 +13,6 @@
 int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
-struct mdev_type {
-	struct kobject kobj;
-	struct kobject *devices_kobj;
-	struct mdev_parent *parent;
-	struct list_head next;
-	unsigned int type_group_id;
-};
-
 extern const struct attribute_group *mdev_device_groups[];
 
 #define to_mdev_type_attr(_attr)	\
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index b71ffc5594870..38b4c2466ec43 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -82,7 +82,6 @@ static void mdev_type_release(struct kobject *kobj)
 	pr_debug("Releasing group %s\n", kobj->name);
 	/* Pairs with the get in add_mdev_supported_type() */
 	put_device(type->parent->dev);
-	kfree(type);
 }
 
 static struct kobj_type mdev_type_ktype = {
@@ -90,35 +89,21 @@ static struct kobj_type mdev_type_ktype = {
 	.release = mdev_type_release,
 };
 
-static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
-						 unsigned int type_group_id)
+static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 {
-	struct mdev_type *type;
-	struct attribute_group *group =
-		parent->mdev_driver->supported_type_groups[type_group_id];
 	int ret;
 
-	if (!group->name) {
-		pr_err("%s: Type name empty!\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	type = kzalloc(sizeof(*type), GFP_KERNEL);
-	if (!type)
-		return ERR_PTR(-ENOMEM);
-
 	type->kobj.kset = parent->mdev_types_kset;
 	type->parent = parent;
 	/* Pairs with the put in mdev_type_release() */
 	get_device(parent->dev);
-	type->type_group_id = type_group_id;
 
 	ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype, NULL,
 				   "%s-%s", dev_driver_string(parent->dev),
-				   group->name);
+				   type->sysfs_name);
 	if (ret) {
 		kobject_put(&type->kobj);
-		return ERR_PTR(ret);
+		return ret;
 	}
 
 	ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
@@ -131,13 +116,10 @@ static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
 		goto attr_devices_failed;
 	}
 
-	ret = sysfs_create_files(&type->kobj,
-				 (const struct attribute **)group->attrs);
-	if (ret) {
-		ret = -ENOMEM;
+	ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs);
+	if (ret)
 		goto attrs_failed;
-	}
-	return type;
+	return 0;
 
 attrs_failed:
 	kobject_put(type->devices_kobj);
@@ -146,78 +128,49 @@ static struct mdev_type *add_mdev_supported_type(struct mdev_parent *parent,
 attr_create_failed:
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
-	return ERR_PTR(ret);
+	return ret;
 }
 
-static void remove_mdev_supported_type(struct mdev_type *type)
+static void mdev_type_remove(struct mdev_type *type)
 {
-	struct attribute_group *group =
-		type->parent->mdev_driver->supported_type_groups[type->type_group_id];
+	sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
 
-	sysfs_remove_files(&type->kobj,
-			   (const struct attribute **)group->attrs);
 	kobject_put(type->devices_kobj);
 	sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
 }
 
-static int add_mdev_supported_type_groups(struct mdev_parent *parent)
-{
-	int i;
-
-	for (i = 0; parent->mdev_driver->supported_type_groups[i]; i++) {
-		struct mdev_type *type;
-
-		type = add_mdev_supported_type(parent, i);
-		if (IS_ERR(type)) {
-			struct mdev_type *ltype, *tmp;
-
-			list_for_each_entry_safe(ltype, tmp, &parent->type_list,
-						  next) {
-				list_del(&ltype->next);
-				remove_mdev_supported_type(ltype);
-			}
-			return PTR_ERR(type);
-		}
-		list_add(&type->next, &parent->type_list);
-	}
-	return 0;
-}
-
 /* mdev sysfs functions */
 void parent_remove_sysfs_files(struct mdev_parent *parent)
 {
-	struct mdev_type *type, *tmp;
-
-	list_for_each_entry_safe(type, tmp, &parent->type_list, next) {
-		list_del(&type->next);
-		remove_mdev_supported_type(type);
-	}
+	int i;
 
+	for (i = 0; i < parent->nr_types; i++)
+		mdev_type_remove(parent->types[i]);
 	kset_unregister(parent->mdev_types_kset);
 }
 
 int parent_create_sysfs_files(struct mdev_parent *parent)
 {
-	int ret;
+	int ret, i;
 
 	parent->mdev_types_kset = kset_create_and_add("mdev_supported_types",
 					       NULL, &parent->dev->kobj);
-
 	if (!parent->mdev_types_kset)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&parent->type_list);
-
-	ret = add_mdev_supported_type_groups(parent);
-	if (ret)
-		goto create_err;
+	for (i = 0; i < parent->nr_types; i++) {
+		ret = mdev_type_add(parent, parent->types[i]);
+		if (ret)
+			goto out_err;
+	}
 	return 0;
 
-create_err:
-	kset_unregister(parent->mdev_types_kset);
-	return ret;
+out_err:
+	while (--i >= 0)
+		mdev_type_remove(parent->types[i]);
+	return 0;
 }
 
 static ssize_t remove_store(struct device *dev, struct device_attribute *attr,
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 262512c2a8ffc..19bc93c10e8c7 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -23,14 +23,27 @@ struct mdev_device {
 	bool active;
 };
 
+struct mdev_type {
+	/* set by the driver before calling mdev_register parent: */
+	const char *sysfs_name;
+
+	/* set by the core, can be used drivers */
+	struct mdev_parent *parent;
+
+	/* internal only */
+	struct kobject kobj;
+	struct kobject *devices_kobj;
+};
+
 /* embedded into the struct device that the mdev devices hang off */
 struct mdev_parent {
 	struct device *dev;
 	struct mdev_driver *mdev_driver;
 	struct kset *mdev_types_kset;
-	struct list_head type_list;
 	/* Synchronize device creation/removal with parent unregistration */
 	struct rw_semaphore unreg_sem;
+	struct mdev_type **types;
+	unsigned int nr_types;
 };
 
 static inline struct mdev_device *to_mdev_device(struct device *dev)
@@ -38,8 +51,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
 	return container_of(dev, struct mdev_device, dev);
 }
 
-unsigned int mdev_get_type_group_id(struct mdev_device *mdev);
-unsigned int mtype_get_type_group_id(struct mdev_type *mtype);
 struct device *mtype_get_parent_dev(struct mdev_type *mtype);
 
 /* interface for exporting mdev supported type attributes */
@@ -66,22 +77,21 @@ struct mdev_type_attribute mdev_type_attr_##_name =		\
  * struct mdev_driver - Mediated device driver
  * @probe: called when new device created
  * @remove: called when device removed
- * @supported_type_groups: Attributes to define supported types. It is mandatory
- *			to provide supported types.
+ * @types_attrs: attributes to the type kobjects.
  * @driver: device driver structure
- *
  **/
 struct mdev_driver {
 	int (*probe)(struct mdev_device *dev);
 	void (*remove)(struct mdev_device *dev);
-	struct attribute_group **supported_type_groups;
+	const struct attribute * const *types_attrs;
 	struct device_driver driver;
 };
 
 extern struct bus_type mdev_bus_type;
 
 int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
-		struct mdev_driver *mdev_driver);
+		struct mdev_driver *mdev_driver, struct mdev_type **types,
+		unsigned int nr_types);
 void mdev_unregister_parent(struct mdev_parent *parent);
 
 int mdev_register_driver(struct mdev_driver *drv);
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 2c4791abbc3d3..4d0839cb51943 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -99,23 +99,27 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
 #define MBOCHS_TYPE_2 "medium"
 #define MBOCHS_TYPE_3 "large"
 
-static const struct mbochs_type {
+static struct mbochs_type {
+	struct mdev_type type;
 	const char *name;
 	u32 mbytes;
 	u32 max_x;
 	u32 max_y;
 } mbochs_types[] = {
 	{
+		.type.sysfs_name	= MBOCHS_TYPE_1,
 		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
 		.mbytes = 4,
 		.max_x  = 800,
 		.max_y  = 600,
 	}, {
+		.type.sysfs_name	= MBOCHS_TYPE_2,
 		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
 		.mbytes = 16,
 		.max_x  = 1920,
 		.max_y  = 1440,
 	}, {
+		.type.sysfs_name	= MBOCHS_TYPE_3,
 		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
 		.mbytes = 64,
 		.max_x  = 0,
@@ -123,6 +127,11 @@ static const struct mbochs_type {
 	},
 };
 
+static struct mdev_type *mbochs_mdev_types[] = {
+	&mbochs_types[0].type,
+	&mbochs_types[1].type,
+	&mbochs_types[2].type,
+};
 
 static dev_t		mbochs_devt;
 static struct class	*mbochs_class;
@@ -510,8 +519,8 @@ static int mbochs_init_dev(struct vfio_device *vdev)
 	struct mdev_state *mdev_state =
 		container_of(vdev, struct mdev_state, vdev);
 	struct mdev_device *mdev = to_mdev_device(vdev->dev);
-	const struct mbochs_type *type =
-		&mbochs_types[mdev_get_type_group_id(mdev)];
+	struct mbochs_type *type =
+		container_of(mdev->type, struct mbochs_type, type);
 	int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
 	int ret = -ENOMEM;
 
@@ -1345,8 +1354,8 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
 			 struct mdev_type_attribute *attr, char *buf)
 {
-	const struct mbochs_type *type =
-		&mbochs_types[mtype_get_type_group_id(mtype)];
+	struct mbochs_type *type =
+		container_of(mtype, struct mbochs_type, type);
 
 	return sprintf(buf, "%s\n", type->name);
 }
@@ -1355,8 +1364,8 @@ static MDEV_TYPE_ATTR_RO(name);
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
-	const struct mbochs_type *type =
-		&mbochs_types[mtype_get_type_group_id(mtype)];
+	struct mbochs_type *type =
+		container_of(mtype, struct mbochs_type, type);
 
 	return sprintf(buf, "virtual display, %d MB video memory\n",
 		       type ? type->mbytes  : 0);
@@ -1367,8 +1376,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
 {
-	const struct mbochs_type *type =
-		&mbochs_types[mtype_get_type_group_id(mtype)];
+	struct mbochs_type *type =
+		container_of(mtype, struct mbochs_type, type);
 	int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
 
 	return sprintf(buf, "%d\n", count);
@@ -1382,7 +1391,7 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
 	&mdev_type_attr_device_api.attr,
@@ -1390,28 +1399,6 @@ static struct attribute *mdev_types_attrs[] = {
 	NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-	.name  = MBOCHS_TYPE_1,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-	.name  = MBOCHS_TYPE_2,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group3 = {
-	.name  = MBOCHS_TYPE_3,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-	&mdev_type_group1,
-	&mdev_type_group2,
-	&mdev_type_group3,
-	NULL,
-};
-
 static const struct vfio_device_ops mbochs_dev_ops = {
 	.close_device = mbochs_close_device,
 	.init = mbochs_init_dev,
@@ -1431,7 +1418,7 @@ static struct mdev_driver mbochs_driver = {
 	},
 	.probe = mbochs_probe,
 	.remove	= mbochs_remove,
-	.supported_type_groups = mdev_type_groups,
+	.types_attrs = mdev_types_attrs,
 };
 
 static const struct file_operations vd_fops = {
@@ -1476,7 +1463,9 @@ static int __init mbochs_dev_init(void)
 	if (ret)
 		goto err_class;
 
-	ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver);
+	ret = mdev_register_parent(&mbochs_parent, &mbochs_dev, &mbochs_driver,
+				   mbochs_mdev_types,
+				   ARRAY_SIZE(mbochs_mdev_types));
 	if (ret)
 		goto err_device;
 
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 01f345430b975..4a341f4849e73 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -51,7 +51,8 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
 #define MDPY_TYPE_2 "xga"
 #define MDPY_TYPE_3 "hd"
 
-static const struct mdpy_type {
+static struct mdpy_type {
+	struct mdev_type type;
 	const char *name;
 	u32 format;
 	u32 bytepp;
@@ -59,18 +60,21 @@ static const struct mdpy_type {
 	u32 height;
 } mdpy_types[] = {
 	{
+		.type.sysfs_name 	= MDPY_TYPE_1,
 		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_1,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
 		.width	= 640,
 		.height = 480,
 	}, {
+		.type.sysfs_name 	= MDPY_TYPE_2,
 		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_2,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
 		.width	= 1024,
 		.height = 768,
 	}, {
+		.type.sysfs_name 	= MDPY_TYPE_3,
 		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_3,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
@@ -79,6 +83,12 @@ static const struct mdpy_type {
 	},
 };
 
+static struct mdev_type *mdpy_mdev_types[] = {
+	&mdpy_types[0].type,
+	&mdpy_types[1].type,
+	&mdpy_types[2].type,
+};
+
 static dev_t		mdpy_devt;
 static struct class	*mdpy_class;
 static struct cdev	mdpy_cdev;
@@ -222,7 +232,7 @@ static int mdpy_init_dev(struct vfio_device *vdev)
 		container_of(vdev, struct mdev_state, vdev);
 	struct mdev_device *mdev = to_mdev_device(vdev->dev);
 	const struct mdpy_type *type =
-		&mdpy_types[mdev_get_type_group_id(mdev)];
+		container_of(mdev->type, struct mdpy_type, type);
 	u32 fbsize;
 	int ret = -ENOMEM;
 
@@ -655,8 +665,7 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
 			 struct mdev_type_attribute *attr, char *buf)
 {
-	const struct mdpy_type *type =
-		&mdpy_types[mtype_get_type_group_id(mtype)];
+	struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
 
 	return sprintf(buf, "%s\n", type->name);
 }
@@ -665,8 +674,7 @@ static MDEV_TYPE_ATTR_RO(name);
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
-	const struct mdpy_type *type =
-		&mdpy_types[mtype_get_type_group_id(mtype)];
+	struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
 
 	return sprintf(buf, "virtual display, %dx%d framebuffer\n",
 		       type->width, type->height);
@@ -688,7 +696,7 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
 	&mdev_type_attr_device_api.attr,
@@ -696,28 +704,6 @@ static struct attribute *mdev_types_attrs[] = {
 	NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-	.name  = MDPY_TYPE_1,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-	.name  = MDPY_TYPE_2,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group3 = {
-	.name  = MDPY_TYPE_3,
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-	&mdev_type_group1,
-	&mdev_type_group2,
-	&mdev_type_group3,
-	NULL,
-};
-
 static const struct vfio_device_ops mdpy_dev_ops = {
 	.init = mdpy_init_dev,
 	.release = mdpy_release_dev,
@@ -736,7 +722,7 @@ static struct mdev_driver mdpy_driver = {
 	},
 	.probe = mdpy_probe,
 	.remove	= mdpy_remove,
-	.supported_type_groups = mdev_type_groups,
+	.types_attrs = mdev_types_attrs,
 };
 
 static const struct file_operations vd_fops = {
@@ -779,7 +765,9 @@ static int __init mdpy_dev_init(void)
 	if (ret)
 		goto err_class;
 
-	ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver);
+	ret = mdev_register_parent(&mdpy_parent, &mdpy_dev, &mdpy_driver,
+				   mdpy_mdev_types,
+				   ARRAY_SIZE(mdpy_mdev_types));
 	if (ret)
 		goto err_device;
 
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index e80baac513811..814a7f98738a2 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -143,6 +143,20 @@ struct mdev_state {
 	int nr_ports;
 };
 
+static struct mtty_type {
+	struct mdev_type type;
+	int nr_ports;
+	const char *name;
+} mtty_types[2] = {
+	{ .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port serial" },
+	{ .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port serial" },
+};
+
+static struct mdev_type *mtty_mdev_types[] = {
+	&mtty_types[0].type,
+	&mtty_types[1].type,
+};
+
 static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS);
 
 static const struct file_operations vd_fops = {
@@ -707,17 +721,19 @@ static int mtty_init_dev(struct vfio_device *vdev)
 	struct mdev_state *mdev_state =
 		container_of(vdev, struct mdev_state, vdev);
 	struct mdev_device *mdev = to_mdev_device(vdev->dev);
-	int nr_ports = mdev_get_type_group_id(mdev) + 1;
+	struct mtty_type *type =
+		container_of(mdev->type, struct mtty_type, type);
 	int avail_ports = atomic_read(&mdev_avail_ports);
 	int ret;
 
 	do {
-		if (avail_ports < nr_ports)
+		if (avail_ports < type->nr_ports)
 			return -ENOSPC;
 	} while (!atomic_try_cmpxchg(&mdev_avail_ports,
-				     &avail_ports, avail_ports - nr_ports));
+				     &avail_ports,
+				     avail_ports - type->nr_ports));
 
-	mdev_state->nr_ports = nr_ports;
+	mdev_state->nr_ports = type->nr_ports;
 	mdev_state->irq_index = -1;
 	mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
 	mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE;
@@ -735,7 +751,7 @@ static int mtty_init_dev(struct vfio_device *vdev)
 	return 0;
 
 err_nr_ports:
-	atomic_add(nr_ports, &mdev_avail_ports);
+	atomic_add(type->nr_ports, &mdev_avail_ports);
 	return ret;
 }
 
@@ -1242,11 +1258,9 @@ static const struct attribute_group *mdev_dev_groups[] = {
 static ssize_t name_show(struct mdev_type *mtype,
 			 struct mdev_type_attribute *attr, char *buf)
 {
-	static const char *name_str[2] = { "Single port serial",
-					   "Dual port serial" };
+	struct mtty_type *type = container_of(mtype, struct mtty_type, type);
 
-	return sysfs_emit(buf, "%s\n",
-			  name_str[mtype_get_type_group_id(mtype)]);
+	return sysfs_emit(buf, "%s\n", type->name);
 }
 
 static MDEV_TYPE_ATTR_RO(name);
@@ -1255,9 +1269,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
 {
-	unsigned int ports = mtype_get_type_group_id(mtype) + 1;
+	struct mtty_type *type = container_of(mtype, struct mtty_type, type);
 
-	return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) / ports);
+	return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
+			type->nr_ports);
 }
 
 static MDEV_TYPE_ATTR_RO(available_instances);
@@ -1270,29 +1285,13 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(device_api);
 
-static struct attribute *mdev_types_attrs[] = {
+static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
-static struct attribute_group mdev_type_group1 = {
-	.name  = "1",
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group mdev_type_group2 = {
-	.name  = "2",
-	.attrs = mdev_types_attrs,
-};
-
-static struct attribute_group *mdev_type_groups[] = {
-	&mdev_type_group1,
-	&mdev_type_group2,
-	NULL,
-};
-
 static const struct vfio_device_ops mtty_dev_ops = {
 	.name = "vfio-mtty",
 	.init = mtty_init_dev,
@@ -1311,7 +1310,7 @@ static struct mdev_driver mtty_driver = {
 	},
 	.probe = mtty_probe,
 	.remove	= mtty_remove,
-	.supported_type_groups = mdev_type_groups,
+	.types_attrs = mdev_types_attrs,
 };
 
 static void mtty_device_release(struct device *dev)
@@ -1363,7 +1362,8 @@ static int __init mtty_dev_init(void)
 		goto err_class;
 
 	ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,
-				   &mtty_driver);
+				   &mtty_driver, mtty_mdev_types,
+				   ARRAY_SIZE(mtty_mdev_types));
 	if (ret)
 		goto err_device;
 	return 0;
-- 
2.30.2


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

* [PATCH 06/14] vfio/mdev: remove mdev_from_dev
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (4 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 05/14] vfio/mdev: simplify mdev_type handling Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 07/14] vfio/mdev: unexport mdev_bus_type Christoph Hellwig
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code it in the only caller.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed By: Kirti Wankhede <kwankhede@nvidia.com>
---
 drivers/vfio/mdev/mdev_core.c | 6 ++----
 include/linux/mdev.h          | 4 ----
 2 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 2d95a497fd3b2..bde7ce620dae0 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -53,10 +53,8 @@ static void mdev_device_remove_common(struct mdev_device *mdev)
 
 static int mdev_device_remove_cb(struct device *dev, void *data)
 {
-	struct mdev_device *mdev = mdev_from_dev(dev);
-
-	if (mdev)
-		mdev_device_remove_common(mdev);
+	if (dev->bus == &mdev_bus_type)
+		mdev_device_remove_common(to_mdev_device(dev));
 	return 0;
 }
 
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 19bc93c10e8c7..4f558de52fd94 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -102,9 +102,5 @@ static inline struct device *mdev_dev(struct mdev_device *mdev)
 {
 	return &mdev->dev;
 }
-static inline struct mdev_device *mdev_from_dev(struct device *dev)
-{
-	return dev->bus == &mdev_bus_type ? to_mdev_device(dev) : NULL;
-}
 
 #endif /* MDEV_H */
-- 
2.30.2


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

* [PATCH 07/14] vfio/mdev: unexport mdev_bus_type
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (5 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 06/14] vfio/mdev: remove mdev_from_dev Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

mdev_bus_type is only used in mdev.ko now, so unexport it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 drivers/vfio/mdev/mdev_driver.c  | 1 -
 drivers/vfio/mdev/mdev_private.h | 1 +
 include/linux/mdev.h             | 2 --
 3 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 1da1ecf76a0d5..5b3c94f4fb13d 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -46,7 +46,6 @@ struct bus_type mdev_bus_type = {
 	.remove		= mdev_remove,
 	.match		= mdev_match,
 };
-EXPORT_SYMBOL_GPL(mdev_bus_type);
 
 /**
  * mdev_register_driver - register a new MDEV driver
diff --git a/drivers/vfio/mdev/mdev_private.h b/drivers/vfio/mdev/mdev_private.h
index ba1b2dbddc0bc..af457b27f6074 100644
--- a/drivers/vfio/mdev/mdev_private.h
+++ b/drivers/vfio/mdev/mdev_private.h
@@ -13,6 +13,7 @@
 int  mdev_bus_register(void);
 void mdev_bus_unregister(void);
 
+extern struct bus_type mdev_bus_type;
 extern const struct attribute_group *mdev_device_groups[];
 
 #define to_mdev_type_attr(_attr)	\
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 4f558de52fd94..6c179d2b89274 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -87,8 +87,6 @@ struct mdev_driver {
 	struct device_driver driver;
 };
 
-extern struct bus_type mdev_bus_type;
-
 int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
 		struct mdev_driver *mdev_driver, struct mdev_type **types,
 		unsigned int nr_types);
-- 
2.30.2


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

* [PATCH 08/14] vfio/mdev: remove mdev_parent_dev
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (6 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 07/14] vfio/mdev: unexport mdev_bus_type Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev Christoph Hellwig
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code the dereferences in the only user.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 Documentation/driver-api/vfio-mediated-device.rst | 3 ---
 drivers/gpu/drm/i915/gvt/kvmgt.c                  | 2 +-
 drivers/vfio/mdev/mdev_core.c                     | 6 ------
 include/linux/mdev.h                              | 1 -
 4 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index ff7342d2e332d..7b660f3fa2c92 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -200,9 +200,6 @@ Directories and files under the sysfs for Each Physical Device
 
 	sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
 
-  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
-  of the core mdev code)
-
 * device_api
 
   This attribute should show which device API is being created, for example,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index ce6b8cb37be0c..1947f553fcd38 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1488,7 +1488,7 @@ static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
 	struct intel_vgpu_type *type =
 		container_of(mdev->type, struct intel_vgpu_type, type);
 
-	vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt;
+	vgpu->gvt = kdev_to_i915(mdev->type->parent->dev)->gvt;
 	return intel_gvt_create_vgpu(vgpu, type->conf);
 }
 
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index bde7ce620dae0..75628759a3bf0 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -23,12 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
 static LIST_HEAD(mdev_list);
 static DEFINE_MUTEX(mdev_list_lock);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev)
-{
-	return mdev->type->parent->dev;
-}
-EXPORT_SYMBOL(mdev_parent_dev);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 6c179d2b89274..bbedffcb38d48 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -95,7 +95,6 @@ void mdev_unregister_parent(struct mdev_parent *parent);
 int mdev_register_driver(struct mdev_driver *drv);
 void mdev_unregister_driver(struct mdev_driver *drv);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev);
 static inline struct device *mdev_dev(struct mdev_device *mdev)
 {
 	return &mdev->dev;
-- 
2.30.2


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

* [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (7 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code the dereferences in the only user.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 drivers/s390/cio/vfio_ccw_ops.c |  3 +--
 drivers/vfio/mdev/mdev_core.c   | 10 ----------
 include/linux/mdev.h            |  2 --
 3 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index c37e712a4b069..3db6251b31143 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -62,8 +62,7 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
 {
-	struct vfio_ccw_private *private =
-		dev_get_drvdata(mtype_get_parent_dev(mtype));
+	struct vfio_ccw_private *private = dev_get_drvdata(mtype->parent->dev);
 
 	return sprintf(buf, "%d\n", atomic_read(&private->avail));
 }
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 75628759a3bf0..93f8caf2e5f77 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -23,16 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
 static LIST_HEAD(mdev_list);
 static DEFINE_MUTEX(mdev_list_lock);
 
-/*
- * Used in mdev_type_attribute sysfs functions to return the parent struct
- * device
- */
-struct device *mtype_get_parent_dev(struct mdev_type *mtype)
-{
-	return mtype->parent->dev;
-}
-EXPORT_SYMBOL(mtype_get_parent_dev);
-
 /* Caller must hold parent unreg_sem read or write lock */
 static void mdev_device_remove_common(struct mdev_device *mdev)
 {
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index bbedffcb38d48..e445f809ceca3 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -51,8 +51,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
 	return container_of(dev, struct mdev_device, dev);
 }
 
-struct device *mtype_get_parent_dev(struct mdev_type *mtype);
-
 /* interface for exporting mdev supported type attributes */
 struct mdev_type_attribute {
 	struct attribute attr;
-- 
2.30.2


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

* [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (8 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 11/14] vfio/mdev: consolidate all the name " Christoph Hellwig
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

From: Jason Gunthorpe <jgg@nvidia.com>

Every driver just emits a static string, simply feed it through the ops
and provide a standard sysfs show function.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |  2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c              |  9 +----
 drivers/s390/cio/vfio_ccw_ops.c               |  9 +----
 drivers/s390/crypto/vfio_ap_ops.c             | 10 +-----
 drivers/vfio/mdev/mdev_driver.c               |  4 ++-
 drivers/vfio/mdev/mdev_sysfs.c                | 35 +++++++++++++------
 include/linux/mdev.h                          |  7 ++--
 samples/vfio-mdev/mbochs.c                    |  9 +----
 samples/vfio-mdev/mdpy.c                      |  9 +----
 samples/vfio-mdev/mtty.c                      | 10 +-----
 10 files changed, 37 insertions(+), 67 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index 7b660f3fa2c92..b0c29e37f61b4 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -202,7 +202,7 @@ Directories and files under the sysfs for Each Physical Device
 
 * device_api
 
-  This attribute should show which device API is being created, for example,
+  This attribute shows which device API is being created, for example,
   "vfio-pci" for a PCI device.
 
 * available_instances
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 1947f553fcd38..9b2d3b078a2c9 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -123,12 +123,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 	return sprintf(buf, "%u\n", type->avail_instance);
 }
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
-}
-
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
@@ -151,13 +145,11 @@ static ssize_t name_show(struct mdev_type *mtype,
 }
 
 static MDEV_TYPE_ATTR_RO(available_instances);
-static MDEV_TYPE_ATTR_RO(device_api);
 static MDEV_TYPE_ATTR_RO(description);
 static MDEV_TYPE_ATTR_RO(name);
 
 static const struct attribute *gvt_type_attrs[] = {
 	&mdev_type_attr_available_instances.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_description.attr,
 	&mdev_type_attr_name.attr,
 	NULL,
@@ -1549,6 +1541,7 @@ static void intel_vgpu_remove(struct mdev_device *mdev)
 }
 
 static struct mdev_driver intel_vgpu_mdev_driver = {
+	.device_api	= VFIO_DEVICE_API_PCI_STRING,
 	.driver = {
 		.name		= "intel_vgpu_mdev",
 		.owner		= THIS_MODULE,
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 3db6251b31143..4c7b181519228 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -51,13 +51,6 @@ static ssize_t name_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(name);
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
-}
-static MDEV_TYPE_ATTR_RO(device_api);
-
 static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
@@ -70,7 +63,6 @@ static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -628,6 +620,7 @@ static const struct vfio_device_ops vfio_ccw_dev_ops = {
 };
 
 struct mdev_driver vfio_ccw_mdev_driver = {
+	.device_api = VFIO_DEVICE_API_CCW_STRING,
 	.driver = {
 		.name = "vfio_ccw_mdev",
 		.owner = THIS_MODULE,
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 24d131c502ca3..d440acfbb261e 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -808,17 +808,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
-}
-
-static MDEV_TYPE_ATTR_RO(device_api);
-
 static const struct attribute *vfio_ap_mdev_type_attrs[] = {
 	&mdev_type_attr_name.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -1799,6 +1790,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {
 };
 
 static struct mdev_driver vfio_ap_matrix_driver = {
+	.device_api = VFIO_DEVICE_API_AP_STRING,
 	.driver = {
 		.name = "vfio_ap_mdev",
 		.owner = THIS_MODULE,
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 5b3c94f4fb13d..60e8b9f6474e8 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -55,8 +55,10 @@ struct bus_type mdev_bus_type = {
  **/
 int mdev_register_driver(struct mdev_driver *drv)
 {
-	if (!drv->types_attrs)
+	if (!drv->types_attrs || !drv->device_api)
 		return -EINVAL;
+
+	/* initialize common driver fields */
 	drv->driver.bus = &mdev_bus_type;
 	return driver_register(&drv->driver);
 }
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 38b4c2466ec43..60fc52ff92448 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -72,9 +72,30 @@ static ssize_t create_store(struct mdev_type *mtype,
 
 	return count;
 }
-
 static MDEV_TYPE_ATTR_WO(create);
 
+static ssize_t device_api_show(struct mdev_type *mtype,
+			       struct mdev_type_attribute *attr, char *buf)
+{
+	return sysfs_emit(buf, "%s\n", mtype->parent->mdev_driver->device_api);
+}
+static MDEV_TYPE_ATTR_RO(device_api);
+
+static struct attribute *mdev_types_core_attrs[] = {
+	&mdev_type_attr_create.attr,
+	&mdev_type_attr_device_api.attr,
+	NULL,
+};
+
+static struct attribute_group mdev_type_core_group = {
+	.attrs = mdev_types_core_attrs,
+};
+
+static const struct attribute_group *mdev_type_groups[] = {
+	&mdev_type_core_group,
+	NULL,
+};
+
 static void mdev_type_release(struct kobject *kobj)
 {
 	struct mdev_type *type = to_mdev_type(kobj);
@@ -85,8 +106,9 @@ static void mdev_type_release(struct kobject *kobj)
 }
 
 static struct kobj_type mdev_type_ktype = {
-	.sysfs_ops = &mdev_type_sysfs_ops,
-	.release = mdev_type_release,
+	.sysfs_ops	= &mdev_type_sysfs_ops,
+	.release	= mdev_type_release,
+	.default_groups	= mdev_type_groups,
 };
 
 static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
@@ -106,10 +128,6 @@ static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 		return ret;
 	}
 
-	ret = sysfs_create_file(&type->kobj, &mdev_type_attr_create.attr);
-	if (ret)
-		goto attr_create_failed;
-
 	type->devices_kobj = kobject_create_and_add("devices", &type->kobj);
 	if (!type->devices_kobj) {
 		ret = -ENOMEM;
@@ -124,8 +142,6 @@ static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 attrs_failed:
 	kobject_put(type->devices_kobj);
 attr_devices_failed:
-	sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
-attr_create_failed:
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
 	return ret;
@@ -136,7 +152,6 @@ static void mdev_type_remove(struct mdev_type *type)
 	sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
 
 	kobject_put(type->devices_kobj);
-	sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
 }
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index e445f809ceca3..af1ff0165b8d3 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -61,11 +61,6 @@ struct mdev_type_attribute {
 			 size_t count);
 };
 
-#define MDEV_TYPE_ATTR(_name, _mode, _show, _store)		\
-struct mdev_type_attribute mdev_type_attr_##_name =		\
-	__ATTR(_name, _mode, _show, _store)
-#define MDEV_TYPE_ATTR_RW(_name) \
-	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RW(_name)
 #define MDEV_TYPE_ATTR_RO(_name) \
 	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
 #define MDEV_TYPE_ATTR_WO(_name) \
@@ -73,12 +68,14 @@ struct mdev_type_attribute mdev_type_attr_##_name =		\
 
 /**
  * struct mdev_driver - Mediated device driver
+ * @device_api: string to return for the device_api sysfs
  * @probe: called when new device created
  * @remove: called when device removed
  * @types_attrs: attributes to the type kobjects.
  * @driver: device driver structure
  **/
 struct mdev_driver {
+	const char *device_api;
 	int (*probe)(struct mdev_device *dev);
 	void (*remove)(struct mdev_device *dev);
 	const struct attribute * const *types_attrs;
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 4d0839cb51943..a2fc13fade757 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1384,17 +1384,9 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
-}
-static MDEV_TYPE_ATTR_RO(device_api);
-
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -1410,6 +1402,7 @@ static const struct vfio_device_ops mbochs_dev_ops = {
 };
 
 static struct mdev_driver mbochs_driver = {
+	.device_api = VFIO_DEVICE_API_PCI_STRING,
 	.driver = {
 		.name = "mbochs",
 		.owner = THIS_MODULE,
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 4a341f4849e73..f9069ed2750fa 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -689,17 +689,9 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
-}
-static MDEV_TYPE_ATTR_RO(device_api);
-
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -714,6 +706,7 @@ static const struct vfio_device_ops mdpy_dev_ops = {
 };
 
 static struct mdev_driver mdpy_driver = {
+	.device_api = VFIO_DEVICE_API_PCI_STRING,
 	.driver = {
 		.name = "mdpy",
 		.owner = THIS_MODULE,
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index 814a7f98738a2..064e71b28dd19 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -1277,17 +1277,8 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(available_instances);
 
-static ssize_t device_api_show(struct mdev_type *mtype,
-			       struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
-}
-
-static MDEV_TYPE_ATTR_RO(device_api);
-
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_name.attr,
-	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -1302,6 +1293,7 @@ static const struct vfio_device_ops mtty_dev_ops = {
 };
 
 static struct mdev_driver mtty_driver = {
+	.device_api = VFIO_DEVICE_API_PCI_STRING,
 	.driver = {
 		.name = "mtty",
 		.owner = THIS_MODULE,
-- 
2.30.2


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

* [PATCH 11/14] vfio/mdev: consolidate all the name sysfs into the core code
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (9 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 12/14] vfio/mdev: consolidate all the available_instance " Christoph Hellwig
                   ` (3 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Every driver just emits a static string, simply add a field to the
mdev_type for the driver to fill out or fall back to the sysfs name and
provide a standard sysfs show function.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |  2 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c              |  8 -------
 drivers/s390/cio/vfio_ccw_drv.c               |  1 +
 drivers/s390/cio/vfio_ccw_ops.c               |  8 -------
 drivers/s390/crypto/vfio_ap_ops.c             | 10 +--------
 drivers/vfio/mdev/mdev_sysfs.c                | 10 +++++++++
 include/linux/mdev.h                          |  1 +
 samples/vfio-mdev/mbochs.c                    | 20 ++++--------------
 samples/vfio-mdev/mdpy.c                      | 21 +++++--------------
 samples/vfio-mdev/mtty.c                      | 18 ++++------------
 10 files changed, 27 insertions(+), 72 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index b0c29e37f61b4..dcd1231a6fa84 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -217,7 +217,7 @@ Directories and files under the sysfs for Each Physical Device
 
 * name
 
-  This attribute should show human readable name. This is optional attribute.
+  This attribute shows a human readable name.
 
 * description
 
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 9b2d3b078a2c9..08fe7458b3610 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -138,20 +138,12 @@ static ssize_t description_show(struct mdev_type *mtype,
 		       type->conf->weight);
 }
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", mtype->sysfs_name);
-}
-
 static MDEV_TYPE_ATTR_RO(available_instances);
 static MDEV_TYPE_ATTR_RO(description);
-static MDEV_TYPE_ATTR_RO(name);
 
 static const struct attribute *gvt_type_attrs[] = {
 	&mdev_type_attr_available_instances.attr,
 	&mdev_type_attr_description.attr,
-	&mdev_type_attr_name.attr,
 	NULL,
 };
 
diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index 25a5de08b3902..e5f21c725326b 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -221,6 +221,7 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
 	dev_set_drvdata(&sch->dev, private);
 
 	private->mdev_type.sysfs_name = "io";
+	private->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)";
 	private->mdev_types[0] = &private->mdev_type;
 	ret = mdev_register_parent(&private->parent, &sch->dev,
 				   &vfio_ccw_mdev_driver,
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 4c7b181519228..394aab60dbd0a 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -44,13 +44,6 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
 	vfio_ccw_mdev_reset(private);
 }
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
-}
-static MDEV_TYPE_ATTR_RO(name);
-
 static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
@@ -62,7 +55,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_name.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index d440acfbb261e..5d8dd7e837f3d 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -790,14 +790,6 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
 	vfio_put_device(&matrix_mdev->vdev);
 }
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
-}
-
-static MDEV_TYPE_ATTR_RO(name);
-
 static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
@@ -809,7 +801,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *vfio_ap_mdev_type_attrs[] = {
-	&mdev_type_attr_name.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
@@ -1813,6 +1804,7 @@ int vfio_ap_mdev_register(void)
 		return ret;
 
 	matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT;
+	matrix_dev->mdev_type.pretty_name = VFIO_AP_MDEV_NAME_HWVIRT;
 	matrix_dev->mdev_types[0] = &matrix_dev->mdev_type;
 	ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev->device,
 				   &vfio_ap_matrix_driver,
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 60fc52ff92448..34583e6a97f27 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -81,9 +81,19 @@ static ssize_t device_api_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(device_api);
 
+static ssize_t name_show(struct mdev_type *mtype,
+			 struct mdev_type_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%s\n",
+		mtype->pretty_name ? mtype->pretty_name : mtype->sysfs_name);
+}
+
+static MDEV_TYPE_ATTR_RO(name);
+
 static struct attribute *mdev_types_core_attrs[] = {
 	&mdev_type_attr_create.attr,
 	&mdev_type_attr_device_api.attr,
+	&mdev_type_attr_name.attr,
 	NULL,
 };
 
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index af1ff0165b8d3..4bb8a58b577b3 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -26,6 +26,7 @@ struct mdev_device {
 struct mdev_type {
 	/* set by the driver before calling mdev_register parent: */
 	const char *sysfs_name;
+	const char *pretty_name;
 
 	/* set by the core, can be used drivers */
 	struct mdev_parent *parent;
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index a2fc13fade757..0b7585f16d8ab 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -101,26 +101,25 @@ MODULE_PARM_DESC(mem, "megabytes available to " MBOCHS_NAME " devices");
 
 static struct mbochs_type {
 	struct mdev_type type;
-	const char *name;
 	u32 mbytes;
 	u32 max_x;
 	u32 max_y;
 } mbochs_types[] = {
 	{
 		.type.sysfs_name	= MBOCHS_TYPE_1,
-		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
+		.type.pretty_name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
 		.mbytes = 4,
 		.max_x  = 800,
 		.max_y  = 600,
 	}, {
 		.type.sysfs_name	= MBOCHS_TYPE_2,
-		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
+		.type.pretty_name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
 		.mbytes = 16,
 		.max_x  = 1920,
 		.max_y  = 1440,
 	}, {
 		.type.sysfs_name	= MBOCHS_TYPE_3,
-		.name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
+		.type.pretty_name	= MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
 		.mbytes = 64,
 		.max_x  = 0,
 		.max_y  = 0,
@@ -556,7 +555,7 @@ static int mbochs_init_dev(struct vfio_device *vdev)
 	mbochs_reset(mdev_state);
 
 	dev_info(vdev->dev, "%s: %s, %d MB, %ld pages\n", __func__,
-		 type->name, type->mbytes, mdev_state->pagecount);
+		 type->type.pretty_name, type->mbytes, mdev_state->pagecount);
 	return 0;
 
 err_vconfig:
@@ -1351,16 +1350,6 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	struct mbochs_type *type =
-		container_of(mtype, struct mbochs_type, type);
-
-	return sprintf(buf, "%s\n", type->name);
-}
-static MDEV_TYPE_ATTR_RO(name);
-
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
@@ -1385,7 +1374,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index f9069ed2750fa..90c6fed200b19 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -53,7 +53,6 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
 
 static struct mdpy_type {
 	struct mdev_type type;
-	const char *name;
 	u32 format;
 	u32 bytepp;
 	u32 width;
@@ -61,21 +60,21 @@ static struct mdpy_type {
 } mdpy_types[] = {
 	{
 		.type.sysfs_name 	= MDPY_TYPE_1,
-		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_1,
+		.type.pretty_name	= MDPY_CLASS_NAME "-" MDPY_TYPE_1,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
 		.width	= 640,
 		.height = 480,
 	}, {
 		.type.sysfs_name 	= MDPY_TYPE_2,
-		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_2,
+		.type.pretty_name	= MDPY_CLASS_NAME "-" MDPY_TYPE_2,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
 		.width	= 1024,
 		.height = 768,
 	}, {
 		.type.sysfs_name 	= MDPY_TYPE_3,
-		.name	= MDPY_CLASS_NAME "-" MDPY_TYPE_3,
+		.type.pretty_name	= MDPY_CLASS_NAME "-" MDPY_TYPE_3,
 		.format = DRM_FORMAT_XRGB8888,
 		.bytepp = 4,
 		.width	= 1920,
@@ -256,8 +255,8 @@ static int mdpy_init_dev(struct vfio_device *vdev)
 	mdpy_create_config_space(mdev_state);
 	mdpy_reset(mdev_state);
 
-	dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type->name, type->width,
-		 type->height);
+	dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type->type.pretty_name,
+		 type->width, type->height);
 
 	mdpy_count++;
 	return 0;
@@ -662,15 +661,6 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
-
-	return sprintf(buf, "%s\n", type->name);
-}
-static MDEV_TYPE_ATTR_RO(name);
-
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
@@ -690,7 +680,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_name.attr,
 	&mdev_type_attr_description.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index 064e71b28dd19..eab1b4442a96e 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -146,10 +146,11 @@ struct mdev_state {
 static struct mtty_type {
 	struct mdev_type type;
 	int nr_ports;
-	const char *name;
 } mtty_types[2] = {
-	{ .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port serial" },
-	{ .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port serial" },
+	{ .nr_ports = 1, .type.sysfs_name = "1",
+	  .type.pretty_name = "Single port serial" },
+	{ .nr_ports = 2, .type.sysfs_name = "2",
+	  .type.pretty_name = "Dual port serial" },
 };
 
 static struct mdev_type *mtty_mdev_types[] = {
@@ -1255,16 +1256,6 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t name_show(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, char *buf)
-{
-	struct mtty_type *type = container_of(mtype, struct mtty_type, type);
-
-	return sysfs_emit(buf, "%s\n", type->name);
-}
-
-static MDEV_TYPE_ATTR_RO(name);
-
 static ssize_t available_instances_show(struct mdev_type *mtype,
 					struct mdev_type_attribute *attr,
 					char *buf)
@@ -1278,7 +1269,6 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_name.attr,
 	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
-- 
2.30.2


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

* [PATCH 12/14] vfio/mdev: consolidate all the available_instance sysfs into the core code
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (10 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 11/14] vfio/mdev: consolidate all the name " Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-23  9:26 ` [PATCH 13/14] vfio/mdev: consolidate all the description " Christoph Hellwig
                   ` (2 subsequent siblings)
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Every driver just print a number, simply add a method to the mdev_driver
to return it and provide a standard sysfs show function.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |  3 +-
 drivers/gpu/drm/i915/gvt/gvt.h                |  1 -
 drivers/gpu/drm/i915/gvt/kvmgt.c              | 34 +++++++++------
 drivers/gpu/drm/i915/gvt/vgpu.c               | 41 ++-----------------
 drivers/s390/cio/vfio_ccw_ops.c               | 14 ++-----
 drivers/s390/crypto/vfio_ap_ops.c             | 16 ++------
 drivers/vfio/mdev/mdev_sysfs.c                | 11 +++++
 include/linux/mdev.h                          |  2 +
 samples/vfio-mdev/mbochs.c                    | 10 ++---
 samples/vfio-mdev/mdpy.c                      |  9 ++--
 samples/vfio-mdev/mtty.c                      | 16 ++------
 11 files changed, 55 insertions(+), 102 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index dcd1231a6fa84..558bd7ebced86 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -103,6 +103,7 @@ structure to represent a mediated device's driver::
      struct mdev_driver {
 	     int  (*probe)  (struct mdev_device *dev);
 	     void (*remove) (struct mdev_device *dev);
+	     unsigned int (*get_available)(struct mdev_type *mtype);
 	     const struct attribute * const *types_attrs;
 	     struct device_driver    driver;
      };
@@ -207,7 +208,7 @@ Directories and files under the sysfs for Each Physical Device
 
 * available_instances
 
-  This attribute should show the number of devices of type <type-id> that can be
+  This attribute shows the number of devices of type <type-id> that can be
   created.
 
 * [device]
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index db182066d56c9..dbf8d7470b2c1 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -314,7 +314,6 @@ struct intel_vgpu_type {
 	struct mdev_type type;
 	char name[16];
 	const struct intel_vgpu_config *conf;
-	unsigned int avail_instance;
 };
 
 struct intel_gvt {
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 08fe7458b3610..d8be21a3931d9 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -113,16 +113,6 @@ static void kvmgt_page_track_flush_slot(struct kvm *kvm,
 		struct kvm_memory_slot *slot,
 		struct kvm_page_track_notifier_node *node);
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
-{
-	struct intel_vgpu_type *type =
-		container_of(mtype, struct intel_vgpu_type, type);
-
-	return sprintf(buf, "%u\n", type->avail_instance);
-}
-
 static ssize_t description_show(struct mdev_type *mtype,
 				struct mdev_type_attribute *attr, char *buf)
 {
@@ -138,11 +128,9 @@ static ssize_t description_show(struct mdev_type *mtype,
 		       type->conf->weight);
 }
 
-static MDEV_TYPE_ATTR_RO(available_instances);
 static MDEV_TYPE_ATTR_RO(description);
 
 static const struct attribute *gvt_type_attrs[] = {
-	&mdev_type_attr_available_instances.attr,
 	&mdev_type_attr_description.attr,
 	NULL,
 };
@@ -1532,6 +1520,27 @@ static void intel_vgpu_remove(struct mdev_device *mdev)
 	vfio_put_device(&vgpu->vfio_device);
 }
 
+static unsigned int intel_vgpu_get_available(struct mdev_type *mtype)
+{
+	struct intel_vgpu_type *type =
+		container_of(mtype, struct intel_vgpu_type, type);
+	struct intel_gvt *gvt = kdev_to_i915(mtype->parent->dev)->gvt;
+	unsigned int low_gm_avail, high_gm_avail, fence_avail;
+
+	mutex_lock(&gvt->lock);
+	low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE -
+		gvt->gm.vgpu_allocated_low_gm_size;
+	high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE -
+		gvt->gm.vgpu_allocated_high_gm_size;
+	fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
+		gvt->fence.vgpu_allocated_fence_num;
+	mutex_unlock(&gvt->lock);
+
+	return min3(low_gm_avail / type->conf->low_mm,
+		    high_gm_avail / type->conf->high_mm,
+		    fence_avail / type->conf->fence);
+}
+
 static struct mdev_driver intel_vgpu_mdev_driver = {
 	.device_api	= VFIO_DEVICE_API_PCI_STRING,
 	.driver = {
@@ -1541,6 +1550,7 @@ static struct mdev_driver intel_vgpu_mdev_driver = {
 	},
 	.probe		= intel_vgpu_probe,
 	.remove		= intel_vgpu_remove,
+	.get_available	= intel_vgpu_get_available,
 	.types_attrs	= gvt_type_attrs,
 };
 
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 8fa06d00fd4b9..148bf5d6c4fd4 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -129,11 +129,11 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 		sprintf(gvt->types[i].name, "GVTg_V%u_%s",
 			GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
 		gvt->types->conf = conf;
-		gvt->types[i].avail_instance = min(low_avail / conf->low_mm,
-						   high_avail / conf->high_mm);
 
 		gvt_dbg_core("type[%d]: %s avail %u low %u high %u fence %u weight %u res %s\n",
-			     i, gvt->types[i].name, gvt->types[i].avail_instance,
+			     i, gvt->types[i].name,
+			     min(low_avail / conf->low_mm,
+				 high_avail / conf->high_mm),
 			     conf->low_mm, conf->high_mm, conf->fence,
 			     conf->weight, vgpu_edid_str(conf->edid));
 
@@ -157,36 +157,6 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
 	kfree(gvt->types);
 }
 
-static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
-{
-	int i;
-	unsigned int low_gm_avail, high_gm_avail, fence_avail;
-	unsigned int low_gm_min, high_gm_min, fence_min;
-
-	/* Need to depend on maxium hw resource size but keep on
-	 * static config for now.
-	 */
-	low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE -
-		gvt->gm.vgpu_allocated_low_gm_size;
-	high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE -
-		gvt->gm.vgpu_allocated_high_gm_size;
-	fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
-		gvt->fence.vgpu_allocated_fence_num;
-
-	for (i = 0; i < gvt->num_types; i++) {
-		low_gm_min = low_gm_avail / gvt->types[i].conf->low_mm;
-		high_gm_min = high_gm_avail / gvt->types[i].conf->high_mm;
-		fence_min = fence_avail / gvt->types[i].conf->fence;
-		gvt->types[i].avail_instance = min(min(low_gm_min, high_gm_min),
-						   fence_min);
-
-		gvt_dbg_core("update type[%d]: %s avail %u low %u high %u fence %u\n",
-		       i, gvt->types[i].name,
-		       gvt->types[i].avail_instance, gvt->types[i].conf->low_mm,
-		       gvt->types[i].conf->high_mm, gvt->types[i].conf->fence);
-	}
-}
-
 /**
  * intel_gvt_active_vgpu - activate a virtual GPU
  * @vgpu: virtual GPU
@@ -281,10 +251,6 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
 	intel_vgpu_clean_mmio(vgpu);
 	intel_vgpu_dmabuf_cleanup(vgpu);
 	mutex_unlock(&vgpu->vgpu_lock);
-
-	mutex_lock(&gvt->lock);
-	intel_gvt_update_vgpu_types(gvt);
-	mutex_unlock(&gvt->lock);
 }
 
 #define IDLE_VGPU_IDR 0
@@ -414,7 +380,6 @@ int intel_gvt_create_vgpu(struct intel_vgpu *vgpu,
 	if (ret)
 		goto out_clean_sched_policy;
 
-	intel_gvt_update_vgpu_types(gvt);
 	intel_gvt_update_reg_whitelist(vgpu);
 	mutex_unlock(&gvt->lock);
 	return 0;
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 394aab60dbd0a..559ca18055928 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -44,20 +44,12 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
 	vfio_ccw_mdev_reset(private);
 }
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
+static unsigned int vfio_ccw_get_available(struct mdev_type *mtype)
 {
 	struct vfio_ccw_private *private = dev_get_drvdata(mtype->parent->dev);
 
-	return sprintf(buf, "%d\n", atomic_read(&private->avail));
+	return atomic_read(&private->avail);
 }
-static MDEV_TYPE_ATTR_RO(available_instances);
-
-static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_available_instances.attr,
-	NULL,
-};
 
 static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
 {
@@ -620,5 +612,5 @@ struct mdev_driver vfio_ccw_mdev_driver = {
 	},
 	.probe = vfio_ccw_mdev_probe,
 	.remove = vfio_ccw_mdev_remove,
-	.types_attrs = mdev_types_attrs,
+	.get_available = vfio_ccw_get_available,
 };
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 5d8dd7e837f3d..8606f5d75188c 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -790,21 +790,11 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
 	vfio_put_device(&matrix_mdev->vdev);
 }
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
+static unsigned int vfio_ap_mdev_get_available(struct mdev_type *mtype)
 {
-	return sprintf(buf, "%d\n",
-		       atomic_read(&matrix_dev->available_instances));
+	return atomic_read(&matrix_dev->available_instances);
 }
 
-static MDEV_TYPE_ATTR_RO(available_instances);
-
-static const struct attribute *vfio_ap_mdev_type_attrs[] = {
-	&mdev_type_attr_available_instances.attr,
-	NULL,
-};
-
 #define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
 			 "already assigned to %s"
 
@@ -1790,7 +1780,7 @@ static struct mdev_driver vfio_ap_matrix_driver = {
 	},
 	.probe = vfio_ap_mdev_probe,
 	.remove = vfio_ap_mdev_remove,
-	.types_attrs = vfio_ap_mdev_type_attrs,
+	.get_available = vfio_ap_mdev_get_available,
 };
 
 int vfio_ap_mdev_register(void)
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 34583e6a97f27..b7f87c3eda5ea 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -90,10 +90,21 @@ static ssize_t name_show(struct mdev_type *mtype,
 
 static MDEV_TYPE_ATTR_RO(name);
 
+static ssize_t available_instances_show(struct mdev_type *mtype,
+					struct mdev_type_attribute *attr,
+					char *buf)
+{
+	struct mdev_driver *drv = mtype->parent->mdev_driver;
+
+	return sysfs_emit(buf, "%u\n", drv->get_available(mtype));
+}
+static MDEV_TYPE_ATTR_RO(available_instances);
+
 static struct attribute *mdev_types_core_attrs[] = {
 	&mdev_type_attr_create.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_name.attr,
+	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 4bb8a58b577b3..d39e08a1824c6 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -72,6 +72,7 @@ struct mdev_type_attribute {
  * @device_api: string to return for the device_api sysfs
  * @probe: called when new device created
  * @remove: called when device removed
+ * @get_available: Return the max number of instances that can be created
  * @types_attrs: attributes to the type kobjects.
  * @driver: device driver structure
  **/
@@ -79,6 +80,7 @@ struct mdev_driver {
 	const char *device_api;
 	int (*probe)(struct mdev_device *dev);
 	void (*remove)(struct mdev_device *dev);
+	unsigned int (*get_available)(struct mdev_type *mtype);
 	const struct attribute * const *types_attrs;
 	struct device_driver driver;
 };
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 0b7585f16d8ab..6c2cbc4e25ca9 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1361,21 +1361,16 @@ static ssize_t description_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(description);
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
+static unsigned int mbochs_get_available(struct mdev_type *mtype)
 {
 	struct mbochs_type *type =
 		container_of(mtype, struct mbochs_type, type);
-	int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
 
-	return sprintf(buf, "%d\n", count);
+	return atomic_read(&mbochs_avail_mbytes) / type->mbytes;
 }
-static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_description.attr,
-	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
@@ -1399,6 +1394,7 @@ static struct mdev_driver mbochs_driver = {
 	},
 	.probe = mbochs_probe,
 	.remove	= mbochs_remove,
+	.get_available = mbochs_get_available,
 	.types_attrs = mdev_types_attrs,
 };
 
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index 90c6fed200b19..d1c835c9cabf2 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -671,17 +671,13 @@ static ssize_t description_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(description);
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
+static unsigned int mdpy_get_available(struct mdev_type *mtype)
 {
-	return sprintf(buf, "%d\n", max_devices - mdpy_count);
+	return max_devices - mdpy_count;
 }
-static MDEV_TYPE_ATTR_RO(available_instances);
 
 static const struct attribute *mdev_types_attrs[] = {
 	&mdev_type_attr_description.attr,
-	&mdev_type_attr_available_instances.attr,
 	NULL,
 };
 
@@ -704,6 +700,7 @@ static struct mdev_driver mdpy_driver = {
 	},
 	.probe = mdpy_probe,
 	.remove	= mdpy_remove,
+	.get_available = mdpy_get_available,
 	.types_attrs = mdev_types_attrs,
 };
 
diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
index eab1b4442a96e..e72085fc13763 100644
--- a/samples/vfio-mdev/mtty.c
+++ b/samples/vfio-mdev/mtty.c
@@ -1256,23 +1256,13 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t available_instances_show(struct mdev_type *mtype,
-					struct mdev_type_attribute *attr,
-					char *buf)
+static unsigned int mtty_get_available(struct mdev_type *mtype)
 {
 	struct mtty_type *type = container_of(mtype, struct mtty_type, type);
 
-	return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
-			type->nr_ports);
+	return atomic_read(&mdev_avail_ports) / type->nr_ports;
 }
 
-static MDEV_TYPE_ATTR_RO(available_instances);
-
-static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_available_instances.attr,
-	NULL,
-};
-
 static const struct vfio_device_ops mtty_dev_ops = {
 	.name = "vfio-mtty",
 	.init = mtty_init_dev,
@@ -1292,7 +1282,7 @@ static struct mdev_driver mtty_driver = {
 	},
 	.probe = mtty_probe,
 	.remove	= mtty_remove,
-	.types_attrs = mdev_types_attrs,
+	.get_available = mtty_get_available,
 };
 
 static void mtty_device_release(struct device *dev)
-- 
2.30.2


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

* [PATCH 13/14] vfio/mdev: consolidate all the description sysfs into the core code
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (11 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 12/14] vfio/mdev: consolidate all the available_instance " Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-23  9:26 ` [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core Christoph Hellwig
  2022-09-27 20:07 ` simplify the mdev interface v8 Alex Williamson
  14 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Every driver just emits a string, simply add a method to the mdev_driver
to return it and provide a standard sysfs show function.

Remove the now unused types_attrs field in struct mdev_driver and the
support code for it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 .../driver-api/vfio-mediated-device.rst       |  4 +-
 drivers/gpu/drm/i915/gvt/kvmgt.c              | 18 +++------
 drivers/vfio/mdev/mdev_driver.c               |  2 +-
 drivers/vfio/mdev/mdev_sysfs.c                | 40 +++++++++++++++----
 include/linux/mdev.h                          | 19 +--------
 samples/vfio-mdev/mbochs.c                    | 11 +----
 samples/vfio-mdev/mdpy.c                      | 11 +----
 7 files changed, 46 insertions(+), 59 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index 558bd7ebced86..fdf7d69378ec4 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -104,7 +104,7 @@ structure to represent a mediated device's driver::
 	     int  (*probe)  (struct mdev_device *dev);
 	     void (*remove) (struct mdev_device *dev);
 	     unsigned int (*get_available)(struct mdev_type *mtype);
-	     const struct attribute * const *types_attrs;
+	     ssize_t (*show_description)(struct mdev_type *mtype, char *buf);
 	     struct device_driver    driver;
      };
 
@@ -222,7 +222,7 @@ Directories and files under the sysfs for Each Physical Device
 
 * description
 
-  This attribute should show brief features/description of the type. This is
+  This attribute can show brief features/description of the type. This is an
   optional attribute.
 
 Directories and Files Under the sysfs for Each mdev Device
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index d8be21a3931d9..f3aa6e08e83d7 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -113,8 +113,7 @@ static void kvmgt_page_track_flush_slot(struct kvm *kvm,
 		struct kvm_memory_slot *slot,
 		struct kvm_page_track_notifier_node *node);
 
-static ssize_t description_show(struct mdev_type *mtype,
-				struct mdev_type_attribute *attr, char *buf)
+static ssize_t intel_vgpu_show_description(struct mdev_type *mtype, char *buf)
 {
 	struct intel_vgpu_type *type =
 		container_of(mtype, struct intel_vgpu_type, type);
@@ -128,13 +127,6 @@ static ssize_t description_show(struct mdev_type *mtype,
 		       type->conf->weight);
 }
 
-static MDEV_TYPE_ATTR_RO(description);
-
-static const struct attribute *gvt_type_attrs[] = {
-	&mdev_type_attr_description.attr,
-	NULL,
-};
-
 static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned long gfn,
 		unsigned long size)
 {
@@ -1548,10 +1540,10 @@ static struct mdev_driver intel_vgpu_mdev_driver = {
 		.owner		= THIS_MODULE,
 		.dev_groups	= intel_vgpu_groups,
 	},
-	.probe		= intel_vgpu_probe,
-	.remove		= intel_vgpu_remove,
-	.get_available	= intel_vgpu_get_available,
-	.types_attrs	= gvt_type_attrs,
+	.probe			= intel_vgpu_probe,
+	.remove			= intel_vgpu_remove,
+	.get_available		= intel_vgpu_get_available,
+	.show_description	= intel_vgpu_show_description,
 };
 
 int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn)
diff --git a/drivers/vfio/mdev/mdev_driver.c b/drivers/vfio/mdev/mdev_driver.c
index 60e8b9f6474e8..7825d83a55f8c 100644
--- a/drivers/vfio/mdev/mdev_driver.c
+++ b/drivers/vfio/mdev/mdev_driver.c
@@ -55,7 +55,7 @@ struct bus_type mdev_bus_type = {
  **/
 int mdev_register_driver(struct mdev_driver *drv)
 {
-	if (!drv->types_attrs || !drv->device_api)
+	if (!drv->device_api)
 		return -EINVAL;
 
 	/* initialize common driver fields */
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index b7f87c3eda5ea..658b3bf5ed0bf 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -14,7 +14,19 @@
 
 #include "mdev_private.h"
 
-/* Static functions */
+struct mdev_type_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct mdev_type *mtype,
+			struct mdev_type_attribute *attr, char *buf);
+	ssize_t (*store)(struct mdev_type *mtype,
+			 struct mdev_type_attribute *attr, const char *buf,
+			 size_t count);
+};
+
+#define MDEV_TYPE_ATTR_RO(_name) \
+	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
+#define MDEV_TYPE_ATTR_WO(_name) \
+	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_WO(_name)
 
 static ssize_t mdev_type_attr_show(struct kobject *kobj,
 				     struct attribute *__attr, char *buf)
@@ -100,16 +112,35 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
+static ssize_t description_show(struct mdev_type *mtype,
+				struct mdev_type_attribute *attr,
+				char *buf)
+{
+	return mtype->parent->mdev_driver->show_description(mtype, buf);
+}
+static MDEV_TYPE_ATTR_RO(description);
+
 static struct attribute *mdev_types_core_attrs[] = {
 	&mdev_type_attr_create.attr,
 	&mdev_type_attr_device_api.attr,
 	&mdev_type_attr_name.attr,
 	&mdev_type_attr_available_instances.attr,
+	&mdev_type_attr_description.attr,
 	NULL,
 };
 
+static umode_t mdev_types_core_is_visible(struct kobject *kobj,
+					  struct attribute *attr, int n)
+{
+	if (attr == &mdev_type_attr_description.attr &&
+	    !to_mdev_type(kobj)->parent->mdev_driver->show_description)
+		return 0;
+	return attr->mode;
+}
+
 static struct attribute_group mdev_type_core_group = {
 	.attrs = mdev_types_core_attrs,
+	.is_visible = mdev_types_core_is_visible,
 };
 
 static const struct attribute_group *mdev_type_groups[] = {
@@ -155,13 +186,8 @@ static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 		goto attr_devices_failed;
 	}
 
-	ret = sysfs_create_files(&type->kobj, parent->mdev_driver->types_attrs);
-	if (ret)
-		goto attrs_failed;
 	return 0;
 
-attrs_failed:
-	kobject_put(type->devices_kobj);
 attr_devices_failed:
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
@@ -170,8 +196,6 @@ static int mdev_type_add(struct mdev_parent *parent, struct mdev_type *type)
 
 static void mdev_type_remove(struct mdev_type *type)
 {
-	sysfs_remove_files(&type->kobj, type->parent->mdev_driver->types_attrs);
-
 	kobject_put(type->devices_kobj);
 	kobject_del(&type->kobj);
 	kobject_put(&type->kobj);
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index d39e08a1824c6..33674cb5ed5d4 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -52,28 +52,13 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
 	return container_of(dev, struct mdev_device, dev);
 }
 
-/* interface for exporting mdev supported type attributes */
-struct mdev_type_attribute {
-	struct attribute attr;
-	ssize_t (*show)(struct mdev_type *mtype,
-			struct mdev_type_attribute *attr, char *buf);
-	ssize_t (*store)(struct mdev_type *mtype,
-			 struct mdev_type_attribute *attr, const char *buf,
-			 size_t count);
-};
-
-#define MDEV_TYPE_ATTR_RO(_name) \
-	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_RO(_name)
-#define MDEV_TYPE_ATTR_WO(_name) \
-	struct mdev_type_attribute mdev_type_attr_##_name = __ATTR_WO(_name)
-
 /**
  * struct mdev_driver - Mediated device driver
  * @device_api: string to return for the device_api sysfs
  * @probe: called when new device created
  * @remove: called when device removed
  * @get_available: Return the max number of instances that can be created
- * @types_attrs: attributes to the type kobjects.
+ * @show_description: Print a description of the mtype
  * @driver: device driver structure
  **/
 struct mdev_driver {
@@ -81,7 +66,7 @@ struct mdev_driver {
 	int (*probe)(struct mdev_device *dev);
 	void (*remove)(struct mdev_device *dev);
 	unsigned int (*get_available)(struct mdev_type *mtype);
-	const struct attribute * const *types_attrs;
+	ssize_t (*show_description)(struct mdev_type *mtype, char *buf);
 	struct device_driver driver;
 };
 
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 6c2cbc4e25ca9..117a8d799f711 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1350,8 +1350,7 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t description_show(struct mdev_type *mtype,
-				struct mdev_type_attribute *attr, char *buf)
+static ssize_t mbochs_show_description(struct mdev_type *mtype, char *buf)
 {
 	struct mbochs_type *type =
 		container_of(mtype, struct mbochs_type, type);
@@ -1359,7 +1358,6 @@ static ssize_t description_show(struct mdev_type *mtype,
 	return sprintf(buf, "virtual display, %d MB video memory\n",
 		       type ? type->mbytes  : 0);
 }
-static MDEV_TYPE_ATTR_RO(description);
 
 static unsigned int mbochs_get_available(struct mdev_type *mtype)
 {
@@ -1369,11 +1367,6 @@ static unsigned int mbochs_get_available(struct mdev_type *mtype)
 	return atomic_read(&mbochs_avail_mbytes) / type->mbytes;
 }
 
-static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_description.attr,
-	NULL,
-};
-
 static const struct vfio_device_ops mbochs_dev_ops = {
 	.close_device = mbochs_close_device,
 	.init = mbochs_init_dev,
@@ -1395,7 +1388,7 @@ static struct mdev_driver mbochs_driver = {
 	.probe = mbochs_probe,
 	.remove	= mbochs_remove,
 	.get_available = mbochs_get_available,
-	.types_attrs = mdev_types_attrs,
+	.show_description = mbochs_show_description,
 };
 
 static const struct file_operations vd_fops = {
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index d1c835c9cabf2..a7cf59246ddd0 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -661,26 +661,19 @@ static const struct attribute_group *mdev_dev_groups[] = {
 	NULL,
 };
 
-static ssize_t description_show(struct mdev_type *mtype,
-				struct mdev_type_attribute *attr, char *buf)
+static ssize_t mdpy_show_description(struct mdev_type *mtype, char *buf)
 {
 	struct mdpy_type *type = container_of(mtype, struct mdpy_type, type);
 
 	return sprintf(buf, "virtual display, %dx%d framebuffer\n",
 		       type->width, type->height);
 }
-static MDEV_TYPE_ATTR_RO(description);
 
 static unsigned int mdpy_get_available(struct mdev_type *mtype)
 {
 	return max_devices - mdpy_count;
 }
 
-static const struct attribute *mdev_types_attrs[] = {
-	&mdev_type_attr_description.attr,
-	NULL,
-};
-
 static const struct vfio_device_ops mdpy_dev_ops = {
 	.init = mdpy_init_dev,
 	.release = mdpy_release_dev,
@@ -701,7 +694,7 @@ static struct mdev_driver mdpy_driver = {
 	.probe = mdpy_probe,
 	.remove	= mdpy_remove,
 	.get_available = mdpy_get_available,
-	.types_attrs = mdev_types_attrs,
+	.show_description = mdpy_show_description,
 };
 
 static const struct file_operations vd_fops = {
-- 
2.30.2


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

* [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (12 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 13/14] vfio/mdev: consolidate all the description " Christoph Hellwig
@ 2022-09-23  9:26 ` Christoph Hellwig
  2022-09-27  1:28   ` Eric Farman
  2022-09-27 20:07 ` simplify the mdev interface v8 Alex Williamson
  14 siblings, 1 reply; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-23  9:26 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

From: Jason Gunthorpe <jgg@nvidia.com>

Many of the mdev drivers use a simple counter for keeping track of the
available instances. Move this code to the core code and store the counter
in the mdev_parent. Implement it using correct locking, fixing mdpy.

Drivers just provide the value in the mdev_driver at registration time
and the core code takes care of maintaining it and exposing the value in
sysfs.

Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
[hch: count instances per-parent instead of per-type, use an atomic_t
 to avoid taking mdev_list_lock in the show method]
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 drivers/s390/cio/vfio_ccw_drv.c       |  1 -
 drivers/s390/cio/vfio_ccw_ops.c       | 15 +--------------
 drivers/s390/cio/vfio_ccw_private.h   |  2 --
 drivers/s390/crypto/vfio_ap_ops.c     | 13 +------------
 drivers/s390/crypto/vfio_ap_private.h |  2 --
 drivers/vfio/mdev/mdev_core.c         | 22 +++++++++++++++++++---
 drivers/vfio/mdev/mdev_sysfs.c        |  5 ++++-
 include/linux/mdev.h                  |  3 +++
 samples/vfio-mdev/mdpy.c              | 22 ++++------------------
 9 files changed, 32 insertions(+), 53 deletions(-)

diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
index e5f21c725326b..7f5402fe857a2 100644
--- a/drivers/s390/cio/vfio_ccw_drv.c
+++ b/drivers/s390/cio/vfio_ccw_drv.c
@@ -141,7 +141,6 @@ static struct vfio_ccw_private *vfio_ccw_alloc_private(struct subchannel *sch)
 	INIT_LIST_HEAD(&private->crw);
 	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
 	INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
-	atomic_set(&private->avail, 1);
 
 	private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX, sizeof(struct ccw1),
 				       GFP_KERNEL);
diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
index 559ca18055928..6ae4d012d8008 100644
--- a/drivers/s390/cio/vfio_ccw_ops.c
+++ b/drivers/s390/cio/vfio_ccw_ops.c
@@ -44,13 +44,6 @@ static void vfio_ccw_dma_unmap(struct vfio_device *vdev, u64 iova, u64 length)
 	vfio_ccw_mdev_reset(private);
 }
 
-static unsigned int vfio_ccw_get_available(struct mdev_type *mtype)
-{
-	struct vfio_ccw_private *private = dev_get_drvdata(mtype->parent->dev);
-
-	return atomic_read(&private->avail);
-}
-
 static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
 {
 	struct vfio_ccw_private *private =
@@ -68,9 +61,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
 	if (private->state == VFIO_CCW_STATE_NOT_OPER)
 		return -ENODEV;
 
-	if (atomic_dec_if_positive(&private->avail) < 0)
-		return -EPERM;
-
 	ret = vfio_init_device(&private->vdev, &mdev->dev, &vfio_ccw_dev_ops);
 	if (ret)
 		return ret;
@@ -88,7 +78,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device *mdev)
 
 err_put_vdev:
 	vfio_put_device(&private->vdev);
-	atomic_inc(&private->avail);
 	return ret;
 }
 
@@ -130,8 +119,6 @@ static void vfio_ccw_mdev_remove(struct mdev_device *mdev)
 	 * cycle.
 	 */
 	wait_for_completion(&private->release_comp);
-
-	atomic_inc(&private->avail);
 }
 
 static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
@@ -605,6 +592,7 @@ static const struct vfio_device_ops vfio_ccw_dev_ops = {
 
 struct mdev_driver vfio_ccw_mdev_driver = {
 	.device_api = VFIO_DEVICE_API_CCW_STRING,
+	.max_instances = 1,
 	.driver = {
 		.name = "vfio_ccw_mdev",
 		.owner = THIS_MODULE,
@@ -612,5 +600,4 @@ struct mdev_driver vfio_ccw_mdev_driver = {
 	},
 	.probe = vfio_ccw_mdev_probe,
 	.remove = vfio_ccw_mdev_remove,
-	.get_available = vfio_ccw_get_available,
 };
diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
index 52caa721ec06c..bd5fb81456af8 100644
--- a/drivers/s390/cio/vfio_ccw_private.h
+++ b/drivers/s390/cio/vfio_ccw_private.h
@@ -73,7 +73,6 @@ struct vfio_ccw_crw {
  * @sch: pointer to the subchannel
  * @state: internal state of the device
  * @completion: synchronization helper of the I/O completion
- * @avail: available for creating a mediated device
  * @io_region: MMIO region to input/output I/O arguments/results
  * @io_mutex: protect against concurrent update of I/O regions
  * @region: additional regions for other subchannel operations
@@ -97,7 +96,6 @@ struct vfio_ccw_private {
 	struct subchannel	*sch;
 	int			state;
 	struct completion	*completion;
-	atomic_t		avail;
 	struct ccw_io_region	*io_region;
 	struct mutex		io_mutex;
 	struct vfio_ccw_region *region;
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 8606f5d75188c..2884189f38771 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -689,9 +689,6 @@ static int vfio_ap_mdev_init_dev(struct vfio_device *vdev)
 	struct ap_matrix_mdev *matrix_mdev =
 		container_of(vdev, struct ap_matrix_mdev, vdev);
 
-	if ((atomic_dec_if_positive(&matrix_dev->available_instances) < 0))
-		return -EPERM;
-
 	matrix_mdev->mdev = to_mdev_device(vdev->dev);
 	vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
 	matrix_mdev->pqap_hook = handle_pqap;
@@ -770,7 +767,6 @@ static void vfio_ap_mdev_unlink_fr_queues(struct ap_matrix_mdev *matrix_mdev)
 
 static void vfio_ap_mdev_release_dev(struct vfio_device *vdev)
 {
-	atomic_inc(&matrix_dev->available_instances);
 	vfio_free_device(vdev);
 }
 
@@ -790,11 +786,6 @@ static void vfio_ap_mdev_remove(struct mdev_device *mdev)
 	vfio_put_device(&matrix_mdev->vdev);
 }
 
-static unsigned int vfio_ap_mdev_get_available(struct mdev_type *mtype)
-{
-	return atomic_read(&matrix_dev->available_instances);
-}
-
 #define MDEV_SHARING_ERR "Userspace may not re-assign queue %02lx.%04lx " \
 			 "already assigned to %s"
 
@@ -1772,6 +1763,7 @@ static const struct vfio_device_ops vfio_ap_matrix_dev_ops = {
 
 static struct mdev_driver vfio_ap_matrix_driver = {
 	.device_api = VFIO_DEVICE_API_AP_STRING,
+	.max_instances = MAX_ZDEV_ENTRIES_EXT,
 	.driver = {
 		.name = "vfio_ap_mdev",
 		.owner = THIS_MODULE,
@@ -1780,15 +1772,12 @@ static struct mdev_driver vfio_ap_matrix_driver = {
 	},
 	.probe = vfio_ap_mdev_probe,
 	.remove = vfio_ap_mdev_remove,
-	.get_available = vfio_ap_mdev_get_available,
 };
 
 int vfio_ap_mdev_register(void)
 {
 	int ret;
 
-	atomic_set(&matrix_dev->available_instances, MAX_ZDEV_ENTRIES_EXT);
-
 	ret = mdev_register_driver(&vfio_ap_matrix_driver);
 	if (ret)
 		return ret;
diff --git a/drivers/s390/crypto/vfio_ap_private.h b/drivers/s390/crypto/vfio_ap_private.h
index 441dc8dda380b..2eddd5f34ed34 100644
--- a/drivers/s390/crypto/vfio_ap_private.h
+++ b/drivers/s390/crypto/vfio_ap_private.h
@@ -29,7 +29,6 @@
  * struct ap_matrix_dev - Contains the data for the matrix device.
  *
  * @device:	generic device structure associated with the AP matrix device
- * @available_instances: number of mediated matrix devices that can be created
  * @info:	the struct containing the output from the PQAP(QCI) instruction
  * @mdev_list:	the list of mediated matrix devices created
  * @mdevs_lock: mutex for locking the AP matrix device. This lock will be
@@ -46,7 +45,6 @@
  */
 struct ap_matrix_dev {
 	struct device device;
-	atomic_t available_instances;
 	struct ap_config_info info;
 	struct list_head mdev_list;
 	struct mutex mdevs_lock; /* serializes access to each ap_matrix_mdev */
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index 93f8caf2e5f77..58f91b3bd670c 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -70,6 +70,7 @@ int mdev_register_parent(struct mdev_parent *parent, struct device *dev,
 	parent->mdev_driver = mdev_driver;
 	parent->types = types;
 	parent->nr_types = nr_types;
+	atomic_set(&parent->available_instances, mdev_driver->max_instances);
 
 	if (!mdev_bus_compat_class) {
 		mdev_bus_compat_class = class_compat_register("mdev_bus");
@@ -115,14 +116,17 @@ EXPORT_SYMBOL(mdev_unregister_parent);
 static void mdev_device_release(struct device *dev)
 {
 	struct mdev_device *mdev = to_mdev_device(dev);
-
-	/* Pairs with the get in mdev_device_create() */
-	kobject_put(&mdev->type->kobj);
+	struct mdev_parent *parent = mdev->type->parent;
 
 	mutex_lock(&mdev_list_lock);
 	list_del(&mdev->next);
+	if (!parent->mdev_driver->get_available)
+		atomic_inc(&parent->available_instances);
 	mutex_unlock(&mdev_list_lock);
 
+	/* Pairs with the get in mdev_device_create() */
+	kobject_put(&mdev->type->kobj);
+
 	dev_dbg(&mdev->dev, "MDEV: destroying\n");
 	kfree(mdev);
 }
@@ -144,6 +148,18 @@ int mdev_device_create(struct mdev_type *type, const guid_t *uuid)
 		}
 	}
 
+	if (!drv->get_available) {
+		/*
+		 * Note: that non-atomic read and dec is fine here because
+		 * all modifications are under mdev_list_lock.
+		 */
+		if (!atomic_read(&parent->available_instances)) {
+			mutex_unlock(&mdev_list_lock);
+			return -EUSERS;
+		}
+		atomic_dec(&parent->available_instances);
+	}
+
 	mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
 	if (!mdev) {
 		mutex_unlock(&mdev_list_lock);
diff --git a/drivers/vfio/mdev/mdev_sysfs.c b/drivers/vfio/mdev/mdev_sysfs.c
index 658b3bf5ed0bf..abe3359dd477f 100644
--- a/drivers/vfio/mdev/mdev_sysfs.c
+++ b/drivers/vfio/mdev/mdev_sysfs.c
@@ -108,7 +108,10 @@ static ssize_t available_instances_show(struct mdev_type *mtype,
 {
 	struct mdev_driver *drv = mtype->parent->mdev_driver;
 
-	return sysfs_emit(buf, "%u\n", drv->get_available(mtype));
+	if (drv->get_available)
+		return sysfs_emit(buf, "%u\n", drv->get_available(mtype));
+	return sysfs_emit(buf, "%u\n",
+			  atomic_read(&mtype->parent->available_instances));
 }
 static MDEV_TYPE_ATTR_RO(available_instances);
 
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 33674cb5ed5d4..139d05b26f820 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -45,6 +45,7 @@ struct mdev_parent {
 	struct rw_semaphore unreg_sem;
 	struct mdev_type **types;
 	unsigned int nr_types;
+	atomic_t available_instances;
 };
 
 static inline struct mdev_device *to_mdev_device(struct device *dev)
@@ -55,6 +56,7 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
 /**
  * struct mdev_driver - Mediated device driver
  * @device_api: string to return for the device_api sysfs
+ * @max_instances: maximum number of instances supported (optional)
  * @probe: called when new device created
  * @remove: called when device removed
  * @get_available: Return the max number of instances that can be created
@@ -63,6 +65,7 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
  **/
 struct mdev_driver {
 	const char *device_api;
+	unsigned int max_instances;
 	int (*probe)(struct mdev_device *dev);
 	void (*remove)(struct mdev_device *dev);
 	unsigned int (*get_available)(struct mdev_type *mtype);
diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
index a7cf59246ddd0..946e8cfde6fdd 100644
--- a/samples/vfio-mdev/mdpy.c
+++ b/samples/vfio-mdev/mdpy.c
@@ -42,11 +42,6 @@
 
 MODULE_LICENSE("GPL v2");
 
-static int max_devices = 4;
-module_param_named(count, max_devices, int, 0444);
-MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
-
-
 #define MDPY_TYPE_1 "vga"
 #define MDPY_TYPE_2 "xga"
 #define MDPY_TYPE_3 "hd"
@@ -93,7 +88,6 @@ static struct class	*mdpy_class;
 static struct cdev	mdpy_cdev;
 static struct device	mdpy_dev;
 static struct mdev_parent mdpy_parent;
-static u32		mdpy_count;
 static const struct vfio_device_ops mdpy_dev_ops;
 
 /* State of each mdev device */
@@ -235,9 +229,6 @@ static int mdpy_init_dev(struct vfio_device *vdev)
 	u32 fbsize;
 	int ret = -ENOMEM;
 
-	if (mdpy_count >= max_devices)
-		return ret;
-
 	mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE, GFP_KERNEL);
 	if (!mdev_state->vconfig)
 		return ret;
@@ -257,8 +248,6 @@ static int mdpy_init_dev(struct vfio_device *vdev)
 
 	dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type->type.pretty_name,
 		 type->width, type->height);
-
-	mdpy_count++;
 	return 0;
 
 out_vconfig:
@@ -292,7 +281,6 @@ static void mdpy_release_dev(struct vfio_device *vdev)
 	struct mdev_state *mdev_state =
 		container_of(vdev, struct mdev_state, vdev);
 
-	mdpy_count--;
 	vfree(mdev_state->memblk);
 	kfree(mdev_state->vconfig);
 	vfio_free_device(vdev);
@@ -669,11 +657,6 @@ static ssize_t mdpy_show_description(struct mdev_type *mtype, char *buf)
 		       type->width, type->height);
 }
 
-static unsigned int mdpy_get_available(struct mdev_type *mtype)
-{
-	return max_devices - mdpy_count;
-}
-
 static const struct vfio_device_ops mdpy_dev_ops = {
 	.init = mdpy_init_dev,
 	.release = mdpy_release_dev,
@@ -685,6 +668,7 @@ static const struct vfio_device_ops mdpy_dev_ops = {
 
 static struct mdev_driver mdpy_driver = {
 	.device_api = VFIO_DEVICE_API_PCI_STRING,
+	.max_instances = 4,
 	.driver = {
 		.name = "mdpy",
 		.owner = THIS_MODULE,
@@ -693,7 +677,6 @@ static struct mdev_driver mdpy_driver = {
 	},
 	.probe = mdpy_probe,
 	.remove	= mdpy_remove,
-	.get_available = mdpy_get_available,
 	.show_description = mdpy_show_description,
 };
 
@@ -770,5 +753,8 @@ static void __exit mdpy_dev_exit(void)
 	mdpy_class = NULL;
 }
 
+module_param_named(count, mdpy_driver.max_instances, int, 0444);
+MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
+
 module_init(mdpy_dev_init)
 module_exit(mdpy_dev_exit)
-- 
2.30.2


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

* Re: [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure
  2022-09-23  9:26 ` [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> Simplify mdev_{un}register_device by requiring the caller to pass in
> a structure allocate as part of the parent device structure.  This
> removes the need for a list of parents and the separate mdev_parent
> refcount as we can simplify rely on the reference to the parent
> device.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  .../driver-api/vfio-mediated-device.rst       |  12 +-
>  Documentation/s390/vfio-ap.rst                |   2 +-
>  Documentation/s390/vfio-ccw.rst               |   2 +-
>  drivers/gpu/drm/i915/gvt/gvt.h                |   2 +
>  drivers/gpu/drm/i915/gvt/kvmgt.c              |   5 +-
>  drivers/s390/cio/vfio_ccw_drv.c               |   5 +-
>  drivers/s390/cio/vfio_ccw_ops.c               |   1 -
>  drivers/s390/cio/vfio_ccw_private.h           |   4 +
>  drivers/s390/crypto/vfio_ap_ops.c             |   5 +-
>  drivers/s390/crypto/vfio_ap_private.h         |   1 +
>  drivers/vfio/mdev/mdev_core.c                 | 120 ++++------------
> --
>  drivers/vfio/mdev/mdev_private.h              |  23 ----
>  drivers/vfio/mdev/mdev_sysfs.c                |   4 +-
>  include/linux/mdev.h                          |  15 ++-
>  samples/vfio-mdev/mbochs.c                    |   5 +-
>  samples/vfio-mdev/mdpy.c                      |   5 +-
>  samples/vfio-mdev/mtty.c                      |   6 +-
>  17 files changed, 71 insertions(+), 146 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index f47dca6645aae..cd1667608ab5d 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -58,19 +58,19 @@ devices as examples, as these devices are the
> first devices to use this module::
>       |  MDEV CORE    |
>       |   MODULE      |
>       |   mdev.ko     |
> -     | +-----------+ |  mdev_register_device() +--------------+
> +     | +-----------+ |  mdev_register_parent() +--------------+
>       | |           | +<------------------------+              |
>       | |           | |                         |  nvidia.ko   |<->
> physical
>       | |           | +------------------------>+              |   
> device
>       | |           | |        callbacks        +--------------+
>       | | Physical  | |
> -     | |  device   | |  mdev_register_device() +--------------+
> +     | |  device   | |  mdev_register_parent() +--------------+
>       | | interface | |<------------------------+              |
>       | |           | |                         |  i915.ko     |<->
> physical
>       | |           | +------------------------>+              |   
> device
>       | |           | |        callbacks        +--------------+
>       | |           | |
> -     | |           | |  mdev_register_device() +--------------+
> +     | |           | |  mdev_register_parent() +--------------+
>       | |           | +<------------------------+              |
>       | |           | |                         | ccw_device.ko|<->
> physical
>       | |           | +------------------------>+              |   
> device
> @@ -125,8 +125,8 @@ vfio_device_ops.
>  When a driver wants to add the GUID creation sysfs to an existing
> device it has
>  probe'd to then it should call::
>  
> -    int mdev_register_device(struct device *dev,
> -                             struct mdev_driver *mdev_driver);
> +    int mdev_register_parent(struct mdev_parent *parent, struct
> device *dev,
> +                       struct mdev_driver *mdev_driver);
>  
>  This will provide the 'mdev_supported_types/XX/create' files which
> can then be
>  used to trigger the creation of a mdev_device. The created
> mdev_device will be
> @@ -134,7 +134,7 @@ attached to the specified driver.
>  
>  When the driver needs to remove itself it calls::
>  
> -    void mdev_unregister_device(struct device *dev);
> +    void mdev_unregister_parent(struct mdev_parent *parent);
>  
>  Which will unbind and destroy all the created mdevs and remove the
> sysfs files.
>  
> diff --git a/Documentation/s390/vfio-ap.rst
> b/Documentation/s390/vfio-ap.rst
> index 61a0a3c6c7b4b..00f4a04f6d4c6 100644
> --- a/Documentation/s390/vfio-ap.rst
> +++ b/Documentation/s390/vfio-ap.rst
> @@ -297,7 +297,7 @@ of the VFIO AP mediated device driver::
>     |  MDEV CORE  |
>     |   MODULE    |
>     |   mdev.ko   |
> -   | +---------+ | mdev_register_device() +--------------+
> +   | +---------+ | mdev_register_parent() +--------------+
>     | |Physical | +<-----------------------+              |
>     | | device  | |                        |  vfio_ap.ko  |<-> matrix
>     | |interface| +----------------------->+              |    device
> diff --git a/Documentation/s390/vfio-ccw.rst
> b/Documentation/s390/vfio-ccw.rst
> index 8aad08a8b8a50..ea928a3806f43 100644
> --- a/Documentation/s390/vfio-ccw.rst
> +++ b/Documentation/s390/vfio-ccw.rst
> @@ -156,7 +156,7 @@ Below is a high Level block diagram::
>   |  MDEV CORE  |
>   |   MODULE    |
>   |   mdev.ko   |
> - | +---------+ | mdev_register_device() +--------------+
> + | +---------+ | mdev_register_parent() +--------------+
>   | |Physical | +<-----------------------+              |
>   | | device  | |                        |  vfio_ccw.ko |<->
> subchannel
>   | |interface| +----------------------->+              |     device
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> b/drivers/gpu/drm/i915/gvt/gvt.h
> index 563ffc2fdfb7a..fa4a56b50c828 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -36,6 +36,7 @@
>  #include <uapi/linux/pci_regs.h>
>  #include <linux/kvm_host.h>
>  #include <linux/vfio.h>
> +#include <linux/mdev.h>
>  
>  #include "i915_drv.h"
>  #include "intel_gvt.h"
> @@ -337,6 +338,7 @@ struct intel_gvt {
>         struct intel_gvt_workload_scheduler scheduler;
>         struct notifier_block
> shadow_ctx_notifier_block[I915_NUM_ENGINES];
>         DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
> +       struct mdev_parent parent;
>         struct intel_vgpu_type *types;
>         unsigned int num_types;
>         struct intel_vgpu *idle_vgpu;
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 68f022c4aafbc..29531b797010f 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -1922,7 +1922,7 @@ static void intel_gvt_clean_device(struct
> drm_i915_private *i915)
>         if (drm_WARN_ON(&i915->drm, !gvt))
>                 return;
>  
> -       mdev_unregister_device(i915->drm.dev);
> +       mdev_unregister_parent(&gvt->parent);
>         intel_gvt_cleanup_vgpu_type_groups(gvt);
>         intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
>         intel_gvt_clean_vgpu_types(gvt);
> @@ -2027,7 +2027,8 @@ static int intel_gvt_init_device(struct
> drm_i915_private *i915)
>         if (ret)
>                 goto out_destroy_idle_vgpu;
>  
> -       ret = mdev_register_device(i915->drm.dev,
> &intel_vgpu_mdev_driver);
> +       ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
> +                                  &intel_vgpu_mdev_driver);
>         if (ret)
>                 goto out_cleanup_vgpu_type_groups;
>  
> diff --git a/drivers/s390/cio/vfio_ccw_drv.c
> b/drivers/s390/cio/vfio_ccw_drv.c
> index e9985c63dc6bf..7d105915bd149 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -221,7 +221,8 @@ static int vfio_ccw_sch_probe(struct subchannel
> *sch)
>  
>         dev_set_drvdata(&sch->dev, private);
>  
> -       ret = mdev_register_device(&sch->dev, &vfio_ccw_mdev_driver);
> +       ret = mdev_register_parent(&private->parent, &sch->dev,
> +                                  &vfio_ccw_mdev_driver);
>         if (ret)
>                 goto out_free;
>  
> @@ -240,7 +241,7 @@ static void vfio_ccw_sch_remove(struct subchannel
> *sch)
>  {
>         struct vfio_ccw_private *private = dev_get_drvdata(&sch-
> >dev);
>  
> -       mdev_unregister_device(&sch->dev);
> +       mdev_unregister_parent(&private->parent);
>  
>         dev_set_drvdata(&sch->dev, NULL);
>  
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 9f8486c0d3d37..9a0e0c5ffb1a5 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -11,7 +11,6 @@
>   */
>  
>  #include <linux/vfio.h>
> -#include <linux/mdev.h>
>  #include <linux/nospec.h>
>  #include <linux/slab.h>
>  
> diff --git a/drivers/s390/cio/vfio_ccw_private.h
> b/drivers/s390/cio/vfio_ccw_private.h
> index 63d9202b29c7f..1a4bfb1b5a808 100644
> --- a/drivers/s390/cio/vfio_ccw_private.h
> +++ b/drivers/s390/cio/vfio_ccw_private.h
> @@ -18,6 +18,7 @@
>  #include <linux/workqueue.h>
>  #include <linux/vfio_ccw.h>
>  #include <linux/vfio.h>
> +#include <linux/mdev.h>
>  #include <asm/crw.h>
>  #include <asm/debug.h>
>  
> @@ -89,6 +90,7 @@ struct vfio_ccw_crw {
>   * @io_work: work for deferral process of I/O handling
>   * @crw_work: work for deferral process of CRW handling
>   * @release_comp: synchronization helper for vfio device release
> + * @parent: parent data structures for mdevs created
>   */
>  struct vfio_ccw_private {
>         struct vfio_device vdev;
> @@ -116,6 +118,8 @@ struct vfio_ccw_private {
>         struct work_struct      crw_work;
>  
>         struct completion       release_comp;
> +
> +       struct mdev_parent      parent;
>  } __aligned(8);
>  
>  int vfio_ccw_sch_quiesce(struct subchannel *sch);
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 161597357a642..724d09a74a8f1 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -1830,7 +1830,8 @@ int vfio_ap_mdev_register(void)
>         if (ret)
>                 return ret;
>  
> -       ret = mdev_register_device(&matrix_dev->device,
> &vfio_ap_matrix_driver);
> +       ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev-
> >device,
> +                                  &vfio_ap_matrix_driver);
>         if (ret)
>                 goto err_driver;
>         return 0;
> @@ -1842,7 +1843,7 @@ int vfio_ap_mdev_register(void)
>  
>  void vfio_ap_mdev_unregister(void)
>  {
> -       mdev_unregister_device(&matrix_dev->device);
> +       mdev_unregister_parent(&matrix_dev->parent);
>         mdev_unregister_driver(&vfio_ap_matrix_driver);
>  }
>  
> diff --git a/drivers/s390/crypto/vfio_ap_private.h
> b/drivers/s390/crypto/vfio_ap_private.h
> index 163eeaaf24cee..35165730f5174 100644
> --- a/drivers/s390/crypto/vfio_ap_private.h
> +++ b/drivers/s390/crypto/vfio_ap_private.h
> @@ -52,6 +52,7 @@ struct ap_matrix_dev {
>         struct mutex mdevs_lock; /* serializes access to each
> ap_matrix_mdev */
>         struct ap_driver  *vfio_ap_drv;
>         struct mutex guests_lock; /* serializes access to each KVM
> guest */
> +       struct mdev_parent parent;
>  };
>  
>  extern struct ap_matrix_dev *matrix_dev;
> diff --git a/drivers/vfio/mdev/mdev_core.c
> b/drivers/vfio/mdev/mdev_core.c
> index 2c32923fbad27..fa05ac3396950 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -18,8 +18,6 @@
>  #define DRIVER_AUTHOR          "NVIDIA Corporation"
>  #define DRIVER_DESC            "Mediated device Core Driver"
>  
> -static LIST_HEAD(parent_list);
> -static DEFINE_MUTEX(parent_list_lock);
>  static struct class_compat *mdev_bus_compat_class;
>  
>  static LIST_HEAD(mdev_list);
> @@ -61,28 +59,6 @@ struct device *mtype_get_parent_dev(struct
> mdev_type *mtype)
>  }
>  EXPORT_SYMBOL(mtype_get_parent_dev);
>  
> -/* Should be called holding parent_list_lock */
> -static struct mdev_parent *__find_parent_device(struct device *dev)
> -{
> -       struct mdev_parent *parent;
> -
> -       list_for_each_entry(parent, &parent_list, next) {
> -               if (parent->dev == dev)
> -                       return parent;
> -       }
> -       return NULL;
> -}
> -
> -void mdev_release_parent(struct kref *kref)
> -{
> -       struct mdev_parent *parent = container_of(kref, struct
> mdev_parent,
> -                                                 ref);
> -       struct device *dev = parent->dev;
> -
> -       kfree(parent);
> -       put_device(dev);
> -}
> -
>  /* Caller must hold parent unreg_sem read or write lock */
>  static void mdev_device_remove_common(struct mdev_device *mdev)
>  {
> @@ -105,125 +81,73 @@ static int mdev_device_remove_cb(struct device
> *dev, void *data)
>  }
>  
>  /*
> - * mdev_register_device : Register a device
> + * mdev_register_parent: Register a device as parent for mdevs
> + * @parent: parent structure registered
>   * @dev: device structure representing parent device.
>   * @mdev_driver: Device driver to bind to the newly created mdev
>   *
> - * Add device to list of registered parent devices.
> + * Registers the @parent stucture as a parent for mdev types and
> thus mdev
> + * devices.  The caller needs to hold a reference on @dev that must
> not be
> + * released until after the call to mdev_unregister_parent().
> + *
>   * Returns a negative value on error, otherwise 0.
>   */
> -int mdev_register_device(struct device *dev, struct mdev_driver
> *mdev_driver)
> +int mdev_register_parent(struct mdev_parent *parent, struct device
> *dev,
> +               struct mdev_driver *mdev_driver)
>  {
> -       int ret;
> -       struct mdev_parent *parent;
>         char *env_string = "MDEV_STATE=registered";
>         char *envp[] = { env_string, NULL };
> +       int ret;
>  
>         /* check for mandatory ops */
>         if (!mdev_driver->supported_type_groups)
>                 return -EINVAL;
>  
> -       dev = get_device(dev);
> -       if (!dev)
> -               return -EINVAL;
> -
> -       mutex_lock(&parent_list_lock);
> -
> -       /* Check for duplicate */
> -       parent = __find_parent_device(dev);
> -       if (parent) {
> -               parent = NULL;
> -               ret = -EEXIST;
> -               goto add_dev_err;
> -       }
> -
> -       parent = kzalloc(sizeof(*parent), GFP_KERNEL);
> -       if (!parent) {
> -               ret = -ENOMEM;
> -               goto add_dev_err;
> -       }
> -
> -       kref_init(&parent->ref);
> +       memset(parent, 0, sizeof(*parent));
>         init_rwsem(&parent->unreg_sem);
> -
>         parent->dev = dev;
>         parent->mdev_driver = mdev_driver;
>  
>         if (!mdev_bus_compat_class) {
>                 mdev_bus_compat_class =
> class_compat_register("mdev_bus");
> -               if (!mdev_bus_compat_class) {
> -                       ret = -ENOMEM;
> -                       goto add_dev_err;
> -               }
> +               if (!mdev_bus_compat_class)
> +                       return -ENOMEM;
>         }
>  
>         ret = parent_create_sysfs_files(parent);
>         if (ret)
> -               goto add_dev_err;
> +               return ret;
>  
>         ret = class_compat_create_link(mdev_bus_compat_class, dev,
> NULL);
>         if (ret)
>                 dev_warn(dev, "Failed to create compatibility class
> link\n");
>  
> -       list_add(&parent->next, &parent_list);
> -       mutex_unlock(&parent_list_lock);
> -
>         dev_info(dev, "MDEV: Registered\n");
>         kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
> -
>         return 0;
> -
> -add_dev_err:
> -       mutex_unlock(&parent_list_lock);
> -       if (parent)
> -               mdev_put_parent(parent);
> -       else
> -               put_device(dev);
> -       return ret;
>  }
> -EXPORT_SYMBOL(mdev_register_device);
> +EXPORT_SYMBOL(mdev_register_parent);
>  
>  /*
> - * mdev_unregister_device : Unregister a parent device
> - * @dev: device structure representing parent device.
> - *
> - * Remove device from list of registered parent devices. Give a
> chance to free
> - * existing mediated devices for given device.
> + * mdev_unregister_parent : Unregister a parent device
> + * @parent: parent structure to unregister
>   */
> -
> -void mdev_unregister_device(struct device *dev)
> +void mdev_unregister_parent(struct mdev_parent *parent)
>  {
> -       struct mdev_parent *parent;
>         char *env_string = "MDEV_STATE=unregistered";
>         char *envp[] = { env_string, NULL };
>  
> -       mutex_lock(&parent_list_lock);
> -       parent = __find_parent_device(dev);
> -
> -       if (!parent) {
> -               mutex_unlock(&parent_list_lock);
> -               return;
> -       }
> -       dev_info(dev, "MDEV: Unregistering\n");
> -
> -       list_del(&parent->next);
> -       mutex_unlock(&parent_list_lock);
> +       dev_info(parent->dev, "MDEV: Unregistering\n");
>  
>         down_write(&parent->unreg_sem);
> -
> -       class_compat_remove_link(mdev_bus_compat_class, dev, NULL);
> -
> -       device_for_each_child(dev, NULL, mdev_device_remove_cb);
> -
> +       class_compat_remove_link(mdev_bus_compat_class, parent->dev,
> NULL);
> +       device_for_each_child(parent->dev, NULL,
> mdev_device_remove_cb);
>         parent_remove_sysfs_files(parent);
>         up_write(&parent->unreg_sem);
>  
> -       mdev_put_parent(parent);
> -
> -       /* We still have the caller's reference to use for the uevent
> */
> -       kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
> +       kobject_uevent_env(&parent->dev->kobj, KOBJ_CHANGE, envp);
>  }
> -EXPORT_SYMBOL(mdev_unregister_device);
> +EXPORT_SYMBOL(mdev_unregister_parent);
>  
>  static void mdev_device_release(struct device *dev)
>  {
> diff --git a/drivers/vfio/mdev/mdev_private.h
> b/drivers/vfio/mdev/mdev_private.h
> index 7c9fc79f3d838..297f911fdc890 100644
> --- a/drivers/vfio/mdev/mdev_private.h
> +++ b/drivers/vfio/mdev/mdev_private.h
> @@ -13,17 +13,6 @@
>  int  mdev_bus_register(void);
>  void mdev_bus_unregister(void);
>  
> -struct mdev_parent {
> -       struct device *dev;
> -       struct mdev_driver *mdev_driver;
> -       struct kref ref;
> -       struct list_head next;
> -       struct kset *mdev_types_kset;
> -       struct list_head type_list;
> -       /* Synchronize device creation/removal with parent
> unregistration */
> -       struct rw_semaphore unreg_sem;
> -};
> -
>  struct mdev_type {
>         struct kobject kobj;
>         struct kobject *devices_kobj;
> @@ -48,16 +37,4 @@ void mdev_remove_sysfs_files(struct mdev_device
> *mdev);
>  int mdev_device_create(struct mdev_type *kobj, const guid_t *uuid);
>  int  mdev_device_remove(struct mdev_device *dev);
>  
> -void mdev_release_parent(struct kref *kref);
> -
> -static inline void mdev_get_parent(struct mdev_parent *parent)
> -{
> -       kref_get(&parent->ref);
> -}
> -
> -static inline void mdev_put_parent(struct mdev_parent *parent)
> -{
> -       kref_put(&parent->ref, mdev_release_parent);
> -}
> -
>  #endif /* MDEV_PRIVATE_H */
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index 4bfbf49aaa66a..b71ffc5594870 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -81,7 +81,7 @@ static void mdev_type_release(struct kobject *kobj)
>  
>         pr_debug("Releasing group %s\n", kobj->name);
>         /* Pairs with the get in add_mdev_supported_type() */
> -       mdev_put_parent(type->parent);
> +       put_device(type->parent->dev);
>         kfree(type);
>  }
>  
> @@ -110,7 +110,7 @@ static struct mdev_type
> *add_mdev_supported_type(struct mdev_parent *parent,
>         type->kobj.kset = parent->mdev_types_kset;
>         type->parent = parent;
>         /* Pairs with the put in mdev_type_release() */
> -       mdev_get_parent(parent);
> +       get_device(parent->dev);
>         type->type_group_id = type_group_id;
>  
>         ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype,
> NULL,
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index a5d8ae6132a20..262512c2a8ffc 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -23,6 +23,16 @@ struct mdev_device {
>         bool active;
>  };
>  
> +/* embedded into the struct device that the mdev devices hang off */
> +struct mdev_parent {
> +       struct device *dev;
> +       struct mdev_driver *mdev_driver;
> +       struct kset *mdev_types_kset;
> +       struct list_head type_list;
> +       /* Synchronize device creation/removal with parent
> unregistration */
> +       struct rw_semaphore unreg_sem;
> +};
> +
>  static inline struct mdev_device *to_mdev_device(struct device *dev)
>  {
>         return container_of(dev, struct mdev_device, dev);
> @@ -70,8 +80,9 @@ struct mdev_driver {
>  
>  extern struct bus_type mdev_bus_type;
>  
> -int mdev_register_device(struct device *dev, struct mdev_driver
> *mdev_driver);
> -void mdev_unregister_device(struct device *dev);
> +int mdev_register_parent(struct mdev_parent *parent, struct device
> *dev,
> +               struct mdev_driver *mdev_driver);
> +void mdev_unregister_parent(struct mdev_parent *parent);
>  
>  int mdev_register_driver(struct mdev_driver *drv);
>  void mdev_unregister_driver(struct mdev_driver *drv);
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 985b6e7136219..2c4791abbc3d3 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -128,6 +128,7 @@ static dev_t                mbochs_devt;
>  static struct class    *mbochs_class;
>  static struct cdev     mbochs_cdev;
>  static struct device   mbochs_dev;
> +static struct mdev_parent mbochs_parent;
>  static atomic_t mbochs_avail_mbytes;
>  static const struct vfio_device_ops mbochs_dev_ops;
>  
> @@ -1475,7 +1476,7 @@ static int __init mbochs_dev_init(void)
>         if (ret)
>                 goto err_class;
>  
> -       ret = mdev_register_device(&mbochs_dev, &mbochs_driver);
> +       ret = mdev_register_parent(&mbochs_parent, &mbochs_dev,
> &mbochs_driver);
>         if (ret)
>                 goto err_device;
>  
> @@ -1496,7 +1497,7 @@ static int __init mbochs_dev_init(void)
>  static void __exit mbochs_dev_exit(void)
>  {
>         mbochs_dev.bus = NULL;
> -       mdev_unregister_device(&mbochs_dev);
> +       mdev_unregister_parent(&mbochs_parent);
>  
>         device_unregister(&mbochs_dev);
>         mdev_unregister_driver(&mbochs_driver);
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 1daab012b5d89..01f345430b975 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -83,6 +83,7 @@ static dev_t          mdpy_devt;
>  static struct class    *mdpy_class;
>  static struct cdev     mdpy_cdev;
>  static struct device   mdpy_dev;
> +static struct mdev_parent mdpy_parent;
>  static u32             mdpy_count;
>  static const struct vfio_device_ops mdpy_dev_ops;
>  
> @@ -778,7 +779,7 @@ static int __init mdpy_dev_init(void)
>         if (ret)
>                 goto err_class;
>  
> -       ret = mdev_register_device(&mdpy_dev, &mdpy_driver);
> +       ret = mdev_register_parent(&mdpy_parent, &mdpy_dev,
> &mdpy_driver);
>         if (ret)
>                 goto err_device;
>  
> @@ -799,7 +800,7 @@ static int __init mdpy_dev_init(void)
>  static void __exit mdpy_dev_exit(void)
>  {
>         mdpy_dev.bus = NULL;
> -       mdev_unregister_device(&mdpy_dev);
> +       mdev_unregister_parent(&mdpy_parent);
>  
>         device_unregister(&mdpy_dev);
>         mdev_unregister_driver(&mdpy_driver);
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index 86843ce3d9a27..e80baac513811 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -72,6 +72,7 @@ static struct mtty_dev {
>         struct cdev     vd_cdev;
>         struct idr      vd_idr;
>         struct device   dev;
> +       struct mdev_parent parent;
>  } mtty_dev;
>  
>  struct mdev_region_info {
> @@ -1361,7 +1362,8 @@ static int __init mtty_dev_init(void)
>         if (ret)
>                 goto err_class;
>  
> -       ret = mdev_register_device(&mtty_dev.dev, &mtty_driver);
> +       ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,
> +                                  &mtty_driver);
>         if (ret)
>                 goto err_device;
>         return 0;
> @@ -1381,7 +1383,7 @@ static int __init mtty_dev_init(void)
>  static void __exit mtty_dev_exit(void)
>  {
>         mtty_dev.dev.bus = NULL;
> -       mdev_unregister_device(&mtty_dev.dev);
> +       mdev_unregister_parent(&mtty_dev.parent);
>  
>         device_unregister(&mtty_dev.dev);
>         idr_destroy(&mtty_dev.vd_idr);


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

* Re: [PATCH 05/14] vfio/mdev: simplify mdev_type handling
  2022-09-23  9:26 ` [PATCH 05/14] vfio/mdev: simplify mdev_type handling Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> Instead of abusing struct attribute_group to control initialization
> of
> struct mdev_type, just define the actual attributes in the
> mdev_driver,
> allocate the mdev_type structures in the caller and pass them to
> mdev_register_parent.
> 
> This allows the caller to use container_of to get at the containing
> structure and thus significantly simplify the code.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  .../driver-api/vfio-mediated-device.rst       |   2 +-
>  drivers/gpu/drm/i915/gvt/gvt.h                |   3 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c              | 102 +++-------------
> --
>  drivers/gpu/drm/i915/gvt/vgpu.c               |  13 ++-
>  drivers/s390/cio/vfio_ccw_drv.c               |   6 +-
>  drivers/s390/cio/vfio_ccw_ops.c               |  14 +--
>  drivers/s390/cio/vfio_ccw_private.h           |   2 +
>  drivers/s390/crypto/vfio_ap_ops.c             |  19 ++--
>  drivers/s390/crypto/vfio_ap_private.h         |   2 +
>  drivers/vfio/mdev/mdev_core.c                 |  31 ++----
>  drivers/vfio/mdev/mdev_driver.c               |   5 +-
>  drivers/vfio/mdev/mdev_private.h              |   8 --
>  drivers/vfio/mdev/mdev_sysfs.c                |  91 ++++------------
>  include/linux/mdev.h                          |  26 +++--
>  samples/vfio-mdev/mbochs.c                    |  57 ++++------
>  samples/vfio-mdev/mdpy.c                      |  50 ++++-----
>  samples/vfio-mdev/mtty.c                      |  60 +++++------
>  17 files changed, 165 insertions(+), 326 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index cd1667608ab5d..ff7342d2e332d 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -103,7 +103,7 @@ structure to represent a mediated device's
> driver::
>       struct mdev_driver {
>              int  (*probe)  (struct mdev_device *dev);
>              void (*remove) (struct mdev_device *dev);
> -            struct attribute_group **supported_type_groups;
> +            const struct attribute * const *types_attrs;
>              struct device_driver    driver;
>       };
>  
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> b/drivers/gpu/drm/i915/gvt/gvt.h
> index fa4a56b50c828..db182066d56c9 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -310,8 +310,8 @@ struct intel_vgpu_config {
>         const char *name;
>  };
>  
> -#define NR_MAX_INTEL_VGPU_TYPES 20
>  struct intel_vgpu_type {
> +       struct mdev_type type;
>         char name[16];
>         const struct intel_vgpu_config *conf;
>         unsigned int avail_instance;
> @@ -339,6 +339,7 @@ struct intel_gvt {
>         struct notifier_block
> shadow_ctx_notifier_block[I915_NUM_ENGINES];
>         DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
>         struct mdev_parent parent;
> +       struct mdev_type **mdev_types;
>         struct intel_vgpu_type *types;
>         unsigned int num_types;
>         struct intel_vgpu *idle_vgpu;
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 29531b797010f..ce6b8cb37be0c 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -117,17 +117,10 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
>  {
> -       struct intel_vgpu_type *type;
> -       unsigned int num = 0;
> -       struct intel_gvt *gvt =
> kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
> +       struct intel_vgpu_type *type =
> +               container_of(mtype, struct intel_vgpu_type, type);
>  
> -       type = &gvt->types[mtype_get_type_group_id(mtype)];
> -       if (!type)
> -               num = 0;
> -       else
> -               num = type->avail_instance;
> -
> -       return sprintf(buf, "%u\n", num);
> +       return sprintf(buf, "%u\n", type->avail_instance);
>  }
>  
>  static ssize_t device_api_show(struct mdev_type *mtype,
> @@ -139,12 +132,8 @@ static ssize_t device_api_show(struct mdev_type
> *mtype,
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> -       struct intel_vgpu_type *type;
> -       struct intel_gvt *gvt =
> kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
> -
> -       type = &gvt->types[mtype_get_type_group_id(mtype)];
> -       if (!type)
> -               return 0;
> +       struct intel_vgpu_type *type =
> +               container_of(mtype, struct intel_vgpu_type, type);
>  
>         return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
>                        "fence: %d\nresolution: %s\n"
> @@ -158,14 +147,7 @@ static ssize_t description_show(struct mdev_type
> *mtype,
>  static ssize_t name_show(struct mdev_type *mtype,
>                          struct mdev_type_attribute *attr, char *buf)
>  {
> -       struct intel_vgpu_type *type;
> -       struct intel_gvt *gvt =
> kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
> -
> -       type = &gvt->types[mtype_get_type_group_id(mtype)];
> -       if (!type)
> -               return 0;
> -
> -       return sprintf(buf, "%s\n", type->name);
> +       return sprintf(buf, "%s\n", mtype->sysfs_name);
>  }
>  
>  static MDEV_TYPE_ATTR_RO(available_instances);
> @@ -173,7 +155,7 @@ static MDEV_TYPE_ATTR_RO(device_api);
>  static MDEV_TYPE_ATTR_RO(description);
>  static MDEV_TYPE_ATTR_RO(name);
>  
> -static struct attribute *gvt_type_attrs[] = {
> +static const struct attribute *gvt_type_attrs[] = {
>         &mdev_type_attr_available_instances.attr,
>         &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_description.attr,
> @@ -181,51 +163,6 @@ static struct attribute *gvt_type_attrs[] = {
>         NULL,
>  };
>  
> -static struct attribute_group *gvt_vgpu_type_groups[] = {
> -       [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
> -};
> -
> -static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
> -{
> -       int i, j;
> -       struct intel_vgpu_type *type;
> -       struct attribute_group *group;
> -
> -       for (i = 0; i < gvt->num_types; i++) {
> -               type = &gvt->types[i];
> -
> -               group = kzalloc(sizeof(struct attribute_group),
> GFP_KERNEL);
> -               if (!group)
> -                       goto unwind;
> -
> -               group->name = type->name;
> -               group->attrs = gvt_type_attrs;
> -               gvt_vgpu_type_groups[i] = group;
> -       }
> -
> -       return 0;
> -
> -unwind:
> -       for (j = 0; j < i; j++) {
> -               group = gvt_vgpu_type_groups[j];
> -               kfree(group);
> -       }
> -
> -       return -ENOMEM;
> -}
> -
> -static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt
> *gvt)
> -{
> -       int i;
> -       struct attribute_group *group;
> -
> -       for (i = 0; i < gvt->num_types; i++) {
> -               group = gvt_vgpu_type_groups[i];
> -               gvt_vgpu_type_groups[i] = NULL;
> -               kfree(group);
> -       }
> -}
> -
>  static void gvt_unpin_guest_page(struct intel_vgpu *vgpu, unsigned
> long gfn,
>                 unsigned long size)
>  {
> @@ -1547,16 +1484,11 @@ static const struct attribute_group
> *intel_vgpu_groups[] = {
>  static int intel_vgpu_init_dev(struct vfio_device *vfio_dev)
>  {
>         struct mdev_device *mdev = to_mdev_device(vfio_dev->dev);
> -       struct device *pdev = mdev_parent_dev(mdev);
> -       struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
> -       struct intel_vgpu_type *type;
>         struct intel_vgpu *vgpu = vfio_dev_to_vgpu(vfio_dev);
> +       struct intel_vgpu_type *type =
> +               container_of(mdev->type, struct intel_vgpu_type,
> type);
>  
> -       type = &gvt->types[mdev_get_type_group_id(mdev)];
> -       if (!type)
> -               return -EINVAL;
> -
> -       vgpu->gvt = gvt;
> +       vgpu->gvt = kdev_to_i915(mdev_parent_dev(mdev))->gvt;
>         return intel_gvt_create_vgpu(vgpu, type->conf);
>  }
>  
> @@ -1624,7 +1556,7 @@ static struct mdev_driver
> intel_vgpu_mdev_driver = {
>         },
>         .probe          = intel_vgpu_probe,
>         .remove         = intel_vgpu_remove,
> -       .supported_type_groups  = gvt_vgpu_type_groups,
> +       .types_attrs    = gvt_type_attrs,
>  };
>  
>  int intel_gvt_page_track_add(struct intel_vgpu *info, u64 gfn)
> @@ -1923,7 +1855,6 @@ static void intel_gvt_clean_device(struct
> drm_i915_private *i915)
>                 return;
>  
>         mdev_unregister_parent(&gvt->parent);
> -       intel_gvt_cleanup_vgpu_type_groups(gvt);
>         intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
>         intel_gvt_clean_vgpu_types(gvt);
>  
> @@ -2023,20 +1954,15 @@ static int intel_gvt_init_device(struct
> drm_i915_private *i915)
>  
>         intel_gvt_debugfs_init(gvt);
>  
> -       ret = intel_gvt_init_vgpu_type_groups(gvt);
> -       if (ret)
> -               goto out_destroy_idle_vgpu;
> -
>         ret = mdev_register_parent(&gvt->parent, i915->drm.dev,
> -                                  &intel_vgpu_mdev_driver);
> +                                  &intel_vgpu_mdev_driver,
> +                                  gvt->mdev_types, gvt->num_types);
>         if (ret)
> -               goto out_cleanup_vgpu_type_groups;
> +               goto out_destroy_idle_vgpu;
>  
>         gvt_dbg_core("gvt device initialization is done\n");
>         return 0;
>  
> -out_cleanup_vgpu_type_groups:
> -       intel_gvt_cleanup_vgpu_type_groups(gvt);
>  out_destroy_idle_vgpu:
>         intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
>         intel_gvt_debugfs_clean(gvt);
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 1b67328c714f1..8fa06d00fd4b9 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -113,13 +113,18 @@ int intel_gvt_init_vgpu_types(struct intel_gvt
> *gvt)
>         if (!gvt->types)
>                 return -ENOMEM;
>  
> +       gvt->mdev_types = kcalloc(num_types, sizeof(*gvt-
> >mdev_types),
> +                            GFP_KERNEL);
> +       if (!gvt->mdev_types)
> +               goto out_free_types;
> +
>         for (i = 0; i < num_types; ++i) {
>                 const struct intel_vgpu_config *conf =
> &intel_vgpu_configs[i];
>  
>                 if (low_avail / conf->low_mm == 0)
>                         break;
>                 if (conf->weight < 1 || conf->weight >
> VGPU_MAX_WEIGHT)
> -                       goto out_free_types;
> +                       goto out_free_mdev_types;
>  
>                 sprintf(gvt->types[i].name, "GVTg_V%u_%s",
>                         GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5,
> conf->name);
> @@ -131,11 +136,16 @@ int intel_gvt_init_vgpu_types(struct intel_gvt
> *gvt)
>                              i, gvt->types[i].name, gvt-
> >types[i].avail_instance,
>                              conf->low_mm, conf->high_mm, conf-
> >fence,
>                              conf->weight, vgpu_edid_str(conf-
> >edid));
> +
> +               gvt->mdev_types[i] = &gvt->types[i].type;
> +               gvt->mdev_types[i]->sysfs_name = gvt->types[i].name;
>         }
>  
>         gvt->num_types = i;
>         return 0;
>  
> +out_free_mdev_types:
> +       kfree(gvt->mdev_types);
>  out_free_types:
>         kfree(gvt->types);
>         return -EINVAL;
> @@ -143,6 +153,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt
> *gvt)
>  
>  void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
>  {
> +       kfree(gvt->mdev_types);
>         kfree(gvt->types);
>  }
>  
> diff --git a/drivers/s390/cio/vfio_ccw_drv.c
> b/drivers/s390/cio/vfio_ccw_drv.c
> index 7d105915bd149..25a5de08b3902 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -202,7 +202,6 @@ static void vfio_ccw_free_private(struct
> vfio_ccw_private *private)
>         mutex_destroy(&private->io_mutex);
>         kfree(private);
>  }
> -
>  static int vfio_ccw_sch_probe(struct subchannel *sch)
>  {
>         struct pmcw *pmcw = &sch->schib.pmcw;
> @@ -221,8 +220,11 @@ static int vfio_ccw_sch_probe(struct subchannel
> *sch)
>  
>         dev_set_drvdata(&sch->dev, private);
>  
> +       private->mdev_type.sysfs_name = "io";
> +       private->mdev_types[0] = &private->mdev_type;
>         ret = mdev_register_parent(&private->parent, &sch->dev,
> -                                  &vfio_ccw_mdev_driver);
> +                                  &vfio_ccw_mdev_driver,
> +                                  private->mdev_types, 1);
>         if (ret)
>                 goto out_free;
>  
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 9a0e0c5ffb1a5..c37e712a4b069 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -69,23 +69,13 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> -static struct attribute *mdev_types_attrs[] = {
> +static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> -static struct attribute_group mdev_type_group = {
> -       .name  = "io",
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group *mdev_type_groups[] = {
> -       &mdev_type_group,
> -       NULL,
> -};
> -
>  static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
>  {
>         struct vfio_ccw_private *private =
> @@ -646,5 +636,5 @@ struct mdev_driver vfio_ccw_mdev_driver = {
>         },
>         .probe = vfio_ccw_mdev_probe,
>         .remove = vfio_ccw_mdev_remove,
> -       .supported_type_groups  = mdev_type_groups,
> +       .types_attrs = mdev_types_attrs,
>  };
> diff --git a/drivers/s390/cio/vfio_ccw_private.h
> b/drivers/s390/cio/vfio_ccw_private.h
> index 1a4bfb1b5a808..52caa721ec06c 100644
> --- a/drivers/s390/cio/vfio_ccw_private.h
> +++ b/drivers/s390/cio/vfio_ccw_private.h
> @@ -120,6 +120,8 @@ struct vfio_ccw_private {
>         struct completion       release_comp;
>  
>         struct mdev_parent      parent;
> +       struct mdev_type        mdev_type;
> +       struct mdev_type        *mdev_types[1];
>  } __aligned(8);
>  
>  int vfio_ccw_sch_quiesce(struct subchannel *sch);
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 724d09a74a8f1..24d131c502ca3 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -816,23 +816,13 @@ static ssize_t device_api_show(struct mdev_type
> *mtype,
>  
>  static MDEV_TYPE_ATTR_RO(device_api);
>  
> -static struct attribute *vfio_ap_mdev_type_attrs[] = {
> +static const struct attribute *vfio_ap_mdev_type_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> -static struct attribute_group vfio_ap_mdev_hwvirt_type_group = {
> -       .name = VFIO_AP_MDEV_TYPE_HWVIRT,
> -       .attrs = vfio_ap_mdev_type_attrs,
> -};
> -
> -static struct attribute_group *vfio_ap_mdev_type_groups[] = {
> -       &vfio_ap_mdev_hwvirt_type_group,
> -       NULL,
> -};
> -
>  #define MDEV_SHARING_ERR "Userspace may not re-assign queue
> %02lx.%04lx " \
>                          "already assigned to %s"
>  
> @@ -1817,7 +1807,7 @@ static struct mdev_driver vfio_ap_matrix_driver
> = {
>         },
>         .probe = vfio_ap_mdev_probe,
>         .remove = vfio_ap_mdev_remove,
> -       .supported_type_groups = vfio_ap_mdev_type_groups,
> +       .types_attrs = vfio_ap_mdev_type_attrs,
>  };
>  
>  int vfio_ap_mdev_register(void)
> @@ -1830,8 +1820,11 @@ int vfio_ap_mdev_register(void)
>         if (ret)
>                 return ret;
>  
> +       matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT;
> +       matrix_dev->mdev_types[0] = &matrix_dev->mdev_type;
>         ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev-
> >device,
> -                                  &vfio_ap_matrix_driver);
> +                                  &vfio_ap_matrix_driver,
> +                                  matrix_dev->mdev_types, 1);
>         if (ret)
>                 goto err_driver;
>         return 0;
> diff --git a/drivers/s390/crypto/vfio_ap_private.h
> b/drivers/s390/crypto/vfio_ap_private.h
> index 35165730f5174..441dc8dda380b 100644
> --- a/drivers/s390/crypto/vfio_ap_private.h
> +++ b/drivers/s390/crypto/vfio_ap_private.h
> @@ -53,6 +53,8 @@ struct ap_matrix_dev {
>         struct ap_driver  *vfio_ap_drv;
>         struct mutex guests_lock; /* serializes access to each KVM
> guest */
>         struct mdev_parent parent;
> +       struct mdev_type mdev_type;
> +       struct mdev_type *mdev_types[];
>  };
>  
>  extern struct ap_matrix_dev *matrix_dev;
> diff --git a/drivers/vfio/mdev/mdev_core.c
> b/drivers/vfio/mdev/mdev_core.c
> index fa05ac3396950..2d95a497fd3b2 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -29,26 +29,6 @@ struct device *mdev_parent_dev(struct mdev_device
> *mdev)
>  }
>  EXPORT_SYMBOL(mdev_parent_dev);
>  
> -/*
> - * Return the index in supported_type_groups that this mdev_device
> was created
> - * from.
> - */
> -unsigned int mdev_get_type_group_id(struct mdev_device *mdev)
> -{
> -       return mdev->type->type_group_id;
> -}
> -EXPORT_SYMBOL(mdev_get_type_group_id);
> -
> -/*
> - * Used in mdev_type_attribute sysfs functions to return the index
> in the
> - * supported_type_groups that the sysfs is called from.
> - */
> -unsigned int mtype_get_type_group_id(struct mdev_type *mtype)
> -{
> -       return mtype->type_group_id;
> -}
> -EXPORT_SYMBOL(mtype_get_type_group_id);
> -
>  /*
>   * Used in mdev_type_attribute sysfs functions to return the parent
> struct
>   * device
> @@ -85,6 +65,8 @@ static int mdev_device_remove_cb(struct device
> *dev, void *data)
>   * @parent: parent structure registered
>   * @dev: device structure representing parent device.
>   * @mdev_driver: Device driver to bind to the newly created mdev
> + * @types: Array of supported mdev types
> + * @nr_types: Number of entries in @types
>   *
>   * Registers the @parent stucture as a parent for mdev types and
> thus mdev
>   * devices.  The caller needs to hold a reference on @dev that must
> not be
> @@ -93,20 +75,19 @@ static int mdev_device_remove_cb(struct device
> *dev, void *data)
>   * Returns a negative value on error, otherwise 0.
>   */
>  int mdev_register_parent(struct mdev_parent *parent, struct device
> *dev,
> -               struct mdev_driver *mdev_driver)
> +               struct mdev_driver *mdev_driver, struct mdev_type
> **types,
> +               unsigned int nr_types)
>  {
>         char *env_string = "MDEV_STATE=registered";
>         char *envp[] = { env_string, NULL };
>         int ret;
>  
> -       /* check for mandatory ops */
> -       if (!mdev_driver->supported_type_groups)
> -               return -EINVAL;
> -
>         memset(parent, 0, sizeof(*parent));
>         init_rwsem(&parent->unreg_sem);
>         parent->dev = dev;
>         parent->mdev_driver = mdev_driver;
> +       parent->types = types;
> +       parent->nr_types = nr_types;
>  
>         if (!mdev_bus_compat_class) {
>                 mdev_bus_compat_class =
> class_compat_register("mdev_bus");
> diff --git a/drivers/vfio/mdev/mdev_driver.c
> b/drivers/vfio/mdev/mdev_driver.c
> index 7bd4bb9850e81..1da1ecf76a0d5 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -56,10 +56,9 @@ EXPORT_SYMBOL_GPL(mdev_bus_type);
>   **/
>  int mdev_register_driver(struct mdev_driver *drv)
>  {
> -       /* initialize common driver fields */
> +       if (!drv->types_attrs)
> +               return -EINVAL;
>         drv->driver.bus = &mdev_bus_type;
> -
> -       /* register with core */
>         return driver_register(&drv->driver);
>  }
>  EXPORT_SYMBOL(mdev_register_driver);
> diff --git a/drivers/vfio/mdev/mdev_private.h
> b/drivers/vfio/mdev/mdev_private.h
> index 297f911fdc890..ba1b2dbddc0bc 100644
> --- a/drivers/vfio/mdev/mdev_private.h
> +++ b/drivers/vfio/mdev/mdev_private.h
> @@ -13,14 +13,6 @@
>  int  mdev_bus_register(void);
>  void mdev_bus_unregister(void);
>  
> -struct mdev_type {
> -       struct kobject kobj;
> -       struct kobject *devices_kobj;
> -       struct mdev_parent *parent;
> -       struct list_head next;
> -       unsigned int type_group_id;
> -};
> -
>  extern const struct attribute_group *mdev_device_groups[];
>  
>  #define to_mdev_type_attr(_attr)       \
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index b71ffc5594870..38b4c2466ec43 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -82,7 +82,6 @@ static void mdev_type_release(struct kobject *kobj)
>         pr_debug("Releasing group %s\n", kobj->name);
>         /* Pairs with the get in add_mdev_supported_type() */
>         put_device(type->parent->dev);
> -       kfree(type);
>  }
>  
>  static struct kobj_type mdev_type_ktype = {
> @@ -90,35 +89,21 @@ static struct kobj_type mdev_type_ktype = {
>         .release = mdev_type_release,
>  };
>  
> -static struct mdev_type *add_mdev_supported_type(struct mdev_parent
> *parent,
> -                                                unsigned int
> type_group_id)
> +static int mdev_type_add(struct mdev_parent *parent, struct
> mdev_type *type)
>  {
> -       struct mdev_type *type;
> -       struct attribute_group *group =
> -               parent->mdev_driver-
> >supported_type_groups[type_group_id];
>         int ret;
>  
> -       if (!group->name) {
> -               pr_err("%s: Type name empty!\n", __func__);
> -               return ERR_PTR(-EINVAL);
> -       }
> -
> -       type = kzalloc(sizeof(*type), GFP_KERNEL);
> -       if (!type)
> -               return ERR_PTR(-ENOMEM);
> -
>         type->kobj.kset = parent->mdev_types_kset;
>         type->parent = parent;
>         /* Pairs with the put in mdev_type_release() */
>         get_device(parent->dev);
> -       type->type_group_id = type_group_id;
>  
>         ret = kobject_init_and_add(&type->kobj, &mdev_type_ktype,
> NULL,
>                                    "%s-%s", dev_driver_string(parent-
> >dev),
> -                                  group->name);
> +                                  type->sysfs_name);
>         if (ret) {
>                 kobject_put(&type->kobj);
> -               return ERR_PTR(ret);
> +               return ret;
>         }
>  
>         ret = sysfs_create_file(&type->kobj,
> &mdev_type_attr_create.attr);
> @@ -131,13 +116,10 @@ static struct mdev_type
> *add_mdev_supported_type(struct mdev_parent *parent,
>                 goto attr_devices_failed;
>         }
>  
> -       ret = sysfs_create_files(&type->kobj,
> -                                (const struct attribute **)group-
> >attrs);
> -       if (ret) {
> -               ret = -ENOMEM;
> +       ret = sysfs_create_files(&type->kobj, parent->mdev_driver-
> >types_attrs);
> +       if (ret)
>                 goto attrs_failed;
> -       }
> -       return type;
> +       return 0;
>  
>  attrs_failed:
>         kobject_put(type->devices_kobj);
> @@ -146,78 +128,49 @@ static struct mdev_type
> *add_mdev_supported_type(struct mdev_parent *parent,
>  attr_create_failed:
>         kobject_del(&type->kobj);
>         kobject_put(&type->kobj);
> -       return ERR_PTR(ret);
> +       return ret;
>  }
>  
> -static void remove_mdev_supported_type(struct mdev_type *type)
> +static void mdev_type_remove(struct mdev_type *type)
>  {
> -       struct attribute_group *group =
> -               type->parent->mdev_driver-
> >supported_type_groups[type->type_group_id];
> +       sysfs_remove_files(&type->kobj, type->parent->mdev_driver-
> >types_attrs);
>  
> -       sysfs_remove_files(&type->kobj,
> -                          (const struct attribute **)group->attrs);
>         kobject_put(type->devices_kobj);
>         sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
>         kobject_del(&type->kobj);
>         kobject_put(&type->kobj);
>  }
>  
> -static int add_mdev_supported_type_groups(struct mdev_parent
> *parent)
> -{
> -       int i;
> -
> -       for (i = 0; parent->mdev_driver->supported_type_groups[i];
> i++) {
> -               struct mdev_type *type;
> -
> -               type = add_mdev_supported_type(parent, i);
> -               if (IS_ERR(type)) {
> -                       struct mdev_type *ltype, *tmp;
> -
> -                       list_for_each_entry_safe(ltype, tmp, &parent-
> >type_list,
> -                                                 next) {
> -                               list_del(&ltype->next);
> -                               remove_mdev_supported_type(ltype);
> -                       }
> -                       return PTR_ERR(type);
> -               }
> -               list_add(&type->next, &parent->type_list);
> -       }
> -       return 0;
> -}
> -
>  /* mdev sysfs functions */
>  void parent_remove_sysfs_files(struct mdev_parent *parent)
>  {
> -       struct mdev_type *type, *tmp;
> -
> -       list_for_each_entry_safe(type, tmp, &parent->type_list, next)
> {
> -               list_del(&type->next);
> -               remove_mdev_supported_type(type);
> -       }
> +       int i;
>  
> +       for (i = 0; i < parent->nr_types; i++)
> +               mdev_type_remove(parent->types[i]);
>         kset_unregister(parent->mdev_types_kset);
>  }
>  
>  int parent_create_sysfs_files(struct mdev_parent *parent)
>  {
> -       int ret;
> +       int ret, i;
>  
>         parent->mdev_types_kset =
> kset_create_and_add("mdev_supported_types",
>                                                NULL, &parent->dev-
> >kobj);
> -
>         if (!parent->mdev_types_kset)
>                 return -ENOMEM;
>  
> -       INIT_LIST_HEAD(&parent->type_list);
> -
> -       ret = add_mdev_supported_type_groups(parent);
> -       if (ret)
> -               goto create_err;
> +       for (i = 0; i < parent->nr_types; i++) {
> +               ret = mdev_type_add(parent, parent->types[i]);
> +               if (ret)
> +                       goto out_err;
> +       }
>         return 0;
>  
> -create_err:
> -       kset_unregister(parent->mdev_types_kset);
> -       return ret;
> +out_err:
> +       while (--i >= 0)
> +               mdev_type_remove(parent->types[i]);
> +       return 0;
>  }
>  
>  static ssize_t remove_store(struct device *dev, struct
> device_attribute *attr,
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index 262512c2a8ffc..19bc93c10e8c7 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -23,14 +23,27 @@ struct mdev_device {
>         bool active;
>  };
>  
> +struct mdev_type {
> +       /* set by the driver before calling mdev_register parent: */
> +       const char *sysfs_name;
> +
> +       /* set by the core, can be used drivers */
> +       struct mdev_parent *parent;
> +
> +       /* internal only */
> +       struct kobject kobj;
> +       struct kobject *devices_kobj;
> +};
> +
>  /* embedded into the struct device that the mdev devices hang off */
>  struct mdev_parent {
>         struct device *dev;
>         struct mdev_driver *mdev_driver;
>         struct kset *mdev_types_kset;
> -       struct list_head type_list;
>         /* Synchronize device creation/removal with parent
> unregistration */
>         struct rw_semaphore unreg_sem;
> +       struct mdev_type **types;
> +       unsigned int nr_types;
>  };
>  
>  static inline struct mdev_device *to_mdev_device(struct device *dev)
> @@ -38,8 +51,6 @@ static inline struct mdev_device
> *to_mdev_device(struct device *dev)
>         return container_of(dev, struct mdev_device, dev);
>  }
>  
> -unsigned int mdev_get_type_group_id(struct mdev_device *mdev);
> -unsigned int mtype_get_type_group_id(struct mdev_type *mtype);
>  struct device *mtype_get_parent_dev(struct mdev_type *mtype);
>  
>  /* interface for exporting mdev supported type attributes */
> @@ -66,22 +77,21 @@ struct mdev_type_attribute mdev_type_attr_##_name
> =         \
>   * struct mdev_driver - Mediated device driver
>   * @probe: called when new device created
>   * @remove: called when device removed
> - * @supported_type_groups: Attributes to define supported types. It
> is mandatory
> - *                     to provide supported types.
> + * @types_attrs: attributes to the type kobjects.
>   * @driver: device driver structure
> - *
>   **/
>  struct mdev_driver {
>         int (*probe)(struct mdev_device *dev);
>         void (*remove)(struct mdev_device *dev);
> -       struct attribute_group **supported_type_groups;
> +       const struct attribute * const *types_attrs;
>         struct device_driver driver;
>  };
>  
>  extern struct bus_type mdev_bus_type;
>  
>  int mdev_register_parent(struct mdev_parent *parent, struct device
> *dev,
> -               struct mdev_driver *mdev_driver);
> +               struct mdev_driver *mdev_driver, struct mdev_type
> **types,
> +               unsigned int nr_types);
>  void mdev_unregister_parent(struct mdev_parent *parent);
>  
>  int mdev_register_driver(struct mdev_driver *drv);
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 2c4791abbc3d3..4d0839cb51943 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -99,23 +99,27 @@ MODULE_PARM_DESC(mem, "megabytes available to "
> MBOCHS_NAME " devices");
>  #define MBOCHS_TYPE_2 "medium"
>  #define MBOCHS_TYPE_3 "large"
>  
> -static const struct mbochs_type {
> +static struct mbochs_type {
> +       struct mdev_type type;
>         const char *name;
>         u32 mbytes;
>         u32 max_x;
>         u32 max_y;
>  } mbochs_types[] = {
>         {
> +               .type.sysfs_name        = MBOCHS_TYPE_1,
>                 .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
>                 .mbytes = 4,
>                 .max_x  = 800,
>                 .max_y  = 600,
>         }, {
> +               .type.sysfs_name        = MBOCHS_TYPE_2,
>                 .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
>                 .mbytes = 16,
>                 .max_x  = 1920,
>                 .max_y  = 1440,
>         }, {
> +               .type.sysfs_name        = MBOCHS_TYPE_3,
>                 .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
>                 .mbytes = 64,
>                 .max_x  = 0,
> @@ -123,6 +127,11 @@ static const struct mbochs_type {
>         },
>  };
>  
> +static struct mdev_type *mbochs_mdev_types[] = {
> +       &mbochs_types[0].type,
> +       &mbochs_types[1].type,
> +       &mbochs_types[2].type,
> +};
>  
>  static dev_t           mbochs_devt;
>  static struct class    *mbochs_class;
> @@ -510,8 +519,8 @@ static int mbochs_init_dev(struct vfio_device
> *vdev)
>         struct mdev_state *mdev_state =
>                 container_of(vdev, struct mdev_state, vdev);
>         struct mdev_device *mdev = to_mdev_device(vdev->dev);
> -       const struct mbochs_type *type =
> -               &mbochs_types[mdev_get_type_group_id(mdev)];
> +       struct mbochs_type *type =
> +               container_of(mdev->type, struct mbochs_type, type);
>         int avail_mbytes = atomic_read(&mbochs_avail_mbytes);
>         int ret = -ENOMEM;
>  
> @@ -1345,8 +1354,8 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>  static ssize_t name_show(struct mdev_type *mtype,
>                          struct mdev_type_attribute *attr, char *buf)
>  {
> -       const struct mbochs_type *type =
> -               &mbochs_types[mtype_get_type_group_id(mtype)];
> +       struct mbochs_type *type =
> +               container_of(mtype, struct mbochs_type, type);
>  
>         return sprintf(buf, "%s\n", type->name);
>  }
> @@ -1355,8 +1364,8 @@ static MDEV_TYPE_ATTR_RO(name);
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> -       const struct mbochs_type *type =
> -               &mbochs_types[mtype_get_type_group_id(mtype)];
> +       struct mbochs_type *type =
> +               container_of(mtype, struct mbochs_type, type);
>  
>         return sprintf(buf, "virtual display, %d MB video memory\n",
>                        type ? type->mbytes  : 0);
> @@ -1367,8 +1376,8 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
>  {
> -       const struct mbochs_type *type =
> -               &mbochs_types[mtype_get_type_group_id(mtype)];
> +       struct mbochs_type *type =
> +               container_of(mtype, struct mbochs_type, type);
>         int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
>  
>         return sprintf(buf, "%d\n", count);
> @@ -1382,7 +1391,7 @@ static ssize_t device_api_show(struct mdev_type
> *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(device_api);
>  
> -static struct attribute *mdev_types_attrs[] = {
> +static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
>         &mdev_type_attr_device_api.attr,
> @@ -1390,28 +1399,6 @@ static struct attribute *mdev_types_attrs[] =
> {
>         NULL,
>  };
>  
> -static struct attribute_group mdev_type_group1 = {
> -       .name  = MBOCHS_TYPE_1,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group mdev_type_group2 = {
> -       .name  = MBOCHS_TYPE_2,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group mdev_type_group3 = {
> -       .name  = MBOCHS_TYPE_3,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group *mdev_type_groups[] = {
> -       &mdev_type_group1,
> -       &mdev_type_group2,
> -       &mdev_type_group3,
> -       NULL,
> -};
> -
>  static const struct vfio_device_ops mbochs_dev_ops = {
>         .close_device = mbochs_close_device,
>         .init = mbochs_init_dev,
> @@ -1431,7 +1418,7 @@ static struct mdev_driver mbochs_driver = {
>         },
>         .probe = mbochs_probe,
>         .remove = mbochs_remove,
> -       .supported_type_groups = mdev_type_groups,
> +       .types_attrs = mdev_types_attrs,
>  };
>  
>  static const struct file_operations vd_fops = {
> @@ -1476,7 +1463,9 @@ static int __init mbochs_dev_init(void)
>         if (ret)
>                 goto err_class;
>  
> -       ret = mdev_register_parent(&mbochs_parent, &mbochs_dev,
> &mbochs_driver);
> +       ret = mdev_register_parent(&mbochs_parent, &mbochs_dev,
> &mbochs_driver,
> +                                  mbochs_mdev_types,
> +                                  ARRAY_SIZE(mbochs_mdev_types));
>         if (ret)
>                 goto err_device;
>  
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 01f345430b975..4a341f4849e73 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -51,7 +51,8 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME "
> devices");
>  #define MDPY_TYPE_2 "xga"
>  #define MDPY_TYPE_3 "hd"
>  
> -static const struct mdpy_type {
> +static struct mdpy_type {
> +       struct mdev_type type;
>         const char *name;
>         u32 format;
>         u32 bytepp;
> @@ -59,18 +60,21 @@ static const struct mdpy_type {
>         u32 height;
>  } mdpy_types[] = {
>         {
> +               .type.sysfs_name        = MDPY_TYPE_1,
>                 .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
>                 .width  = 640,
>                 .height = 480,
>         }, {
> +               .type.sysfs_name        = MDPY_TYPE_2,
>                 .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
>                 .width  = 1024,
>                 .height = 768,
>         }, {
> +               .type.sysfs_name        = MDPY_TYPE_3,
>                 .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
> @@ -79,6 +83,12 @@ static const struct mdpy_type {
>         },
>  };
>  
> +static struct mdev_type *mdpy_mdev_types[] = {
> +       &mdpy_types[0].type,
> +       &mdpy_types[1].type,
> +       &mdpy_types[2].type,
> +};
> +
>  static dev_t           mdpy_devt;
>  static struct class    *mdpy_class;
>  static struct cdev     mdpy_cdev;
> @@ -222,7 +232,7 @@ static int mdpy_init_dev(struct vfio_device
> *vdev)
>                 container_of(vdev, struct mdev_state, vdev);
>         struct mdev_device *mdev = to_mdev_device(vdev->dev);
>         const struct mdpy_type *type =
> -               &mdpy_types[mdev_get_type_group_id(mdev)];
> +               container_of(mdev->type, struct mdpy_type, type);
>         u32 fbsize;
>         int ret = -ENOMEM;
>  
> @@ -655,8 +665,7 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>  static ssize_t name_show(struct mdev_type *mtype,
>                          struct mdev_type_attribute *attr, char *buf)
>  {
> -       const struct mdpy_type *type =
> -               &mdpy_types[mtype_get_type_group_id(mtype)];
> +       struct mdpy_type *type = container_of(mtype, struct
> mdpy_type, type);
>  
>         return sprintf(buf, "%s\n", type->name);
>  }
> @@ -665,8 +674,7 @@ static MDEV_TYPE_ATTR_RO(name);
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> -       const struct mdpy_type *type =
> -               &mdpy_types[mtype_get_type_group_id(mtype)];
> +       struct mdpy_type *type = container_of(mtype, struct
> mdpy_type, type);
>  
>         return sprintf(buf, "virtual display, %dx%d framebuffer\n",
>                        type->width, type->height);
> @@ -688,7 +696,7 @@ static ssize_t device_api_show(struct mdev_type
> *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(device_api);
>  
> -static struct attribute *mdev_types_attrs[] = {
> +static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
>         &mdev_type_attr_device_api.attr,
> @@ -696,28 +704,6 @@ static struct attribute *mdev_types_attrs[] = {
>         NULL,
>  };
>  
> -static struct attribute_group mdev_type_group1 = {
> -       .name  = MDPY_TYPE_1,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group mdev_type_group2 = {
> -       .name  = MDPY_TYPE_2,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group mdev_type_group3 = {
> -       .name  = MDPY_TYPE_3,
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group *mdev_type_groups[] = {
> -       &mdev_type_group1,
> -       &mdev_type_group2,
> -       &mdev_type_group3,
> -       NULL,
> -};
> -
>  static const struct vfio_device_ops mdpy_dev_ops = {
>         .init = mdpy_init_dev,
>         .release = mdpy_release_dev,
> @@ -736,7 +722,7 @@ static struct mdev_driver mdpy_driver = {
>         },
>         .probe = mdpy_probe,
>         .remove = mdpy_remove,
> -       .supported_type_groups = mdev_type_groups,
> +       .types_attrs = mdev_types_attrs,
>  };
>  
>  static const struct file_operations vd_fops = {
> @@ -779,7 +765,9 @@ static int __init mdpy_dev_init(void)
>         if (ret)
>                 goto err_class;
>  
> -       ret = mdev_register_parent(&mdpy_parent, &mdpy_dev,
> &mdpy_driver);
> +       ret = mdev_register_parent(&mdpy_parent, &mdpy_dev,
> &mdpy_driver,
> +                                  mdpy_mdev_types,
> +                                  ARRAY_SIZE(mdpy_mdev_types));
>         if (ret)
>                 goto err_device;
>  
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index e80baac513811..814a7f98738a2 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -143,6 +143,20 @@ struct mdev_state {
>         int nr_ports;
>  };
>  
> +static struct mtty_type {
> +       struct mdev_type type;
> +       int nr_ports;
> +       const char *name;
> +} mtty_types[2] = {
> +       { .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port
> serial" },
> +       { .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port
> serial" },
> +};
> +
> +static struct mdev_type *mtty_mdev_types[] = {
> +       &mtty_types[0].type,
> +       &mtty_types[1].type,
> +};
> +
>  static atomic_t mdev_avail_ports = ATOMIC_INIT(MAX_MTTYS);
>  
>  static const struct file_operations vd_fops = {
> @@ -707,17 +721,19 @@ static int mtty_init_dev(struct vfio_device
> *vdev)
>         struct mdev_state *mdev_state =
>                 container_of(vdev, struct mdev_state, vdev);
>         struct mdev_device *mdev = to_mdev_device(vdev->dev);
> -       int nr_ports = mdev_get_type_group_id(mdev) + 1;
> +       struct mtty_type *type =
> +               container_of(mdev->type, struct mtty_type, type);
>         int avail_ports = atomic_read(&mdev_avail_ports);
>         int ret;
>  
>         do {
> -               if (avail_ports < nr_ports)
> +               if (avail_ports < type->nr_ports)
>                         return -ENOSPC;
>         } while (!atomic_try_cmpxchg(&mdev_avail_ports,
> -                                    &avail_ports, avail_ports -
> nr_ports));
> +                                    &avail_ports,
> +                                    avail_ports - type->nr_ports));
>  
> -       mdev_state->nr_ports = nr_ports;
> +       mdev_state->nr_ports = type->nr_ports;
>         mdev_state->irq_index = -1;
>         mdev_state->s[0].max_fifo_size = MAX_FIFO_SIZE;
>         mdev_state->s[1].max_fifo_size = MAX_FIFO_SIZE;
> @@ -735,7 +751,7 @@ static int mtty_init_dev(struct vfio_device
> *vdev)
>         return 0;
>  
>  err_nr_ports:
> -       atomic_add(nr_ports, &mdev_avail_ports);
> +       atomic_add(type->nr_ports, &mdev_avail_ports);
>         return ret;
>  }
>  
> @@ -1242,11 +1258,9 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>  static ssize_t name_show(struct mdev_type *mtype,
>                          struct mdev_type_attribute *attr, char *buf)
>  {
> -       static const char *name_str[2] = { "Single port serial",
> -                                          "Dual port serial" };
> +       struct mtty_type *type = container_of(mtype, struct
> mtty_type, type);
>  
> -       return sysfs_emit(buf, "%s\n",
> -                         name_str[mtype_get_type_group_id(mtype)]);
> +       return sysfs_emit(buf, "%s\n", type->name);
>  }
>  
>  static MDEV_TYPE_ATTR_RO(name);
> @@ -1255,9 +1269,10 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
>  {
> -       unsigned int ports = mtype_get_type_group_id(mtype) + 1;
> +       struct mtty_type *type = container_of(mtype, struct
> mtty_type, type);
>  
> -       return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
> ports);
> +       return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
> +                       type->nr_ports);
>  }
>  
>  static MDEV_TYPE_ATTR_RO(available_instances);
> @@ -1270,29 +1285,13 @@ static ssize_t device_api_show(struct
> mdev_type *mtype,
>  
>  static MDEV_TYPE_ATTR_RO(device_api);
>  
> -static struct attribute *mdev_types_attrs[] = {
> +static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> -static struct attribute_group mdev_type_group1 = {
> -       .name  = "1",
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group mdev_type_group2 = {
> -       .name  = "2",
> -       .attrs = mdev_types_attrs,
> -};
> -
> -static struct attribute_group *mdev_type_groups[] = {
> -       &mdev_type_group1,
> -       &mdev_type_group2,
> -       NULL,
> -};
> -
>  static const struct vfio_device_ops mtty_dev_ops = {
>         .name = "vfio-mtty",
>         .init = mtty_init_dev,
> @@ -1311,7 +1310,7 @@ static struct mdev_driver mtty_driver = {
>         },
>         .probe = mtty_probe,
>         .remove = mtty_remove,
> -       .supported_type_groups = mdev_type_groups,
> +       .types_attrs = mdev_types_attrs,
>  };
>  
>  static void mtty_device_release(struct device *dev)
> @@ -1363,7 +1362,8 @@ static int __init mtty_dev_init(void)
>                 goto err_class;
>  
>         ret = mdev_register_parent(&mtty_dev.parent, &mtty_dev.dev,
> -                                  &mtty_driver);
> +                                  &mtty_driver, mtty_mdev_types,
> +                                  ARRAY_SIZE(mtty_mdev_types));
>         if (ret)
>                 goto err_device;
>         return 0;


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

* Re: [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev
  2022-09-23  9:26 ` [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> Just open code the dereferences in the only user.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Jason J. Herne <jjherne@linux.ibm.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  drivers/s390/cio/vfio_ccw_ops.c |  3 +--
>  drivers/vfio/mdev/mdev_core.c   | 10 ----------
>  include/linux/mdev.h            |  2 --
>  3 files changed, 1 insertion(+), 14 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index c37e712a4b069..3db6251b31143 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -62,8 +62,7 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
>  {
> -       struct vfio_ccw_private *private =
> -               dev_get_drvdata(mtype_get_parent_dev(mtype));
> +       struct vfio_ccw_private *private = dev_get_drvdata(mtype-
> >parent->dev);
>  
>         return sprintf(buf, "%d\n", atomic_read(&private->avail));
>  }
> diff --git a/drivers/vfio/mdev/mdev_core.c
> b/drivers/vfio/mdev/mdev_core.c
> index 75628759a3bf0..93f8caf2e5f77 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -23,16 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
>  static LIST_HEAD(mdev_list);
>  static DEFINE_MUTEX(mdev_list_lock);
>  
> -/*
> - * Used in mdev_type_attribute sysfs functions to return the parent
> struct
> - * device
> - */
> -struct device *mtype_get_parent_dev(struct mdev_type *mtype)
> -{
> -       return mtype->parent->dev;
> -}
> -EXPORT_SYMBOL(mtype_get_parent_dev);
> -
>  /* Caller must hold parent unreg_sem read or write lock */
>  static void mdev_device_remove_common(struct mdev_device *mdev)
>  {
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index bbedffcb38d48..e445f809ceca3 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -51,8 +51,6 @@ static inline struct mdev_device
> *to_mdev_device(struct device *dev)
>         return container_of(dev, struct mdev_device, dev);
>  }
>  
> -struct device *mtype_get_parent_dev(struct mdev_type *mtype);
> -
>  /* interface for exporting mdev supported type attributes */
>  struct mdev_type_attribute {
>         struct attribute attr;


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

* Re: [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code
  2022-09-23  9:26 ` [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
> 
> Every driver just emits a static string, simply feed it through the
> ops
> and provide a standard sysfs show function.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  .../driver-api/vfio-mediated-device.rst       |  2 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c              |  9 +----
>  drivers/s390/cio/vfio_ccw_ops.c               |  9 +----
>  drivers/s390/crypto/vfio_ap_ops.c             | 10 +-----
>  drivers/vfio/mdev/mdev_driver.c               |  4 ++-
>  drivers/vfio/mdev/mdev_sysfs.c                | 35 +++++++++++++----
> --
>  include/linux/mdev.h                          |  7 ++--
>  samples/vfio-mdev/mbochs.c                    |  9 +----
>  samples/vfio-mdev/mdpy.c                      |  9 +----
>  samples/vfio-mdev/mtty.c                      | 10 +-----
>  10 files changed, 37 insertions(+), 67 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index 7b660f3fa2c92..b0c29e37f61b4 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -202,7 +202,7 @@ Directories and files under the sysfs for Each
> Physical Device
>  
>  * device_api
>  
> -  This attribute should show which device API is being created, for
> example,
> +  This attribute shows which device API is being created, for
> example,
>    "vfio-pci" for a PCI device.
>  
>  * available_instances
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 1947f553fcd38..9b2d3b078a2c9 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -123,12 +123,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>         return sprintf(buf, "%u\n", type->avail_instance);
>  }
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> @@ -151,13 +145,11 @@ static ssize_t name_show(struct mdev_type
> *mtype,
>  }
>  
>  static MDEV_TYPE_ATTR_RO(available_instances);
> -static MDEV_TYPE_ATTR_RO(device_api);
>  static MDEV_TYPE_ATTR_RO(description);
>  static MDEV_TYPE_ATTR_RO(name);
>  
>  static const struct attribute *gvt_type_attrs[] = {
>         &mdev_type_attr_available_instances.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_description.attr,
>         &mdev_type_attr_name.attr,
>         NULL,
> @@ -1549,6 +1541,7 @@ static void intel_vgpu_remove(struct
> mdev_device *mdev)
>  }
>  
>  static struct mdev_driver intel_vgpu_mdev_driver = {
> +       .device_api     = VFIO_DEVICE_API_PCI_STRING,
>         .driver = {
>                 .name           = "intel_vgpu_mdev",
>                 .owner          = THIS_MODULE,
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 3db6251b31143..4c7b181519228 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -51,13 +51,6 @@ static ssize_t name_show(struct mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(name);
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_CCW_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>  static ssize_t available_instances_show(struct mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
> @@ -70,7 +63,6 @@ static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -628,6 +620,7 @@ static const struct vfio_device_ops
> vfio_ccw_dev_ops = {
>  };
>  
>  struct mdev_driver vfio_ccw_mdev_driver = {
> +       .device_api = VFIO_DEVICE_API_CCW_STRING,
>         .driver = {
>                 .name = "vfio_ccw_mdev",
>                 .owner = THIS_MODULE,
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 24d131c502ca3..d440acfbb261e 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -808,17 +808,8 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_AP_STRING);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>  static const struct attribute *vfio_ap_mdev_type_attrs[] = {
>         &mdev_type_attr_name.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -1799,6 +1790,7 @@ static const struct vfio_device_ops
> vfio_ap_matrix_dev_ops = {
>  };
>  
>  static struct mdev_driver vfio_ap_matrix_driver = {
> +       .device_api = VFIO_DEVICE_API_AP_STRING,
>         .driver = {
>                 .name = "vfio_ap_mdev",
>                 .owner = THIS_MODULE,
> diff --git a/drivers/vfio/mdev/mdev_driver.c
> b/drivers/vfio/mdev/mdev_driver.c
> index 5b3c94f4fb13d..60e8b9f6474e8 100644
> --- a/drivers/vfio/mdev/mdev_driver.c
> +++ b/drivers/vfio/mdev/mdev_driver.c
> @@ -55,8 +55,10 @@ struct bus_type mdev_bus_type = {
>   **/
>  int mdev_register_driver(struct mdev_driver *drv)
>  {
> -       if (!drv->types_attrs)
> +       if (!drv->types_attrs || !drv->device_api)
>                 return -EINVAL;
> +
> +       /* initialize common driver fields */
>         drv->driver.bus = &mdev_bus_type;
>         return driver_register(&drv->driver);
>  }
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index 38b4c2466ec43..60fc52ff92448 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -72,9 +72,30 @@ static ssize_t create_store(struct mdev_type
> *mtype,
>  
>         return count;
>  }
> -
>  static MDEV_TYPE_ATTR_WO(create);
>  
> +static ssize_t device_api_show(struct mdev_type *mtype,
> +                              struct mdev_type_attribute *attr, char
> *buf)
> +{
> +       return sysfs_emit(buf, "%s\n", mtype->parent->mdev_driver-
> >device_api);
> +}
> +static MDEV_TYPE_ATTR_RO(device_api);
> +
> +static struct attribute *mdev_types_core_attrs[] = {
> +       &mdev_type_attr_create.attr,
> +       &mdev_type_attr_device_api.attr,
> +       NULL,
> +};
> +
> +static struct attribute_group mdev_type_core_group = {
> +       .attrs = mdev_types_core_attrs,
> +};
> +
> +static const struct attribute_group *mdev_type_groups[] = {
> +       &mdev_type_core_group,
> +       NULL,
> +};
> +
>  static void mdev_type_release(struct kobject *kobj)
>  {
>         struct mdev_type *type = to_mdev_type(kobj);
> @@ -85,8 +106,9 @@ static void mdev_type_release(struct kobject
> *kobj)
>  }
>  
>  static struct kobj_type mdev_type_ktype = {
> -       .sysfs_ops = &mdev_type_sysfs_ops,
> -       .release = mdev_type_release,
> +       .sysfs_ops      = &mdev_type_sysfs_ops,
> +       .release        = mdev_type_release,
> +       .default_groups = mdev_type_groups,
>  };
>  
>  static int mdev_type_add(struct mdev_parent *parent, struct
> mdev_type *type)
> @@ -106,10 +128,6 @@ static int mdev_type_add(struct mdev_parent
> *parent, struct mdev_type *type)
>                 return ret;
>         }
>  
> -       ret = sysfs_create_file(&type->kobj,
> &mdev_type_attr_create.attr);
> -       if (ret)
> -               goto attr_create_failed;
> -
>         type->devices_kobj = kobject_create_and_add("devices", &type-
> >kobj);
>         if (!type->devices_kobj) {
>                 ret = -ENOMEM;
> @@ -124,8 +142,6 @@ static int mdev_type_add(struct mdev_parent
> *parent, struct mdev_type *type)
>  attrs_failed:
>         kobject_put(type->devices_kobj);
>  attr_devices_failed:
> -       sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
> -attr_create_failed:
>         kobject_del(&type->kobj);
>         kobject_put(&type->kobj);
>         return ret;
> @@ -136,7 +152,6 @@ static void mdev_type_remove(struct mdev_type
> *type)
>         sysfs_remove_files(&type->kobj, type->parent->mdev_driver-
> >types_attrs);
>  
>         kobject_put(type->devices_kobj);
> -       sysfs_remove_file(&type->kobj, &mdev_type_attr_create.attr);
>         kobject_del(&type->kobj);
>         kobject_put(&type->kobj);
>  }
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index e445f809ceca3..af1ff0165b8d3 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -61,11 +61,6 @@ struct mdev_type_attribute {
>                          size_t count);
>  };
>  
> -#define MDEV_TYPE_ATTR(_name, _mode, _show, _store)            \
> -struct mdev_type_attribute mdev_type_attr_##_name =            \
> -       __ATTR(_name, _mode, _show, _store)
> -#define MDEV_TYPE_ATTR_RW(_name) \
> -       struct mdev_type_attribute mdev_type_attr_##_name =
> __ATTR_RW(_name)
>  #define MDEV_TYPE_ATTR_RO(_name) \
>         struct mdev_type_attribute mdev_type_attr_##_name =
> __ATTR_RO(_name)
>  #define MDEV_TYPE_ATTR_WO(_name) \
> @@ -73,12 +68,14 @@ struct mdev_type_attribute mdev_type_attr_##_name
> =         \
>  
>  /**
>   * struct mdev_driver - Mediated device driver
> + * @device_api: string to return for the device_api sysfs
>   * @probe: called when new device created
>   * @remove: called when device removed
>   * @types_attrs: attributes to the type kobjects.
>   * @driver: device driver structure
>   **/
>  struct mdev_driver {
> +       const char *device_api;
>         int (*probe)(struct mdev_device *dev);
>         void (*remove)(struct mdev_device *dev);
>         const struct attribute * const *types_attrs;
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 4d0839cb51943..a2fc13fade757 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -1384,17 +1384,9 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -1410,6 +1402,7 @@ static const struct vfio_device_ops
> mbochs_dev_ops = {
>  };
>  
>  static struct mdev_driver mbochs_driver = {
> +       .device_api = VFIO_DEVICE_API_PCI_STRING,
>         .driver = {
>                 .name = "mbochs",
>                 .owner = THIS_MODULE,
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 4a341f4849e73..f9069ed2750fa 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -689,17 +689,9 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -714,6 +706,7 @@ static const struct vfio_device_ops mdpy_dev_ops
> = {
>  };
>  
>  static struct mdev_driver mdpy_driver = {
> +       .device_api = VFIO_DEVICE_API_PCI_STRING,
>         .driver = {
>                 .name = "mdpy",
>                 .owner = THIS_MODULE,
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index 814a7f98738a2..064e71b28dd19 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -1277,17 +1277,8 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> -static ssize_t device_api_show(struct mdev_type *mtype,
> -                              struct mdev_type_attribute *attr, char
> *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(device_api);
> -
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_name.attr,
> -       &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -1302,6 +1293,7 @@ static const struct vfio_device_ops
> mtty_dev_ops = {
>  };
>  
>  static struct mdev_driver mtty_driver = {
> +       .device_api = VFIO_DEVICE_API_PCI_STRING,
>         .driver = {
>                 .name = "mtty",
>                 .owner = THIS_MODULE,


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

* Re: [PATCH 11/14] vfio/mdev: consolidate all the name sysfs into the core code
  2022-09-23  9:26 ` [PATCH 11/14] vfio/mdev: consolidate all the name " Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> Every driver just emits a static string, simply add a field to the
> mdev_type for the driver to fill out or fall back to the sysfs name
> and
> provide a standard sysfs show function.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  .../driver-api/vfio-mediated-device.rst       |  2 +-
>  drivers/gpu/drm/i915/gvt/kvmgt.c              |  8 -------
>  drivers/s390/cio/vfio_ccw_drv.c               |  1 +
>  drivers/s390/cio/vfio_ccw_ops.c               |  8 -------
>  drivers/s390/crypto/vfio_ap_ops.c             | 10 +--------
>  drivers/vfio/mdev/mdev_sysfs.c                | 10 +++++++++
>  include/linux/mdev.h                          |  1 +
>  samples/vfio-mdev/mbochs.c                    | 20 ++++-------------
> -
>  samples/vfio-mdev/mdpy.c                      | 21 +++++------------
> --
>  samples/vfio-mdev/mtty.c                      | 18 ++++------------
>  10 files changed, 27 insertions(+), 72 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index b0c29e37f61b4..dcd1231a6fa84 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -217,7 +217,7 @@ Directories and files under the sysfs for Each
> Physical Device
>  
>  * name
>  
> -  This attribute should show human readable name. This is optional
> attribute.
> +  This attribute shows a human readable name.
>  
>  * description
>  
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 9b2d3b078a2c9..08fe7458b3610 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -138,20 +138,12 @@ static ssize_t description_show(struct
> mdev_type *mtype,
>                        type->conf->weight);
>  }
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       return sprintf(buf, "%s\n", mtype->sysfs_name);
> -}
> -
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  static MDEV_TYPE_ATTR_RO(description);
> -static MDEV_TYPE_ATTR_RO(name);
>  
>  static const struct attribute *gvt_type_attrs[] = {
>         &mdev_type_attr_available_instances.attr,
>         &mdev_type_attr_description.attr,
> -       &mdev_type_attr_name.attr,
>         NULL,
>  };
>  
> diff --git a/drivers/s390/cio/vfio_ccw_drv.c
> b/drivers/s390/cio/vfio_ccw_drv.c
> index 25a5de08b3902..e5f21c725326b 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -221,6 +221,7 @@ static int vfio_ccw_sch_probe(struct subchannel
> *sch)
>         dev_set_drvdata(&sch->dev, private);
>  
>         private->mdev_type.sysfs_name = "io";
> +       private->mdev_type.pretty_name = "I/O subchannel (Non-QDIO)";
>         private->mdev_types[0] = &private->mdev_type;
>         ret = mdev_register_parent(&private->parent, &sch->dev,
>                                    &vfio_ccw_mdev_driver,
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 4c7b181519228..394aab60dbd0a 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -44,13 +44,6 @@ static void vfio_ccw_dma_unmap(struct vfio_device
> *vdev, u64 iova, u64 length)
>         vfio_ccw_mdev_reset(private);
>  }
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       return sprintf(buf, "I/O subchannel (Non-QDIO)\n");
> -}
> -static MDEV_TYPE_ATTR_RO(name);
> -
>  static ssize_t available_instances_show(struct mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
> @@ -62,7 +55,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_name.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index d440acfbb261e..5d8dd7e837f3d 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -790,14 +790,6 @@ static void vfio_ap_mdev_remove(struct
> mdev_device *mdev)
>         vfio_put_device(&matrix_mdev->vdev);
>  }
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       return sprintf(buf, "%s\n", VFIO_AP_MDEV_NAME_HWVIRT);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(name);
> -
>  static ssize_t available_instances_show(struct mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
> @@ -809,7 +801,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *vfio_ap_mdev_type_attrs[] = {
> -       &mdev_type_attr_name.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
> @@ -1813,6 +1804,7 @@ int vfio_ap_mdev_register(void)
>                 return ret;
>  
>         matrix_dev->mdev_type.sysfs_name = VFIO_AP_MDEV_TYPE_HWVIRT;
> +       matrix_dev->mdev_type.pretty_name = VFIO_AP_MDEV_NAME_HWVIRT;
>         matrix_dev->mdev_types[0] = &matrix_dev->mdev_type;
>         ret = mdev_register_parent(&matrix_dev->parent, &matrix_dev-
> >device,
>                                    &vfio_ap_matrix_driver,
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index 60fc52ff92448..34583e6a97f27 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -81,9 +81,19 @@ static ssize_t device_api_show(struct mdev_type
> *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(device_api);
>  
> +static ssize_t name_show(struct mdev_type *mtype,
> +                        struct mdev_type_attribute *attr, char *buf)
> +{
> +       return sprintf(buf, "%s\n",
> +               mtype->pretty_name ? mtype->pretty_name : mtype-
> >sysfs_name);
> +}
> +
> +static MDEV_TYPE_ATTR_RO(name);
> +
>  static struct attribute *mdev_types_core_attrs[] = {
>         &mdev_type_attr_create.attr,
>         &mdev_type_attr_device_api.attr,
> +       &mdev_type_attr_name.attr,
>         NULL,
>  };
>  
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index af1ff0165b8d3..4bb8a58b577b3 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -26,6 +26,7 @@ struct mdev_device {
>  struct mdev_type {
>         /* set by the driver before calling mdev_register parent: */
>         const char *sysfs_name;
> +       const char *pretty_name;
>  
>         /* set by the core, can be used drivers */
>         struct mdev_parent *parent;
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index a2fc13fade757..0b7585f16d8ab 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -101,26 +101,25 @@ MODULE_PARM_DESC(mem, "megabytes available to "
> MBOCHS_NAME " devices");
>  
>  static struct mbochs_type {
>         struct mdev_type type;
> -       const char *name;
>         u32 mbytes;
>         u32 max_x;
>         u32 max_y;
>  } mbochs_types[] = {
>         {
>                 .type.sysfs_name        = MBOCHS_TYPE_1,
> -               .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_1,
> +               .type.pretty_name       = MBOCHS_CLASS_NAME "-"
> MBOCHS_TYPE_1,
>                 .mbytes = 4,
>                 .max_x  = 800,
>                 .max_y  = 600,
>         }, {
>                 .type.sysfs_name        = MBOCHS_TYPE_2,
> -               .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_2,
> +               .type.pretty_name       = MBOCHS_CLASS_NAME "-"
> MBOCHS_TYPE_2,
>                 .mbytes = 16,
>                 .max_x  = 1920,
>                 .max_y  = 1440,
>         }, {
>                 .type.sysfs_name        = MBOCHS_TYPE_3,
> -               .name   = MBOCHS_CLASS_NAME "-" MBOCHS_TYPE_3,
> +               .type.pretty_name       = MBOCHS_CLASS_NAME "-"
> MBOCHS_TYPE_3,
>                 .mbytes = 64,
>                 .max_x  = 0,
>                 .max_y  = 0,
> @@ -556,7 +555,7 @@ static int mbochs_init_dev(struct vfio_device
> *vdev)
>         mbochs_reset(mdev_state);
>  
>         dev_info(vdev->dev, "%s: %s, %d MB, %ld pages\n", __func__,
> -                type->name, type->mbytes, mdev_state->pagecount);
> +                type->type.pretty_name, type->mbytes, mdev_state-
> >pagecount);
>         return 0;
>  
>  err_vconfig:
> @@ -1351,16 +1350,6 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>         NULL,
>  };
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       struct mbochs_type *type =
> -               container_of(mtype, struct mbochs_type, type);
> -
> -       return sprintf(buf, "%s\n", type->name);
> -}
> -static MDEV_TYPE_ATTR_RO(name);
> -
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> @@ -1385,7 +1374,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index f9069ed2750fa..90c6fed200b19 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -53,7 +53,6 @@ MODULE_PARM_DESC(count, "number of " MDPY_NAME "
> devices");
>  
>  static struct mdpy_type {
>         struct mdev_type type;
> -       const char *name;
>         u32 format;
>         u32 bytepp;
>         u32 width;
> @@ -61,21 +60,21 @@ static struct mdpy_type {
>  } mdpy_types[] = {
>         {
>                 .type.sysfs_name        = MDPY_TYPE_1,
> -               .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_1,
> +               .type.pretty_name       = MDPY_CLASS_NAME "-"
> MDPY_TYPE_1,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
>                 .width  = 640,
>                 .height = 480,
>         }, {
>                 .type.sysfs_name        = MDPY_TYPE_2,
> -               .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_2,
> +               .type.pretty_name       = MDPY_CLASS_NAME "-"
> MDPY_TYPE_2,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
>                 .width  = 1024,
>                 .height = 768,
>         }, {
>                 .type.sysfs_name        = MDPY_TYPE_3,
> -               .name   = MDPY_CLASS_NAME "-" MDPY_TYPE_3,
> +               .type.pretty_name       = MDPY_CLASS_NAME "-"
> MDPY_TYPE_3,
>                 .format = DRM_FORMAT_XRGB8888,
>                 .bytepp = 4,
>                 .width  = 1920,
> @@ -256,8 +255,8 @@ static int mdpy_init_dev(struct vfio_device
> *vdev)
>         mdpy_create_config_space(mdev_state);
>         mdpy_reset(mdev_state);
>  
> -       dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type->name,
> type->width,
> -                type->height);
> +       dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type-
> >type.pretty_name,
> +                type->width, type->height);
>  
>         mdpy_count++;
>         return 0;
> @@ -662,15 +661,6 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>         NULL,
>  };
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       struct mdpy_type *type = container_of(mtype, struct
> mdpy_type, type);
> -
> -       return sprintf(buf, "%s\n", type->name);
> -}
> -static MDEV_TYPE_ATTR_RO(name);
> -
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> @@ -690,7 +680,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_name.attr,
>         &mdev_type_attr_description.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index 064e71b28dd19..eab1b4442a96e 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -146,10 +146,11 @@ struct mdev_state {
>  static struct mtty_type {
>         struct mdev_type type;
>         int nr_ports;
> -       const char *name;
>  } mtty_types[2] = {
> -       { .nr_ports = 1, .type.sysfs_name = "1", .name = "Single port
> serial" },
> -       { .nr_ports = 2, .type.sysfs_name = "2", .name = "Dual port
> serial" },
> +       { .nr_ports = 1, .type.sysfs_name = "1",
> +         .type.pretty_name = "Single port serial" },
> +       { .nr_ports = 2, .type.sysfs_name = "2",
> +         .type.pretty_name = "Dual port serial" },
>  };
>  
>  static struct mdev_type *mtty_mdev_types[] = {
> @@ -1255,16 +1256,6 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>         NULL,
>  };
>  
> -static ssize_t name_show(struct mdev_type *mtype,
> -                        struct mdev_type_attribute *attr, char *buf)
> -{
> -       struct mtty_type *type = container_of(mtype, struct
> mtty_type, type);
> -
> -       return sysfs_emit(buf, "%s\n", type->name);
> -}
> -
> -static MDEV_TYPE_ATTR_RO(name);
> -
>  static ssize_t available_instances_show(struct mdev_type *mtype,
>                                         struct mdev_type_attribute
> *attr,
>                                         char *buf)
> @@ -1278,7 +1269,6 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_name.attr,
>         &mdev_type_attr_available_instances.attr,
>         NULL,
>  };


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

* Re: [PATCH 12/14] vfio/mdev: consolidate all the available_instance sysfs into the core code
  2022-09-23  9:26 ` [PATCH 12/14] vfio/mdev: consolidate all the available_instance " Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> Every driver just print a number, simply add a method to the
> mdev_driver
> to return it and provide a standard sysfs show function.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  .../driver-api/vfio-mediated-device.rst       |  3 +-
>  drivers/gpu/drm/i915/gvt/gvt.h                |  1 -
>  drivers/gpu/drm/i915/gvt/kvmgt.c              | 34 +++++++++------
>  drivers/gpu/drm/i915/gvt/vgpu.c               | 41 ++---------------
> --
>  drivers/s390/cio/vfio_ccw_ops.c               | 14 ++-----
>  drivers/s390/crypto/vfio_ap_ops.c             | 16 ++------
>  drivers/vfio/mdev/mdev_sysfs.c                | 11 +++++
>  include/linux/mdev.h                          |  2 +
>  samples/vfio-mdev/mbochs.c                    | 10 ++---
>  samples/vfio-mdev/mdpy.c                      |  9 ++--
>  samples/vfio-mdev/mtty.c                      | 16 ++------
>  11 files changed, 55 insertions(+), 102 deletions(-)
> 
> diff --git a/Documentation/driver-api/vfio-mediated-device.rst
> b/Documentation/driver-api/vfio-mediated-device.rst
> index dcd1231a6fa84..558bd7ebced86 100644
> --- a/Documentation/driver-api/vfio-mediated-device.rst
> +++ b/Documentation/driver-api/vfio-mediated-device.rst
> @@ -103,6 +103,7 @@ structure to represent a mediated device's
> driver::
>       struct mdev_driver {
>              int  (*probe)  (struct mdev_device *dev);
>              void (*remove) (struct mdev_device *dev);
> +            unsigned int (*get_available)(struct mdev_type *mtype);
>              const struct attribute * const *types_attrs;
>              struct device_driver    driver;
>       };
> @@ -207,7 +208,7 @@ Directories and files under the sysfs for Each
> Physical Device
>  
>  * available_instances
>  
> -  This attribute should show the number of devices of type <type-id>
> that can be
> +  This attribute shows the number of devices of type <type-id> that
> can be
>    created.
>  
>  * [device]
> diff --git a/drivers/gpu/drm/i915/gvt/gvt.h
> b/drivers/gpu/drm/i915/gvt/gvt.h
> index db182066d56c9..dbf8d7470b2c1 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -314,7 +314,6 @@ struct intel_vgpu_type {
>         struct mdev_type type;
>         char name[16];
>         const struct intel_vgpu_config *conf;
> -       unsigned int avail_instance;
>  };
>  
>  struct intel_gvt {
> diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c
> b/drivers/gpu/drm/i915/gvt/kvmgt.c
> index 08fe7458b3610..d8be21a3931d9 100644
> --- a/drivers/gpu/drm/i915/gvt/kvmgt.c
> +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
> @@ -113,16 +113,6 @@ static void kvmgt_page_track_flush_slot(struct
> kvm *kvm,
>                 struct kvm_memory_slot *slot,
>                 struct kvm_page_track_notifier_node *node);
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> -{
> -       struct intel_vgpu_type *type =
> -               container_of(mtype, struct intel_vgpu_type, type);
> -
> -       return sprintf(buf, "%u\n", type->avail_instance);
> -}
> -
>  static ssize_t description_show(struct mdev_type *mtype,
>                                 struct mdev_type_attribute *attr,
> char *buf)
>  {
> @@ -138,11 +128,9 @@ static ssize_t description_show(struct mdev_type
> *mtype,
>                        type->conf->weight);
>  }
>  
> -static MDEV_TYPE_ATTR_RO(available_instances);
>  static MDEV_TYPE_ATTR_RO(description);
>  
>  static const struct attribute *gvt_type_attrs[] = {
> -       &mdev_type_attr_available_instances.attr,
>         &mdev_type_attr_description.attr,
>         NULL,
>  };
> @@ -1532,6 +1520,27 @@ static void intel_vgpu_remove(struct
> mdev_device *mdev)
>         vfio_put_device(&vgpu->vfio_device);
>  }
>  
> +static unsigned int intel_vgpu_get_available(struct mdev_type
> *mtype)
> +{
> +       struct intel_vgpu_type *type =
> +               container_of(mtype, struct intel_vgpu_type, type);
> +       struct intel_gvt *gvt = kdev_to_i915(mtype->parent->dev)-
> >gvt;
> +       unsigned int low_gm_avail, high_gm_avail, fence_avail;
> +
> +       mutex_lock(&gvt->lock);
> +       low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE -
> +               gvt->gm.vgpu_allocated_low_gm_size;
> +       high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE -
> +               gvt->gm.vgpu_allocated_high_gm_size;
> +       fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
> +               gvt->fence.vgpu_allocated_fence_num;
> +       mutex_unlock(&gvt->lock);
> +
> +       return min3(low_gm_avail / type->conf->low_mm,
> +                   high_gm_avail / type->conf->high_mm,
> +                   fence_avail / type->conf->fence);
> +}
> +
>  static struct mdev_driver intel_vgpu_mdev_driver = {
>         .device_api     = VFIO_DEVICE_API_PCI_STRING,
>         .driver = {
> @@ -1541,6 +1550,7 @@ static struct mdev_driver
> intel_vgpu_mdev_driver = {
>         },
>         .probe          = intel_vgpu_probe,
>         .remove         = intel_vgpu_remove,
> +       .get_available  = intel_vgpu_get_available,
>         .types_attrs    = gvt_type_attrs,
>  };
>  
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c
> b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 8fa06d00fd4b9..148bf5d6c4fd4 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -129,11 +129,11 @@ int intel_gvt_init_vgpu_types(struct intel_gvt
> *gvt)
>                 sprintf(gvt->types[i].name, "GVTg_V%u_%s",
>                         GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5,
> conf->name);
>                 gvt->types->conf = conf;
> -               gvt->types[i].avail_instance = min(low_avail / conf-
> >low_mm,
> -                                                  high_avail / conf-
> >high_mm);
>  
>                 gvt_dbg_core("type[%d]: %s avail %u low %u high %u
> fence %u weight %u res %s\n",
> -                            i, gvt->types[i].name, gvt-
> >types[i].avail_instance,
> +                            i, gvt->types[i].name,
> +                            min(low_avail / conf->low_mm,
> +                                high_avail / conf->high_mm),
>                              conf->low_mm, conf->high_mm, conf-
> >fence,
>                              conf->weight, vgpu_edid_str(conf-
> >edid));
>  
> @@ -157,36 +157,6 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt
> *gvt)
>         kfree(gvt->types);
>  }
>  
> -static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
> -{
> -       int i;
> -       unsigned int low_gm_avail, high_gm_avail, fence_avail;
> -       unsigned int low_gm_min, high_gm_min, fence_min;
> -
> -       /* Need to depend on maxium hw resource size but keep on
> -        * static config for now.
> -        */
> -       low_gm_avail = gvt_aperture_sz(gvt) - HOST_LOW_GM_SIZE -
> -               gvt->gm.vgpu_allocated_low_gm_size;
> -       high_gm_avail = gvt_hidden_sz(gvt) - HOST_HIGH_GM_SIZE -
> -               gvt->gm.vgpu_allocated_high_gm_size;
> -       fence_avail = gvt_fence_sz(gvt) - HOST_FENCE -
> -               gvt->fence.vgpu_allocated_fence_num;
> -
> -       for (i = 0; i < gvt->num_types; i++) {
> -               low_gm_min = low_gm_avail / gvt->types[i].conf-
> >low_mm;
> -               high_gm_min = high_gm_avail / gvt->types[i].conf-
> >high_mm;
> -               fence_min = fence_avail / gvt->types[i].conf->fence;
> -               gvt->types[i].avail_instance = min(min(low_gm_min,
> high_gm_min),
> -                                                  fence_min);
> -
> -               gvt_dbg_core("update type[%d]: %s avail %u low %u
> high %u fence %u\n",
> -                      i, gvt->types[i].name,
> -                      gvt->types[i].avail_instance, gvt-
> >types[i].conf->low_mm,
> -                      gvt->types[i].conf->high_mm, gvt-
> >types[i].conf->fence);
> -       }
> -}
> -
>  /**
>   * intel_gvt_active_vgpu - activate a virtual GPU
>   * @vgpu: virtual GPU
> @@ -281,10 +251,6 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu
> *vgpu)
>         intel_vgpu_clean_mmio(vgpu);
>         intel_vgpu_dmabuf_cleanup(vgpu);
>         mutex_unlock(&vgpu->vgpu_lock);
> -
> -       mutex_lock(&gvt->lock);
> -       intel_gvt_update_vgpu_types(gvt);
> -       mutex_unlock(&gvt->lock);
>  }
>  
>  #define IDLE_VGPU_IDR 0
> @@ -414,7 +380,6 @@ int intel_gvt_create_vgpu(struct intel_vgpu
> *vgpu,
>         if (ret)
>                 goto out_clean_sched_policy;
>  
> -       intel_gvt_update_vgpu_types(gvt);
>         intel_gvt_update_reg_whitelist(vgpu);
>         mutex_unlock(&gvt->lock);
>         return 0;
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 394aab60dbd0a..559ca18055928 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -44,20 +44,12 @@ static void vfio_ccw_dma_unmap(struct vfio_device
> *vdev, u64 iova, u64 length)
>         vfio_ccw_mdev_reset(private);
>  }
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> +static unsigned int vfio_ccw_get_available(struct mdev_type *mtype)
>  {
>         struct vfio_ccw_private *private = dev_get_drvdata(mtype-
> >parent->dev);
>  
> -       return sprintf(buf, "%d\n", atomic_read(&private->avail));
> +       return atomic_read(&private->avail);
>  }
> -static MDEV_TYPE_ATTR_RO(available_instances);
> -
> -static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_available_instances.attr,
> -       NULL,
> -};
>  
>  static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
>  {
> @@ -620,5 +612,5 @@ struct mdev_driver vfio_ccw_mdev_driver = {
>         },
>         .probe = vfio_ccw_mdev_probe,
>         .remove = vfio_ccw_mdev_remove,
> -       .types_attrs = mdev_types_attrs,
> +       .get_available = vfio_ccw_get_available,
>  };
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 5d8dd7e837f3d..8606f5d75188c 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -790,21 +790,11 @@ static void vfio_ap_mdev_remove(struct
> mdev_device *mdev)
>         vfio_put_device(&matrix_mdev->vdev);
>  }
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> +static unsigned int vfio_ap_mdev_get_available(struct mdev_type
> *mtype)
>  {
> -       return sprintf(buf, "%d\n",
> -                      atomic_read(&matrix_dev-
> >available_instances));
> +       return atomic_read(&matrix_dev->available_instances);
>  }
>  
> -static MDEV_TYPE_ATTR_RO(available_instances);
> -
> -static const struct attribute *vfio_ap_mdev_type_attrs[] = {
> -       &mdev_type_attr_available_instances.attr,
> -       NULL,
> -};
> -
>  #define MDEV_SHARING_ERR "Userspace may not re-assign queue
> %02lx.%04lx " \
>                          "already assigned to %s"
>  
> @@ -1790,7 +1780,7 @@ static struct mdev_driver vfio_ap_matrix_driver
> = {
>         },
>         .probe = vfio_ap_mdev_probe,
>         .remove = vfio_ap_mdev_remove,
> -       .types_attrs = vfio_ap_mdev_type_attrs,
> +       .get_available = vfio_ap_mdev_get_available,
>  };
>  
>  int vfio_ap_mdev_register(void)
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index 34583e6a97f27..b7f87c3eda5ea 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -90,10 +90,21 @@ static ssize_t name_show(struct mdev_type *mtype,
>  
>  static MDEV_TYPE_ATTR_RO(name);
>  
> +static ssize_t available_instances_show(struct mdev_type *mtype,
> +                                       struct mdev_type_attribute
> *attr,
> +                                       char *buf)
> +{
> +       struct mdev_driver *drv = mtype->parent->mdev_driver;
> +
> +       return sysfs_emit(buf, "%u\n", drv->get_available(mtype));
> +}
> +static MDEV_TYPE_ATTR_RO(available_instances);
> +
>  static struct attribute *mdev_types_core_attrs[] = {
>         &mdev_type_attr_create.attr,
>         &mdev_type_attr_device_api.attr,
>         &mdev_type_attr_name.attr,
> +       &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index 4bb8a58b577b3..d39e08a1824c6 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -72,6 +72,7 @@ struct mdev_type_attribute {
>   * @device_api: string to return for the device_api sysfs
>   * @probe: called when new device created
>   * @remove: called when device removed
> + * @get_available: Return the max number of instances that can be
> created
>   * @types_attrs: attributes to the type kobjects.
>   * @driver: device driver structure
>   **/
> @@ -79,6 +80,7 @@ struct mdev_driver {
>         const char *device_api;
>         int (*probe)(struct mdev_device *dev);
>         void (*remove)(struct mdev_device *dev);
> +       unsigned int (*get_available)(struct mdev_type *mtype);
>         const struct attribute * const *types_attrs;
>         struct device_driver driver;
>  };
> diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
> index 0b7585f16d8ab..6c2cbc4e25ca9 100644
> --- a/samples/vfio-mdev/mbochs.c
> +++ b/samples/vfio-mdev/mbochs.c
> @@ -1361,21 +1361,16 @@ static ssize_t description_show(struct
> mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(description);
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> +static unsigned int mbochs_get_available(struct mdev_type *mtype)
>  {
>         struct mbochs_type *type =
>                 container_of(mtype, struct mbochs_type, type);
> -       int count = atomic_read(&mbochs_avail_mbytes) / type->mbytes;
>  
> -       return sprintf(buf, "%d\n", count);
> +       return atomic_read(&mbochs_avail_mbytes) / type->mbytes;
>  }
> -static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_description.attr,
> -       &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> @@ -1399,6 +1394,7 @@ static struct mdev_driver mbochs_driver = {
>         },
>         .probe = mbochs_probe,
>         .remove = mbochs_remove,
> +       .get_available = mbochs_get_available,
>         .types_attrs = mdev_types_attrs,
>  };
>  
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index 90c6fed200b19..d1c835c9cabf2 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -671,17 +671,13 @@ static ssize_t description_show(struct
> mdev_type *mtype,
>  }
>  static MDEV_TYPE_ATTR_RO(description);
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> +static unsigned int mdpy_get_available(struct mdev_type *mtype)
>  {
> -       return sprintf(buf, "%d\n", max_devices - mdpy_count);
> +       return max_devices - mdpy_count;
>  }
> -static MDEV_TYPE_ATTR_RO(available_instances);
>  
>  static const struct attribute *mdev_types_attrs[] = {
>         &mdev_type_attr_description.attr,
> -       &mdev_type_attr_available_instances.attr,
>         NULL,
>  };
>  
> @@ -704,6 +700,7 @@ static struct mdev_driver mdpy_driver = {
>         },
>         .probe = mdpy_probe,
>         .remove = mdpy_remove,
> +       .get_available = mdpy_get_available,
>         .types_attrs = mdev_types_attrs,
>  };
>  
> diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c
> index eab1b4442a96e..e72085fc13763 100644
> --- a/samples/vfio-mdev/mtty.c
> +++ b/samples/vfio-mdev/mtty.c
> @@ -1256,23 +1256,13 @@ static const struct attribute_group
> *mdev_dev_groups[] = {
>         NULL,
>  };
>  
> -static ssize_t available_instances_show(struct mdev_type *mtype,
> -                                       struct mdev_type_attribute
> *attr,
> -                                       char *buf)
> +static unsigned int mtty_get_available(struct mdev_type *mtype)
>  {
>         struct mtty_type *type = container_of(mtype, struct
> mtty_type, type);
>  
> -       return sprintf(buf, "%d\n", atomic_read(&mdev_avail_ports) /
> -                       type->nr_ports);
> +       return atomic_read(&mdev_avail_ports) / type->nr_ports;
>  }
>  
> -static MDEV_TYPE_ATTR_RO(available_instances);
> -
> -static const struct attribute *mdev_types_attrs[] = {
> -       &mdev_type_attr_available_instances.attr,
> -       NULL,
> -};
> -
>  static const struct vfio_device_ops mtty_dev_ops = {
>         .name = "vfio-mtty",
>         .init = mtty_init_dev,
> @@ -1292,7 +1282,7 @@ static struct mdev_driver mtty_driver = {
>         },
>         .probe = mtty_probe,
>         .remove = mtty_remove,
> -       .types_attrs = mdev_types_attrs,
> +       .get_available = mtty_get_available,
>  };
>  
>  static void mtty_device_release(struct device *dev)


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

* Re: [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core
  2022-09-23  9:26 ` [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core Christoph Hellwig
@ 2022-09-27  1:28   ` Eric Farman
  0 siblings, 0 replies; 31+ messages in thread
From: Eric Farman @ 2022-09-27  1:28 UTC (permalink / raw)
  To: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

On Fri, 2022-09-23 at 11:26 +0200, Christoph Hellwig wrote:
> From: Jason Gunthorpe <jgg@nvidia.com>
> 
> Many of the mdev drivers use a simple counter for keeping track of
> the
> available instances. Move this code to the core code and store the
> counter
> in the mdev_parent. Implement it using correct locking, fixing mdpy.
> 
> Drivers just provide the value in the mdev_driver at registration
> time
> and the core code takes care of maintaining it and exposing the value
> in
> sysfs.
> 
> Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
> [hch: count instances per-parent instead of per-type, use an atomic_t
>  to avoid taking mdev_list_lock in the show method]
> Signed-off-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Kevin Tian <kevin.tian@intel.com>
> Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>

Reviewed-by: Eric Farman <farman@linux.ibm.com>

> ---
>  drivers/s390/cio/vfio_ccw_drv.c       |  1 -
>  drivers/s390/cio/vfio_ccw_ops.c       | 15 +--------------
>  drivers/s390/cio/vfio_ccw_private.h   |  2 --
>  drivers/s390/crypto/vfio_ap_ops.c     | 13 +------------
>  drivers/s390/crypto/vfio_ap_private.h |  2 --
>  drivers/vfio/mdev/mdev_core.c         | 22 +++++++++++++++++++---
>  drivers/vfio/mdev/mdev_sysfs.c        |  5 ++++-
>  include/linux/mdev.h                  |  3 +++
>  samples/vfio-mdev/mdpy.c              | 22 ++++------------------
>  9 files changed, 32 insertions(+), 53 deletions(-)
> 
> diff --git a/drivers/s390/cio/vfio_ccw_drv.c
> b/drivers/s390/cio/vfio_ccw_drv.c
> index e5f21c725326b..7f5402fe857a2 100644
> --- a/drivers/s390/cio/vfio_ccw_drv.c
> +++ b/drivers/s390/cio/vfio_ccw_drv.c
> @@ -141,7 +141,6 @@ static struct vfio_ccw_private
> *vfio_ccw_alloc_private(struct subchannel *sch)
>         INIT_LIST_HEAD(&private->crw);
>         INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
>         INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
> -       atomic_set(&private->avail, 1);
>  
>         private->cp.guest_cp = kcalloc(CCWCHAIN_LEN_MAX,
> sizeof(struct ccw1),
>                                        GFP_KERNEL);
> diff --git a/drivers/s390/cio/vfio_ccw_ops.c
> b/drivers/s390/cio/vfio_ccw_ops.c
> index 559ca18055928..6ae4d012d8008 100644
> --- a/drivers/s390/cio/vfio_ccw_ops.c
> +++ b/drivers/s390/cio/vfio_ccw_ops.c
> @@ -44,13 +44,6 @@ static void vfio_ccw_dma_unmap(struct vfio_device
> *vdev, u64 iova, u64 length)
>         vfio_ccw_mdev_reset(private);
>  }
>  
> -static unsigned int vfio_ccw_get_available(struct mdev_type *mtype)
> -{
> -       struct vfio_ccw_private *private = dev_get_drvdata(mtype-
> >parent->dev);
> -
> -       return atomic_read(&private->avail);
> -}
> -
>  static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
>  {
>         struct vfio_ccw_private *private =
> @@ -68,9 +61,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device
> *mdev)
>         if (private->state == VFIO_CCW_STATE_NOT_OPER)
>                 return -ENODEV;
>  
> -       if (atomic_dec_if_positive(&private->avail) < 0)
> -               return -EPERM;
> -
>         ret = vfio_init_device(&private->vdev, &mdev->dev,
> &vfio_ccw_dev_ops);
>         if (ret)
>                 return ret;
> @@ -88,7 +78,6 @@ static int vfio_ccw_mdev_probe(struct mdev_device
> *mdev)
>  
>  err_put_vdev:
>         vfio_put_device(&private->vdev);
> -       atomic_inc(&private->avail);
>         return ret;
>  }
>  
> @@ -130,8 +119,6 @@ static void vfio_ccw_mdev_remove(struct
> mdev_device *mdev)
>          * cycle.
>          */
>         wait_for_completion(&private->release_comp);
> -
> -       atomic_inc(&private->avail);
>  }
>  
>  static int vfio_ccw_mdev_open_device(struct vfio_device *vdev)
> @@ -605,6 +592,7 @@ static const struct vfio_device_ops
> vfio_ccw_dev_ops = {
>  
>  struct mdev_driver vfio_ccw_mdev_driver = {
>         .device_api = VFIO_DEVICE_API_CCW_STRING,
> +       .max_instances = 1,
>         .driver = {
>                 .name = "vfio_ccw_mdev",
>                 .owner = THIS_MODULE,
> @@ -612,5 +600,4 @@ struct mdev_driver vfio_ccw_mdev_driver = {
>         },
>         .probe = vfio_ccw_mdev_probe,
>         .remove = vfio_ccw_mdev_remove,
> -       .get_available = vfio_ccw_get_available,
>  };
> diff --git a/drivers/s390/cio/vfio_ccw_private.h
> b/drivers/s390/cio/vfio_ccw_private.h
> index 52caa721ec06c..bd5fb81456af8 100644
> --- a/drivers/s390/cio/vfio_ccw_private.h
> +++ b/drivers/s390/cio/vfio_ccw_private.h
> @@ -73,7 +73,6 @@ struct vfio_ccw_crw {
>   * @sch: pointer to the subchannel
>   * @state: internal state of the device
>   * @completion: synchronization helper of the I/O completion
> - * @avail: available for creating a mediated device
>   * @io_region: MMIO region to input/output I/O arguments/results
>   * @io_mutex: protect against concurrent update of I/O regions
>   * @region: additional regions for other subchannel operations
> @@ -97,7 +96,6 @@ struct vfio_ccw_private {
>         struct subchannel       *sch;
>         int                     state;
>         struct completion       *completion;
> -       atomic_t                avail;
>         struct ccw_io_region    *io_region;
>         struct mutex            io_mutex;
>         struct vfio_ccw_region *region;
> diff --git a/drivers/s390/crypto/vfio_ap_ops.c
> b/drivers/s390/crypto/vfio_ap_ops.c
> index 8606f5d75188c..2884189f38771 100644
> --- a/drivers/s390/crypto/vfio_ap_ops.c
> +++ b/drivers/s390/crypto/vfio_ap_ops.c
> @@ -689,9 +689,6 @@ static int vfio_ap_mdev_init_dev(struct
> vfio_device *vdev)
>         struct ap_matrix_mdev *matrix_mdev =
>                 container_of(vdev, struct ap_matrix_mdev, vdev);
>  
> -       if ((atomic_dec_if_positive(&matrix_dev->available_instances)
> < 0))
> -               return -EPERM;
> -
>         matrix_mdev->mdev = to_mdev_device(vdev->dev);
>         vfio_ap_matrix_init(&matrix_dev->info, &matrix_mdev->matrix);
>         matrix_mdev->pqap_hook = handle_pqap;
> @@ -770,7 +767,6 @@ static void vfio_ap_mdev_unlink_fr_queues(struct
> ap_matrix_mdev *matrix_mdev)
>  
>  static void vfio_ap_mdev_release_dev(struct vfio_device *vdev)
>  {
> -       atomic_inc(&matrix_dev->available_instances);
>         vfio_free_device(vdev);
>  }
>  
> @@ -790,11 +786,6 @@ static void vfio_ap_mdev_remove(struct
> mdev_device *mdev)
>         vfio_put_device(&matrix_mdev->vdev);
>  }
>  
> -static unsigned int vfio_ap_mdev_get_available(struct mdev_type
> *mtype)
> -{
> -       return atomic_read(&matrix_dev->available_instances);
> -}
> -
>  #define MDEV_SHARING_ERR "Userspace may not re-assign queue
> %02lx.%04lx " \
>                          "already assigned to %s"
>  
> @@ -1772,6 +1763,7 @@ static const struct vfio_device_ops
> vfio_ap_matrix_dev_ops = {
>  
>  static struct mdev_driver vfio_ap_matrix_driver = {
>         .device_api = VFIO_DEVICE_API_AP_STRING,
> +       .max_instances = MAX_ZDEV_ENTRIES_EXT,
>         .driver = {
>                 .name = "vfio_ap_mdev",
>                 .owner = THIS_MODULE,
> @@ -1780,15 +1772,12 @@ static struct mdev_driver
> vfio_ap_matrix_driver = {
>         },
>         .probe = vfio_ap_mdev_probe,
>         .remove = vfio_ap_mdev_remove,
> -       .get_available = vfio_ap_mdev_get_available,
>  };
>  
>  int vfio_ap_mdev_register(void)
>  {
>         int ret;
>  
> -       atomic_set(&matrix_dev->available_instances,
> MAX_ZDEV_ENTRIES_EXT);
> -
>         ret = mdev_register_driver(&vfio_ap_matrix_driver);
>         if (ret)
>                 return ret;
> diff --git a/drivers/s390/crypto/vfio_ap_private.h
> b/drivers/s390/crypto/vfio_ap_private.h
> index 441dc8dda380b..2eddd5f34ed34 100644
> --- a/drivers/s390/crypto/vfio_ap_private.h
> +++ b/drivers/s390/crypto/vfio_ap_private.h
> @@ -29,7 +29,6 @@
>   * struct ap_matrix_dev - Contains the data for the matrix device.
>   *
>   * @device:    generic device structure associated with the AP
> matrix device
> - * @available_instances: number of mediated matrix devices that can
> be created
>   * @info:      the struct containing the output from the PQAP(QCI)
> instruction
>   * @mdev_list: the list of mediated matrix devices created
>   * @mdevs_lock: mutex for locking the AP matrix device. This lock
> will be
> @@ -46,7 +45,6 @@
>   */
>  struct ap_matrix_dev {
>         struct device device;
> -       atomic_t available_instances;
>         struct ap_config_info info;
>         struct list_head mdev_list;
>         struct mutex mdevs_lock; /* serializes access to each
> ap_matrix_mdev */
> diff --git a/drivers/vfio/mdev/mdev_core.c
> b/drivers/vfio/mdev/mdev_core.c
> index 93f8caf2e5f77..58f91b3bd670c 100644
> --- a/drivers/vfio/mdev/mdev_core.c
> +++ b/drivers/vfio/mdev/mdev_core.c
> @@ -70,6 +70,7 @@ int mdev_register_parent(struct mdev_parent
> *parent, struct device *dev,
>         parent->mdev_driver = mdev_driver;
>         parent->types = types;
>         parent->nr_types = nr_types;
> +       atomic_set(&parent->available_instances, mdev_driver-
> >max_instances);
>  
>         if (!mdev_bus_compat_class) {
>                 mdev_bus_compat_class =
> class_compat_register("mdev_bus");
> @@ -115,14 +116,17 @@ EXPORT_SYMBOL(mdev_unregister_parent);
>  static void mdev_device_release(struct device *dev)
>  {
>         struct mdev_device *mdev = to_mdev_device(dev);
> -
> -       /* Pairs with the get in mdev_device_create() */
> -       kobject_put(&mdev->type->kobj);
> +       struct mdev_parent *parent = mdev->type->parent;
>  
>         mutex_lock(&mdev_list_lock);
>         list_del(&mdev->next);
> +       if (!parent->mdev_driver->get_available)
> +               atomic_inc(&parent->available_instances);
>         mutex_unlock(&mdev_list_lock);
>  
> +       /* Pairs with the get in mdev_device_create() */
> +       kobject_put(&mdev->type->kobj);
> +
>         dev_dbg(&mdev->dev, "MDEV: destroying\n");
>         kfree(mdev);
>  }
> @@ -144,6 +148,18 @@ int mdev_device_create(struct mdev_type *type,
> const guid_t *uuid)
>                 }
>         }
>  
> +       if (!drv->get_available) {
> +               /*
> +                * Note: that non-atomic read and dec is fine here
> because
> +                * all modifications are under mdev_list_lock.
> +                */
> +               if (!atomic_read(&parent->available_instances)) {
> +                       mutex_unlock(&mdev_list_lock);
> +                       return -EUSERS;
> +               }
> +               atomic_dec(&parent->available_instances);
> +       }
> +
>         mdev = kzalloc(sizeof(*mdev), GFP_KERNEL);
>         if (!mdev) {
>                 mutex_unlock(&mdev_list_lock);
> diff --git a/drivers/vfio/mdev/mdev_sysfs.c
> b/drivers/vfio/mdev/mdev_sysfs.c
> index 658b3bf5ed0bf..abe3359dd477f 100644
> --- a/drivers/vfio/mdev/mdev_sysfs.c
> +++ b/drivers/vfio/mdev/mdev_sysfs.c
> @@ -108,7 +108,10 @@ static ssize_t available_instances_show(struct
> mdev_type *mtype,
>  {
>         struct mdev_driver *drv = mtype->parent->mdev_driver;
>  
> -       return sysfs_emit(buf, "%u\n", drv->get_available(mtype));
> +       if (drv->get_available)
> +               return sysfs_emit(buf, "%u\n", drv-
> >get_available(mtype));
> +       return sysfs_emit(buf, "%u\n",
> +                         atomic_read(&mtype->parent-
> >available_instances));
>  }
>  static MDEV_TYPE_ATTR_RO(available_instances);
>  
> diff --git a/include/linux/mdev.h b/include/linux/mdev.h
> index 33674cb5ed5d4..139d05b26f820 100644
> --- a/include/linux/mdev.h
> +++ b/include/linux/mdev.h
> @@ -45,6 +45,7 @@ struct mdev_parent {
>         struct rw_semaphore unreg_sem;
>         struct mdev_type **types;
>         unsigned int nr_types;
> +       atomic_t available_instances;
>  };
>  
>  static inline struct mdev_device *to_mdev_device(struct device *dev)
> @@ -55,6 +56,7 @@ static inline struct mdev_device
> *to_mdev_device(struct device *dev)
>  /**
>   * struct mdev_driver - Mediated device driver
>   * @device_api: string to return for the device_api sysfs
> + * @max_instances: maximum number of instances supported (optional)
>   * @probe: called when new device created
>   * @remove: called when device removed
>   * @get_available: Return the max number of instances that can be
> created
> @@ -63,6 +65,7 @@ static inline struct mdev_device
> *to_mdev_device(struct device *dev)
>   **/
>  struct mdev_driver {
>         const char *device_api;
> +       unsigned int max_instances;
>         int (*probe)(struct mdev_device *dev);
>         void (*remove)(struct mdev_device *dev);
>         unsigned int (*get_available)(struct mdev_type *mtype);
> diff --git a/samples/vfio-mdev/mdpy.c b/samples/vfio-mdev/mdpy.c
> index a7cf59246ddd0..946e8cfde6fdd 100644
> --- a/samples/vfio-mdev/mdpy.c
> +++ b/samples/vfio-mdev/mdpy.c
> @@ -42,11 +42,6 @@
>  
>  MODULE_LICENSE("GPL v2");
>  
> -static int max_devices = 4;
> -module_param_named(count, max_devices, int, 0444);
> -MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
> -
> -
>  #define MDPY_TYPE_1 "vga"
>  #define MDPY_TYPE_2 "xga"
>  #define MDPY_TYPE_3 "hd"
> @@ -93,7 +88,6 @@ static struct class   *mdpy_class;
>  static struct cdev     mdpy_cdev;
>  static struct device   mdpy_dev;
>  static struct mdev_parent mdpy_parent;
> -static u32             mdpy_count;
>  static const struct vfio_device_ops mdpy_dev_ops;
>  
>  /* State of each mdev device */
> @@ -235,9 +229,6 @@ static int mdpy_init_dev(struct vfio_device
> *vdev)
>         u32 fbsize;
>         int ret = -ENOMEM;
>  
> -       if (mdpy_count >= max_devices)
> -               return ret;
> -
>         mdev_state->vconfig = kzalloc(MDPY_CONFIG_SPACE_SIZE,
> GFP_KERNEL);
>         if (!mdev_state->vconfig)
>                 return ret;
> @@ -257,8 +248,6 @@ static int mdpy_init_dev(struct vfio_device
> *vdev)
>  
>         dev_info(vdev->dev, "%s: %s (%dx%d)\n", __func__, type-
> >type.pretty_name,
>                  type->width, type->height);
> -
> -       mdpy_count++;
>         return 0;
>  
>  out_vconfig:
> @@ -292,7 +281,6 @@ static void mdpy_release_dev(struct vfio_device
> *vdev)
>         struct mdev_state *mdev_state =
>                 container_of(vdev, struct mdev_state, vdev);
>  
> -       mdpy_count--;
>         vfree(mdev_state->memblk);
>         kfree(mdev_state->vconfig);
>         vfio_free_device(vdev);
> @@ -669,11 +657,6 @@ static ssize_t mdpy_show_description(struct
> mdev_type *mtype, char *buf)
>                        type->width, type->height);
>  }
>  
> -static unsigned int mdpy_get_available(struct mdev_type *mtype)
> -{
> -       return max_devices - mdpy_count;
> -}
> -
>  static const struct vfio_device_ops mdpy_dev_ops = {
>         .init = mdpy_init_dev,
>         .release = mdpy_release_dev,
> @@ -685,6 +668,7 @@ static const struct vfio_device_ops mdpy_dev_ops
> = {
>  
>  static struct mdev_driver mdpy_driver = {
>         .device_api = VFIO_DEVICE_API_PCI_STRING,
> +       .max_instances = 4,
>         .driver = {
>                 .name = "mdpy",
>                 .owner = THIS_MODULE,
> @@ -693,7 +677,6 @@ static struct mdev_driver mdpy_driver = {
>         },
>         .probe = mdpy_probe,
>         .remove = mdpy_remove,
> -       .get_available = mdpy_get_available,
>         .show_description = mdpy_show_description,
>  };
>  
> @@ -770,5 +753,8 @@ static void __exit mdpy_dev_exit(void)
>         mdpy_class = NULL;
>  }
>  
> +module_param_named(count, mdpy_driver.max_instances, int, 0444);
> +MODULE_PARM_DESC(count, "number of " MDPY_NAME " devices");
> +
>  module_init(mdpy_dev_init)
>  module_exit(mdpy_dev_exit)


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

* Re: simplify the mdev interface v8
  2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
                   ` (13 preceding siblings ...)
  2022-09-23  9:26 ` [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core Christoph Hellwig
@ 2022-09-27 20:07 ` Alex Williamson
  2022-09-27 21:54   ` Alex Williamson
  14 siblings, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2022-09-27 20:07 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Fri, 23 Sep 2022 11:26:38 +0200
Christoph Hellwig <hch@lst.de> wrote:

> Hi all,
> 
> this series significantly simplifies the mdev driver interface by
> following the patterns for device model interaction used elsewhere in
> the kernel.
> 
> Changes since v7:
>  - rebased to the latests vfio/next branch
>  - move the mdev.h include from cio.h to vfio_ccw_private.h
>  - don't free the parent in mdev_type_release
>  - set the pretty_name for vfio_ap
>  - fix the available_instances check in mdev_device_create

Thanks for your persistence, I think all threads are resolved at this
point.  Applied to vfio next branch for v6.1.  Thanks,

Alex


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

* Re: simplify the mdev interface v8
  2022-09-27 20:07 ` simplify the mdev interface v8 Alex Williamson
@ 2022-09-27 21:54   ` Alex Williamson
  2022-09-28 12:11     ` Christoph Hellwig
  0 siblings, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2022-09-27 21:54 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Tue, 27 Sep 2022 14:07:37 -0600
Alex Williamson <alex.williamson@redhat.com> wrote:

> On Fri, 23 Sep 2022 11:26:38 +0200
> Christoph Hellwig <hch@lst.de> wrote:
> 
> > Hi all,
> > 
> > this series significantly simplifies the mdev driver interface by
> > following the patterns for device model interaction used elsewhere in
> > the kernel.
> > 
> > Changes since v7:
> >  - rebased to the latests vfio/next branch
> >  - move the mdev.h include from cio.h to vfio_ccw_private.h
> >  - don't free the parent in mdev_type_release
> >  - set the pretty_name for vfio_ap
> >  - fix the available_instances check in mdev_device_create  
> 
> Thanks for your persistence, I think all threads are resolved at this
> point.  Applied to vfio next branch for v6.1.  Thanks,

Oops, I had to drop this, I get a null pointer from gvt-g code:

[   92.132636] BUG: kernel NULL pointer dereference, address: 0000000000000000
[   92.139597] #PF: supervisor read access in kernel mode
[   92.144734] #PF: error_code(0x0000) - not-present page
[   92.149865] PGD 0 P4D 0 
[   92.152405] Oops: 0000 [#2] PREEMPT SMP PTI
[   92.156592] CPU: 2 PID: 950 Comm: mdevctl Tainted: G      D W          6.0.0-rc4+ #1
[   92.164330] Hardware name:  /NUC5i5MYBE, BIOS MYBDWi5v.86A.0054.2019.0520.1531 05/20/2019
[   92.172495] RIP: 0010:intel_vgpu_get_available+0x7e/0xb0 [kvmgt]
[   92.178518] Code: 00 45 2b a5 a0 00 00 00 89 d1 41 2b 8d 90 00 00 00 29 d3 41 83 ec 04 8d a9 00 00 00 f8 e8 fa f3 43 e1 49 8b 4e 70 89 e8 31 d2 <f7> 31 31 d2 89 c5 44 89 e0 f7 71 08 39 c5 0f 47 e8 89 d8 31 d2 5b
[   92.197264] RSP: 0018:ffffaf57818ffd80 EFLAGS: 00010246
[   92.202490] RAX: 0000000038000000 RBX: 00000000a8000000 RCX: 0000000000000000
[   92.209622] RDX: 0000000000000000 RSI: ffffffffc0454160 RDI: ffff9b389aaa8000
[   92.216747] RBP: 0000000038000000 R08: ffff9b3881826f08 R09: ffff9b38969aeb40
[   92.223879] R10: 0000000000000000 R11: 0000000000000000 R12: 000000000000001c
[   92.231004] R13: ffff9b389aaa8000 R14: ffff9b3881826ef0 R15: 0000000000000001
[   92.238136] FS:  00007f2f76f12800(0000) GS:ffff9b3bf6d00000(0000) knlGS:0000000000000000
[   92.246222] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   92.251968] CR2: 0000000000000000 CR3: 000000011686e002 CR4: 00000000003706e0
[   92.259101] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   92.266234] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   92.273366] Call Trace:
[   92.275811]  <TASK>
[   92.277919]  available_instances_show+0x1f/0x60 [mdev]
[   92.283055]  sysfs_kf_seq_show+0xa3/0xe0
[   92.286983]  seq_read_iter+0x122/0x450
[   92.290735]  vfs_read+0x1d2/0x2a0
[   92.294056]  ksys_read+0x53/0xd0
[   92.297286]  do_syscall_64+0x5b/0x80
[   92.300866]  ? syscall_exit_to_user_mode+0x17/0x40
[   92.305659]  ? do_syscall_64+0x67/0x80
[   92.309412]  ? exc_page_fault+0x70/0x170
[   92.313337]  entry_SYSCALL_64_after_hwframe+0x63/0xcd
[   92.318388] RIP: 0033:0x7f2f76d01852
[   92.321977] Code: c0 e9 b2 fe ff ff 50 48 8d 3d 9a d0 0b 00 e8 55 f6 01 00 0f 1f 44 00 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 0f 05 <48> 3d 00 f0 ff ff 77 56 c3 0f 1f 44 00 00 48 83 ec 28 48 89 54 24
[   92.340725] RSP: 002b:00007fff85c74b58 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
[   92.348290] RAX: ffffffffffffffda RBX: 0000000000001000 RCX: 00007f2f76d01852
[   92.355422] RDX: 0000000000001000 RSI: 0000562f18d61120 RDI: 0000000000000005
[   92.362555] RBP: 0000000000001000 R08: 00007f2f76df8eb0 R09: 00007f2f76df8eb0
[   92.369689] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff85c74c58
[   92.376820] R13: 0000000000000000 R14: 00007fff85c74c70 R15: 0000000000000005
[   92.383946]  </TASK>
[   92.386137] Modules linked in: nft_fib_inet nft_fib_ipv4 nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 ip_set nf_tables rfkill nfnetlink qrtr sunrpc vfat fat snd_hda_codec_realtek snd_hda_codec_generic snd_hda_codec_hdmi ledtrig_audio snd_hda_intel snd_intel_dspcfg snd_intel_sdw_acpi snd_hda_codec snd_hda_core snd_hwdep mei_pxp intel_rapl_msr intel_rapl_common snd_pcm x86_pkg_temp_thermal intel_powerclamp coretemp mei_wdt mei_hdcp kvm_intel mei_me rapl mei intel_cstate snd_timer snd at24 intel_uncore soundcore iTCO_wdt intel_pmc_bxt iTCO_vendor_support lpc_ich pcspkr i2c_i801 i2c_smbus acpi_pad fuse zram kvmgt vfio_iommu_type1 vfio kvm irqbypass i915 mdev drm_buddy crct10dif_pclmul crc32_pclmul drm_display_helper crc32c_intel cec e1000e ghash_clmulni_intel ttm video pinctrl_lynxpoint
[   92.386194] Unloaded tainted modules: acpi_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 fjes():1 fjes():1 fjes():1 fjes():1 fjes():1 pcc_cpufreq():1 pcc_cpufreq():1 pcc_cpufreq():1 pcc_cpufreq():1 acpi_cpufreq():1 pcc_cpufreq():1 acpi_cpufreq():1 pcc_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 pcc_cpufreq():1 pcc_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 acpi_cpufreq():1 fjes():1 fjes():1 fjes():1 fjes():1 fjes():1
[   92.504665] CR2: 0000000000000000
[   92.507982] ---[ end trace 0000000000000000 ]---
[   92.512603] RIP: 0010:intel_vgpu_get_available+0x7e/0xb0 [kvmgt]
[   92.518626] Code: 00 45 2b a5 a0 00 00 00 89 d1 41 2b 8d 90 00 00 00 29 d3 41 83 ec 04 8d a9 00 00 00 f8 e8 fa f3 43 e1 49 8b 4e 70 89 e8 31 d2 <f7> 31 31 d2 89 c5 44 89 e0 f7 71 08 39 c5 0f 47 e8 89 d8 31 d2 5b
[   92.537370] RSP: 0018:ffffaf5780557d20 EFLAGS: 00010246
[   92.542598] RAX: 0000000038000000 RBX: 00000000a8000000 RCX: 0000000000000000
[   92.549729] RDX: 0000000000000000 RSI: ffffffffc0454160 RDI: ffff9b389aaa8000
[   92.556861] RBP: 0000000038000000 R08: ffff9b3881826e90 R09: ffff9b3897860240
[   92.563987] R10: 0000000000000000 R11: 0000000000000001 R12: 000000000000001c
[   92.571119] R13: ffff9b389aaa8000 R14: ffff9b3881826e78 R15: 0000000000000001
[   92.578251] FS:  00007f2f76f12800(0000) GS:ffff9b3bf6d00000(0000) knlGS:0000000000000000
[   92.586336] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   92.592074] CR2: 0000000000000000 CR3: 000000011686e002 CR4: 00000000003706e0
[   92.599199] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   92.606333] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400


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

* Re: simplify the mdev interface v8
  2022-09-27 21:54   ` Alex Williamson
@ 2022-09-28 12:11     ` Christoph Hellwig
  2022-09-28 18:56       ` Alex Williamson
  2022-09-30 21:31       ` Alex Williamson
  0 siblings, 2 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-28 12:11 UTC (permalink / raw)
  To: Alex Williamson
  Cc: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Tue, Sep 27, 2022 at 03:54:26PM -0600, Alex Williamson wrote:
> Oops, I had to drop this, I get a null pointer from gvt-g code:

Ok, this is a stupid bug in the second patch in the series.  I did not
hit it in my mdev testing as my script just uses the first type and
thus never hits these, but as your trace showed mdevctl and once I
used that I could reproduce it.  The fix for patch 2 is below, and
the git tree at:

   git://git.infradead.org/users/hch/misc.git mvdev-lifetime

has been updated with that folded in and the recent reviews.

---
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 1b67328c714f1..b0d5dafd013f4 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -123,7 +123,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
 
 		sprintf(gvt->types[i].name, "GVTg_V%u_%s",
 			GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
-		gvt->types->conf = conf;
+		gvt->types[i].conf = conf;
 		gvt->types[i].avail_instance = min(low_avail / conf->low_mm,
 						   high_avail / conf->high_mm);
 

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

* Re: simplify the mdev interface v8
  2022-09-28 12:11     ` Christoph Hellwig
@ 2022-09-28 18:56       ` Alex Williamson
  2022-09-29  7:11         ` Christoph Hellwig
  2022-09-30 21:31       ` Alex Williamson
  1 sibling, 1 reply; 31+ messages in thread
From: Alex Williamson @ 2022-09-28 18:56 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Wed, 28 Sep 2022 14:11:10 +0200
Christoph Hellwig <hch@lst.de> wrote:

> On Tue, Sep 27, 2022 at 03:54:26PM -0600, Alex Williamson wrote:
> > Oops, I had to drop this, I get a null pointer from gvt-g code:  
> 
> Ok, this is a stupid bug in the second patch in the series.  I did not
> hit it in my mdev testing as my script just uses the first type and
> thus never hits these, but as your trace showed mdevctl and once I
> used that I could reproduce it.  The fix for patch 2 is below, and
> the git tree at:
> 
>    git://git.infradead.org/users/hch/misc.git mvdev-lifetime
> 
> has been updated with that folded in and the recent reviews.

That fixes the crash, but available_instances isn't working:

[root@nuc ~]# cd /sys/class/mdev_bus/0000\:00\:02.0/mdev_supported_types/
[root@nuc mdev_supported_types]# ls */devices/
i915-GVTg_V4_1/devices/:

i915-GVTg_V4_2/devices/:

i915-GVTg_V4_4/devices/:

i915-GVTg_V4_8/devices/:
[root@nuc mdev_supported_types]# grep . */available_instances
i915-GVTg_V4_1/available_instances:1
i915-GVTg_V4_2/available_instances:2
i915-GVTg_V4_4/available_instances:5
i915-GVTg_V4_8/available_instances:7
[root@nuc mdev_supported_types]# uuidgen > i915-GVTg_V4_1/create
[root@nuc mdev_supported_types]# ls */devices/
i915-GVTg_V4_1/devices/:
669d83b1-81d8-4fd4-8d8b-7f972721c83f

i915-GVTg_V4_2/devices/:

i915-GVTg_V4_4/devices/:

i915-GVTg_V4_8/devices/:
[root@nuc mdev_supported_types]# grep . */available_instances
i915-GVTg_V4_1/available_instances:0
i915-GVTg_V4_2/available_instances:0
i915-GVTg_V4_4/available_instances:1
i915-GVTg_V4_8/available_instances:1
[root@nuc mdev_supported_types]# echo 1 > i915-GVTg_V4_1/devices/669d83b1-81d8-4fd4-8d8b-7f972721c83f/remove 
[root@nuc mdev_supported_types]# ls */devices/
i915-GVTg_V4_1/devices/:

i915-GVTg_V4_2/devices/:

i915-GVTg_V4_4/devices/:

i915-GVTg_V4_8/devices/:
[root@nuc mdev_supported_types]# grep . */available_instances
i915-GVTg_V4_1/available_instances:0
i915-GVTg_V4_2/available_instances:0
i915-GVTg_V4_4/available_instances:1
i915-GVTg_V4_8/available_instances:1


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

* Re: simplify the mdev interface v8
  2022-09-28 18:56       ` Alex Williamson
@ 2022-09-29  7:11         ` Christoph Hellwig
  0 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-09-29  7:11 UTC (permalink / raw)
  To: Alex Williamson
  Cc: Christoph Hellwig, Kirti Wankhede, Tony Krowiak, Halil Pasic,
	Jason Herne, Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Wed, Sep 28, 2022 at 12:56:50PM -0600, Alex Williamson wrote:
> That fixes the crash, but available_instances isn't working:

I see the same behavior both with and without my series.  Given that
the code to report it didn't change that is also very much expected.

So something in i915 fails to update the resources when deleting
instances, but it is an existing issue.

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

* Re: simplify the mdev interface v8
  2022-09-28 12:11     ` Christoph Hellwig
  2022-09-28 18:56       ` Alex Williamson
@ 2022-09-30 21:31       ` Alex Williamson
  1 sibling, 0 replies; 31+ messages in thread
From: Alex Williamson @ 2022-09-30 21:31 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev

On Wed, 28 Sep 2022 14:11:10 +0200
Christoph Hellwig <hch@lst.de> wrote:

> On Tue, Sep 27, 2022 at 03:54:26PM -0600, Alex Williamson wrote:
> > Oops, I had to drop this, I get a null pointer from gvt-g code:  
> 
> Ok, this is a stupid bug in the second patch in the series.  I did not
> hit it in my mdev testing as my script just uses the first type and
> thus never hits these, but as your trace showed mdevctl and once I
> used that I could reproduce it.  The fix for patch 2 is below, and
> the git tree at:
> 
>    git://git.infradead.org/users/hch/misc.git mvdev-lifetime
> 
> has been updated with that folded in and the recent reviews.
> 
> ---
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 1b67328c714f1..b0d5dafd013f4 100644
> --- a/drivers/gpu/drm/i915/gvt/vgpu.c
> +++ b/drivers/gpu/drm/i915/gvt/vgpu.c
> @@ -123,7 +123,7 @@ int intel_gvt_init_vgpu_types(struct intel_gvt *gvt)
>  
>  		sprintf(gvt->types[i].name, "GVTg_V%u_%s",
>  			GRAPHICS_VER(gvt->gt->i915) == 8 ? 4 : 5, conf->name);
> -		gvt->types->conf = conf;
> +		gvt->types[i].conf = conf;
>  		gvt->types[i].avail_instance = min(low_avail / conf->low_mm,
>  						   high_avail / conf->high_mm);

Fix folded in, re-applied to vfio next branch for v6.1.  Thanks,

Alex


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

* [PATCH 08/14] vfio/mdev: remove mdev_parent_dev
  2022-08-22  6:21 simplify the mdev interface v7 Christoph Hellwig
@ 2022-08-22  6:22 ` Christoph Hellwig
  0 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-08-22  6:22 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code the dereferences in the only user.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 Documentation/driver-api/vfio-mediated-device.rst | 3 ---
 drivers/gpu/drm/i915/gvt/kvmgt.c                  | 2 +-
 drivers/vfio/mdev/mdev_core.c                     | 6 ------
 include/linux/mdev.h                              | 1 -
 4 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index ff7342d2e332d..7b660f3fa2c92 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -200,9 +200,6 @@ Directories and files under the sysfs for Each Physical Device
 
 	sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
 
-  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
-  of the core mdev code)
-
 * device_api
 
   This attribute should show which device API is being created, for example,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 2dc7615bb4f7f..ef9d114349c3a 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1493,7 +1493,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = {
 
 static int intel_vgpu_probe(struct mdev_device *mdev)
 {
-	struct device *pdev = mdev_parent_dev(mdev);
+	struct device *pdev = mdev->type->parent->dev;
 	struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
 	struct intel_vgpu_type *type =
 		container_of(mdev->type, struct intel_vgpu_type, type);
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index bde7ce620dae0..75628759a3bf0 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -23,12 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
 static LIST_HEAD(mdev_list);
 static DEFINE_MUTEX(mdev_list_lock);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev)
-{
-	return mdev->type->parent->dev;
-}
-EXPORT_SYMBOL(mdev_parent_dev);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 6c179d2b89274..bbedffcb38d48 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -95,7 +95,6 @@ void mdev_unregister_parent(struct mdev_parent *parent);
 int mdev_register_driver(struct mdev_driver *drv);
 void mdev_unregister_driver(struct mdev_driver *drv);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev);
 static inline struct device *mdev_dev(struct mdev_device *mdev)
 {
 	return &mdev->dev;
-- 
2.30.2


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

* [PATCH 08/14] vfio/mdev: remove mdev_parent_dev
  2022-07-09  4:54 simplify the mdev interface v6 Christoph Hellwig
@ 2022-07-09  4:54 ` Christoph Hellwig
  0 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-07-09  4:54 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code the dereferences in the only user.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 Documentation/driver-api/vfio-mediated-device.rst | 3 ---
 drivers/gpu/drm/i915/gvt/kvmgt.c                  | 2 +-
 drivers/vfio/mdev/mdev_core.c                     | 6 ------
 include/linux/mdev.h                              | 1 -
 4 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index 82a4007bd7207..a4c3a4a168ec6 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -202,9 +202,6 @@ Directories and files under the sysfs for Each Physical Device
 
 	sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
 
-  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
-  of the core mdev code)
-
 * device_api
 
   This attribute should show which device API is being created, for example,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index ead56e4d30650..3473d4bafd61e 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1549,7 +1549,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = {
 
 static int intel_vgpu_probe(struct mdev_device *mdev)
 {
-	struct device *pdev = mdev_parent_dev(mdev);
+	struct device *pdev = mdev->type->parent->dev;
 	struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
 	struct intel_vgpu_type *type =
 		container_of(mdev->type, struct intel_vgpu_type, type);
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index bde7ce620dae0..75628759a3bf0 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -23,12 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
 static LIST_HEAD(mdev_list);
 static DEFINE_MUTEX(mdev_list_lock);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev)
-{
-	return mdev->type->parent->dev;
-}
-EXPORT_SYMBOL(mdev_parent_dev);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 6c179d2b89274..bbedffcb38d48 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -95,7 +95,6 @@ void mdev_unregister_parent(struct mdev_parent *parent);
 int mdev_register_driver(struct mdev_driver *drv);
 void mdev_unregister_driver(struct mdev_driver *drv);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev);
 static inline struct device *mdev_dev(struct mdev_device *mdev)
 {
 	return &mdev->dev;
-- 
2.30.2


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

* [PATCH 08/14] vfio/mdev: remove mdev_parent_dev
  2022-07-04 12:51 simplify the mdev interface v4 Christoph Hellwig
@ 2022-07-04 12:51 ` Christoph Hellwig
  0 siblings, 0 replies; 31+ messages in thread
From: Christoph Hellwig @ 2022-07-04 12:51 UTC (permalink / raw)
  To: Kirti Wankhede, Tony Krowiak, Halil Pasic, Jason Herne,
	Eric Farman, Matthew Rosato, Zhenyu Wang, Zhi Wang,
	Alex Williamson
  Cc: Jason Gunthorpe, kvm, linux-s390, intel-gvt-dev, Kevin Tian

Just open code the dereferences in the only user.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Kirti Wankhede <kwankhede@nvidia.com>
---
 Documentation/driver-api/vfio-mediated-device.rst | 3 ---
 drivers/gpu/drm/i915/gvt/kvmgt.c                  | 2 +-
 drivers/vfio/mdev/mdev_core.c                     | 6 ------
 include/linux/mdev.h                              | 1 -
 4 files changed, 1 insertion(+), 11 deletions(-)

diff --git a/Documentation/driver-api/vfio-mediated-device.rst b/Documentation/driver-api/vfio-mediated-device.rst
index 82a4007bd7207..a4c3a4a168ec6 100644
--- a/Documentation/driver-api/vfio-mediated-device.rst
+++ b/Documentation/driver-api/vfio-mediated-device.rst
@@ -202,9 +202,6 @@ Directories and files under the sysfs for Each Physical Device
 
 	sprintf(buf, "%s-%s", dev_driver_string(parent->dev), group->name);
 
-  (or using mdev_parent_dev(mdev) to arrive at the parent device outside
-  of the core mdev code)
-
 * device_api
 
   This attribute should show which device API is being created, for example,
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index ead56e4d30650..3473d4bafd61e 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1549,7 +1549,7 @@ static const struct vfio_device_ops intel_vgpu_dev_ops = {
 
 static int intel_vgpu_probe(struct mdev_device *mdev)
 {
-	struct device *pdev = mdev_parent_dev(mdev);
+	struct device *pdev = mdev->type->parent->dev;
 	struct intel_gvt *gvt = kdev_to_i915(pdev)->gvt;
 	struct intel_vgpu_type *type =
 		container_of(mdev->type, struct intel_vgpu_type, type);
diff --git a/drivers/vfio/mdev/mdev_core.c b/drivers/vfio/mdev/mdev_core.c
index bde7ce620dae0..75628759a3bf0 100644
--- a/drivers/vfio/mdev/mdev_core.c
+++ b/drivers/vfio/mdev/mdev_core.c
@@ -23,12 +23,6 @@ static struct class_compat *mdev_bus_compat_class;
 static LIST_HEAD(mdev_list);
 static DEFINE_MUTEX(mdev_list_lock);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev)
-{
-	return mdev->type->parent->dev;
-}
-EXPORT_SYMBOL(mdev_parent_dev);
-
 /*
  * Used in mdev_type_attribute sysfs functions to return the parent struct
  * device
diff --git a/include/linux/mdev.h b/include/linux/mdev.h
index 2ca85b6072b9e..186e5c866871e 100644
--- a/include/linux/mdev.h
+++ b/include/linux/mdev.h
@@ -100,7 +100,6 @@ void mdev_unregister_parent(struct mdev_parent *parent);
 int mdev_register_driver(struct mdev_driver *drv);
 void mdev_unregister_driver(struct mdev_driver *drv);
 
-struct device *mdev_parent_dev(struct mdev_device *mdev);
 static inline struct device *mdev_dev(struct mdev_device *mdev)
 {
 	return &mdev->dev;
-- 
2.30.2


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

end of thread, other threads:[~2022-09-30 21:31 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-23  9:26 simplify the mdev interface v8 Christoph Hellwig
2022-09-23  9:26 ` [PATCH 01/14] drm/i915/gvt: fix a memory leak in intel_gvt_init_vgpu_types Christoph Hellwig
2022-09-23  9:26 ` [PATCH 02/14] drm/i915/gvt: simplify vgpu configuration management Christoph Hellwig
2022-09-23  9:26 ` [PATCH 03/14] vfio/mdev: make mdev.h standalone includable Christoph Hellwig
2022-09-23  9:26 ` [PATCH 04/14] vfio/mdev: embedd struct mdev_parent in the parent data structure Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 05/14] vfio/mdev: simplify mdev_type handling Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 06/14] vfio/mdev: remove mdev_from_dev Christoph Hellwig
2022-09-23  9:26 ` [PATCH 07/14] vfio/mdev: unexport mdev_bus_type Christoph Hellwig
2022-09-23  9:26 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
2022-09-23  9:26 ` [PATCH 09/14] vfio/mdev: remove mtype_get_parent_dev Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 10/14] vfio/mdev: consolidate all the device_api sysfs into the core code Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 11/14] vfio/mdev: consolidate all the name " Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 12/14] vfio/mdev: consolidate all the available_instance " Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-23  9:26 ` [PATCH 13/14] vfio/mdev: consolidate all the description " Christoph Hellwig
2022-09-23  9:26 ` [PATCH 14/14] vfio/mdev: add mdev available instance checking to the core Christoph Hellwig
2022-09-27  1:28   ` Eric Farman
2022-09-27 20:07 ` simplify the mdev interface v8 Alex Williamson
2022-09-27 21:54   ` Alex Williamson
2022-09-28 12:11     ` Christoph Hellwig
2022-09-28 18:56       ` Alex Williamson
2022-09-29  7:11         ` Christoph Hellwig
2022-09-30 21:31       ` Alex Williamson
  -- strict thread matches above, loose matches on Subject: below --
2022-08-22  6:21 simplify the mdev interface v7 Christoph Hellwig
2022-08-22  6:22 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
2022-07-09  4:54 simplify the mdev interface v6 Christoph Hellwig
2022-07-09  4:54 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig
2022-07-04 12:51 simplify the mdev interface v4 Christoph Hellwig
2022-07-04 12:51 ` [PATCH 08/14] vfio/mdev: remove mdev_parent_dev Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).