void i915_gem_object_make_unshrinkable(struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *i915 = obj_to_i915(obj);
+       unsigned long flags;
+
        /*
         * We can only be called while the pages are pinned or when
         * the pages are released. If pinned, we should only be called
         * from a single caller under controlled conditions; and on release
         * only one caller may release us. Neither the two may cross.
         */
-       if (!list_empty(&obj->mm.link)) { /* pinned by caller */
-               struct drm_i915_private *i915 = obj_to_i915(obj);
-               unsigned long flags;
-
-               spin_lock_irqsave(&i915->mm.obj_lock, flags);
-               GEM_BUG_ON(list_empty(&obj->mm.link));
+       if (atomic_add_unless(&obj->mm.shrink_pin, 1, 0))
+               return;
 
+       spin_lock_irqsave(&i915->mm.obj_lock, flags);
+       if (!atomic_fetch_inc(&obj->mm.shrink_pin) &&
+           !list_empty(&obj->mm.link)) {
                list_del_init(&obj->mm.link);
                i915->mm.shrink_count--;
                i915->mm.shrink_memory -= obj->base.size;
-
-               spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
        }
+       spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
 }
 
 static void __i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj,
                                              struct list_head *head)
 {
+       struct drm_i915_private *i915 = obj_to_i915(obj);
+       unsigned long flags;
+
        GEM_BUG_ON(!i915_gem_object_has_pages(obj));
-       GEM_BUG_ON(!list_empty(&obj->mm.link));
+       if (!i915_gem_object_is_shrinkable(obj))
+               return;
 
-       if (i915_gem_object_is_shrinkable(obj)) {
-               struct drm_i915_private *i915 = obj_to_i915(obj);
-               unsigned long flags;
+       if (atomic_add_unless(&obj->mm.shrink_pin, -1, 1))
+               return;
 
-               spin_lock_irqsave(&i915->mm.obj_lock, flags);
-               GEM_BUG_ON(!kref_read(&obj->base.refcount));
+       spin_lock_irqsave(&i915->mm.obj_lock, flags);
+       GEM_BUG_ON(!kref_read(&obj->base.refcount));
+       if (atomic_dec_and_test(&obj->mm.shrink_pin)) {
+               GEM_BUG_ON(!list_empty(&obj->mm.link));
 
                list_add_tail(&obj->mm.link, head);
                i915->mm.shrink_count++;
                i915->mm.shrink_memory += obj->base.size;
 
-               spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
        }
+       spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
 }
 
 void i915_gem_object_make_shrinkable(struct drm_i915_gem_object *obj)