Re: [PATCH 02/14] drm/i915/gvt: simplify vgpu configuration management

Zhenyu Wang
2022-07-05T08:22:57Z

[-- Attachment #1: Type: text/plain, Size: 17492 bytes --]

On 2022.07.04 14:51:32 +0200, Christoph Hellwig wrote:
> 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>
> ---

Looks fine to me. We still carry some legacy codes like vgpu create param
originally used for other hypervisor. Thanks for cleaning this up!

Reviewed-by: Zhenyu Wang <zhenyuw@linux.intel.com>

> drivers/gpu/drm/i915/gvt/aperture_gm.c | 20 +--
> drivers/gpu/drm/i915/gvt/gvt.h | 36 +++---
> drivers/gpu/drm/i915/gvt/kvmgt.c | 10 +-
> drivers/gpu/drm/i915/gvt/vgpu.c | 172 +++++++++----------------
> 4 files changed, 91 insertions(+), 147 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c
> index 557f3314291a8..7dd8163f8a569 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 aee1a45da74bc..392c2ad49d376 100644
> --- a/drivers/gpu/drm/i915/gvt/gvt.h
> +++ b/drivers/gpu/drm/i915/gvt/gvt.h
> @@ -295,15 +295,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 {
> @@ -437,19 +448,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,
> @@ -496,7 +496,7 @@ 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);
> struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
> - struct intel_vgpu_type *type);
> + 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 e2f6c56ab3420..7b060c0e66ae7 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,
> @@ -1624,7 +1624,7 @@ static int intel_vgpu_probe(struct mdev_device *mdev)
> if (!type)
> return -EINVAL;
>
> - vgpu = intel_gvt_create_vgpu(gvt, type);
> + vgpu = intel_gvt_create_vgpu(gvt, type->conf);
> if (IS_ERR(vgpu)) {
> gvt_err("failed to create intel vgpu: %ld\n", PTR_ERR(vgpu));
> return PTR_ERR(vgpu);
> diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
> index 5c828556cefd7..8e136dcc70112 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);
> }
> }
>
> @@ -367,42 +335,53 @@ void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu)
> vfree(vgpu);
> }
>
> -static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
> - struct intel_vgpu_creation_params *param)
> +/**
> + * intel_gvt_create_vgpu - create a virtual GPU
> + * @gvt: GVT device
> + * @conf: 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.
> + */
> +struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
> + const struct intel_vgpu_config *conf)
> {
> struct drm_i915_private *dev_priv = gvt->gt->i915;
> struct intel_vgpu *vgpu;
> 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);
>
> vgpu = vzalloc(sizeof(*vgpu));
> if (!vgpu)
> return ERR_PTR(-ENOMEM);
>
> + mutex_lock(&gvt->lock);
> ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU,
> GFP_KERNEL);
> if (ret < 0)
> - goto out_free_vgpu;
> + goto out_unlock;;
>
> vgpu->id = ret;
> vgpu->gvt = gvt;
> - 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;
>
> @@ -416,7 +395,7 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
> 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;
>
> @@ -441,6 +420,9 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
> if (ret)
> goto out_clean_sched_policy;
>
> + intel_gvt_update_vgpu_types(gvt);
> + intel_gvt_update_reg_whitelist(vgpu);
> + mutex_unlock(&gvt->lock);
> return vgpu;
>
> out_clean_sched_policy:
> @@ -459,50 +441,12 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
> intel_vgpu_clean_mmio(vgpu);
> out_clean_idr:
> idr_remove(&gvt->vgpu_idr, vgpu->id);
> -out_free_vgpu:
> +out_unlock:
> + mutex_unlock(&gvt->lock);
> vfree(vgpu);
> return ERR_PTR(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.
> - */
> -struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
> - struct intel_vgpu_type *type)
> -{
> - struct intel_vgpu_creation_params param;
> - struct intel_vgpu *vgpu;
> -
> - 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);
> - vgpu = __intel_gvt_create_vgpu(gvt, &param);
> - if (!IS_ERR(vgpu)) {
> - /* calculate left instance change for types */
> - intel_gvt_update_vgpu_types(gvt);
> - intel_gvt_update_reg_whitelist(vgpu);
> - }
> - mutex_unlock(&gvt->lock);
> -
> - return vgpu;
> -}
> -
> /**
> * intel_gvt_reset_vgpu_locked - reset a virtual GPU by DMLR or GT reset
> * @vgpu: virtual GPU
> --
> 2.30.2
>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]