From: Daniel Vetter <daniel@ffwll.ch>
To: Ben Widawsky <ben@bwidawsk.net>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 05/18] drm/i915: context switch implementation
Date: Thu, 29 Mar 2012 20:24:11 +0200 [thread overview]
Message-ID: <20120329182411.GA27737@phenom.ffwll.local> (raw)
In-Reply-To: <1332103198-25852-6-git-send-email-ben@bwidawsk.net>
On Sun, Mar 18, 2012 at 01:39:45PM -0700, Ben Widawsky wrote:
> Implement the context switch code as well as the interfaces to do the
> context switch. This patch also doesn't match 1:1 with the RFC patches.
> The main difference is that from Daniel's responses the last context
> object is now stored instead of the last context. This aids in allows us
> to free the context data structure, and context object independently.
>
> There is room for optimization: this code will pin the context object
> until the next context is active. The optimal way to do it is to
> actually pin the object, move it to the active list, do the context
> switch, and then unpin it. This allows the eviction code to actually
> evict the context object if needed.
>
> The context switch code is missing workarounds, they will be implemented
> in future patches.
>
> Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Ok, I've looked at the use-sites of context_get and all this refcounting
and noticed that:
- we always hold dev->struct_mutex
- we always drop the acquired reference to the context structure in the
same function without dropping struct_mutex in between.
So we don't seem to require any reference counting on these (and
additional locking on the idr). Additionally the idr locking seems to give
us a false sense of security because afaics the locking/refcounting would
be broken when we would _not_ hold struct_mutex.
So can we just rip this out or do we need this (in which case it needs
some more work imo)?
-Daniel
> ---
> drivers/gpu/drm/i915/i915_drv.h | 5 ++
> drivers/gpu/drm/i915/i915_gem_context.c | 118 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/i915/intel_ringbuffer.c | 26 +++++++
> drivers/gpu/drm/i915/intel_ringbuffer.h | 5 ++
> 4 files changed, 153 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index f458a8f..c6c2ada 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1303,10 +1303,15 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj,
> enum i915_cache_level cache_level);
>
> /* i915_gem_context.c */
> +#define I915_CONTEXT_FORCED_SWITCH (1<<0)
> +#define I915_CONTEXT_INITIAL_SWITCH (1<<1)
> void i915_gem_context_load(struct drm_device *dev);
> void i915_gem_context_unload(struct drm_device *dev);
> void i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
> void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
> +int i915_switch_context(struct intel_ring_buffer *ring,
> + struct drm_file *file,
> + int to_id, u32 seqno, u32 flags);
>
> /* i915_gem_gtt.c */
> int __must_check i915_gem_init_aliasing_ppgtt(struct drm_device *dev);
> diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c
> index 321bafd..cc508d5 100644
> --- a/drivers/gpu/drm/i915/i915_gem_context.c
> +++ b/drivers/gpu/drm/i915/i915_gem_context.c
> @@ -262,7 +262,7 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
> mutex_unlock(&dev->struct_mutex);
> }
>
> -static __used struct i915_hw_context *
> +static struct i915_hw_context *
> i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
> {
> struct i915_hw_context *ctx = NULL;
> @@ -279,3 +279,119 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
>
> return ctx;
> }
> +
> +static int do_switch(struct drm_i915_gem_object *from_obj,
> + struct i915_hw_context *to,
> + u32 seqno, u32 flags)
> +{
> + bool initial_switch = (flags & I915_CONTEXT_INITIAL_SWITCH) ? true : false;
> + bool force = (flags & I915_CONTEXT_FORCED_SWITCH) ? true : false;
> + struct intel_ring_buffer *ring = NULL;
> + u32 hw_flags = 0;
> + int ret;
> +
> + BUG_ON(to == NULL);
> + BUG_ON(from_obj != NULL && from_obj->pin_count == 0);
> + BUG_ON((from_obj != NULL && from_obj->context_id < 0) || to->obj->context_id < 0);
> +
> + ret = i915_gem_object_pin(to->obj, CONTEXT_ALIGN, false);
> + if (ret)
> + return ret;
> +
> + if (initial_switch)
> + hw_flags |= MI_RESTORE_INHIBIT;
> + if (force)
> + hw_flags |= MI_FORCE_RESTORE;
> +
> + ring = to->ring;
> + ret = intel_ring_mi_set_context(ring, to, hw_flags);
> + if (ret) {
> + i915_gem_object_unpin(to->obj);
> + return ret;
> + }
> +
> + /* The backing object for the context is done after switching to the
> + * *next* context. Therefore we cannot retire the previous context until
> + * the next context has already started running. In fact, the below code
> + * is a bit suboptimal because the retiring can occur simply after the
> + * MI_SET_CONTEXT instead of when the next seqno has completed.
> + */
> + if (from_obj != NULL) {
> + i915_gem_object_move_to_active(from_obj, ring, seqno);
> + /* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
> + * whole damn pipeline, we don't need to explicitly mark the
> + * object dirty. It should be safe to evict the object at any
> + * point after MI_SET_CONTEXT has finished executing... true as
> + * of GEN7. If not from_obj->dirty=1 would make this safer.
> + */
> + BUG_ON(from_obj->ring != to->ring);
> + }
> +
> + if (from_obj)
> + i915_gem_object_unpin(from_obj);
> +
> + ring->last_context_obj = to->obj;
> +
> + return 0;
> +}
> +
> +/**
> + * i915_switch_context() - perform a GPU context switch.
> + * @ring: ring for which we'll execute the context switch
> + * @file_priv: file_priv associated with the context, may be NULL
> + * @id: context id number
> + * @seqno: sequence number by which the new context will be switched to
> + * @flags:
> + *
> + * This function will perform the context switch to the given context id on the
> + * specified ring. Unfortunately the context switch code doesn't have an
> + * independent way of knowing when the context switch has occurred, so the
> + * caller must notify of us a time by which the context switch has occurred.
> + */
> +int i915_switch_context(struct intel_ring_buffer *ring,
> + struct drm_file *file,
> + int to_id, u32 seqno, u32 flags)
> +{
> + struct drm_i915_private *dev_priv = ring->dev->dev_private;
> + struct drm_i915_file_private *file_priv = NULL;
> + struct i915_hw_context *to;
> + struct drm_i915_gem_object *from_obj = ring->last_context_obj;
> + int ret;
> +
> + if (dev_priv->hw_contexts_disabled)
> + return 0;
> +
> + if (ring != &dev_priv->ring[RCS])
> + return 0;
> +
> + if (file)
> + file_priv = file->driver_priv;
> +
> + if (to_id == DEFAULT_CONTEXT_ID) {
> + to = ring->default_context;
> + kref_get(&to->nref);
> + } else {
> + to = i915_gem_context_get(file_priv, to_id);
> + if (to == NULL)
> + return -EINVAL;
> + }
> + drm_gem_object_reference(&to->obj->base);
> +
> + /* If the object is still on the active list, we can shortcut */
> + if (from_obj == to->obj) {
> + ret = 0;
> + goto out;
> + }
> +
> + ret = do_switch(from_obj, to, seqno, flags);
> + if (ret) {
> + drm_gem_object_unreference(&to->obj->base);
> + goto out;
> + }
> +
> +out:
> + if (from_obj != NULL)
> + drm_gem_object_unreference(&from_obj->base);
> + kref_put(&to->nref, destroy_hw_context);
> + return ret;
> +}
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
> index ca3972f..cd74f86 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.c
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
> @@ -920,6 +920,32 @@ render_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
> return 0;
> }
>
> +int intel_ring_mi_set_context(struct intel_ring_buffer *ring,
> + struct i915_hw_context *new_context,
> + u32 hw_flags)
> +{
> + int ret;
> +
> + ret = intel_ring_begin(ring, 4);
> + if (ret)
> + return ret;
> +
> + intel_ring_emit(ring, MI_NOOP);
> + intel_ring_emit(ring, MI_SET_CONTEXT);
> + intel_ring_emit(ring, new_context->obj->gtt_offset |
> + MI_MM_SPACE_GTT |
> + MI_SAVE_EXT_STATE_EN |
> + MI_RESTORE_EXT_STATE_EN |
> + hw_flags);
> + /* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP */
> + intel_ring_emit(ring, MI_NOOP);
> +
> + intel_ring_advance(ring);
> +
> + return ret;
> +
> +}
> +
> static void cleanup_status_page(struct intel_ring_buffer *ring)
> {
> drm_i915_private_t *dev_priv = ring->dev->dev_private;
> diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
> index 8c9f898..0ed98bb 100644
> --- a/drivers/gpu/drm/i915/intel_ringbuffer.h
> +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
> @@ -121,6 +121,7 @@ struct intel_ring_buffer {
> drm_local_map_t map;
>
> struct i915_hw_context *default_context;
> + struct drm_i915_gem_object *last_context_obj;
>
> void *private;
> };
> @@ -216,6 +217,10 @@ static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno)
> ring->trace_irq_seqno = seqno;
> }
>
> +int intel_ring_mi_set_context(struct intel_ring_buffer *ring,
> + struct i915_hw_context *new_context,
> + u32 hw_flags);
> +
> /* DRI warts */
> int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size);
>
> --
> 1.7.9.4
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Mail: daniel@ffwll.ch
Mobile: +41 (0)79 365 57 48
next prev parent reply other threads:[~2012-03-29 18:23 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-18 20:39 [PATCH 00/18] i915 HW Context Support Ben Widawsky
2012-03-18 20:39 ` [PATCH 01/18] drm/i915: CXT_SIZE register offsets added Ben Widawsky
2012-03-18 20:39 ` [PATCH 02/18] drm/i915: preliminary context support Ben Widawsky
2012-03-28 22:43 ` Daniel Vetter
2012-03-28 22:59 ` Ben Widawsky
2012-03-29 8:43 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 03/18] drm/i915: context basic create & destroy Ben Widawsky
2012-03-18 20:39 ` [PATCH 04/18] drm/i915: add context information to objects Ben Widawsky
2012-03-28 22:36 ` Daniel Vetter
2012-03-29 0:20 ` Ben Widawsky
2012-03-29 8:47 ` Daniel Vetter
2012-03-29 15:57 ` Ben Widawsky
2012-03-18 20:39 ` [PATCH 05/18] drm/i915: context switch implementation Ben Widawsky
2012-03-29 18:24 ` Daniel Vetter [this message]
2012-03-29 18:43 ` Ben Widawsky
2012-03-29 18:49 ` Daniel Vetter
2012-03-30 18:11 ` Ben Widawsky
2012-03-29 18:47 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 06/18] drm/i915: trace events for contexts Ben Widawsky
2012-03-18 20:39 ` [PATCH 07/18] drm/i915: Ivybridge MI_ARB_ON_OFF context w/a Ben Widawsky
2012-03-18 20:39 ` [PATCH 08/18] drm/i915: PIPE_CONTROL_TLB_INVALIDATE Ben Widawsky
2012-03-18 20:39 ` [PATCH 09/18] drm/i915: possibly invalidate TLB before context switch Ben Widawsky
2012-03-29 19:25 ` Daniel Vetter
2012-03-30 18:39 ` Ben Widawsky
2012-03-30 19:01 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 10/18] drm/i915: use the default context Ben Widawsky
2012-03-18 20:39 ` [PATCH 11/18] drm/i915: switch to default context on idle Ben Widawsky
2012-03-29 19:29 ` Daniel Vetter
2012-03-29 20:28 ` Chris Wilson
2012-03-30 21:17 ` Ben Widawsky
2012-03-30 21:30 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 12/18] drm/i915: try to reset the gpu before unload Ben Widawsky
2012-03-29 19:31 ` Daniel Vetter
2012-03-30 18:50 ` Ben Widawsky
2012-03-30 19:05 ` Daniel Vetter
2012-03-30 16:54 ` Jesse Barnes
2012-03-30 17:30 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 13/18] drm/i915/context: create & destroy ioctls Ben Widawsky
2012-03-29 19:35 ` Daniel Vetter
2012-03-30 18:55 ` Ben Widawsky
2012-03-30 19:16 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 14/18] drm/i915/context: switch contexts with execbuf2 Ben Widawsky
2012-03-29 19:38 ` Daniel Vetter
2012-03-30 18:58 ` Ben Widawsky
2012-03-30 19:20 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 15/18] drm/i915/context: add params Ben Widawsky
2012-03-18 20:39 ` [PATCH 16/18] drm/i915/context: anonymous context interfaces Ben Widawsky
2012-03-29 19:42 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 17/18] drm/i915: Ironlake rc6 can use " Ben Widawsky
2012-03-29 19:47 ` Daniel Vetter
2012-03-18 20:39 ` [PATCH 18/18] drm/i915: try to enable rc6 on Ironlake... again Ben Widawsky
2012-03-19 3:47 ` [PATCH 00/18] i915 HW Context Support Ben Widawsky
2012-03-19 10:14 ` Daniel Vetter
2012-03-29 19:51 ` Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20120329182411.GA27737@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=ben@bwidawsk.net \
--cc=intel-gfx@lists.freedesktop.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox