Merge tag 'v4.0-rc6' into drm-intel-next
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 30 Mar 2015 14:37:08 +0000 (16:37 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Mon, 30 Mar 2015 14:37:08 +0000 (16:37 +0200)
Backmerge Linux 4.0-rc6 because conflicts are (again) getting out of
hand. To make sure we don't lose any bugfixes from the 4.0-rc5-rc6
flurry of patches we've applied them all to -next too.

Conflicts:
drivers/gpu/drm/i915/intel_display.c

Always take the version from -next, we've already handled all
conflicts with explicit cherrypicking.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
1  2 
drivers/gpu/drm/i915/i915_gem.c

index 4ca3dab77fa4658077cce07e543554ee7315e4a1,27ea6bdebce761dbd8dca5340a4cd6e2bd32eaa3..d07c0b1fb498264ba0f6224db81434e98c7c6ff5
@@@ -1,5 -1,5 +1,5 @@@
  /*
 - * Copyright © 2008 Intel Corporation
 + * Copyright © 2008-2015 Intel Corporation
   *
   * Permission is hereby granted, free of charge, to any person obtaining a
   * copy of this software and associated documentation files (the "Software"),
@@@ -29,9 -29,9 +29,9 @@@
  #include <drm/drm_vma_manager.h>
  #include <drm/i915_drm.h>
  #include "i915_drv.h"
 +#include "i915_vgpu.h"
  #include "i915_trace.h"
  #include "intel_drv.h"
 -#include <linux/oom.h>
  #include <linux/shmem_fs.h>
  #include <linux/slab.h>
  #include <linux/swap.h>
@@@ -52,6 -52,15 +52,6 @@@ static void i915_gem_object_update_fenc
                                         struct drm_i915_fence_reg *fence,
                                         bool enable);
  
 -static unsigned long i915_gem_shrinker_count(struct shrinker *shrinker,
 -                                           struct shrink_control *sc);
 -static unsigned long i915_gem_shrinker_scan(struct shrinker *shrinker,
 -                                          struct shrink_control *sc);
 -static int i915_gem_shrinker_oom(struct notifier_block *nb,
 -                               unsigned long event,
 -                               void *ptr);
 -static unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
 -
  static bool cpu_cache_is_coherent(struct drm_device *dev,
                                  enum i915_cache_level level)
  {
@@@ -341,7 -350,7 +341,7 @@@ i915_gem_phys_pwrite(struct drm_i915_ge
        struct drm_device *dev = obj->base.dev;
        void *vaddr = obj->phys_handle->vaddr + args->offset;
        char __user *user_data = to_user_ptr(args->data_ptr);
 -      int ret;
 +      int ret = 0;
  
        /* We manually control the domain here and pretend that it
         * remains coherent i.e. in the GTT domain, like shmem_pwrite.
        if (ret)
                return ret;
  
 +      intel_fb_obj_invalidate(obj, NULL, ORIGIN_CPU);
        if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
                unsigned long unwritten;
  
                mutex_unlock(&dev->struct_mutex);
                unwritten = copy_from_user(vaddr, user_data, args->size);
                mutex_lock(&dev->struct_mutex);
 -              if (unwritten)
 -                      return -EFAULT;
 +              if (unwritten) {
 +                      ret = -EFAULT;
 +                      goto out;
 +              }
        }
  
        drm_clflush_virt_range(vaddr, args->size);
        i915_gem_chipset_flush(dev);
 -      return 0;
 +
 +out:
 +      intel_fb_obj_flush(obj, false);
 +      return ret;
  }
  
  void *i915_gem_object_alloc(struct drm_device *dev)
@@@ -806,8 -809,6 +806,8 @@@ i915_gem_gtt_pwrite_fast(struct drm_dev
  
        offset = i915_gem_obj_ggtt_offset(obj) + args->offset;
  
 +      intel_fb_obj_invalidate(obj, NULL, ORIGIN_GTT);
 +
        while (remain > 0) {
                /* Operation in this page
                 *
                if (fast_user_write(dev_priv->gtt.mappable, page_base,
                                    page_offset, user_data, page_length)) {
                        ret = -EFAULT;
 -                      goto out_unpin;
 +                      goto out_flush;
                }
  
                remain -= page_length;
                offset += page_length;
        }
  
 +out_flush:
 +      intel_fb_obj_flush(obj, false);
  out_unpin:
        i915_gem_object_ggtt_unpin(obj);
  out:
@@@ -952,8 -951,6 +952,8 @@@ i915_gem_shmem_pwrite(struct drm_devic
        if (ret)
                return ret;
  
 +      intel_fb_obj_invalidate(obj, NULL, ORIGIN_CPU);
 +
        i915_gem_object_pin_pages(obj);
  
        offset = args->offset;
@@@ -1032,7 -1029,6 +1032,7 @@@ out
        if (needs_clflush_after)
                i915_gem_chipset_flush(dev);
  
 +      intel_fb_obj_flush(obj, false);
        return ret;
  }
  
@@@ -1926,6 -1922,12 +1926,6 @@@ i915_gem_mmap_gtt_ioctl(struct drm_devi
        return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
  }
  
 -static inline int
 -i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj)
 -{
 -      return obj->madv == I915_MADV_DONTNEED;
 -}
 -
  /* Immediately discard the backing storage */
  static void
  i915_gem_object_truncate(struct drm_i915_gem_object *obj)
@@@ -2031,6 -2033,85 +2031,6 @@@ i915_gem_object_put_pages(struct drm_i9
        return 0;
  }
  
 -unsigned long
 -i915_gem_shrink(struct drm_i915_private *dev_priv,
 -              long target, unsigned flags)
 -{
 -      const struct {
 -              struct list_head *list;
 -              unsigned int bit;
 -      } phases[] = {
 -              { &dev_priv->mm.unbound_list, I915_SHRINK_UNBOUND },
 -              { &dev_priv->mm.bound_list, I915_SHRINK_BOUND },
 -              { NULL, 0 },
 -      }, *phase;
 -      unsigned long count = 0;
 -
 -      /*
 -       * As we may completely rewrite the (un)bound list whilst unbinding
 -       * (due to retiring requests) we have to strictly process only
 -       * one element of the list at the time, and recheck the list
 -       * on every iteration.
 -       *
 -       * In particular, we must hold a reference whilst removing the
 -       * object as we may end up waiting for and/or retiring the objects.
 -       * This might release the final reference (held by the active list)
 -       * and result in the object being freed from under us. This is
 -       * similar to the precautions the eviction code must take whilst
 -       * removing objects.
 -       *
 -       * Also note that although these lists do not hold a reference to
 -       * the object we can safely grab one here: The final object
 -       * unreferencing and the bound_list are both protected by the
 -       * dev->struct_mutex and so we won't ever be able to observe an
 -       * object on the bound_list with a reference count equals 0.
 -       */
 -      for (phase = phases; phase->list; phase++) {
 -              struct list_head still_in_list;
 -
 -              if ((flags & phase->bit) == 0)
 -                      continue;
 -
 -              INIT_LIST_HEAD(&still_in_list);
 -              while (count < target && !list_empty(phase->list)) {
 -                      struct drm_i915_gem_object *obj;
 -                      struct i915_vma *vma, *v;
 -
 -                      obj = list_first_entry(phase->list,
 -                                             typeof(*obj), global_list);
 -                      list_move_tail(&obj->global_list, &still_in_list);
 -
 -                      if (flags & I915_SHRINK_PURGEABLE &&
 -                          !i915_gem_object_is_purgeable(obj))
 -                              continue;
 -
 -                      drm_gem_object_reference(&obj->base);
 -
 -                      /* For the unbound phase, this should be a no-op! */
 -                      list_for_each_entry_safe(vma, v,
 -                                               &obj->vma_list, vma_link)
 -                              if (i915_vma_unbind(vma))
 -                                      break;
 -
 -                      if (i915_gem_object_put_pages(obj) == 0)
 -                              count += obj->base.size >> PAGE_SHIFT;
 -
 -                      drm_gem_object_unreference(&obj->base);
 -              }
 -              list_splice(&still_in_list, phase->list);
 -      }
 -
 -      return count;
 -}
 -
 -static unsigned long
 -i915_gem_shrink_all(struct drm_i915_private *dev_priv)
 -{
 -      i915_gem_evict_everything(dev_priv->dev);
 -      return i915_gem_shrink(dev_priv, LONG_MAX,
 -                             I915_SHRINK_BOUND | I915_SHRINK_UNBOUND);
 -}
 -
  static int
  i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
  {
@@@ -2411,8 -2492,6 +2411,8 @@@ int __i915_add_request(struct intel_eng
                list_add_tail(&request->client_list,
                              &file_priv->mm.request_list);
                spin_unlock(&file_priv->mm.lock);
 +
 +              request->pid = get_pid(task_pid(current));
        }
  
        trace_i915_gem_request_add(request);
@@@ -2493,8 -2572,6 +2493,8 @@@ static void i915_gem_free_request(struc
        list_del(&request->list);
        i915_gem_request_remove_from_client(request);
  
 +      put_pid(request->pid);
 +
        i915_gem_request_unreference(request);
  }
  
@@@ -2660,26 -2737,14 +2660,13 @@@ i915_gem_retire_requests_ring(struct in
  
        WARN_ON(i915_verify_lists(ring->dev));
  
-       /* Move any buffers on the active list that are no longer referenced
-        * by the ringbuffer to the flushing/inactive lists as appropriate,
-        * before we free the context associated with the requests.
+       /* Retire requests first as we use it above for the early return.
+        * If we retire requests last, we may use a later seqno and so clear
+        * the requests lists without clearing the active list, leading to
+        * confusion.
         */
-       while (!list_empty(&ring->active_list)) {
-               struct drm_i915_gem_object *obj;
-               obj = list_first_entry(&ring->active_list,
-                                     struct drm_i915_gem_object,
-                                     ring_list);
-               if (!i915_gem_request_completed(obj->last_read_req, true))
-                       break;
-               i915_gem_object_move_to_inactive(obj);
-       }
        while (!list_empty(&ring->request_list)) {
                struct drm_i915_gem_request *request;
 -              struct intel_ringbuffer *ringbuf;
  
                request = list_first_entry(&ring->request_list,
                                           struct drm_i915_gem_request,
  
                trace_i915_gem_request_retire(request);
  
 -              /* This is one of the few common intersection points
 -               * between legacy ringbuffer submission and execlists:
 -               * we need to tell them apart in order to find the correct
 -               * ringbuffer to which the request belongs to.
 -               */
 -              if (i915.enable_execlists) {
 -                      struct intel_context *ctx = request->ctx;
 -                      ringbuf = ctx->engine[ring->id].ringbuf;
 -              } else
 -                      ringbuf = ring->buffer;
 -
                /* We know the GPU must have read the request to have
                 * sent us the seqno + interrupt, so use the position
                 * of tail of the request to update the last known position
                 * of the GPU head.
                 */
 -              ringbuf->last_retired_head = request->postfix;
 +              request->ringbuf->last_retired_head = request->postfix;
  
                i915_gem_free_request(request);
        }
  
+       /* Move any buffers on the active list that are no longer referenced
+        * by the ringbuffer to the flushing/inactive lists as appropriate,
+        * before we free the context associated with the requests.
+        */
+       while (!list_empty(&ring->active_list)) {
+               struct drm_i915_gem_object *obj;
+               obj = list_first_entry(&ring->active_list,
+                                     struct drm_i915_gem_object,
+                                     ring_list);
+               if (!i915_gem_request_completed(obj->last_read_req, true))
+                       break;
+               i915_gem_object_move_to_inactive(obj);
+       }
        if (unlikely(ring->trace_irq_req &&
                     i915_gem_request_completed(ring->trace_irq_req, true))) {
                ring->irq_put(ring);
@@@ -3423,9 -3516,9 +3427,9 @@@ static bool i915_gem_valid_gtt_space(st
  static struct i915_vma *
  i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
                           struct i915_address_space *vm,
 +                         const struct i915_ggtt_view *ggtt_view,
                           unsigned alignment,
 -                         uint64_t flags,
 -                         const struct i915_ggtt_view *view)
 +                         uint64_t flags)
  {
        struct drm_device *dev = obj->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct i915_vma *vma;
        int ret;
  
 +      if(WARN_ON(i915_is_ggtt(vm) != !!ggtt_view))
 +              return ERR_PTR(-EINVAL);
 +
        fence_size = i915_gem_get_gtt_size(dev,
                                           obj->base.size,
                                           obj->tiling_mode);
  
        i915_gem_object_pin_pages(obj);
  
 -      vma = i915_gem_obj_lookup_or_create_vma_view(obj, vm, view);
 +      vma = ggtt_view ? i915_gem_obj_lookup_or_create_ggtt_vma(obj, ggtt_view) :
 +                        i915_gem_obj_lookup_or_create_vma(obj, vm);
 +
        if (IS_ERR(vma))
                goto err_unpin;
  
@@@ -3510,17 -3598,6 +3514,17 @@@ search_free
        if (ret)
                goto err_remove_node;
  
 +      /*  allocate before insert / bind */
 +      if (vma->vm->allocate_va_range) {
 +              trace_i915_va_alloc(vma->vm, vma->node.start, vma->node.size,
 +                              VM_TO_TRACE_NAME(vma->vm));
 +              ret = vma->vm->allocate_va_range(vma->vm,
 +                                              vma->node.start,
 +                                              vma->node.size);
 +              if (ret)
 +                      goto err_remove_node;
 +      }
 +
        trace_i915_vma_bind(vma, flags);
        ret = i915_vma_bind(vma, obj->cache_level,
                            flags & PIN_GLOBAL ? GLOBAL_BIND : 0);
@@@ -3691,7 -3768,7 +3695,7 @@@ i915_gem_object_set_to_gtt_domain(struc
        }
  
        if (write)
 -              intel_fb_obj_invalidate(obj, NULL);
 +              intel_fb_obj_invalidate(obj, NULL, ORIGIN_GTT);
  
        trace_i915_gem_object_change_domain(obj,
                                            old_read_domains,
@@@ -3873,8 -3950,7 +3877,8 @@@ static bool is_pin_display(struct drm_i
  int
  i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,
                                     u32 alignment,
 -                                   struct intel_engine_cs *pipelined)
 +                                   struct intel_engine_cs *pipelined,
 +                                   const struct i915_ggtt_view *view)
  {
        u32 old_read_domains, old_write_domain;
        bool was_pin_display;
         * (e.g. libkms for the bootup splash), we have to ensure that we
         * always use map_and_fenceable for all scanout buffers.
         */
 -      ret = i915_gem_obj_ggtt_pin(obj, alignment, PIN_MAPPABLE);
 +      ret = i915_gem_object_ggtt_pin(obj, view, alignment,
 +                                     view->type == I915_GGTT_VIEW_NORMAL ?
 +                                     PIN_MAPPABLE : 0);
        if (ret)
                goto err_unpin_display;
  
@@@ -3940,11 -4014,9 +3944,11 @@@ err_unpin_display
  }
  
  void
 -i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj)
 +i915_gem_object_unpin_from_display_plane(struct drm_i915_gem_object *obj,
 +                                       const struct i915_ggtt_view *view)
  {
 -      i915_gem_object_ggtt_unpin(obj);
 +      i915_gem_object_ggtt_unpin_view(obj, view);
 +
        obj->pin_display = is_pin_display(obj);
  }
  
@@@ -4011,7 -4083,7 +4015,7 @@@ i915_gem_object_set_to_cpu_domain(struc
        }
  
        if (write)
 -              intel_fb_obj_invalidate(obj, NULL);
 +              intel_fb_obj_invalidate(obj, NULL, ORIGIN_CPU);
  
        trace_i915_gem_object_change_domain(obj,
                                            old_read_domains,
@@@ -4093,12 -4165,12 +4097,12 @@@ i915_vma_misplaced(struct i915_vma *vma
        return false;
  }
  
 -int
 -i915_gem_object_pin_view(struct drm_i915_gem_object *obj,
 -                       struct i915_address_space *vm,
 -                       uint32_t alignment,
 -                       uint64_t flags,
 -                       const struct i915_ggtt_view *view)
 +static int
 +i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
 +                     struct i915_address_space *vm,
 +                     const struct i915_ggtt_view *ggtt_view,
 +                     uint32_t alignment,
 +                     uint64_t flags)
  {
        struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
        struct i915_vma *vma;
        if (WARN_ON((flags & (PIN_MAPPABLE | PIN_GLOBAL)) == PIN_MAPPABLE))
                return -EINVAL;
  
 -      vma = i915_gem_obj_to_vma_view(obj, vm, view);
 +      if (WARN_ON(i915_is_ggtt(vm) != !!ggtt_view))
 +              return -EINVAL;
 +
 +      vma = ggtt_view ? i915_gem_obj_to_ggtt_view(obj, ggtt_view) :
 +                        i915_gem_obj_to_vma(obj, vm);
 +
 +      if (IS_ERR(vma))
 +              return PTR_ERR(vma);
 +
        if (vma) {
                if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
                        return -EBUSY;
  
                if (i915_vma_misplaced(vma, alignment, flags)) {
 +                      unsigned long offset;
 +                      offset = ggtt_view ? i915_gem_obj_ggtt_offset_view(obj, ggtt_view) :
 +                                           i915_gem_obj_offset(obj, vm);
                        WARN(vma->pin_count,
 -                           "bo is already pinned with incorrect alignment:"
 +                           "bo is already pinned in %s with incorrect alignment:"
                             " offset=%lx, req.alignment=%x, req.map_and_fenceable=%d,"
                             " obj->map_and_fenceable=%d\n",
 -                           i915_gem_obj_offset_view(obj, vm, view->type),
 +                           ggtt_view ? "ggtt" : "ppgtt",
 +                           offset,
                             alignment,
                             !!(flags & PIN_MAPPABLE),
                             obj->map_and_fenceable);
  
        bound = vma ? vma->bound : 0;
        if (vma == NULL || !drm_mm_node_allocated(&vma->node)) {
 -              vma = i915_gem_object_bind_to_vm(obj, vm, alignment,
 -                                               flags, view);
 +              /* In true PPGTT, bind has possibly changed PDEs, which
 +               * means we must do a context switch before the GPU can
 +               * accurately read some of the VMAs.
 +               */
 +              vma = i915_gem_object_bind_to_vm(obj, vm, ggtt_view, alignment,
 +                                               flags);
                if (IS_ERR(vma))
                        return PTR_ERR(vma);
        }
                fenceable = (vma->node.size == fence_size &&
                             (vma->node.start & (fence_alignment - 1)) == 0);
  
 -              mappable = (vma->node.start + obj->base.size <=
 +              mappable = (vma->node.start + fence_size <=
                            dev_priv->gtt.mappable_end);
  
                obj->map_and_fenceable = mappable && fenceable;
        return 0;
  }
  
 +int
 +i915_gem_object_pin(struct drm_i915_gem_object *obj,
 +                  struct i915_address_space *vm,
 +                  uint32_t alignment,
 +                  uint64_t flags)
 +{
 +      return i915_gem_object_do_pin(obj, vm,
 +                                    i915_is_ggtt(vm) ? &i915_ggtt_view_normal : NULL,
 +                                    alignment, flags);
 +}
 +
 +int
 +i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
 +                       const struct i915_ggtt_view *view,
 +                       uint32_t alignment,
 +                       uint64_t flags)
 +{
 +      if (WARN_ONCE(!view, "no view specified"))
 +              return -EINVAL;
 +
 +      return i915_gem_object_do_pin(obj, i915_obj_to_ggtt(obj), view,
 +                                    alignment, flags | PIN_GLOBAL);
 +}
 +
  void
 -i915_gem_object_ggtt_unpin(struct drm_i915_gem_object *obj)
 +i915_gem_object_ggtt_unpin_view(struct drm_i915_gem_object *obj,
 +                              const struct i915_ggtt_view *view)
  {
 -      struct i915_vma *vma = i915_gem_obj_to_ggtt(obj);
 +      struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
  
        BUG_ON(!vma);
 -      BUG_ON(vma->pin_count == 0);
 -      BUG_ON(!i915_gem_obj_ggtt_bound(obj));
 +      WARN_ON(vma->pin_count == 0);
 +      WARN_ON(!i915_gem_obj_ggtt_bound_view(obj, view));
  
 -      if (--vma->pin_count == 0)
 +      if (--vma->pin_count == 0 && view->type == I915_GGTT_VIEW_NORMAL)
                obj->pin_mappable = false;
  }
  
@@@ -4351,7 -4382,7 +4355,7 @@@ i915_gem_madvise_ioctl(struct drm_devic
                obj->madv = args->madv;
  
        /* if the object is no longer attached, discard its backing storage */
 -      if (i915_gem_object_is_purgeable(obj) && obj->pages == NULL)
 +      if (obj->madv == I915_MADV_DONTNEED && obj->pages == NULL)
                i915_gem_object_truncate(obj);
  
        args->retained = obj->madv != __I915_MADV_PURGED;
@@@ -4526,33 -4557,15 +4530,33 @@@ void i915_gem_free_object(struct drm_ge
        intel_runtime_pm_put(dev_priv);
  }
  
 -struct i915_vma *i915_gem_obj_to_vma_view(struct drm_i915_gem_object *obj,
 -                                        struct i915_address_space *vm,
 -                                        const struct i915_ggtt_view *view)
 +struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
 +                                   struct i915_address_space *vm)
  {
        struct i915_vma *vma;
 -      list_for_each_entry(vma, &obj->vma_list, vma_link)
 -              if (vma->vm == vm && vma->ggtt_view.type == view->type)
 +      list_for_each_entry(vma, &obj->vma_list, vma_link) {
 +              if (i915_is_ggtt(vma->vm) &&
 +                  vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
 +                      continue;
 +              if (vma->vm == vm)
                        return vma;
 +      }
 +      return NULL;
 +}
 +
 +struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
 +                                         const struct i915_ggtt_view *view)
 +{
 +      struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
 +      struct i915_vma *vma;
 +
 +      if (WARN_ONCE(!view, "no view specified"))
 +              return ERR_PTR(-EINVAL);
  
 +      list_for_each_entry(vma, &obj->vma_list, vma_link)
 +              if (vma->vm == ggtt &&
 +                  i915_ggtt_view_equal(&vma->ggtt_view, view))
 +                      return vma;
        return NULL;
  }
  
@@@ -4599,6 -4612,10 +4603,6 @@@ i915_gem_suspend(struct drm_device *dev
  
        i915_gem_retire_requests(dev);
  
 -      /* Under UMS, be paranoid and evict. */
 -      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 -              i915_gem_evict_everything(dev);
 -
        i915_gem_stop_ringbuffers(dev);
        mutex_unlock(&dev->struct_mutex);
  
@@@ -4969,8 -4986,18 +4973,8 @@@ i915_gem_load(struct drm_device *dev
                          i915_gem_idle_work_handler);
        init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
  
 -      /* On GEN3 we really need to make sure the ARB C3 LP bit is set */
 -      if (!drm_core_check_feature(dev, DRIVER_MODESET) && IS_GEN3(dev)) {
 -              I915_WRITE(MI_ARB_STATE,
 -                         _MASKED_BIT_ENABLE(MI_ARB_C3_LP_WRITE_ENABLE));
 -      }
 -
        dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
  
 -      /* Old X drivers will take 0-2 for front, back, depth buffers */
 -      if (!drm_core_check_feature(dev, DRIVER_MODESET))
 -              dev_priv->fence_reg_start = 3;
 -
        if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
                dev_priv->num_fence_regs = 32;
        else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
        else
                dev_priv->num_fence_regs = 8;
  
 +      if (intel_vgpu_active(dev))
 +              dev_priv->num_fence_regs =
 +                              I915_READ(vgtif_reg(avail_rs.fence_num));
 +
        /* Initialize fence registers to zero */
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
        i915_gem_restore_fences(dev);
  
        dev_priv->mm.interruptible = true;
  
 -      dev_priv->mm.shrinker.scan_objects = i915_gem_shrinker_scan;
 -      dev_priv->mm.shrinker.count_objects = i915_gem_shrinker_count;
 -      dev_priv->mm.shrinker.seeks = DEFAULT_SEEKS;
 -      register_shrinker(&dev_priv->mm.shrinker);
 -
 -      dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
 -      register_oom_notifier(&dev_priv->mm.oom_notifier);
 +      i915_gem_shrinker_init(dev_priv);
  
        i915_gem_batch_pool_init(dev, &dev_priv->mm.batch_pool);
  
@@@ -5083,70 -5112,106 +5087,70 @@@ void i915_gem_track_fb(struct drm_i915_
        }
  }
  
 -static bool mutex_is_locked_by(struct mutex *mutex, struct task_struct *task)
 -{
 -      if (!mutex_is_locked(mutex))
 -              return false;
 -
 -#if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_MUTEXES)
 -      return mutex->owner == task;
 -#else
 -      /* Since UP may be pre-empted, we cannot assume that we own the lock */
 -      return false;
 -#endif
 -}
 -
 -static bool i915_gem_shrinker_lock(struct drm_device *dev, bool *unlock)
 +/* All the new VM stuff */
 +unsigned long
 +i915_gem_obj_offset(struct drm_i915_gem_object *o,
 +                  struct i915_address_space *vm)
  {
 -      if (!mutex_trylock(&dev->struct_mutex)) {
 -              if (!mutex_is_locked_by(&dev->struct_mutex, current))
 -                      return false;
 +      struct drm_i915_private *dev_priv = o->base.dev->dev_private;
 +      struct i915_vma *vma;
  
 -              if (to_i915(dev)->mm.shrinker_no_lock_stealing)
 -                      return false;
 +      WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
  
 -              *unlock = false;
 -      } else
 -              *unlock = true;
 +      list_for_each_entry(vma, &o->vma_list, vma_link) {
 +              if (i915_is_ggtt(vma->vm) &&
 +                  vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
 +                      continue;
 +              if (vma->vm == vm)
 +                      return vma->node.start;
 +      }
  
 -      return true;
 +      WARN(1, "%s vma for this object not found.\n",
 +           i915_is_ggtt(vm) ? "global" : "ppgtt");
 +      return -1;
  }
  
 -static int num_vma_bound(struct drm_i915_gem_object *obj)
 +unsigned long
 +i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
 +                            const struct i915_ggtt_view *view)
  {
 +      struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
        struct i915_vma *vma;
 -      int count = 0;
  
 -      list_for_each_entry(vma, &obj->vma_list, vma_link)
 -              if (drm_mm_node_allocated(&vma->node))
 -                      count++;
 -
 -      return count;
 -}
 -
 -static unsigned long
 -i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
 -{
 -      struct drm_i915_private *dev_priv =
 -              container_of(shrinker, struct drm_i915_private, mm.shrinker);
 -      struct drm_device *dev = dev_priv->dev;
 -      struct drm_i915_gem_object *obj;
 -      unsigned long count;
 -      bool unlock;
 -
 -      if (!i915_gem_shrinker_lock(dev, &unlock))
 -              return 0;
 -
 -      count = 0;
 -      list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
 -              if (obj->pages_pin_count == 0)
 -                      count += obj->base.size >> PAGE_SHIFT;
 -
 -      list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 -              if (!i915_gem_obj_is_pinned(obj) &&
 -                  obj->pages_pin_count == num_vma_bound(obj))
 -                      count += obj->base.size >> PAGE_SHIFT;
 -      }
 -
 -      if (unlock)
 -              mutex_unlock(&dev->struct_mutex);
 +      list_for_each_entry(vma, &o->vma_list, vma_link)
 +              if (vma->vm == ggtt &&
 +                  i915_ggtt_view_equal(&vma->ggtt_view, view))
 +                      return vma->node.start;
  
 -      return count;
 +      WARN(1, "global vma for this object not found.\n");
 +      return -1;
  }
  
 -/* All the new VM stuff */
 -unsigned long i915_gem_obj_offset_view(struct drm_i915_gem_object *o,
 -                                     struct i915_address_space *vm,
 -                                     enum i915_ggtt_view_type view)
 +bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
 +                      struct i915_address_space *vm)
  {
 -      struct drm_i915_private *dev_priv = o->base.dev->dev_private;
        struct i915_vma *vma;
  
 -      WARN_ON(vm == &dev_priv->mm.aliasing_ppgtt->base);
 -
        list_for_each_entry(vma, &o->vma_list, vma_link) {
 -              if (vma->vm == vm && vma->ggtt_view.type == view)
 -                      return vma->node.start;
 -
 +              if (i915_is_ggtt(vma->vm) &&
 +                  vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
 +                      continue;
 +              if (vma->vm == vm && drm_mm_node_allocated(&vma->node))
 +                      return true;
        }
 -      WARN(1, "%s vma for this object not found.\n",
 -           i915_is_ggtt(vm) ? "global" : "ppgtt");
 -      return -1;
 +
 +      return false;
  }
  
 -bool i915_gem_obj_bound_view(struct drm_i915_gem_object *o,
 -                           struct i915_address_space *vm,
 -                           enum i915_ggtt_view_type view)
 +bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
 +                                const struct i915_ggtt_view *view)
  {
 +      struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
        struct i915_vma *vma;
  
        list_for_each_entry(vma, &o->vma_list, vma_link)
 -              if (vma->vm == vm &&
 -                  vma->ggtt_view.type == view &&
 +              if (vma->vm == ggtt &&
 +                  i915_ggtt_view_equal(&vma->ggtt_view, view) &&
                    drm_mm_node_allocated(&vma->node))
                        return true;
  
@@@ -5174,26 -5239,118 +5178,26 @@@ unsigned long i915_gem_obj_size(struct 
  
        BUG_ON(list_empty(&o->vma_list));
  
 -      list_for_each_entry(vma, &o->vma_list, vma_link)
 +      list_for_each_entry(vma, &o->vma_list, vma_link) {
 +              if (i915_is_ggtt(vma->vm) &&
 +                  vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
 +                      continue;
                if (vma->vm == vm)
                        return vma->node.size;
 -
 +      }
        return 0;
  }
  
 -static unsigned long
 -i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
 -{
 -      struct drm_i915_private *dev_priv =
 -              container_of(shrinker, struct drm_i915_private, mm.shrinker);
 -      struct drm_device *dev = dev_priv->dev;
 -      unsigned long freed;
 -      bool unlock;
 -
 -      if (!i915_gem_shrinker_lock(dev, &unlock))
 -              return SHRINK_STOP;
 -
 -      freed = i915_gem_shrink(dev_priv,
 -                              sc->nr_to_scan,
 -                              I915_SHRINK_BOUND |
 -                              I915_SHRINK_UNBOUND |
 -                              I915_SHRINK_PURGEABLE);
 -      if (freed < sc->nr_to_scan)
 -              freed += i915_gem_shrink(dev_priv,
 -                                       sc->nr_to_scan - freed,
 -                                       I915_SHRINK_BOUND |
 -                                       I915_SHRINK_UNBOUND);
 -      if (unlock)
 -              mutex_unlock(&dev->struct_mutex);
 -
 -      return freed;
 -}
 -
 -static int
 -i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
 +bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj)
  {
 -      struct drm_i915_private *dev_priv =
 -              container_of(nb, struct drm_i915_private, mm.oom_notifier);
 -      struct drm_device *dev = dev_priv->dev;
 -      struct drm_i915_gem_object *obj;
 -      unsigned long timeout = msecs_to_jiffies(5000) + 1;
 -      unsigned long pinned, bound, unbound, freed_pages;
 -      bool was_interruptible;
 -      bool unlock;
 -
 -      while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout) {
 -              schedule_timeout_killable(1);
 -              if (fatal_signal_pending(current))
 -                      return NOTIFY_DONE;
 -      }
 -      if (timeout == 0) {
 -              pr_err("Unable to purge GPU memory due lock contention.\n");
 -              return NOTIFY_DONE;
 -      }
 -
 -      was_interruptible = dev_priv->mm.interruptible;
 -      dev_priv->mm.interruptible = false;
 -
 -      freed_pages = i915_gem_shrink_all(dev_priv);
 -
 -      dev_priv->mm.interruptible = was_interruptible;
 -
 -      /* Because we may be allocating inside our own driver, we cannot
 -       * assert that there are no objects with pinned pages that are not
 -       * being pointed to by hardware.
 -       */
 -      unbound = bound = pinned = 0;
 -      list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list) {
 -              if (!obj->base.filp) /* not backed by a freeable object */
 -                      continue;
 -
 -              if (obj->pages_pin_count)
 -                      pinned += obj->base.size;
 -              else
 -                      unbound += obj->base.size;
 -      }
 -      list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
 -              if (!obj->base.filp)
 +      struct i915_vma *vma;
 +      list_for_each_entry(vma, &obj->vma_list, vma_link) {
 +              if (i915_is_ggtt(vma->vm) &&
 +                  vma->ggtt_view.type != I915_GGTT_VIEW_NORMAL)
                        continue;
 -
 -              if (obj->pages_pin_count)
 -                      pinned += obj->base.size;
 -              else
 -                      bound += obj->base.size;
 +              if (vma->pin_count > 0)
 +                      return true;
        }
 -
 -      if (unlock)
 -              mutex_unlock(&dev->struct_mutex);
 -
 -      if (freed_pages || unbound || bound)
 -              pr_info("Purging GPU memory, %lu bytes freed, %lu bytes still pinned.\n",
 -                      freed_pages << PAGE_SHIFT, pinned);
 -      if (unbound || bound)
 -              pr_err("%lu and %lu bytes still available in the "
 -                     "bound and unbound GPU page lists.\n",
 -                     bound, unbound);
 -
 -      *(unsigned long *)ptr += freed_pages;
 -      return NOTIFY_DONE;
 +      return false;
  }
  
 -struct i915_vma *i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
 -{
 -      struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
 -      struct i915_vma *vma;
 -
 -      list_for_each_entry(vma, &obj->vma_list, vma_link)
 -              if (vma->vm == ggtt &&
 -                  vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL)
 -                      return vma;
 -
 -      return NULL;
 -}