obj_priv->active = 1;
        }
        /* Move from whatever list we were on to the tail of execution. */
+       spin_lock(&dev_priv->mm.active_list_lock);
        list_move_tail(&obj_priv->list,
                       &dev_priv->mm.active_list);
+       spin_unlock(&dev_priv->mm.active_list_lock);
        obj_priv->last_rendering_seqno = seqno;
 }
 
        /* Move any buffers on the active list that are no longer referenced
         * by the ringbuffer to the flushing/inactive lists as appropriate.
         */
+       spin_lock(&dev_priv->mm.active_list_lock);
        while (!list_empty(&dev_priv->mm.active_list)) {
                struct drm_gem_object *obj;
                struct drm_i915_gem_object *obj_priv;
                 * this seqno.
                 */
                if (obj_priv->last_rendering_seqno != request->seqno)
-                       return;
+                       goto out;
 
 #if WATCH_LRU
                DRM_INFO("%s: retire %d moves to inactive list %p\n",
                else
                        i915_gem_object_move_to_inactive(obj);
        }
+out:
+       spin_unlock(&dev_priv->mm.active_list_lock);
 }
 
 /**
                }
        }
        if (obj_priv->gtt_space == NULL) {
+               bool lists_empty;
+
                /* If the gtt is empty and we're still having trouble
                 * fitting our object in, we're out of memory.
                 */
 #if WATCH_LRU
                DRM_INFO("%s: GTT full, evicting something\n", __func__);
 #endif
-               if (list_empty(&dev_priv->mm.inactive_list) &&
-                   list_empty(&dev_priv->mm.flushing_list) &&
-                   list_empty(&dev_priv->mm.active_list)) {
+               spin_lock(&dev_priv->mm.active_list_lock);
+               lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
+                              list_empty(&dev_priv->mm.flushing_list) &&
+                              list_empty(&dev_priv->mm.active_list));
+               spin_unlock(&dev_priv->mm.active_list_lock);
+               if (lists_empty) {
                        DRM_ERROR("GTT full, but LRU list empty\n");
                        return -ENOMEM;
                }
 
        i915_gem_retire_requests(dev);
 
+       spin_lock(&dev_priv->mm.active_list_lock);
        if (!dev_priv->mm.wedged) {
                /* Active and flushing should now be empty as we've
                 * waited for a sequence higher than any pending execbuffer
                obj_priv->obj->write_domain &= ~I915_GEM_GPU_DOMAINS;
                i915_gem_object_move_to_inactive(obj_priv->obj);
        }
+       spin_unlock(&dev_priv->mm.active_list_lock);
 
        while (!list_empty(&dev_priv->mm.flushing_list)) {
                struct drm_i915_gem_object *obj_priv;
        if (ret != 0)
                return ret;
 
+       spin_lock(&dev_priv->mm.active_list_lock);
        BUG_ON(!list_empty(&dev_priv->mm.active_list));
+       spin_unlock(&dev_priv->mm.active_list_lock);
+
        BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
        BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
        BUG_ON(!list_empty(&dev_priv->mm.request_list));
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
 
+       spin_lock_init(&dev_priv->mm.active_list_lock);
        INIT_LIST_HEAD(&dev_priv->mm.active_list);
        INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
        INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
 
        struct drm_i915_gem_object      *obj_priv;
 
        DRM_INFO("active list %s {\n", where);
+       spin_lock(&dev_priv->mm.active_list_lock);
        list_for_each_entry(obj_priv, &dev_priv->mm.active_list,
                            list)
        {
                DRM_INFO("    %p: %08x\n", obj_priv,
                         obj_priv->last_rendering_seqno);
        }
+       spin_unlock(&dev_priv->mm.active_list_lock);
        DRM_INFO("}\n");
        DRM_INFO("flushing list %s {\n", where);
        list_for_each_entry(obj_priv, &dev_priv->mm.flushing_list,