Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 25 Oct 2016 06:57:53 +0000 (08:57 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Tue, 25 Oct 2016 06:57:53 +0000 (08:57 +0200)
Backmerge because Chris Wilson needs the very latest&greates of
Gustavo Padovan's sync_file work, specifically the refcounting changes
from:

commit 30cd85dd6edc86ea8d8589efb813f1fad41ef233
Author: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Date:   Wed Oct 19 15:48:32 2016 -0200

    dma-buf/sync_file: hold reference to fence when creating sync_file

Also good to sync in general since git tends to get confused with the
cherry-picking going on.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
15 files changed:
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_evict.c
drivers/gpu/drm/i915/i915_gem_fence.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_tiling.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fbc.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_runtime_pm.c

index 1c1b19ccb92f38490b892116911eeff004870e35..45a5eb71e8e64a312871d82a7e4b4cc1ecf24abc 100644 (file)
@@ -24,16 +24,17 @@ config DRM_I915
          including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G,
          G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3,
          Core i5, Core i7 as well as Atom CPUs with integrated graphics.
-         If M is selected, the module will be called i915.  AGP support
-         is required for this driver to work. This driver is used by
-         the Intel driver in X.org 6.8 and XFree86 4.4 and above. It
-         replaces the older i830 module that supported a subset of the
-         hardware in older X.org releases.
+
+         This driver is used by the Intel driver in X.org 6.8 and
+         XFree86 4.4 and above. It replaces the older i830 module that
+         supported a subset of the hardware in older X.org releases.
 
          Note that the older i810/i815 chipsets require the use of the
          i810 driver instead, and the Atom z5xx series has an entirely
          different implementation.
 
+         If "M" is selected, the module will be called i915.
+
 config DRM_I915_PRELIMINARY_HW_SUPPORT
        bool "Enable preliminary support for prerelease Intel hardware by default"
        depends on DRM_I915
index 20638d22bbad1eae081039fda72a641fc391d3ad..4751b618ae12dcf4ad0a1b473715da4809ad1513 100644 (file)
@@ -107,7 +107,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj)
 
 static char get_global_flag(struct drm_i915_gem_object *obj)
 {
-       return obj->fault_mappable ? 'g' : ' ';
+       return !list_empty(&obj->userfault_link) ? 'g' : ' ';
 }
 
 static char get_pin_mapped_flag(struct drm_i915_gem_object *obj)
@@ -743,17 +743,32 @@ static int i915_interrupt_info(struct seq_file *m, void *data)
                           I915_READ(VLV_IIR_RW));
                seq_printf(m, "Display IMR:\t%08x\n",
                           I915_READ(VLV_IMR));
-               for_each_pipe(dev_priv, pipe)
+               for_each_pipe(dev_priv, pipe) {
+                       enum intel_display_power_domain power_domain;
+
+                       power_domain = POWER_DOMAIN_PIPE(pipe);
+                       if (!intel_display_power_get_if_enabled(dev_priv,
+                                                               power_domain)) {
+                               seq_printf(m, "Pipe %c power disabled\n",
+                                          pipe_name(pipe));
+                               continue;
+                       }
+
                        seq_printf(m, "Pipe %c stat:\t%08x\n",
                                   pipe_name(pipe),
                                   I915_READ(PIPESTAT(pipe)));
 
+                       intel_display_power_put(dev_priv, power_domain);
+               }
+
+               intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
                seq_printf(m, "Port hotplug:\t%08x\n",
                           I915_READ(PORT_HOTPLUG_EN));
                seq_printf(m, "DPFLIPSTAT:\t%08x\n",
                           I915_READ(VLV_DPFLIPSTAT));
                seq_printf(m, "DPINVGTT:\t%08x\n",
                           I915_READ(DPINVGTT));
