VIGS: Fixed GEM reserve deadlock
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Mon, 6 May 2013 16:39:28 +0000 (20:39 +0400)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 9 Apr 2014 05:42:21 +0000 (14:42 +0900)
Change-Id: Ic4609ff43ea4689f13a56da41696f6a500d21a64

drivers/gpu/drm/vigs/vigs_device.c

index 0393390..f07f4bd 100644 (file)
@@ -89,6 +89,21 @@ static struct vigs_surface
     return sfc;
 }
 
+static bool vigs_gem_is_reserved(struct list_head* gem_list,
+                                 struct vigs_gem_object *gem)
+{
+    struct vigs_gem_object *tmp;
+
+    list_for_each_entry(tmp, gem_list, list)
+    {
+        if (tmp == gem) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
 /*
  * 'gem_list' will hold a list of GEMs that should be
  * unreserved and unreferenced after execution.
@@ -137,7 +152,12 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 ret = -EINVAL;
                 break;
             }
-            vigs_gem_reserve(&sfc->gem);
+            if (vigs_gem_is_reserved(gem_list, &sfc->gem)) {
+                drm_gem_object_unreference_unlocked(&sfc->gem.base);
+            } else {
+                vigs_gem_reserve(&sfc->gem);
+                list_add_tail(&sfc->gem.list, gem_list);
+            }
             if (vigs_gem_in_vram(&sfc->gem)) {
                 update_vram_request->offset = vigs_gem_offset(&sfc->gem);
             } else {
@@ -145,7 +165,6 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                                  update_vram_request->sfc_id);
                 update_vram_request->sfc_id = 0;
             }
-            list_add_tail(&sfc->gem.list, gem_list);
             break;
         case vigsp_cmd_update_gpu:
             update_gpu_request =
@@ -156,7 +175,12 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                 ret = -EINVAL;
                 break;
             }
-            vigs_gem_reserve(&sfc->gem);
+            if (vigs_gem_is_reserved(gem_list, &sfc->gem)) {
+                drm_gem_object_unreference_unlocked(&sfc->gem.base);
+            } else {
+                vigs_gem_reserve(&sfc->gem);
+                list_add_tail(&sfc->gem.list, gem_list);
+            }
             if (vigs_gem_in_vram(&sfc->gem)) {
                 update_gpu_request->offset = vigs_gem_offset(&sfc->gem);
                 sfc->is_dirty = false;
@@ -165,7 +189,6 @@ static int vigs_device_patch_commands(struct vigs_device *vigs_dev,
                                  update_gpu_request->sfc_id);
                 update_gpu_request->sfc_id = 0;
             }
-            list_add_tail(&sfc->gem.list, gem_list);
             break;
         default:
             break;