Merge tag 'gvt-next-2022-11-17' of https://github.com/intel/gvt-linux into drm-intel...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / gvt / vgpu.c
index 8e71cda1999560359955105adfd8b467432a61ad..3c529c2705ddcaf4c796d776c42e135ecebe34f4 100644 (file)
@@ -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,102 +103,58 @@ 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;
+       gvt->mdev_types = kcalloc(num_types, sizeof(*gvt->mdev_types),
+                            GFP_KERNEL);
+       if (!gvt->mdev_types)
+               goto out_free_types;
 
-               if (vgpu_types[i].weight < 1 ||
-                                       vgpu_types[i].weight > VGPU_MAX_WEIGHT)
-                       return -EINVAL;
+       for (i = 0; i < num_types; ++i) {
+               const struct intel_vgpu_config *conf = &intel_vgpu_configs[i];
 
-               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 (low_avail / conf->low_mm == 0)
+                       break;
+               if (conf->weight < 1 || conf->weight > VGPU_MAX_WEIGHT)
+                       goto out_free_mdev_types;
 
-               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[i].conf = conf;
 
                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));
+                            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));
+
+               gvt->mdev_types[i] = &gvt->types[i].type;
+               gvt->mdev_types[i]->sysfs_name = gvt->types[i].name;
        }
 
        gvt->num_types = i;
        return 0;
-}
 
-void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
-{
+out_free_mdev_types:
+       kfree(gvt->mdev_types);
+out_free_types:
        kfree(gvt->types);
+       return -EINVAL;
 }
 
-static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
+void intel_gvt_clean_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].low_gm_size;
-               high_gm_min = high_gm_avail / gvt->types[i].high_gm_size;
-               fence_min = fence_avail / gvt->types[i].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);
-       }
+       kfree(gvt->mdev_types);
+       kfree(gvt->types);
 }
 
 /**
@@ -298,12 +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);
-
-       vfree(vgpu);
 }
 
 #define IDLE_VGPU_IDR 0
@@ -363,42 +310,38 @@ 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)
+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;
-       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);
-
-       vgpu = vzalloc(sizeof(*vgpu));
-       if (!vgpu)
-               return ERR_PTR(-ENOMEM);
+       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)
-               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;
 
@@ -412,7 +355,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;
 
@@ -437,7 +380,9 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
        if (ret)
                goto out_clean_sched_policy;
 
-       return vgpu;
+       intel_gvt_update_reg_whitelist(vgpu);
+       mutex_unlock(&gvt->lock);
+       return 0;
 
 out_clean_sched_policy:
        intel_vgpu_clean_sched_policy(vgpu);
@@ -455,48 +400,9 @@ out_clean_vgpu_mmio:
        intel_vgpu_clean_mmio(vgpu);
 out_clean_idr:
        idr_remove(&gvt->vgpu_idr, vgpu->id);
-out_free_vgpu:
-       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);
-       }
+out_unlock:
        mutex_unlock(&gvt->lock);
-
-       return vgpu;
+       return ret;
 }
 
 /**