+               intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
 
                for (i = 0; i < 4; i++) {
                        seq_printf(m, "GT Interrupt IMR %d:\t%08x\n",
@@ -1396,14 +1411,9 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
 static int ironlake_drpc_info(struct seq_file *m)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
        u32 rgvmodectl, rstdbyctl;
        u16 crstandvid;
-       int ret;
 
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
        intel_runtime_pm_get(dev_priv);
 
        rgvmodectl = I915_READ(MEMMODECTL);
@@ -1411,7 +1421,6 @@ static int ironlake_drpc_info(struct seq_file *m)
        crstandvid = I915_READ16(CRSTANDVID);
 
        intel_runtime_pm_put(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
 
        seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN));
        seq_printf(m, "Boost freq: %d\n",
@@ -1674,11 +1683,13 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
                seq_printf(m, "FBC disabled: %s\n",
                           dev_priv->fbc.no_fbc_reason);
 
-       if (intel_fbc_is_active(dev_priv) &&
-           INTEL_GEN(dev_priv) >= 7)
+       if (intel_fbc_is_active(dev_priv) && INTEL_GEN(dev_priv) >= 7) {
+               uint32_t mask = INTEL_GEN(dev_priv) >= 8 ?
+                               BDW_FBC_COMPRESSION_MASK :
+                               IVB_FBC_COMPRESSION_MASK;
                seq_printf(m, "Compressing: %s\n",
-                          yesno(I915_READ(FBC_STATUS2) &
-                                FBC_COMPRESSION_MASK));
+                          yesno(I915_READ(FBC_STATUS2) & mask));
+       }
 
        mutex_unlock(&dev_priv->fbc.lock);
        intel_runtime_pm_put(dev_priv);
@@ -1757,6 +1768,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        bool sr_enabled = false;
 
        intel_runtime_pm_get(dev_priv);
+       intel_display_power_get(dev_priv, POWER_DOMAIN_INIT);
 
        if (HAS_PCH_SPLIT(dev_priv))
                sr_enabled = I915_READ(WM1_LP_ILK) & WM1_LP_SR_EN;
@@ -1770,6 +1782,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
        else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
                sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
 
+       intel_display_power_put(dev_priv, POWER_DOMAIN_INIT);
        intel_runtime_pm_put(dev_priv);
 
        seq_printf(m, "self-refresh: %s\n",
@@ -2091,12 +2104,7 @@ static const char *swizzle_string(unsigned swizzle)
 static int i915_swizzle_info(struct seq_file *m, void *data)
 {
        struct drm_i915_private *dev_priv = node_to_i915(m->private);
-       struct drm_device *dev = &dev_priv->drm;
-       int ret;
 
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
        intel_runtime_pm_get(dev_priv);
 
        seq_printf(m, "bit6 swizzle for X-tiling = %s\n",
@@ -2136,7 +2144,6 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
                seq_puts(m, "L-shaped memory detected\n");
 
        intel_runtime_pm_put(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
 
        return 0;
 }
@@ -2542,11 +2549,22 @@ static int i915_edp_psr_status(struct seq_file *m, void *data)
                enabled = I915_READ(EDP_PSR_CTL) & EDP_PSR_ENABLE;
        else {
                for_each_pipe(dev_priv, pipe) {
+                       enum transcoder cpu_transcoder =
+                               intel_pipe_to_cpu_transcoder(dev_priv, pipe);
+                       enum intel_display_power_domain power_domain;
+
+                       power_domain = POWER_DOMAIN_TRANSCODER(cpu_transcoder);
+                       if (!intel_display_power_get_if_enabled(dev_priv,
+                                                               power_domain))
+                               continue;
+
                        stat[pipe] = I915_READ(VLV_PSRSTAT(pipe)) &
                                VLV_EDP_PSR_CURR_STATE_MASK;
                        if ((stat[pipe] == VLV_EDP_PSR_ACTIVE_NORFB_UP) ||
                            (stat[pipe] == VLV_EDP_PSR_ACTIVE_SF_UPDATE))
                                enabled = true;
+
+                       intel_display_power_put(dev_priv, power_domain);
                }
        }
 
@@ -3094,6 +3112,8 @@ static int i915_engine_info(struct seq_file *m, void *unused)
        struct intel_engine_cs *engine;
        enum intel_engine_id id;
 
+       intel_runtime_pm_get(dev_priv);
+
        for_each_engine(engine, dev_priv, id) {
                struct intel_breadcrumbs *b = &engine->breadcrumbs;
                struct drm_i915_gem_request *rq;
@@ -3213,6 +3233,8 @@ static int i915_engine_info(struct seq_file *m, void *unused)
                seq_puts(m, "\n");
        }
 
+       intel_runtime_pm_put(dev_priv);
+
        return 0;
 }
 
@@ -4798,13 +4820,9 @@ i915_wedged_set(void *data, u64 val)
        if (i915_reset_in_progress(&dev_priv->gpu_error))
                return -EAGAIN;
 
-       intel_runtime_pm_get(dev_priv);
-
        i915_handle_error(dev_priv, val,
                          "Manually setting wedged to %llu", val);
 
-       intel_runtime_pm_put(dev_priv);
-
        return 0;
 }
 
@@ -5039,22 +5057,16 @@ static int
 i915_cache_sharing_get(void *data, u64 *val)
 {
        struct drm_i915_private *dev_priv = data;
-       struct drm_device *dev = &dev_priv->drm;
        u32 snpcr;
-       int ret;
 
        if (!(IS_GEN6(dev_priv) || IS_GEN7(dev_priv)))
                return -ENODEV;
 
-       ret = mutex_lock_interruptible(&dev->struct_mutex);
-       if (ret)
-               return ret;
        intel_runtime_pm_get(dev_priv);
 
        snpcr = I915_READ(GEN6_MBCUNIT_SNPCR);
 
        intel_runtime_pm_put(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
 
        *val = (snpcr & GEN6_MBC_SNPCR_MASK) >> GEN6_MBC_SNPCR_SHIFT;
 
index 912d5348e3e76ae55aab66dfe7eaca90237ff02f..99e4e044e958a3e97705959429b808f1f81009ab 100644 (file)
@@ -2278,10 +2278,8 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
 
        vlv_check_no_gt_access(dev_priv);
 
-       if (rpm_resume) {
+       if (rpm_resume)
                intel_init_clock_gating(dev);
-               i915_gem_restore_fences(dev);
-       }
 
        return ret;
 }
@@ -2301,32 +2299,13 @@ static int intel_runtime_suspend(struct device *kdev)
 
        DRM_DEBUG_KMS("Suspending device\n");
 
-       /*
-        * We could deadlock here in case another thread holding struct_mutex
-        * calls RPM suspend concurrently, since the RPM suspend will wait
-        * first for this RPM suspend to finish. In this case the concurrent
-        * RPM resume will be followed by its RPM suspend counterpart. Still
-        * for consistency return -EAGAIN, which will reschedule this suspend.
-        */
-       if (!mutex_trylock(&dev->struct_mutex)) {
-               DRM_DEBUG_KMS("device lock contention, deffering suspend\n");
-               /*
-                * Bump the expiration timestamp, otherwise the suspend won't
-                * be rescheduled.
-                */
-               pm_runtime_mark_last_busy(kdev);
-
-               return -EAGAIN;
-       }
-
        disable_rpm_wakeref_asserts(dev_priv);
 
        /*
         * We are safe here against re-faults, since the fault handler takes
         * an RPM reference.
         */
-       i915_gem_release_all_mmaps(dev_priv);
-       mutex_unlock(&dev->struct_mutex);
+       i915_gem_runtime_suspend(dev_priv);
 
        intel_guc_suspend(dev);
 
index f022f438e5b93e1c408d102ee3f70d57a57a6c11..dd3acabb7edb38eeae90c7cd81b32b4345e49f17 100644 (file)
@@ -1361,6 +1361,11 @@ struct i915_gem_mm {
         */
        struct list_head unbound_list;
 
+       /** List of all objects in gtt_space, currently mmaped by userspace.
+        * All objects within this list must also be on bound_list.
+        */
+       struct list_head userfault_list;
+
        /** Usable portion of the GTT for GEM */
        unsigned long stolen_base; /* limited to low memory (32-bit) */
 
@@ -1682,7 +1687,6 @@ struct skl_wm_level {
  */
 struct i915_runtime_pm {
        atomic_t wakeref_count;
-       atomic_t atomic_seq;
        bool suspended;
        bool irqs_enabled;
 };
@@ -2205,6 +2209,11 @@ struct drm_i915_gem_object {
        struct drm_mm_node *stolen;
        struct list_head global_list;
 
+       /**
+        * Whether the object is currently in the GGTT mmap.
+        */
+       struct list_head userfault_link;
+
        /** Used in execbuf to temporarily hold a ref */
        struct list_head obj_exec_link;
 
@@ -2232,13 +2241,6 @@ struct drm_i915_gem_object {
         */
        unsigned int madv:2;
 
-       /**
-        * Whether the current gtt mapping needs to be mappable (and isn't just
-        * mappable by accident). Track pin and fault separate for a more
-        * accurate mappable working set.
-        */
-       unsigned int fault_mappable:1;
-
        /*
         * Is the object to be mapped as read-only to the GPU
         * Only honoured if hardware has relevant pte bit
@@ -3128,9 +3130,10 @@ void i915_vma_destroy(struct i915_vma *vma);
 
 int i915_gem_object_unbind(struct drm_i915_gem_object *obj);
 int i915_gem_object_put_pages(struct drm_i915_gem_object *obj);
-void i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv);
 void i915_gem_release_mmap(struct drm_i915_gem_object *obj);
 
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv);
+
 int __must_check i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
 
 static inline int __sg_page_count(struct scatterlist *sg)
index 8ed8e24025aca7f6f7e8520c2789c1042a9eabe6..0e26ee96856e945331a6f6ae7a51d436a5bf3200 100644 (file)
@@ -826,6 +826,7 @@ i915_gem_gtt_pread(struct drm_device *dev,
        uint64_t offset;
        int ret;
 
+       intel_runtime_pm_get(to_i915(dev));
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, PIN_MAPPABLE);
        if (!IS_ERR(vma)) {
                node.start = i915_ggtt_offset(vma);
@@ -926,6 +927,7 @@ out_unpin:
                i915_vma_unpin(vma);
        }
 out:
+       intel_runtime_pm_put(to_i915(dev));
        return ret;
 }
 
@@ -1060,12 +1062,9 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
        ret = i915_gem_shmem_pread(dev, obj, args, file);
 
        /* pread for non shmem backed objects */
-       if (ret == -EFAULT || ret == -ENODEV) {
-               intel_runtime_pm_get(to_i915(dev));
+       if (ret == -EFAULT || ret == -ENODEV)
                ret = i915_gem_gtt_pread(dev, obj, args->size,
                                        args->offset, args->data_ptr);
-               intel_runtime_pm_put(to_i915(dev));
-       }
 
        i915_gem_object_put(obj);
        mutex_unlock(&dev->struct_mutex);
@@ -1126,6 +1125,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_private *i915,
        if (i915_gem_object_is_tiled(obj))
                return -EFAULT;
 
+       intel_runtime_pm_get(i915);
        vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0,
                                       PIN_MAPPABLE | PIN_NONBLOCK);
        if (!IS_ERR(vma)) {
@@ -1234,6 +1234,7 @@ out_unpin:
                i915_vma_unpin(vma);
        }
 out:
+       intel_runtime_pm_put(i915);
        return ret;
 }
 
@@ -1466,12 +1467,12 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
         * perspective, requiring manual detiling by the client.
         */
        if (!i915_gem_object_has_struct_page(obj) ||
-           cpu_write_needs_clflush(obj)) {
-               ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file);
+           cpu_write_needs_clflush(obj))
                /* Note that the gtt paths might fail with non-page-backed user
                 * pointers (e.g. gtt mappings when moving data between
-                * textures). Fallback to the shmem path in that case. */
-       }
+                * textures). Fallback to the shmem path in that case.
+                */
+               ret = i915_gem_gtt_pwrite_fast(dev_priv, obj, args, file);
 
        if (ret == -EFAULT || ret == -ENOSPC) {
                if (obj->phys_handle)
@@ -1839,16 +1840,18 @@ int i915_gem_fault(struct vm_area_struct *area, struct vm_fault *vmf)
        if (ret)
                goto err_unpin;
 
+       /* Mark as being mmapped into userspace for later revocation */
+       assert_rpm_wakelock_held(dev_priv);
+       if (list_empty(&obj->userfault_link))
+               list_add(&obj->userfault_link, &dev_priv->mm.userfault_list);
+
        /* Finally, remap it using the new GTT offset */
        ret = remap_io_mapping(area,
                               area->vm_start + (vma->ggtt_view.params.partial.offset << PAGE_SHIFT),
                               (ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT,
                               min_t(u64, vma->size, area->vm_end - area->vm_start),
                               &ggtt->mappable);
-       if (ret)
-               goto err_unpin;
 
-       obj->fault_mappable = true;
 err_unpin:
        __i915_vma_unpin(vma);
 err_unlock:
@@ -1916,15 +1919,23 @@ err:
 void
 i915_gem_release_mmap(struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *i915 = to_i915(obj->base.dev);
+
        /* Serialisation between user GTT access and our code depends upon
         * revoking the CPU's PTE whilst the mutex is held. The next user
         * pagefault then has to wait until we release the mutex.
+        *
+        * Note that RPM complicates somewhat by adding an additional
+        * requirement that operations to the GGTT be made holding the RPM
+        * wakeref.
         */
-       lockdep_assert_held(&obj->base.dev->struct_mutex);
+       lockdep_assert_held(&i915->drm.struct_mutex);
+       intel_runtime_pm_get(i915);
 
-       if (!obj->fault_mappable)
-               return;
+       if (list_empty(&obj->userfault_link))
+               goto out;
 
+       list_del_init(&obj->userfault_link);
        drm_vma_node_unmap(&obj->base.vma_node,
                           obj->base.dev->anon_inode->i_mapping);
 
@@ -1937,16 +1948,45 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj)
         */
        wmb();
 
-       obj->fault_mappable = false;
+out:
+       intel_runtime_pm_put(i915);
 }
 
-void
-i915_gem_release_all_mmaps(struct drm_i915_private *dev_priv)
+void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv)
 {
-       struct drm_i915_gem_object *obj;
+       struct drm_i915_gem_object *obj, *on;
+       int i;
 
-       list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list)
-               i915_gem_release_mmap(obj);
+       /*
+        * Only called during RPM suspend. All users of the userfault_list
+        * must be holding an RPM wakeref to ensure that this can not
+        * run concurrently with themselves (and use the struct_mutex for
+        * protection between themselves).
+        */
+
+       list_for_each_entry_safe(obj, on,
+                                &dev_priv->mm.userfault_list, userfault_link) {
+               list_del_init(&obj->userfault_link);
+               drm_vma_node_unmap(&obj->base.vma_node,
+                                  obj->base.dev->anon_inode->i_mapping);
+       }
+
+       /* The fence will be lost when the device powers down. If any were
+        * in use by hardware (i.e. they are pinned), we should not be powering
+        * down! All other fences will be reacquired by the user upon waking.
+        */
+       for (i = 0; i < dev_priv->num_fence_regs; i++) {
+               struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
+
+               if (WARN_ON(reg->pin_count))
+                       continue;
+
+               if (!reg->vma)
+                       continue;
+
+               GEM_BUG_ON(!list_empty(&reg->vma->obj->userfault_link));
+               reg->dirty = true;
+       }
 }
 
 /**
@@ -3455,7 +3495,7 @@ int i915_gem_get_caching_ioctl(struct drm_device *dev, void *data,
 int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                               struct drm_file *file)
 {
-       struct drm_i915_private *dev_priv = to_i915(dev);
+       struct drm_i915_private *i915 = to_i915(dev);
        struct drm_i915_gem_caching *args = data;
        struct drm_i915_gem_object *obj;
        enum i915_cache_level level;
@@ -3472,23 +3512,21 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                 * cacheline, whereas normally such cachelines would get
                 * invalidated.
                 */
-               if (!HAS_LLC(dev) && !HAS_SNOOP(dev))
+               if (!HAS_LLC(i915) && !HAS_SNOOP(i915))
                        return -ENODEV;
 
                level = I915_CACHE_LLC;
                break;
        case I915_CACHING_DISPLAY:
-               level = HAS_WT(dev_priv) ? I915_CACHE_WT : I915_CACHE_NONE;
+               level = HAS_WT(i915) ? I915_CACHE_WT : I915_CACHE_NONE;
                break;
        default:
                return -EINVAL;
        }
 
