These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / i915 / i915_gem_render_state.c
index 521548a..5026a62 100644 (file)
@@ -73,6 +73,24 @@ free_gem:
        return ret;
 }
 
+/*
+ * Macro to add commands to auxiliary batch.
+ * This macro only checks for page overflow before inserting the commands,
+ * this is sufficient as the null state generator makes the final batch
+ * with two passes to build command and state separately. At this point
+ * the size of both are known and it compacts them by relocating the state
+ * right after the commands taking care of aligment so we should sufficient
+ * space below them for adding new commands.
+ */
+#define OUT_BATCH(batch, i, val)                               \
+       do {                                                    \
+               if (WARN_ON((i) >= PAGE_SIZE / sizeof(u32))) {  \
+                       ret = -ENOSPC;                          \
+                       goto err_out;                           \
+               }                                               \
+               (batch)[(i)++] = (val);                         \
+       } while(0)
+
 static int render_state_setup(struct render_state *so)
 {
        const struct intel_renderstate_rodata *rodata = so->rodata;
@@ -96,8 +114,10 @@ static int render_state_setup(struct render_state *so)
                        s = lower_32_bits(r);
                        if (so->gen >= 8) {
                                if (i + 1 >= rodata->batch_items ||
-                                   rodata->batch[i + 1] != 0)
-                                       return -EINVAL;
+                                   rodata->batch[i + 1] != 0) {
+                                       ret = -EINVAL;
+                                       goto err_out;
+                               }
 
                                d[i++] = s;
                                s = upper_32_bits(r);
@@ -108,6 +128,21 @@ static int render_state_setup(struct render_state *so)
 
                d[i++] = s;
        }
+
+       while (i % CACHELINE_DWORDS)
+               OUT_BATCH(d, i, MI_NOOP);
+
+       so->aux_batch_offset = i * sizeof(u32);
+
+       OUT_BATCH(d, i, MI_BATCH_BUFFER_END);
+       so->aux_batch_size = (i * sizeof(u32)) - so->aux_batch_offset;
+
+       /*
+        * Since we are sending length, we need to strictly conform to
+        * all requirements. For Gen2 this must be a multiple of 8.
+        */
+       so->aux_batch_size = ALIGN(so->aux_batch_size, 8);
+
        kunmap(page);
 
        ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
@@ -120,8 +155,14 @@ static int render_state_setup(struct render_state *so)
        }
 
        return 0;
+
+err_out:
+       kunmap(page);
+       return ret;
 }
 
+#undef OUT_BATCH
+
 void i915_gem_render_state_fini(struct render_state *so)
 {
        i915_gem_object_ggtt_unpin(so->obj);
@@ -152,29 +193,36 @@ int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
        return 0;
 }
 
-int i915_gem_render_state_init(struct intel_engine_cs *ring)
+int i915_gem_render_state_init(struct drm_i915_gem_request *req)
 {
        struct render_state so;
        int ret;
 
-       ret = i915_gem_render_state_prepare(ring, &so);
+       ret = i915_gem_render_state_prepare(req->ring, &so);
        if (ret)
                return ret;
 
        if (so.rodata == NULL)
                return 0;
 
-       ret = ring->dispatch_execbuffer(ring,
-                                       so.ggtt_offset,
-                                       so.rodata->batch_items * 4,
-                                       I915_DISPATCH_SECURE);
+       ret = req->ring->dispatch_execbuffer(req, so.ggtt_offset,
+                                            so.rodata->batch_items * 4,
+                                            I915_DISPATCH_SECURE);
        if (ret)
                goto out;
 
-       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), ring);
+       if (so.aux_batch_size > 8) {
+               ret = req->ring->dispatch_execbuffer(req,
+                                                    (so.ggtt_offset +
+                                                     so.aux_batch_offset),
+                                                    so.aux_batch_size,
+                                                    I915_DISPATCH_SECURE);
+               if (ret)
+                       goto out;
+       }
+
+       i915_vma_move_to_active(i915_gem_obj_to_ggtt(so.obj), req);
 
-       ret = __i915_add_request(ring, NULL, so.obj);
-       /* __i915_add_request moves object to inactive if it fails */
 out:
        i915_gem_render_state_fini(&so);
        return ret;