From ca31e53561796359868bde0d9dab75463a87fc31 Mon Sep 17 00:00:00 2001 From: Stanislav Vorobiov Date: Wed, 11 Dec 2013 13:26:13 +0400 Subject: [PATCH] VIGS: Don't rely on 'no_wait_reserve' parameter when pinnin GEMs '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 | 24 +++++++++++++++++++++++- drivers/gpu/drm/vigs/vigs_gem.c | 4 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vigs/vigs_crtc.c b/drivers/gpu/drm/vigs/vigs_crtc.c index 9989ae62d4de..72d0ad442c60 100644 --- a/drivers/gpu/drm/vigs/vigs_crtc.c +++ b/drivers/gpu/drm/vigs/vigs_crtc.c @@ -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); diff --git a/drivers/gpu/drm/vigs/vigs_gem.c b/drivers/gpu/drm/vigs/vigs_gem.c index 9cef303688f2..57d0e32ad70d 100644 --- a/drivers/gpu/drm/vigs/vigs_gem.c +++ b/drivers/gpu/drm/vigs/vigs_gem.c @@ -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", -- 2.34.1