-       intel_runtime_pm_get(dev_priv);
-
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
-               goto rpm_put;
+               return ret;
 
        obj = i915_gem_object_lookup(file, args->handle);
        if (!obj) {
@@ -3497,13 +3535,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
        }
 
        ret = i915_gem_object_set_cache_level(obj, level);
-
        i915_gem_object_put(obj);
 unlock:
        mutex_unlock(&dev->struct_mutex);
-rpm_put:
-       intel_runtime_pm_put(dev_priv);
-
        return ret;
 }
 
@@ -4108,6 +4142,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
        int i;
 
        INIT_LIST_HEAD(&obj->global_list);
+       INIT_LIST_HEAD(&obj->userfault_link);
        for (i = 0; i < I915_NUM_ENGINES; i++)
                init_request_active(&obj->last_read[i],
                                    i915_gem_object_retire__read);
@@ -4640,6 +4675,7 @@ i915_gem_load_init(struct drm_device *dev)
        INIT_LIST_HEAD(&dev_priv->mm.unbound_list);
        INIT_LIST_HEAD(&dev_priv->mm.bound_list);
        INIT_LIST_HEAD(&dev_priv->mm.fence_list);
+       INIT_LIST_HEAD(&dev_priv->mm.userfault_list);
        INIT_DELAYED_WORK(&dev_priv->gt.retire_work,
                          i915_gem_retire_work_handler);
        INIT_DELAYED_WORK(&dev_priv->gt.idle_work,
index b5e9e669f50f7e6c7fe6d79fb6292c4c319f20b5..a934f372c5cef40ec2414b6bde7f1e30e85d45e5 100644 (file)
@@ -56,7 +56,7 @@ mark_free(struct i915_vma *vma, unsigned int flags, struct list_head *unwind)
        if (WARN_ON(!list_empty(&vma->exec_list)))
                return false;
 
-       if (flags & PIN_NONFAULT && vma->obj->fault_mappable)
+       if (flags & PIN_NONFAULT && !list_empty(&vma->obj->userfault_link))
                return false;
 
        list_add(&vma->exec_list, unwind);
index a6daf2deab74c96e66ba4952505b2ef8e0c51a82..3c5a8082cac3bfc21a9ef3cc2bf779c9c979717f 100644 (file)
@@ -343,6 +343,9 @@ i915_vma_get_fence(struct i915_vma *vma)
        struct drm_i915_fence_reg *fence;
        struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL;
 
+       /* Note that we revoke fences on runtime suspend. Therefore the user
+        * must keep the device awake whilst using the fence.
+        */
        assert_rpm_wakelock_held(to_i915(vma->vm->dev));
 
        /* Just update our place in the LRU if our fence is getting reused. */
@@ -368,19 +371,14 @@ i915_vma_get_fence(struct i915_vma *vma)
  * @dev: DRM device
  *
  * Restore the hw fence state to match the software tracking again, to be called
- * after a gpu reset and on resume.
+ * after a gpu reset and on resume. Note that on runtime suspend we only cancel
+ * the fences, to be reacquired by the user later.
  */
 void i915_gem_restore_fences(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
        int i;
 
-       /* Note that this may be called outside of struct_mutex, by
-        * runtime suspend/resume. The barrier we require is enforced by
-        * rpm itself - all access to fences/GTT are only within an rpm
-        * wakeref, and to acquire that wakeref you must pass through here.
-        */
-
        for (i = 0; i < dev_priv->num_fence_regs; i++) {
                struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];
                struct i915_vma *vma = reg->vma;
@@ -391,7 +389,7 @@ void i915_gem_restore_fences(struct drm_device *dev)
                 */
                if (vma && !i915_gem_object_is_tiled(vma->obj)) {
                        GEM_BUG_ON(!reg->dirty);
-                       GEM_BUG_ON(vma->obj->fault_mappable);
+                       GEM_BUG_ON(!list_empty(&vma->obj->userfault_link));
 
                        list_move(&reg->link, &dev_priv->mm.fence_list);
                        vma->fence = NULL;
index 062fb0ad75dac88e9642a8fd4bc567ed3baacb60..947d5ad51fb7b2b22f3c950c9fb77399bc4b8581 100644 (file)
@@ -2395,16 +2395,11 @@ static void gen8_ggtt_insert_page(struct i915_address_space *vm,
        gen8_pte_t __iomem *pte =
                (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
                (offset >> PAGE_SHIFT);
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        gen8_set_pte(pte, gen8_pte_encode(addr, level));
 
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2418,11 +2413,8 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
        gen8_pte_t __iomem *gtt_entries;
        gen8_pte_t gtt_entry;
        dma_addr_t addr;
-       int rpm_atomic_seq;
        int i = 0;
 
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
        gtt_entries = (gen8_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
 
        for_each_sgt_dma(addr, sgt_iter, st) {
@@ -2446,8 +2438,6 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 struct insert_entries {
@@ -2486,16 +2476,11 @@ static void gen6_ggtt_insert_page(struct i915_address_space *vm,
        gen6_pte_t __iomem *pte =
                (gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
                (offset >> PAGE_SHIFT);
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        iowrite32(vm->pte_encode(addr, level, flags), pte);
 
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 /*
@@ -2515,11 +2500,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
        gen6_pte_t __iomem *gtt_entries;
        gen6_pte_t gtt_entry;
        dma_addr_t addr;
-       int rpm_atomic_seq;
        int i = 0;
 
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
        gtt_entries = (gen6_pte_t __iomem *)ggtt->gsm + (start >> PAGE_SHIFT);
 
        for_each_sgt_dma(addr, sgt_iter, st) {
@@ -2542,8 +2524,6 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
         */
        I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
        POSTING_READ(GFX_FLSH_CNTL_GEN6);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void nop_clear_range(struct i915_address_space *vm,
@@ -2554,7 +2534,6 @@ static void nop_clear_range(struct i915_address_space *vm,
 static void gen8_ggtt_clear_range(struct i915_address_space *vm,
                                  uint64_t start, uint64_t length)
 {
-       struct drm_i915_private *dev_priv = to_i915(vm->dev);
        struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
        unsigned first_entry = start >> PAGE_SHIFT;
        unsigned num_entries = length >> PAGE_SHIFT;
@@ -2562,9 +2541,6 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
                (gen8_pte_t __iomem *)ggtt->gsm + first_entry;
        const int max_entries = ggtt_total_entries(ggtt) - first_entry;
        int i;
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        if (WARN(num_entries > max_entries,
                 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2576,15 +2552,12 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
        for (i = 0; i < num_entries; i++)
                gen8_set_pte(&gtt_base[i], scratch_pte);
        readl(gtt_base);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void gen6_ggtt_clear_range(struct i915_address_space *vm,
                                  uint64_t start,
                                  uint64_t length)
 {
-       struct drm_i915_private *dev_priv = to_i915(vm->dev);
        struct i915_ggtt *ggtt = i915_vm_to_ggtt(vm);
        unsigned first_entry = start >> PAGE_SHIFT;
        unsigned num_entries = length >> PAGE_SHIFT;
@@ -2592,9 +2565,6 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
                (gen6_pte_t __iomem *)ggtt->gsm + first_entry;
        const int max_entries = ggtt_total_entries(ggtt) - first_entry;
        int i;
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        if (WARN(num_entries > max_entries,
                 "First entry = %d; Num entries = %d (max=%d)\n",
@@ -2607,8 +2577,6 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
        for (i = 0; i < num_entries; i++)
                iowrite32(scratch_pte, &gtt_base[i]);
        readl(gtt_base);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void i915_ggtt_insert_page(struct i915_address_space *vm,
@@ -2617,16 +2585,10 @@ static void i915_ggtt_insert_page(struct i915_address_space *vm,
                                  enum i915_cache_level cache_level,
                                  u32 unused)
 {
-       struct drm_i915_private *dev_priv = to_i915(vm->dev);
        unsigned int flags = (cache_level == I915_CACHE_NONE) ?
                AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        intel_gtt_insert_page(addr, offset >> PAGE_SHIFT, flags);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
 }
 
 static void i915_ggtt_insert_entries(struct i915_address_space *vm,
@@ -2634,39 +2596,25 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
                                     uint64_t start,
                                     enum i915_cache_level cache_level, u32 unused)
 {
-       struct drm_i915_private *dev_priv = to_i915(vm->dev);
        unsigned int flags = (cache_level == I915_CACHE_NONE) ?
                AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
 
        intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
 
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
-
 }
 
 static void i915_ggtt_clear_range(struct i915_address_space *vm,
                                  uint64_t start,
                                  uint64_t length)
 {
-       struct drm_i915_private *dev_priv = to_i915(vm->dev);
-       unsigned first_entry = start >> PAGE_SHIFT;
-       unsigned num_entries = length >> PAGE_SHIFT;
-       int rpm_atomic_seq;
-
-       rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
-
-       intel_gtt_clear_range(first_entry, num_entries);
-
-       assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
+       intel_gtt_clear_range(start >> PAGE_SHIFT, length >> PAGE_SHIFT);
 }
 
 static int ggtt_bind_vma(struct i915_vma *vma,
                         enum i915_cache_level cache_level,
                         u32 flags)
 {
+       struct drm_i915_private *i915 = to_i915(vma->vm->dev);
        struct drm_i915_gem_object *obj = vma->obj;
        u32 pte_flags = 0;
        int ret;
@@ -2679,8 +2627,10 @@ static int ggtt_bind_vma(struct i915_vma *vma,
        if (obj->gt_ro)
                pte_flags |= PTE_READ_ONLY;
 
+       intel_runtime_pm_get(i915);
        vma->vm->insert_entries(vma->vm, vma->pages, vma->node.start,
                                cache_level, pte_flags);
+       intel_runtime_pm_put(i915);
 
        /*
         * Without aliasing PPGTT there's no difference between
@@ -2696,6 +2646,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
                                 enum i915_cache_level cache_level,
                                 u32 flags)
 {
+       struct drm_i915_private *i915 = to_i915(vma->vm->dev);
        u32 pte_flags;
        int ret;
 
@@ -2710,14 +2661,15 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 
 
        if (flags & I915_VMA_GLOBAL_BIND) {
+               intel_runtime_pm_get(i915);
                vma->vm->insert_entries(vma->vm,
                                        vma->pages, vma->node.start,
                                        cache_level, pte_flags);
+               intel_runtime_pm_put(i915);
        }
 
        if (flags & I915_VMA_LOCAL_BIND) {
-               struct i915_hw_ppgtt *appgtt =
-                       to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+               struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
                appgtt->base.insert_entries(&appgtt->base,
                                            vma->pages, vma->node.start,
                                            cache_level, pte_flags);
@@ -2728,12 +2680,16 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma,
 
 static void ggtt_unbind_vma(struct i915_vma *vma)
 {
-       struct i915_hw_ppgtt *appgtt = to_i915(vma->vm->dev)->mm.aliasing_ppgtt;
+       struct drm_i915_private *i915 = to_i915(vma->vm->dev);
+       struct i915_hw_ppgtt *appgtt = i915->mm.aliasing_ppgtt;
        const u64 size = min(vma->size, vma->node.size);
 
-       if (vma->flags & I915_VMA_GLOBAL_BIND)
+       if (vma->flags & I915_VMA_GLOBAL_BIND) {
+               intel_runtime_pm_get(i915);
                vma->vm->clear_range(vma->vm,
                                     vma->node.start, size);
+               intel_runtime_pm_put(i915);
+       }
 
        if (vma->flags & I915_VMA_LOCAL_BIND && appgtt)
                appgtt->base.clear_range(&appgtt->base,
index c21bc0068d20c60be79c69c1064f1d6f2c67d6de..71f80d2a487c7f799ecef9fe06652aa8fa9acf24 100644 (file)
@@ -205,8 +205,6 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
-       intel_runtime_pm_get(dev_priv);
-
        mutex_lock(&dev->struct_mutex);
        if (obj->pin_display || obj->framebuffer_references) {
                err = -EBUSY;
@@ -302,8 +300,6 @@ err:
        i915_gem_object_put(obj);
        mutex_unlock(&dev->struct_mutex);
 
-       intel_runtime_pm_put(dev_priv);
-
        return err;
 }
 
index 00efaa13974d93295275be42a06350afde86270e..a9be3f037f43c37eb0910575cf4edb323589fd2e 100644 (file)
@@ -2188,8 +2188,9 @@ enum skl_disp_power_wells {
 #define FBC_FENCE_OFF          _MMIO(0x3218) /* BSpec typo has 321Bh */
 #define FBC_TAG(i)             _MMIO(0x3300 + (i) * 4)
 
-#define FBC_STATUS2            _MMIO(0x43214)
-#define  FBC_COMPRESSION_MASK  0x7ff
+#define FBC_STATUS2                    _MMIO(0x43214)
+#define  IVB_FBC_COMPRESSION_MASK      0x7ff
+#define  BDW_FBC_COMPRESSION_MASK      0xfff
 
 #define FBC_LL_SIZE            (1536)
 
index 6f8f6ec5b27a34a7c28d1b9f46719cd79c9c0706..2a5a7c2868dec914ac33d356d4ac1cc2ef44f843 100644 (file)
@@ -14406,7 +14406,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)
 
        for_each_plane_in_state(state, plane, plane_state, i) {
                struct intel_plane_state *intel_plane_state =
-                       to_intel_plane_state(plane_state);
+                       to_intel_plane_state(plane->state);
 
                if (!intel_plane_state->wait_req)
                        continue;
index 4e90b0760f3f9c45a1338adfac3a016261f84a56..16b33f59dd6f0ce42fccadf3263dcb492bcb8077 100644 (file)
@@ -1655,23 +1655,6 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv)
                DRM_DEBUG_DRIVER("RPM wakelock ref not held during HW access");
 }
 
-static inline int
-assert_rpm_atomic_begin(struct drm_i915_private *dev_priv)
-{
-       int seq = atomic_read(&dev_priv->pm.atomic_seq);
-
-       assert_rpm_wakelock_held(dev_priv);
-
-       return seq;
-}
-
-static inline void
-assert_rpm_atomic_end(struct drm_i915_private *dev_priv, int begin_seq)
-{
-       WARN_ONCE(atomic_read(&dev_priv->pm.atomic_seq) != begin_seq,
-                 "HW access outside of RPM atomic section\n");
-}
-
 /**
  * disable_rpm_wakeref_asserts - disable the RPM assert checks
  * @dev_priv: i915 device instance
index 49048d9d7895153b2cea961e03de07b147a19f1f..cbe2ebda4c4092e19bc96985882c539602a1ff46 100644 (file)
@@ -104,8 +104,10 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,
        int lines;
 
        intel_fbc_get_plane_source_size(cache, NULL, &lines);
-       if (INTEL_INFO(dev_priv)->gen >= 7)
+       if (INTEL_GEN(dev_priv) == 7)
                lines = min(lines, 2048);
+       else if (INTEL_GEN(dev_priv) >= 8)
+               lines = min(lines, 2560);
 
        /* Hardware needs the full buffer stride, not just the active area. */
        return lines * cache->fb.stride;
index 560fc7af8267a07d0009aff5ba6f4acdf671fb87..9e0e8741253e8721785f7403278fc07660269bb9 100644 (file)
@@ -8043,5 +8043,4 @@ void intel_pm_setup(struct drm_device *dev)
 
        dev_priv->pm.suspended = false;
        atomic_set(&dev_priv->pm.wakeref_count, 0);
-       atomic_set(&dev_priv->pm.atomic_seq, 0);
 }
index ee56a8756c07753c8a5770b3a1c303e5eef1c531..82edba2f35899b669fbd6d40919de0cb8c4f5547 100644 (file)
@@ -2736,8 +2736,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv)
        struct device *kdev = &pdev->dev;
 
        assert_rpm_wakelock_held(dev_priv);
-       if (atomic_dec_and_test(&dev_priv->pm.wakeref_count))
-               atomic_inc(&dev_priv->pm.atomic_seq);
+       atomic_dec(&dev_priv->pm.wakeref_count);
 
        pm_runtime_mark_last_busy(kdev);
        pm_runtime_put_autosuspend(kdev);