VIGS: Don't rely on 'no_wait_reserve' parameter when pinnin GEMs 47/13647/1
authorStanislav Vorobiov <s.vorobiov@samsung.com>
Wed, 11 Dec 2013 09:26:13 +0000 (13:26 +0400)
committerStanislav Vorobiov <s.vorobiov@samsung.com>
Wed, 11 Dec 2013 09:26:13 +0000 (13:26 +0400)
'no_wait_reserve' parameter isn't accounted for in
ttm_bo_validate, so don't rely on GEM reserve wait,
just retry things instead

Change-Id: Iab57645c8ab96f30c01b943342cdff9bacac8feb

drivers/gpu/drm/vigs/vigs_crtc.c
drivers/gpu/drm/vigs/vigs_gem.c

index 9989ae62d4deb68164c2b2c8b13904016b048abe..72d0ad442c60fa28ea2c6568630aeb84a1abb41b 100644 (file)
@@ -26,10 +26,32 @@ static int vigs_crtc_update(struct drm_crtc *crtc,
 
     vigs_fb = fb_to_vigs_fb(crtc->fb);
 
+retry:
     ret = vigs_framebuffer_pin(vigs_fb);
 
     if (ret != 0) {
-        return ret;
+        /*
+         * In condition of very intense GEM operations
+         * and with small amount of VRAM memory it's possible that
+         * GEM pin will be failing for some time, thus, framebuffer pin
+         * will be failing. This is unavoidable with current TTM design,
+         * even though ttm_bo_validate has 'no_wait_reserve' parameter it's
+         * always assumed that it's true, thus, if someone is intensively
+         * reserves/unreserves GEMs then ttm_bo_validate can fail even if there
+         * is free space in a placement. Even worse, ttm_bo_validate fails with
+         * ENOMEM so it's not possible to tell if it's a temporary failure due
+         * to reserve/unreserve pressure or constant one due to memory shortage.
+         * We assume here that it's temporary and retry framebuffer pin. This
+         * is relatively safe since we only pin GEMs on pageflip and user
+         * should have started the VM with VRAM size equal to at least 3 frames,
+         * thus, 2 frame will always be free and we can always pin 1 frame.
+         *
+         * Also, 'no_wait_reserve' parameter is completely removed in future
+         * kernels with this commit:
+         * https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=97a875cbdf89a4638eea57c2b456c7cc4e3e8b21
+         */
+        cpu_relax();
+        goto retry;
     }
 
     vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
index 9cef303688f2ed997f89fadb784eaacddb45c13c..57d0e32ad70d07781aade91a93bde4328ec6e77a 100644 (file)
@@ -128,7 +128,7 @@ int vigs_gem_pin(struct vigs_gem_object *vigs_gem)
     placement.num_placement = 1;
     placement.num_busy_placement = 1;
 
-    ret = ttm_bo_validate(&vigs_gem->bo, &placement, false, false, false);
+    ret = ttm_bo_validate(&vigs_gem->bo, &placement, false, true, false);
 
     if (ret != 0) {
         DRM_ERROR("GEM pin failed (type = %u, off = 0x%llX, sz = %lu)\n",
@@ -178,7 +178,7 @@ void vigs_gem_unpin(struct vigs_gem_object *vigs_gem)
     placement.num_placement = 2;
     placement.num_busy_placement = 2;
 
-    ret = ttm_bo_validate(&vigs_gem->bo, &placement, false, false, false);
+    ret = ttm_bo_validate(&vigs_gem->bo, &placement, false, true, false);
 
     if (ret != 0) {
         DRM_ERROR("GEM unpin failed (type = %u, off = 0x%llX, sz = %lu)\n",