drm/i915/gvt: Handle orphan dmabuf_objs
authorTina Zhang <tina.zhang@intel.com>
Thu, 23 Nov 2017 08:26:37 +0000 (16:26 +0800)
committerZhenyu Wang <zhenyuw@linux.intel.com>
Mon, 4 Dec 2017 03:24:34 +0000 (11:24 +0800)
dmabuf_obj's destruction relys on GEM release operation, which is managed
in i915 driver. And there is a time window between vgpu's destruction and
its dmabuf_objs' destruction. This patch is to free the orphan dmabuf_objs
correctly after the vgpu passes away.

Signed-off-by: Tina Zhang <tina.zhang@intel.com>
Cc: Zhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
drivers/gpu/drm/i915/gvt/dmabuf.c

index 190710c..50215b2 100644 (file)
@@ -88,19 +88,26 @@ static void dmabuf_gem_object_free(struct kref *kref)
                container_of(kref, struct intel_vgpu_dmabuf_obj, kref);
        struct intel_vgpu *vgpu = obj->vgpu;
        struct list_head *pos;
-
        struct intel_vgpu_dmabuf_obj *dmabuf_obj;
 
-       list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
-               dmabuf_obj = container_of(pos, struct intel_vgpu_dmabuf_obj,
-                                               list);
-               if (dmabuf_obj == obj) {
-                       idr_remove(&vgpu->object_idr, dmabuf_obj->dmabuf_id);
-                       kfree(dmabuf_obj->info);
-                       kfree(dmabuf_obj);
-                       list_del(pos);
-                       break;
+       if (vgpu) {
+               list_for_each(pos, &vgpu->dmabuf_obj_list_head) {
+                       dmabuf_obj = container_of(pos,
+                                       struct intel_vgpu_dmabuf_obj, list);
+                       if (dmabuf_obj == obj) {
+                               intel_gvt_hypervisor_put_vfio_device(vgpu);
+                               idr_remove(&vgpu->object_idr,
+                                          dmabuf_obj->dmabuf_id);
+                               kfree(dmabuf_obj->info);
+                               kfree(dmabuf_obj);
+                               list_del(pos);
+                               break;
+                       }
                }
+       } else {
+               /* Free the orphan dmabuf_objs here */
+               kfree(obj->info);
+               kfree(obj);
        }
 }
 
@@ -122,11 +129,16 @@ static void vgpu_gem_release(struct drm_i915_gem_object *gem_obj)
        struct intel_vgpu_dmabuf_obj *obj = fb_info->obj;
        struct intel_vgpu *vgpu = obj->vgpu;
 
-       mutex_lock(&vgpu->dmabuf_lock);
-       gem_obj->base.dma_buf = NULL;
-       dmabuf_obj_put(obj);
-       intel_gvt_hypervisor_put_vfio_device(vgpu);
-       mutex_unlock(&vgpu->dmabuf_lock);
+       if (vgpu) {
+               mutex_lock(&vgpu->dmabuf_lock);
+               gem_obj->base.dma_buf = NULL;
+               dmabuf_obj_put(obj);
+               mutex_unlock(&vgpu->dmabuf_lock);
+       } else {
+               /* vgpu is NULL, as it has been removed already */
+               gem_obj->base.dma_buf = NULL;
+               dmabuf_obj_put(obj);
+       }
 }
 
 static const struct drm_i915_gem_object_ops intel_vgpu_gem_ops = {
@@ -471,12 +483,6 @@ int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id)
        }
        dmabuf_fd = ret;
 
-       if (intel_gvt_hypervisor_get_vfio_device(vgpu)) {
-               gvt_vgpu_err("get vfio device failed\n");
-               put_unused_fd(ret);
-               goto out_free_dmabuf;
-       }
-
        dmabuf_obj_get(dmabuf_obj);
 
        if (dmabuf_obj->initref) {
@@ -518,6 +524,14 @@ void intel_vgpu_dmabuf_cleanup(struct intel_vgpu *vgpu)
                        dmabuf_obj->initref = false;
                        dmabuf_obj_put(dmabuf_obj);
                }
+
+               idr_remove(&vgpu->object_idr, dmabuf_obj->dmabuf_id);
+
+               if (dmabuf_obj->vgpu)
+                       intel_gvt_hypervisor_put_vfio_device(vgpu);
+
+               dmabuf_obj->vgpu = NULL;
+
        }
        mutex_unlock(&vgpu->dmabuf_lock);
 }