On Thu, Jul 24, 2014 at 05:04:33PM +0100, Thomas Daniel wrote: > From: Oscar Mateo <oscar.mateo@xxxxxxxxx> > > This is what i915_gem_do_execbuffer calls when it wants to execute some > worload in an Execlists world. > > v2: Check arguments before doing stuff in intel_execlists_submission. Also, > get rel_constants parsing right. > > Signed-off-by: Oscar Mateo <oscar.mateo@xxxxxxxxx> > --- > drivers/gpu/drm/i915/i915_drv.h | 6 ++ > drivers/gpu/drm/i915/i915_gem_execbuffer.c | 4 +- > drivers/gpu/drm/i915/intel_lrc.c | 130 +++++++++++++++++++++++++++- > 3 files changed, 137 insertions(+), 3 deletions(-) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 1caed52..4303e2c 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -2239,6 +2239,12 @@ int i915_gem_set_domain_ioctl(struct drm_device *dev, void *data, > struct drm_file *file_priv); > int i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data, > struct drm_file *file_priv); > +void i915_gem_execbuffer_move_to_active(struct list_head *vmas, > + struct intel_engine_cs *ring); > +void i915_gem_execbuffer_retire_commands(struct drm_device *dev, > + struct drm_file *file, > + struct intel_engine_cs *ring, > + struct drm_i915_gem_object *obj); > int i915_gem_ringbuffer_submission(struct drm_device *dev, > struct drm_file *file, > struct intel_engine_cs *ring, > diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c > index 8c63d79..cae7df8 100644 > --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c > +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c > @@ -962,7 +962,7 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file, > return ctx; > } > > -static void > +void > i915_gem_execbuffer_move_to_active(struct list_head *vmas, > struct intel_engine_cs *ring) > { > @@ -994,7 +994,7 @@ i915_gem_execbuffer_move_to_active(struct list_head *vmas, > } > } > > -static void > +void > i915_gem_execbuffer_retire_commands(struct drm_device *dev, > struct drm_file *file, > struct intel_engine_cs *ring, > diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c > index 55ee8dd..cd834b3 100644 > --- a/drivers/gpu/drm/i915/intel_lrc.c > +++ b/drivers/gpu/drm/i915/intel_lrc.c > @@ -89,6 +89,57 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists > return 0; > } > > +static int logical_ring_invalidate_all_caches(struct intel_ringbuffer *ringbuf) > +{ > + struct intel_engine_cs *ring = ringbuf->ring; > + uint32_t flush_domains; > + int ret; > + > + flush_domains = 0; > + if (ring->gpu_caches_dirty) > + flush_domains = I915_GEM_GPU_DOMAINS; > + > + ret = ring->emit_flush(ringbuf, I915_GEM_GPU_DOMAINS, flush_domains); > + if (ret) > + return ret; > + > + ring->gpu_caches_dirty = false; > + return 0; > +} > + > +static int execlists_move_to_gpu(struct intel_ringbuffer *ringbuf, > + struct list_head *vmas) > +{ > + struct intel_engine_cs *ring = ringbuf->ring; > + struct i915_vma *vma; > + uint32_t flush_domains = 0; > + bool flush_chipset = false; > + int ret; > + > + list_for_each_entry(vma, vmas, exec_list) { > + struct drm_i915_gem_object *obj = vma->obj; > + ret = i915_gem_object_sync(obj, ring); > + if (ret) > + return ret; > + > + if (obj->base.write_domain & I915_GEM_DOMAIN_CPU) > + flush_chipset |= i915_gem_clflush_object(obj, false); > + > + flush_domains |= obj->base.write_domain; > + } > + > + if (flush_chipset) > + i915_gem_chipset_flush(ring->dev); chipset flush is gen5 and earlier only. I'll ditch it. > + > + if (flush_domains & I915_GEM_DOMAIN_GTT) > + wmb(); > + > + /* Unconditionally invalidate gpu caches and ensure that we do flush > + * any residual writes from the previous batch. > + */ > + return logical_ring_invalidate_all_caches(ringbuf); > +} > + > int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, > struct intel_engine_cs *ring, > struct intel_context *ctx, > @@ -97,7 +148,84 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, > struct drm_i915_gem_object *batch_obj, > u64 exec_start, u32 flags) > { > - /* TODO */ > + struct drm_i915_private *dev_priv = dev->dev_private; > + struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; > + int instp_mode; > + u32 instp_mask; > + int ret; > + > + instp_mode = args->flags & I915_EXEC_CONSTANTS_MASK; > + instp_mask = I915_EXEC_CONSTANTS_MASK; > + switch (instp_mode) { > + case I915_EXEC_CONSTANTS_REL_GENERAL: > + case I915_EXEC_CONSTANTS_ABSOLUTE: > + case I915_EXEC_CONSTANTS_REL_SURFACE: > + if (instp_mode != 0 && ring != &dev_priv->ring[RCS]) { > + DRM_DEBUG("non-0 rel constants mode on non-RCS\n"); > + return -EINVAL; > + } > + > + if (instp_mode != dev_priv->relative_constants_mode) { > + if (instp_mode == I915_EXEC_CONSTANTS_REL_SURFACE) { > + DRM_DEBUG("rel surface constants mode invalid on gen5+\n"); > + return -EINVAL; > + } > + > + /* The HW changed the meaning on this bit on gen6 */ > + instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE; > + } > + break; > + default: > + DRM_DEBUG("execbuf with unknown constants: %d\n", instp_mode); > + return -EINVAL; > + } > + > + if (args->num_cliprects != 0) { > + DRM_DEBUG("clip rectangles are only valid on pre-gen5\n"); > + return -EINVAL; > + } else { > + if (args->DR4 == 0xffffffff) { > + DRM_DEBUG("UXA submitting garbage DR4, fixing up\n"); > + args->DR4 = 0; > + } > + > + if (args->DR1 || args->DR4 || args->cliprects_ptr) { > + DRM_DEBUG("0 cliprects but dirt in cliprects fields\n"); > + return -EINVAL; > + } > + } Yay for all the legacy nonsense that we can ditch here ;-) -Daniel > + > + if (args->flags & I915_EXEC_GEN7_SOL_RESET) { > + DRM_DEBUG("sol reset is gen7 only\n"); > + return -EINVAL; > + } > + > + ret = execlists_move_to_gpu(ringbuf, vmas); > + if (ret) > + return ret; > + > + if (ring == &dev_priv->ring[RCS] && > + instp_mode != dev_priv->relative_constants_mode) { > + ret = intel_logical_ring_begin(ringbuf, 4); > + if (ret) > + return ret; > + > + intel_logical_ring_emit(ringbuf, MI_NOOP); > + intel_logical_ring_emit(ringbuf, MI_LOAD_REGISTER_IMM(1)); > + intel_logical_ring_emit(ringbuf, INSTPM); > + intel_logical_ring_emit(ringbuf, instp_mask << 16 | instp_mode); > + intel_logical_ring_advance(ringbuf); > + > + dev_priv->relative_constants_mode = instp_mode; > + } > + > + ret = ring->emit_bb_start(ringbuf, exec_start, flags); > + if (ret) > + return ret; > + > + i915_gem_execbuffer_move_to_active(vmas, ring); > + i915_gem_execbuffer_retire_commands(dev, file, ring, batch_obj); > + > return 0; > } > > -- > 1.7.9.5 > > _______________________________________________ > Intel-gfx mailing list > Intel-gfx@xxxxxxxxxxxxxxxxxxxxx > http://lists.freedesktop.org/mailman/listinfo/intel-gfx -- Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/intel-gfx