drm/i915/gvt: create an idle vGPU
authorPing Gao <ping.a.gao@intel.com>
Wed, 29 Mar 2017 16:36:39 +0000 (00:36 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Thu, 30 Mar 2017 05:34:07 +0000 (13:34 +0800)
vGPU resource is allocated by scheduler. To account for non-allocated
free cycles, we create an idle vGPU as the placeholder similar to idle task
concept, which is useful to handle some corner cases in scheduling policy.

Signed-off-by: Ping Gao <ping.a.gao@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/vgpu.c

index 894735c77f63f0dad4c9c103e4edbf2562639934..0f3a98865a58265815831814590deaeebb2ec032 100644 (file)
@@ -202,6 +202,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
 
        idr_destroy(&gvt->vgpu_idr);
 
+       intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
+
        kfree(dev_priv->gvt);
        dev_priv->gvt = NULL;
 }
@@ -220,6 +222,7 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
 int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 {
        struct intel_gvt *gvt;
+       struct intel_vgpu *vgpu;
        int ret;
 
        /*
@@ -292,6 +295,14 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
                goto out_clean_types;
        }
 
+       vgpu = intel_gvt_create_idle_vgpu(gvt);
+       if (IS_ERR(vgpu)) {
+               ret = PTR_ERR(vgpu);
+               gvt_err("failed to create idle vgpu\n");
+               goto out_clean_types;
+       }
+       gvt->idle_vgpu = vgpu;
+
        gvt_dbg_core("gvt device initialization is done\n");
        dev_priv->gvt = gvt;
        return 0;
index 0631f64e06dbc3ec38e968b25ea27c213e8fe33e..806da96b6a92ab83fec739cfb6e8cb5afb2110db 100644 (file)
@@ -243,6 +243,7 @@ struct intel_gvt {
        DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
        struct intel_vgpu_type *types;
        unsigned int num_types;
+       struct intel_vgpu *idle_vgpu;
 
        struct task_struct *service_thread;
        wait_queue_head_t service_thread_wq;
@@ -386,6 +387,8 @@ static inline void intel_vgpu_write_pci_bar(struct intel_vgpu *vgpu,
 int intel_gvt_init_vgpu_types(struct intel_gvt *gvt);
 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);
 void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
index 36c107e2058a9566e2de2687c3c3ad0bd6ec4c23..6ba02525e90598f74b67bc7b1144511efef55820 100644 (file)
@@ -233,6 +233,59 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
        mutex_unlock(&gvt->lock);
 }
 
+#define IDLE_VGPU_IDR 0
+
+/**
+ * intel_gvt_create_idle_vgpu - create an idle virtual GPU
+ * @gvt: GVT device
+ *
+ * This function is called when user wants to create an idle virtual GPU.
+ *
+ * Returns:
+ * pointer to intel_vgpu, error pointer if failed.
+ */
+struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt)
+{
+       struct intel_vgpu *vgpu;
+       enum intel_engine_id i;
+       int ret;
+
+       vgpu = vzalloc(sizeof(*vgpu));
+       if (!vgpu)
+               return ERR_PTR(-ENOMEM);
+
+       vgpu->id = IDLE_VGPU_IDR;
+       vgpu->gvt = gvt;
+
+       for (i = 0; i < I915_NUM_ENGINES; i++)
+               INIT_LIST_HEAD(&vgpu->workload_q_head[i]);
+
+       ret = intel_vgpu_init_sched_policy(vgpu);
+       if (ret)
+               goto out_free_vgpu;
+
+       vgpu->active = false;
+
+       return vgpu;
+
+out_free_vgpu:
+       vfree(vgpu);
+       return ERR_PTR(ret);
+}
+
+/**
+ * intel_gvt_destroy_vgpu - destroy an idle virtual GPU
+ * @vgpu: virtual GPU
+ *
+ * This function is called when user wants to destroy an idle virtual GPU.
+ *
+ */
+void intel_gvt_destroy_idle_vgpu(struct intel_vgpu *vgpu)
+{
+       intel_vgpu_clean_sched_policy(vgpu);
+       vfree(vgpu);
+}
+
 static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
                struct intel_vgpu_creation_params *param)
 {
@@ -249,7 +302,8 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
 
        mutex_lock(&gvt->lock);
 
-       ret = idr_alloc(&gvt->vgpu_idr, vgpu, 1, GVT_MAX_VGPU, GFP_KERNEL);
+       ret = idr_alloc(&gvt->vgpu_idr, vgpu, IDLE_VGPU_IDR + 1, GVT_MAX_VGPU,
+               GFP_KERNEL);
        if (ret < 0)
                goto out_free_vgpu;