]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/i915/i915_gem.c
drm/i915: mark a newly-created GEM object dirty when filled with data
[karo-tx-linux.git] / drivers / gpu / drm / i915 / i915_gem.c
index 001c47693fec3436cf633ec19f0c1aa8e7ce6f8a..47f6a8244151ac0f329290edf3a1e027b4e78cc4 100644 (file)
@@ -2216,9 +2216,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
         * Fail silently without starting the shrinker
         */
        mapping = file_inode(obj->base.filp)->i_mapping;
-       gfp = mapping_gfp_mask(mapping);
-       gfp |= __GFP_NORETRY | __GFP_NOWARN | __GFP_NO_KSWAPD;
-       gfp &= ~(__GFP_IO | __GFP_WAIT);
+       gfp = mapping_gfp_constraint(mapping, ~(__GFP_IO | __GFP_RECLAIM));
+       gfp |= __GFP_NORETRY | __GFP_NOWARN;
        sg = st->sgl;
        st->nents = 0;
        for (i = 0; i < page_count; i++) {
@@ -2758,20 +2757,13 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
 
        if (i915.enable_execlists) {
                spin_lock_irq(&ring->execlist_lock);
-               while (!list_empty(&ring->execlist_queue)) {
-                       struct drm_i915_gem_request *submit_req;
 
-                       submit_req = list_first_entry(&ring->execlist_queue,
-                                       struct drm_i915_gem_request,
-                                       execlist_link);
-                       list_del(&submit_req->execlist_link);
+               /* list_splice_tail_init checks for empty lists */
+               list_splice_tail_init(&ring->execlist_queue,
+                                     &ring->execlist_retired_req_list);
 
-                       if (submit_req->ctx != ring->default_context)
-                               intel_lr_context_unpin(submit_req);
-
-                       i915_gem_request_unreference(submit_req);
-               }
                spin_unlock_irq(&ring->execlist_lock);
+               intel_execlists_retire_requests(ring);
        }
 
        /*
@@ -3066,7 +3058,7 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
                if (ret == 0)
                        ret = __i915_wait_request(req[i], reset_counter, true,
                                                  args->timeout_ns > 0 ? &args->timeout_ns : NULL,
-                                                 file->driver_priv);
+                                                 to_rps_client(file));
                i915_gem_request_unreference__unlocked(req[i]);
        }
        return ret;
@@ -3469,30 +3461,50 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
        if (IS_ERR(vma))
                goto err_unpin;
 
-       if (flags & PIN_HIGH) {
-               search_flag = DRM_MM_SEARCH_BELOW;
-               alloc_flag = DRM_MM_CREATE_TOP;
+       if (flags & PIN_OFFSET_FIXED) {
+               uint64_t offset = flags & PIN_OFFSET_MASK;
+
+               if (offset & (alignment - 1) || offset + size > end) {
+                       ret = -EINVAL;
+                       goto err_free_vma;
+               }
+               vma->node.start = offset;
+               vma->node.size = size;
+               vma->node.color = obj->cache_level;
+               ret = drm_mm_reserve_node(&vm->mm, &vma->node);
+               if (ret) {
+                       ret = i915_gem_evict_for_vma(vma);
+                       if (ret == 0)
+                               ret = drm_mm_reserve_node(&vm->mm, &vma->node);
+               }
+               if (ret)
+                       goto err_free_vma;
        } else {
-               search_flag = DRM_MM_SEARCH_DEFAULT;
-               alloc_flag = DRM_MM_CREATE_DEFAULT;
-       }
+               if (flags & PIN_HIGH) {
+                       search_flag = DRM_MM_SEARCH_BELOW;
+                       alloc_flag = DRM_MM_CREATE_TOP;
+               } else {
+                       search_flag = DRM_MM_SEARCH_DEFAULT;
+                       alloc_flag = DRM_MM_CREATE_DEFAULT;
+               }
 
 search_free:
-       ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
-                                                 size, alignment,
-                                                 obj->cache_level,
-                                                 start, end,
-                                                 search_flag,
-                                                 alloc_flag);
-       if (ret) {
-               ret = i915_gem_evict_something(dev, vm, size, alignment,
-                                              obj->cache_level,
-                                              start, end,
-                                              flags);
-               if (ret == 0)
-                       goto search_free;
+               ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
+                                                         size, alignment,
+                                                         obj->cache_level,
+                                                         start, end,
+                                                         search_flag,
+                                                         alloc_flag);
+               if (ret) {
+                       ret = i915_gem_evict_something(dev, vm, size, alignment,
+                                                      obj->cache_level,
+                                                      start, end,
+                                                      flags);
+                       if (ret == 0)
+                               goto search_free;
 
-               goto err_free_vma;
+                       goto err_free_vma;
+               }
        }
        if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) {
                ret = -EINVAL;
@@ -3829,6 +3841,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 = dev->dev_private;
        struct drm_i915_gem_caching *args = data;
        struct drm_i915_gem_object *obj;
        enum i915_cache_level level;
@@ -3857,9 +3870,11 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
                return -EINVAL;
        }
 
+       intel_runtime_pm_get(dev_priv);
+
        ret = i915_mutex_lock_interruptible(dev);
        if (ret)
-               return ret;
+               goto rpm_put;
 
        obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
        if (&obj->base == NULL) {
@@ -3872,6 +3887,9 @@ int i915_gem_set_caching_ioctl(struct drm_device *dev, void *data,
        drm_gem_object_unreference(&obj->base);
 unlock:
        mutex_unlock(&dev->struct_mutex);
+rpm_put:
+       intel_runtime_pm_put(dev_priv);
+
        return ret;
 }
 
@@ -4077,6 +4095,10 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
            vma->node.start < (flags & PIN_OFFSET_MASK))
                return true;
 
+       if (flags & PIN_OFFSET_FIXED &&
+           vma->node.start != (flags & PIN_OFFSET_MASK))
+               return true;
+
        return false;
 }
 
@@ -4591,7 +4613,7 @@ int i915_gem_l3_remap(struct drm_i915_gem_request *req, int slice)
         */
        for (i = 0; i < GEN7_L3LOG_SIZE / 4; i++) {
                intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-               intel_ring_emit(ring, GEN7_L3LOG(slice, i));
+               intel_ring_emit_reg(ring, GEN7_L3LOG(slice, i));
                intel_ring_emit(ring, remap_info[i]);
        }
 
@@ -4825,14 +4847,6 @@ int i915_gem_init(struct drm_device *dev)
 
        mutex_lock(&dev->struct_mutex);
 
-       if (IS_VALLEYVIEW(dev)) {
-               /* VLVA0 (potential hack), BIOS isn't actually waking us */
-               I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
-               if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
-                             VLV_GTLC_ALLOWWAKEACK), 10))
-                       DRM_DEBUG_DRIVER("allow wake ack timed out\n");
-       }
-
        if (!i915.enable_execlists) {
                dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
                dev_priv->gt.init_rings = i915_gem_init_rings;
@@ -4950,7 +4964,7 @@ i915_gem_load(struct drm_device *dev)
 
        dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
 
-       if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
+       if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
                dev_priv->num_fence_regs = 32;
        else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
                dev_priv->num_fence_regs = 16;
@@ -5171,6 +5185,21 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj)
        return false;
 }
 
+/* Like i915_gem_object_get_page(), but mark the returned page dirty */
+struct page *
+i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
+{
+       struct page *page;
+
+       /* Only default objects have per-page dirty tracking */
+       if (WARN_ON(obj->ops != &i915_gem_object_ops))
+               return NULL;
+
+       page = i915_gem_object_get_page(obj, n);
+       set_page_dirty(page);
+       return page;
+}
+
 /* Allocate a new GEM object and fill it with the supplied data */
 struct drm_i915_gem_object *
 i915_gem_object_create_from_data(struct drm_device *dev,
@@ -5196,6 +5225,7 @@ i915_gem_object_create_from_data(struct drm_device *dev,
        i915_gem_object_pin_pages(obj);
        sg = obj->pages;
        bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
+       obj->dirty = 1;         /* Backing store is now out of date */
        i915_gem_object_unpin_pages(obj);
 
        if (WARN_ON(bytes != size)) {