return ret;
 }
 
-#define  __EXEC_OBJECT_HAS_FENCE (1<<31)
+#define  __EXEC_OBJECT_HAS_PIN (1<<31)
+#define  __EXEC_OBJECT_HAS_FENCE (1<<30)
 
 static int
 need_reloc_mappable(struct drm_i915_gem_object *obj)
 }
 
 static int
-pin_and_fence_object(struct drm_i915_gem_object *obj,
-                    struct intel_ring_buffer *ring)
+i915_gem_execbuffer_reserve_object(struct drm_i915_gem_object *obj,
+                                  struct intel_ring_buffer *ring)
 {
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
        struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
        bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
        bool need_fence, need_mappable;
        if (ret)
                return ret;
 
+       entry->flags |= __EXEC_OBJECT_HAS_PIN;
+
        if (has_fenced_gpu_access) {
                if (entry->flags & EXEC_OBJECT_NEEDS_FENCE) {
                        ret = i915_gem_object_get_fence(obj);
                        if (ret)
-                               goto err_unpin;
+                               return ret;
 
                        if (i915_gem_object_pin_fence(obj))
                                entry->flags |= __EXEC_OBJECT_HAS_FENCE;
                }
        }
 
+       /* Ensure ppgtt mapping exists if needed */
+       if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
+               i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
+                                      obj, obj->cache_level);
+
+               obj->has_aliasing_ppgtt_mapping = 1;
+       }
+
        entry->offset = obj->gtt_offset;
        return 0;
+}
 
-err_unpin:
-       i915_gem_object_unpin(obj);
-       return ret;
+static void
+i915_gem_execbuffer_unreserve_object(struct drm_i915_gem_object *obj)
+{
+       struct drm_i915_gem_exec_object2 *entry;
+
+       if (!obj->gtt_space)
+               return;
+
+       entry = obj->exec_entry;
+
+       if (entry->flags & __EXEC_OBJECT_HAS_FENCE)
+               i915_gem_object_unpin_fence(obj);
+
+       if (entry->flags & __EXEC_OBJECT_HAS_PIN)
+               i915_gem_object_unpin(obj);
+
+       entry->flags &= ~(__EXEC_OBJECT_HAS_FENCE | __EXEC_OBJECT_HAS_PIN);
 }
 
 static int
                            struct drm_file *file,
                            struct list_head *objects)
 {
-       drm_i915_private_t *dev_priv = ring->dev->dev_private;
        struct drm_i915_gem_object *obj;
-       int ret, retry;
-       bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
        struct list_head ordered_objects;
+       bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
+       int retry;
 
        INIT_LIST_HEAD(&ordered_objects);
        while (!list_empty(objects)) {
         * 2.  Bind new objects.
         * 3.  Decrement pin count.
         *
-        * This avoid unnecessary unbinding of later objects in order to makr
+        * This avoid unnecessary unbinding of later objects in order to make
         * room for the earlier objects *unless* we need to defragment.
         */
        retry = 0;
        do {
-               ret = 0;
+               int ret = 0;
 
                /* Unbind any ill-fitting objects or pin. */
                list_for_each_entry(obj, objects, exec_list) {
                            (need_mappable && !obj->map_and_fenceable))
                                ret = i915_gem_object_unbind(obj);
                        else
-                               ret = pin_and_fence_object(obj, ring);
+                               ret = i915_gem_execbuffer_reserve_object(obj, ring);
                        if (ret)
                                goto err;
                }
                        if (obj->gtt_space)
                                continue;
 
-                       ret = pin_and_fence_object(obj, ring);
-                       if (ret) {
-                               int ret_ignore;
-
-                               /* This can potentially raise a harmless
-                                * -EINVAL if we failed to bind in the above
-                                * call. It cannot raise -EINTR since we know
-                                * that the bo is freshly bound and so will
-                                * not need to be flushed or waited upon.
-                                */
-                               ret_ignore = i915_gem_object_unbind(obj);
-                               (void)ret_ignore;
-                               WARN_ON(obj->gtt_space);
-                               break;
-                       }
+                       ret = i915_gem_execbuffer_reserve_object(obj, ring);
+                       if (ret)
+                               goto err;
                }
 
-               /* Decrement pin count for bound objects */
-               list_for_each_entry(obj, objects, exec_list) {
-                       struct drm_i915_gem_exec_object2 *entry;
-
-                       if (!obj->gtt_space)
-                               continue;
-
-                       entry = obj->exec_entry;
-                       if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-                               i915_gem_object_unpin_fence(obj);
-                               entry->flags &= ~__EXEC_OBJECT_HAS_FENCE;
-                       }
-
-                       i915_gem_object_unpin(obj);
-
-                       /* ... and ensure ppgtt mapping exist if needed. */
-                       if (dev_priv->mm.aliasing_ppgtt && !obj->has_aliasing_ppgtt_mapping) {
-                               i915_ppgtt_bind_object(dev_priv->mm.aliasing_ppgtt,
-                                                      obj, obj->cache_level);
-
-                               obj->has_aliasing_ppgtt_mapping = 1;
-                       }
-               }
+err:           /* Decrement pin count for bound objects */
+               list_for_each_entry(obj, objects, exec_list)
+                       i915_gem_execbuffer_unreserve_object(obj);
 
                if (ret != -ENOSPC || retry++)
                        return ret;
                if (ret)
                        return ret;
        } while (1);
-
-err:
-       list_for_each_entry_continue_reverse(obj, objects, exec_list) {
-               struct drm_i915_gem_exec_object2 *entry;
-
-               if (!obj->gtt_space)
-                       continue;
-
-               entry = obj->exec_entry;
-               if (entry->flags & __EXEC_OBJECT_HAS_FENCE) {
-                       i915_gem_object_unpin_fence(obj);
-                       entry->flags &= ~__EXEC_OBJECT_HAS_FENCE;
-               }
-
-               i915_gem_object_unpin(obj);
-       }
-
-       return ret;
 }
 
 static int