Execlists v5
Subsystems (3)
cover Execlists v5
From: Thomas Daniel <[email protected]>
For a description of this patchset, please check the previous cover letters: [1], [2], [3] and [4].
I have taken ownership of this patchset from Oscar, and this version represents his last work on the execlists patchset. The narrative below is from him.
I have been given some grace period to fix the remaining issues in Execlists before I move to a different project, and this is the result. There are very little differences between this v5 and the v4 I sent out last week, so I was unsure whether to drop a new patchbomb or simply reply to the patches that have changed, but I decided for the former to make the review easier.
The changes are:
- New prep-work patch to prevent a potential problem with the legacy ringbuffer submission extraction that was done earlier.
- Do the remaining intel_runtime_put while purging the execlists queue during reset.
- Check arguments before doing stuff in intel_execlists_submission. Also, get rel_constants parsing right.
- Do gen8_emit_flush = gen6_ring_flush + gen6_bsd_ring_flush.
- New patches for pinning context and ringbuffer backing objects on-demand (before I was pinning on interrupt time, which was a no-no). These fix the reamining eviction issues I was seeing.
The previous comment about the WAs still applies. I reproduce it here for completeness:
"One other caveat I have noticed is that many WAs in gen8_init_clock_gating (those that affect registers that now exist per-context) can get lost in the render default context. The reason is, in Execlists, a context is saved as soon as head = tail (with MI_SET_CONTEXT, however, the context wouldn't be saved until you tried to restore a different context). As we are sending the golden state batchbuffer to the render ring as soon as the rings are initialized, we are effectively saving the default context before gen8_init_clock_gating has an opportunity to set the WAs. I haven't noticed any ill-effect from this (yet) but it would be a good idea to move the WAs somewhere else (ring init looks like a good place). I believe there is already work in progress to create a new WA architecture, so this can be tackled there."
The previous IGT test [4] still applies.
There are three pending issues:
- The test gem_close_race warns about "scheduling while atomic" when the shrinker gets called. Without Execlists, the shrinker does not get called at all (which kind of makes sense) but the tests timeouts before finishing.
- The test gem_concurrent_blit fails in the gtt-* subtests: some pixels (14, to be exact) do not get copied correctly from one bo to another. Funnily enough, the tests pass if I do a i915 module reload first (./tests/drv_module_reload). Yesterday I dumped all the registers in the chip before and after a module reload (attached), but I havenŽt found any meaningful difference yet.
- When I try to run a whole IGT suite using Piglit, sometimes I hit the BUG_ON(!i915_gem_obj_is_pinned(ctx_obj0)) in execlists_submit_context(). I havenŽt managed to reproduce the problem at will, but there is obviously something wrong with the last two Execlists patches.
Keep the r-b tags coming, please!!
-- Oscar
[1]
http://lists.freedesktop.org/archives/intel-gfx/2014-March/042563.html
[2]
http://lists.freedesktop.org/archives/intel-gfx/2014-May/044847.html
[3]
http://lists.freedesktop.org/archives/intel-gfx/2014-June/047138.html
[4]
http://lists.freedesktop.org/archives/intel-gfx/2014-July/048944.html
[5]
http://lists.freedesktop.org/archives/intel-gfx/2014-May/044846.html
Ben Widawsky (2):
drm/i915/bdw: Implement context switching (somewhat) drm/i915/bdw: Print context state in debugfs
Michel Thierry (1):
drm/i915/bdw: Two-stage execlist submit process
Oscar Mateo (39):
drm/i915: Reorder the actual workload submission so that args checking
is done earlier
drm/i915/bdw: New source and header file for LRs, LRCs and Execlists drm/i915/bdw: Macro for LRCs and module option for Execlists drm/i915/bdw: Initialization for Logical Ring Contexts drm/i915/bdw: Introduce one context backing object per engine drm/i915/bdw: A bit more advanced LR context alloc/free drm/i915/bdw: Allocate ringbuffers for Logical Ring Contexts drm/i915/bdw: Add a context and an engine pointers to the ringbuffer drm/i915/bdw: Populate LR contexts (somewhat) drm/i915/bdw: Deferred creation of user-created LRCs drm/i915/bdw: Render moot context reset and switch with Execlists drm/i915/bdw: Don't write PDP in the legacy way when using LRCs drm/i915: Abstract the legacy workload submission mechanism away drm/i915/bdw: Skeleton for the new logical rings submission path drm/i915/bdw: Generic logical ring init and cleanup drm/i915/bdw: GEN-specific logical ring init
drm/i915/bdw: GEN-specific logical ring set/get seqno drm/i915/bdw: New logical ring submission mechanism drm/i915/bdw: GEN-specific logical ring emit request drm/i915/bdw: GEN-specific logical ring emit flush drm/i915/bdw: Emission of requests with logical rings drm/i915/bdw: Ring idle and stop with logical rings drm/i915/bdw: Interrupts with logical rings
drm/i915/bdw: GEN-specific logical ring emit batchbuffer start drm/i915/bdw: Workload submission mechanism for Execlists drm/i915/bdw: Always use MMIO flips with Execlists drm/i915/bdw: Render state init for Execlists drm/i915/bdw: Write the tail pointer, LRC style drm/i915/bdw: Avoid non-lite-restore preemptions drm/i915/bdw: Help out the ctx switch interrupt handler drm/i915/bdw: Make sure gpu reset still works with Execlists drm/i915/bdw: Make sure error capture keeps working with Execlists drm/i915/bdw: Disable semaphores for Execlists drm/i915/bdw: Display execlists info in debugfs drm/i915/bdw: Display context backing obj & ringbuffer info in debugfs drm/i915/bdw: Document Logical Rings, LR contexts and Execlists drm/i915/bdw: Enable Logical Ring Contexts (hence, Execlists) drm/i915/bdw: Pin the context backing objects to GGTT on-demand drm/i915/bdw: Pin the ringbuffer backing object to GGTT on-demand
Thomas Daniel (1):
drm/i915/bdw: Handle context switch events
Documentation/DocBook/drm.tmpl | 5 + drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_debugfs.c | 157 ++- drivers/gpu/drm/i915/i915_drv.c | 4 + drivers/gpu/drm/i915/i915_drv.h | 47 +- drivers/gpu/drm/i915/i915_gem.c | 132 +- drivers/gpu/drm/i915/i915_gem_context.c | 56 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 118 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 + drivers/gpu/drm/i915/i915_gem_render_state.c | 40 +- drivers/gpu/drm/i915/i915_gem_render_state.h | 47 + drivers/gpu/drm/i915/i915_gpu_error.c | 22 +- drivers/gpu/drm/i915/i915_irq.c | 44 +- drivers/gpu/drm/i915/i915_params.c | 6 + drivers/gpu/drm/i915/i915_reg.h | 5 + drivers/gpu/drm/i915/intel_display.c | 2 + drivers/gpu/drm/i915/intel_lrc.c | 1802 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 115 ++ drivers/gpu/drm/i915/intel_renderstate.h | 8 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 166 ++- drivers/gpu/drm/i915/intel_ringbuffer.h | 41 +- 21 files changed, 2622 insertions(+), 201 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.h create mode 100644 drivers/gpu/drm/i915/intel_lrc.c create mode 100644 drivers/gpu/drm/i915/intel_lrc.h
Signature · 5 lines
1.9.0 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 1/43 drm/i915: Reorder the actual workload submission so that args checking is done earlier
From: Oscar Mateo <[email protected]>
In this patch:
commit 78382593e921c88371abd019aca8978db3248a8f
Author: Oscar Mateo <[email protected]> Date: Thu Jul 3 16:28:05 2014 +0100
drm/i915: Extract the actual workload submission mechanism from execbuffer
So that we isolate the legacy ringbuffer submission mechanism, which becomes a good candidate to be abstracted away. This is prep-work for Execlists (which will its own workload submission mechanism).
No functional changes.
I changed the order in which the args checking is done. I don't know why I did (brain fade?) but itś not right. I haven't seen any ill effect from this, but the Execlists version of this function will have problems if the order is not correct.
--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 86 ++++++++++++++-------------- 1 file changed, 43 insertions(+), 43 deletions(-)
drivers/gpu/drm/i915/i915_gem_execbuffer.c +43 -43
@@ -1042,6 +1042,43 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,u32 instp_mask;int i, ret =0 ; + 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" ); + ret = -EINVAL ; + goto error; + } + +if (instp_mode != dev_priv->relative_constants_mode) { +if (INTEL_INFO (dev)->gen <4 ) { +DRM_DEBUG ("no rel constants on pre-gen4\n" ); + ret = -EINVAL ; + goto error; + } + +if (INTEL_INFO (dev)->gen >5 && + instp_mode ==I915_EXEC_CONSTANTS_REL_SURFACE ) { +DRM_DEBUG ("rel surface constants mode invalid on gen5+\n" ); + ret = -EINVAL ; + goto error; + } + +/* The HW changed the meaning on this bit on gen6 */ +if (INTEL_INFO (dev)->gen >=6 ) + instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE ; + } +break ; +default : +DRM_DEBUG ("execbuf with unknown constants: %d\n" , instp_mode); + ret = -EINVAL ; + goto error; + } +if (args->num_cliprects !=0 ) {if (ring != &dev_priv->ring[RCS ]) {DRM_DEBUG ("clip rectangles are only valid with the render ring\n" );
@@ -1085,6 +1122,12 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, } } +if (args->flags &I915_EXEC_GEN7_SOL_RESET ) { + ret =i915_reset_gen7_sol_offsets (dev, ring); +if (ret) + goto error; + } + ret =i915_gem_execbuffer_move_to_gpu (ring, vmas);if (ret) goto error;
@@ -1093,43 +1136,6 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,if (ret) goto error; - 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" ); - ret = -EINVAL ; - goto error; - } - -if (instp_mode != dev_priv->relative_constants_mode) { -if (INTEL_INFO (dev)->gen <4 ) { -DRM_DEBUG ("no rel constants on pre-gen4\n" ); - ret = -EINVAL ; - goto error; - } - -if (INTEL_INFO (dev)->gen >5 && - instp_mode ==I915_EXEC_CONSTANTS_REL_SURFACE ) { -DRM_DEBUG ("rel surface constants mode invalid on gen5+\n" ); - ret = -EINVAL ; - goto error; - } - -/* The HW changed the meaning on this bit on gen6 */ -if (INTEL_INFO (dev)->gen >=6 ) - instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE ; - } -break ; -default : -DRM_DEBUG ("execbuf with unknown constants: %d\n" , instp_mode); - ret = -EINVAL ; - goto error; - } -if (ring == &dev_priv->ring[RCS ] && instp_mode != dev_priv->relative_constants_mode) { ret =intel_ring_begin (ring,4 );
@@ -1145,12 +1151,6 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, dev_priv->relative_constants_mode = instp_mode; } -if (args->flags &I915_EXEC_GEN7_SOL_RESET ) { - ret =i915_reset_gen7_sol_offsets (dev, ring); -if (ret) - goto error; - } - exec_len = args->batch_len;if (cliprects) {for (i =0 ; i < args->num_cliprects; i++) {
Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 01/43] drm/i915: Reorder the actual workload submission so that args checking is done earlier
Quoted 14 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
In this patch:
commit
78382593e921c88371abd019aca8978db3248a8fAuthor: Oscar Mateo <[email protected]> Date: Thu Jul 3 16:28:05 2014 +0100drm/i915: Extract the actual workload submission mechanism from execbuffer
So that we isolate the legacy ringbuffer submission mechanism, which becomes a good candidate to be abstracted away. This is prep-work for Execlists (which will its own workload submission mechanism).
Quoted 7 lines
No functional changes.
I changed the order in which the args checking is done. I don't know why I did (brain fade?) but itś not right. I haven't seen any ill effect from this, but the Execlists version of this function will have problems if the order is not correct.
Signed-off-by Oscar Mateo <[email protected]>
I don't think this matters - the point of no return for legacy execbuf is the call to ring->dispatch. After that nothing may fail any more. But as long as we track state correctly (e.g. if we've switched the context already) we'll be fine.
So presuming I'm not blind I dont' think this is needed. But maybe Chris spots something.
-Daniel
Quoted 129 lines
--- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 86 ++++++++++++++-------------- 1 file changed, 43 insertions(+), 43 deletions(-)drivers/gpu/drm/i915/i915_gem_execbuffer.c +43
-43@@ -1042,6 +1042,43 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,u32 instp_mask;int i, ret =0 ; + 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" ); + ret = -EINVAL ; + goto error; + } + +if (instp_mode != dev_priv->relative_constants_mode) { +if (INTEL_INFO (dev)->gen <4 ) { +DRM_DEBUG ("no rel constants on pre-gen4\n" ); + ret = -EINVAL ; + goto error; + } + +if (INTEL_INFO (dev)->gen >5 && + instp_mode ==I915_EXEC_CONSTANTS_REL_SURFACE ) { +DRM_DEBUG ("rel surface constants mode invalid on gen5+\n" ); + ret = -EINVAL ; + goto error; + } + +/* The HW changed the meaning on this bit on gen6 */ +if (INTEL_INFO (dev)->gen >=6 ) + instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE ; + } +break ; +default : +DRM_DEBUG ("execbuf with unknown constants: %d\n" , instp_mode); + ret = -EINVAL ; + goto error; + } +if (args->num_cliprects !=0 ) {if (ring != &dev_priv->ring[RCS ]) {DRM_DEBUG ("clip rectangles are only valid with the render ring\n" );@@ -1085,6 +1122,12 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, } } +if (args->flags &I915_EXEC_GEN7_SOL_RESET ) { + ret =i915_reset_gen7_sol_offsets (dev, ring); +if (ret) + goto error; + } + ret =i915_gem_execbuffer_move_to_gpu (ring, vmas);if (ret) goto error;@@ -1093,43 +1136,6 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file,if (ret) goto error; - 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" ); - ret = -EINVAL ; - goto error; - } - -if (instp_mode != dev_priv->relative_constants_mode) { -if (INTEL_INFO (dev)->gen <4 ) { -DRM_DEBUG ("no rel constants on pre-gen4\n" ); - ret = -EINVAL ; - goto error; - } - -if (INTEL_INFO (dev)->gen >5 && - instp_mode ==I915_EXEC_CONSTANTS_REL_SURFACE ) { -DRM_DEBUG ("rel surface constants mode invalid on gen5+\n" ); - ret = -EINVAL ; - goto error; - } - -/* The HW changed the meaning on this bit on gen6 */ -if (INTEL_INFO (dev)->gen >=6 ) - instp_mask &= ~I915_EXEC_CONSTANTS_REL_SURFACE ; - } -break ; -default : -DRM_DEBUG ("execbuf with unknown constants: %d\n" , instp_mode); - ret = -EINVAL ; - goto error; - } -if (ring == &dev_priv->ring[RCS ] && instp_mode != dev_priv->relative_constants_mode) { ret =intel_ring_begin (ring,4 );@@ -1145,12 +1151,6 @@ legacy_ringbuffer_submission(struct drm_device *dev, struct drm_file *file, dev_priv->relative_constants_mode = instp_mode; } -if (args->flags &I915_EXEC_GEN7_SOL_RESET ) { - ret =i915_reset_gen7_sol_offsets (dev, ring); -if (ret) - goto error; - } - exec_len = args->batch_len;if (cliprects) {for (i =0 ; i < args->num_cliprects; i++) {Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 7 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 01/43] drm/i915: Reorder the actual workload submission so that args checking is done earlier
Quoted 21 lines · Daniel Vetter
Quoted 20 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
In this patch:
commit
78382593e921c88371abd019aca8978db3248a8fAuthor: Oscar Mateo <[email protected]> Date: Thu Jul 3 16:28:05 2014 +0100drm/i915: Extract the actual workload submission mechanism from execbuffer
So that we isolate the legacy ringbuffer submission mechanism, which becomes a good candidate to be abstracted away. This is prep-work for Execlists (which will its own workload submission mechanism).
No functional changes.
I changed the order in which the args checking is done. I don't know why I did (brain fade?) but itś not right. I haven't seen any ill effect from this, but the Execlists version of this function will have problems if the order is not correct.
Quoted 6 lines
Quoted 1 line
Signed-off-by Oscar Mateo <[email protected]>I don't think this matters - the point of no return for legacy execbuf is the call to
ring->dispatch. After that nothing may fail any more. But as long as we track state correctly (e.g. if we've switched the context already) we'll be fine.
Right. Except that I think our tracking is buggy - or at least insufficient to address the needs of future dispatch mechanisms. I think that we confuse some bookkeeping that should be at the request level and place it on the ring. At the moment, we have one request per-ring and so it doesn't matter, but transitioning to one request per-logical-ring we start to have issues as that state is being tracked on the wrong struct.
Anyway, that's part of the motivation to fixing up requests and making them central to accessing the rings/dispatch (whereas at the moment they are behind the scenes).
-Chris
Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 2/43 drm/i915/bdw: New source and header file for LRs, LRCs and Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Some legacy HW context code assumptions don't make sense for this new submission method, so we will place this stuff in a separate file.
Note for reviewers: I've carefully considered the best name for this file and this was my best option (other possibilities were intel_lr_context.c or intel_execlist.c). I am open to a certain bikeshedding on this matter, anyway.
And some point in time, it would be a good idea to split intel_lrc.c/.h even further, but for the moment just shove everything together.
v2: Change to intel_lrc.c
v3: Squash together with the header file addition
--- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 42 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 27 ++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 drivers/gpu/drm/i915/intel_lrc.c create mode 100644 drivers/gpu/drm/i915/intel_lrc.h
drivers/gpu/drm/i915/Makefile +1 -0
@@ -31,6 +31,7 @@ i915-y += i915_cmd_parser.o \ i915_gpu_error.o \ i915_irq.o \ i915_trace_points.o \ + intel_lrc.o \ intel_ringbuffer.o \ intel_uncore.o
drivers/gpu/drm/i915/i915_drv.h +1 -0
@@ -35,6 +35,7 @@#include "i915_reg.h" #include "intel_bios.h" #include "intel_ringbuffer.h" +#include "intel_lrc.h" #include "i915_gem_gtt.h" #include <linux/io-mapping.h> #include <linux/i2c.h>
drivers/gpu/drm/i915/intel_lrc.c new file +42 -0
42 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.h new file +27 -0
@@ -0,0 +1,27 @@ +/* +* Copyright © 2014 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +#ifndef _INTEL_LRC_H_ +#define _INTEL_LRC_H_ + +#endif /* _INTEL_LRC_H_ */
Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
PATCH 3/43 drm/i915/bdw: Macro for LRCs and module option for Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
GEN8 brings an expansion of the HW contexts: "Logical Ring Contexts". These expanded contexts enable a number of new abilities, especially "Execlists".
The macro is defined to off until we have things in place to hope to work.
v2: Rename "advanced contexts" to the more correct "logical ring contexts".
v3: Add a module parameter to enable execlists. Execlist are relatively new, and so it'd be wise to be able to switch back to ring submission to debug subtle problems that will inevitably arise.
v4: Add an intel_enable_execlists function.
v5: Sanitize early, as suggested by Daniel. Remove lrc_enabled.
--- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 3 +++ drivers/gpu/drm/i915/i915_params.c | 6 ++++++ drivers/gpu/drm/i915/intel_lrc.c | 11 +++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 3 +++ 5 files changed, 25 insertions(+)
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -2037,6 +2037,7 @@ struct drm_i915_cmd_table {#define I915_NEED_GFX_HWS (dev) (INTEL_INFO(dev)->need_gfx_hws)#define HAS_HW_CONTEXTS (dev) (INTEL_INFO(dev)->gen >= 6) +#define HAS_LOGICAL_RING_CONTEXTS (dev) 0#define HAS_ALIASING_PPGTT (dev) (INTEL_INFO(dev)->gen >= 6)#define HAS_PPGTT (dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))#define USES_PPGTT (dev) intel_enable_ppgtt(dev, false)
@@ -2122,6 +2123,7 @@ struct i915_params {int enable_rc6;int enable_fbc;int enable_ppgtt; +int enable_execlists;int enable_psr;unsigned int preliminary_hw_support;int disable_power_well;
drivers/gpu/drm/i915/i915_gem.c +3 -0
@@ -4746,6 +4746,9 @@ int i915_gem_init(struct drm_device *dev)struct drm_i915_private *dev_priv = dev->dev_private;int ret; + i915.enable_execlists =intel_sanitize_enable_execlists (dev, + i915.enable_execlists); +mutex_lock (&dev->struct_mutex);if (IS_VALLEYVIEW (dev)) {
drivers/gpu/drm/i915/i915_params.c +6 -0
@@ -35,6 +35,7 @@ struct i915_params i915 __read_mostly = { .vbt_sdvo_panel_type = -1, .enable_rc6 = -1, .enable_fbc = -1, + .enable_execlists = -1, .enable_hangcheck = true, .enable_ppgtt = -1, .enable_psr = 1,
@@ -117,6 +118,11 @@ MODULE_PARM_DESC(enable_ppgtt,"Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); +module_param_named (enable_execlists, i915.enable_execlists, int,0400 ); +MODULE_PARM_DESC (enable_execlists, +"Override execlists usage. " +"(-1=auto [default], 0=disabled, 1=enabled)" ); +module_param_named (enable_psr, i915.enable_psr, int,0600 );MODULE_PARM_DESC (enable_psr,"Enable PSR (default: true)" );
drivers/gpu/drm/i915/intel_lrc.c +11 -0
@@ -40,3 +40,14 @@#include <drm/drmP.h> #include <drm/i915_drm.h> #include "i915_drv.h" + +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) +{ +if (enable_execlists ==0 ) +return 0 ; + +if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev)) +return 1 ; + +return 0 ; +}
drivers/gpu/drm/i915/intel_lrc.h +3 -0
@@ -24,4 +24,7 @@#ifndef _INTEL_LRC_H_#define _INTEL_LRC_H_ +/* Execlists */ +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists); +#endif /* _INTEL_LRC_H_ */
Signature · 1 line
1.7.9.5
Re: [PATCH 03/43] drm/i915/bdw: Macro for LRCs and module option for Execlists
Quoted 56 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
GEN8 brings an expansion of the HW contexts: "Logical Ring Contexts". These expanded contexts enable a number of new abilities, especially "Execlists".
The macro is defined to off until we have things in place to hope to work.
v2: Rename "advanced contexts" to the more correct "logical ring contexts".
v3: Add a module parameter to enable execlists. Execlist are relatively new, and so it'd be wise to be able to switch back to ring submission to debug subtle problems that will inevitably arise.
v4: Add an
intel_enable_execlistsfunction.v5: Sanitize early, as suggested by Daniel. Remove
lrc_enabled.Signed-off-by Ben Widawsky <[email protected]> (v1)Signed-off-by Damien Lespiau <[email protected]> (v3)Signed-off-by Oscar Mateo <[email protected]> (v2, v4 & v5)--- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem.c | 3 +++ drivers/gpu/drm/i915/i915_params.c | 6 ++++++ drivers/gpu/drm/i915/intel_lrc.c | 11 +++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 3 +++ 5 files changed, 25 insertions(+)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -2037,6 +2037,7 @@ struct drm_i915_cmd_table {#define I915_NEED_GFX_HWS (dev) (INTEL_INFO(dev)->need_gfx_hws)#define HAS_HW_CONTEXTS (dev) (INTEL_INFO(dev)->gen >= 6) +#define HAS_LOGICAL_RING_CONTEXTS (dev) 0#define HAS_ALIASING_PPGTT (dev) (INTEL_INFO(dev)->gen >= 6)#define HAS_PPGTT (dev) (INTEL_INFO(dev)->gen >= 7 && !IS_GEN8(dev))#define USES_PPGTT (dev) intel_enable_ppgtt(dev, false)@@ -2122,6 +2123,7 @@ struct i915_params {int enable_rc6;int enable_fbc;int enable_ppgtt; +int enable_execlists;int enable_psr;unsigned int preliminary_hw_support;int disable_power_well;drivers/gpu/drm/i915/i915_gem.c +0
-0
drivers/gpu/drm/i915/i915_gem.c int i915_gem_init(struct drm_device *dev) · line 4750
Quoted 5 lines
drivers/gpu/drm/i915/i915_gem.c +2
-0@@ -4746,6 +4746,9 @@ int i915_gem_init(struct drm_device *dev)struct drm_i915_private *dev_priv = dev->dev_private;int ret; + i915.enable_execlists =intel_sanitize_enable_execlists (dev, + i915.enable_execlists);
The ordering constraint on i915.enabel_ppgtt sanitization is imo super-fragile. You'll all get a big price (and grumpy maintainer) if this blows up. I'll add a patch on top to WARN about this.
-Daniel
Quoted 66 lines
drivers/gpu/drm/i915/i915_gem.c +1
-0+mutex_lock (&dev->struct_mutex);if (IS_VALLEYVIEW (dev)) {drivers/gpu/drm/i915/i915_params.c +6
-0@@ -35,6 +35,7 @@ struct i915_params i915 __read_mostly = { .vbt_sdvo_panel_type = -1, .enable_rc6 = -1, .enable_fbc = -1, + .enable_execlists = -1, .enable_hangcheck = true, .enable_ppgtt = -1, .enable_psr = 1,@@ -117,6 +118,11 @@ MODULE_PARM_DESC(enable_ppgtt,"Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full)"); +module_param_named (enable_execlists, i915.enable_execlists, int,0400 ); +MODULE_PARM_DESC (enable_execlists, +"Override execlists usage. " +"(-1=auto [default], 0=disabled, 1=enabled)" ); +module_param_named (enable_psr, i915.enable_psr, int,0600 );MODULE_PARM_DESC (enable_psr,"Enable PSR (default: true)" );drivers/gpu/drm/i915/intel_lrc.c +11
-0@@ -40,3 +40,14 @@#include <drm/drmP.h> #include <drm/i915_drm.h> #include "i915_drv.h" + +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) +{ +if (enable_execlists ==0 ) +return 0 ; + +if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev)) +return 1 ; + +return 0 ; +}drivers/gpu/drm/i915/intel_lrc.h +3
-0@@ -24,4 +24,7 @@#ifndef _INTEL_LRC_H_#define _INTEL_LRC_H_ +/* Execlists */ +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists); +#endif /* _INTEL_LRC_H_ */ Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 4/43 drm/i915/bdw: Initialization for Logical Ring Contexts
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
For the moment this is just a placeholder, but it shows one of the main differences between the good ol' HW contexts and the shiny new Logical Ring Contexts: LR contexts allocate and free their own backing objects. Another difference is that the allocation is deferred (as the create function name suggests), but that does not happen in this patch yet, because for the moment we are only dealing with the default context.
Early in the series we had our own gen8_gem_context_init/fini functions, but the truth is they now look almost the same as the legacy hw context init/fini functions. We can always split them later if this ceases to be the case.
Also, we do not fall back to legacy ringbuffers when logical ring context initialization fails (not very likely to happen and, even if it does, hw contexts would probably fail as well).
v2: Daniel says "explain, do not showcase".
--- drivers/gpu/drm/i915/i915_gem_context.c | 29 +++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_lrc.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 5 +++++ 3 files changed, 43 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_gem_context.c +23 -6
@@ -182,7 +182,10 @@ void i915_gem_context_free(struct kref *ctx_ref) typeof(*ctx), ref);struct i915_hw_ppgtt *ppgtt =NULL ; -if (ctx->legacy_hw_ctx.rcs_state) { +if (i915.enable_execlists) { + ppgtt =ctx_to_ppgtt (ctx); +intel_lr_context_free (ctx); + }else if (ctx->legacy_hw_ctx.rcs_state) {/* We refcount even the aliasing PPGTT to keep the code symmetric */ if (USES_PPGTT (ctx->legacy_hw_ctx.rcs_state->base.dev)) ppgtt =ctx_to_ppgtt (ctx);
@@ -419,7 +422,11 @@ int i915_gem_context_init(struct drm_device *dev)if (WARN_ON (dev_priv->ring[RCS ].default_context))return 0 ; -if (HAS_HW_CONTEXTS (dev)) { +if (i915.enable_execlists) { +/* NB: intentionally left blank. We will allocate our own +* backing objects as we need them, thank you very much */ + dev_priv->hw_context_size =0 ; + }else if (HAS_HW_CONTEXTS (dev)) { dev_priv->hw_context_size =round_up (get_context_size (dev),4096 );if (dev_priv->hw_context_size > (1 <<20 )) { DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
@@ -435,11 +442,20 @@ int i915_gem_context_init(struct drm_device *dev)return PTR_ERR (ctx); } -/* NB: RCS will hold a ref for all rings */ -for (i =0 ; i <I915_NUM_RINGS ; i++) - dev_priv->ring[i].default_context = ctx; +for (i =0 ; i <I915_NUM_RINGS ; i++) { +struct intel_engine_cs *ring = &dev_priv->ring[i]; + +/* NB: RCS will hold a ref for all rings */ + ring->default_context = ctx; + +/* FIXME: we really only want to do this for initialized rings */ +if (i915.enable_execlists) +intel_lr_context_deferred_create (ctx, ring); + } -DRM_DEBUG_DRIVER ("%s context support initialized\n" , dev_priv->hw_context_size ?"HW" :"fake" ); +DRM_DEBUG_DRIVER ("%s context support initialized\n" , + i915.enable_execlists ?"LR" : + dev_priv->hw_context_size ?"HW" :"fake" );return 0 ; }
@@ -781,6 +797,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,struct intel_context *ctx;int ret; +/* FIXME: allow user-created LR contexts as well */ if (!hw_context_enabled (dev))return -ENODEV ;
drivers/gpu/drm/i915/intel_lrc.c +15 -0
@@ -51,3 +51,18 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsreturn 0 ; } + +void intel_lr_context_free (struct intel_context *ctx) +{ +/* TODO */ +} + +int intel_lr_context_deferred_create (struct intel_context *ctx, +struct intel_engine_cs *ring) +{ +BUG_ON (ctx->legacy_hw_ctx.rcs_state !=NULL ); + +/* TODO */ + +return 0 ; +}
drivers/gpu/drm/i915/intel_lrc.h +5 -0
@@ -24,6 +24,11 @@#ifndef _INTEL_LRC_H_#define _INTEL_LRC_H_ +/* Logical Ring Contexts */ +void intel_lr_context_free (struct intel_context *ctx); +int intel_lr_context_deferred_create (struct intel_context *ctx, +struct intel_engine_cs *ring); +/* Execlists */ int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists);
Signature · 1 line
1.7.9.5
Re: [PATCH 04/43] drm/i915/bdw: Initialization for Logical Ring Contexts
Quoted 98 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
For the moment this is just a placeholder, but it shows one of the main differences between the good ol' HW contexts and the shiny new Logical Ring Contexts: LR contexts allocate and free their own backing objects. Another difference is that the allocation is deferred (as the create function name suggests), but that does not happen in this patch yet, because for the moment we are only dealing with the default context.
Early in the series we had our own gen8_gem_context_init/fini functions, but the truth is they now look almost the same as the legacy hw context init/fini functions. We can always split them later if this ceases to be the case.
Also, we do not fall back to legacy ringbuffers when logical ring context initialization fails (not very likely to happen and, even if it does, hw contexts would probably fail as well).
v2: Daniel says "explain, do not showcase".
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_context.c | 29 +++++++++++++++++++++++------ drivers/gpu/drm/i915/intel_lrc.c | 15 +++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 5 +++++ 3 files changed, 43 insertions(+), 6 deletions(-)drivers/gpu/drm/i915/i915_gem_context.c +23
-6@@ -182,7 +182,10 @@ void i915_gem_context_free(struct kref *ctx_ref) typeof(*ctx), ref);struct i915_hw_ppgtt *ppgtt =NULL ; -if (ctx->legacy_hw_ctx.rcs_state) { +if (i915.enable_execlists) { + ppgtt =ctx_to_ppgtt (ctx); +intel_lr_context_free (ctx); + }else if (ctx->legacy_hw_ctx.rcs_state) {/* We refcount even the aliasing PPGTT to keep the code symmetric */ if (USES_PPGTT (ctx->legacy_hw_ctx.rcs_state->base.dev)) ppgtt =ctx_to_ppgtt (ctx);@@ -419,7 +422,11 @@ int i915_gem_context_init(struct drm_device *dev)if (WARN_ON (dev_priv->ring[RCS ].default_context))return 0 ; -if (HAS_HW_CONTEXTS (dev)) { +if (i915.enable_execlists) { +/* NB: intentionally left blank. We will allocate our own +* backing objects as we need them, thank you very much */ + dev_priv->hw_context_size =0 ; + }else if (HAS_HW_CONTEXTS (dev)) { dev_priv->hw_context_size =round_up (get_context_size (dev),4096 );if (dev_priv->hw_context_size > (1 <<20 )) { DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",@@ -435,11 +442,20 @@ int i915_gem_context_init(struct drm_device *dev)return PTR_ERR (ctx); } -/* NB: RCS will hold a ref for all rings */ -for (i =0 ; i <I915_NUM_RINGS ; i++) - dev_priv->ring[i].default_context = ctx; +for (i =0 ; i <I915_NUM_RINGS ; i++) { +struct intel_engine_cs *ring = &dev_priv->ring[i]; + +/* NB: RCS will hold a ref for all rings */ + ring->default_context = ctx; + +/* FIXME: we really only want to do this for initialized rings */ +if (i915.enable_execlists) +intel_lr_context_deferred_create (ctx, ring); + } -DRM_DEBUG_DRIVER ("%s context support initialized\n" , dev_priv->hw_context_size ?"HW" :"fake" ); +DRM_DEBUG_DRIVER ("%s context support initialized\n" , + i915.enable_execlists ?"LR" : + dev_priv->hw_context_size ?"HW" :"fake" );return 0 ; }@@ -781,6 +797,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,struct intel_context *ctx;int ret; +/* FIXME: allow user-created LR contexts as well */ if (!hw_context_enabled (dev))return -ENODEV ;drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -51,3 +51,18 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsreturn 0 ; }
drivers/gpu/drm/i915/intel_lrc.c int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists · line 63
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+ +void intel_lr_context_free (struct intel_context *ctx) +{ +/* TODO */ +} + +int intel_lr_context_deferred_create (struct intel_context *ctx, +struct intel_engine_cs *ring) +{ +BUG_ON (ctx->legacy_hw_ctx.rcs_state !=NULL );
I command thy:
Thou shalt not use BUG_ON except in especially dire circumstances!
Fixed while applying.
-Daniel
Quoted 28 lines
drivers/gpu/drm/i915/intel_lrc.c +5
-0+ +/* TODO */ + +return 0 ; +}drivers/gpu/drm/i915/intel_lrc.h +5
-0@@ -24,6 +24,11 @@#ifndef _INTEL_LRC_H_#define _INTEL_LRC_H_ +/* Logical Ring Contexts */ +void intel_lr_context_free (struct intel_context *ctx); +int intel_lr_context_deferred_create (struct intel_context *ctx, +struct intel_engine_cs *ring); +/* Execlists */ int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 5/43 drm/i915/bdw: Introduce one context backing object per engine
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
A context backing object only makes sense for a given engine (because it holds state data specific to that engine).
In legacy ringbuffer sumission mode, the only MI_SET_CONTEXT we really perform is for the render engine, so one backing object is all we nee.
With Execlists, however, we need backing objects for every engine, as contexts become the only way to submit workloads to the GPU. To tackle this problem, we multiplex the context struct to contain <no-of-engines> objects.
Originally, I colored this code by instantiating one new context for every engine I wanted to use, but this change suggested by Brad Volkin makes it more elegant.
v2: Leave the old backing object pointer behind. Daniel Vetter suggested using a union, but it makes more sense to keep rcs_state as a NULL pointer behind, to make sure no one uses it incorrectly when Execlists are enabled, similar to what he suggested for ring->buffer (Rusty's API level 5).
v3: Use the name "state" instead of the too-generic "obj", so that it mirrors the name choice for the legacy rcs_state.
--- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/i915/i915_drv.h +6 -0
@@ -616,11 +616,17 @@ struct intel_context {struct i915_ctx_hang_stats hang_stats;struct i915_address_space *vm; +/* Legacy ring buffer submission */ struct {struct drm_i915_gem_object *rcs_state;bool initialized; } legacy_hw_ctx; +/* Execlists */ +struct { +struct drm_i915_gem_object *state; + } engine[I915_NUM_RINGS ]; +struct list_head link; };
Signature · 1 line
1.7.9.5
PATCH 1/1 drm/i915: WARN if module opt sanitization goes out of order
Depending upon one module option to be sanitized (through USES_PPGTT) for the other is a bit too fragile for my taste. At least WARN about this.
--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +2 -0
@@ -43,6 +43,8 @@int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) { +WARN_ON (i915.enable_ppgtt ==-1 ); +if (enable_execlists ==0 )return 0 ;
Signature · 1 line
2.0.1
Re: [PATCH] drm/i915: WARN if module opt sanitization goes out of order
Quoted 8 lines · Daniel Vetter
Depending upon one module option to be sanitized (through
USES_PPGTT) for the other is a bit too fragile for my taste. At least WARN about this.Cc Ben Widawsky <[email protected]>Cc Damien Lespiau <[email protected]>Cc Oscar Mateo <[email protected]>Signed-off-by Daniel Vetter <[email protected]>
Sounds like a safety measure we'd want. Until we try to fix these kind of dependencies in a more adequate manner that is.
Signature · 1 line
Damien
Quoted 20 lines
--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ 1 file changed, 2 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +2
-0@@ -43,6 +43,8 @@int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) { +WARN_ON (i915.enable_ppgtt ==-1 ); +if (enable_execlists ==0 )return 0 ;Signature · 1 line
2.0.1
PATCH 6/43 drm/i915/bdw: A bit more advanced LR context alloc/free
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Now that we have the ability to allocate our own context backing objects and we have multiplexed one of them per engine inside the context structs, we can finally allocate and free them correctly.
Regarding the context size, reading the register to calculate the sizes can work, I think, however the docs are very clear about the actual context sizes on GEN8, so just hardcode that and use it.
v2: Rebased on top of the Full PPGTT series. It is important to notice that at this point we have one global default context per engine, all of them using the aliasing PPGTT (as opposed to the single global default context we have with legacy HW contexts).
v3:
- Go back to one single global default context, this time with multiple backing objects inside.
- Use different context sizes for non-render engines, as suggested by Damien (still hardcoded, since the information about the context size registers in the BSpec is, well, *lacking*).
- Render ctx size is 20 (or 19) pages, but not 21 (caught by Damien).
- Move default context backing object creation to intel_init_ring (so that we don't waste memory in rings that might not get initialized).
v4:
- Reuse the HW legacy context init/fini.
- Create a separate free function.
- Rename the functions with an intel_ preffix.
v5: Several rebases to account for the changes in the previous patches.
--- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/i915_gem_context.c | 2 +- drivers/gpu/drm/i915/intel_lrc.c | 59 +++++++++++++++++++++++++++++-- 3 files changed, 60 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +2 -0
@@ -2500,6 +2500,8 @@ int i915_switch_context(struct intel_engine_cs *ring,struct intel_context *i915_gem_context_get (struct drm_i915_file_private *file_priv,u32 id);void i915_gem_context_free (struct kref *ctx_ref); +struct drm_i915_gem_object * +i915_gem_alloc_context_obj (struct drm_device *dev,size_t size);static inline void i915_gem_context_reference (struct intel_context *ctx) {kref_get (&ctx->ref);
drivers/gpu/drm/i915/i915_gem_context.c +1 -1
@@ -201,7 +201,7 @@ void i915_gem_context_free(struct kref *ctx_ref)kfree (ctx); } -static struct drm_i915_gem_object * +struct drm_i915_gem_object *i915_gem_alloc_context_obj (struct drm_device *dev,size_t size) {struct drm_i915_gem_object *obj;
drivers/gpu/drm/i915/intel_lrc.c +57 -2
78 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH 7/43 drm/i915/bdw: Allocate ringbuffers for Logical Ring Contexts
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
As we have said a couple of times by now, logical ring contexts have their own ringbuffers: not only the backing pages, but the whole management struct.
In a previous version of the series, this was achieved with two separate patches:
drm/i915/bdw: Allocate ringbuffer backing objects for default global LRC drm/i915/bdw: Allocate ringbuffer for user-created LRCs
--- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 38 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 6 ++--- drivers/gpu/drm/i915/intel_ringbuffer.h | 4 ++++ 4 files changed, 46 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
@@ -625,6 +625,7 @@ struct intel_context {/* Execlists */ struct {struct drm_i915_gem_object *state; +struct intel_ringbuffer *ringbuf; } engine[I915_NUM_RINGS ];struct list_head link;
drivers/gpu/drm/i915/intel_lrc.c +38 -0
@@ -63,7 +63,11 @@ void intel_lr_context_free(struct intel_context *ctx)for (i =0 ; i <I915_NUM_RINGS ; i++) {struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state; +struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf; +if (ctx_obj) { +intel_destroy_ringbuffer_obj (ringbuf); +kfree (ringbuf);i915_gem_object_ggtt_unpin (ctx_obj);drm_gem_object_unreference (&ctx_obj->base); }
@@ -97,6 +101,7 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,struct drm_device *dev = ring->dev;struct drm_i915_gem_object *ctx_obj;uint32_t context_size; +struct intel_ringbuffer *ringbuf;int ret;BUG_ON (ctx->legacy_hw_ctx.rcs_state !=NULL );
@@ -117,6 +122,39 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,return ret; } + ringbuf =kzalloc (sizeof (*ringbuf),GFP_KERNEL ); +if (!ringbuf) { +DRM_DEBUG_DRIVER ("Failed to allocate ringbuffer %s\n" , + ring->name); +i915_gem_object_ggtt_unpin (ctx_obj); +drm_gem_object_unreference (&ctx_obj->base); + ret = -ENOMEM ; +return ret; + } + + ringbuf->size =32 *PAGE_SIZE ; + ringbuf->effective_size = ringbuf->size; + ringbuf->head =0 ; + ringbuf->tail =0 ; + ringbuf->space = ringbuf->size; + ringbuf->last_retired_head =-1 ; + +/* TODO: For now we put this in the mappable region so that we can reuse +* the existing ringbuffer code which ioremaps it. When we start +* creating many contexts, this will no longer work and we must switch +* to a kmapish interface. +*/ + ret =intel_alloc_ringbuffer_obj (dev, ringbuf); +if (ret) { +DRM_DEBUG_DRIVER ("Failed to allocate ringbuffer obj %s: %d\n" , + ring->name, ret); +kfree (ringbuf); +i915_gem_object_ggtt_unpin (ctx_obj); +drm_gem_object_unreference (&ctx_obj->base); +return ret; + } + + ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj;return 0 ;
drivers/gpu/drm/i915/intel_ringbuffer.c +3 -3
@@ -1495,7 +1495,7 @@ static int init_phys_status_page(struct intel_engine_cs *ring)return 0 ; } -static void intel_destroy_ringbuffer_obj (struct intel_ringbuffer *ringbuf) +void intel_destroy_ringbuffer_obj (struct intel_ringbuffer *ringbuf) {if (!ringbuf->obj)return ;
@@ -1506,8 +1506,8 @@ static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf) ringbuf->obj =NULL ; } -static int intel_alloc_ringbuffer_obj (struct drm_device *dev, -struct intel_ringbuffer *ringbuf) +int intel_alloc_ringbuffer_obj (struct drm_device *dev, +struct intel_ringbuffer *ringbuf) {struct drm_i915_private *dev_priv =to_i915 (dev);struct drm_i915_gem_object *obj;
drivers/gpu/drm/i915/intel_ringbuffer.h +4 -0
@@ -353,6 +353,10 @@ intel_write_status_page(struct intel_engine_cs *ring,#define I915_GEM_HWS_SCRATCH_INDEX 0x30#define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) +void intel_destroy_ringbuffer_obj (struct intel_ringbuffer *ringbuf); +int intel_alloc_ringbuffer_obj (struct drm_device *dev, +struct intel_ringbuffer *ringbuf); +void intel_stop_ring_buffer (struct intel_engine_cs *ring);void intel_cleanup_ring_buffer (struct intel_engine_cs *ring);
Signature · 1 line
1.7.9.5
PATCH 8/43 drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one engine. By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +2 -0
@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;
drivers/gpu/drm/i915/intel_ringbuffer.c +2 -0
@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;memset (ring->semaphore.sync_seqno,0 ,sizeof (ring->semaphore.sync_seqno));init_waitqueue_head (&ring->irq_queue);
drivers/gpu/drm/i915/intel_ringbuffer.h +3 -0
@@ -88,6 +88,9 @@ struct intel_ringbuffer {struct drm_i915_gem_object *obj;void __iomem *virtual_start; +struct intel_engine_cs *ring; +struct intel_context *ctx; +u32 head;u32 tail;int space;
Signature · 1 line
1.7.9.5
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 32 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one engine. By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +2
-0@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct drm_device *dev, · line 1574
Quoted 5 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +2
-0@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;
That doesn't make a terribly lot of sense tbh. I fear it's one of these slight confusions which will take tons of patches to clean up. Why exactly do we need the ring->ctx pointer?
If we only need this for lrc I want to name it accordingly, to make sure legacy code doesn't grow stupid ideas. And also we should only initialize this in the lrc ctx init then.
All patches up to this one merged.
-Daniel
Quoted 24 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0memset (ring->semaphore.sync_seqno,0 ,sizeof (ring->semaphore.sync_seqno));init_waitqueue_head (&ring->irq_queue);drivers/gpu/drm/i915/intel_ringbuffer.h +3
-0@@ -88,6 +88,9 @@ struct intel_ringbuffer {struct drm_i915_gem_object *obj;void __iomem *virtual_start; +struct intel_engine_cs *ring; +struct intel_context *ctx; +u32 head;u32 tail;int space;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 43 lines · Daniel Vetter
Quoted 32 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one engine. By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +2
-0@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct drm_device *dev, · line 1574
Quoted 5 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +2
-0@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct drm_device *dev,INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;That doesn't make a terribly lot of sense tbh. I fear it's one of these slight confusions which will take tons of patches to clean up. Why exactly do we need the
ring->ctxpointer?
Quoted 5 lines
If we only need this for lrc I want to name it accordingly, to make sure legacy code doesn't grow stupid ideas. And also we should only initialize this in the lrc ctx init then.
All patches up to this one merged.
Ok, I've discussed this quickly with Damien on irc. We decided to cut away the ring->ctx part of this patch for now to be able to move on. -Daniel
Quoted 31 lines
-Daniel
Quoted 24 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0memset (ring->semaphore.sync_seqno,0 ,sizeof (ring->semaphore.sync_seqno));init_waitqueue_head (&ring->irq_queue);drivers/gpu/drm/i915/intel_ringbuffer.h +3
-0@@ -88,6 +88,9 @@ struct intel_ringbuffer {struct drm_i915_gem_object *obj;void __iomem *virtual_start; +struct intel_engine_cs *ring; +struct intel_context *ctx; +u32 head;u32 tail;int space;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfxSignature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 63 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 3:21 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 15 lines · Daniel Vetter
Quoted 14 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one engine. By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c int intel_lr_context_deferred_create(struct
Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct
intel_context*ctx,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct
Quoted 14 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-0return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct
drm_device*dev,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct drm_device *dev, · line 1574
Quoted 5 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +2
-0INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;That doesn't make a terribly lot of sense tbh. I fear it's one of these slight confusions which will take tons of patches to clean up. Why exactly do we need the
ring->ctxpointer?If we only need this for lrc I want to name it accordingly, to make sure legacy code doesn't grow stupid ideas. And also we should only initialize this in the lrc ctx init then.
Quoted 5 lines
Quoted 1 line
All patches up to this one merged.
Ok, I've discussed this quickly with Damien on irc. We decided to cut away the
ring->ctxpart of this patch for now to be able to move on. -Daniel
As you've seen, removing ringbuffer->ctx causes serious problems with the plumbing later on. This can be renamed (perhaps to lrc) and removed from legacy init.
Each ring buffer belongs to a specific context - it makes sense to me to keep this information within the ringbuffer structure so that we don't have to pass the context pointer around everywhere.
Thomas.
Quoted 39 lines
Quoted 25 lines
-Daniel
Quoted 22 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0memset (ring->semaphore.sync_seqno,0 ,sizeof (ring->semaphore.sync_seqno));drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0init_waitqueue_head (&ring->irq_queue);drivers/gpu/drm/i915/intel_ringbuffer.h +3
-1@@ -88,6 +88,9 @@ struct intel_ringbuffer {struct drm_i915_gem_object *obj;void __iomem *virtual_start; +struct intel_engine_cs *ring; +struct intel_context *ctx; +u32 head;u32 tail;int space; --1.7.9.5
Quoted 9 lines
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 68 lines · Thomas
Quoted 63 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 3:21 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 15 lines · Daniel Vetter
Quoted 14 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one engine. By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c int intel_lr_context_deferred_create(struct
Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct
intel_context*ctx,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct
Quoted 14 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-0return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct
drm_device*dev,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct drm_device *dev, · line 1574
Quoted 5 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +2
-0INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;That doesn't make a terribly lot of sense tbh. I fear it's one of these slight confusions which will take tons of patches to clean up. Why exactly do we need the
ring->ctxpointer?If we only need this for lrc I want to name it accordingly, to make sure legacy code doesn't grow stupid ideas. And also we should only initialize this in the lrc ctx init then.
Quoted 5 lines
Quoted 1 line
All patches up to this one merged.
Ok, I've discussed this quickly with Damien on irc. We decided to cut away the
ring->ctxpart of this patch for now to be able to move on. -Daniel
Quoted 7 lines
As you've seen, removing
ringbuffer->ctxcauses serious problems with the plumbing later on. This can be renamed (perhaps to lrc) and removed from legacy init.Each ring buffer belongs to a specific context - it makes sense to me to keep this information within the ringbuffer structure so that we don't have to pass the context pointer around everywhere.
I agree that it causes trouble with the follow-up patches, but I'm not sold on this being a terrible good idea. After all for ELSP we don't want to submit a ring, we want to submit the full context. So if the code that's supposed to do the execlist ctx submission only has the pointer to the ring object, the layer looks a bit wrong.
Same was iirc about the add_request part.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 89 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Wednesday, August 13, 2014 4:16 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 11 lines · Thomas
Quoted 11 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 3:21 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 5 lines
Quoted 5 lines · Daniel Vetter
Quoted 4 lines · Thomas Daniel
Quoted 3 lines
From: Oscar Mateo <[email protected]>
Any given ringbuffer is unequivocally tied to one context and one
engine.
Quoted 52 lines
Quoted 47 lines
Quoted 11 lines
Quoted 11 lines
By setting the appropriate pointers to them, the ringbuffer struct holds all the infromation you might need to submit a workload for processing, Execlists style.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 7 insertions(+)Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c int intel_lr_context_deferred_create(struct
Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -132,6 +132,8 @@ int intel_lr_context_deferred_create(struct
intel_context*ctx,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct
Quoted 14 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-0return ret; } + ringbuf->ring = ring; + ringbuf->ctx = ctx; ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.c +0
-0@@ -1570,6 +1570,8 @@ static int intel_init_ring_buffer(struct
drm_device*dev,Quoted 14 lines
drivers/gpu/drm/i915/intel_ringbuffer.c static int intel_init_ring_buffer(struct drm_device *dev, · line 1574
Quoted 5 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +2
-0INIT_LIST_HEAD (&ring->active_list);INIT_LIST_HEAD (&ring->request_list); ringbuf->size =32 *PAGE_SIZE ; + ringbuf->ring = ring; + ringbuf->ctx = ring->default_context;That doesn't make a terribly lot of sense tbh. I fear it's one of these slight confusions which will take tons of patches to clean up. Why exactly do we need the
ring->ctxpointer?If we only need this for lrc I want to name it accordingly, to make sure legacy code doesn't grow stupid ideas. And also we should only initialize this in the lrc ctx init then.
Quoted 5 lines
Quoted 1 line
All patches up to this one merged.
Ok, I've discussed this quickly with Damien on irc. We decided to cut away the
ring->ctxpart of this patch for now to be able to move on. -DanielQuoted 7 lines
As you've seen, removing
ringbuffer->ctxcauses serious problems with the plumbing later on. This can be renamed (perhaps to lrc) and removed from legacy init.Each ring buffer belongs to a specific context - it makes sense to me to keep this information within the ringbuffer structure so that we don't have to pass the context pointer around everywhere.
Quoted 5 lines
I agree that it causes trouble with the follow-up patches, but I'm not sold on this being a terrible good idea. After all for ELSP we don't want to submit a ring, we want to submit the full context. So if the code that's supposed to do the execlist ctx submission only has the pointer to the ring object, the layer looks a bit wrong.
When it comes to the execlist submission (actually as early as the execlist request queueing), the engine and context are indeed used and required. intel_logical_ring_advance_and_submit() is the lrc function analogous to __intel_ring_advance() and I believe the initial creation of intel_lrc.c was actually done by copying intel_ringbuffer.c. This explains why some of the lrc code is perhaps not as it would have been if this had been designed from scratch, and there is room for future improvement. advance_and_submit therefore only gets the ringbuffer struct and uses the context pointer in that struct to get the logical ring context itself. At that point the engine, context and new tail pointer are handed over to the execlist queue backend.
Thomas.
Quoted 7 lines
Same was iirc about the
add_requestpart.
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 11 lines · Thomas
When it comes to the execlist submission (actually as early as the execlist request queueing), the engine and context are indeed used and required.
intel_logical_ring_advance_and_submit()is the lrc function analogous to__intel_ring_advance()and I believe the initial creation ofintel_lrc.cwas actually done by copyingintel_ringbuffer.c. This explains why some of the lrc code is perhaps not as it would have been if this had been designed from scratch, and there is room for future improvement.advance_and_submittherefore only gets the ringbuffer struct and uses the context pointer in that struct to get the logical ring context itself. At that point the engine, context and new tail pointer are handed over to the execlist queue backend.
I guess I need to clarify: Does it make sense to move the ELSP respectively the submission to the execlist scheduler queue out of there up a few levels into the execlist cmd submission function? Is it possible or is there some technical reason that I'm overlooking?
I want to know what exactly I'm dealing with here before I sign up for it by merging the patches as-is and asking for a cleanup. I doesn't look bad really, but there's always a good chance that I've overlooked a bigger dragon.
Since you have the patches and worked with them I'm asking you such explorative questions. Ofc I can do this checking myself, but that takes time ... This doesn't mean that you have to implement the changes, just be reasonable confident that it will work out as a cleanup on top. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 23 lines · Daniel Vetter
Quoted 11 lines · Thomas
When it comes to the execlist submission (actually as early as the execlist request queueing), the engine and context are indeed used and required.
intel_logical_ring_advance_and_submit()is the lrc function analogous to__intel_ring_advance()and I believe the initial creation ofintel_lrc.cwas actually done by copyingintel_ringbuffer.c. This explains why some of the lrc code is perhaps not as it would have been if this had been designed from scratch, and there is room for future improvement.advance_and_submittherefore only gets the ringbuffer struct and uses the context pointer in that struct to get the logical ring context itself. At that point the engine, context and new tail pointer are handed over to the execlist queue backend.I guess I need to clarify: Does it make sense to move the ELSP respectively the submission to the execlist scheduler queue out of there up a few levels into the execlist cmd submission function? Is it possible or is there some technical reason that I'm overlooking?
I want to know what exactly I'm dealing with here before I sign up for it by merging the patches as-is and asking for a cleanup. I doesn't look bad really, but there's always a good chance that I've overlooked a bigger dragon.
Quoted 4 lines
Since you have the patches and worked with them I'm asking you such explorative questions. Ofc I can do this checking myself, but that takes time ... This doesn't mean that you have to implement the changes, just be reasonable confident that it will work out as a cleanup on top.
To clarify more the context: Currently you're replies sound like "This is what it looks like and I don't really know why nor whether we can change that". That's not confidence instilling and that makes maintainers reluctant to merge patches for fear of needing to fix things themselves ;-)
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 15 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 4:37 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 3 lines · Daniel Vetter
Quoted 2 lines · Thomas
When it comes to the execlist submission (actually as early as the execlist request queueing), the engine and context are indeed used and
Quoted 17 lines
required.
Quoted 6 lines
Quoted 6 lines
intel_logical_ring_advance_and_submit()is the lrc function analogous to__intel_ring_advance()and I believe the initial creation ofintel_lrc.cwas actually done by copyingintel_ringbuffer.c. This explains why some of the lrc code is perhaps not as it would have been if this had been designed from scratch, and there is room for futureimprovement.
Quoted 9 lines
Quoted 4 lines
advance_and_submittherefore only gets the ringbuffer struct and uses the context pointer in that struct to get the logical ring context itself. At that point the engine, context and new tail pointer are handed over to the execlist queue backend.I guess I need to clarify: Does it make sense to move the ELSP respectively the submission to the execlist scheduler queue out of there up a few levels into the execlist cmd submission function? Is it possible or is there some technical reason that I'm overlooking?
Yes this would make sense, and we already have a separate emit_request vfunc which is only used in lrc mode so we can for example change the signature to accept a drm_i915_gem_request* directly and take the ctx and engine from there.
Quoted 11 lines
Quoted 10 lines
I want to know what exactly I'm dealing with here before I sign up for it by merging the patches as-is and asking for a cleanup. I doesn't look bad really, but there's always a good chance that I've overlooked a bigger dragon.
Since you have the patches and worked with them I'm asking you such explorative questions. Ofc I can do this checking myself, but that takes time ... This doesn't mean that you have to implement the changes, just be reasonable confident that it will work out as a cleanup on
top.
Understood.
Quoted 3 lines
To clarify more the context: Currently you're replies sound like "This is what it looks like and I don't really know why nor whether we can change that".
You're right, I don't know why it was done this way. But I can see that there is no problem to change it later - it's only a piece of code after all...
Quoted 3 lines
That's not confidence instilling and that makes maintainers reluctant to merge patches for fear of needing to fix things themselves ;-)
If it helps, I can tell you that several guys in our team are working with this code and we have a vested interest in making sure the quality is as high as possible.
Cheers,
Thomas.
Quoted 5 lines
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbuffer
Quoted 28 lines · Thomas
Quoted 28 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 4:37 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 08/43] drm/i915/bdw: Add a context and an engine pointers to the ringbufferQuoted 3 lines · Daniel Vetter
Quoted 2 lines · Thomas
When it comes to the execlist submission (actually as early as the execlist request queueing), the engine and context are indeed used and
required.
Quoted 6 lines
Quoted 6 lines
intel_logical_ring_advance_and_submit()is the lrc function analogous to__intel_ring_advance()and I believe the initial creation ofintel_lrc.cwas actually done by copyingintel_ringbuffer.c. This explains why some of the lrc code is perhaps not as it would have been if this had been designed from scratch, and there is room for futureimprovement.
Quoted 5 lines
Quoted 4 lines
advance_and_submittherefore only gets the ringbuffer struct and uses the context pointer in that struct to get the logical ring context itself. At that point the engine, context and new tail pointer are handed over to the execlist queue backend.
Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
I guess I need to clarify: Does it make sense to move the ELSP respectively the submission to the execlist scheduler queue out of there up a few levels into the execlist cmd submission function? Is it possible or is there some technical reason that I'm overlooking?
Yes this would make sense, and we already have a separate
emit_requestvfunc which is only used in lrc mode so we can for example change the signature to accept a drm_i915_gem_request* directly and take the ctx and engine from there.
Hm, I didn't spot the emit_request vfunc yet. Probably another one that I'll ask you to fold in ;-)
Quoted 18 lines
Quoted 10 lines
Quoted 9 lines
I want to know what exactly I'm dealing with here before I sign up for it by merging the patches as-is and asking for a cleanup. I doesn't look bad really, but there's always a good chance that I've overlooked a bigger dragon.
Since you have the patches and worked with them I'm asking you such explorative questions. Ofc I can do this checking myself, but that takes time ... This doesn't mean that you have to implement the changes, just be reasonable confident that it will work out as a cleanup on
top.
Understood.
Quoted 3 lines
To clarify more the context: Currently you're replies sound like "This is what it looks like and I don't really know why nor whether we can change that".
You're right, I don't know why it was done this way. But I can see that there is no problem to change it later - it's only a piece of code after all...
Quoted 6 lines
Quoted 3 lines
That's not confidence instilling and that makes maintainers reluctant to merge patches for fear of needing to fix things themselves ;-)
If it helps, I can tell you that several guys in our team are working with this code and we have a vested interest in making sure the quality is as high as possible.
Ok, I think you get the hang of how this "guide your maintainer into accepting stuff" game works ;-) I'll take your word for it that there's no dragon hiding and that you'll bravely fight it anyway and will merge in a few more patches. And I'll do a JIRA to jot down the restructuring we need to do.
Merging might be a bit slower since I'm heading to Chicago on Saturday already, so I might ask you to resend the remaining patches.
Cheers, Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 1/1 drm/i915: Add temporary ring->ctx backpointer
From: Oscar Mateo <[email protected]>
The execlist patches have a bit a convoluted and long history and due to that have the actual submission still misplaced deeply burried in the low-level ringbuffer handling code. This design goes back to the legacy ringbuffer code with its tricky lazy request and simple work submissiion using ring tail writes. For that reason they need a ring->ctx backpointer.
The goal is to unburry that code and move it up into a level where the full execlist context is available so that we can ditch this backpointer. Until that's done make it really obvious that there's work still to be done.
--
Thomas, please ack this patch and the general plan we've discussed. Then I'll start pulling in more patches and I'll do the s/ctx/FIXME_lrc_ctx/ on the fly.
-Daniel
--- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +++++++ 2 files changed, 9 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +2 -0
@@ -1086,6 +1086,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, } ringbuf->ring = ring; + ringbuf->FIXME_lrc_ctx = ctx; + ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size; ringbuf->head =0 ;
drivers/gpu/drm/i915/intel_ringbuffer.h +7 -0
@@ -99,6 +99,13 @@ struct intel_ringbuffer {struct intel_engine_cs *ring; +/* +* FIXME: This backpointer is an artifact of the history of how the +* execlist patches came into being. It will get removed once the basic +* code has landed. +*/ +struct intel_context *FIXME_lrc_ctx; +u32 head;u32 tail;int space;
Signature · 1 line
2.0.1
Re: [PATCH] drm/i915: Add temporary ring->ctx backpointer
Quoted 22 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]]
Sent: Thursday, August 14, 2014 5:28 PM
To: Intel Graphics Development
Cc: Mateo Lozano, Oscar; Daniel, Thomas; Daniel Vetter
Subject: [PATCH] drm/i915: Add temporaryring->ctxbackpointerFrom: Oscar Mateo <[email protected]>
The execlist patches have a bit a convoluted and long history and due to that have the actual submission still misplaced deeply burried in the low-level ringbuffer handling code. This design goes back to the legacy ringbuffer code with its tricky lazy request and simple work submissiion using ring tail writes. For that reason they need a
ring->ctxbackpointer.The goal is to unburry that code and move it up into a level where the full execlist context is available so that we can ditch this backpointer. Until that's done make it really obvious that there's work still to be done.
Quoted 7 lines
Cc Oscar Mateo <[email protected]>Cc Thomas Daniel <[email protected]>Signed-off-by Daniel Vetter <[email protected]>--
Thomas, please ack this patch and the general plan we've discussed.
Quoted 44 lines
Then I'll start pulling in more patches and I'll do the s/ctx/FIXME_lrc_ctx/ on the fly.
(quoted diff) +0
-2-Daniel --- drivers/gpu/drm/i915/intel_lrc.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.h | 7 +++++++ 2 files changed, 9 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +2
-0@@ -1086,6 +1086,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, } ringbuf->ring = ring; + ringbuf->FIXME_lrc_ctx = ctx; + ringbuf->size =32 *PAGE_SIZE ; ringbuf->effective_size = ringbuf->size;drivers/gpu/drm/i915/intel_lrc.c +0
-0ringbuf->head =0 ;drivers/gpu/drm/i915/intel_ringbuffer.h +7
-1@@ -99,6 +99,13 @@ struct intel_ringbuffer {struct intel_engine_cs *ring; +/* +* FIXME: This backpointer is an artifact of the history of how the +* execlist patches came into being. It will get removed once the basic +* code has landed. +*/ +struct intel_context *FIXME_lrc_ctx; +u32 head;u32 tail;int space; --2.0.1
PATCH 9/43 drm/i915/bdw: Populate LR contexts (somewhat)
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
For the most part, logical ring context objects are similar to hardware contexts in that the backing object is meant to be opaque. There are some exceptions where we need to poke certain offsets of the object for initialization, updating the tail pointer or updating the PDPs.
For our basic execlist implementation we'll only need our PPGTT PDs, and ringbuffer addresses in order to set up the context. With previous patches, we have both, so start prepping the context to be load.
Before running a context for the first time you must populate some fields in the context object. These fields begin 1 PAGE + LRCA, ie. the first page (in 0 based counting) of the context image. These same fields will be read and written to as contexts are saved and restored once the system is up and running.
Many of these fields are completely reused from previous global
registers: ringbuffer head/tail/control, context control matches some previous MI_SET_CONTEXT flags, and page directories. There are other fields which we don't touch which we may want in the future.
v2: CTX_LRI_HEADER_0 is MI_LOAD_REGISTER_IMM(14) for render and (11) for other engines.
v3: Several rebases and general changes to the code.
v4: Squash with "Extract LR context object populating"
Also, Damien's review comments:
- Set the Force Posted bit on the LRI header, as the BSpec suggest we do.
- Prevent warning when compiling a 32-bits kernel without HIGHMEM64.
- Add a clarifying comment to the context population code.
v5: Damien's review comments:
- The third MI_LOAD_REGISTER_IMM in the context does not set Force Posted.
- Remove dead code.
v6: Add a note about the (presumed) differences between BDW and CHV state contexts. Also, Brad's review comments:
- Use the _MASKED_BIT_ENABLE, upper_32_bits and lower_32_bits macros.
- Be less magical about how we set the ring size in the context.
--- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 159 +++++++++++++++++++++++++++++++++++++- 2 files changed, 156 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +1 -0
@@ -282,6 +282,7 @@* address/value pairs. Don't overdue it, though, x <= 2^4 must hold! */ #define MI_LOAD_REGISTER_IMM (x) MI_INSTR(0x22, 2*(x)-1) +#define MI_LRI_FORCE_POSTED (1<<12)#define MI_STORE_REGISTER_MEM (x) MI_INSTR(0x24, 2*(x)-1)#define MI_STORE_REGISTER_MEM_GEN8 (x) MI_INSTR(0x24, 3*(x)-1)#define MI_SRM_LRM_GLOBAL_GTT (1<<22)
drivers/gpu/drm/i915/intel_lrc.c +155 -4
181 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH 10/43 drm/i915/bdw: Deferred creation of user-created LRCs
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
The backing objects and ringbuffers for contexts created via open fd are actually empty until the user starts sending execbuffers to them. At that point, we allocate & populate them. We do this because, at create time, we really don't know which engine is going to be used with the context later on (and we don't want to waste memory on objects that we might never use).
v2: As contexts created via ioctl can only be used with the render ring, we have enough information to allocate & populate them right away.
v3: Defer the creation always, even with ioctl-created contexts, as requested by Daniel Vetter.
--- drivers/gpu/drm/i915/i915_gem_context.c | 7 +++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++++++ 2 files changed, 11 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_gem_context.c +3 -4
@@ -784,9 +784,9 @@ int i915_switch_context(struct intel_engine_cs *ring,return do_switch (ring, to); } -static bool hw_context_enabled (struct drm_device *dev) +static bool contexts_enabled (struct drm_device *dev) { -return to_i915 (dev)->hw_context_size; +return i915.enable_execlists ||to_i915 (dev)->hw_context_size; } int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
@@ -797,8 +797,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,struct intel_context *ctx;int ret; -/* FIXME: allow user-created LR contexts as well */ -if (!hw_context_enabled (dev)) +if (!contexts_enabled (dev))return -ENODEV ; ret =i915_mutex_lock_interruptible (dev);
drivers/gpu/drm/i915/i915_gem_execbuffer.c +8 -0
@@ -951,6 +951,14 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,return ERR_PTR (-EIO ); } +if (i915.enable_execlists && !ctx->engine[ring->id].state) { +int ret =intel_lr_context_deferred_create (ctx, ring); +if (ret) { +DRM_DEBUG ("Could not create LRC %u: %d\n" , ctx_id, ret); +return ERR_PTR (ret); + } + } +return ctx; }
Signature · 1 line
1.7.9.5
Re: [PATCH 10/43] drm/i915/bdw: Deferred creation of user-created LRCs
Quoted 9 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
The backing objects and ringbuffers for contexts created via open fd are actually empty until the user starts sending execbuffers to them. At that point, we allocate & populate them. We do this because, at create time, we really don't know which engine is going to be used with the context later on (and we don't want to waste memory on objects that we might never use).
Quoted 8 lines
v2: As contexts created via ioctl can only be used with the render ring, we have enough information to allocate & populate them right away.
v3: Defer the creation always, even with ioctl-created contexts, as requested by Daniel Vetter.
Signed-off-by Oscar Mateo <[email protected]>
This patch seems to miss the hunk to remove
/* FIXME: we really only want to do this for initialized rings */ if (i915.enable_execlists) intel_lr_context_deferred_create(ctx, ring);
Also I just realized that that code completely lacks error handling.
If it's not already there please quickly submit a fixup patch. -Daniel
Quoted 57 lines
--- drivers/gpu/drm/i915/i915_gem_context.c | 7 +++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 8 ++++++++ 2 files changed, 11 insertions(+), 4 deletions(-)drivers/gpu/drm/i915/i915_gem_context.c +3
-4@@ -784,9 +784,9 @@ int i915_switch_context(struct intel_engine_cs *ring,return do_switch (ring, to); } -static bool hw_context_enabled (struct drm_device *dev) +static bool contexts_enabled (struct drm_device *dev) { -return to_i915 (dev)->hw_context_size; +return i915.enable_execlists ||to_i915 (dev)->hw_context_size; } int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,@@ -797,8 +797,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,struct intel_context *ctx;int ret; -/* FIXME: allow user-created LR contexts as well */ -if (!hw_context_enabled (dev)) +if (!contexts_enabled (dev))return -ENODEV ; ret =i915_mutex_lock_interruptible (dev);drivers/gpu/drm/i915/i915_gem_execbuffer.c +8
-0@@ -951,6 +951,14 @@ i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,return ERR_PTR (-EIO ); } +if (i915.enable_execlists && !ctx->engine[ring->id].state) { +int ret =intel_lr_context_deferred_create (ctx, ring); +if (ret) { +DRM_DEBUG ("Could not create LRC %u: %d\n" , ctx_id, ret); +return ERR_PTR (ret); + } + } +return ctx; }Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 11/43 drm/i915/bdw: Render moot context reset and switch with Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of lrc_enabled and centralized everything in the sanitized i915.enbale_execlists instead.
--- drivers/gpu/drm/i915/i915_gem_context.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +9 -0
@@ -380,6 +380,9 @@ void i915_gem_context_reset(struct drm_device *dev)struct drm_i915_private *dev_priv = dev->dev_private;int i; +if (i915.enable_execlists) +return ; +/* Prevent the hardware from restoring the last context (which hung) on * the next switch */ for (i =0 ; i <I915_NUM_RINGS ; i++) {
@@ -514,6 +517,9 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) ppgtt->enable (ppgtt); } +if (i915.enable_execlists) +return 0 ; +/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))return 0 ;
@@ -769,6 +775,9 @@ int i915_switch_context(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private; +if (i915.enable_execlists) +return 0 ; +WARN_ON (!mutex_is_locked (&dev_priv->dev->struct_mutex));if (to->legacy_hw_ctx.rcs_state ==NULL ) {/* We have the fake context */
Signature · 1 line
1.7.9.5
Re: [PATCH 11/43] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 18 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enbale_execlists instead.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_context.c | 9 +++++++++ 1 file changed, 9 insertions(+)drivers/gpu/drm/i915/i915_gem_context.c +0
-0
drivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device *dev) · line 384
Quoted 5 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0@@ -380,6 +380,9 @@ void i915_gem_context_reset(struct drm_device *dev)struct drm_i915_private *dev_priv = dev->dev_private;int i; +if (i915.enable_execlists) +return ;
This will conflict badly with Alistair's patch at a functional level. I'm pretty sure that we want _some_ form of reset for the context state, since the hw didn't just magically load the previously running context. So NACK on this hunk.
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 521
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +3
-0+/* Prevent the hardware from restoring the last context (which hung) on * the next switch */ for (i =0 ; i <I915_NUM_RINGS ; i++) {@@ -514,6 +517,9 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) ppgtt->enable (ppgtt); } +if (i915.enable_execlists) +return 0 ;
Again this conflicts with Alistair's patch. Furthermore it looks redudant since you no-op out i915_switch_context separately.
drivers/gpu/drm/i915/i915_gem_context.c int i915_switch_context(struct intel_engine_cs *ring, · line 779
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +3
-0+/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))return 0 ;@@ -769,6 +775,9 @@ int i915_switch_context(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private; +if (i915.enable_execlists) +return 0 ;
I've hoped we don't need this with the legacy ringbuffer cmdsubmission fuly split out. If there are other paths (resume, gpu reset) where this comes into play then I guess we need to look at where the best place is to make this call. So until this comes with a bit a better justification I'll punt on this for now.
-Daniel
Quoted 11 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+WARN_ON (!mutex_is_locked (&dev_priv->dev->struct_mutex));if (to->legacy_hw_ctx.rcs_state ==NULL ) {/* We have the fake context */ Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 11/43] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 35 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 3:30 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 11/43] drm/i915/bdw: Render moot context reset and switch with Execlistsdrivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device
Quoted 19 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enbale_execlists instead.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_context.c | 9 +++++++++ 1 file changed, 9 insertions(+)drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -380,6 +380,9 @@ void i915_gem_context_reset(struct drm_device*dev)
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0struct drm_i915_private *dev_priv = dev->dev_private;int i;
Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device *dev) · line 384
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return ;This will conflict badly with Alistair's patch at a functional level. I'm pretty sure that we want _some_ form of reset for the context state, since the hw didn't just magically load the previously running context. So NACK on this hunk.
OK I'll wait to see the final version of Alistair's patch and decide what to do about this hunk.
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device · line 386
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+/* Prevent the hardware from restoring the last context (which hung) on
Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0* the next switch */ for (i = 0; i < I915_NUM_RINGS; i++) { @@ -514,6 +517,9 @@ int
i915_gem_context_enable(struct drm_i915_private *dev_priv)drivers/gpu/drm/i915/i915_gem_context.c +0
-0ppgtt->enable (ppgtt); }
Quoted 5 lines
drivers/gpu/drm/i915/i915_gem_context.c
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return 0 ;Again this conflicts with Alistair's patch. Furthermore it looks redudant since you no-op out
i915_switch_contextseparately.
I don't think this is a conflict. Doesn't Alistair's change here just involve writing PDPs for full PPGTT? We don't want to do that in lrc mode.
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))return 0 ;@@ -769,6 +775,9 @@ int i915_switch_context(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;
Quoted 8 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_switch_context(struct intel_engine_cs · line 779
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return 0 ;I've hoped we don't need this with the legacy ringbuffer cmdsubmission fuly split out. If there are other paths (resume, gpu reset) where this comes into play then I guess we need to look at where the best place is to make this call. So until this comes with a bit a better justification I'll punt on this for now. -Daniel
Yes, the command submission lrc path doesn't call this but other codepaths do. If we keep the check in context_enable() the only remaining call I see is in i915_gpu_idle(). I don't mind if the check is done there but perhaps a WARN_ON should then be added into switch_context() because we don't want to be putting illegal MI_SET_CONTEXT commands into the ring.
Thomas.
Quoted 18 lines
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+WARN_ON (!mutex_is_locked (&dev_priv->dev->struct_mutex));if (to->legacy_hw_ctx.rcs_state ==NULL ) {/* We have the fake context */
--
1.7.9.5Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 11/43] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 54 lines · Thomas
Quoted 35 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 3:30 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 11/43] drm/i915/bdw: Render moot context reset and switch with Execlistsdrivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device
Quoted 19 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enbale_execlists instead.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_context.c | 9 +++++++++ 1 file changed, 9 insertions(+)drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -380,6 +380,9 @@ void i915_gem_context_reset(struct drm_device*dev)
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0struct drm_i915_private *dev_priv = dev->dev_private;int i;Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device *dev) · line 384
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return ;This will conflict badly with Alistair's patch at a functional level. I'm pretty sure that we want _some_ form of reset for the context state, since the hw didn't just magically load the previously running context. So NACK on this hunk.
OK I'll wait to see the final version of Alistair's patch and decide what to do about this hunk.
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c void i915_gem_context_reset(struct drm_device · line 386
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+/* Prevent the hardware from restoring the last context (which hung) on
Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0* the next switch */ for (i = 0; i < I915_NUM_RINGS; i++) { @@ -514,6 +517,9 @@ int
i915_gem_context_enable(struct drm_i915_private *dev_priv)drivers/gpu/drm/i915/i915_gem_context.c +0
-0ppgtt->enable (ppgtt); }
Quoted 7 lines
Quoted 5 lines
drivers/gpu/drm/i915/i915_gem_context.c
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return 0 ;Again this conflicts with Alistair's patch. Furthermore it looks redudant since you no-op out
i915_switch_contextseparately.I don't think this is a conflict. Doesn't Alistair's change here just involve writing PDPs for full PPGTT? We don't want to do that in lrc mode.
Oh, just context conflict since Alistair's patch removes the next line ;-) Also I shuffled some of the ppgtt code right above this around.
Quoted 16 lines
Quoted 8 lines
Quoted 8 lines
drivers/gpu/drm/i915/i915_gem_context.c +1
-0+/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))return 0 ;@@ -769,6 +775,9 @@ int i915_switch_context(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;Quoted 8 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_switch_context(struct intel_engine_cs · line 779
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (i915.enable_execlists) +return 0 ;I've hoped we don't need this with the legacy ringbuffer cmdsubmission fuly split out. If there are other paths (resume, gpu reset) where this comes into play then I guess we need to look at where the best place is to make this call. So until this comes with a bit a better justification I'll punt on this for now. -Daniel
Quoted 5 lines
Yes, the command submission lrc path doesn't call this but other codepaths do. If we keep the check in
context_enable()the only remaining call I see is ini915_gpu_idle(). I don't mind if the check is done there but perhaps aWARN_ONshould then be added intoswitch_context()because we don't want to be putting illegalMI_SET_CONTEXTcommands into the ring.
Yeah, that sounds like a plan. There's still a bit of confusion around the ctx reset in Alistairs patch but unrelated to the code bits we've discussed here. So when you resend this revised patch can you please merge Alistair's patch into your baseline to avoid conflicts.
Thanks, Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 1/1 drm/i915/bdw: Render moot context reset and switch with Execlists
In reply to Thomas DanielThese two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of lrc_enabled and centralized everything in the sanitized i915.enable_execlists instead.
v3: Rebased. Corrected a typo in comment for i915_switch_context and added a comment that it should not be called in execlist mode. Added WARN_ON if i915_switch_context is called in execlist mode. Moved check for execlist mode out of i915_switch_context and into callers. Added comment in context_reset explaining why nothing is done in execlist mode.
--- drivers/gpu/drm/i915/i915_gem.c | 8 +++++--- drivers/gpu/drm/i915/i915_gem_context.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +5 -3
@@ -2981,9 +2981,11 @@ int i915_gpu_idle(struct drm_device *dev)/* Flush everything onto the inactive list. */ for_each_ring (ring, dev_priv, i) { - ret =i915_switch_context (ring, ring->default_context); -if (ret) -return ret; +if (!i915.enable_execlists) { + ret =i915_switch_context (ring, ring->default_context); +if (ret) +return ret; + } ret =intel_ring_idle (ring);if (ret)
drivers/gpu/drm/i915/i915_gem_context.c +15 -1
@@ -289,6 +289,12 @@ void i915_gem_context_reset(struct drm_device *dev)struct drm_i915_private *dev_priv = dev->dev_private;int i; +/* In execlists mode we will unreference the context when the execlist +* queue is cleared and the requests destroyed. +*/ +if (i915.enable_execlists) +return ; +for (i =0 ; i <I915_NUM_RINGS ; i++) {struct intel_engine_cs *ring = &dev_priv->ring[i];struct intel_context *lctx = ring->last_context;
@@ -397,6 +403,9 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)BUG_ON (!dev_priv->ring[RCS ].default_context); +if (i915.enable_execlists) +return 0 ; +for_each_ring (ring, dev_priv, i) { ret =i915_switch_context (ring, ring->default_context);if (ret)
@@ -637,14 +646,19 @@ unpin_out:* * The context life cycle is simple. The context refcount is incremented and * decremented by 1 and create and destroy. If the context is in use by the GPU, -* it will have a refoucnt > 1. This allows us to destroy the context abstract +* it will have a refcount > 1. This allows us to destroy the context abstract * object while letting the normal object tracking destroy the backing BO. +* +* This function should not be used in execlists mode. Instead the context is +* switched by writing to the ELSP and requests keep a reference to their +* context. */ int i915_switch_context (struct intel_engine_cs *ring,struct intel_context *to) {struct drm_i915_private *dev_priv = ring->dev->dev_private; +WARN_ON (i915.enable_execlists);WARN_ON (!mutex_is_locked (&dev_priv->dev->struct_mutex));if (to->legacy_hw_ctx.rcs_state ==NULL ) {/* We have the fake context */
Signature · 1 line
1.7.9.5
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.
Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
-Chris
Signature · 1 line
Chris Wilson, Intel Open Source Technology Centre
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 16 lines · Chris Wilson
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.
Quoted 3 lines
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
I think it's ok-ish for now. Maybe we need to reconsider when we wire up lrc reclaim - which is the real user of the switch_context in gpu_idle. The problem I have though is that I can't parse the subject of the patch, someone please translate that to simplified English for me. I can do the replacement while applying.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 21 lines · Daniel Vetter
Quoted 16 lines · Chris Wilson
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.Quoted 3 lines
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
Quoted 6 lines
I think it's ok-ish for now. Maybe we need to reconsider when we wire up lrc reclaim - which is the real user of the
switch_contextingpu_idle. The problem I have though is that I can't parse the subject of the patch, someone please translate that to simplified English for me. I can do the replacement while applying.
-Daniel
"Render moot" usually means something like "make obsolete", not sure about the rest.
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
In reply to Daniel VetterQuoted 21 lines · Daniel Vetter
Quoted 16 lines · Chris Wilson
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.Quoted 3 lines
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
Quoted 5 lines
I think it's ok-ish for now. Maybe we need to reconsider when we wire up lrc reclaim - which is the real user of the
switch_contextingpu_idle. The problem I have though is that I can't parse the subject of the patch, someone please translate that to simplified English for me. I can do the replacement while applying.
No, it is not. execlists is badly designed and this is a further symptom of that.
-Chris
Signature · 1 line
Chris Wilson, Intel Open Source Technology Centre
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 28 lines · Chris Wilson
Quoted 21 lines · Daniel Vetter
Quoted 16 lines · Chris Wilson
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.Quoted 3 lines
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
Quoted 5 lines
I think it's ok-ish for now. Maybe we need to reconsider when we wire up lrc reclaim - which is the real user of the
switch_contextingpu_idle. The problem I have though is that I can't parse the subject of the patch, someone please translate that to simplified English for me. I can do the replacement while applying.
Quoted 4 lines
No, it is not. execlists is badly designed and this is a further symptom of that.
-Chris
Thomas is not available and I am replying on his behalf. Is the following subject is good for this patch?
"Don't execute context reset and switch when using Execlists"
regards
Arun
Re: [PATCH] drm/i915/bdw: Render moot context reset and switch with Execlists
Quoted 29 lines · Arun
Quoted 28 lines · Chris Wilson
Quoted 26 lines · Daniel Vetter
Quoted 16 lines · Chris Wilson
Quoted 6 lines · Thomas Daniel
These two functions make no sense in an Logical Ring Context & Execlists world.
v2: We got rid of
lrc_enabledand centralized everything in the sanitized i915.enable_execlists instead.Quoted 8 lines
Signed-off-by Oscar Mateo <[email protected]>v3: Rebased. Corrected a typo in comment for
i915_switch_contextand added a comment that it should not be called in execlist mode. AddedWARN_ONifi915_switch_contextis called in execlist mode. Moved check for execlist mode out ofi915_switch_contextand into callers. Added comment incontext_resetexplaining why nothing is done in execlist mode.Quoted 3 lines
No, this is not the way. The requirement is to reduce the number of special cases not increase them. These should be evaluated to be no-ops when execlists is used.
I think it's ok-ish for now. Maybe we need to reconsider when we wire up lrc reclaim - which is the real user of the
switch_contextingpu_idle. The problem I have though is that I can't parse the subject of the patch, someone please translate that to simplified English for me. I can do the replacement while applying.
Quoted 8 lines
Quoted 4 lines
No, it is not. execlists is badly designed and this is a further symptom of that.
-ChrisThomas is not available and I am replying on his behalf. Is the following subject is good for this patch?
"Don't execute context reset and switch when using Execlists"
Yeah, I think that's more parseable by mere mortals^W^W non-native speakers. Pulled in.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 12/43 drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the ppgtt->enable was part of the ring init, where it logically belongs.
--- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +5 -0
@@ -852,6 +852,11 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)if (USES_FULL_PPGTT (dev))continue ; +/* In the case of Execlists, we don't want to write the PDPs +* in the legacy way (they live inside the context now) */ +if (i915.enable_execlists) +return 0 ; + ret = ppgtt->switch_mm (ppgtt, ring, true);if (ret) goto err_out;
Signature · 1 line
1.7.9.5
Re: [PATCH 12/43] drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
Quoted 22 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the
ppgtt->enablewas part of the ring init, where it logically belongs.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+)drivers/gpu/drm/i915/i915_gem_gtt.c +0
-0
drivers/gpu/drm/i915/i915_gem_gtt.c static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt) · line 858
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_gtt.c +4
-0@@ -852,6 +852,11 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)if (USES_FULL_PPGTT (dev))continue ; +/* In the case of Execlists, we don't want to write the PDPs +* in the legacy way (they live inside the context now) */ +if (i915.enable_execlists) +return 0 ;
This looks like it should be a continue to enable PPGTT on more rings then the render ring?
Signature · 1 line
Damien
PATCH 12/43 drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the ppgtt->enable was part of the ring init, where it logically belongs.
v3: Move the check to the start of the enable PPGTT function. None of the legacy PPGTT enabling is required when using LRCs as the PPGTT is enabled in the context descriptor and the PDPs are written in the LRC.
--- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +5 -0
@@ -843,6 +843,11 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)struct intel_engine_cs *ring;int j, ret; +/* In the case of Execlists, we don't want to write the PDPs +* in the legacy way (they live inside the context now) */ +if (i915.enable_execlists) +return 0 ; +for_each_ring (ring, dev_priv, j) {I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_ENABLE (GFX_PPGTT_ENABLE ));
Signature · 1 line
1.7.9.5
Re: [PATCH 12/43] drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
Quoted 12 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the
ppgtt->enablewas part of the ring init, where it logically belongs.
Quoted 7 lines
v3: Move the check to the start of the enable PPGTT function. None of the legacy PPGTT enabling is required when using LRCs as the PPGTT is enabled in the context descriptor and the PDPs are written in the LRC.
Signed-off-by Oscar Mateo <[email protected]>Signed-off-by Thomas Daniel <[email protected]>
Signature · 1 line
Damien
Quoted 27 lines
--- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+)drivers/gpu/drm/i915/i915_gem_gtt.c +5
-0@@ -843,6 +843,11 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)struct intel_engine_cs *ring;int j, ret; +/* In the case of Execlists, we don't want to write the PDPs +* in the legacy way (they live inside the context now) */ +if (i915.enable_execlists) +return 0 ; +for_each_ring (ring, dev_priv, j) {I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_ENABLE (GFX_PPGTT_ENABLE ));Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 12/43] drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
In reply to Thomas DanielQuoted 28 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the
ppgtt->enablewas part of the ring init, where it logically belongs.v3: Move the check to the start of the enable PPGTT function. None of the legacy PPGTT enabling is required when using LRCs as the PPGTT is enabled in the context descriptor and the PDPs are written in the LRC.
Signed-off-by Oscar Mateo <[email protected]>Signed-off-by Thomas Daniel <[email protected]>--- drivers/gpu/drm/i915/i915_gem_gtt.c | 5 +++++ 1 file changed, 5 insertions(+)drivers/gpu/drm/i915/i915_gem_gtt.c +0
-0
drivers/gpu/drm/i915/i915_gem_gtt.c static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt) · line 846
Quoted 4 lines
drivers/gpu/drm/i915/i915_gem_gtt.c +1
-0@@ -843,6 +843,11 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)struct intel_engine_cs *ring;int j, ret; +/* In the case of Execlists, we don't want to write the PDPs
This comment is misleading since you now also disable the ppgtt enable bit setting. Not that the code disabled in v2 of this patch is for aliasing ppgtt mode only anyway, so irrelevant for execlist mode. Aside: A few patches from myself will clear this up a bit better.
As-is this just looks confusing, so I'll punt for now. -Daniel
Quoted 14 lines
drivers/gpu/drm/i915/i915_gem_gtt.c +4
-0+* in the legacy way (they live inside the context now) */ +if (i915.enable_execlists) +return 0 ; +for_each_ring (ring, dev_priv, j) {I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_ENABLE (GFX_PPGTT_ENABLE ));Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 1/1 drm/i915/bdw: Don't write PDP in the legacy way when using LRCs
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
This is mostly for correctness so that we know we are running the LR context correctly (this is, the PDPs are contained inside the context object).
v2: Move the check to inside the enable PPGTT function. The switch happens in two places: the legacy context switch (that we won't hit when Execlists are enabled) and the PPGTT enable, which unfortunately we need. This would look much nicer if the ppgtt->enable was part of the ring init, where it logically belongs.
v3: Move the check to the start of the enable PPGTT function. None of the legacy PPGTT enabling is required when using LRCs as the PPGTT is enabled in the context descriptor and the PDPs are written in the LRC.
v4: Clarify comment based on review feedback.
--- drivers/gpu/drm/i915/i915_gem_gtt.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/i915/i915_gem_gtt.c +6 -0
@@ -843,6 +843,12 @@ static int gen8_ppgtt_enable(struct i915_hw_ppgtt *ppgtt)struct intel_engine_cs *ring;int j, ret; +/* In the case of execlists, PPGTT is enabled by the context descriptor +* and the PDPs are contained within the context itself. We don't +* need to do anything here. */ +if (i915.enable_execlists) +return 0 ; +for_each_ring (ring, dev_priv, j) {I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_ENABLE (GFX_PPGTT_ENABLE ));
Signature · 1 line
1.7.9.5
PATCH 13/43 drm/i915: Abstract the legacy workload submission mechanism away
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
As suggested by Daniel Vetter. The idea, in subsequent patches, is to provide an alternative to these vfuncs for the Execlists submission mechanism.
v2: Splitted into two and reordered to illustrate our intentions, instead of showing it off. Also, remove the add_request vfunc and added the stop_ring one.
--- drivers/gpu/drm/i915/i915_drv.h | 24 ++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 20 ++++++++++---------- 3 files changed, 45 insertions(+), 14 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +24 -0
@@ -1617,6 +1617,21 @@ struct drm_i915_private {/* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; +/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ +struct { +int (*do_execbuf) (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags); +int (*init_rings) (struct drm_device *dev); +void (*cleanup_ring) (struct intel_engine_cs *ring); +void (*stop_ring) (struct intel_engine_cs *ring); +bool (*is_ring_initialized) (struct intel_engine_cs *ring); + } gt; +/* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place.
@@ -2224,6 +2239,14 @@ 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); +int i915_gem_ringbuffer_submission (struct drm_device *dev, +struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags);int i915_gem_execbuffer (struct drm_device *dev,void *data,struct drm_file *file_priv); int i915_gem_execbuffer2(struct drm_device *dev, void *data,
@@ -2376,6 +2399,7 @@ void i915_gem_reset(struct drm_device *dev);bool i915_gem_clflush_object (struct drm_i915_gem_object *obj,bool force);int __must_check i915_gem_object_finish_gpu (struct drm_i915_gem_object *obj);int __must_check i915_gem_init (struct drm_device *dev); +int i915_gem_init_rings (struct drm_device *dev);int __must_check i915_gem_init_hw (struct drm_device *dev);int i915_gem_l3_remap (struct intel_engine_cs *ring,int slice);void i915_gem_init_swizzling (struct drm_device *dev);
drivers/gpu/drm/i915/i915_gem.c +11 -4
@@ -4518,7 +4518,7 @@ i915_gem_stop_ringbuffers(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_stop_ring_buffer (ring); + dev_priv->gt.stop_ring (ring); }int
@@ -4635,7 +4635,7 @@ intel_enable_blt(struct drm_device *dev)return true; } -static int i915_gem_init_rings (struct drm_device *dev) +int i915_gem_init_rings (struct drm_device *dev) {struct drm_i915_private *dev_priv = dev->dev_private;int ret;
@@ -4718,7 +4718,7 @@ i915_gem_init_hw(struct drm_device *dev)i915_gem_init_swizzling (dev); - ret =i915_gem_init_rings (dev); + ret = dev_priv->gt.init_rings (dev);if (ret)return ret;
@@ -4759,6 +4759,13 @@ int i915_gem_init(struct drm_device *dev)DRM_DEBUG_DRIVER ("allow wake ack timed out\n" ); } +if (!i915.enable_execlists) { + dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission; + dev_priv->gt.init_rings = i915_gem_init_rings; + dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; + dev_priv->gt.stop_ring = intel_stop_ring_buffer; + } +i915_gem_init_userptr (dev);i915_gem_init_global_gtt (dev);
@@ -4794,7 +4801,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_cleanup_ring_buffer (ring); + dev_priv->gt.cleanup_ring (ring); }int
drivers/gpu/drm/i915/i915_gem_execbuffer.c +10 -10
@@ -1034,14 +1034,14 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,return 0 ; } -static int -legacy_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, -struct intel_engine_cs *ring, -struct intel_context *ctx, -struct drm_i915_gem_execbuffer2 *args, -struct list_head *vmas, -struct drm_i915_gem_object *batch_obj, -u64 exec_start,u32 flags) +int +i915_gem_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags) {struct drm_clip_rect *cliprects =NULL ;struct drm_i915_private *dev_priv = dev->dev_private;
@@ -1408,8 +1408,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,else exec_start +=i915_gem_obj_offset (batch_obj, vm); - ret =legacy_ringbuffer_submission (dev, file, ring, ctx, - args, &eb->vmas, batch_obj, exec_start, flags); + ret = dev_priv->gt.do_execbuf (dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, flags);if (ret) goto err;
Signature · 1 line
1.7.9.5
Re: [PATCH 13/43] drm/i915: Abstract the legacy workload submission mechanism away
Quoted 27 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
As suggested by Daniel Vetter. The idea, in subsequent patches, is to provide an alternative to these vfuncs for the Execlists submission mechanism.
v2: Splitted into two and reordered to illustrate our intentions, instead of showing it off. Also, remove the
add_requestvfunc and added thestop_ringone.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 24 ++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 20 ++++++++++---------- 3 files changed, 45 insertions(+), 14 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -1617,6 +1617,21 @@ struct drm_i915_private {/* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; +/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ +struct {
drivers/gpu/drm/i915/i915_drv.h struct drm_i915_private { · line 1631
Quoted 10 lines
drivers/gpu/drm/i915/i915_drv.h +10
-0+int (*do_execbuf) (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags); +int (*init_rings) (struct drm_device *dev); +void (*cleanup_ring) (struct intel_engine_cs *ring); +void (*stop_ring) (struct intel_engine_cs *ring);
My rule of thumb is that with just one caller it's probably better to not have a vtable - just makes it harder to follow the code flow.
Usually (with non-borked code design at least) init/teardown functions have only one caller, so there's a good chance I'll ask you to remove them again.
drivers/gpu/drm/i915/i915_drv.h struct drm_i915_private { · line 1632
Quoted 1 line
drivers/gpu/drm/i915/i915_drv.h +1
-0+bool (*is_ring_initialized) (struct intel_engine_cs *ring);
This one is unused and I didn't really like the taste of it. So I killed it.
-Daniel
Quoted 127 lines
drivers/gpu/drm/i915/i915_drv.h +11
-0+ } gt; +/* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -2224,6 +2239,14 @@ 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); +int i915_gem_ringbuffer_submission (struct drm_device *dev, +struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags);int i915_gem_execbuffer (struct drm_device *dev,void *data,struct drm_file *file_priv); int i915_gem_execbuffer2(struct drm_device *dev, void *data,@@ -2376,6 +2399,7 @@ void i915_gem_reset(struct drm_device *dev);bool i915_gem_clflush_object (struct drm_i915_gem_object *obj,bool force);int __must_check i915_gem_object_finish_gpu (struct drm_i915_gem_object *obj);int __must_check i915_gem_init (struct drm_device *dev); +int i915_gem_init_rings (struct drm_device *dev);int __must_check i915_gem_init_hw (struct drm_device *dev);int i915_gem_l3_remap (struct intel_engine_cs *ring,int slice);void i915_gem_init_swizzling (struct drm_device *dev);drivers/gpu/drm/i915/i915_gem.c +11
-4@@ -4518,7 +4518,7 @@ i915_gem_stop_ringbuffers(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_stop_ring_buffer (ring); + dev_priv->gt.stop_ring (ring); }int @@ -4635,7 +4635,7 @@ intel_enable_blt(struct drm_device *dev)return true; } -static int i915_gem_init_rings (struct drm_device *dev) +int i915_gem_init_rings (struct drm_device *dev) {struct drm_i915_private *dev_priv = dev->dev_private;int ret;@@ -4718,7 +4718,7 @@ i915_gem_init_hw(struct drm_device *dev)i915_gem_init_swizzling (dev); - ret =i915_gem_init_rings (dev); + ret = dev_priv->gt.init_rings (dev);if (ret)return ret;@@ -4759,6 +4759,13 @@ int i915_gem_init(struct drm_device *dev)DRM_DEBUG_DRIVER ("allow wake ack timed out\n" ); } +if (!i915.enable_execlists) { + dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission; + dev_priv->gt.init_rings = i915_gem_init_rings; + dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; + dev_priv->gt.stop_ring = intel_stop_ring_buffer; + } +i915_gem_init_userptr (dev);i915_gem_init_global_gtt (dev);@@ -4794,7 +4801,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_cleanup_ring_buffer (ring); + dev_priv->gt.cleanup_ring (ring); }int drivers/gpu/drm/i915/i915_gem_execbuffer.c +10
-10@@ -1034,14 +1034,14 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,return 0 ; } -static int -legacy_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, -struct intel_engine_cs *ring, -struct intel_context *ctx, -struct drm_i915_gem_execbuffer2 *args, -struct list_head *vmas, -struct drm_i915_gem_object *batch_obj, -u64 exec_start,u32 flags) +int +i915_gem_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags) {struct drm_clip_rect *cliprects =NULL ;struct drm_i915_private *dev_priv = dev->dev_private;@@ -1408,8 +1408,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,else exec_start +=i915_gem_obj_offset (batch_obj, vm); - ret =legacy_ringbuffer_submission (dev, file, ring, ctx, - args, &eb->vmas, batch_obj, exec_start, flags); + ret = dev_priv->gt.do_execbuf (dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, flags);if (ret) goto err;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 13/43] drm/i915: Abstract the legacy workload submission mechanism away
Quoted 42 lines · Daniel Vetter
Quoted 27 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
As suggested by Daniel Vetter. The idea, in subsequent patches, is to provide an alternative to these vfuncs for the Execlists submission mechanism.
v2: Splitted into two and reordered to illustrate our intentions, instead of showing it off. Also, remove the
add_requestvfunc and added thestop_ringone.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 24 ++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 20 ++++++++++---------- 3 files changed, 45 insertions(+), 14 deletions(-)drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -1617,6 +1617,21 @@ struct drm_i915_private {/* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; +/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ +struct {drivers/gpu/drm/i915/i915_drv.h struct drm_i915_private { · line 1631
Quoted 10 lines
drivers/gpu/drm/i915/i915_drv.h +10
-0+int (*do_execbuf) (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags); +int (*init_rings) (struct drm_device *dev); +void (*cleanup_ring) (struct intel_engine_cs *ring); +void (*stop_ring) (struct intel_engine_cs *ring);My rule of thumb is that with just one caller it's probably better to not have a vtable - just makes it harder to follow the code flow.
Quoted 3 lines
Usually (with non-borked code design at least) init/teardown functions have only one caller, so there's a good chance I'll ask you to remove them again.
Also checkpatch (and my eyes!) where unhappy about the space you've put between ) and (. Fixed that too.
-Daniel
Quoted 139 lines
drivers/gpu/drm/i915/i915_drv.h struct drm_i915_private { · line 1632
Quoted 2 lines
drivers/gpu/drm/i915/i915_drv.h +1
-0+bool (*is_ring_initialized) (struct intel_engine_cs *ring);This one is unused and I didn't really like the taste of it. So I killed it.
-DanielQuoted 127 lines
drivers/gpu/drm/i915/i915_drv.h +11
-0+ } gt; +/* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -2224,6 +2239,14 @@ 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); +int i915_gem_ringbuffer_submission (struct drm_device *dev, +struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags);int i915_gem_execbuffer (struct drm_device *dev,void *data,struct drm_file *file_priv); int i915_gem_execbuffer2(struct drm_device *dev, void *data,@@ -2376,6 +2399,7 @@ void i915_gem_reset(struct drm_device *dev);bool i915_gem_clflush_object (struct drm_i915_gem_object *obj,bool force);int __must_check i915_gem_object_finish_gpu (struct drm_i915_gem_object *obj);int __must_check i915_gem_init (struct drm_device *dev); +int i915_gem_init_rings (struct drm_device *dev);int __must_check i915_gem_init_hw (struct drm_device *dev);int i915_gem_l3_remap (struct intel_engine_cs *ring,int slice);void i915_gem_init_swizzling (struct drm_device *dev);drivers/gpu/drm/i915/i915_gem.c +11
-4@@ -4518,7 +4518,7 @@ i915_gem_stop_ringbuffers(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_stop_ring_buffer (ring); + dev_priv->gt.stop_ring (ring); }int @@ -4635,7 +4635,7 @@ intel_enable_blt(struct drm_device *dev)return true; } -static int i915_gem_init_rings (struct drm_device *dev) +int i915_gem_init_rings (struct drm_device *dev) {struct drm_i915_private *dev_priv = dev->dev_private;int ret;@@ -4718,7 +4718,7 @@ i915_gem_init_hw(struct drm_device *dev)i915_gem_init_swizzling (dev); - ret =i915_gem_init_rings (dev); + ret = dev_priv->gt.init_rings (dev);if (ret)return ret;@@ -4759,6 +4759,13 @@ int i915_gem_init(struct drm_device *dev)DRM_DEBUG_DRIVER ("allow wake ack timed out\n" ); } +if (!i915.enable_execlists) { + dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission; + dev_priv->gt.init_rings = i915_gem_init_rings; + dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; + dev_priv->gt.stop_ring = intel_stop_ring_buffer; + } +i915_gem_init_userptr (dev);i915_gem_init_global_gtt (dev);@@ -4794,7 +4801,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_cleanup_ring_buffer (ring); + dev_priv->gt.cleanup_ring (ring); }int drivers/gpu/drm/i915/i915_gem_execbuffer.c +10
-10@@ -1034,14 +1034,14 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,return 0 ; } -static int -legacy_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, -struct intel_engine_cs *ring, -struct intel_context *ctx, -struct drm_i915_gem_execbuffer2 *args, -struct list_head *vmas, -struct drm_i915_gem_object *batch_obj, -u64 exec_start,u32 flags) +int +i915_gem_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags) {struct drm_clip_rect *cliprects =NULL ;struct drm_i915_private *dev_priv = dev->dev_private;@@ -1408,8 +1408,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,else exec_start +=i915_gem_obj_offset (batch_obj, vm); - ret =legacy_ringbuffer_submission (dev, file, ring, ctx, - args, &eb->vmas, batch_obj, exec_start, flags); + ret = dev_priv->gt.do_execbuf (dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, flags);if (ret) goto err;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfxSignature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 13/43] drm/i915: Abstract the legacy workload submission mechanism away
In reply to Thomas Danieldrivers/gpu/drm/i915/i915_gem_execbuffer.c i915_gem_do_execbuffer(struct drm_device *dev, void *data, · line 1412
Quoted 8 lines · Thomas Daniel
drivers/gpu/drm/i915/i915_gem_execbuffer.c +2
-2@@ -1408,8 +1408,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,else exec_start +=i915_gem_obj_offset (batch_obj, vm); - ret =legacy_ringbuffer_submission (dev, file, ring, ctx, - args, &eb->vmas, batch_obj, exec_start, flags); + ret = dev_priv->gt.do_execbuf (dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, flags);
Also misaligned and too long line here. Fixed, too. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 13/43] drm/i915: Abstract the legacy workload submission mechanism away
In reply to Thomas DanielQuoted 28 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
As suggested by Daniel Vetter. The idea, in subsequent patches, is to provide an alternative to these vfuncs for the Execlists submission mechanism.
v2: Splitted into two and reordered to illustrate our intentions, instead of showing it off. Also, remove the
add_requestvfunc and added thestop_ringone.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 24 ++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_gem.c | 15 +++++++++++---- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 20 ++++++++++---------- 3 files changed, 45 insertions(+), 14 deletions(-)drivers/gpu/drm/i915/i915_drv.h +3
-0@@ -1617,6 +1617,21 @@ struct drm_i915_private {/* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; +/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ +struct { + int (*do_execbuf) (struct drm_device *dev, struct drm_file *file,
drivers/gpu/drm/i915/i915_drv.h struct drm_i915_private { · line 1632
Quoted 10 lines
drivers/gpu/drm/i915/i915_drv.h +10
-0+struct intel_engine_cs *ring, + struct intel_context *ctx, + struct drm_i915_gem_execbuffer2 *args, + struct list_head *vmas, + struct drm_i915_gem_object *batch_obj, + u64 exec_start, u32 flags); +int (*init_rings) (struct drm_device *dev); +void (*cleanup_ring) (struct intel_engine_cs *ring); +void (*stop_ring) (struct intel_engine_cs *ring); +bool (*is_ring_initialized) (struct intel_engine_cs *ring);
Aside: ring here is a bit a misnomer, we talk about the engines. I guess at the end of all this we should throw a few patches on top to name things correctly with ring/engine where appropriate.
-Daniel
Quoted 127 lines
drivers/gpu/drm/i915/i915_drv.h +11
-0+ } gt; +/* * NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch * will be rejected. Instead look for a better place. @@ -2224,6 +2239,14 @@ 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); +int i915_gem_ringbuffer_submission (struct drm_device *dev, +struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags);int i915_gem_execbuffer (struct drm_device *dev,void *data,struct drm_file *file_priv); int i915_gem_execbuffer2(struct drm_device *dev, void *data,@@ -2376,6 +2399,7 @@ void i915_gem_reset(struct drm_device *dev);bool i915_gem_clflush_object (struct drm_i915_gem_object *obj,bool force);int __must_check i915_gem_object_finish_gpu (struct drm_i915_gem_object *obj);int __must_check i915_gem_init (struct drm_device *dev); +int i915_gem_init_rings (struct drm_device *dev);int __must_check i915_gem_init_hw (struct drm_device *dev);int i915_gem_l3_remap (struct intel_engine_cs *ring,int slice);void i915_gem_init_swizzling (struct drm_device *dev);drivers/gpu/drm/i915/i915_gem.c +11
-4@@ -4518,7 +4518,7 @@ i915_gem_stop_ringbuffers(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_stop_ring_buffer (ring); + dev_priv->gt.stop_ring (ring); }int @@ -4635,7 +4635,7 @@ intel_enable_blt(struct drm_device *dev)return true; } -static int i915_gem_init_rings (struct drm_device *dev) +int i915_gem_init_rings (struct drm_device *dev) {struct drm_i915_private *dev_priv = dev->dev_private;int ret;@@ -4718,7 +4718,7 @@ i915_gem_init_hw(struct drm_device *dev)i915_gem_init_swizzling (dev); - ret =i915_gem_init_rings (dev); + ret = dev_priv->gt.init_rings (dev);if (ret)return ret;@@ -4759,6 +4759,13 @@ int i915_gem_init(struct drm_device *dev)DRM_DEBUG_DRIVER ("allow wake ack timed out\n" ); } +if (!i915.enable_execlists) { + dev_priv->gt.do_execbuf = i915_gem_ringbuffer_submission; + dev_priv->gt.init_rings = i915_gem_init_rings; + dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; + dev_priv->gt.stop_ring = intel_stop_ring_buffer; + } +i915_gem_init_userptr (dev);i915_gem_init_global_gtt (dev);@@ -4794,7 +4801,7 @@ i915_gem_cleanup_ringbuffer(struct drm_device *dev)int i;for_each_ring (ring, dev_priv, i) -intel_cleanup_ring_buffer (ring); + dev_priv->gt.cleanup_ring (ring); }int drivers/gpu/drm/i915/i915_gem_execbuffer.c +10
-10@@ -1034,14 +1034,14 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,return 0 ; } -static int -legacy_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, -struct intel_engine_cs *ring, -struct intel_context *ctx, -struct drm_i915_gem_execbuffer2 *args, -struct list_head *vmas, -struct drm_i915_gem_object *batch_obj, -u64 exec_start,u32 flags) +int +i915_gem_ringbuffer_submission (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags) {struct drm_clip_rect *cliprects =NULL ;struct drm_i915_private *dev_priv = dev->dev_private;@@ -1408,8 +1408,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,else exec_start +=i915_gem_obj_offset (batch_obj, vm); - ret =legacy_ringbuffer_submission (dev, file, ring, ctx, - args, &eb->vmas, batch_obj, exec_start, flags); + ret = dev_priv->gt.do_execbuf (dev, file, ring, ctx, args, + &eb->vmas, batch_obj, exec_start, flags);if (ret) goto err;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 14/43 drm/i915/bdw: Skeleton for the new logical rings submission path
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Execlists are indeed a brave new world with respect to workload submission to the GPU.
In previous version of these series, I have tried to impact the legacy ringbuffer submission path as little as possible (mostly, passing the context around and using the correct ringbuffer when I needed one) but Daniel is afraid (probably with a reason) that these changes and, especially, future ones, will end up breaking older gens.
This commit and some others coming next will try to limit the damage by creating an alternative path for workload submission. The first step is here: laying out a new ring init/fini.
--- drivers/gpu/drm/i915/i915_gem.c | 5 ++ drivers/gpu/drm/i915/intel_lrc.c | 151 ++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 12 +++ 3 files changed, 168 insertions(+)
drivers/gpu/drm/i915/i915_gem.c +5 -0
@@ -4764,6 +4764,11 @@ int i915_gem_init(struct drm_device *dev) dev_priv->gt.init_rings = i915_gem_init_rings; dev_priv->gt.cleanup_ring = intel_cleanup_ring_buffer; dev_priv->gt.stop_ring = intel_stop_ring_buffer; + }else { + dev_priv->gt.do_execbuf = intel_execlists_submission; + dev_priv->gt.init_rings = intel_logical_rings_init; + dev_priv->gt.cleanup_ring = intel_logical_ring_cleanup; + dev_priv->gt.stop_ring = intel_logical_ring_stop; }i915_gem_init_userptr (dev);
drivers/gpu/drm/i915/intel_lrc.c +151 -0
157 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.h +12 -0
@@ -24,6 +24,11 @@#ifndef _INTEL_LRC_H_#define _INTEL_LRC_H_ +/* Logical Rings */ +void intel_logical_ring_stop (struct intel_engine_cs *ring); +void intel_logical_ring_cleanup (struct intel_engine_cs *ring); +int intel_logical_rings_init (struct drm_device *dev); +/* Logical Ring Contexts */ void intel_lr_context_free (struct intel_context *ctx); int intel_lr_context_deferred_create(struct intel_context *ctx,
@@ -31,5 +36,12 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,/* Execlists */ int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists); +int intel_execlists_submission (struct drm_device *dev,struct drm_file *file, +struct intel_engine_cs *ring, +struct intel_context *ctx, +struct drm_i915_gem_execbuffer2 *args, +struct list_head *vmas, +struct drm_i915_gem_object *batch_obj, +u64 exec_start,u32 flags);#endif /* _INTEL_LRC_H_ */
Signature · 1 line
1.7.9.5
PATCH 15/43 drm/i915/bdw: Generic logical ring init and cleanup
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Allocate and populate the default LRC for every ring, call gen-specific init/cleanup, init/fini the command parser and set the status page (now inside the LRC object). These are things all engines/rings have in common.
Stopping the ring before cleanup and initializing the seqnos is left as a TODO task (we need more infrastructure in place before we can achieve this).
v2: Check the ringbuffer backing obj for ring_is_initialized, instead of the context backing obj (similar, but not exactly the same).
--- drivers/gpu/drm/i915/i915_gem_context.c | 4 --- drivers/gpu/drm/i915/intel_lrc.c | 54 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 17 ++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 6 +--- 4 files changed, 70 insertions(+), 11 deletions(-)
drivers/gpu/drm/i915/i915_gem_context.c +0 -4
@@ -450,10 +450,6 @@ int i915_gem_context_init(struct drm_device *dev)/* NB: RCS will hold a ref for all rings */ ring->default_context = ctx; - -/* FIXME: we really only want to do this for initialized rings */ -if (i915.enable_execlists) -intel_lr_context_deferred_create (ctx, ring); } DRM_DEBUG_DRIVER("%s context support initialized\n",
drivers/gpu/drm/i915/intel_lrc.c +52 -2
70 lines not on this page · raw message
drivers/gpu/drm/i915/intel_ringbuffer.c +17 -0
@@ -40,6 +40,23 @@*/ #define CACHELINE_BYTES 64 +bool +intel_ring_initialized (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; + +if (!dev) +return false; + +if (i915.enable_execlists) { +struct intel_context *dctx = ring->default_context; +struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf; + +return ringbuf->obj; + }else +return ring->buffer && ring->buffer->obj; +} +static inline int __ring_space (int head,int tail,int size) {int space = head - (tail +I915_RING_FREE_SPACE );
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -5
@@ -288,11 +288,7 @@ struct intel_engine_cs {u32 (*get_cmd_length_mask)(u32 cmd_header); }; -static inline bool -intel_ring_initialized (struct intel_engine_cs *ring) -{ -return ring->buffer && ring->buffer->obj; -} +bool intel_ring_initialized (struct intel_engine_cs *ring);static inline unsigned intel_ring_flag (struct intel_engine_cs *ring)
Signature · 1 line
1.7.9.5
Re: [PATCH 15/43] drm/i915/bdw: Generic logical ring init and cleanup
Quoted 28 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Allocate and populate the default LRC for every ring, call gen-specific init/cleanup, init/fini the command parser and set the status page (now inside the LRC object). These are things all engines/rings have in common.
Stopping the ring before cleanup and initializing the seqnos is left as a TODO task (we need more infrastructure in place before we can achieve this).
v2: Check the ringbuffer backing obj for
ring_is_initialized, instead of the context backing obj (similar, but not exactly the same).Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem_context.c | 4 --- drivers/gpu/drm/i915/intel_lrc.c | 54 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_ringbuffer.c | 17 ++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 6 +--- 4 files changed, 70 insertions(+), 11 deletions(-)drivers/gpu/drm/i915/i915_gem_context.c +0
-0
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_init(struct drm_device *dev) · line 456
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-4@@ -450,10 +450,6 @@ int i915_gem_context_init(struct drm_device *dev)/* NB: RCS will hold a ref for all rings */ ring->default_context = ctx; - -/* FIXME: we really only want to do this for initialized rings */ -if (i915.enable_execlists) -intel_lr_context_deferred_create (ctx, ring);
Ah, here we go ;-)
Quoted 93 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0} DRM_DEBUG_DRIVER("%s context support initialized\n",drivers/gpu/drm/i915/intel_lrc.c +52
-2@@ -108,12 +108,60 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)void intel_logical_ring_cleanup (struct intel_engine_cs *ring) { -/* TODO */ +if (!intel_ring_initialized (ring)) +return ; + +/* TODO: make sure the ring is stopped */ + ring->preallocated_lazy_request =NULL ; + ring->outstanding_lazy_seqno =0 ; + +if (ring->cleanup) + ring->cleanup (ring); + +i915_cmd_parser_fini_ring (ring); + +if (ring->status_page.obj) { +kunmap (sg_page (ring->status_page.obj->pages->sgl)); + ring->status_page.obj =NULL ; + } }static int logical_ring_init (struct drm_device *dev,struct intel_engine_cs *ring) { -/* TODO */ +int ret; +struct intel_context *dctx = ring->default_context; +struct drm_i915_gem_object *dctx_obj; + +/* Intentionally left blank. */ + ring->buffer =NULL ; + + ring->dev = dev; +INIT_LIST_HEAD (&ring->active_list); +INIT_LIST_HEAD (&ring->request_list); +init_waitqueue_head (&ring->irq_queue); + + ret =intel_lr_context_deferred_create (dctx, ring); +if (ret) +return ret; + +/* The status page is offset 0 from the context object in LRCs. */ + dctx_obj = dctx->engine[ring->id].state; + ring->status_page.gfx_addr =i915_gem_obj_ggtt_offset (dctx_obj); + ring->status_page.page_addr =kmap (sg_page (dctx_obj->pages->sgl)); +if (ring->status_page.page_addr ==NULL ) +return -ENOMEM ; + ring->status_page.obj = dctx_obj; + + ret =i915_cmd_parser_init_ring (ring); +if (ret) +return ret; + +if (ring->init) { + ret = ring->init (ring); +if (ret) +return ret; + } +return 0 ; }@@ -397,6 +445,8 @@ int intel_lr_context_deferred_create(struct intel_context *ctx,int ret;BUG_ON (ctx->legacy_hw_ctx.rcs_state !=NULL ); +if (ctx->engine[ring->id].state) +return 0 ; context_size =round_up (get_lr_context_size (ring),4096 );drivers/gpu/drm/i915/intel_ringbuffer.c +6
-0@@ -40,6 +40,23 @@*/ #define CACHELINE_BYTES 64 +bool +intel_ring_initialized (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; + +if (!dev)
drivers/gpu/drm/i915/intel_ringbuffer.c line 58
Quoted 10 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +10
-0+return false; + +if (i915.enable_execlists) { +struct intel_context *dctx = ring->default_context; +struct intel_ringbuffer *ringbuf = dctx->engine[ring->id].ringbuf; + +return ringbuf->obj; + }else +return ring->buffer && ring->buffer->obj; +}
Looks like I'll not regret having ditched gt.ring_is_initialized. -Daniel
Quoted 28 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +1
-0+static inline int __ring_space (int head,int tail,int size) {int space = head - (tail +I915_RING_FREE_SPACE );drivers/gpu/drm/i915/intel_ringbuffer.h +1
-5@@ -288,11 +288,7 @@ struct intel_engine_cs {u32 (*get_cmd_length_mask)(u32 cmd_header); }; -static inline bool -intel_ring_initialized (struct intel_engine_cs *ring) -{ -return ring->buffer && ring->buffer->obj; -} +bool intel_ring_initialized (struct intel_engine_cs *ring);static inline unsigned intel_ring_flag (struct intel_engine_cs *ring)Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 16/43 drm/i915/bdw: GEN-specific logical ring init
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Logical rings do not need most of the initialization their legacy ringbuffer counterparts do: we just need the pipe control object for the render ring, enable Execlists on the hardware and a few workarounds.
v2: Squash with: "drm/i915: Extract pipe control fini & make init outside accesible".
--- drivers/gpu/drm/i915/intel_lrc.c | 54 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 34 +++++++++++-------- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 ++ 3 files changed, 78 insertions(+), 13 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +54 -0
@@ -106,6 +106,49 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */ } +static int gen8_init_common_ring (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; + +I915_WRITE (RING_MODE_GEN7 (ring), +_MASKED_BIT_DISABLE (GFX_REPLAY_MODE ) | +_MASKED_BIT_ENABLE (GFX_RUN_LIST_ENABLE )); +POSTING_READ (RING_MODE_GEN7 (ring)); +DRM_DEBUG_DRIVER ("Execlists enabled for %s\n" , ring->name); + +memset (&ring->hangcheck,0 ,sizeof (ring->hangcheck)); + +return 0 ; +} + +static int gen8_init_render_ring (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +int ret; + + ret =gen8_init_common_ring (ring); +if (ret) +return ret; + +/* We need to disable the AsyncFlip performance optimisations in order +* to use MI_WAIT_FOR_EVENT within the CS. It should already be +* programmed to '1' on all products. +* +* WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv +*/ +I915_WRITE (MI_MODE ,_MASKED_BIT_ENABLE (ASYNC_FLIP_PERF_DISABLE )); + + ret =intel_init_pipe_control (ring); +if (ret) +return ret; + +I915_WRITE (INSTPM ,_MASKED_BIT_ENABLE (INSTPM_FORCE_ORDERING )); + +return ret; +} +void intel_logical_ring_cleanup (struct intel_engine_cs *ring) {if (!intel_ring_initialized (ring))
@@ -176,6 +219,9 @@ static int logical_render_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; + ring->init = gen8_init_render_ring; + ring->cleanup = intel_fini_pipe_control; +return logical_ring_init (dev, ring); }
@@ -190,6 +236,8 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }
@@ -204,6 +252,8 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }
@@ -218,6 +268,8 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }
@@ -232,6 +284,8 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }
drivers/gpu/drm/i915/intel_ringbuffer.c +21 -13
@@ -573,8 +573,25 @@ out:return ret; } -static int -init_pipe_control (struct intel_engine_cs *ring) +void +intel_fini_pipe_control (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; + +if (ring->scratch.obj ==NULL ) +return ; + +if (INTEL_INFO (dev)->gen >=5 ) { +kunmap (sg_page (ring->scratch.obj->pages->sgl)); +i915_gem_object_ggtt_unpin (ring->scratch.obj); + } + +drm_gem_object_unreference (&ring->scratch.obj->base); + ring->scratch.obj =NULL ; +} + +int +intel_init_pipe_control (struct intel_engine_cs *ring) {int ret;
@@ -649,7 +666,7 @@ static int init_render_ring(struct intel_engine_cs *ring) _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));if (INTEL_INFO (dev)->gen >=5 ) { - ret =init_pipe_control (ring); + ret =intel_init_pipe_control (ring);if (ret)return ret; }
@@ -684,16 +701,7 @@ static void render_ring_cleanup(struct intel_engine_cs *ring) dev_priv->semaphore_obj =NULL ; } -if (ring->scratch.obj ==NULL ) -return ; - -if (INTEL_INFO (dev)->gen >=5 ) { -kunmap (sg_page (ring->scratch.obj->pages->sgl)); -i915_gem_object_ggtt_unpin (ring->scratch.obj); - } - -drm_gem_object_unreference (&ring->scratch.obj->base); - ring->scratch.obj =NULL ; +intel_fini_pipe_control (ring); } static int gen8_rcs_signal(struct intel_engine_cs *signaller,
drivers/gpu/drm/i915/intel_ringbuffer.h +3 -0
@@ -380,6 +380,9 @@ void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno);int intel_ring_flush_all_caches (struct intel_engine_cs *ring);int intel_ring_invalidate_all_caches (struct intel_engine_cs *ring); +void intel_fini_pipe_control (struct intel_engine_cs *ring); +int intel_init_pipe_control (struct intel_engine_cs *ring); +int intel_init_render_ring_buffer (struct drm_device *dev);int intel_init_bsd_ring_buffer (struct drm_device *dev);int intel_init_bsd2_ring_buffer (struct drm_device *dev);
Signature · 1 line
1.7.9.5
Re: [PATCH 16/43] drm/i915/bdw: GEN-specific logical ring init
Quoted 23 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Logical rings do not need most of the initialization their legacy ringbuffer counterparts do: we just need the pipe control object for the render ring, enable Execlists on the hardware and a few workarounds.
v2: Squash with: "drm/i915: Extract pipe control fini & make init outside accesible".
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 54 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 34 +++++++++++-------- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 ++ 3 files changed, 78 insertions(+), 13 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -106,6 +106,49 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */
drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_stop(struct intel_engine_cs *ring) · line 116
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +8
-0} +static int gen8_init_common_ring (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; + +I915_WRITE (RING_MODE_GEN7 (ring), +_MASKED_BIT_DISABLE (GFX_REPLAY_MODE ) | +_MASKED_BIT_ENABLE (GFX_RUN_LIST_ENABLE ));
Please build up a bit a closer relationship with checkpatch.pl, thanks.
Fixed while merging.
-Daniel
Quoted 164 lines
drivers/gpu/drm/i915/intel_lrc.c +46
-0+POSTING_READ (RING_MODE_GEN7 (ring)); +DRM_DEBUG_DRIVER ("Execlists enabled for %s\n" , ring->name); + +memset (&ring->hangcheck,0 ,sizeof (ring->hangcheck)); + +return 0 ; +} + +static int gen8_init_render_ring (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +int ret; + + ret =gen8_init_common_ring (ring); +if (ret) +return ret; + +/* We need to disable the AsyncFlip performance optimisations in order +* to use MI_WAIT_FOR_EVENT within the CS. It should already be +* programmed to '1' on all products. +* +* WaDisableAsyncFlipPerfMode:snb,ivb,hsw,vlv,bdw,chv +*/ +I915_WRITE (MI_MODE ,_MASKED_BIT_ENABLE (ASYNC_FLIP_PERF_DISABLE )); + + ret =intel_init_pipe_control (ring); +if (ret) +return ret; + +I915_WRITE (INSTPM ,_MASKED_BIT_ENABLE (INSTPM_FORCE_ORDERING )); + +return ret; +} +void intel_logical_ring_cleanup (struct intel_engine_cs *ring) {if (!intel_ring_initialized (ring))@@ -176,6 +219,9 @@ static int logical_render_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; + ring->init = gen8_init_render_ring; + ring->cleanup = intel_fini_pipe_control; +return logical_ring_init (dev, ring); }@@ -190,6 +236,8 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }@@ -204,6 +252,8 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }@@ -218,6 +268,8 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }@@ -232,6 +284,8 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; + ring->init = gen8_init_common_ring; +return logical_ring_init (dev, ring); }drivers/gpu/drm/i915/intel_ringbuffer.c +21
-13@@ -573,8 +573,25 @@ out:return ret; } -static int -init_pipe_control (struct intel_engine_cs *ring) +void +intel_fini_pipe_control (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; + +if (ring->scratch.obj ==NULL ) +return ; + +if (INTEL_INFO (dev)->gen >=5 ) { +kunmap (sg_page (ring->scratch.obj->pages->sgl)); +i915_gem_object_ggtt_unpin (ring->scratch.obj); + } + +drm_gem_object_unreference (&ring->scratch.obj->base); + ring->scratch.obj =NULL ; +} + +int +intel_init_pipe_control (struct intel_engine_cs *ring) {int ret;@@ -649,7 +666,7 @@ static int init_render_ring(struct intel_engine_cs *ring) _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));if (INTEL_INFO (dev)->gen >=5 ) { - ret =init_pipe_control (ring); + ret =intel_init_pipe_control (ring);if (ret)return ret; }@@ -684,16 +701,7 @@ static void render_ring_cleanup(struct intel_engine_cs *ring) dev_priv->semaphore_obj =NULL ; } -if (ring->scratch.obj ==NULL ) -return ; - -if (INTEL_INFO (dev)->gen >=5 ) { -kunmap (sg_page (ring->scratch.obj->pages->sgl)); -i915_gem_object_ggtt_unpin (ring->scratch.obj); - } - -drm_gem_object_unreference (&ring->scratch.obj->base); - ring->scratch.obj =NULL ; +intel_fini_pipe_control (ring); } static int gen8_rcs_signal(struct intel_engine_cs *signaller,drivers/gpu/drm/i915/intel_ringbuffer.h +3
-0@@ -380,6 +380,9 @@ void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno);int intel_ring_flush_all_caches (struct intel_engine_cs *ring);int intel_ring_invalidate_all_caches (struct intel_engine_cs *ring); +void intel_fini_pipe_control (struct intel_engine_cs *ring); +int intel_init_pipe_control (struct intel_engine_cs *ring); +int intel_init_render_ring_buffer (struct drm_device *dev);int intel_init_bsd_ring_buffer (struct drm_device *dev);int intel_init_bsd2_ring_buffer (struct drm_device *dev);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 17/43 drm/i915/bdw: GEN-specific logical ring set/get seqno
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
No mistery here: the seqno is still retrieved from the engine's HW status page (the one in the default context. For the moment, I see no reason to worry about other context's HWS page).
--- drivers/gpu/drm/i915/intel_lrc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +20 -0
@@ -149,6 +149,16 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static u32 gen8_get_seqno (struct intel_engine_cs *ring,bool lazy_coherency) +{ +return intel_read_status_page (ring,I915_GEM_HWS_INDEX ); +} + +static void gen8_set_seqno (struct intel_engine_cs *ring,u32 seqno) +{ +intel_write_status_page (ring,I915_GEM_HWS_INDEX , seqno); +} +void intel_logical_ring_cleanup (struct intel_engine_cs *ring) {if (!intel_ring_initialized (ring))
@@ -221,6 +231,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->init = gen8_init_render_ring; ring->cleanup = intel_fini_pipe_control; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }
@@ -237,6 +249,8 @@ static int logical_bsd_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }
@@ -253,6 +267,8 @@ static int logical_bsd2_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }
@@ -269,6 +285,8 @@ static int logical_blt_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }
@@ -285,6 +303,8 @@ static int logical_vebox_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }
Signature · 1 line
1.7.9.5
Re: [PATCH 17/43] drm/i915/bdw: GEN-specific logical ring set/get seqno
Quoted 7 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
No mistery here: the seqno is still retrieved from the engine's HW status page (the one in the default context. For the moment, I see no reason to worry about other context's HWS page).
Signed-off-by Oscar Mateo <[email protected]>
Ok, merged or bikeshedded up to this one. I need a bit a break to recharge, will continue later on.
Cheers, Daniel
Quoted 77 lines
--- drivers/gpu/drm/i915/intel_lrc.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +20
-0@@ -149,6 +149,16 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static u32 gen8_get_seqno (struct intel_engine_cs *ring,bool lazy_coherency) +{ +return intel_read_status_page (ring,I915_GEM_HWS_INDEX ); +} + +static void gen8_set_seqno (struct intel_engine_cs *ring,u32 seqno) +{ +intel_write_status_page (ring,I915_GEM_HWS_INDEX , seqno); +} +void intel_logical_ring_cleanup (struct intel_engine_cs *ring) {if (!intel_ring_initialized (ring))@@ -221,6 +231,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->init = gen8_init_render_ring; ring->cleanup = intel_fini_pipe_control; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }@@ -237,6 +249,8 @@ static int logical_bsd_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }@@ -253,6 +267,8 @@ static int logical_bsd2_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }@@ -269,6 +285,8 @@ static int logical_blt_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }@@ -285,6 +303,8 @@ static int logical_vebox_ring_init(struct drm_device *dev)GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; + ring->get_seqno = gen8_get_seqno; + ring->set_seqno = gen8_set_seqno;return logical_ring_init (dev, ring); }Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 18/43 drm/i915/bdw: New logical ring submission mechanism
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Well, new-ish: if all this code looks familiar, that's because it's a clone of the existing submission mechanism (with some modifications here and there to adapt it to LRCs and Execlists).
And why did we do this instead of reusing code, one might wonder? Well, there are some fears that the differences are big enough that they will end up breaking all platforms.
Also, Execlists offer several advantages, like control over when the GPU is done with a given workload, that can help simplify the submission mechanism, no doubt. I am interested in getting Execlists to work first and foremost, but in the future this parallel submission mechanism will help us to fine tune the mechanism without affecting old gens.
v2: Pass the ringbuffer only (whenever possible).
--- drivers/gpu/drm/i915/intel_lrc.c | 193 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 12 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 + 4 files changed, 218 insertions(+), 10 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +193 -0
@@ -106,6 +106,199 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */ } +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) +{ +intel_logical_ring_advance (ringbuf); + +if (intel_ring_stopped (ringbuf->ring)) +return ; + +/* TODO: how to submit a context to the ELSP is not here yet */ +} + +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +{ +if (ring->outstanding_lazy_seqno) +return 0 ; + +if (ring->preallocated_lazy_request ==NULL ) { +struct drm_i915_gem_request *request; + + request =kmalloc (sizeof (*request),GFP_KERNEL ); +if (request ==NULL ) +return -ENOMEM ; + + ring->preallocated_lazy_request = request; + } + +return i915_gem_get_seqno (ring->dev, &ring->outstanding_lazy_seqno); +} + +static int logical_ring_wait_request (struct intel_ringbuffer *ringbuf,int bytes) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_i915_gem_request *request; +u32 seqno =0 ; +int ret; + +if (ringbuf->last_retired_head !=-1 ) { + ringbuf->head = ringbuf->last_retired_head; + ringbuf->last_retired_head =-1 ; + + ringbuf->space =intel_ring_space (ringbuf); +if (ringbuf->space >= bytes) +return 0 ; + } + +list_for_each_entry (request, &ring->request_list, list) { +if (__intel_ring_space (request->tail, ringbuf->tail, + ringbuf->size) >= bytes) { + seqno = request->seqno; +break ; + } + } + +if (seqno ==0 ) +return -ENOSPC ; + + ret =i915_wait_seqno (ring, seqno); +if (ret) +return ret; + +/* TODO: make sure we update the right ringbuffer's last_retired_head +* when retiring requests */ +i915_gem_retire_requests_ring (ring); + ringbuf->head = ringbuf->last_retired_head; + ringbuf->last_retired_head =-1 ; + + ringbuf->space =intel_ring_space (ringbuf); +return 0 ; +} + +static int logical_ring_wait_for_space (struct intel_ringbuffer *ringbuf,int bytes) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long end; +int ret; + + ret =logical_ring_wait_request (ringbuf, bytes); +if (ret != -ENOSPC ) +return ret; + +/* Force the context submission in case we have been skipping it */ +intel_logical_ring_advance_and_submit (ringbuf); + +/* With GEM the hangcheck timer should kick us out of the loop, +* leaving it early runs the risk of corrupting GEM state (due +* to running on almost untested codepaths). But on resume +* timers don't work yet, so prevent a complete hang in that +* case by choosing an insanely large timeout. */ + end = jiffies +60 *HZ ; + +do { + ringbuf->head =I915_READ_HEAD (ring); + ringbuf->space =intel_ring_space (ringbuf); +if (ringbuf->space >= bytes) { + ret =0 ; +break ; + } + +if (!drm_core_check_feature (dev,DRIVER_MODESET ) && + dev->primary->master) { +struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; +if (master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |=I915_BOX_WAIT ; + } + +msleep (1 ); + +if (dev_priv->mm.interruptible &&signal_pending (current)) { + ret = -ERESTARTSYS ; +break ; + } + + ret =i915_gem_check_wedge (&dev_priv->gpu_error, + dev_priv->mm.interruptible); +if (ret) +break ; + +if (time_after (jiffies, end)) { + ret = -EBUSY ; +break ; + } + }while (1 ); + +return ret; +} + +static int logical_ring_wrap_buffer (struct intel_ringbuffer *ringbuf) +{ +uint32_t __iomem *virt; +int rem = ringbuf->size - ringbuf->tail; + +if (ringbuf->space < rem) { +int ret =logical_ring_wait_for_space (ringbuf, rem); +if (ret) +return ret; + } + + virt = ringbuf->virtual_start + ringbuf->tail; + rem /=4 ; +while (rem--) +iowrite32 (MI_NOOP , virt++); + + ringbuf->tail =0 ; + ringbuf->space =intel_ring_space (ringbuf); + +return 0 ; +} + +static int logical_ring_prepare (struct intel_ringbuffer *ringbuf,int bytes) +{ +int ret; + +if (unlikely (ringbuf->tail + bytes > ringbuf->effective_size)) { + ret =logical_ring_wrap_buffer (ringbuf); +if (unlikely (ret)) +return ret; + } + +if (unlikely (ringbuf->space < bytes)) { + ret =logical_ring_wait_for_space (ringbuf, bytes); +if (unlikely (ret)) +return ret; + } + +return 0 ; +} + +int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +int ret; + + ret =i915_gem_check_wedge (&dev_priv->gpu_error, + dev_priv->mm.interruptible); +if (ret) +return ret; + + ret =logical_ring_prepare (ringbuf, num_dwords *sizeof (uint32_t )); +if (ret) +return ret; + +/* Preallocate the olr before touching the ring */ + ret =logical_ring_alloc_seqno (ring); +if (ret) +return ret; + + ringbuf->space -= num_dwords *sizeof (uint32_t ); +return 0 ; +} +static int gen8_init_common_ring (struct intel_engine_cs *ring) {struct drm_device *dev = ring->dev;
drivers/gpu/drm/i915/intel_lrc.h +12 -0
@@ -29,6 +29,18 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring);void intel_logical_ring_cleanup (struct intel_engine_cs *ring);int intel_logical_rings_init (struct drm_device *dev); +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf); +static inline void intel_logical_ring_advance (struct intel_ringbuffer *ringbuf) +{ + ringbuf->tail &= ringbuf->size -1 ; +} +static inline void intel_logical_ring_emit (struct intel_ringbuffer *ringbuf,u32 data) +{ +iowrite32 (data, ringbuf->virtual_start + ringbuf->tail); + ringbuf->tail +=4 ; +} +int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords); +/* Logical Ring Contexts */ void intel_lr_context_free (struct intel_context *ctx); int intel_lr_context_deferred_create(struct intel_context *ctx,
drivers/gpu/drm/i915/intel_ringbuffer.c +10 -10
@@ -57,7 +57,7 @@ intel_ring_initialized(struct intel_engine_cs *ring)return ring->buffer && ring->buffer->obj; } -static inline int __ring_space (int head,int tail,int size) +int __intel_ring_space (int head,int tail,int size) {int space = head - (tail +I915_RING_FREE_SPACE );if (space <0 )
@@ -65,12 +65,12 @@ static inline int __ring_space(int head, int tail, int size)return space; } -static inline int ring_space (struct intel_ringbuffer *ringbuf) +int intel_ring_space (struct intel_ringbuffer *ringbuf) { -return __ring_space (ringbuf->head &HEAD_ADDR , ringbuf->tail, ringbuf->size); +return __intel_ring_space (ringbuf->head &HEAD_ADDR , ringbuf->tail, ringbuf->size); } -static bool intel_ring_stopped (struct intel_engine_cs *ring) +bool intel_ring_stopped (struct intel_engine_cs *ring) {struct drm_i915_private *dev_priv = ring->dev->dev_private;return dev_priv->gpu_error.stop_rings &intel_ring_flag (ring);
@@ -561,7 +561,7 @@ static int init_ring_common(struct intel_engine_cs *ring)else { ringbuf->head =I915_READ_HEAD (ring); ringbuf->tail =I915_READ_TAIL (ring) &TAIL_ADDR ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf); ringbuf->last_retired_head =-1 ; }
@@ -1679,13 +1679,13 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);if (ringbuf->space >= n)return 0 ; }list_for_each_entry (request, &ring->request_list, list) { -if (__ring_space (request->tail, ringbuf->tail, ringbuf->size) >= n) { +if (__intel_ring_space (request->tail, ringbuf->tail, ringbuf->size) >= n) { seqno = request->seqno;break ; }
@@ -1702,7 +1702,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);return 0 ; }
@@ -1731,7 +1731,7 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)trace_i915_ring_wait_begin (ring); do { ringbuf->head = I915_READ_HEAD(ring); - ringbuf->space = ring_space(ringbuf); + ringbuf->space = intel_ring_space(ringbuf); if (ringbuf->space >= n) { ret = 0; break;
@@ -1783,7 +1783,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)iowrite32 (MI_NOOP , virt++); ringbuf->tail =0 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);return 0 ; }
drivers/gpu/drm/i915/intel_ringbuffer.h +3 -0
@@ -373,6 +373,9 @@ static inline void intel_ring_advance(struct intel_engine_cs *ring)struct intel_ringbuffer *ringbuf = ring->buffer; ringbuf->tail &= ringbuf->size -1 ; } +int __intel_ring_space (int head,int tail,int size); +int intel_ring_space (struct intel_ringbuffer *ringbuf); +bool intel_ring_stopped (struct intel_engine_cs *ring);void __intel_ring_advance (struct intel_engine_cs *ring);int __must_check intel_ring_idle (struct intel_engine_cs *ring);
Signature · 1 line
1.7.9.5
Re: [PATCH 18/43] drm/i915/bdw: New logical ring submission mechanism
Quoted 130 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Well, new-ish: if all this code looks familiar, that's because it's a clone of the existing submission mechanism (with some modifications here and there to adapt it to LRCs and Execlists).
And why did we do this instead of reusing code, one might wonder? Well, there are some fears that the differences are big enough that they will end up breaking all platforms.
Also, Execlists offer several advantages, like control over when the GPU is done with a given workload, that can help simplify the submission mechanism, no doubt. I am interested in getting Execlists to work first and foremost, but in the future this parallel submission mechanism will help us to fine tune the mechanism without affecting old gens.
v2: Pass the ringbuffer only (whenever possible).
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 193 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 12 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 20 ++-- drivers/gpu/drm/i915/intel_ringbuffer.h | 3 + 4 files changed, 218 insertions(+), 10 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +95
-0@@ -106,6 +106,199 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */ } +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) +{ +intel_logical_ring_advance (ringbuf); + +if (intel_ring_stopped (ringbuf->ring)) +return ; + +/* TODO: how to submit a context to the ELSP is not here yet */ +} + +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +{ +if (ring->outstanding_lazy_seqno) +return 0 ; + +if (ring->preallocated_lazy_request ==NULL ) { +struct drm_i915_gem_request *request; + + request =kmalloc (sizeof (*request),GFP_KERNEL ); +if (request ==NULL ) +return -ENOMEM ; + + ring->preallocated_lazy_request = request; + } + +return i915_gem_get_seqno (ring->dev, &ring->outstanding_lazy_seqno); +} + +static int logical_ring_wait_request (struct intel_ringbuffer *ringbuf,int bytes) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_i915_gem_request *request; +u32 seqno =0 ; +int ret; + +if (ringbuf->last_retired_head !=-1 ) { + ringbuf->head = ringbuf->last_retired_head; + ringbuf->last_retired_head =-1 ; + + ringbuf->space =intel_ring_space (ringbuf); +if (ringbuf->space >= bytes) +return 0 ; + } + +list_for_each_entry (request, &ring->request_list, list) { +if (__intel_ring_space (request->tail, ringbuf->tail, + ringbuf->size) >= bytes) { + seqno = request->seqno; +break ; + } + } + +if (seqno ==0 ) +return -ENOSPC ; + + ret =i915_wait_seqno (ring, seqno); +if (ret) +return ret; + +/* TODO: make sure we update the right ringbuffer's last_retired_head +* when retiring requests */ +i915_gem_retire_requests_ring (ring); + ringbuf->head = ringbuf->last_retired_head; + ringbuf->last_retired_head =-1 ; + + ringbuf->space =intel_ring_space (ringbuf); +return 0 ; +} + +static int logical_ring_wait_for_space (struct intel_ringbuffer *ringbuf,int bytes) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long end; +int ret; + + ret =logical_ring_wait_request (ringbuf, bytes); +if (ret != -ENOSPC ) +return ret; + +/* Force the context submission in case we have been skipping it */ +intel_logical_ring_advance_and_submit (ringbuf); + +/* With GEM the hangcheck timer should kick us out of the loop, +* leaving it early runs the risk of corrupting GEM state (due +* to running on almost untested codepaths). But on resume +* timers don't work yet, so prevent a complete hang in that +* case by choosing an insanely large timeout. */ + end = jiffies +60 *HZ ; + + do { + ringbuf->head = I915_READ_HEAD(ring); + ringbuf->space = intel_ring_space(ringbuf); + if (ringbuf->space >= bytes) {
drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_stop(struct intel_engine_cs *ring) · line 213
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+ ret =0 ; +break ; + } + +if (!drm_core_check_feature (dev,DRIVER_MODESET ) && + dev->primary->master) { +struct drm_i915_master_private *master_priv = dev->primary->master->driver_priv; +if (master_priv->sarea_priv) + master_priv->sarea_priv->perf_boxes |=I915_BOX_WAIT ; + }
sarea is legacy gunk. Really bad legacy gunk. The DRIVE_MODESET check should have been a give-away. Also checkpatch.
Fixed while applying.
-Daniel
Quoted 216 lines
drivers/gpu/drm/i915/intel_lrc.c +88
-0+ +msleep (1 ); + +if (dev_priv->mm.interruptible &&signal_pending (current)) { + ret = -ERESTARTSYS ; +break ; + } + + ret =i915_gem_check_wedge (&dev_priv->gpu_error, + dev_priv->mm.interruptible); +if (ret) +break ; + +if (time_after (jiffies, end)) { + ret = -EBUSY ; +break ; + } + }while (1 ); + +return ret; +} + +static int logical_ring_wrap_buffer (struct intel_ringbuffer *ringbuf) +{ +uint32_t __iomem *virt; +int rem = ringbuf->size - ringbuf->tail; + +if (ringbuf->space < rem) { +int ret =logical_ring_wait_for_space (ringbuf, rem); +if (ret) +return ret; + } + + virt = ringbuf->virtual_start + ringbuf->tail; + rem /=4 ; +while (rem--) +iowrite32 (MI_NOOP , virt++); + + ringbuf->tail =0 ; + ringbuf->space =intel_ring_space (ringbuf); + +return 0 ; +} + +static int logical_ring_prepare (struct intel_ringbuffer *ringbuf,int bytes) +{ +int ret; + +if (unlikely (ringbuf->tail + bytes > ringbuf->effective_size)) { + ret =logical_ring_wrap_buffer (ringbuf); +if (unlikely (ret)) +return ret; + } + +if (unlikely (ringbuf->space < bytes)) { + ret =logical_ring_wait_for_space (ringbuf, bytes); +if (unlikely (ret)) +return ret; + } + +return 0 ; +} + +int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +int ret; + + ret =i915_gem_check_wedge (&dev_priv->gpu_error, + dev_priv->mm.interruptible); +if (ret) +return ret; + + ret =logical_ring_prepare (ringbuf, num_dwords *sizeof (uint32_t )); +if (ret) +return ret; + +/* Preallocate the olr before touching the ring */ + ret =logical_ring_alloc_seqno (ring); +if (ret) +return ret; + + ringbuf->space -= num_dwords *sizeof (uint32_t ); +return 0 ; +} +static int gen8_init_common_ring (struct intel_engine_cs *ring) {struct drm_device *dev = ring->dev;drivers/gpu/drm/i915/intel_lrc.h +12
-0@@ -29,6 +29,18 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring);void intel_logical_ring_cleanup (struct intel_engine_cs *ring);int intel_logical_rings_init (struct drm_device *dev); +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf); +static inline void intel_logical_ring_advance (struct intel_ringbuffer *ringbuf) +{ + ringbuf->tail &= ringbuf->size -1 ; +} +static inline void intel_logical_ring_emit (struct intel_ringbuffer *ringbuf,u32 data) +{ +iowrite32 (data, ringbuf->virtual_start + ringbuf->tail); + ringbuf->tail +=4 ; +} +int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords); +/* Logical Ring Contexts */ void intel_lr_context_free (struct intel_context *ctx); int intel_lr_context_deferred_create(struct intel_context *ctx,drivers/gpu/drm/i915/intel_ringbuffer.c +10
-10@@ -57,7 +57,7 @@ intel_ring_initialized(struct intel_engine_cs *ring)return ring->buffer && ring->buffer->obj; } -static inline int __ring_space (int head,int tail,int size) +int __intel_ring_space (int head,int tail,int size) {int space = head - (tail +I915_RING_FREE_SPACE );if (space <0 )@@ -65,12 +65,12 @@ static inline int __ring_space(int head, int tail, int size)return space; } -static inline int ring_space (struct intel_ringbuffer *ringbuf) +int intel_ring_space (struct intel_ringbuffer *ringbuf) { -return __ring_space (ringbuf->head &HEAD_ADDR , ringbuf->tail, ringbuf->size); +return __intel_ring_space (ringbuf->head &HEAD_ADDR , ringbuf->tail, ringbuf->size); } -static bool intel_ring_stopped (struct intel_engine_cs *ring) +bool intel_ring_stopped (struct intel_engine_cs *ring) {struct drm_i915_private *dev_priv = ring->dev->dev_private;return dev_priv->gpu_error.stop_rings &intel_ring_flag (ring);@@ -561,7 +561,7 @@ static int init_ring_common(struct intel_engine_cs *ring)else { ringbuf->head =I915_READ_HEAD (ring); ringbuf->tail =I915_READ_TAIL (ring) &TAIL_ADDR ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf); ringbuf->last_retired_head =-1 ; }@@ -1679,13 +1679,13 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);if (ringbuf->space >= n)return 0 ; }list_for_each_entry (request, &ring->request_list, list) { -if (__ring_space (request->tail, ringbuf->tail, ringbuf->size) >= n) { +if (__intel_ring_space (request->tail, ringbuf->tail, ringbuf->size) >= n) { seqno = request->seqno;break ; }@@ -1702,7 +1702,7 @@ static int intel_ring_wait_request(struct intel_engine_cs *ring, int n) ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);return 0 ; }@@ -1731,7 +1731,7 @@ static int ring_wait_for_space(struct intel_engine_cs *ring, int n)trace_i915_ring_wait_begin (ring); do { ringbuf->head = I915_READ_HEAD(ring); - ringbuf->space = ring_space(ringbuf); + ringbuf->space = intel_ring_space(ringbuf); if (ringbuf->space >= n) { ret = 0; break;@@ -1783,7 +1783,7 @@ static int intel_wrap_ring_buffer(struct intel_engine_cs *ring)iowrite32 (MI_NOOP , virt++); ringbuf->tail =0 ; - ringbuf->space =ring_space (ringbuf); + ringbuf->space =intel_ring_space (ringbuf);return 0 ; }drivers/gpu/drm/i915/intel_ringbuffer.h +3
-0@@ -373,6 +373,9 @@ static inline void intel_ring_advance(struct intel_engine_cs *ring)struct intel_ringbuffer *ringbuf = ring->buffer; ringbuf->tail &= ringbuf->size -1 ; } +int __intel_ring_space (int head,int tail,int size); +int intel_ring_space (struct intel_ringbuffer *ringbuf); +bool intel_ring_stopped (struct intel_engine_cs *ring);void __intel_ring_advance (struct intel_engine_cs *ring);int __must_check intel_ring_idle (struct intel_engine_cs *ring);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 19/43 drm/i915/bdw: GEN-specific logical ring emit request
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Very similar to the legacy add_request, only modified to account for logical ringbuffer.
v2: Use MI_GLOBAL_GTT, as suggested by Brad Volkin.
v3: Unify render and non-render in the same function, as noticed by Brad Volkin.
--- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_lrc.c | 31 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 3 +++ 3 files changed, 35 insertions(+)
drivers/gpu/drm/i915/i915_reg.h +1 -0
@@ -272,6 +272,7 @@#define MI_SEMAPHORE_POLL (1<<15)#define MI_SEMAPHORE_SAD_GTE_SDD (1<<12)#define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) +#define MI_STORE_DWORD_IMM_GEN8 MI_INSTR(0x20, 2)#define MI_MEM_VIRTUAL (1 << 22)/* 965+ only */ #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)#define MI_STORE_DWORD_INDEX_SHIFT 2
drivers/gpu/drm/i915/intel_lrc.c +31 -0
@@ -352,6 +352,32 @@ static void gen8_set_seqno(struct intel_engine_cs *ring, u32 seqno)intel_write_status_page (ring,I915_GEM_HWS_INDEX , seqno); } +static int gen8_emit_request (struct intel_ringbuffer *ringbuf) +{ +struct intel_engine_cs *ring = ringbuf->ring; +u32 cmd; +int ret; + + ret =intel_logical_ring_begin (ringbuf,6 ); +if (ret) +return ret; + + cmd =MI_STORE_DWORD_IMM_GEN8 ; + cmd |=MI_GLOBAL_GTT ; + +intel_logical_ring_emit (ringbuf, cmd); +intel_logical_ring_emit (ringbuf, + (ring->status_page.gfx_addr + + (I915_GEM_HWS_INDEX <<MI_STORE_DWORD_INDEX_SHIFT ))); +intel_logical_ring_emit (ringbuf,0 ); +intel_logical_ring_emit (ringbuf, ring->outstanding_lazy_seqno); +intel_logical_ring_emit (ringbuf,MI_USER_INTERRUPT ); +intel_logical_ring_emit (ringbuf,MI_NOOP ); +intel_logical_ring_advance_and_submit (ringbuf); + +return 0 ; +} +void intel_logical_ring_cleanup (struct intel_engine_cs *ring) {if (!intel_ring_initialized (ring))
@@ -426,6 +452,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->cleanup = intel_fini_pipe_control; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; + ring->emit_request = gen8_emit_request;return logical_ring_init (dev, ring); }
@@ -444,6 +471,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; + ring->emit_request = gen8_emit_request;return logical_ring_init (dev, ring); }
@@ -462,6 +490,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; + ring->emit_request = gen8_emit_request;return logical_ring_init (dev, ring); }
@@ -480,6 +509,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; + ring->emit_request = gen8_emit_request;return logical_ring_init (dev, ring); }
@@ -498,6 +528,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; + ring->emit_request = gen8_emit_request;return logical_ring_init (dev, ring); }
drivers/gpu/drm/i915/intel_ringbuffer.h +3 -0
@@ -215,6 +215,9 @@ struct intel_engine_cs { unsigned int num_dwords); } semaphore; +/* Execlists */ +int (*emit_request)(struct intel_ringbuffer *ringbuf); +/** * List of objects currently involved in rendering from the * ringbuffer.
Signature · 1 line
1.7.9.5
PATCH 20/43 drm/i915/bdw: GEN-specific logical ring emit flush
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Same as the legacy-style ring->flush.
v2: The BSD invalidate bit still exists in GEN8! Add it for the VCS rings (but still consolidate the blt and bsd ring flushes into one). This was noticed by Brad Volkin.
v3: The command for BSD and for other rings is slightly different:
get it exactly the same as in gen6_ring_flush + gen6_bsd_ring_flush
--- drivers/gpu/drm/i915/intel_lrc.c | 82 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.c | 7 --- drivers/gpu/drm/i915/intel_ringbuffer.h | 10 ++++ 3 files changed, 92 insertions(+), 7 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +82 -0
@@ -342,6 +342,83 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static int gen8_emit_flush (struct intel_ringbuffer *ringbuf, +u32 invalidate_domains, +u32 unused) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +uint32_t cmd; +int ret; + + ret =intel_logical_ring_begin (ringbuf,4 ); +if (ret) +return ret; + + cmd =MI_FLUSH_DW +1 ; + +if (ring == &dev_priv->ring[VCS ]) { +if (invalidate_domains &I915_GEM_GPU_DOMAINS ) + cmd |=MI_INVALIDATE_TLB |MI_INVALIDATE_BSD | +MI_FLUSH_DW_STORE_INDEX |MI_FLUSH_DW_OP_STOREDW ; + }else { +if (invalidate_domains &I915_GEM_DOMAIN_RENDER ) + cmd |=MI_INVALIDATE_TLB |MI_FLUSH_DW_STORE_INDEX | +MI_FLUSH_DW_OP_STOREDW ; + } + +intel_logical_ring_emit (ringbuf, cmd); +intel_logical_ring_emit (ringbuf,I915_GEM_HWS_SCRATCH_ADDR |MI_FLUSH_DW_USE_GTT ); +intel_logical_ring_emit (ringbuf,0 );/* upper addr */ +intel_logical_ring_emit (ringbuf,0 );/* value */ +intel_logical_ring_advance (ringbuf); + +return 0 ; +} + +static int gen8_emit_flush_render (struct intel_ringbuffer *ringbuf, +u32 invalidate_domains, +u32 flush_domains) +{ +struct intel_engine_cs *ring = ringbuf->ring; +u32 scratch_addr = ring->scratch.gtt_offset +2 *CACHELINE_BYTES ; +u32 flags =0 ; +int ret; + + flags |=PIPE_CONTROL_CS_STALL ; + +if (flush_domains) { + flags |=PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH ; + flags |=PIPE_CONTROL_DEPTH_CACHE_FLUSH ; + } + +if (invalidate_domains) { + flags |=PIPE_CONTROL_TLB_INVALIDATE ; + flags |=PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE ; + flags |=PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE ; + flags |=PIPE_CONTROL_VF_CACHE_INVALIDATE ; + flags |=PIPE_CONTROL_CONST_CACHE_INVALIDATE ; + flags |=PIPE_CONTROL_STATE_CACHE_INVALIDATE ; + flags |=PIPE_CONTROL_QW_WRITE ; + flags |=PIPE_CONTROL_GLOBAL_GTT_IVB ; + } + + ret =intel_logical_ring_begin (ringbuf,6 ); +if (ret) +return ret; + +intel_logical_ring_emit (ringbuf,GFX_OP_PIPE_CONTROL (6 )); +intel_logical_ring_emit (ringbuf, flags); +intel_logical_ring_emit (ringbuf, scratch_addr); +intel_logical_ring_emit (ringbuf,0 ); +intel_logical_ring_emit (ringbuf,0 ); +intel_logical_ring_emit (ringbuf,0 ); +intel_logical_ring_advance (ringbuf); + +return 0 ; +} +static u32 gen8_get_seqno (struct intel_engine_cs *ring,bool lazy_coherency) {return intel_read_status_page (ring,I915_GEM_HWS_INDEX );
@@ -453,6 +530,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush_render;return logical_ring_init (dev, ring); }
@@ -472,6 +550,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush;return logical_ring_init (dev, ring); }
@@ -491,6 +570,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush;return logical_ring_init (dev, ring); }
@@ -510,6 +590,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush;return logical_ring_init (dev, ring); }
@@ -529,6 +610,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; + ring->emit_flush = gen8_emit_flush;return logical_ring_init (dev, ring); }
drivers/gpu/drm/i915/intel_ringbuffer.c +0 -7
@@ -33,13 +33,6 @@#include "i915_trace.h" #include "intel_drv.h" -/* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, -* but keeps the logic simple. Indeed, the whole purpose of this macro is just -* to give some inclination as to some of the magic values used in the various -* workarounds! -*/ -#define CACHELINE_BYTES 64 -bool intel_ring_initialized (struct intel_engine_cs *ring) {
drivers/gpu/drm/i915/intel_ringbuffer.h +10 -0
@@ -5,6 +5,13 @@#define I915_CMD_HASH_ORDER 9 +/* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, +* but keeps the logic simple. Indeed, the whole purpose of this macro is just +* to give some inclination as to some of the magic values used in the various +* workarounds! +*/ +#define CACHELINE_BYTES 64 +/* * Gen2 BSpec "1. Programming Environment" / 1.4.4.6 "Ring Buffer Use" * Gen3 BSpec "vol1c Memory Interface Functions" / 2.3.4.5 "Ring Buffer Use"
@@ -217,6 +224,9 @@ struct intel_engine_cs {/* Execlists */ int (*emit_request)(struct intel_ringbuffer *ringbuf); +int (*emit_flush)(struct intel_ringbuffer *ringbuf, +u32 invalidate_domains, +u32 flush_domains);/** * List of objects currently involved in rendering from the
Signature · 1 line
1.7.9.5
PATCH 21/43 drm/i915/bdw: Emission of requests with logical rings
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
On a previous iteration of this patch, I created an Execlists version of __i915_add_request and asbtracted it away as a vfunc. Daniel Vetter wondered then why that was needed:
"with the clean split in command submission I expect every function to know wether it'll submit to an lrc (everything in intel_lrc.c) or wether it'll submit to a legacy ring (existing code), so I don't see a need for an add_request vfunc."
The honest, hairy truth is that this patch is the glue keeping the whole logical ring puzzle together:
- i915_add_request is used by intel_ring_idle, which in turn is used by i915_gpu_idle, which in turn is used in several places inside the eviction and gtt codes.
- Also, it is used by i915_gem_check_olr, which is littered all over i915_gem.c
- ...
If I were to duplicate all the code that directly or indirectly uses __i915_add_request, I'll end up creating a separate driver.
To show the differences between the existing legacy version and the new Execlists one, this time I have special-cased __i915_add_request instead of adding an add_request vfunc. I hope this helps to untangle this Gordian knot.
--- drivers/gpu/drm/i915/i915_gem.c | 72 ++++++++++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_lrc.c | 30 +++++++++++++--- drivers/gpu/drm/i915/intel_lrc.h | 1 + 3 files changed, 80 insertions(+), 23 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +53 -19
@@ -2327,10 +2327,21 @@ int __i915_add_request(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf;u32 request_ring_position, request_start;int ret; - request_start =intel_ring_get_tail (ring->buffer); + request = ring->preallocated_lazy_request; +if (WARN_ON (request ==NULL )) +return -ENOMEM ; + +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; + + request_start =intel_ring_get_tail (ringbuf);/* * Emit any outstanding flushes - execbuf can fail to emit the flush * after having emitted the batchbuffer command. Hence we need to fix
@@ -2338,24 +2349,32 @@ int __i915_add_request(struct intel_engine_cs *ring,* is that the flush _must_ happen before the next request, no matter * what. */ - ret =intel_ring_flush_all_caches (ring); -if (ret) -return ret; - - request = ring->preallocated_lazy_request; -if (WARN_ON (request ==NULL )) -return -ENOMEM ; +if (i915.enable_execlists) { + ret =logical_ring_flush_all_caches (ringbuf); +if (ret) +return ret; + }else { + ret =intel_ring_flush_all_caches (ring); +if (ret) +return ret; + }/* Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the head. */ - request_ring_position =intel_ring_get_tail (ring->buffer); + request_ring_position =intel_ring_get_tail (ringbuf); - ret = ring->add_request (ring); -if (ret) -return ret; +if (i915.enable_execlists) { + ret = ring->emit_request (ringbuf); +if (ret) +return ret; + }else { + ret = ring->add_request (ring); +if (ret) +return ret; + } request->seqno =intel_ring_get_seqno (ring); request->ring = ring;
@@ -2370,12 +2389,14 @@ int __i915_add_request(struct intel_engine_cs *ring,*/ request->batch_obj = obj; -/* Hold a reference to the current context so that we can inspect -* it later in case a hangcheck error event fires. -*/ - request->ctx = ring->last_context; -if (request->ctx) -i915_gem_context_reference (request->ctx); +if (!i915.enable_execlists) { +/* Hold a reference to the current context so that we can inspect +* it later in case a hangcheck error event fires. +*/ + request->ctx = ring->last_context; +if (request->ctx) +i915_gem_context_reference (request->ctx); + } request->emitted_jiffies = jiffies;list_add_tail (&request->list, &ring->request_list);
@@ -2630,6 +2651,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)while (!list_empty (&ring->request_list)) {struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf; request = list_first_entry(&ring->request_list, struct drm_i915_gem_request,
@@ -2639,12 +2661,24 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)break ;trace_i915_gem_request_retire (ring, request->seqno); + +/* This is one of the few common intersection points +* between legacy ringbuffer submission and execlists: +* we need to tell them apart in order to find the correct +* ringbuffer to which the request belongs to. +*/ +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; +/* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position * of tail of the request to update the last known position * of the GPU head. */ - ring->buffer->last_retired_head = request->tail; + ringbuf->last_retired_head = request->tail;i915_gem_free_request (request); }
drivers/gpu/drm/i915/intel_lrc.c +26 -4
@@ -106,6 +106,22 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */ } +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf) +{ +struct intel_engine_cs *ring = ringbuf->ring; +int ret; + +if (!ring->gpu_caches_dirty) +return 0 ; + + ret = ring->emit_flush (ringbuf,0 ,I915_GEM_GPU_DOMAINS ); +if (ret) +return ret; + + ring->gpu_caches_dirty = false; +return 0 ; +} +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) {intel_logical_ring_advance (ringbuf);
@@ -116,7 +132,8 @@ void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)/* TODO: how to submit a context to the ELSP is not here yet */ } -static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring, +struct intel_context *ctx) {if (ring->outstanding_lazy_seqno)return 0 ;
@@ -128,6 +145,13 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring)if (request ==NULL )return -ENOMEM ; +/* Hold a reference to the context this request belongs to +* (we will need it when the time comes to emit/retire the +* request). +*/ + request->ctx = ctx; +i915_gem_context_reference (request->ctx); + ring->preallocated_lazy_request = request; }
@@ -165,8 +189,6 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, int bytesif (ret)return ret; -/* TODO: make sure we update the right ringbuffer's last_retired_head -* when retiring requests */ i915_gem_retire_requests_ring (ring); ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ;
@@ -291,7 +313,7 @@ int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords)return ret;/* Preallocate the olr before touching the ring */ - ret =logical_ring_alloc_seqno (ring); + ret =logical_ring_alloc_seqno (ring, ringbuf->ctx);if (ret)return ret;
drivers/gpu/drm/i915/intel_lrc.h +1 -0
@@ -29,6 +29,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring);void intel_logical_ring_cleanup (struct intel_engine_cs *ring);int intel_logical_rings_init (struct drm_device *dev); +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf);void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf);static inline void intel_logical_ring_advance (struct intel_ringbuffer *ringbuf) {
Signature · 1 line
1.7.9.5
Re: [PATCH 21/43] drm/i915/bdw: Emission of requests with logical rings
Quoted 6 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
On a previous iteration of this patch, I created an Execlists version of
__i915_add_requestand asbtracted it away as a vfunc. Daniel Vetter wondered then why that was needed:
Quoted 7 lines
"with the clean split in command submission I expect every function to know wether it'll submit to an lrc (everything in
intel_lrc.c) or wether it'll submit to a legacy ring (existing code), so I don't see a need for anadd_requestvfunc."The honest, hairy truth is that this patch is the glue keeping the whole logical ring puzzle together:
Oops, I didn't spot this and it's indeed not terribly pretty.
Quoted 4 lines
-
i915_add_requestis used byintel_ring_idle, which in turn is used byi915_gpu_idle, which in turn is used in several places inside the eviction and gtt codes.
This should probably be folded in with the lrc specific version of stop_rings and so should work out.
Quoted 2 lines
- Also, it is used by
i915_gem_check_olr, which is littered all overi915_gem.c
We now always preallocate the request struct, so olr is officially dead. Well almost, except for non-execbuf stuff that we emit through the rings. Which is nothing for lrc/execlist mode.
Also there's the icky-bitty problem with ringbuf->ctx which makes this patch not apply any more. I think we need to revise or at least discuss a bit.
Quoted 204 lines
- ...
If I were to duplicate all the code that directly or indirectly uses
__i915_add_request, I'll end up creating a separate driver.To show the differences between the existing legacy version and the new Execlists one, this time I have special-cased
__i915_add_requestinstead of adding anadd_requestvfunc. I hope this helps to untangle this Gordian knot.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem.c | 72 ++++++++++++++++++++++++++++---------- drivers/gpu/drm/i915/intel_lrc.c | 30 +++++++++++++--- drivers/gpu/drm/i915/intel_lrc.h | 1 + 3 files changed, 80 insertions(+), 23 deletions(-)drivers/gpu/drm/i915/i915_gem.c +53
-19@@ -2327,10 +2327,21 @@ int __i915_add_request(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf;u32 request_ring_position, request_start;int ret; - request_start =intel_ring_get_tail (ring->buffer); + request = ring->preallocated_lazy_request; +if (WARN_ON (request ==NULL )) +return -ENOMEM ; + +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; + + request_start =intel_ring_get_tail (ringbuf);/* * Emit any outstanding flushes - execbuf can fail to emit the flush * after having emitted the batchbuffer command. Hence we need to fix @@ -2338,24 +2349,32 @@ int __i915_add_request(struct intel_engine_cs *ring,* is that the flush _must_ happen before the next request, no matter * what. */ - ret =intel_ring_flush_all_caches (ring); -if (ret) -return ret; - - request = ring->preallocated_lazy_request; -if (WARN_ON (request ==NULL )) -return -ENOMEM ; +if (i915.enable_execlists) { + ret =logical_ring_flush_all_caches (ringbuf); +if (ret) +return ret; + }else { + ret =intel_ring_flush_all_caches (ring); +if (ret) +return ret; + }/* Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the head. */ - request_ring_position =intel_ring_get_tail (ring->buffer); + request_ring_position =intel_ring_get_tail (ringbuf); - ret = ring->add_request (ring); -if (ret) -return ret; +if (i915.enable_execlists) { + ret = ring->emit_request (ringbuf); +if (ret) +return ret; + }else { + ret = ring->add_request (ring); +if (ret) +return ret; + } request->seqno =intel_ring_get_seqno (ring); request->ring = ring;@@ -2370,12 +2389,14 @@ int __i915_add_request(struct intel_engine_cs *ring,*/ request->batch_obj = obj; -/* Hold a reference to the current context so that we can inspect -* it later in case a hangcheck error event fires. -*/ - request->ctx = ring->last_context; -if (request->ctx) -i915_gem_context_reference (request->ctx); +if (!i915.enable_execlists) { +/* Hold a reference to the current context so that we can inspect +* it later in case a hangcheck error event fires. +*/ + request->ctx = ring->last_context; +if (request->ctx) +i915_gem_context_reference (request->ctx); + } request->emitted_jiffies = jiffies;list_add_tail (&request->list, &ring->request_list);@@ -2630,6 +2651,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)while (!list_empty (&ring->request_list)) {struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf; request = list_first_entry(&ring->request_list, struct drm_i915_gem_request,@@ -2639,12 +2661,24 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring)break ;trace_i915_gem_request_retire (ring, request->seqno); + +/* This is one of the few common intersection points +* between legacy ringbuffer submission and execlists: +* we need to tell them apart in order to find the correct +* ringbuffer to which the request belongs to. +*/ +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; +/* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position * of tail of the request to update the last known position * of the GPU head. */ - ring->buffer->last_retired_head = request->tail; + ringbuf->last_retired_head = request->tail;i915_gem_free_request (request); }drivers/gpu/drm/i915/intel_lrc.c +25
-3@@ -106,6 +106,22 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)/* TODO */ } +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf) +{ +struct intel_engine_cs *ring = ringbuf->ring; +int ret; + +if (!ring->gpu_caches_dirty) +return 0 ; + + ret = ring->emit_flush (ringbuf,0 ,I915_GEM_GPU_DOMAINS ); +if (ret) +return ret; + + ring->gpu_caches_dirty = false; +return 0 ; +} +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) {intel_logical_ring_advance (ringbuf);@@ -116,7 +132,8 @@ void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)/* TODO: how to submit a context to the ELSP is not here yet */ } -static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring, +struct intel_context *ctx) {if (ring->outstanding_lazy_seqno)return 0 ;@@ -128,6 +145,13 @@ static int logical_ring_alloc_seqno(struct intel_engine_cs *ring)if (request ==NULL )return -ENOMEM ; +/* Hold a reference to the context this request belongs to +* (we will need it when the time comes to emit/retire the +* request). +*/ + request->ctx = ctx; +i915_gem_context_reference (request->ctx); + ring->preallocated_lazy_request = request; }@@ -165,8 +189,6 @@ static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, int bytesif (ret)return ret; -/* TODO: make sure we update the right ringbuffer's last_retired_head -* when retiring requests */ i915_gem_retire_requests_ring (ring); ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ;
drivers/gpu/drm/i915/intel_lrc.c int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords) · line 316
Quoted 5 lines
drivers/gpu/drm/i915/intel_lrc.c +1
-1@@ -291,7 +313,7 @@ int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords)return ret;/* Preallocate the olr before touching the ring */ - ret =logical_ring_alloc_seqno (ring); + ret =logical_ring_alloc_seqno (ring, ringbuf->ctx);
Ok, this is hairy. Really hairy, since this uses ringbuf->ctx. Not sure we really want this or need this.
Quoted 22 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0if (ret)return ret;drivers/gpu/drm/i915/intel_lrc.h +1
-0@@ -29,6 +29,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring);void intel_logical_ring_cleanup (struct intel_engine_cs *ring);int intel_logical_rings_init (struct drm_device *dev); +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf);void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf);static inline void intel_logical_ring_advance (struct intel_ringbuffer *ringbuf) {Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 21/43] drm/i915/bdw: Emission of requests with logical rings
Quoted 23 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 9:57 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 21/43] drm/i915/bdw: Emission of requests with logical ringsQuoted 11 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
On a previous iteration of this patch, I created an Execlists version of
__i915_add_requestand asbtracted it away as a vfunc. Daniel Vetter wondered then why that was needed:"with the clean split in command submission I expect every function to know wether it'll submit to an lrc (everything in
intel_lrc.c) or wether it'll submit to a legacy ring (existing code), so I don't see a need for anadd_requestvfunc."
Quoted 4 lines
Quoted 2 lines
The honest, hairy truth is that this patch is the glue keeping the whole logical ring puzzle together:
Oops, I didn't spot this and it's indeed not terribly pretty.
Are you saying you want to go back to a vfunc for add_request?
Quoted 11 lines
Quoted 4 lines
-
i915_add_requestis used byintel_ring_idle, which in turn is used byi915_gpu_idle, which in turn is used in several places inside the eviction and gtt codes.This should probably be folded in with the lrc specific version of
stop_ringsand so should work out.Quoted 2 lines
- Also, it is used by
i915_gem_check_olr, which is littered all overi915_gem.c
Quoted 7 lines
We now always preallocate the request struct, so olr is officially dead. Well almost, except for non-execbuf stuff that we emit through the rings. Which is nothing for lrc/execlist mode.
Also there's the icky-bitty problem with
ringbuf->ctxwhich makes this patch not apply any more. I think we need to revise or at least discuss a bit.
Context is required when doing an advance_and_submit so that we know which context to queue in the execlist queue.
Quoted 215 lines
Quoted 5 lines
- ...
If I were to duplicate all the code that directly or indirectly uses
__i915_add_request, I'll end up creating a separate driver.Quoted 8 lines
To show the differences between the existing legacy version and the new Execlists one, this time I have special-cased
__i915_add_requestinstead of adding anadd_requestvfunc. I hope this helps to untangle this Gordian knot.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem.c | 72++++++++++++++++++++++++++++----------
Quoted 31 lines
drivers/gpu/drm/i915/intel_lrc.c | 30 +++++++++++++--- drivers/gpu/drm/i915/intel_lrc.h | 1 + 3 files changed, 80 insertions(+), 23 deletions(-)(quoted diff) +0
-0
b/drivers/gpu/drm/i915/i915_gem.cindex 9560b40..1c83b9c 100644drivers/gpu/drm/i915/i915_gem.c +12
-1@@ -2327,10 +2327,21 @@ int __i915_add_request(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf;u32 request_ring_position, request_start;int ret; - request_start =intel_ring_get_tail (ring->buffer); + request = ring->preallocated_lazy_request; +if (WARN_ON (request ==NULL )) +return -ENOMEM ; + +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; + + request_start =intel_ring_get_tail (ringbuf);/* * Emit any outstanding flushes - execbuf can fail to emit the flush * after having emitted the batchbuffer command. Hence we need to Quoted 1 line
fix @@ -2338,24 +2349,32 @@ int __i915_add_request(struct
intel_engine_cs*ring,Quoted 1 line
* is that the flush _must_ happen before the next request, no
matter
drivers/gpu/drm/i915/i915_gem.c int __i915_add_request(struct intel_engine_cs
Quoted 43 lines
drivers/gpu/drm/i915/i915_gem.c +19
-11* what. */ - ret =intel_ring_flush_all_caches (ring); -if (ret) -return ret; - - request = ring->preallocated_lazy_request; -if (WARN_ON (request ==NULL )) -return -ENOMEM ; +if (i915.enable_execlists) { + ret =logical_ring_flush_all_caches (ringbuf); +if (ret) +return ret; + }else { + ret =intel_ring_flush_all_caches (ring); +if (ret) +return ret; + }/* Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the head. */ - request_ring_position =intel_ring_get_tail (ring->buffer); + request_ring_position =intel_ring_get_tail (ringbuf); - ret = ring->add_request (ring); -if (ret) -return ret; +if (i915.enable_execlists) { + ret = ring->emit_request (ringbuf); +if (ret) +return ret; + }else { + ret = ring->add_request (ring); +if (ret) +return ret; + } request->seqno =intel_ring_get_seqno (ring); request->ring = ring;@@ -2370,12 +2389,14 @@ int __i915_add_request(struct intel_engine_cs*ring,
drivers/gpu/drm/i915/i915_gem.c int __i915_add_request(struct intel_engine_cs *ring,
Quoted 11 lines
drivers/gpu/drm/i915/i915_gem.c +2
-6*/ request->batch_obj = obj; -/* Hold a reference to the current context so that we can inspect -* it later in case a hangcheck error event fires. -*/ - request->ctx = ring->last_context; -if (request->ctx) -i915_gem_context_reference (request->ctx); +if (!i915.enable_execlists) { +/* Hold a reference to the current context so that we can inspect
drivers/gpu/drm/i915/i915_gem.c i915_gem_retire_requests_ring(struct
Quoted 18 lines
drivers/gpu/drm/i915/i915_gem.c +8
-0+* it later in case a hangcheck error event fires. +*/ + request->ctx = ring->last_context; +if (request->ctx) +i915_gem_context_reference (request->ctx); + } request->emitted_jiffies = jiffies; list_add_tail(&request->list, &ring->request_list); @@ -2630,6 +2651,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) while (!list_empty(&ring->request_list)) {struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf; request = list_first_entry(&ring->request_list, struct drm_i915_gem_request,@@ -2639,12 +2661,24 @@ i915_gem_retire_requests_ring(struct
intel_engine_cs*ring)drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_stop(struct intel_engine_cs
Quoted 31 lines
drivers/gpu/drm/i915/i915_gem.c +13
-1break ;trace_i915_gem_request_retire (ring, request->seqno); + +/* This is one of the few common intersection points +* between legacy ringbuffer submission and execlists: +* we need to tell them apart in order to find the correct +* ringbuffer to which the request belongs to. +*/ +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; +/* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position * of tail of the request to update the last known position * of the GPU head. */ - ring->buffer->last_retired_head = request->tail; + ringbuf->last_retired_head = request->tail;i915_gem_free_request (request); }drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -106,6 +106,22 @@ void intel_logical_ring_stop(struct intel_engine_cs*ring)
drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_advance_and_submit(struct
Quoted 22 lines
drivers/gpu/drm/i915/intel_lrc.c +15
-0/* TODO */ } +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf) { +struct intel_engine_cs *ring = ringbuf->ring; +int ret; + +if (!ring->gpu_caches_dirty) +return 0 ; + + ret = ring->emit_flush (ringbuf,0 ,I915_GEM_GPU_DOMAINS ); +if (ret) +return ret; + + ring->gpu_caches_dirty = false; +return 0 ; +} +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) {intel_logical_ring_advance (ringbuf);@@ -116,7 +132,8 @@ void intel_logical_ring_advance_and_submit(struct
intel_ringbuffer*ringbuf)drivers/gpu/drm/i915/intel_lrc.c static int logical_ring_alloc_seqno(struct
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-1/* TODO: how to submit a context to the ELSP is not here yet */ } -static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring, +struct intel_context *ctx) {if (ring->outstanding_lazy_seqno)return 0 ;@@ -128,6 +145,13 @@ static int logical_ring_alloc_seqno(struct
intel_engine_cs*ring)drivers/gpu/drm/i915/intel_lrc.c static int logical_ring_wait_request(struct
Quoted 14 lines
drivers/gpu/drm/i915/intel_lrc.c +7
-0if (request ==NULL )return -ENOMEM ; +/* Hold a reference to the context this request belongs to +* (we will need it when the time comes to emit/retire the +* request). +*/ + request->ctx = ctx; +i915_gem_context_reference (request->ctx); + ring->preallocated_lazy_request = request; }@@ -165,8 +189,6 @@ static int logical_ring_wait_request(struct
intel_ringbuffer*ringbuf, int bytesdrivers/gpu/drm/i915/intel_lrc.c static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, int bytes
Quoted 4 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-1if (ret)return ret; -/* TODO: make sure we update the right ringbuffer's
last_retired_headdrivers/gpu/drm/i915/intel_lrc.c int intel_logical_ring_begin(struct intel_ringbuffer
Quoted 5 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-1-* when retiring requests */ i915_gem_retire_requests_ring (ring); ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ;@@ -291,7 +313,7 @@ int intel_logical_ring_begin(struct intel_ringbuffer*ringbuf, int
num_dwords)
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords) · line 316
Quoted 5 lines
drivers/gpu/drm/i915/intel_lrc.c +1
-1return ret;/* Preallocate the olr before touching the ring */ - ret =logical_ring_alloc_seqno (ring); + ret =logical_ring_alloc_seqno (ring, ringbuf->ctx);Ok, this is hairy. Really hairy, since this uses
ringbuf->ctx. Not sure we really want this or need this.
alloc_seqno needs to know the context since it also preallocates and populates the request, which belongs to a specific context. Having the logical context pointer inside the ring buffer makes the code a lot more elegant imo, since we don't have to keep passing buffer and context around when there is only one context which can use each ring buffer, just as keeping the engine pointer in the ring buffer means we don't have to pass the engine with it.
As I said in my reply to your patch 8 review I'm happy for ctx to be renamed to avoid confusion in the legacy path
Thomas.
Quoted 28 lines
Quoted 19 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0if (ret)return ret;drivers/gpu/drm/i915/intel_lrc.h +1
-1@@ -29,6 +29,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring); void intel_logical_ring_cleanup(struct intel_engine_cs *ring);int intel_logical_rings_init (struct drm_device *dev); +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf);void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf);static inline void intel_logical_ring_advance (struct intel_ringbuffer *ringbuf) { --1.7.9.5
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 21/43] drm/i915/bdw: Emission of requests with logical rings
Quoted 23 lines · Thomas
Quoted 23 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 9:57 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 21/43] drm/i915/bdw: Emission of requests with logical ringsQuoted 11 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
On a previous iteration of this patch, I created an Execlists version of
__i915_add_requestand asbtracted it away as a vfunc. Daniel Vetter wondered then why that was needed:"with the clean split in command submission I expect every function to know wether it'll submit to an lrc (everything in
intel_lrc.c) or wether it'll submit to a legacy ring (existing code), so I don't see a need for anadd_requestvfunc."
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines
The honest, hairy truth is that this patch is the glue keeping the whole logical ring puzzle together:
Oops, I didn't spot this and it's indeed not terribly pretty.
Are you saying you want to go back to a vfunc for
add_request?
Nope, I'd have expected that there's no need for such a switch at all, and that all these differences disappear behind the execbuf cmd submission abstraction.
Quoted 14 lines
Quoted 14 lines
Quoted 3 lines
-
i915_add_requestis used byintel_ring_idle, which in turn is used byi915_gpu_idle, which in turn is used in several places inside the eviction and gtt codes.This should probably be folded in with the lrc specific version of
stop_ringsand so should work out.Quoted 2 lines
- Also, it is used by
i915_gem_check_olr, which is littered all overi915_gem.cWe now always preallocate the request struct, so olr is officially dead. Well almost, except for non-execbuf stuff that we emit through the rings. Which is nothing for lrc/execlist mode.
Quoted 5 lines
Quoted 3 lines
Also there's the icky-bitty problem with
ringbuf->ctxwhich makes this patch not apply any more. I think we need to revise or at least discuss a bit.Context is required when doing an
advance_and_submitso that we know which context to queue in the execlist queue.
Might need to re-read, but imo it's not a good idea to do a submit in there. If I understand this correctly there should only be a need for an ELSP write (or queueing it up) at the end of the execlist-specific cmd submission implementation. The ringbuffer writes we do before that for the different pieces (flushes, seqno write, bb_start, whatever) should just update the tail pointer in the ring.
Or do I miss something really big here?
Quoted 233 lines
Quoted 216 lines
Quoted 6 lines
- ...
If I were to duplicate all the code that directly or indirectly uses
__i915_add_request, I'll end up creating a separate driver.Quoted 8 lines
To show the differences between the existing legacy version and the new Execlists one, this time I have special-cased
__i915_add_requestinstead of adding anadd_requestvfunc. I hope this helps to untangle this Gordian knot.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_gem.c | 72++++++++++++++++++++++++++++----------
Quoted 31 lines
drivers/gpu/drm/i915/intel_lrc.c | 30 +++++++++++++--- drivers/gpu/drm/i915/intel_lrc.h | 1 + 3 files changed, 80 insertions(+), 23 deletions(-)(quoted diff) +0
-0
b/drivers/gpu/drm/i915/i915_gem.cindex 9560b40..1c83b9c 100644drivers/gpu/drm/i915/i915_gem.c +12
-1@@ -2327,10 +2327,21 @@ int __i915_add_request(struct intel_engine_cs *ring, {struct drm_i915_private *dev_priv = ring->dev->dev_private;struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf;u32 request_ring_position, request_start;int ret; - request_start =intel_ring_get_tail (ring->buffer); + request = ring->preallocated_lazy_request; +if (WARN_ON (request ==NULL )) +return -ENOMEM ; + +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; + + request_start =intel_ring_get_tail (ringbuf);/* * Emit any outstanding flushes - execbuf can fail to emit the flush * after having emitted the batchbuffer command. Hence we need to Quoted 1 line
fix @@ -2338,24 +2349,32 @@ int __i915_add_request(struct
intel_engine_cs*ring,Quoted 1 line
* is that the flush _must_ happen before the next request, no
matter
drivers/gpu/drm/i915/i915_gem.c int __i915_add_request(struct intel_engine_cs
Quoted 43 lines
drivers/gpu/drm/i915/i915_gem.c +19
-11* what. */ - ret =intel_ring_flush_all_caches (ring); -if (ret) -return ret; - - request = ring->preallocated_lazy_request; -if (WARN_ON (request ==NULL )) -return -ENOMEM ; +if (i915.enable_execlists) { + ret =logical_ring_flush_all_caches (ringbuf); +if (ret) +return ret; + }else { + ret =intel_ring_flush_all_caches (ring); +if (ret) +return ret; + }/* Record the position of the start of the request so that * should we detect the updated seqno part-way through the * GPU processing the request, we never over-estimate the * position of the head. */ - request_ring_position =intel_ring_get_tail (ring->buffer); + request_ring_position =intel_ring_get_tail (ringbuf); - ret = ring->add_request (ring); -if (ret) -return ret; +if (i915.enable_execlists) { + ret = ring->emit_request (ringbuf); +if (ret) +return ret; + }else { + ret = ring->add_request (ring); +if (ret) +return ret; + } request->seqno =intel_ring_get_seqno (ring); request->ring = ring;@@ -2370,12 +2389,14 @@ int __i915_add_request(struct intel_engine_cs*ring,
drivers/gpu/drm/i915/i915_gem.c int __i915_add_request(struct intel_engine_cs *ring,
Quoted 11 lines
drivers/gpu/drm/i915/i915_gem.c +2
-6*/ request->batch_obj = obj; -/* Hold a reference to the current context so that we can inspect -* it later in case a hangcheck error event fires. -*/ - request->ctx = ring->last_context; -if (request->ctx) -i915_gem_context_reference (request->ctx); +if (!i915.enable_execlists) { +/* Hold a reference to the current context so that we can inspect
drivers/gpu/drm/i915/i915_gem.c i915_gem_retire_requests_ring(struct
Quoted 18 lines
drivers/gpu/drm/i915/i915_gem.c +8
-0+* it later in case a hangcheck error event fires. +*/ + request->ctx = ring->last_context; +if (request->ctx) +i915_gem_context_reference (request->ctx); + } request->emitted_jiffies = jiffies; list_add_tail(&request->list, &ring->request_list); @@ -2630,6 +2651,7 @@ i915_gem_retire_requests_ring(struct intel_engine_cs *ring) while (!list_empty(&ring->request_list)) {struct drm_i915_gem_request *request; +struct intel_ringbuffer *ringbuf; request = list_first_entry(&ring->request_list, struct drm_i915_gem_request,@@ -2639,12 +2661,24 @@ i915_gem_retire_requests_ring(struct
intel_engine_cs*ring)drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_stop(struct intel_engine_cs
Quoted 31 lines
drivers/gpu/drm/i915/i915_gem.c +13
-1break ;trace_i915_gem_request_retire (ring, request->seqno); + +/* This is one of the few common intersection points +* between legacy ringbuffer submission and execlists: +* we need to tell them apart in order to find the correct +* ringbuffer to which the request belongs to. +*/ +if (i915.enable_execlists) { +struct intel_context *ctx = request->ctx; + ringbuf = ctx->engine[ring->id].ringbuf; + }else + ringbuf = ring->buffer; +/* We know the GPU must have read the request to have * sent us the seqno + interrupt, so use the position * of tail of the request to update the last known position * of the GPU head. */ - ring->buffer->last_retired_head = request->tail; + ringbuf->last_retired_head = request->tail;i915_gem_free_request (request); }drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -106,6 +106,22 @@ void intel_logical_ring_stop(struct intel_engine_cs*ring)
drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_advance_and_submit(struct
Quoted 22 lines
drivers/gpu/drm/i915/intel_lrc.c +15
-0/* TODO */ } +int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf) { +struct intel_engine_cs *ring = ringbuf->ring; +int ret; + +if (!ring->gpu_caches_dirty) +return 0 ; + + ret = ring->emit_flush (ringbuf,0 ,I915_GEM_GPU_DOMAINS ); +if (ret) +return ret; + + ring->gpu_caches_dirty = false; +return 0 ; +} +void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) {intel_logical_ring_advance (ringbuf);@@ -116,7 +132,8 @@ void intel_logical_ring_advance_and_submit(struct
intel_ringbuffer*ringbuf)drivers/gpu/drm/i915/intel_lrc.c static int logical_ring_alloc_seqno(struct
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-1/* TODO: how to submit a context to the ELSP is not here yet */ } -static int logical_ring_alloc_seqno (struct intel_engine_cs *ring) +static int logical_ring_alloc_seqno (struct intel_engine_cs *ring, +struct intel_context *ctx) {if (ring->outstanding_lazy_seqno)return 0 ;@@ -128,6 +145,13 @@ static int logical_ring_alloc_seqno(struct
intel_engine_cs*ring)drivers/gpu/drm/i915/intel_lrc.c static int logical_ring_wait_request(struct
Quoted 14 lines
drivers/gpu/drm/i915/intel_lrc.c +7
-0if (request ==NULL )return -ENOMEM ; +/* Hold a reference to the context this request belongs to +* (we will need it when the time comes to emit/retire the +* request). +*/ + request->ctx = ctx; +i915_gem_context_reference (request->ctx); + ring->preallocated_lazy_request = request; }@@ -165,8 +189,6 @@ static int logical_ring_wait_request(struct
intel_ringbuffer*ringbuf, int bytesdrivers/gpu/drm/i915/intel_lrc.c static int logical_ring_wait_request(struct intel_ringbuffer *ringbuf, int bytes
Quoted 4 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-1if (ret)return ret; -/* TODO: make sure we update the right ringbuffer's
last_retired_headdrivers/gpu/drm/i915/intel_lrc.c int intel_logical_ring_begin(struct intel_ringbuffer
Quoted 5 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-1-* when retiring requests */ i915_gem_retire_requests_ring (ring); ringbuf->head = ringbuf->last_retired_head; ringbuf->last_retired_head =-1 ;@@ -291,7 +313,7 @@ int intel_logical_ring_begin(struct intel_ringbuffer*ringbuf, int
num_dwords)Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c int intel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords) · line 316
Quoted 5 lines
drivers/gpu/drm/i915/intel_lrc.c +1
-1return ret;/* Preallocate the olr before touching the ring */ - ret =logical_ring_alloc_seqno (ring); + ret =logical_ring_alloc_seqno (ring, ringbuf->ctx);Ok, this is hairy. Really hairy, since this uses
ringbuf->ctx. Not sure we really want this or need this.
alloc_seqnoneeds to know the context since it also preallocates and populates the request, which belongs to a specific context. Having the logical context pointer inside the ring buffer makes the code a lot more elegant imo, since we don't have to keep passing buffer and context around when there is only one context which can use each ring buffer, just as keeping the engine pointer in the ring buffer means we don't have to pass the engine with it.
Quoted 2 lines
As I said in my reply to your patch 8 review I'm happy for ctx to be renamed to avoid confusion in the legacy path
Well I'm not yet sold on whether we need it at all. For this case here doing the request allocation deeply buried in the ring_begin function isn't pretty. It's an artifact of 5 years of engineering history for the legacy gem codepaths essentially, and with execlists (and the new explicitly fenced world everyone wants to have) I don't think it's a sound decision any more.
Imo for execlist it would make a lot more sense to do this request preallocation much higher up in the execlist cmd submission function. That's kinda one of the reasons I wanted that abstraction. It would be placed after all the prep work and argument checking is done right before we start to fill in new instructions into the lrc ring.
logical_ring_begin would then only have aWARN_ON(!request_not_preallocated).
Cheers, Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 22/43 drm/i915/bdw: Ring idle and stop with logical rings
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
This is a hard one, since there is no direct hardware ring to control when in Execlists.
We reuse intel_ring_idle here, but it should be fine as long as i915_add_request does the ring thing.
--- drivers/gpu/drm/i915/intel_lrc.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +22 -2
@@ -103,7 +103,24 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,void intel_logical_ring_stop (struct intel_engine_cs *ring) { -/* TODO */ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +int ret; + +if (!intel_ring_initialized (ring)) +return ; + + ret =intel_ring_idle (ring); +if (ret && !i915_reset_in_progress (&to_i915 (ring->dev)->gpu_error)) +DRM_ERROR ("failed to quiesce %s whilst cleaning up: %d\n" , + ring->name, ret); + +/* TODO: Is this correct with Execlists enabled? */ +I915_WRITE_MODE (ring,_MASKED_BIT_ENABLE (STOP_RING )); +if (wait_for_atomic ((I915_READ_MODE (ring) &MODE_IDLE ) !=0 ,1000 )) { +DRM_ERROR ("%s :timed out trying to stop ring\n" , ring->name); +return ; + } +I915_WRITE_MODE (ring,_MASKED_BIT_DISABLE (STOP_RING )); }int logical_ring_flush_all_caches (struct intel_ringbuffer *ringbuf)
@@ -479,10 +496,13 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf)void intel_logical_ring_cleanup (struct intel_engine_cs *ring) { +struct drm_i915_private *dev_priv = ring->dev->dev_private; +if (!intel_ring_initialized (ring))return ; -/* TODO: make sure the ring is stopped */ +intel_logical_ring_stop (ring); +WARN_ON ((I915_READ_MODE (ring) &MODE_IDLE ) ==0 ); ring->preallocated_lazy_request =NULL ; ring->outstanding_lazy_seqno =0 ;
Signature · 1 line
1.7.9.5
PATCH 23/43 drm/i915/bdw: Interrupts with logical rings
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
We need to attend context switch interrupts from all rings. Also, fixed writing IMR/IER and added HWSTAM at ring init time.
Notice that, if added to irq_enable_mask, the context switch interrupts would be incorrectly masked out when the user interrupts are due to no users waiting on a sequence number. Therefore, this commit adds a bitmask of interrupts to be kept unmasked at all times.
v2: Disable HWSTAM, as suggested by Damien (nobody listens to these interrupts, anyway).
v3: Add new get/put_irq functions.
--- drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++-- drivers/gpu/drm/i915/i915_reg.h | 3 ++ drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 78 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +16 -3
@@ -1643,6 +1643,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,notify_ring (dev, &dev_priv->ring[RCS ]);if (bcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[BCS ]); +if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }
@@ -1655,9 +1657,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS2 ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }
@@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VECS_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VECS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }
@@ -3768,12 +3776,17 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)/* These are interrupts we'll toggle with the ring mask register */ uint32_t gt_interrupts[] = {GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_RCS_IRQ_SHIFT |GT_RENDER_L3_PARITY_ERROR_INTERRUPT | -GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT , +GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ,GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | -GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT , +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | +GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ,0 , -GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT +GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VECS_IRQ_SHIFT };for (i =0 ; i <ARRAY_SIZE (gt_interrupts); i++)
drivers/gpu/drm/i915/i915_reg.h +3 -0
@@ -1062,6 +1062,7 @@ enum punit_power_well {#define RING_ACTHD_UDW (base) ((base)+0x5c)#define RING_NOPID (base) ((base)+0x94)#define RING_IMR (base) ((base)+0xa8) +#define RING_HWSTAM (base) ((base)+0x98)#define RING_TIMESTAMP (base) ((base)+0x358)#define TAIL_ADDR 0x001FFFF8#define HEAD_WRAP_COUNT 0xFFE00000
@@ -4590,6 +4591,8 @@ enum punit_power_well {#define GEN8_GT_IIR (which) (0x44308 + (0x10 * (which)))#define GEN8_GT_IER (which) (0x4430c + (0x10 * (which))) +#define GEN8_GT_CONTEXT_SWITCH_INTERRUPT (1 << 8) +#define GEN8_BCS_IRQ_SHIFT 16#define GEN8_RCS_IRQ_SHIFT 0#define GEN8_VCS2_IRQ_SHIFT 16
drivers/gpu/drm/i915/intel_lrc.c +58 -0
130 lines not on this page · raw message
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -0
@@ -223,6 +223,7 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf, u32 invalidate_domains,
Signature · 1 line
1.7.9.5
Re: [PATCH 23/43] drm/i915/bdw: Interrupts with logical rings
Quoted 10 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
We need to attend context switch interrupts from all rings. Also, fixed writing IMR/IER and added HWSTAM at ring init time.
Notice that, if added to
irq_enable_mask, the context switch interrupts would be incorrectly masked out when the user interrupts are due to no users waiting on a sequence number. Therefore, this commit adds a bitmask of interrupts to be kept unmasked at all times.
Quoted 7 lines
v2: Disable HWSTAM, as suggested by Damien (nobody listens to these interrupts, anyway).
v3: Add new get/put_irq functions.
Signed-off-by Thomas Daniel <[email protected]> (v1)Signed-off-by Oscar Mateo <[email protected]> (v2 & v3)
irq_keep_mask is a nifty idea, would be pretty to roll it out for legacy rings too. But totally optional.
-Daniel
Quoted 246 lines
--- drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++-- drivers/gpu/drm/i915/i915_reg.h | 3 ++ drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 78 insertions(+), 3 deletions(-)drivers/gpu/drm/i915/i915_irq.c +16
-3@@ -1643,6 +1643,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,notify_ring (dev, &dev_priv->ring[RCS ]);if (bcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[BCS ]); +if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }@@ -1655,9 +1657,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS2 ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }@@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VECS_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VECS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }@@ -3768,12 +3776,17 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)/* These are interrupts we'll toggle with the ring mask register */ uint32_t gt_interrupts[] = {GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_RCS_IRQ_SHIFT |GT_RENDER_L3_PARITY_ERROR_INTERRUPT | -GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT , +GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ,GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | -GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT , +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | +GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ,0 , -GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT +GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VECS_IRQ_SHIFT };for (i =0 ; i <ARRAY_SIZE (gt_interrupts); i++)drivers/gpu/drm/i915/i915_reg.h +3
-0@@ -1062,6 +1062,7 @@ enum punit_power_well {#define RING_ACTHD_UDW (base) ((base)+0x5c)#define RING_NOPID (base) ((base)+0x94)#define RING_IMR (base) ((base)+0xa8) +#define RING_HWSTAM (base) ((base)+0x98)#define RING_TIMESTAMP (base) ((base)+0x358)#define TAIL_ADDR 0x001FFFF8#define HEAD_WRAP_COUNT 0xFFE00000@@ -4590,6 +4591,8 @@ enum punit_power_well {#define GEN8_GT_IIR (which) (0x44308 + (0x10 * (which)))#define GEN8_GT_IER (which) (0x4430c + (0x10 * (which))) +#define GEN8_GT_CONTEXT_SWITCH_INTERRUPT (1 << 8) +#define GEN8_BCS_IRQ_SHIFT 16#define GEN8_RCS_IRQ_SHIFT 0#define GEN8_VCS2_IRQ_SHIFT 16drivers/gpu/drm/i915/intel_lrc.c +58
-0@@ -343,6 +343,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)struct drm_device *dev = ring->dev;struct drm_i915_private *dev_priv = dev->dev_private; +I915_WRITE_IMR (ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); +I915_WRITE (RING_HWSTAM (ring->mmio_base),0xffffffff ); +I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_DISABLE (GFX_REPLAY_MODE ) |_MASKED_BIT_ENABLE (GFX_RUN_LIST_ENABLE ));@@ -381,6 +384,39 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static bool gen8_logical_ring_get_irq (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long flags; + +if (!dev->irq_enabled) +return false; + +spin_lock_irqsave (&dev_priv->irq_lock, flags); +if (ring->irq_refcount++ ==0 ) { +I915_WRITE_IMR (ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); +POSTING_READ (RING_IMR (ring->mmio_base)); + } +spin_unlock_irqrestore (&dev_priv->irq_lock, flags); + +return true; +} + +static void gen8_logical_ring_put_irq (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long flags; + +spin_lock_irqsave (&dev_priv->irq_lock, flags); +if (--ring->irq_refcount ==0 ) { +I915_WRITE_IMR (ring, ~ring->irq_keep_mask); +POSTING_READ (RING_IMR (ring->mmio_base)); + } +spin_unlock_irqrestore (&dev_priv->irq_lock, flags); +} +static int gen8_emit_flush (struct intel_ringbuffer *ringbuf,u32 invalidate_domains,u32 unused)@@ -566,6 +602,10 @@ static int logical_render_ring_init(struct drm_device *dev) ring->mmio_base =RENDER_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; +if (HAS_L3_DPF (dev)) + ring->irq_keep_mask |=GT_RENDER_L3_PARITY_ERROR_INTERRUPT ; ring->init = gen8_init_render_ring; ring->cleanup = intel_fini_pipe_control;@@ -573,6 +613,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush_render; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -587,12 +629,16 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->mmio_base =GEN6_BSD_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -607,12 +653,16 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->mmio_base =GEN8_BSD2_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -627,12 +677,16 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->mmio_base =BLT_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -647,12 +701,16 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->mmio_base =VEBOX_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }drivers/gpu/drm/i915/intel_ringbuffer.h +1
-0@@ -223,6 +223,7 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf, u32 invalidate_domains,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 23/43] drm/i915/bdw: Interrupts with logical rings
In reply to Thomas DanielQuoted 94 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
We need to attend context switch interrupts from all rings. Also, fixed writing IMR/IER and added HWSTAM at ring init time.
Notice that, if added to
irq_enable_mask, the context switch interrupts would be incorrectly masked out when the user interrupts are due to no users waiting on a sequence number. Therefore, this commit adds a bitmask of interrupts to be kept unmasked at all times.v2: Disable HWSTAM, as suggested by Damien (nobody listens to these interrupts, anyway).
v3: Add new get/put_irq functions.
Signed-off-by Thomas Daniel <[email protected]> (v1)Signed-off-by Oscar Mateo <[email protected]> (v2 & v3)--- drivers/gpu/drm/i915/i915_irq.c | 19 ++++++++-- drivers/gpu/drm/i915/i915_reg.h | 3 ++ drivers/gpu/drm/i915/intel_lrc.c | 58 +++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 78 insertions(+), 3 deletions(-)drivers/gpu/drm/i915/i915_irq.c +16
-3@@ -1643,6 +1643,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,notify_ring (dev, &dev_priv->ring[RCS ]);if (bcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[BCS ]); +if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }@@ -1655,9 +1657,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VCS2 ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }@@ -1681,6 +1687,8 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, vcs = tmp >>GEN8_VECS_IRQ_SHIFT ;if (vcs >_RENDER_USER_INTERRUPT )notify_ring (dev, &dev_priv->ring[VECS ]); +if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }@@ -3768,12 +3776,17 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv)/* These are interrupts we'll toggle with the ring mask register */ uint32_t gt_interrupts[] = {GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_RCS_IRQ_SHIFT |GT_RENDER_L3_PARITY_ERROR_INTERRUPT | -GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT , +GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ,GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | -GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT , +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT | +GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ,0 , -GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT +GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT | +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VECS_IRQ_SHIFT };for (i =0 ; i <ARRAY_SIZE (gt_interrupts); i++)drivers/gpu/drm/i915/i915_reg.h +1
-0@@ -1062,6 +1062,7 @@ enum punit_power_well {#define RING_ACTHD_UDW (base) ((base)+0x5c)#define RING_NOPID (base) ((base)+0x94)#define RING_IMR (base) ((base)+0xa8) +#define RING_HWSTAM (base) ((base)+0x98)#define RING_TIMESTAMP (base) ((base)+0x358)#define TAIL_ADDR 0x001FFFF8#define HEAD_WRAP_COUNT 0xFFE00000
drivers/gpu/drm/i915/i915_reg.h enum punit_power_well { · line 4594
Quoted 4 lines
drivers/gpu/drm/i915/i915_reg.h +1
-0@@ -4590,6 +4591,8 @@ enum punit_power_well {#define GEN8_GT_IIR (which) (0x44308 + (0x10 * (which)))#define GEN8_GT_IER (which) (0x4430c + (0x10 * (which))) +#define GEN8_GT_CONTEXT_SWITCH_INTERRUPT (1 << 8)
This looked misplaced - I've moved it to its brethren and dropped the GEN8_ prefix for consistency.
-Daniel
Quoted 165 lines
drivers/gpu/drm/i915/i915_reg.h +1
-0+#define GEN8_BCS_IRQ_SHIFT 16#define GEN8_RCS_IRQ_SHIFT 0#define GEN8_VCS2_IRQ_SHIFT 16drivers/gpu/drm/i915/intel_lrc.c +58
-0@@ -343,6 +343,9 @@ static int gen8_init_common_ring(struct intel_engine_cs *ring)struct drm_device *dev = ring->dev;struct drm_i915_private *dev_priv = dev->dev_private; +I915_WRITE_IMR (ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); +I915_WRITE (RING_HWSTAM (ring->mmio_base),0xffffffff ); +I915_WRITE (RING_MODE_GEN7 (ring),_MASKED_BIT_DISABLE (GFX_REPLAY_MODE ) |_MASKED_BIT_ENABLE (GFX_RUN_LIST_ENABLE ));@@ -381,6 +384,39 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static bool gen8_logical_ring_get_irq (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long flags; + +if (!dev->irq_enabled) +return false; + +spin_lock_irqsave (&dev_priv->irq_lock, flags); +if (ring->irq_refcount++ ==0 ) { +I915_WRITE_IMR (ring, ~(ring->irq_enable_mask | ring->irq_keep_mask)); +POSTING_READ (RING_IMR (ring->mmio_base)); + } +spin_unlock_irqrestore (&dev_priv->irq_lock, flags); + +return true; +} + +static void gen8_logical_ring_put_irq (struct intel_engine_cs *ring) +{ +struct drm_device *dev = ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; +unsigned long flags; + +spin_lock_irqsave (&dev_priv->irq_lock, flags); +if (--ring->irq_refcount ==0 ) { +I915_WRITE_IMR (ring, ~ring->irq_keep_mask); +POSTING_READ (RING_IMR (ring->mmio_base)); + } +spin_unlock_irqrestore (&dev_priv->irq_lock, flags); +} +static int gen8_emit_flush (struct intel_ringbuffer *ringbuf,u32 invalidate_domains,u32 unused)@@ -566,6 +602,10 @@ static int logical_render_ring_init(struct drm_device *dev) ring->mmio_base =RENDER_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_RCS_IRQ_SHIFT ; +if (HAS_L3_DPF (dev)) + ring->irq_keep_mask |=GT_RENDER_L3_PARITY_ERROR_INTERRUPT ; ring->init = gen8_init_render_ring; ring->cleanup = intel_fini_pipe_control;@@ -573,6 +613,8 @@ static int logical_render_ring_init(struct drm_device *dev) ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush_render; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -587,12 +629,16 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->mmio_base =GEN6_BSD_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS1_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -607,12 +653,16 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->mmio_base =GEN8_BSD2_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VCS2_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -627,12 +677,16 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->mmio_base =BLT_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_BCS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }@@ -647,12 +701,16 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->mmio_base =VEBOX_RING_BASE ; ring->irq_enable_mask =GT_RENDER_USER_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; + ring->irq_keep_mask = +GEN8_GT_CONTEXT_SWITCH_INTERRUPT <<GEN8_VECS_IRQ_SHIFT ; ring->init = gen8_init_common_ring; ring->get_seqno = gen8_get_seqno; ring->set_seqno = gen8_set_seqno; ring->emit_request = gen8_emit_request; ring->emit_flush = gen8_emit_flush; + ring->irq_get = gen8_logical_ring_get_irq; + ring->irq_put = gen8_logical_ring_put_irq;return logical_ring_init (dev, ring); }drivers/gpu/drm/i915/intel_ringbuffer.h +1
-0@@ -223,6 +223,7 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf, u32 invalidate_domains,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 24/43 drm/i915/bdw: GEN-specific logical ring emit batchbuffer start
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Dispatch_execbuffer's evil twin.
--- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 ++ 2 files changed, 30 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +28 -0
@@ -384,6 +384,29 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static int gen8_emit_bb_start (struct intel_ringbuffer *ringbuf, +u64 offset,unsigned flags) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_i915_private *dev_priv = ring->dev->dev_private; +bool ppgtt = dev_priv->mm.aliasing_ppgtt !=NULL && + !(flags &I915_DISPATCH_SECURE ); +int ret; + + ret =intel_logical_ring_begin (ringbuf,4 ); +if (ret) +return ret; + +/* FIXME(BDW): Address space and security selectors. */ +intel_logical_ring_emit (ringbuf,MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8 )); +intel_logical_ring_emit (ringbuf,lower_32_bits (offset)); +intel_logical_ring_emit (ringbuf,upper_32_bits (offset)); +intel_logical_ring_emit (ringbuf,MI_NOOP ); +intel_logical_ring_advance (ringbuf); + +return 0 ; +} +static bool gen8_logical_ring_get_irq (struct intel_engine_cs *ring) {struct drm_device *dev = ring->dev;
@@ -615,6 +638,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush_render; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }
@@ -639,6 +663,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }
@@ -663,6 +688,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }
@@ -687,6 +713,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }
@@ -711,6 +738,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }
drivers/gpu/drm/i915/intel_ringbuffer.h +2 -0
@@ -228,6 +228,8 @@ struct intel_engine_cs {int (*emit_flush)(struct intel_ringbuffer *ringbuf,u32 invalidate_domains,u32 flush_domains); +int (*emit_bb_start)(struct intel_ringbuffer *ringbuf, +u64 offset,unsigned flags);/** * List of objects currently involved in rendering from the
Signature · 1 line
1.7.9.5
Re: [PATCH 24/43] drm/i915/bdw: GEN-specific logical ring emit batchbuffer start
Quoted 15 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Dispatch_execbuffer's evil twin.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 ++ 2 files changed, 30 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +0
-0
drivers/gpu/drm/i915/intel_lrc.c static int gen8_init_render_ring(struct intel_engine_cs *ring) · line 392
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c +6
-0@@ -384,6 +384,29 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static int gen8_emit_bb_start (struct intel_ringbuffer *ringbuf, +u64 offset,unsigned flags) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_i915_private *dev_priv = ring->dev->dev_private; + bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL &&
The aliasing ppgtt check here is fairly decent bullocks, especially since full ppgtt is a requirement for execlists. I've ditched it since a series from myself will otherwise break this patch.
-Daniel
Quoted 80 lines
drivers/gpu/drm/i915/intel_lrc.c +22
-0+ !(flags &I915_DISPATCH_SECURE ); +int ret; + + ret =intel_logical_ring_begin (ringbuf,4 ); +if (ret) +return ret; + +/* FIXME(BDW): Address space and security selectors. */ +intel_logical_ring_emit (ringbuf,MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8 )); +intel_logical_ring_emit (ringbuf,lower_32_bits (offset)); +intel_logical_ring_emit (ringbuf,upper_32_bits (offset)); +intel_logical_ring_emit (ringbuf,MI_NOOP ); +intel_logical_ring_advance (ringbuf); + +return 0 ; +} +static bool gen8_logical_ring_get_irq (struct intel_engine_cs *ring) {struct drm_device *dev = ring->dev;@@ -615,6 +638,7 @@ static int logical_render_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush_render; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }@@ -639,6 +663,7 @@ static int logical_bsd_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }@@ -663,6 +688,7 @@ static int logical_bsd2_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }@@ -687,6 +713,7 @@ static int logical_blt_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }@@ -711,6 +738,7 @@ static int logical_vebox_ring_init(struct drm_device *dev) ring->emit_flush = gen8_emit_flush; ring->irq_get = gen8_logical_ring_get_irq; ring->irq_put = gen8_logical_ring_put_irq; + ring->emit_bb_start = gen8_emit_bb_start;return logical_ring_init (dev, ring); }drivers/gpu/drm/i915/intel_ringbuffer.h +2
-0@@ -228,6 +228,8 @@ struct intel_engine_cs {int (*emit_flush)(struct intel_ringbuffer *ringbuf,u32 invalidate_domains,u32 flush_domains); +int (*emit_bb_start)(struct intel_ringbuffer *ringbuf, +u64 offset,unsigned flags);/** * List of objects currently involved in rendering from the Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 24/43] drm/i915/bdw: GEN-specific logical ring emit batchbuffer start
Quoted 31 lines · Daniel Vetter
Quoted 15 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Dispatch_execbuffer's evil twin.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 ++ 2 files changed, 30 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +0
-0drivers/gpu/drm/i915/intel_lrc.c static int gen8_init_render_ring(struct intel_engine_cs *ring) · line 392
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c +6
-0@@ -384,6 +384,29 @@ static int gen8_init_render_ring(struct intel_engine_cs *ring)return ret; } +static int gen8_emit_bb_start (struct intel_ringbuffer *ringbuf, +u64 offset,unsigned flags) +{ +struct intel_engine_cs *ring = ringbuf->ring; +struct drm_i915_private *dev_priv = ring->dev->dev_private; + bool ppgtt = dev_priv->mm.aliasing_ppgtt != NULL &&The aliasing ppgtt check here is fairly decent bullocks, especially since full ppgtt is a requirement for execlists. I've ditched it since a series from myself will otherwise break this patch.
-Daniel
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c static int gen8_init_render_ring(struct intel_engine_cs *ring) · line 401
Quoted 9 lines
drivers/gpu/drm/i915/intel_lrc.c +9
-0+ !(flags &I915_DISPATCH_SECURE ); +int ret; + + ret =intel_logical_ring_begin (ringbuf,4 ); +if (ret) +return ret; + +/* FIXME(BDW): Address space and security selectors. */ +intel_logical_ring_emit (ringbuf,MI_BATCH_BUFFER_START_GEN8 | (ppgtt<<8 ));
Also please follow up with a patch to replace the magic 8 here with a proper define. Usual approach is to build this up with an u32 cmd_flags or so. Patch should obviously also rectify the legacy ring stuff. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 25/43 drm/i915/bdw: Workload submission mechanism for Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
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.
--- 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(-)
drivers/gpu/drm/i915/i915_drv.h +6 -0
@@ -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,
drivers/gpu/drm/i915/i915_gem_execbuffer.c +2 -2
@@ -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,
drivers/gpu/drm/i915/intel_lrc.c +129 -1
142 lines not on this page · raw message
Signature · 1 line
1.7.9.5
Re: [PATCH 25/43] drm/i915/bdw: Workload submission mechanism for Execlists
Quoted 93 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
This is what
i915_gem_do_execbuffercalls when it wants to execute some worload in an Execlists world.v2: Check arguments before doing stuff in
intel_execlists_submission. Also, getrel_constantsparsing right.Signed-off-by Oscar Mateo <[email protected]>--- 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(-)drivers/gpu/drm/i915/i915_drv.h +6
-0@@ -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,drivers/gpu/drm/i915/i915_gem_execbuffer.c +2
-2@@ -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,drivers/gpu/drm/i915/intel_lrc.c +31
-0@@ -89,6 +89,57 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsreturn 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)
drivers/gpu/drm/i915/intel_lrc.c int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists · line 132
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+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.
Quoted 54 lines
drivers/gpu/drm/i915/intel_lrc.c +46
-1+ +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 {
drivers/gpu/drm/i915/intel_lrc.c int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, · line 196
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+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
Quoted 42 lines
drivers/gpu/drm/i915/intel_lrc.c +32
-0+ +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 ; }Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 26/43 drm/i915/bdw: Always use MMIO flips with Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
The normal flip function places things in the ring in the legacy way, so we either fix that or force MMIO flips always as we do in this patch.
--- drivers/gpu/drm/i915/intel_display.c | 2 ++ drivers/gpu/drm/i915/intel_lrc.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/intel_display.c +2 -0
@@ -9482,6 +9482,8 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,return false; else if (i915.use_mmio_flip > 0) return true; + else if (i915.enable_execlists) + return true; else return ring != obj->ring; }
drivers/gpu/drm/i915/intel_lrc.c +2 -1
@@ -83,7 +83,8 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsif (enable_execlists ==0 )return 0 ; -if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev)) +if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev) && + i915.use_mmio_flip >=0 )return 1 ;return 0 ;
Signature · 1 line
1.7.9.5
Re: [PATCH 26/43] drm/i915/bdw: Always use MMIO flips with Execlists
Quoted 30 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
The normal flip function places things in the ring in the legacy way, so we either fix that or force MMIO flips always as we do in this patch.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_display.c | 2 ++ drivers/gpu/drm/i915/intel_lrc.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-)drivers/gpu/drm/i915/intel_display.c +2
-0@@ -9482,6 +9482,8 @@ static bool use_mmio_flip(struct intel_engine_cs *ring,return false; else if (i915.use_mmio_flip > 0) return true; + else if (i915.enable_execlists) + return true; else return ring != obj->ring; }drivers/gpu/drm/i915/intel_lrc.c +0
-0
drivers/gpu/drm/i915/intel_lrc.c int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlists · line 87
Quoted 6 lines
drivers/gpu/drm/i915/intel_lrc.c +2
-1@@ -83,7 +83,8 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsif (enable_execlists ==0 )return 0 ; -if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev)) +if (HAS_LOGICAL_RING_CONTEXTS (dev) &&USES_PPGTT (dev) && + i915.use_mmio_flip >=0 )
Almost every patch gets the alignment wrong somewhere. Not terribly amused.
-Daniel
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0return 1 ;return 0 ;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 27/43 drm/i915/bdw: Render state init for Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
The batchbuffer that sets the render context state is submitted in a different way, and from different places.
We needed to make both the render state preparation and free functions outside accesible, and namespace accordingly. This mess is so that all LR, LRC and Execlists functionality can go together in intel_lrc.c: we can fix all of this later on, once the interfaces are clear.
v2: Create a separate ctx->rcs_initialized for the Execlists case, as suggested by Chris Wilson.
--- drivers/gpu/drm/i915/i915_drv.h | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++- drivers/gpu/drm/i915/i915_gem_render_state.c | 40 ++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_render_state.h | 47 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 46 +++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 2 ++ drivers/gpu/drm/i915/intel_renderstate.h | 8 +---- 7 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.h
drivers/gpu/drm/i915/i915_drv.h +2 -2
@@ -37,6 +37,7 @@#include "intel_ringbuffer.h" #include "intel_lrc.h" #include "i915_gem_gtt.h" +#include "i915_gem_render_state.h" #include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h>
@@ -623,6 +624,7 @@ struct intel_context { } legacy_hw_ctx;/* Execlists */ +bool rcs_initialized;struct {struct drm_i915_gem_object *state;struct intel_ringbuffer *ringbuf;
@@ -2553,8 +2555,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,int i915_gem_context_destroy_ioctl (struct drm_device *dev,void *data,struct drm_file *file); -/* i915_gem_render_state.c */ -int i915_gem_render_state_init (struct intel_engine_cs *ring);/* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
drivers/gpu/drm/i915/i915_gem_context.c +16 -1
@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) ppgtt->enable (ppgtt); } -if (i915.enable_execlists) +if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret =intel_lr_context_render_state_init (ring, dctx); +if (ret) { +DRM_ERROR ("Init render state failed: %d\n" , ret); +return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))
drivers/gpu/drm/i915/i915_gem_render_state.c +25 -15
@@ -28,13 +28,6 @@#include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { -const struct intel_renderstate_rodata *rodata; -struct drm_i915_gem_object *obj; -u64 ggtt_offset; -int gen; -}; -static const struct intel_renderstate_rodata *render_state_get_rodata (struct drm_device *dev,const int gen) {
@@ -127,30 +120,47 @@ static int render_state_setup(struct render_state *so)return 0 ; } -static void render_state_fini (struct render_state *so) +void i915_gem_render_state_fini (struct render_state *so) {i915_gem_object_ggtt_unpin (so->obj);drm_gem_object_unreference (&so->obj->base); } -int i915_gem_render_state_init (struct intel_engine_cs *ring) +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so) { -struct render_state so;int ret;if (WARN_ON (ring->id !=RCS ))return -ENOENT ; - ret =render_state_init (&so, ring->dev); + ret =render_state_init (so, ring->dev);if (ret)return ret; -if (so.rodata ==NULL ) +if (so->rodata ==NULL )return 0 ; - ret =render_state_setup (&so); + ret =render_state_setup (so); +if (ret) { +i915_gem_render_state_fini (so); +return ret; + } + +return 0 ; +} + +int i915_gem_render_state_init (struct intel_engine_cs *ring) +{ +struct render_state so; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so);if (ret) - goto out; +return ret; + +if (so.rodata ==NULL ) +return 0 ; ret = ring->dispatch_execbuffer(ring, so.ggtt_offset,
@@ -164,6 +174,6 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring) ret =__i915_add_request (ring,NULL , so.obj,NULL );/* __i915_add_request moves object to inactive if it fails */ out: -render_state_fini (&so); +i915_gem_render_state_fini (&so);return ret; }
drivers/gpu/drm/i915/i915_gem_render_state.h new file +47 -0
47 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.c +46 -0
58 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.h +2 -0
@@ -43,6 +43,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, u32int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords);/* Logical Ring Contexts */ +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx);void intel_lr_context_free (struct intel_context *ctx);int intel_lr_context_deferred_create (struct intel_context *ctx,struct intel_engine_cs *ring);
drivers/gpu/drm/i915/intel_renderstate.h +1 -7
@@ -24,13 +24,7 @@#ifndef _INTEL_RENDERSTATE_H#define _INTEL_RENDERSTATE_H -#include <linux/types.h> - -struct intel_renderstate_rodata { -const u32 *reloc; -const u32 *batch; -const u32 batch_items; -}; +#include "i915_drv.h" extern const struct intel_renderstate_rodata gen6_null_state;extern const struct intel_renderstate_rodata gen7_null_state;
Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 70 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
The batchbuffer that sets the render context state is submitted in a different way, and from different places.
We needed to make both the render state preparation and free functions outside accesible, and namespace accordingly. This mess is so that all LR, LRC and Execlists functionality can go together in
intel_lrc.c: we can fix all of this later on, once the interfaces are clear.v2: Create a separate
ctx->rcs_initializedfor the Execlists case, as suggested by Chris Wilson.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++- drivers/gpu/drm/i915/i915_gem_render_state.c | 40 ++++++++++++++-------- drivers/gpu/drm/i915/i915_gem_render_state.h | 47 ++++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 46 +++++++++++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.h | 2 ++ drivers/gpu/drm/i915/intel_renderstate.h | 8 +---- 7 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.hdrivers/gpu/drm/i915/i915_drv.h +2
-2@@ -37,6 +37,7 @@#include "intel_ringbuffer.h" #include "intel_lrc.h" #include "i915_gem_gtt.h" +#include "i915_gem_render_state.h" #include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -623,6 +624,7 @@ struct intel_context { } legacy_hw_ctx;/* Execlists */ +bool rcs_initialized;struct {struct drm_i915_gem_object *state;struct intel_ringbuffer *ringbuf;@@ -2553,8 +2555,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,int i915_gem_context_destroy_ioctl (struct drm_device *dev,void *data,struct drm_file *file); -/* i915_gem_render_state.c */ -int i915_gem_render_state_init (struct intel_engine_cs *ring);/* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,drivers/gpu/drm/i915/i915_gem_context.c +7
-1@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv) ppgtt->enable (ppgtt); } -if (i915.enable_execlists) +if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) {
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +9
-0+ ret =intel_lr_context_render_state_init (ring, dctx); +if (ret) { +DRM_ERROR ("Init render state failed: %d\n" , ret); +return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }
This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for the first time. The later is what the legacy contexts currently do in do_switch.
But ctx_enable should do the switch to the default context and that's about it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now. -Daniel
Quoted 240 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))drivers/gpu/drm/i915/i915_gem_render_state.c +25
-15@@ -28,13 +28,6 @@#include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { -const struct intel_renderstate_rodata *rodata; -struct drm_i915_gem_object *obj; -u64 ggtt_offset; -int gen; -}; -static const struct intel_renderstate_rodata *render_state_get_rodata (struct drm_device *dev,const int gen) {@@ -127,30 +120,47 @@ static int render_state_setup(struct render_state *so)return 0 ; } -static void render_state_fini (struct render_state *so) +void i915_gem_render_state_fini (struct render_state *so) {i915_gem_object_ggtt_unpin (so->obj);drm_gem_object_unreference (&so->obj->base); } -int i915_gem_render_state_init (struct intel_engine_cs *ring) +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so) { -struct render_state so;int ret;if (WARN_ON (ring->id !=RCS ))return -ENOENT ; - ret =render_state_init (&so, ring->dev); + ret =render_state_init (so, ring->dev);if (ret)return ret; -if (so.rodata ==NULL ) +if (so->rodata ==NULL )return 0 ; - ret =render_state_setup (&so); + ret =render_state_setup (so); +if (ret) { +i915_gem_render_state_fini (so); +return ret; + } + +return 0 ; +} + +int i915_gem_render_state_init (struct intel_engine_cs *ring) +{ +struct render_state so; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so);if (ret) - goto out; +return ret; + +if (so.rodata ==NULL ) +return 0 ; ret = ring->dispatch_execbuffer(ring, so.ggtt_offset,@@ -164,6 +174,6 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring) ret =__i915_add_request (ring,NULL , so.obj,NULL );/* __i915_add_request moves object to inactive if it fails */ out: -render_state_fini (&so); +i915_gem_render_state_fini (&so);return ret; }drivers/gpu/drm/i915/i915_gem_render_state.h new file +47
-0@@ -0,0 +1,47 @@ +/* +* Copyright © 2014 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +#ifndef _I915_GEM_RENDER_STATE_H_ +#define _I915_GEM_RENDER_STATE_H_ + +#include <linux/types.h> + +struct intel_renderstate_rodata { +const u32 *reloc; +const u32 *batch; +const u32 batch_items; +}; + +struct render_state { +const struct intel_renderstate_rodata *rodata; +struct drm_i915_gem_object *obj; +u64 ggtt_offset; +int gen; +}; + +int i915_gem_render_state_init (struct intel_engine_cs *ring); +void i915_gem_render_state_fini (struct render_state *so); +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so); + +#endif /* _I915_GEM_RENDER_STATE_H_ */ drivers/gpu/drm/i915/intel_lrc.c +46
-0@@ -925,6 +925,37 @@ cleanup_render_ring:return ret; } +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx) +{ +struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; +struct render_state so; +struct drm_i915_file_private *file_priv = ctx->file_priv; +struct drm_file *file = file_priv? file_priv->file :NULL ; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so); +if (ret) +return ret; + +if (so.rodata ==NULL ) +return 0 ; + + ret = ring->emit_bb_start (ringbuf, + so.ggtt_offset, +I915_DISPATCH_SECURE ); +if (ret) + goto out; + +i915_vma_move_to_active (i915_gem_obj_to_ggtt (so.obj), ring); + + ret =__i915_add_request (ring, file, so.obj,NULL ); +/* intel_logical_ring_add_request moves object to inactive if it fails */ +out: +i915_gem_render_state_fini (&so); +return ret; +} +static int populate_lr_context (struct intel_context *ctx,struct drm_i915_gem_object *ctx_obj,struct intel_engine_cs *ring,struct intel_ringbuffer *ringbuf)@@ -1142,6 +1173,21 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; +/* The default context will have to wait, because we are not yet +* ready to send a batchbuffer at this point */ +if (ring->id ==RCS && !ctx->rcs_initialized && + ctx != ring->default_context) { + ret =intel_lr_context_render_state_init (ring, ctx); +if (ret) { +DRM_ERROR ("Init render state failed: %d\n" , ret); + ctx->engine[ring->id].ringbuf =NULL ; + ctx->engine[ring->id].state =NULL ; +intel_destroy_ringbuffer_obj (ringbuf); + goto error; + } + ctx->rcs_initialized = true; + } +return 0 ; error:drivers/gpu/drm/i915/intel_lrc.h +2
-0@@ -43,6 +43,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf, u32int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords);/* Logical Ring Contexts */ +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx);void intel_lr_context_free (struct intel_context *ctx);int intel_lr_context_deferred_create (struct intel_context *ctx,struct intel_engine_cs *ring);drivers/gpu/drm/i915/intel_renderstate.h +1
-7@@ -24,13 +24,7 @@#ifndef _INTEL_RENDERSTATE_H#define _INTEL_RENDERSTATE_H -#include <linux/types.h> - -struct intel_renderstate_rodata { -const u32 *reloc; -const u32 *batch; -const u32 batch_items; -}; +#include "i915_drv.h" extern const struct intel_renderstate_rodata gen6_null_state;extern const struct intel_renderstate_rodata gen7_null_state;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 105 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 10 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
The batchbuffer that sets the render context state is submitted in a different way, and from different places.
We needed to make both the render state preparation and free functions outside accesible, and namespace accordingly. This mess is so that all LR, LRC and Execlists functionality can go together in
intel_lrc.c: we can fix all of this later on, once the interfaces are clear.Quoted 8 lines
v2: Create a separate
ctx->rcs_initializedfor the Execlists case, as suggested by Chris Wilson.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_drv.h | 4 +-- drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++- drivers/gpu/drm/i915/i915_gem_render_state.c | 40 ++++++++++++++--------
Quoted 1 line
drivers/gpu/drm/i915/i915_gem_render_state.h | 47++++++++++++++++++++++++++
Quoted 1 line
drivers/gpu/drm/i915/intel_lrc.c | 46+++++++++++++++++++++++++
Quoted 26 lines
drivers/gpu/drm/i915/intel_lrc.h | 2 ++ drivers/gpu/drm/i915/intel_renderstate.h | 8 +---- 7 files changed, 139 insertions(+), 25 deletions(-) create mode100644
drivers/gpu/drm/i915/i915_gem_render_state.h(quoted diff) +0
-0
b/drivers/gpu/drm/i915/i915_drv.hindex 4303e2c..b7cf0ec 100644drivers/gpu/drm/i915/i915_drv.h +2
-0@@ -37,6 +37,7 @@#include "intel_ringbuffer.h" #include "intel_lrc.h" #include "i915_gem_gtt.h" +#include "i915_gem_render_state.h" #include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -623,6 +624,7 @@ struct intel_context { } legacy_hw_ctx;/* Execlists */ +bool rcs_initialized;struct {struct drm_i915_gem_object *state;struct intel_ringbuffer *ringbuf;@@ -2553,8 +2555,6 @@ int i915_gem_context_create_ioctl(structQuoted 1 line
drm_device*dev, void *data, int i915_gem_context_destroy_ioctl(struct
drm_device*dev, void *data,drivers/gpu/drm/i915/i915_drv.h int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
Quoted 7 lines
drivers/gpu/drm/i915/i915_drv.h +0
-2struct drm_file *file); -/* i915_gem_render_state.c */ -int i915_gem_render_state_init (struct intel_engine_cs *ring);/* i915_gem_evict.c */ int __must_check i915_gem_evict_something (struct drm_device *dev, struct i915_address_space *vm, diff--git
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 6 lines
a/drivers/gpu/drm/i915/i915_gem_context.cb/drivers/gpu/drm/i915/i915_gem_context.c
index 9085ff1..0dc6992 100644drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 4 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-1ppgtt->enable (ppgtt); } -if (i915.enable_execlists)drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +10
-0+if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret =intel_lr_context_render_state_init (ring, dctx); +if (ret) { + DRM_ERROR("Init render state failed: %d\n",ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for the first time. The later is what the legacy contexts currently do in
do_switch.
Quoted 1 line
But
ctx_enableshould do the switch to the default context and that's about
Well, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an enable_execlists branch in i915_switch_context() but that doen't seem like the right place.
How about in i915_gem_init() after calling i915_gem_init_hw()?
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
Thomas.
Quoted 273 lines
-Daniel
drivers/gpu/drm/i915/i915_gem_render_state.c int i915_gem_render_state_init(struct
Quoted 76 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0/* FIXME: We should make this work, even in reset */ if (i915_reset_in_progress (&dev_priv->gpu_error))drivers/gpu/drm/i915/i915_gem_render_state.c +0
-7@@ -28,13 +28,6 @@#include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { -const struct intel_renderstate_rodata *rodata; -struct drm_i915_gem_object *obj; -u64 ggtt_offset; -int gen; -}; - static const struct intel_renderstate_rodata *
render_state_get_rodata(struct drm_device *dev, const int gen){ @@ -127,30 +120,47 @@ static intrender_state_setup(struct render_state *so)drivers/gpu/drm/i915/i915_gem_render_state.c +23
-7return 0 ; } -static void render_state_fini (struct render_state *so) +void i915_gem_render_state_fini (struct render_state *so) {i915_gem_object_ggtt_unpin (so->obj);drm_gem_object_unreference (&so->obj->base); } -int i915_gem_render_state_init (struct intel_engine_cs *ring) +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so) { -struct render_state so;int ret;if (WARN_ON (ring->id !=RCS ))return -ENOENT ; - ret =render_state_init (&so, ring->dev); + ret =render_state_init (so, ring->dev);if (ret)return ret; -if (so.rodata ==NULL ) +if (so->rodata ==NULL )return 0 ; - ret =render_state_setup (&so); + ret =render_state_setup (so); +if (ret) { +i915_gem_render_state_fini (so); +return ret; + } + +return 0 ; +} + +int i915_gem_render_state_init (struct intel_engine_cs *ring) { +struct render_state so; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so);if (ret) - goto out; +return ret; + +if (so.rodata ==NULL ) +return 0 ; ret = ring->dispatch_execbuffer(ring, so.ggtt_offset,@@ -164,6 +174,6 @@ int i915_gem_render_state_init(struct
intel_engine_cs*ring)Quoted 26 lines
drivers/gpu/drm/i915/i915_gem_render_state.c +1
-1ret =__i915_add_request (ring,NULL , so.obj,NULL );/* __i915_add_request moves object to inactive if it fails */ out: -render_state_fini (&so); +i915_gem_render_state_fini (&so);return ret; }drivers/gpu/drm/i915/i915_gem_render_state.h new file +12
-0@@ -0,0 +1,47 @@ +/* +* Copyright (c) 2014 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person +obtaining a +* copy of this software and associated documentation files (the +"Software"), +* to deal in the Software without restriction, including without +limitation +* the rights to use, copy, modify, merge, publish, distribute, +sublicense, +* and/or sell copies of the Software, and to permit persons to whom drivers/gpu/drm/i915/i915_gem_render_state.h line 22
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +10
-0+the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including +the next + * paragraph) shall be included in all copies or substantial portions +of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANYKIND,
drivers/gpu/drm/i915/i915_gem_render_state.h line 26
Quoted 4 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +4
-0+EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY , + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. INNO EVENT
drivers/gpu/drm/i915/i915_gem_render_state.h line 28
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +2
-0+SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES
drivers/gpu/drm/i915/i915_gem_render_state.h line 30
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +2
-0+OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OROTHERWISE,
drivers/gpu/drm/i915/i915_gem_render_state.h line 32
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +2
-0+ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USEOR
Quoted 60 lines
drivers/gpu/drm/i915/i915_gem_render_state.h new file +28
-0+OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +#ifndef _I915_GEM_RENDER_STATE_H_ +#define _I915_GEM_RENDER_STATE_H_ + +#include <linux/types.h> + +struct intel_renderstate_rodata { +const u32 *reloc; +const u32 *batch; +const u32 batch_items; +}; + +struct render_state { +const struct intel_renderstate_rodata *rodata; +struct drm_i915_gem_object *obj; +u64 ggtt_offset; +int gen; +}; + +int i915_gem_render_state_init (struct intel_engine_cs *ring);void +i915_gem_render_state_fini (struct render_state *so);int +i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so); + +#endif /* _I915_GEM_RENDER_STATE_H_ */ drivers/gpu/drm/i915/intel_lrc.c +23
-0@@ -925,6 +925,37 @@ cleanup_render_ring:return ret; } +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx) { +struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; +struct render_state so; +struct drm_i915_file_private *file_priv = ctx->file_priv; +struct drm_file *file = file_priv? file_priv->file :NULL ; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so); +if (ret) +return ret; + +if (so.rodata ==NULL ) +return 0 ; + + ret = ring->emit_bb_start (ringbuf, + so.ggtt_offset, +I915_DISPATCH_SECURE ); +if (ret) + goto out; + +i915_vma_move_to_active (i915_gem_obj_to_ggtt (so.obj), ring); +drivers/gpu/drm/i915/intel_lrc.c cleanup_render_ring: · line 960
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +8
-0+ ret =__i915_add_request (ring, file, so.obj,NULL ); +/* intel_logical_ring_add_request moves object to inactive if it +fails */ +out: +i915_gem_render_state_fini (&so); +return ret; +} + static int populate_lr_context(struct intel_context *ctx, struct
drm_i915_gem_object*ctx_obj,drivers/gpu/drm/i915/intel_lrc.c cleanup_render_ring: · line 961
Quoted 1 line
drivers/gpu/drm/i915/intel_lrc.c +0
-0struct intel_engine_cs *ring, struct intel_ringbuffer*ringbuf)
drivers/gpu/drm/i915/intel_lrc.c int intel_lr_context_deferred_create(struct
Quoted 1 line
drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -1142,6 +1173,21 @@ int intel_lr_context_deferred_create(struct
intel_context*ctx,Quoted 59 lines
drivers/gpu/drm/i915/intel_lrc.c +15
-0ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; +/* The default context will have to wait, because we are not yet +* ready to send a batchbuffer at this point */ +if (ring->id ==RCS && !ctx->rcs_initialized && + ctx != ring->default_context) { + ret =intel_lr_context_render_state_init (ring, ctx); +if (ret) { +DRM_ERROR ("Init render state failed: %d\n" , ret); + ctx->engine[ring->id].ringbuf =NULL ; + ctx->engine[ring->id].state =NULL ; +intel_destroy_ringbuffer_obj (ringbuf); + goto error; + } + ctx->rcs_initialized = true; + } +return 0 ; error:drivers/gpu/drm/i915/intel_lrc.h +0
-0@@ -43,6 +43,8 @@ static inline void intel_logical_ring_emit(struct
intel_ringbuffer*ringbuf, u32 intintel_logical_ring_begin(struct intel_ringbuffer *ringbuf, int num_dwords);/* Logical Ring Contexts */
drivers/gpu/drm/i915/intel_lrc.h +2
-0+int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx);void intel_lr_context_free (struct intel_context *ctx);int intel_lr_context_deferred_create(struct
intel_context*ctx,
structintel_engine_cs*ring); diff --gita/drivers/gpu/drm/i915/intel_renderstate.hb/drivers/gpu/drm/i915/intel_renderstate.h
index fd4f662..6c792d3 100644drivers/gpu/drm/i915/intel_renderstate.h +1
-8@@ -24,13 +24,7 @@#ifndef _INTEL_RENDERSTATE_H#define _INTEL_RENDERSTATE_H -#include <linux/types.h> - -struct intel_renderstate_rodata { -const u32 *reloc; -const u32 *batch; -const u32 batch_items; -}; +#include "i915_drv.h" extern const struct intel_renderstate_rodata gen6_null_state;extern const struct intel_renderstate_rodata gen7_null_state; --1.7.9.5
Quoted 4 lines
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 51 lines · Thomas
Quoted 43 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 1 line · Thomas Daniel
From: Oscar Mateo <[email protected]>
index 9085ff1..0dc6992 100644
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 4 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-1ppgtt->enable (ppgtt); } -if (i915.enable_execlists)drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +10
-0+if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret =intel_lr_context_render_state_init (ring, dctx); +if (ret) { + DRM_ERROR("Init render state failed: %d\n",ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for the first time. The later is what the legacy contexts currently do in
do_switch.Quoted 1 line
But
ctx_enableshould do the switch to the default context and that's aboutWell, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an
enable_execlistsbranch ini915_switch_context()but that doen't seem like the right place.How about in
i915_gem_init()after callingi915_gem_init_hw()?
Quoted 7 lines
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
That sounds like the default context is created too early. Essentially I want to avoid needless divergence between the default context and normal contexts, because sooner or later that will means someone will creep in with a _really_ subtle bug.
What about:
- We create the default lrc contexs in context_init, but like with a normal context we don't do any of the deferred setup.
- In context_enable (which since yesterday properly propagates errors to callers) we force the deferred lrc ctx setup for the default contexts on all engines.
- The render state init is done as part of the deferred ctx setup for the render engine in all cases.
Totally off the track or do you see a workable solution somewhere in that direction?
Cheers, Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 74 lines · Daniel Vetter
Quoted 51 lines · Thomas
Quoted 43 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 1 line · Thomas Daniel
From: Oscar Mateo <[email protected]>
index 9085ff1..0dc6992 100644
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 4 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-1ppgtt->enable (ppgtt); } -if (i915.enable_execlists)drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 10 lines
drivers/gpu/drm/i915/i915_gem_context.c +10
-0+if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret =intel_lr_context_render_state_init (ring, dctx); +if (ret) { + DRM_ERROR("Init render state failed: %d\n",ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for the first time. The later is what the legacy contexts currently do in
do_switch.Quoted 1 line
But
ctx_enableshould do the switch to the default context and that's aboutWell, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an
enable_execlistsbranch ini915_switch_context()but that doen't seem like the right place.How about in
i915_gem_init()after callingi915_gem_init_hw()?Quoted 7 lines
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
That sounds like the default context is created too early. Essentially I want to avoid needless divergence between the default context and normal contexts, because sooner or later that will means someone will creep in with a _really_ subtle bug.
What about:
- We create the default lrc contexs incontext_init, but like with a normal context we don't do any of the deferred setup.
- Incontext_enable(which since yesterday properly propagates errors to callers) we force the deferred lrc ctx setup for the default contexts on all engines.
- The render state init is done as part of the deferred ctx setup for the render engine in all cases.
Quoted 2 lines
Totally off the track or do you see a workable solution somewhere in that direction?
I'd like to discuss this first a bit more, so will punt on this patch for now.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 90 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 9:00 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 20 lines · Daniel Vetter
Quoted 19 lines · Thomas
Quoted 19 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 1 line · Thomas Daniel
From: Oscar Mateo <[email protected]>
index 9085ff1..0dc6992 100644
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0ppgtt->enable (ppgtt); }Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +8
-1-if (i915.enable_execlists) +if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret = intel_lr_context_render_state_init(ring,dctx);
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct · line 525
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (ret) { + DRM_ERROR("Init render state failed:%d\n",
Quoted 11 lines
Quoted 11 lines
Quoted 11 lines
ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for
the first time.
Quoted 33 lines
Quoted 11 lines
Quoted 4 lines
The later is what the legacy contexts currently do in
do_switch.But
ctx_enableshould do the switch to the default context and that's aboutWell, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an
enable_execlistsbranch ini915_switch_context()but that doen't seem like the right place.How about in
i915_gem_init()after callingi915_gem_init_hw()?Quoted 7 lines
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
That sounds like the default context is created too early. Essentially I want to avoid needless divergence between the default context and normal contexts, because sooner or later that will means someone will creep in with a _really_ subtle bug.
What about:
- We create the default lrc contexs incontext_init, but like with a normal context we don't do any of the deferred setup.
- Incontext_enable(which since yesterday properly propagates errors to callers) we force the deferred lrc ctx setup for the default contexts on all engines.
- The render state init is done as part of the deferred ctx setup for the render engine in all cases.
Quoted 5 lines
Quoted 2 lines
Totally off the track or do you see a workable solution somewhere in that direction?
I'd like to discuss this first a bit more, so will punt on this patch for now. -Daniel
I think that your proposal will work. I've been having some trouble with my RVP board so haven't had a chance to test it out yet.
Thomas.
Quoted 4 lines
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
In reply to Daniel VetterQuoted 104 lines
-----Original Message-----
From: Daniel, Thomas
Sent: Friday, August 15, 2014 9:44 AM
To: 'Daniel Vetter'
Cc: [email protected]
Subject: RE: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 92 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 9:00 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 20 lines · Daniel Vetter
Quoted 19 lines · Thomas
Quoted 19 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 1 line · Thomas Daniel
From: Oscar Mateo <[email protected]>
index 9085ff1..0dc6992 100644
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0ppgtt->enable (ppgtt); }Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +8
-1-if (i915.enable_execlists) +if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret = intel_lr_context_render_state_init(ring,dctx);
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct · line 525
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (ret) { + DRM_ERROR("Init render state failed:%d\n",
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for
the first time.
Quoted 35 lines
Quoted 11 lines
Quoted 4 lines
The later is what the legacy contexts currently do in
do_switch.But
ctx_enableshould do the switch to the default context and that's aboutWell, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an
enable_execlistsbranch ini915_switch_context()but that doen't seem like the right place.How about in
i915_gem_init()after callingi915_gem_init_hw()?Quoted 7 lines
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
That sounds like the default context is created too early. Essentially I want to avoid needless divergence between the default context and normal contexts, because sooner or later that will means someone will creep in with a _really_ subtle bug.
What about:
- We create the default lrc contexs incontext_init, but like with a normal context we don't do any of the deferred setup.
- Incontext_enable(which since yesterday properly propagates errors to callers) we force the deferred lrc ctx setup for the default contexts on all engines.
- The render state init is done as part of the deferred ctx setup for the render engine in all cases.Totally off the track or do you see a workable solution somewhere in that direction?
Quoted 6 lines
Quoted 2 lines
I'd like to discuss this first a bit more, so will punt on this patch for now. -Daniel
I think that your proposal will work. I've been having some trouble with my RVP board so haven't had a chance to test it out yet.
Thomas.
I've now tried this out and I don't think it can work without introducing more problems than the original patch. Trouble is that in lrc mode the Hardware Status Page is offset 0 from the context. All contexts use the default context's HWSP for writing seqnos, this is stored in ring->status_page. We can't populate this until the deferred creation of the default context is done, so we can't execute any instructions in the deferred creation (unless we check for default context in the deferred creation which is what we wanted to avoid in the first place).
Thomas.
Quoted 4 lines
Quoted 4 lines
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 27/43] drm/i915/bdw: Render state init for Execlists
Quoted 110 lines · Thomas
Quoted 104 lines
-----Original Message-----
From: Daniel, Thomas
Sent: Friday, August 15, 2014 9:44 AM
To: 'Daniel Vetter'
Cc: [email protected]
Subject: RE: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 92 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 9:00 PM
To: Daniel, Thomas
Cc: Daniel Vetter; [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 20 lines · Daniel Vetter
Quoted 19 lines · Thomas
Quoted 19 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Monday, August 11, 2014 10:25 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 27/43] drm/i915/bdw: Render state init for ExeclistsQuoted 1 line · Thomas Daniel
From: Oscar Mateo <[email protected]>
index 9085ff1..0dc6992 100644
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct
Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0@@ -513,8 +513,23 @@ int i915_gem_context_enable(struct
drm_i915_private*dev_priv)Quoted 3 lines
drivers/gpu/drm/i915/i915_gem_context.c +0
-0ppgtt->enable (ppgtt); }Quoted 9 lines
Quoted 9 lines
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv)
Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +8
-1-if (i915.enable_execlists) +if (i915.enable_execlists) { +struct intel_context *dctx; + + ring = &dev_priv->ring[RCS ]; + dctx = ring->default_context; + +if (!dctx->rcs_initialized) { + ret = intel_lr_context_render_state_init(ring,dctx);
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct · line 525
Quoted 2 lines
drivers/gpu/drm/i915/i915_gem_context.c +2
-0+if (ret) { + DRM_ERROR("Init render state failed:%d\n",
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
ret);
drivers/gpu/drm/i915/i915_gem_context.c int i915_gem_context_enable(struct drm_i915_private *dev_priv) · line 532
Quoted 7 lines
drivers/gpu/drm/i915/i915_gem_context.c +6
-0+return ret; + } + dctx->rcs_initialized = true; + } +return 0 ; + }This looks very much like the wrong place. We should init the render state when we create the context, or when we switch to it for
the first time.
Quoted 35 lines
Quoted 11 lines
Quoted 4 lines
The later is what the legacy contexts currently do in
do_switch.But
ctx_enableshould do the switch to the default context and that's aboutWell, a side-effect of switching to the default context in legacy mode is that the render state gets initialized. I could move the lr render state init call into an
enable_execlistsbranch ini915_switch_context()but that doen't seem like the right place.How about in
i915_gem_init()after callingi915_gem_init_hw()?Quoted 7 lines
Quoted 5 lines
it. If there's some depency then I guess we should stall the creation of the default context a bit, maybe.
In any case someone needs to explain this better and if there's not other wey this at least needs a bit comment. So I'll punt for now.
When the default context is created the driver is not ready to execute a batch. That is why the render state init can't be done then.
That sounds like the default context is created too early. Essentially I want to avoid needless divergence between the default context and normal contexts, because sooner or later that will means someone will creep in with a _really_ subtle bug.
What about:
- We create the default lrc contexs incontext_init, but like with a normal context we don't do any of the deferred setup.
- Incontext_enable(which since yesterday properly propagates errors to callers) we force the deferred lrc ctx setup for the default contexts on all engines.
- The render state init is done as part of the deferred ctx setup for the render engine in all cases.Totally off the track or do you see a workable solution somewhere in that direction?
Quoted 6 lines
Quoted 2 lines
I'd like to discuss this first a bit more, so will punt on this patch for now. -Daniel
I think that your proposal will work. I've been having some trouble with my RVP board so haven't had a chance to test it out yet.
Thomas.
Quoted 8 lines
I've now tried this out and I don't think it can work without introducing more problems than the original patch. Trouble is that in lrc mode the Hardware Status Page is offset 0 from the context. All contexts use the default context's HWSP for writing seqnos, this is stored in
ring->status_page. We can't populate this until the deferred creation of the default context is done, so we can't execute any instructions in the deferred creation (unless we check for default context in the deferred creation which is what we wanted to avoid in the first place).
That just sounds like we should either allocate the HWS at engine init time (since it's shared across all rings). Or that we should switch to per-ring/ctx hws, but that's probably only something for when the scheduler shows up.
Or is there some other blocker?
Generally I really don't like to bend over backwards in the init code if we get such initialization ordering constraints wrong - in the past that really has been a fairly awesome source of bugs. What's needed though is a pile of WARN_ON to check that the initialization ordering is done in the right way, in case someone touches the code. That still means runtime testing, but that's still a lot better than silent failures. -Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 1/1 drm/i915/bdw: Render state init for Execlists
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
The batchbuffer that sets the render context state is submitted in a different way, and from different places.
We needed to make both the render state preparation and free functions outside accesible, and namespace accordingly. This mess is so that all LR, LRC and Execlists functionality can go together in intel_lrc.c: we can fix all of this later on, once the interfaces are clear.
v2: Create a separate ctx->rcs_initialized for the Execlists case, as suggested by Chris Wilson.
v3: Setup ring status page in lr_context_deferred_create when the default context is being created. This means that the render state init for the default context is no longer a special case. Execute deferred creation of the default context at the end of logical_ring_init to allow the render state commands to be submitted. Fix style errors reported by checkpatch. Rebased.
--- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 40 ++++++++------ drivers/gpu/drm/i915/i915_gem_render_state.h | 47 +++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 73 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_lrc.h | 2 + drivers/gpu/drm/i915/intel_renderstate.h | 8 +-- 6 files changed, 135 insertions(+), 39 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.h
drivers/gpu/drm/i915/i915_drv.h +2 -2
@@ -37,6 +37,7 @@#include "intel_ringbuffer.h" #include "intel_lrc.h" #include "i915_gem_gtt.h" +#include "i915_gem_render_state.h" #include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h>
@@ -635,6 +636,7 @@ struct intel_context { } legacy_hw_ctx;/* Execlists */ +bool rcs_initialized;struct {struct drm_i915_gem_object *state;struct intel_ringbuffer *ringbuf;
@@ -2596,8 +2598,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,int i915_gem_context_destroy_ioctl (struct drm_device *dev,void *data,struct drm_file *file); -/* i915_gem_render_state.c */ -int i915_gem_render_state_init (struct intel_engine_cs *ring);/* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,
drivers/gpu/drm/i915/i915_gem_render_state.c +25 -15
@@ -28,13 +28,6 @@#include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { -const struct intel_renderstate_rodata *rodata; -struct drm_i915_gem_object *obj; -u64 ggtt_offset; -int gen; -}; -static const struct intel_renderstate_rodata *render_state_get_rodata (struct drm_device *dev,const int gen) {
@@ -127,30 +120,47 @@ static int render_state_setup(struct render_state *so)return 0 ; } -static void render_state_fini (struct render_state *so) +void i915_gem_render_state_fini (struct render_state *so) {i915_gem_object_ggtt_unpin (so->obj);drm_gem_object_unreference (&so->obj->base); } -int i915_gem_render_state_init (struct intel_engine_cs *ring) +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so) { -struct render_state so;int ret;if (WARN_ON (ring->id !=RCS ))return -ENOENT ; - ret =render_state_init (&so, ring->dev); + ret =render_state_init (so, ring->dev);if (ret)return ret; -if (so.rodata ==NULL ) +if (so->rodata ==NULL )return 0 ; - ret =render_state_setup (&so); + ret =render_state_setup (so); +if (ret) { +i915_gem_render_state_fini (so); +return ret; + } + +return 0 ; +} + +int i915_gem_render_state_init (struct intel_engine_cs *ring) +{ +struct render_state so; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so);if (ret) - goto out; +return ret; + +if (so.rodata ==NULL ) +return 0 ; ret = ring->dispatch_execbuffer(ring, so.ggtt_offset,
@@ -164,6 +174,6 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring) ret =__i915_add_request (ring,NULL , so.obj,NULL );/* __i915_add_request moves object to inactive if it fails */ out: -render_state_fini (&so); +i915_gem_render_state_fini (&so);return ret; }
drivers/gpu/drm/i915/i915_gem_render_state.h new file +47 -0
47 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.c +58 -15
103 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.h +2 -0
@@ -62,6 +62,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf,int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords);/* Logical Ring Contexts */ +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx);void intel_lr_context_free (struct intel_context *ctx);int intel_lr_context_deferred_create (struct intel_context *ctx,struct intel_engine_cs *ring);
drivers/gpu/drm/i915/intel_renderstate.h +1 -7
@@ -24,13 +24,7 @@#ifndef _INTEL_RENDERSTATE_H#define _INTEL_RENDERSTATE_H -#include <linux/types.h> - -struct intel_renderstate_rodata { -const u32 *reloc; -const u32 *batch; -const u32 batch_items; -}; +#include "i915_drv.h" extern const struct intel_renderstate_rodata gen6_null_state;extern const struct intel_renderstate_rodata gen7_null_state;
Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Daniel Vetter
AppliedRe: [PATCH] drm/i915/bdw: Render state init for Execlists
Quoted 15 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
The batchbuffer that sets the render context state is submitted in a different way, and from different places.
We needed to make both the render state preparation and free functions outside accesible, and namespace accordingly. This mess is so that all LR, LRC and Execlists functionality can go together in
intel_lrc.c: we can fix all of this later on, once the interfaces are clear.v2: Create a separate
ctx->rcs_initializedfor the Execlists case, as suggested by Chris Wilson.Signed-off-by Oscar Mateo <[email protected]>
Quoted 8 lines
v3: Setup ring status page in
lr_context_deferred_createwhen the default context is being created. This means that the render state init for the default context is no longer a special case. Execute deferred creation of the default context at the end oflogical_ring_initto allow the render state commands to be submitted. Fix style errors reported by checkpatch. Rebased.Signed-off-by Thomas Daniel <[email protected]>
Queued for -next, thanks for the patch.
-Daniel
Quoted 324 lines
--- drivers/gpu/drm/i915/i915_drv.h | 4 +- drivers/gpu/drm/i915/i915_gem_render_state.c | 40 ++++++++------ drivers/gpu/drm/i915/i915_gem_render_state.h | 47 +++++++++++++++++ drivers/gpu/drm/i915/intel_lrc.c | 73 ++++++++++++++++++++------ drivers/gpu/drm/i915/intel_lrc.h | 2 + drivers/gpu/drm/i915/intel_renderstate.h | 8 +-- 6 files changed, 135 insertions(+), 39 deletions(-) create mode 100644 drivers/gpu/drm/i915/i915_gem_render_state.hdrivers/gpu/drm/i915/i915_drv.h +2
-2@@ -37,6 +37,7 @@#include "intel_ringbuffer.h" #include "intel_lrc.h" #include "i915_gem_gtt.h" +#include "i915_gem_render_state.h" #include <linux/io-mapping.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> @@ -635,6 +636,7 @@ struct intel_context { } legacy_hw_ctx;/* Execlists */ +bool rcs_initialized;struct {struct drm_i915_gem_object *state;struct intel_ringbuffer *ringbuf;@@ -2596,8 +2598,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,int i915_gem_context_destroy_ioctl (struct drm_device *dev,void *data,struct drm_file *file); -/* i915_gem_render_state.c */ -int i915_gem_render_state_init (struct intel_engine_cs *ring);/* i915_gem_evict.c */ int __must_check i915_gem_evict_something(struct drm_device *dev, struct i915_address_space *vm,drivers/gpu/drm/i915/i915_gem_render_state.c +25
-15@@ -28,13 +28,6 @@#include "i915_drv.h" #include "intel_renderstate.h" -struct render_state { -const struct intel_renderstate_rodata *rodata; -struct drm_i915_gem_object *obj; -u64 ggtt_offset; -int gen; -}; -static const struct intel_renderstate_rodata *render_state_get_rodata (struct drm_device *dev,const int gen) {@@ -127,30 +120,47 @@ static int render_state_setup(struct render_state *so)return 0 ; } -static void render_state_fini (struct render_state *so) +void i915_gem_render_state_fini (struct render_state *so) {i915_gem_object_ggtt_unpin (so->obj);drm_gem_object_unreference (&so->obj->base); } -int i915_gem_render_state_init (struct intel_engine_cs *ring) +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so) { -struct render_state so;int ret;if (WARN_ON (ring->id !=RCS ))return -ENOENT ; - ret =render_state_init (&so, ring->dev); + ret =render_state_init (so, ring->dev);if (ret)return ret; -if (so.rodata ==NULL ) +if (so->rodata ==NULL )return 0 ; - ret =render_state_setup (&so); + ret =render_state_setup (so); +if (ret) { +i915_gem_render_state_fini (so); +return ret; + } + +return 0 ; +} + +int i915_gem_render_state_init (struct intel_engine_cs *ring) +{ +struct render_state so; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so);if (ret) - goto out; +return ret; + +if (so.rodata ==NULL ) +return 0 ; ret = ring->dispatch_execbuffer(ring, so.ggtt_offset,@@ -164,6 +174,6 @@ int i915_gem_render_state_init(struct intel_engine_cs *ring) ret =__i915_add_request (ring,NULL , so.obj,NULL );/* __i915_add_request moves object to inactive if it fails */ out: -render_state_fini (&so); +i915_gem_render_state_fini (&so);return ret; }drivers/gpu/drm/i915/i915_gem_render_state.h new file +47
-0@@ -0,0 +1,47 @@ +/* +* Copyright © 2014 Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice (including the next +* paragraph) shall be included in all copies or substantial portions of the +* Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +* DEALINGS IN THE SOFTWARE. +*/ + +#ifndef _I915_GEM_RENDER_STATE_H_ +#define _I915_GEM_RENDER_STATE_H_ + +#include <linux/types.h> + +struct intel_renderstate_rodata { +const u32 *reloc; +const u32 *batch; +const u32 batch_items; +}; + +struct render_state { +const struct intel_renderstate_rodata *rodata; +struct drm_i915_gem_object *obj; +u64 ggtt_offset; +int gen; +}; + +int i915_gem_render_state_init (struct intel_engine_cs *ring); +void i915_gem_render_state_fini (struct render_state *so); +int i915_gem_render_state_prepare (struct intel_engine_cs *ring, +struct render_state *so); + +#endif /* _I915_GEM_RENDER_STATE_H_ */ drivers/gpu/drm/i915/intel_lrc.c +58
-15@@ -1217,8 +1217,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *ring)static int logical_ring_init (struct drm_device *dev,struct intel_engine_cs *ring) {int ret; -struct intel_context *dctx = ring->default_context; -struct drm_i915_gem_object *dctx_obj;/* Intentionally left blank. */ ring->buffer =NULL ;@@ -1232,18 +1230,6 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinspin_lock_init (&ring->execlist_lock); ring->next_context_status_buffer =0 ; - ret =intel_lr_context_deferred_create (dctx, ring); -if (ret) -return ret; - -/* The status page is offset 0 from the context object in LRCs. */ - dctx_obj = dctx->engine[ring->id].state; - ring->status_page.gfx_addr =i915_gem_obj_ggtt_offset (dctx_obj); - ring->status_page.page_addr =kmap (sg_page (dctx_obj->pages->sgl)); -if (ring->status_page.page_addr ==NULL ) -return -ENOMEM ; - ring->status_page.obj = dctx_obj; - ret =i915_cmd_parser_init_ring (ring);if (ret)return ret;@@ -1254,7 +1240,9 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinreturn ret; } -return 0 ; + ret =intel_lr_context_deferred_create (ring->default_context, ring); + +return ret; }static int logical_render_ring_init (struct drm_device *dev)@@ -1448,6 +1436,38 @@ cleanup_render_ring:return ret; } +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx) +{ +struct intel_ringbuffer *ringbuf = ctx->engine[ring->id].ringbuf; +struct render_state so; +struct drm_i915_file_private *file_priv = ctx->file_priv; +struct drm_file *file = file_priv ? file_priv->file :NULL ; +int ret; + + ret =i915_gem_render_state_prepare (ring, &so); +if (ret) +return ret; + +if (so.rodata ==NULL ) +return 0 ; + + ret = ring->emit_bb_start (ringbuf, + so.ggtt_offset, +I915_DISPATCH_SECURE ); +if (ret) + goto out; + +i915_vma_move_to_active (i915_gem_obj_to_ggtt (so.obj), ring); + + ret =__i915_add_request (ring, file, so.obj,NULL ); +/* intel_logical_ring_add_request moves object to inactive if it +* fails */ +out: +i915_gem_render_state_fini (&so); +return ret; +} +static int populate_lr_context (struct intel_context *ctx,struct drm_i915_gem_object *ctx_obj,struct intel_engine_cs *ring,struct intel_ringbuffer *ringbuf)@@ -1687,6 +1707,29 @@ int intel_lr_context_deferred_create(struct intel_context *ctx, ctx->engine[ring->id].ringbuf = ringbuf; ctx->engine[ring->id].state = ctx_obj; +if (ctx == ring->default_context) { +/* The status page is offset 0 from the default context object +* in LRC mode. */ + ring->status_page.gfx_addr =i915_gem_obj_ggtt_offset (ctx_obj); + ring->status_page.page_addr = +kmap (sg_page (ctx_obj->pages->sgl)); +if (ring->status_page.page_addr ==NULL ) +return -ENOMEM ; + ring->status_page.obj = ctx_obj; + } + +if (ring->id ==RCS && !ctx->rcs_initialized) { + ret =intel_lr_context_render_state_init (ring, ctx); +if (ret) { +DRM_ERROR ("Init render state failed: %d\n" , ret); + ctx->engine[ring->id].ringbuf =NULL ; + ctx->engine[ring->id].state =NULL ; +intel_destroy_ringbuffer_obj (ringbuf); + goto error; + } + ctx->rcs_initialized = true; + } +return 0 ; error:drivers/gpu/drm/i915/intel_lrc.h +2
-0@@ -62,6 +62,8 @@ static inline void intel_logical_ring_emit(struct intel_ringbuffer *ringbuf,int intel_logical_ring_begin (struct intel_ringbuffer *ringbuf,int num_dwords);/* Logical Ring Contexts */ +int intel_lr_context_render_state_init (struct intel_engine_cs *ring, +struct intel_context *ctx);void intel_lr_context_free (struct intel_context *ctx);int intel_lr_context_deferred_create (struct intel_context *ctx,struct intel_engine_cs *ring);drivers/gpu/drm/i915/intel_renderstate.h +1
-7@@ -24,13 +24,7 @@#ifndef _INTEL_RENDERSTATE_H#define _INTEL_RENDERSTATE_H -#include <linux/types.h> - -struct intel_renderstate_rodata { -const u32 *reloc; -const u32 *batch; -const u32 batch_items; -}; +#include "i915_drv.h" extern const struct intel_renderstate_rodata gen6_null_state;extern const struct intel_renderstate_rodata gen7_null_state;Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 28/43 drm/i915/bdw: Implement context switching (somewhat)
In reply to Thomas DanielFrom: Ben Widawsky <[email protected]>
A context switch occurs by submitting a context descriptor to the ExecList Submission Port. Given that we can now initialize a context, it's possible to begin implementing the context switch by creating the descriptor and submitting it to ELSP (actually two, since the ELSP has two ports).
The context object must be mapped in the GGTT, which means it must exist in the 0-4GB graphics VA range.
v2: This code has changed quite a lot in various rebases. Of particular importance is that now we use the globally unique Submission ID to send to the hardware. Also, context pages are now pinned unconditionally to GGTT, so there is no need to bind them.
v3: Use LRCA[31:12] as hwCtxId[19:0]. This guarantees that the HW context ID we submit to the ELSP is globally unique and != 0 (Bspec requirements of the software use-only bits of the Context ID in the Context Descriptor Format) without the hassle of the previous submission Id construction. Also, re-add the ELSP porting read (it was dropped somewhere during the rebases).
v4:
- Squash with "drm/i915/bdw: Add forcewake lock around ELSP writes" (BSPEC
says: "SW must set Force Wakeup bit to prevent GT from entering C6 while ELSP writes are in progress") as noted by Thomas Daniel ([email protected]).
- Rename functions and use an execlists/intel_execlists_ namespace.
- The BUG_ON only checked that the LRCA was <32 bits, but it didn't make sure that it was properly aligned. Spotted by Alistair Mcaulay <[email protected]>.
v5:
- Improved source code comments as suggested by Chris Wilson.
- No need to abstract submit_ctx away, as pointed by Brad Volkin.
--- drivers/gpu/drm/i915/intel_lrc.c | 116 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.h | 1 + 2 files changed, 115 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +114 -2
@@ -47,6 +47,7 @@#define GEN8_LR_CONTEXT_ALIGN 4096#define RING_ELSP (ring) ((ring)->mmio_base+0x230) +#define RING_EXECLIST_STATUS (ring) ((ring)->mmio_base+0x234)#define RING_CONTEXT_CONTROL (ring) ((ring)->mmio_base+0x244)#define CTX_LRI_HEADER_0 0x01
@@ -78,6 +79,26 @@#define CTX_R_PWR_CLK_STATE 0x42#define CTX_GPGPU_CSR_BASE_ADDRESS 0x44 +#define GEN8_CTX_VALID (1<<0) +#define GEN8_CTX_FORCE_PD_RESTORE (1<<1) +#define GEN8_CTX_FORCE_RESTORE (1<<2) +#define GEN8_CTX_L3LLC_COHERENT (1<<5) +#define GEN8_CTX_PRIVILEGE (1<<8) +enum { +ADVANCED_CONTEXT =0 , +LEGACY_CONTEXT , +ADVANCED_AD_CONTEXT , +LEGACY_64B_CONTEXT +}; +#define GEN8_CTX_MODE_SHIFT 3 +enum { +FAULT_AND_HANG =0 , +FAULT_AND_HALT ,/* Debug only */ +FAULT_AND_STREAM , +FAULT_AND_CONTINUE /* Unsupported */ +}; +#define GEN8_CTX_ID_SHIFT 32 +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) {if (enable_execlists ==0 )
@@ -90,6 +111,93 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsreturn 0 ; } +u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj) +{ +u32 lrca =i915_gem_obj_ggtt_offset (ctx_obj); + +/* LRCA is required to be 4K aligned so the more significant 20 bits +* are globally unique */ +return lrca >>12 ; +} + +static uint64_t execlists_ctx_descriptor (struct drm_i915_gem_object *ctx_obj) +{ +uint64_t desc; +uint64_t lrca =i915_gem_obj_ggtt_offset (ctx_obj); +BUG_ON (lrca &0xFFFFFFFF00000FFFULL ); + + desc =GEN8_CTX_VALID ; + desc |=LEGACY_CONTEXT <<GEN8_CTX_MODE_SHIFT ; + desc |=GEN8_CTX_L3LLC_COHERENT ; + desc |=GEN8_CTX_PRIVILEGE ; + desc |= lrca; + desc |= (u64 )intel_execlists_ctx_id (ctx_obj) <<GEN8_CTX_ID_SHIFT ; + +/* TODO: WaDisableLiteRestore when we start using semaphore +* signalling between Command Streamers */ +/* desc |= GEN8_CTX_FORCE_RESTORE; */ + +return desc; +} + +static void execlists_elsp_write (struct intel_engine_cs *ring, +struct drm_i915_gem_object *ctx_obj0, +struct drm_i915_gem_object *ctx_obj1) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +uint64_t temp =0 ; +uint32_t desc[4 ]; + +/* XXX: You must always write both descriptors in the order below. */ +if (ctx_obj1) + temp =execlists_ctx_descriptor (ctx_obj1); +else + temp =0 ; + desc[1 ] = (u32)(temp >>32 ); + desc[0 ] = (u32 )temp; + + temp =execlists_ctx_descriptor (ctx_obj0); + desc[3 ] = (u32)(temp >>32 ); + desc[2 ] = (u32 )temp; + +/* Set Force Wakeup bit to prevent GT from entering C6 while +* ELSP writes are in progress */ +gen6_gt_force_wake_get (dev_priv,FORCEWAKE_ALL ); + +I915_WRITE (RING_ELSP (ring), desc[1 ]); +I915_WRITE (RING_ELSP (ring), desc[0 ]); +I915_WRITE (RING_ELSP (ring), desc[3 ]); +/* The context is automatically loaded after the following */ +I915_WRITE (RING_ELSP (ring), desc[2 ]); + +/* ELSP is a wo register, so use another nearby reg for posting instead */ +POSTING_READ (RING_EXECLIST_STATUS (ring)); + +gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); +} + +static int execlists_submit_context (struct intel_engine_cs *ring, +struct intel_context *to0,u32 tail0, +struct intel_context *to1,u32 tail1) +{ +struct drm_i915_gem_object *ctx_obj0; +struct drm_i915_gem_object *ctx_obj1 =NULL ; + + ctx_obj0 = to0->engine[ring->id].state; +BUG_ON (!ctx_obj0); +BUG_ON (!i915_gem_obj_is_pinned (ctx_obj0)); + +if (to1) { + ctx_obj1 = to1->engine[ring->id].state; +BUG_ON (!ctx_obj1); +BUG_ON (!i915_gem_obj_is_pinned (ctx_obj1)); + } + +execlists_elsp_write (ring, ctx_obj0, ctx_obj1); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) {struct intel_engine_cs *ring = ringbuf->ring;
@@ -270,12 +378,16 @@ int logical_ring_flush_all_caches(struct intel_ringbuffer *ringbuf)void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) { +struct intel_engine_cs *ring = ringbuf->ring; +struct intel_context *ctx = ringbuf->ctx; +intel_logical_ring_advance (ringbuf); -if (intel_ring_stopped (ringbuf->ring)) +if (intel_ring_stopped (ring))return ; -/* TODO: how to submit a context to the ELSP is not here yet */ +/* FIXME: too cheeky, we don't even check if the ELSP is ready */ +execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 ); } static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,
drivers/gpu/drm/i915/intel_lrc.h +1 -0
@@ -58,5 +58,6 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,struct list_head *vmas, struct drm_i915_gem_object *batch_obj, u64 exec_start, u32 flags); +u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj);#endif /* _INTEL_LRC_H_ */
Signature · 1 line
1.7.9.5
Re: [PATCH 28/43] drm/i915/bdw: Implement context switching (somewhat)
Quoted 184 lines · Thomas Daniel
From: Ben Widawsky <[email protected]>
A context switch occurs by submitting a context descriptor to the ExecList Submission Port. Given that we can now initialize a context, it's possible to begin implementing the context switch by creating the descriptor and submitting it to ELSP (actually two, since the ELSP has two ports).
The context object must be mapped in the GGTT, which means it must exist in the 0-4GB graphics VA range.
Signed-off-by Ben Widawsky <[email protected]>v2: This code has changed quite a lot in various rebases. Of particular importance is that now we use the globally unique Submission ID to send to the hardware. Also, context pages are now pinned unconditionally to GGTT, so there is no need to bind them.
v3: Use LRCA[31:12] as hwCtxId[19:0]. This guarantees that the HW context ID we submit to the ELSP is globally unique and != 0 (Bspec requirements of the software use-only bits of the Context ID in the Context Descriptor Format) without the hassle of the previous submission Id construction. Also, re-add the ELSP porting read (it was dropped somewhere during the rebases).
v4:
- Squash with "drm/i915/bdw: Add forcewake lock around ELSP writes" (BSPEC
says: "SW must set Force Wakeup bit to prevent GT from entering C6 while ELSP writes are in progress") as noted by Thomas Daniel ([email protected]).
- Rename functions and use an execlists/intel_execlists_ namespace.
- TheBUG_ONonly checked that the LRCA was <32 bits, but it didn't make sure that it was properly aligned. Spotted by Alistair Mcaulay <[email protected]>.v5:
- Improved source code comments as suggested by Chris Wilson.
- No need to abstractsubmit_ctxaway, as pointed by Brad Volkin.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 116 +++++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.h | 1 + 2 files changed, 115 insertions(+), 2 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +110
-0@@ -47,6 +47,7 @@#define GEN8_LR_CONTEXT_ALIGN 4096#define RING_ELSP (ring) ((ring)->mmio_base+0x230) +#define RING_EXECLIST_STATUS (ring) ((ring)->mmio_base+0x234)#define RING_CONTEXT_CONTROL (ring) ((ring)->mmio_base+0x244)#define CTX_LRI_HEADER_0 0x01@@ -78,6 +79,26 @@#define CTX_R_PWR_CLK_STATE 0x42#define CTX_GPGPU_CSR_BASE_ADDRESS 0x44 +#define GEN8_CTX_VALID (1<<0) +#define GEN8_CTX_FORCE_PD_RESTORE (1<<1) +#define GEN8_CTX_FORCE_RESTORE (1<<2) +#define GEN8_CTX_L3LLC_COHERENT (1<<5) +#define GEN8_CTX_PRIVILEGE (1<<8) +enum { +ADVANCED_CONTEXT =0 , +LEGACY_CONTEXT , +ADVANCED_AD_CONTEXT , +LEGACY_64B_CONTEXT +}; +#define GEN8_CTX_MODE_SHIFT 3 +enum { +FAULT_AND_HANG =0 , +FAULT_AND_HALT ,/* Debug only */ +FAULT_AND_STREAM , +FAULT_AND_CONTINUE /* Unsupported */ +}; +#define GEN8_CTX_ID_SHIFT 32 +int intel_sanitize_enable_execlists (struct drm_device *dev,int enable_execlists) {if (enable_execlists ==0 )@@ -90,6 +111,93 @@ int intel_sanitize_enable_execlists(struct drm_device *dev, int enable_execlistsreturn 0 ; } +u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj) +{ +u32 lrca =i915_gem_obj_ggtt_offset (ctx_obj); + +/* LRCA is required to be 4K aligned so the more significant 20 bits +* are globally unique */ +return lrca >>12 ; +} + +static uint64_t execlists_ctx_descriptor (struct drm_i915_gem_object *ctx_obj) +{ +uint64_t desc; +uint64_t lrca =i915_gem_obj_ggtt_offset (ctx_obj); +BUG_ON (lrca &0xFFFFFFFF00000FFFULL ); + + desc =GEN8_CTX_VALID ; + desc |=LEGACY_CONTEXT <<GEN8_CTX_MODE_SHIFT ; + desc |=GEN8_CTX_L3LLC_COHERENT ; + desc |=GEN8_CTX_PRIVILEGE ; + desc |= lrca; + desc |= (u64 )intel_execlists_ctx_id (ctx_obj) <<GEN8_CTX_ID_SHIFT ; + +/* TODO: WaDisableLiteRestore when we start using semaphore +* signalling between Command Streamers */ +/* desc |= GEN8_CTX_FORCE_RESTORE; */ + +return desc; +} + +static void execlists_elsp_write (struct intel_engine_cs *ring, +struct drm_i915_gem_object *ctx_obj0, +struct drm_i915_gem_object *ctx_obj1) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +uint64_t temp =0 ; +uint32_t desc[4 ]; + +/* XXX: You must always write both descriptors in the order below. */ +if (ctx_obj1) + temp =execlists_ctx_descriptor (ctx_obj1); +else + temp =0 ; + desc[1 ] = (u32)(temp >>32 ); + desc[0 ] = (u32 )temp; + + temp =execlists_ctx_descriptor (ctx_obj0); + desc[3 ] = (u32)(temp >>32 ); + desc[2 ] = (u32 )temp; + +/* Set Force Wakeup bit to prevent GT from entering C6 while +* ELSP writes are in progress */ +gen6_gt_force_wake_get (dev_priv,FORCEWAKE_ALL ); + +I915_WRITE (RING_ELSP (ring), desc[1 ]); +I915_WRITE (RING_ELSP (ring), desc[0 ]); +I915_WRITE (RING_ELSP (ring), desc[3 ]); +/* The context is automatically loaded after the following */ +I915_WRITE (RING_ELSP (ring), desc[2 ]); + +/* ELSP is a wo register, so use another nearby reg for posting instead */ +POSTING_READ (RING_EXECLIST_STATUS (ring)); + +gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); +} + +static int execlists_submit_context (struct intel_engine_cs *ring, +struct intel_context *to0,u32 tail0, +struct intel_context *to1,u32 tail1) +{ +struct drm_i915_gem_object *ctx_obj0; +struct drm_i915_gem_object *ctx_obj1 =NULL ; + + ctx_obj0 = to0->engine[ring->id].state; +BUG_ON (!ctx_obj0); +BUG_ON (!i915_gem_obj_is_pinned (ctx_obj0)); + +if (to1) { + ctx_obj1 = to1->engine[ring->id].state; +BUG_ON (!ctx_obj1); +BUG_ON (!i915_gem_obj_is_pinned (ctx_obj1)); + } + +execlists_elsp_write (ring, ctx_obj0, ctx_obj1); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) {struct intel_engine_cs *ring = ringbuf->ring;@@ -270,12 +378,16 @@ int logical_ring_flush_all_caches(struct intel_ringbuffer *ringbuf)void intel_logical_ring_advance_and_submit (struct intel_ringbuffer *ringbuf) { +struct intel_engine_cs *ring = ringbuf->ring; +struct intel_context *ctx = ringbuf->ctx;
drivers/gpu/drm/i915/intel_lrc.c int logical_ring_flush_all_caches(struct intel_ringbuffer *ringbuf) · line 390
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +4
-2+intel_logical_ring_advance (ringbuf); -if (intel_ring_stopped (ringbuf->ring)) +if (intel_ring_stopped (ring))return ; -/* TODO: how to submit a context to the ELSP is not here yet */ +/* FIXME: too cheeky, we don't even check if the ELSP is ready */ +execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 );
So this is the 2nd user of ringbuf->ctx I've spotted (well gcc did) and imo it shouldn't be here. We should have one ELSP submit for each batch, not one for each ring_advance. Heck even the ring_advance should probably be done just once.
This is one of the reasons why I wanted to have a parallel execlist function hierarchy, so that we could implement such stuff correctly without jumping through hoops (or doing the lazy update trick we do for legacy rings).
Punt on this for now.
-Daniel
Quoted 21 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0} static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,drivers/gpu/drm/i915/intel_lrc.h +1
-0@@ -58,5 +58,6 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file,struct list_head *vmas, struct drm_i915_gem_object *batch_obj, u64 exec_start, u32 flags); +u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj);#endif /* _INTEL_LRC_H_ */ Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 29/43 drm/i915/bdw: Write the tail pointer, LRC style
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
Each logical ring context has the tail pointer in the context object, so update it before submission.
v2: New namespace.
--- drivers/gpu/drm/i915/intel_lrc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/gpu/drm/i915/intel_lrc.c +19 -0
@@ -176,6 +176,21 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); } +static int execlists_ctx_write_tail (struct drm_i915_gem_object *ctx_obj,u32 tail) +{ +struct page *page; +uint32_t *reg_state; + + page =i915_gem_object_get_page (ctx_obj,1 ); + reg_state =kmap_atomic (page); + + reg_state[CTX_RING_TAIL +1 ] = tail; + +kunmap_atomic (reg_state); + +return 0 ; +} +static int execlists_submit_context (struct intel_engine_cs *ring,struct intel_context *to0,u32 tail0,struct intel_context *to1,u32 tail1)
@@ -187,10 +202,14 @@ static int execlists_submit_context(struct intel_engine_cs *ring,BUG_ON (!ctx_obj0);BUG_ON (!i915_gem_obj_is_pinned (ctx_obj0)); +execlists_ctx_write_tail (ctx_obj0, tail0); +if (to1) { ctx_obj1 = to1->engine[ring->id].state;BUG_ON (!ctx_obj1);BUG_ON (!i915_gem_obj_is_pinned (ctx_obj1)); + +execlists_ctx_write_tail (ctx_obj1, tail1); }execlists_elsp_write (ring, ctx_obj0, ctx_obj1);
Signature · 1 line
1.7.9.5
Re: [PATCH 29/43] drm/i915/bdw: Write the tail pointer, LRC style
Quoted 6 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Each logical ring context has the tail pointer in the context object, so update it before submission.
v2: New namespace.
I believe we could just leave the context object mapped for its whole lifetime. Something to thing about at a later point.
Signature · 1 line
Damien
Quoted 53 lines
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +19
-0@@ -176,6 +176,21 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); } +static int execlists_ctx_write_tail (struct drm_i915_gem_object *ctx_obj,u32 tail) +{ +struct page *page; +uint32_t *reg_state; + + page =i915_gem_object_get_page (ctx_obj,1 ); + reg_state =kmap_atomic (page); + + reg_state[CTX_RING_TAIL +1 ] = tail; + +kunmap_atomic (reg_state); + +return 0 ; +} +static int execlists_submit_context (struct intel_engine_cs *ring,struct intel_context *to0,u32 tail0,struct intel_context *to1,u32 tail1)@@ -187,10 +202,14 @@ static int execlists_submit_context(struct intel_engine_cs *ring,BUG_ON (!ctx_obj0);BUG_ON (!i915_gem_obj_is_pinned (ctx_obj0)); +execlists_ctx_write_tail (ctx_obj0, tail0); +if (to1) { ctx_obj1 = to1->engine[ring->id].state;BUG_ON (!ctx_obj1);BUG_ON (!i915_gem_obj_is_pinned (ctx_obj1)); + +execlists_ctx_write_tail (ctx_obj1, tail1); }execlists_elsp_write (ring, ctx_obj0, ctx_obj1);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 29/43] drm/i915/bdw: Write the tail pointer, LRC style
In reply to Thomas DanielQuoted 40 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
Each logical ring context has the tail pointer in the context object, so update it before submission.
v2: New namespace.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)drivers/gpu/drm/i915/intel_lrc.c +15
-0@@ -176,6 +176,21 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); } +static int execlists_ctx_write_tail (struct drm_i915_gem_object *ctx_obj,u32 tail) +{ +struct page *page; +uint32_t *reg_state; + + page =i915_gem_object_get_page (ctx_obj,1 ); + reg_state =kmap_atomic (page); + + reg_state[CTX_RING_TAIL +1 ] = tail; + +kunmap_atomic (reg_state); + +return 0 ; +} +static int execlists_submit_context (struct intel_engine_cs *ring,struct intel_context *to0,u32 tail0,struct intel_context *to1,u32 tail1)@@ -187,10 +202,14 @@ static int execlists_submit_context(struct intel_engine_cs *ring,BUG_ON (!ctx_obj0);
drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring, · line 212
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +4
-0BUG_ON (!i915_gem_obj_is_pinned (ctx_obj0)); +execlists_ctx_write_tail (ctx_obj0, tail0); +if (to1) { ctx_obj1 = to1->engine[ring->id].state;BUG_ON (!ctx_obj1);BUG_ON (!i915_gem_obj_is_pinned (ctx_obj1)); + +execlists_ctx_write_tail (ctx_obj1, tail1);
Ok, now I'm totally surprised - here's the tail write and elsp submit like excepted. So why do we need the dance in the previous patch?
I'll look at this again tomorrow and will stop merging for today. -Daniel
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +0
-0}execlists_elsp_write (ring, ctx_obj0, ctx_obj1);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 30/43 drm/i915/bdw: Two-stage execlist submit process
In reply to Thomas DanielFrom: Michel Thierry <[email protected]>
Context switch (and execlist submission) should happen only when other contexts are not active, otherwise pre-emption occurs.
To assure this, we place context switch requests in a queue and those request are later consumed when the right context switch interrupt is received (still TODO).
v2: Use a spinlock, do not remove the requests on unqueue (wait for context switch completion).
v3: Several rebases and code changes. Use unique ID.
v4:
- Move the queue/lock init to the late ring initialization.
- Damien's kmalloc review comments: check return, use sizeof(*req), do not cast.
v5:
- Do not reuse drm_i915_gem_request. Instead, create our own.
- New namespace.
--- drivers/gpu/drm/i915/intel_lrc.c | 63 ++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.h | 8 ++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 3 files changed, 71 insertions(+), 2 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +61 -2
@@ -217,6 +217,63 @@ static int execlists_submit_context(struct intel_engine_cs *ring,return 0 ; } +static void execlists_context_unqueue (struct intel_engine_cs *ring) +{ +struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ; +struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; + +if (list_empty (&ring->execlist_queue)) +return ; + +/* Try to read in pairs */ +list_for_each_entry_safe (cursor, tmp, &ring->execlist_queue, execlist_link) { +if (!req0) + req0 = cursor; +else if (req0->ctx == cursor->ctx) { +/* Same ctx: ignore first request, as second request +* will update tail past first request's workload */ +list_del (&req0->execlist_link); +i915_gem_context_unreference (req0->ctx); +kfree (req0); + req0 = cursor; + }else { + req1 = cursor; +break ; + } + } + +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, + req1? req1->ctx :NULL , req1? req1->tail :0 )); +} + +static int execlists_context_queue (struct intel_engine_cs *ring, +struct intel_context *to, +u32 tail) +{ +struct intel_ctx_submit_request *req =NULL ; +unsigned long flags; +bool was_empty; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (req ==NULL ) +return -ENOMEM ; + req->ctx = to; +i915_gem_context_reference (req->ctx); + req->ring = ring; + req->tail = tail; + +spin_lock_irqsave (&ring->execlist_lock, flags); + + was_empty =list_empty (&ring->execlist_queue); +list_add_tail (&req->execlist_link, &ring->execlist_queue); +if (was_empty) +execlists_context_unqueue (ring); + +spin_unlock_irqrestore (&ring->execlist_lock, flags); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) {struct intel_engine_cs *ring = ringbuf->ring;
@@ -405,8 +462,7 @@ void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)if (intel_ring_stopped (ring))return ; -/* FIXME: too cheeky, we don't even check if the ELSP is ready */ -execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 ); +execlists_context_queue (ring, ctx, ringbuf->tail); } static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,
@@ -850,6 +906,9 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->request_list);init_waitqueue_head (&ring->irq_queue); +INIT_LIST_HEAD (&ring->execlist_queue); +spin_lock_init (&ring->execlist_lock); + ret =intel_lr_context_deferred_create (dctx, ring);if (ret)return ret;
drivers/gpu/drm/i915/intel_lrc.h +8 -0
@@ -60,4 +60,12 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, u64 exec_start, u32 flags);u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj); +struct intel_ctx_submit_request { +struct intel_context *ctx; +struct intel_engine_cs *ring; +u32 tail; + +struct list_head execlist_link; +}; +#endif /* _INTEL_LRC_H_ */
drivers/gpu/drm/i915/intel_ringbuffer.h +2 -0
@@ -223,6 +223,8 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +spinlock_t execlist_lock; +struct list_head execlist_queue;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,
Signature · 1 line
1.7.9.5
Re: [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit process
Quoted 58 lines · Thomas Daniel
From: Michel Thierry <[email protected]>
Context switch (and execlist submission) should happen only when other contexts are not active, otherwise pre-emption occurs.
To assure this, we place context switch requests in a queue and those request are later consumed when the right context switch interrupt is received (still TODO).
v2: Use a spinlock, do not remove the requests on unqueue (wait for context switch completion).
Signed-off-by Thomas Daniel <[email protected]>v3: Several rebases and code changes. Use unique ID.
v4:
- Move the queue/lock init to the late ring initialization.
- Damien's kmalloc review comments: check return, usesizeof(*req), do not cast.v5:
- Do not reusedrm_i915_gem_request. Instead, create our own.
- New namespace.Signed-off-by Michel Thierry <[email protected]> (v1)Signed-off-by Oscar Mateo <[email protected]> (v2-v5)--- drivers/gpu/drm/i915/intel_lrc.c | 63 ++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.h | 8 ++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 3 files changed, 71 insertions(+), 2 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +17
-0@@ -217,6 +217,63 @@ static int execlists_submit_context(struct intel_engine_cs *ring,return 0 ; } +static void execlists_context_unqueue (struct intel_engine_cs *ring) +{ +struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ; +struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; + +if (list_empty (&ring->execlist_queue)) +return ; + +/* Try to read in pairs */ +list_for_each_entry_safe (cursor, tmp, &ring->execlist_queue, execlist_link) { +if (!req0) + req0 = cursor; +else if (req0->ctx == cursor->ctx) { +/* Same ctx: ignore first request, as second request +* will update tail past first request's workload */ +list_del (&req0->execlist_link); +i915_gem_context_unreference (req0->ctx);
drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring, · line 246
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+kfree (req0); + req0 = cursor; + }else { + req1 = cursor; +break ; + } + } + +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, + req1? req1->ctx :NULL , req1? req1->tail :0 ));
You don't get to hard-hang my driver just because you've done a programming mistake. Please remember my commandements ;-)
Also checkpatch ...
-Daniel
Quoted 90 lines
drivers/gpu/drm/i915/intel_lrc.c +34
-2+} + +static int execlists_context_queue (struct intel_engine_cs *ring, +struct intel_context *to, +u32 tail) +{ +struct intel_ctx_submit_request *req =NULL ; +unsigned long flags; +bool was_empty; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (req ==NULL ) +return -ENOMEM ; + req->ctx = to; +i915_gem_context_reference (req->ctx); + req->ring = ring; + req->tail = tail; + +spin_lock_irqsave (&ring->execlist_lock, flags); + + was_empty =list_empty (&ring->execlist_queue); +list_add_tail (&req->execlist_link, &ring->execlist_queue); +if (was_empty) +execlists_context_unqueue (ring); + +spin_unlock_irqrestore (&ring->execlist_lock, flags); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) {struct intel_engine_cs *ring = ringbuf->ring;@@ -405,8 +462,7 @@ void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)if (intel_ring_stopped (ring))return ; -/* FIXME: too cheeky, we don't even check if the ELSP is ready */ -execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 ); +execlists_context_queue (ring, ctx, ringbuf->tail); } static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,@@ -850,6 +906,9 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->request_list);init_waitqueue_head (&ring->irq_queue); +INIT_LIST_HEAD (&ring->execlist_queue); +spin_lock_init (&ring->execlist_lock); + ret =intel_lr_context_deferred_create (dctx, ring);if (ret)return ret;drivers/gpu/drm/i915/intel_lrc.h +8
-0@@ -60,4 +60,12 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, u64 exec_start, u32 flags);u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj); +struct intel_ctx_submit_request { +struct intel_context *ctx; +struct intel_engine_cs *ring; +u32 tail; + +struct list_head execlist_link; +}; +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +2
-0@@ -223,6 +223,8 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +spinlock_t execlist_lock; +struct list_head execlist_queue;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit process
In reply to Thomas DanielQuoted 41 lines · Thomas Daniel
From: Michel Thierry <[email protected]>
Context switch (and execlist submission) should happen only when other contexts are not active, otherwise pre-emption occurs.
To assure this, we place context switch requests in a queue and those request are later consumed when the right context switch interrupt is received (still TODO).
v2: Use a spinlock, do not remove the requests on unqueue (wait for context switch completion).
Signed-off-by Thomas Daniel <[email protected]>v3: Several rebases and code changes. Use unique ID.
v4:
- Move the queue/lock init to the late ring initialization.
- Damien's kmalloc review comments: check return, usesizeof(*req), do not cast.v5:
- Do not reusedrm_i915_gem_request. Instead, create our own.
- New namespace.Signed-off-by Michel Thierry <[email protected]> (v1)Signed-off-by Oscar Mateo <[email protected]> (v2-v5)--- drivers/gpu/drm/i915/intel_lrc.c | 63 ++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/intel_lrc.h | 8 ++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 3 files changed, 71 insertions(+), 2 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -217,6 +217,63 @@ static int execlists_submit_context(struct intel_engine_cs *ring,return 0 ; }
drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring, · line 229
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+static void execlists_context_unqueue (struct intel_engine_cs *ring) +{ +struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ; +struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; + +if (list_empty (&ring->execlist_queue)) +return ; + +/* Try to read in pairs */ +list_for_each_entry_safe (cursor, tmp, &ring->execlist_queue, execlist_link) {
Ok, because checkpatch I've looked at this. Imo open-coding this would be much easier to read i.e.
if (!list_empty) grab&remove first item; if (!list_empty) grab&remove 2nd item;
Care to follow up with a patch for that?
Thanks, Daniel
Quoted 107 lines
drivers/gpu/drm/i915/intel_lrc.c +51
-2+if (!req0) + req0 = cursor; +else if (req0->ctx == cursor->ctx) { +/* Same ctx: ignore first request, as second request +* will update tail past first request's workload */ +list_del (&req0->execlist_link); +i915_gem_context_unreference (req0->ctx); +kfree (req0); + req0 = cursor; + }else { + req1 = cursor; +break ; + } + } + +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, + req1? req1->ctx :NULL , req1? req1->tail :0 )); +} + +static int execlists_context_queue (struct intel_engine_cs *ring, +struct intel_context *to, +u32 tail) +{ +struct intel_ctx_submit_request *req =NULL ; +unsigned long flags; +bool was_empty; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (req ==NULL ) +return -ENOMEM ; + req->ctx = to; +i915_gem_context_reference (req->ctx); + req->ring = ring; + req->tail = tail; + +spin_lock_irqsave (&ring->execlist_lock, flags); + + was_empty =list_empty (&ring->execlist_queue); +list_add_tail (&req->execlist_link, &ring->execlist_queue); +if (was_empty) +execlists_context_unqueue (ring); + +spin_unlock_irqrestore (&ring->execlist_lock, flags); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) {struct intel_engine_cs *ring = ringbuf->ring;@@ -405,8 +462,7 @@ void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)if (intel_ring_stopped (ring))return ; -/* FIXME: too cheeky, we don't even check if the ELSP is ready */ -execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 ); +execlists_context_queue (ring, ctx, ringbuf->tail); } static int logical_ring_alloc_seqno(struct intel_engine_cs *ring,@@ -850,6 +906,9 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->request_list);init_waitqueue_head (&ring->irq_queue); +INIT_LIST_HEAD (&ring->execlist_queue); +spin_lock_init (&ring->execlist_lock); + ret =intel_lr_context_deferred_create (dctx, ring);if (ret)return ret;drivers/gpu/drm/i915/intel_lrc.h +8
-0@@ -60,4 +60,12 @@ int intel_execlists_submission(struct drm_device *dev, struct drm_file *file, u64 exec_start, u32 flags);u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj); +struct intel_ctx_submit_request { +struct intel_context *ctx; +struct intel_engine_cs *ring; +u32 tail; + +struct list_head execlist_link; +}; +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +2
-0@@ -223,6 +223,8 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +spinlock_t execlist_lock; +struct list_head execlist_queue;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit process
Quoted 70 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 9:10 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit processQuoted 21 lines · Thomas Daniel
From: Michel Thierry <[email protected]>
Context switch (and execlist submission) should happen only when other contexts are not active, otherwise pre-emption occurs.
To assure this, we place context switch requests in a queue and those request are later consumed when the right context switch interrupt is received (still TODO).
v2: Use a spinlock, do not remove the requests on unqueue (wait for context switch completion).
Signed-off-by Thomas Daniel <[email protected]>v3: Several rebases and code changes. Use unique ID.
v4:
- Move the queue/lock init to the late ring initialization.
- Damien's kmalloc review comments: check return, usesizeof(*req), do not cast.Quoted 8 lines
v5:
- Do not reusedrm_i915_gem_request. Instead, create our own.
- New namespace.Signed-off-by Michel Thierry <[email protected]> (v1)Signed-off-by Oscar Mateo <[email protected]> (v2-v5)--- drivers/gpu/drm/i915/intel_lrc.c | 63++++++++++++++++++++++++++++++-
drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.h | 8 ++++ drivers/gpu/drm/i915/intel_ringbuffer.h | 2 + 3 files changed, 71 insertions(+), 2 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +0
-0@@ -217,6 +217,63 @@ static int execlists_submit_context(struct
intel_engine_cs*ring,drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring,
Quoted 13 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0return 0 ; } +static void execlists_context_unqueue (struct intel_engine_cs *ring) { +struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ; +struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; + +if (list_empty (&ring->execlist_queue)) +return ; + +/* Try to read in pairs */ +list_for_each_entry_safe (cursor, tmp, &ring->execlist_queue, +execlist_link) {Ok, because checkpatch I've looked at this. Imo open-coding this would be much easier to read i.e.
Quoted 8 lines
if (!list_empty) grab&remove first item; if (!list_empty) grab&remove 2nd item;Care to follow up with a patch for that?
Thanks, Daniel
This needs to be kept as a loop because if there are two consecutive requests for the same context they are squashed. Also the non-squashed requests are not removed here (unfortunately the remove is in the next patch).
Quoted 4 lines
drivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring, · line 232
Quoted 4 lines
drivers/gpu/drm/i915/intel_lrc.c +3
-0+if (!req0) + req0 = cursor; +else if (req0->ctx == cursor->ctx) {
This:
Quoted 114 lines
Quoted 46 lines
drivers/gpu/drm/i915/intel_lrc.c +43
-0+/* Same ctx: ignore first request, as second request +* will update tail past first request's workload */ +list_del (&req0->execlist_link); +i915_gem_context_unreference (req0->ctx); +kfree (req0); + req0 = cursor; + }else { + req1 = cursor; +break ; + } + } + +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, + req1? req1->ctx :NULL , req1? req1->tail :0 )); } + +static int execlists_context_queue (struct intel_engine_cs *ring, +struct intel_context *to, +u32 tail) +{ +struct intel_ctx_submit_request *req =NULL ; +unsigned long flags; +bool was_empty; + + req =kzalloc (sizeof (*req),GFP_KERNEL ); +if (req ==NULL ) +return -ENOMEM ; + req->ctx = to; +i915_gem_context_reference (req->ctx); + req->ring = ring; + req->tail = tail; + +spin_lock_irqsave (&ring->execlist_lock, flags); + + was_empty =list_empty (&ring->execlist_queue); +list_add_tail (&req->execlist_link, &ring->execlist_queue); +if (was_empty) +execlists_context_unqueue (ring); + +spin_unlock_irqrestore (&ring->execlist_lock, flags); + +return 0 ; +} +static int logical_ring_invalidate_all_caches (struct intel_ringbuffer *ringbuf) { struct intel_engine_cs *ring = ringbuf->ring; @@ -405,8 +462,7 @@Quoted 1 line
void intel_logical_ring_advance_and_submit(struct
intel_ringbuffer*ringbuf)
drivers/gpu/drm/i915/intel_lrc.c void intel_logical_ring_advance_and_submit(struct intel_ringbuffer *ringbuf)
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +1
-3if (intel_ring_stopped (ring))return ; -/* FIXME: too cheeky, we don't even check if the ELSP is ready */ -execlists_submit_context (ring, ctx, ringbuf->tail,NULL ,0 ); +execlists_context_queue (ring, ctx, ringbuf->tail); } static int logical_ring_alloc_seqno(struct intel_engine_cs *ring, @@ -850,6 +906,9 @@ static int logical_ring_init(struct drm_device *dev, struct
intel_engine_cs*rindrivers/gpu/drm/i915/intel_lrc.h int intel_execlists_submission(struct drm_device
Quoted 15 lines
drivers/gpu/drm/i915/intel_lrc.c +3
-0INIT_LIST_HEAD (&ring->request_list);init_waitqueue_head (&ring->irq_queue); +INIT_LIST_HEAD (&ring->execlist_queue); +spin_lock_init (&ring->execlist_lock); + ret =intel_lr_context_deferred_create (dctx, ring);if (ret)return ret;drivers/gpu/drm/i915/intel_lrc.h +0
-0@@ -60,4 +60,12 @@ int intel_execlists_submission(struct drm_device*dev, struct
drm_file*file,Quoted 18 lines
drivers/gpu/drm/i915/intel_lrc.h +8
-0u64 exec_start, u32 flags);u32 intel_execlists_ctx_id (struct drm_i915_gem_object *ctx_obj); +struct intel_ctx_submit_request { +struct intel_context *ctx; +struct intel_engine_cs *ring; +u32 tail; + +struct list_head execlist_link; +}; +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +0
-0drivers/gpu/drm/i915/intel_ringbuffer.h struct intel_engine_cs { · line 228
Quoted 6 lines
drivers/gpu/drm/i915/intel_ringbuffer.h +2
-0@@ -223,6 +223,8 @@ struct intel_engine_cs { } semaphore;/* Execlists */ +spinlock_t execlist_lock; +struct list_head execlist_queue;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */
Quoted 9 lines
drivers/gpu/drm/i915/intel_ringbuffer.h +0
-1int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf, --1.7.9.5
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit process
Quoted 29 lines · Thomas
Quoted 29 lines
-----Original Message-----
From: Daniel Vetter [mailto:[email protected]] On Behalf Of Daniel Vetter
Sent: Thursday, August 14, 2014 9:10 PM
To: Daniel, Thomas
Cc: [email protected]
Subject: Re: [Intel-gfx] [PATCH 30/43] drm/i915/bdw: Two-stage execlist submit processdrivers/gpu/drm/i915/intel_lrc.c static int execlists_submit_context(struct intel_engine_cs *ring,
Quoted 11 lines · Thomas Daniel
From: Michel Thierry <[email protected]>
drivers/gpu/drm/i915/intel_lrc.c +10
-0+static void execlists_context_unqueue (struct intel_engine_cs *ring) { +struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ; +struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; + +if (list_empty (&ring->execlist_queue)) +return ; + +/* Try to read in pairs */ +list_for_each_entry_safe (cursor, tmp, &ring->execlist_queue, +execlist_link) {Ok, because checkpatch I've looked at this. Imo open-coding this would be much easier to read i.e.
if (!list_empty) grab&remove first item; if (!list_empty) grab&remove 2nd item;
Quoted 7 lines
Quoted 3 lines
Care to follow up with a patch for that?
Thanks, Daniel
This needs to be kept as a loop because if there are two consecutive requests for the same context they are squashed. Also the non-squashed requests are not removed here (unfortunately the remove is in the next patch).
Ok, this sounds like we need to overhaul it anyway for the request tracking then.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 31/43 drm/i915/bdw: Handle context switch events
In reply to Thomas DanielHandle all context status events in the context status buffer on every context switch interrupt. We only remove work from the execlist queue after a context status buffer reports that it has completed and we only attempt to schedule new contexts on interrupt when a previously submitted context completes (unless no contexts are queued, which means the GPU is free).
We canot call intel_runtime_pm_get() in an interrupt (or with a spinlock grabbed, FWIW), because it might sleep, which is not a nice thing to do. Instead, do the runtime_pm get/put together with the create/destroy request, and handle the forcewake get/put directly.
v2: Unreferencing the context when we are freeing the request might free the backing bo, which requires the struct_mutex to be grabbed, so defer unreferencing and freeing to a bottom half.
v3:
- Ack the interrupt inmediately, before trying to handle it (fix for missing interrupts by Bob Beckett <[email protected]>).
- Update the Context Status Buffer Read Pointer, just in case (spotted by Damien Lespiau).
v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call intel_runtime_pm_get() in an interrupt", as suggested by Daniel.
--- drivers/gpu/drm/i915/i915_irq.c | 35 ++++++--- drivers/gpu/drm/i915/intel_lrc.c | 129 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_lrc.h | 3 + drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 151 insertions(+), 17 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +24 -11
@@ -1628,6 +1628,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 master_ctl) { +struct intel_engine_cs *ring;u32 rcs, bcs, vcs;uint32_t tmp =0 ;irqreturn_t ret =IRQ_NONE ;
@@ -1637,14 +1638,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (0 ), tmp); ret =IRQ_HANDLED ; + rcs = tmp >>GEN8_RCS_IRQ_SHIFT ; - bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[RCS ];if (rcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[RCS ]); +notify_ring (dev, ring); +if (rcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring); + + bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[BCS ];if (bcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[BCS ]); -if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +notify_ring (dev, ring); +if (bcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }
@@ -1654,16 +1661,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (1 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); + vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS2 ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS2 ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }
@@ -1684,11 +1695,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (3 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VECS_IRQ_SHIFT ; + ring = &dev_priv->ring[VECS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VECS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }
drivers/gpu/drm/i915/intel_lrc.c +123 -6
183 lines not on this page · raw message
drivers/gpu/drm/i915/intel_lrc.h +3 -0
@@ -66,6 +66,9 @@ struct intel_ctx_submit_request {u32 tail;struct list_head execlist_link; + struct work_struct work; }; +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring); +#endif /* _INTEL_LRC_H_ */
drivers/gpu/drm/i915/intel_ringbuffer.h +1 -0
@@ -225,6 +225,7 @@ struct intel_engine_cs {/* Execlists */ spinlock_t execlist_lock;struct list_head execlist_queue; +u8 next_context_status_buffer;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,
Signature · 1 line
1.7.9.5
Re: [PATCH 31/43] drm/i915/bdw: Handle context switch events
Quoted 106 lines · Thomas Daniel
Handle all context status events in the context status buffer on every context switch interrupt. We only remove work from the execlist queue after a context status buffer reports that it has completed and we only attempt to schedule new contexts on interrupt when a previously submitted context completes (unless no contexts are queued, which means the GPU is free).
We canot call
intel_runtime_pm_get()in an interrupt (or with a spinlock grabbed, FWIW), because it might sleep, which is not a nice thing to do. Instead, do theruntime_pmget/put together with the create/destroy request, and handle the forcewake get/put directly.Signed-off-by Thomas Daniel <[email protected]>v2: Unreferencing the context when we are freeing the request might free the backing bo, which requires the
struct_mutexto be grabbed, so defer unreferencing and freeing to a bottom half.v3:
- Ack the interrupt inmediately, before trying to handle it (fix for missing interrupts by Bob Beckett <[email protected]>).
- Update the Context Status Buffer Read Pointer, just in case (spotted by Damien Lespiau).v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call
intel_runtime_pm_get()in an interrupt", as suggested by Daniel.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_irq.c | 35 ++++++--- drivers/gpu/drm/i915/intel_lrc.c | 129 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_lrc.h | 3 + drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 151 insertions(+), 17 deletions(-)drivers/gpu/drm/i915/i915_irq.c +21
-9@@ -1628,6 +1628,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 master_ctl) { +struct intel_engine_cs *ring;u32 rcs, bcs, vcs;uint32_t tmp =0 ;irqreturn_t ret =IRQ_NONE ;@@ -1637,14 +1638,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (0 ), tmp); ret =IRQ_HANDLED ; + rcs = tmp >>GEN8_RCS_IRQ_SHIFT ; - bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[RCS ];if (rcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[RCS ]); +notify_ring (dev, ring); +if (rcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring); + + bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[BCS ];if (bcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[BCS ]); -if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +notify_ring (dev, ring); +if (bcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }@@ -1654,16 +1661,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (1 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); + vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS2 ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS2 ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }@@ -1684,11 +1695,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (3 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VECS_IRQ_SHIFT ;
drivers/gpu/drm/i915/i915_irq.c static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, · line 1707
Quoted 10 lines
drivers/gpu/drm/i915/i915_irq.c +3
-2+ ring = &dev_priv->ring[VECS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VECS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }
The above stuff is dropping of the left edge a bit. And it's all so super-nicely lead out thanks to the hw engineers, so with a bit of code refactoring we should be able to have one generic ring irq handler and 5 callers for them and rip this all you.
Can you please do that?
-Daniel
Quoted 229 lines
drivers/gpu/drm/i915/intel_lrc.c +123
-6@@ -49,6 +49,22 @@#define RING_ELSP (ring) ((ring)->mmio_base+0x230)#define RING_EXECLIST_STATUS (ring) ((ring)->mmio_base+0x234)#define RING_CONTEXT_CONTROL (ring) ((ring)->mmio_base+0x244) +#define RING_CONTEXT_STATUS_BUF (ring) ((ring)->mmio_base+0x370) +#define RING_CONTEXT_STATUS_PTR (ring) ((ring)->mmio_base+0x3a0) + +#define RING_EXECLIST_QFULL (1 << 0x2) +#define RING_EXECLIST1_VALID (1 << 0x3) +#define RING_EXECLIST0_VALID (1 << 0x4) +#define RING_EXECLIST_ACTIVE_STATUS (3 << 0xE) +#define RING_EXECLIST1_ACTIVE (1 << 0x11) +#define RING_EXECLIST0_ACTIVE (1 << 0x12) + +#define GEN8_CTX_STATUS_IDLE_ACTIVE (1 << 0) +#define GEN8_CTX_STATUS_PREEMPTED (1 << 1) +#define GEN8_CTX_STATUS_ELEMENT_SWITCH (1 << 2) +#define GEN8_CTX_STATUS_ACTIVE_IDLE (1 << 3) +#define GEN8_CTX_STATUS_COMPLETE (1 << 4) +#define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15)#define CTX_LRI_HEADER_0 0x01#define CTX_CONTEXT_CONTROL 0x02@@ -147,6 +163,7 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,struct drm_i915_private *dev_priv = ring->dev->dev_private;uint64_t temp =0 ;uint32_t desc[4 ]; +unsigned long flags;/* XXX: You must always write both descriptors in the order below. */ if (ctx_obj1)@@ -160,9 +177,17 @@ static void execlists_elsp_write(struct intel_engine_cs *ring, desc[3 ] = (u32)(temp >>32 ); desc[2 ] = (u32 )temp; -/* Set Force Wakeup bit to prevent GT from entering C6 while -* ELSP writes are in progress */ -gen6_gt_force_wake_get (dev_priv,FORCEWAKE_ALL ); +/* Set Force Wakeup bit to prevent GT from entering C6 while ELSP writes +* are in progress. +* +* The other problem is that we can't just call gen6_gt_force_wake_get() +* because that function calls intel_runtime_pm_get(), which might sleep. +* Instead, we do the runtime_pm_get/put when creating/destroying requests. +*/ +spin_lock_irqsave (&dev_priv->uncore.lock, flags); +if (dev_priv->uncore.forcewake_count++ ==0 ) + dev_priv->uncore.funcs.force_wake_get (dev_priv,FORCEWAKE_ALL ); +spin_unlock_irqrestore (&dev_priv->uncore.lock, flags);I915_WRITE (RING_ELSP (ring), desc[1 ]);I915_WRITE (RING_ELSP (ring), desc[0 ]);@@ -173,7 +198,11 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,/* ELSP is a wo register, so use another nearby reg for posting instead */ POSTING_READ (RING_EXECLIST_STATUS (ring)); -gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); +/* Release Force Wakeup (see the big comment above). */ +spin_lock_irqsave (&dev_priv->uncore.lock, flags); +if (--dev_priv->uncore.forcewake_count ==0 ) + dev_priv->uncore.funcs.force_wake_put (dev_priv,FORCEWAKE_ALL ); +spin_unlock_irqrestore (&dev_priv->uncore.lock, flags); }static int execlists_ctx_write_tail (struct drm_i915_gem_object *ctx_obj,u32 tail)@@ -221,6 +250,9 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) {struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ;struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; +struct drm_i915_private *dev_priv = ring->dev->dev_private; + +assert_spin_locked (&ring->execlist_lock);if (list_empty (&ring->execlist_queue))return ;@@ -233,8 +265,7 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)/* Same ctx: ignore first request, as second request * will update tail past first request's workload */ list_del (&req0->execlist_link); -i915_gem_context_unreference (req0->ctx); -kfree (req0); +queue_work (dev_priv->wq, &req0->work); req0 = cursor; }else { req1 = cursor;@@ -246,6 +277,89 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) req1? req1->ctx : NULL, req1? req1->tail : 0)); } +static bool execlists_check_remove_request (struct intel_engine_cs *ring, +u32 request_id) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +struct intel_ctx_submit_request *head_req; + +assert_spin_locked (&ring->execlist_lock); + + head_req =list_first_entry_or_null (&ring->execlist_queue, + struct intel_ctx_submit_request, execlist_link); +if (head_req !=NULL ) { +struct drm_i915_gem_object *ctx_obj = + head_req->ctx->engine[ring->id].state; +if (intel_execlists_ctx_id (ctx_obj) == request_id) { +list_del (&head_req->execlist_link); +queue_work (dev_priv->wq, &head_req->work); +return true; + } + } + +return false; +} + +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +u32 status_pointer; +u8 read_pointer; +u8 write_pointer; +u32 status; +u32 status_id; +u32 submit_contexts =0 ; + + status_pointer =I915_READ (RING_CONTEXT_STATUS_PTR (ring)); + + read_pointer = ring->next_context_status_buffer; + write_pointer = status_pointer &0x07 ; +if (read_pointer > write_pointer) + write_pointer +=6 ; + +spin_lock (&ring->execlist_lock); + +while (read_pointer < write_pointer) { + read_pointer++; + status =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 ); + status_id =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 +4 ); + +if (status &GEN8_CTX_STATUS_COMPLETE ) { +if (execlists_check_remove_request (ring, status_id)) + submit_contexts++; + } + } + +if (submit_contexts !=0 ) +execlists_context_unqueue (ring); + +spin_unlock (&ring->execlist_lock); + +WARN (submit_contexts >2 ,"More than two context complete events?\n" ); + ring->next_context_status_buffer = write_pointer %6 ; + +I915_WRITE (RING_CONTEXT_STATUS_PTR (ring), + ((u32 )ring->next_context_status_buffer &0x07 ) <<8 ); +} + +static void execlists_free_request_task (struct work_struct *work) +{ +struct intel_ctx_submit_request *req = + container_of(work, struct intel_ctx_submit_request, work); +struct drm_device *dev = req->ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; + +intel_runtime_pm_put (dev_priv); + +mutex_lock (&dev->struct_mutex); +i915_gem_context_unreference (req->ctx); +mutex_unlock (&dev->struct_mutex); + +kfree (req); +} +static int execlists_context_queue (struct intel_engine_cs *ring,struct intel_context *to,u32 tail)@@ -261,6 +375,8 @@ static int execlists_context_queue(struct intel_engine_cs *ring,i915_gem_context_reference (req->ctx); req->ring = ring; req->tail = tail; +INIT_WORK (&req->work, execlists_free_request_task); +intel_runtime_pm_get (dev_priv);spin_lock_irqsave (&ring->execlist_lock, flags);@@ -908,6 +1024,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->execlist_queue);spin_lock_init (&ring->execlist_lock); + ring->next_context_status_buffer =0 ; ret =intel_lr_context_deferred_create (dctx, ring);if (ret)drivers/gpu/drm/i915/intel_lrc.h +3
-0@@ -66,6 +66,9 @@ struct intel_ctx_submit_request {u32 tail;struct list_head execlist_link; + struct work_struct work; }; +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring); +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +1
-0@@ -225,6 +225,7 @@ struct intel_engine_cs {/* Execlists */ spinlock_t execlist_lock;struct list_head execlist_queue; +u8 next_context_status_buffer;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 31/43] drm/i915/bdw: Handle context switch events
In reply to Thomas DanielQuoted 62 lines · Thomas Daniel
Handle all context status events in the context status buffer on every context switch interrupt. We only remove work from the execlist queue after a context status buffer reports that it has completed and we only attempt to schedule new contexts on interrupt when a previously submitted context completes (unless no contexts are queued, which means the GPU is free).
We canot call
intel_runtime_pm_get()in an interrupt (or with a spinlock grabbed, FWIW), because it might sleep, which is not a nice thing to do. Instead, do theruntime_pmget/put together with the create/destroy request, and handle the forcewake get/put directly.Signed-off-by Thomas Daniel <[email protected]>v2: Unreferencing the context when we are freeing the request might free the backing bo, which requires the
struct_mutexto be grabbed, so defer unreferencing and freeing to a bottom half.v3:
- Ack the interrupt inmediately, before trying to handle it (fix for missing interrupts by Bob Beckett <[email protected]>).
- Update the Context Status Buffer Read Pointer, just in case (spotted by Damien Lespiau).v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call
intel_runtime_pm_get()in an interrupt", as suggested by Daniel.Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/i915_irq.c | 35 ++++++--- drivers/gpu/drm/i915/intel_lrc.c | 129 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/intel_lrc.h | 3 + drivers/gpu/drm/i915/intel_ringbuffer.h | 1 + 4 files changed, 151 insertions(+), 17 deletions(-)drivers/gpu/drm/i915/i915_irq.c +6
-2@@ -1628,6 +1628,7 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, struct drm_i915_private *dev_priv, u32 master_ctl) { +struct intel_engine_cs *ring;u32 rcs, bcs, vcs;uint32_t tmp =0 ;irqreturn_t ret =IRQ_NONE ;@@ -1637,14 +1638,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (0 ), tmp); ret =IRQ_HANDLED ; + rcs = tmp >>GEN8_RCS_IRQ_SHIFT ; - bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[RCS ];if (rcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[RCS ]); +notify_ring (dev, ring); +if (rcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring);
drivers/gpu/drm/i915/i915_irq.c static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev, · line 1654
Quoted 10 lines
drivers/gpu/drm/i915/i915_irq.c +6
-3+ + bcs = tmp >>GEN8_BCS_IRQ_SHIFT ; + ring = &dev_priv->ring[BCS ];if (bcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[BCS ]); -if ((rcs | bcs) &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +notify_ring (dev, ring); +if (bcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) +intel_execlists_handle_ctx_events (ring);
Also patch split fail here, the above two cases should have been in an earlier patch that added the basic irq handling.
-Daniel
Quoted 273 lines
drivers/gpu/drm/i915/i915_irq.c +12
-6}else DRM_ERROR ("The master control interrupt lied (GT0)!\n" ); }@@ -1654,16 +1661,20 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (1 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VCS1_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); + vcs = tmp >>GEN8_VCS2_IRQ_SHIFT ; + ring = &dev_priv->ring[VCS2 ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VCS2 ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT1)!\n" ); }@@ -1684,11 +1695,13 @@ static irqreturn_t gen8_gt_irq_handler(struct drm_device *dev,if (tmp) {I915_WRITE (GEN8_GT_IIR (3 ), tmp); ret =IRQ_HANDLED ; + vcs = tmp >>GEN8_VECS_IRQ_SHIFT ; + ring = &dev_priv->ring[VECS ];if (vcs >_RENDER_USER_INTERRUPT ) -notify_ring (dev, &dev_priv->ring[VECS ]); +notify_ring (dev, ring);if (vcs &GEN8_GT_CONTEXT_SWITCH_INTERRUPT ) -DRM_DEBUG_DRIVER ("TODO: Context switch\n" ); +intel_execlists_handle_ctx_events (ring); }else DRM_ERROR ("The master control interrupt lied (GT3)!\n" ); }drivers/gpu/drm/i915/intel_lrc.c +123
-6@@ -49,6 +49,22 @@#define RING_ELSP (ring) ((ring)->mmio_base+0x230)#define RING_EXECLIST_STATUS (ring) ((ring)->mmio_base+0x234)#define RING_CONTEXT_CONTROL (ring) ((ring)->mmio_base+0x244) +#define RING_CONTEXT_STATUS_BUF (ring) ((ring)->mmio_base+0x370) +#define RING_CONTEXT_STATUS_PTR (ring) ((ring)->mmio_base+0x3a0) + +#define RING_EXECLIST_QFULL (1 << 0x2) +#define RING_EXECLIST1_VALID (1 << 0x3) +#define RING_EXECLIST0_VALID (1 << 0x4) +#define RING_EXECLIST_ACTIVE_STATUS (3 << 0xE) +#define RING_EXECLIST1_ACTIVE (1 << 0x11) +#define RING_EXECLIST0_ACTIVE (1 << 0x12) + +#define GEN8_CTX_STATUS_IDLE_ACTIVE (1 << 0) +#define GEN8_CTX_STATUS_PREEMPTED (1 << 1) +#define GEN8_CTX_STATUS_ELEMENT_SWITCH (1 << 2) +#define GEN8_CTX_STATUS_ACTIVE_IDLE (1 << 3) +#define GEN8_CTX_STATUS_COMPLETE (1 << 4) +#define GEN8_CTX_STATUS_LITE_RESTORE (1 << 15)#define CTX_LRI_HEADER_0 0x01#define CTX_CONTEXT_CONTROL 0x02@@ -147,6 +163,7 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,struct drm_i915_private *dev_priv = ring->dev->dev_private;uint64_t temp =0 ;uint32_t desc[4 ]; +unsigned long flags;/* XXX: You must always write both descriptors in the order below. */ if (ctx_obj1)@@ -160,9 +177,17 @@ static void execlists_elsp_write(struct intel_engine_cs *ring, desc[3 ] = (u32)(temp >>32 ); desc[2 ] = (u32 )temp; -/* Set Force Wakeup bit to prevent GT from entering C6 while -* ELSP writes are in progress */ -gen6_gt_force_wake_get (dev_priv,FORCEWAKE_ALL ); +/* Set Force Wakeup bit to prevent GT from entering C6 while ELSP writes +* are in progress. +* +* The other problem is that we can't just call gen6_gt_force_wake_get() +* because that function calls intel_runtime_pm_get(), which might sleep. +* Instead, we do the runtime_pm_get/put when creating/destroying requests. +*/ +spin_lock_irqsave (&dev_priv->uncore.lock, flags); +if (dev_priv->uncore.forcewake_count++ ==0 ) + dev_priv->uncore.funcs.force_wake_get (dev_priv,FORCEWAKE_ALL ); +spin_unlock_irqrestore (&dev_priv->uncore.lock, flags);I915_WRITE (RING_ELSP (ring), desc[1 ]);I915_WRITE (RING_ELSP (ring), desc[0 ]);@@ -173,7 +198,11 @@ static void execlists_elsp_write(struct intel_engine_cs *ring,/* ELSP is a wo register, so use another nearby reg for posting instead */ POSTING_READ (RING_EXECLIST_STATUS (ring)); -gen6_gt_force_wake_put (dev_priv,FORCEWAKE_ALL ); +/* Release Force Wakeup (see the big comment above). */ +spin_lock_irqsave (&dev_priv->uncore.lock, flags); +if (--dev_priv->uncore.forcewake_count ==0 ) + dev_priv->uncore.funcs.force_wake_put (dev_priv,FORCEWAKE_ALL ); +spin_unlock_irqrestore (&dev_priv->uncore.lock, flags); }static int execlists_ctx_write_tail (struct drm_i915_gem_object *ctx_obj,u32 tail)@@ -221,6 +250,9 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) {struct intel_ctx_submit_request *req0 =NULL , *req1 =NULL ;struct intel_ctx_submit_request *cursor =NULL , *tmp =NULL ; +struct drm_i915_private *dev_priv = ring->dev->dev_private; + +assert_spin_locked (&ring->execlist_lock);if (list_empty (&ring->execlist_queue))return ;@@ -233,8 +265,7 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)/* Same ctx: ignore first request, as second request * will update tail past first request's workload */ list_del (&req0->execlist_link); -i915_gem_context_unreference (req0->ctx); -kfree (req0); +queue_work (dev_priv->wq, &req0->work); req0 = cursor; }else { req1 = cursor;@@ -246,6 +277,89 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) req1? req1->ctx : NULL, req1? req1->tail : 0)); } +static bool execlists_check_remove_request (struct intel_engine_cs *ring, +u32 request_id) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +struct intel_ctx_submit_request *head_req; + +assert_spin_locked (&ring->execlist_lock); + + head_req =list_first_entry_or_null (&ring->execlist_queue, + struct intel_ctx_submit_request, execlist_link); +if (head_req !=NULL ) { +struct drm_i915_gem_object *ctx_obj = + head_req->ctx->engine[ring->id].state; +if (intel_execlists_ctx_id (ctx_obj) == request_id) { +list_del (&head_req->execlist_link); +queue_work (dev_priv->wq, &head_req->work); +return true; + } + } + +return false; +} + +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring) +{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +u32 status_pointer; +u8 read_pointer; +u8 write_pointer; +u32 status; +u32 status_id; +u32 submit_contexts =0 ; + + status_pointer =I915_READ (RING_CONTEXT_STATUS_PTR (ring)); + + read_pointer = ring->next_context_status_buffer; + write_pointer = status_pointer &0x07 ; +if (read_pointer > write_pointer) + write_pointer +=6 ; + +spin_lock (&ring->execlist_lock); + +while (read_pointer < write_pointer) { + read_pointer++; + status =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 ); + status_id =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 +4 ); + +if (status &GEN8_CTX_STATUS_COMPLETE ) { +if (execlists_check_remove_request (ring, status_id)) + submit_contexts++; + } + } + +if (submit_contexts !=0 ) +execlists_context_unqueue (ring); + +spin_unlock (&ring->execlist_lock); + +WARN (submit_contexts >2 ,"More than two context complete events?\n" ); + ring->next_context_status_buffer = write_pointer %6 ; + +I915_WRITE (RING_CONTEXT_STATUS_PTR (ring), + ((u32 )ring->next_context_status_buffer &0x07 ) <<8 ); +} + +static void execlists_free_request_task (struct work_struct *work) +{ +struct intel_ctx_submit_request *req = + container_of(work, struct intel_ctx_submit_request, work); +struct drm_device *dev = req->ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; + +intel_runtime_pm_put (dev_priv); + +mutex_lock (&dev->struct_mutex); +i915_gem_context_unreference (req->ctx); +mutex_unlock (&dev->struct_mutex); + +kfree (req); +} +static int execlists_context_queue (struct intel_engine_cs *ring,struct intel_context *to,u32 tail)@@ -261,6 +375,8 @@ static int execlists_context_queue(struct intel_engine_cs *ring,i915_gem_context_reference (req->ctx); req->ring = ring; req->tail = tail; +INIT_WORK (&req->work, execlists_free_request_task); +intel_runtime_pm_get (dev_priv);spin_lock_irqsave (&ring->execlist_lock, flags);@@ -908,6 +1024,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->execlist_queue);spin_lock_init (&ring->execlist_lock); + ring->next_context_status_buffer =0 ; ret =intel_lr_context_deferred_create (dctx, ring);if (ret)drivers/gpu/drm/i915/intel_lrc.h +3
-0@@ -66,6 +66,9 @@ struct intel_ctx_submit_request {u32 tail;struct list_head execlist_link; + struct work_struct work; }; +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring); +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +1
-0@@ -225,6 +225,7 @@ struct intel_engine_cs {/* Execlists */ spinlock_t execlist_lock;struct list_head execlist_queue; +u8 next_context_status_buffer;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 31/43] drm/i915/bdw: Handle context switch events
In reply to Thomas DanielQuoted 36 lines · Thomas Daniel
Handle all context status events in the context status buffer on every context switch interrupt. We only remove work from the execlist queue after a context status buffer reports that it has completed and we only attempt to schedule new contexts on interrupt when a previously submitted context completes (unless no contexts are queued, which means the GPU is free).
We canot call
intel_runtime_pm_get()in an interrupt (or with a spinlock grabbed, FWIW), because it might sleep, which is not a nice thing to do. Instead, do theruntime_pmget/put together with the create/destroy request, and handle the forcewake get/put directly.Signed-off-by Thomas Daniel <[email protected]>v2: Unreferencing the context when we are freeing the request might free the backing bo, which requires the
struct_mutexto be grabbed, so defer unreferencing and freeing to a bottom half.v3:
- Ack the interrupt inmediately, before trying to handle it (fix for missing interrupts by Bob Beckett <[email protected]>).
- Update the Context Status Buffer Read Pointer, just in case (spotted by Damien Lespiau).v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call
intel_runtime_pm_get()in an interrupt", as suggested by Daniel.Signed-off-by Oscar Mateo <[email protected]>drivers/gpu/drm/i915/intel_lrc.c +5
-0+static void execlists_free_request_task (struct work_struct *work) +{ +struct intel_ctx_submit_request *req = + container_of(work, struct intel_ctx_submit_request, work); +struct drm_device *dev = req->ring->dev;
drivers/gpu/drm/i915/intel_lrc.c static void execlists_context_unqueue(struct intel_engine_cs *ring) · line 361
Quoted 10 lines
drivers/gpu/drm/i915/intel_lrc.c +10
-0+struct drm_i915_private *dev_priv = dev->dev_private; + +intel_runtime_pm_put (dev_priv); + +mutex_lock (&dev->struct_mutex); +i915_gem_context_unreference (req->ctx); +mutex_unlock (&dev->struct_mutex); + +kfree (req); +}
Latching a work item simply for the unference of the context looks very fishy. The context really can't possible disappear before the last request on it has completed, since the request already holds a reference.
That you have this additional reference here makes it look a bit like the relationship and lifetime rules for the execlist queue item is misshapen.
I'd have expected:
- A given execlist queue item is responsible for a list of requests (one or more)
- Each request already holds onto the context.
The other thing that's strange here is the runtime pm handling. We already keep the device awake as long as it's busy, so I wonder why exactly we need this here in addition.
In any case these kind of cleanup tasks are imo better done in the retire request handler that we already have.
Imo needs some cleanup.
-Daniel
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
Re: [PATCH 31/43] drm/i915/bdw: Handle context switch events
In reply to Thomas DanielQuoted 24 lines · Thomas Daniel
Handle all context status events in the context status buffer on every context switch interrupt. We only remove work from the execlist queue after a context status buffer reports that it has completed and we only attempt to schedule new contexts on interrupt when a previously submitted context completes (unless no contexts are queued, which means the GPU is free).
We canot call
intel_runtime_pm_get()in an interrupt (or with a spinlock grabbed, FWIW), because it might sleep, which is not a nice thing to do. Instead, do theruntime_pmget/put together with the create/destroy request, and handle the forcewake get/put directly.Signed-off-by Thomas Daniel <[email protected]>v2: Unreferencing the context when we are freeing the request might free the backing bo, which requires the
struct_mutexto be grabbed, so defer unreferencing and freeing to a bottom half.v3:
- Ack the interrupt inmediately, before trying to handle it (fix for missing interrupts by Bob Beckett <[email protected]>).
- Update the Context Status Buffer Read Pointer, just in case (spotted by Damien Lespiau).
Quoted 6 lines
v4: New namespace and multiple rebase changes.
v5: Squash with "drm/i915/bdw: Do not call
intel_runtime_pm_get()in an interrupt", as suggested by Daniel.Signed-off-by Oscar Mateo <[email protected]>
One more ...
Quoted 1 line
+void
intel_execlists_handle_ctx_events(struct intel_engine_cs *ring)
Please rename this to intel_execlist_ctx_events_irq_handler or similar for consistency with all the other irq handler functions in a follow-up patch. That kind of consistency helps a lot when reviewing the locking of irq-save spinlocks.
-Daniel
Quoted 112 lines
drivers/gpu/drm/i915/intel_lrc.c +62
-0+{ +struct drm_i915_private *dev_priv = ring->dev->dev_private; +u32 status_pointer; +u8 read_pointer; +u8 write_pointer; +u32 status; +u32 status_id; +u32 submit_contexts =0 ; + + status_pointer =I915_READ (RING_CONTEXT_STATUS_PTR (ring)); + + read_pointer = ring->next_context_status_buffer; + write_pointer = status_pointer &0x07 ; +if (read_pointer > write_pointer) + write_pointer +=6 ; + +spin_lock (&ring->execlist_lock); + +while (read_pointer < write_pointer) { + read_pointer++; + status =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 ); + status_id =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + + (read_pointer %6 ) *8 +4 ); + +if (status &GEN8_CTX_STATUS_COMPLETE ) { +if (execlists_check_remove_request (ring, status_id)) + submit_contexts++; + } + } + +if (submit_contexts !=0 ) +execlists_context_unqueue (ring); + +spin_unlock (&ring->execlist_lock); + +WARN (submit_contexts >2 ,"More than two context complete events?\n" ); + ring->next_context_status_buffer = write_pointer %6 ; + +I915_WRITE (RING_CONTEXT_STATUS_PTR (ring), + ((u32 )ring->next_context_status_buffer &0x07 ) <<8 ); +} + +static void execlists_free_request_task (struct work_struct *work) +{ +struct intel_ctx_submit_request *req = + container_of(work, struct intel_ctx_submit_request, work); +struct drm_device *dev = req->ring->dev; +struct drm_i915_private *dev_priv = dev->dev_private; + +intel_runtime_pm_put (dev_priv); + +mutex_lock (&dev->struct_mutex); +i915_gem_context_unreference (req->ctx); +mutex_unlock (&dev->struct_mutex); + +kfree (req); +} +static int execlists_context_queue (struct intel_engine_cs *ring,struct intel_context *to,u32 tail)@@ -261,6 +375,8 @@ static int execlists_context_queue(struct intel_engine_cs *ring,i915_gem_context_reference (req->ctx); req->ring = ring; req->tail = tail; +INIT_WORK (&req->work, execlists_free_request_task); +intel_runtime_pm_get (dev_priv);spin_lock_irqsave (&ring->execlist_lock, flags);@@ -908,6 +1024,7 @@ static int logical_ring_init(struct drm_device *dev, struct intel_engine_cs *rinINIT_LIST_HEAD (&ring->execlist_queue);spin_lock_init (&ring->execlist_lock); + ring->next_context_status_buffer =0 ; ret =intel_lr_context_deferred_create (dctx, ring);if (ret)drivers/gpu/drm/i915/intel_lrc.h +3
-0@@ -66,6 +66,9 @@ struct intel_ctx_submit_request {u32 tail;struct list_head execlist_link; + struct work_struct work; }; +void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring); +#endif /* _INTEL_LRC_H_ */ drivers/gpu/drm/i915/intel_ringbuffer.h +1
-0@@ -225,6 +225,7 @@ struct intel_engine_cs {/* Execlists */ spinlock_t execlist_lock;struct list_head execlist_queue; +u8 next_context_status_buffer;u32 irq_keep_mask;/* bitmask for interrupts that should not be masked */ int (*emit_request)(struct intel_ringbuffer *ringbuf); int (*emit_flush)(struct intel_ringbuffer *ringbuf,Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 32/43 drm/i915/bdw: Avoid non-lite-restore preemptions
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
In the current Execlists feeding mechanism, full preemption is not supported yet: only lite-restores are allowed (this is: the GPU simply samples a new tail pointer for the context currently in execution).
But we have identified an scenario in which a full preemption occurs:
1) We submit two contexts for execution (A & B).
2) The GPU finishes with the first one (A), switches to the second one
(B) and informs us.
3) We submit B again (hoping to cause a lite restore) together with C, but in the time we spend writing to the ELSP, the GPU finishes B.
4) The GPU start executing B again (since we told it so).
5) We receive a B finished interrupt and, mistakenly, we submit C (again) and D, causing a full preemption of B.
The race is avoided by keeping track of how many times a context has been submitted to the hardware and by better discriminating the received context switch interrupts: in the example, when we have submitted B twice, we won´t submit C and D as soon as we receive the notification that B is completed because we were expecting to get a LITE_RESTORE and we didn´t, so we know a second completion will be received shortly.
Without this explicit checking, somehow, the batch buffer execution order gets messed with. This can be verified with the IGT test I sent together with the series. I don´t know the exact mechanism by which the pre-emption messes with the execution order but, since other people is working on the Scheduler
+ Preemption on Execlists, I didn´t try to fix it. In these series, only Lite Restores are supported (other kind of preemptions WARN).
v2: elsp_submitted belongs in the new intel_ctx_submit_request. Several rebase changes.
v3: Clarify how the race is avoided, as requested by Daniel.
--- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_lrc.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +24 -4
@@ -264,6 +264,7 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)else if (req0->ctx == cursor->ctx) {/* Same ctx: ignore first request, as second request * will update tail past first request's workload */ + cursor->elsp_submitted = req0->elsp_submitted;list_del (&req0->execlist_link);queue_work (dev_priv->wq, &req0->work); req0 = cursor;
@@ -273,8 +274,14 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) } } +WARN_ON (req1 && req1->elsp_submitted); +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, req1? req1->ctx :NULL , req1? req1->tail :0 )); + + req0->elsp_submitted++; +if (req1) + req1->elsp_submitted++; } static bool execlists_check_remove_request(struct intel_engine_cs *ring,
@@ -291,9 +298,13 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring,struct drm_i915_gem_object *ctx_obj = head_req->ctx->engine[ring->id].state;if (intel_execlists_ctx_id (ctx_obj) == request_id) { -list_del (&head_req->execlist_link); -queue_work (dev_priv->wq, &head_req->work); -return true; +WARN (head_req->elsp_submitted ==0 , +"Never submitted head request\n" ); +if (--head_req->elsp_submitted <=0 ) { +list_del (&head_req->execlist_link); +queue_work (dev_priv->wq, &head_req->work); +return true; + } } }
@@ -326,7 +337,16 @@ void intel_execlists_handle_ctx_events(struct intel_engine_cs *ring) status_id =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + (read_pointer %6 ) *8 +4 ); -if (status &GEN8_CTX_STATUS_COMPLETE ) { +if (status &GEN8_CTX_STATUS_PREEMPTED ) { +if (status &GEN8_CTX_STATUS_LITE_RESTORE ) { +if (execlists_check_remove_request (ring, status_id)) +WARN (1 ,"Lite Restored request removed from queue\n" ); + }else +WARN (1 ,"Preemption without Lite Restore\n" ); + } + +if ((status &GEN8_CTX_STATUS_ACTIVE_IDLE ) || + (status &GEN8_CTX_STATUS_ELEMENT_SWITCH )) {if (execlists_check_remove_request (ring, status_id)) submit_contexts++; }
drivers/gpu/drm/i915/intel_lrc.h +2 -0
@@ -67,6 +67,8 @@ struct intel_ctx_submit_request {struct list_head execlist_link;struct work_struct work; + +int elsp_submitted; };void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring);
Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Re: [PATCH 32/43] drm/i915/bdw: Avoid non-lite-restore preemptions
Quoted 24 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
In the current Execlists feeding mechanism, full preemption is not supported yet: only lite-restores are allowed (this is: the GPU simply samples a new tail pointer for the context currently in execution).
But we have identified an scenario in which a full preemption occurs:
1) We submit two contexts for execution (A & B).
2) The GPU finishes with the first one (A), switches to the second one
(B) and informs us.
3) We submit B again (hoping to cause a lite restore) together with C, but in the time we spend writing to the ELSP, the GPU finishes B.
4) The GPU start executing B again (since we told it so).
5) We receive a B finished interrupt and, mistakenly, we submit C (again) and D, causing a full preemption of B.The race is avoided by keeping track of how many times a context has been submitted to the hardware and by better discriminating the received context switch interrupts: in the example, when we have submitted B twice, we won´t submit C and D as soon as we receive the notification that B is completed because we were expecting to get a
LITE_RESTOREand we didn´t, so we know a second completion will be received shortly.
Quoted 6 lines
Without this explicit checking, somehow, the batch buffer execution order gets messed with. This can be verified with the IGT test I sent together with the series. I don´t know the exact mechanism by which the pre-emption messes with the execution order but, since other people is working on the Scheduler
+ Preemption on Execlists, I didn´t try to fix it. In these series, only Lite Restores are supported (other kind of preemptions WARN).
Where's this igt patch? The kernel patch here is at least missing the
Testcase: igt/foo
tag. Please supply.
-Daniel
Quoted 94 lines
v2:
elsp_submittedbelongs in the newintel_ctx_submit_request. Several rebase changes.v3: Clarify how the race is avoided, as requested by Daniel.
Signed-off-by Oscar Mateo <[email protected]>--- drivers/gpu/drm/i915/intel_lrc.c | 28 ++++++++++++++++++++++++---- drivers/gpu/drm/i915/intel_lrc.h | 2 ++ 2 files changed, 26 insertions(+), 4 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +24
-4@@ -264,6 +264,7 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)else if (req0->ctx == cursor->ctx) {/* Same ctx: ignore first request, as second request * will update tail past first request's workload */ + cursor->elsp_submitted = req0->elsp_submitted;list_del (&req0->execlist_link);queue_work (dev_priv->wq, &req0->work); req0 = cursor;@@ -273,8 +274,14 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) } } +WARN_ON (req1 && req1->elsp_submitted); +BUG_ON (execlists_submit_context (ring, req0->ctx, req0->tail, req1? req1->ctx :NULL , req1? req1->tail :0 )); + + req0->elsp_submitted++; +if (req1) + req1->elsp_submitted++; } static bool execlists_check_remove_request(struct intel_engine_cs *ring,@@ -291,9 +298,13 @@ static bool execlists_check_remove_request(struct intel_engine_cs *ring,struct drm_i915_gem_object *ctx_obj = head_req->ctx->engine[ring->id].state;if (intel_execlists_ctx_id (ctx_obj) == request_id) { -list_del (&head_req->execlist_link); -queue_work (dev_priv->wq, &head_req->work); -return true; +WARN (head_req->elsp_submitted ==0 , +"Never submitted head request\n" ); +if (--head_req->elsp_submitted <=0 ) { +list_del (&head_req->execlist_link); +queue_work (dev_priv->wq, &head_req->work); +return true; + } } }@@ -326,7 +337,16 @@ void intel_execlists_handle_ctx_events(struct intel_engine_cs *ring) status_id =I915_READ (RING_CONTEXT_STATUS_BUF (ring) + (read_pointer %6 ) *8 +4 ); -if (status &GEN8_CTX_STATUS_COMPLETE ) { +if (status &GEN8_CTX_STATUS_PREEMPTED ) { +if (status &GEN8_CTX_STATUS_LITE_RESTORE ) { +if (execlists_check_remove_request (ring, status_id)) +WARN (1 ,"Lite Restored request removed from queue\n" ); + }else +WARN (1 ,"Preemption without Lite Restore\n" ); + } + +if ((status &GEN8_CTX_STATUS_ACTIVE_IDLE ) || + (status &GEN8_CTX_STATUS_ELEMENT_SWITCH )) {if (execlists_check_remove_request (ring, status_id)) submit_contexts++; }drivers/gpu/drm/i915/intel_lrc.h +2
-0@@ -67,6 +67,8 @@ struct intel_ctx_submit_request {struct list_head execlist_link;struct work_struct work; + +int elsp_submitted; };void intel_execlists_handle_ctx_events (struct intel_engine_cs *ring);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch
PATCH 33/43 drm/i915/bdw: Help out the ctx switch interrupt handler
In reply to Thomas DanielFrom: Oscar Mateo <[email protected]>
If we receive a storm of requests for the same context (see gem_storedw_loop_*) we might end up iterating over too many elements in interrupt time, looking for contexts to squash together. Instead, share the burden by giving more intelligence to the queue function. At most, the interrupt will iterate over three elements.
--- drivers/gpu/drm/i915/intel_lrc.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/intel_lrc.c +22 -4
@@ -384,9 +384,10 @@ static int execlists_context_queue(struct intel_engine_cs *ring, struct intel_context *to, u32 tail) { -struct intel_ctx_submit_request *req =NULL ; +struct drm_i915_private *dev_priv = ring->dev->dev_private; +struct intel_ctx_submit_request *req =NULL , *cursor;unsigned long flags; -bool was_empty; +int num_elements =0 ; req =kzalloc (sizeof (*req),GFP_KERNEL );if (req ==NULL )
@@ -400,9 +401,26 @@ static int execlists_context_queue(struct intel_engine_cs *ring,spin_lock_irqsave (&ring->execlist_lock, flags); - was_empty =list_empty (&ring->execlist_queue); +list_for_each_entry (cursor, &ring->execlist_queue, execlist_link) +if (++num_elements >2 ) +break ; + +if (num_elements >2 ) { +struct intel_ctx_submit_request *tail_req; + + tail_req =list_last_entry (&ring->execlist_queue, + struct intel_ctx_submit_request, + execlist_link); +if (to == tail_req->ctx) { +WARN (tail_req->elsp_submitted !=0 , +"More than 2 already-submitted reqs queued\n" ); +list_del (&tail_req->execlist_link); +queue_work (dev_priv->wq, &tail_req->work); + } + } +list_add_tail (&req->execlist_link, &ring->execlist_queue); -if (was_empty) +if (num_elements ==0 )execlists_context_unqueue (ring);spin_unlock_irqrestore (&ring->execlist_lock, flags);
Signature · 1 line
1.7.9.5
Re: [PATCH 33/43] drm/i915/bdw: Help out the ctx switch interrupt handler
Quoted 9 lines · Thomas Daniel
From: Oscar Mateo <[email protected]>
If we receive a storm of requests for the same context (see gem_storedw_loop_*) we might end up iterating over too many elements in interrupt time, looking for contexts to squash together. Instead, share the burden by giving more intelligence to the queue function. At most, the interrupt will iterate over three elements.
Signed-off-by Oscar Mateo <[email protected]>
I'll continue merging after this patch tomorrow.
-Daniel
Quoted 57 lines
--- drivers/gpu/drm/i915/intel_lrc.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)drivers/gpu/drm/i915/intel_lrc.c +22
-4@@ -384,9 +384,10 @@ static int execlists_context_queue(struct intel_engine_cs *ring, struct intel_context *to, u32 tail) { -struct intel_ctx_submit_request *req =NULL ; +struct drm_i915_private *dev_priv = ring->dev->dev_private; +struct intel_ctx_submit_request *req =NULL , *cursor;unsigned long flags; -bool was_empty; +int num_elements =0 ; req =kzalloc (sizeof (*req),GFP_KERNEL );if (req ==NULL )@@ -400,9 +401,26 @@ static int execlists_context_queue(struct intel_engine_cs *ring,spin_lock_irqsave (&ring->execlist_lock, flags); - was_empty =list_empty (&ring->execlist_queue); +list_for_each_entry (cursor, &ring->execlist_queue, execlist_link) +if (++num_elements >2 ) +break ; + +if (num_elements >2 ) { +struct intel_ctx_submit_request *tail_req; + + tail_req =list_last_entry (&ring->execlist_queue, + struct intel_ctx_submit_request, + execlist_link); +if (to == tail_req->ctx) { +WARN (tail_req->elsp_submitted !=0 , +"More than 2 already-submitted reqs queued\n" ); +list_del (&tail_req->execlist_link); +queue_work (dev_priv->wq, &tail_req->work); + } + } +list_add_tail (&req->execlist_link, &ring->execlist_queue); -if (was_empty) +if (num_elements ==0 )execlists_context_unqueue (ring);spin_unlock_irqrestore (&ring->execlist_lock, flags);Signature · 6 lines
1.7.9.5 _______________________________________________ Intel-gfx mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter Software Engineer, Intel Corporation +41 (0) 79 365 57 48 - http://blog.ffwll.ch