From 6cb0c6ad9e07f2c7971c4e8e0d9b7ceba151a925 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Fri, 4 Aug 2017 11:41:35 +0100 Subject: [PATCH] drm/i915/shrinker: Wrap need_resched() inside preempt-disable In order for us to successfully detect the end of a timeslice, preemption must be disabled. Otherwise, inside the loop we may be preempted many times without our noticing, and each time our timeslice will be reset, invalidating need_resched() Reported-by: Joonas Lahtinen Reported-by: Tomi Sarvela Fixes: 290271de34f6 ("drm/i915: Spin for struct_mutex inside shrinker") Signed-off-by: Chris Wilson Cc: Mika Kuoppala Cc: Joonas Lahtinen Cc: # v4.13-rc1+ Link: https://patchwork.freedesktop.org/patch/msgid/20170804104135.26805-1-chris@chris-wilson.co.uk Tested-by: Joonas Lahtinen Reviewed-by: Joonas Lahtinen --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 1032f98add11..77fb39808131 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -43,16 +43,21 @@ static bool shrinker_lock(struct drm_i915_private *dev_priv, bool *unlock) return true; case MUTEX_TRYLOCK_FAILED: + *unlock = false; + preempt_disable(); do { cpu_relax(); if (mutex_trylock(&dev_priv->drm.struct_mutex)) { - case MUTEX_TRYLOCK_SUCCESS: *unlock = true; - return true; + break; } } while (!need_resched()); + preempt_enable(); + return *unlock; - return false; + case MUTEX_TRYLOCK_SUCCESS: + *unlock = true; + return true; } BUG(); -- 2.20.1