Re: [Intel-gfx] [PATCH 6/7] drm/i915/execlists: Flush pending preemption events during reset

2018-05-16 Thread Tvrtko Ursulin


On 16/05/2018 16:12, Chris Wilson wrote:

Catch up with the inflight CSB events, after disabling the tasklet
before deciding which request was truly guilty of hanging the GPU.

Signed-off-by: Chris Wilson 
Cc: Michał Winiarski 
CC: Michel Thierry 
Cc: Jeff McGee 
Cc: Tvrtko Ursulin 
---
  drivers/gpu/drm/i915/intel_lrc.c | 36 +++-
  1 file changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e70d8d624899..3b889bb4352a 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1843,6 +1843,7 @@ static struct i915_request *
  execlists_reset_prepare(struct intel_engine_cs *engine)
  {
struct intel_engine_execlists * const execlists = &engine->execlists;
+   struct i915_request *request, *active;
  
  	GEM_TRACE("%s\n", engine->name);
  
@@ -1857,7 +1858,40 @@ execlists_reset_prepare(struct intel_engine_cs *engine)

 */
__tasklet_disable_sync_once(&execlists->tasklet);
  
-	return i915_gem_find_active_request(engine);

+   /*
+* We want to flush the pending context switches, having disabled
+* the tasklet above, we can assume exclusive access to the execlists.
+* For this allows us to catch up with an inflight preemption event,
+* and avoid blaming an innocent request if the stall was due to the
+* preemption itself.
+*/
+   if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted))
+   process_csb(engine);
+
+   /*
+* The last active request can then be no later than the last request
+* now in ELSP[0]. So search backwards from there, so that if the GPU
+* has advanced beyond the last CSB update, it will be pardoned.
+*/
+   active = NULL;
+   request = port_request(execlists->port);
+   if (request) {
+   unsigned long flags;
+
+   spin_lock_irqsave(&engine->timeline.lock, flags);
+   list_for_each_entry_from_reverse(request,
+&engine->timeline.requests,
+link) {
+   if (__i915_request_completed(request,
+request->global_seqno))
+   break;
+
+   active = request;
+   }
+   spin_unlock_irqrestore(&engine->timeline.lock, flags);
+   }
+
+   return active;
  }
  
  static void execlists_reset(struct intel_engine_cs *engine,




Sounds sensible to me, just don't ask me to describe preemption and 
reset flow where things go bad without it. :)


Reviewed-by: Tvrtko Ursulin 

Regards,

Tvrtko
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 6/7] drm/i915/execlists: Flush pending preemption events during reset

2018-05-16 Thread Chris Wilson
Quoting Tvrtko Ursulin (2018-05-16 15:24:33)
> > + /*
> > +  * The last active request can then be no later than the last request
> > +  * now in ELSP[0]. So search backwards from there, so that if the GPU
> > +  * has advanced beyond the last CSB update, it will be pardoned.
> > +  */
> > + active = NULL;
> > + request = port_request(execlists->port);
> > + if (request) {
> 
> Assignment to request is for nothing it seems.
> 
> > + unsigned long flags;
> > +
> > + spin_lock_irqsave(&engine->timeline.lock, flags);
> > + list_for_each_entry_from_reverse(request,

It's a 'from' list_for_each variant.

> > +  &engine->timeline.requests,
> > +  link) {
> > + if (__i915_request_completed(request,
> > +  request->global_seqno))
> > + break;
> > +
> > + active = request;
> > + }
> > + spin_unlock_irqrestore(&engine->timeline.lock, flags);
> > + }
> > +
> > + return active;
> >   }
> >   
> >   static void execlists_reset(struct intel_engine_cs *engine,
> > 
> 
> No other complaints and I could be bribed to look past the request to 
> split it. :)

Is not clearing the backlog so we can get onto features not enough
incentive? Chocolate? Beer? Chocolate-flavoured beer?
-Chris
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 6/7] drm/i915/execlists: Flush pending preemption events during reset

2018-05-16 Thread Tvrtko Ursulin


On 16/05/2018 07:47, Chris Wilson wrote:

Catch up with the inflight CSB events, after disabling the tasklet
before deciding which request was truly guilty of hanging the GPU.

v2: Restore checking of use_csb_mmio on every loop, don't forget old
vgpu.

Signed-off-by: Chris Wilson 
Cc: Michał Winiarski 
CC: Michel Thierry 
Cc: Jeff McGee 
---
  drivers/gpu/drm/i915/intel_lrc.c | 127 +--
  1 file changed, 87 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7afe52fa615d..cae10ebf9432 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -957,34 +957,14 @@ static void execlists_cancel_requests(struct 
intel_engine_cs *engine)
local_irq_restore(flags);
  }
  
-/*

- * Check the unread Context Status Buffers and manage the submission of new
- * contexts to the ELSP accordingly.
- */
-static void execlists_submission_tasklet(unsigned long data)
+static void process_csb(struct intel_engine_cs *engine)
  {
-   struct intel_engine_cs * const engine = (struct intel_engine_cs *)data;
struct intel_engine_execlists * const execlists = &engine->execlists;
struct execlist_port *port = execlists->port;
-   struct drm_i915_private *dev_priv = engine->i915;
+   struct drm_i915_private *i915 = engine->i915;
bool fw = false;
  
-	/*

-* We can skip acquiring intel_runtime_pm_get() here as it was taken
-* on our behalf by the request (see i915_gem_mark_busy()) and it will
-* not be relinquished until the device is idle (see
-* i915_gem_idle_work_handler()). As a precaution, we make sure
-* that all ELSP are drained i.e. we have processed the CSB,
-* before allowing ourselves to idle and calling intel_runtime_pm_put().
-*/
-   GEM_BUG_ON(!dev_priv->gt.awake);
-
-   /*
-* Prefer doing test_and_clear_bit() as a two stage operation to avoid
-* imposing the cost of a locked atomic transaction when submitting a
-* new request (outside of the context-switch interrupt).
-*/
-   while (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) {
+   do {
/* The HWSP contains a (cacheable) mirror of the CSB */
const u32 *buf =
&engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX];
@@ -992,28 +972,27 @@ static void execlists_submission_tasklet(unsigned long 
data)
  
  		if (unlikely(execlists->csb_use_mmio)) {

buf = (u32 * __force)
-   (dev_priv->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)));
-   execlists->csb_head = -1; /* force mmio read of CSB 
ptrs */
+   (i915->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)));
+   execlists->csb_head = -1; /* force mmio read of CSB */
}
  
  		/* Clear before reading to catch new interrupts */

clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted);
smp_mb__after_atomic();
  
-		if (unlikely(execlists->csb_head == -1)) { /* following a reset */

+   if (unlikely(execlists->csb_head == -1)) { /* after a reset */
if (!fw) {
-   intel_uncore_forcewake_get(dev_priv,
-  
execlists->fw_domains);
+   intel_uncore_forcewake_get(i915, 
execlists->fw_domains);
fw = true;
}
  
-			head = readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)));

+   head = readl(i915->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)));
tail = GEN8_CSB_WRITE_PTR(head);
head = GEN8_CSB_READ_PTR(head);
execlists->csb_head = head;
} else {
const int write_idx =
-   intel_hws_csb_write_index(dev_priv) -
+   intel_hws_csb_write_index(i915) -
I915_HWS_CSB_BUF0_INDEX;
  
  			head = execlists->csb_head;

@@ -1022,8 +1001,8 @@ static void execlists_submission_tasklet(unsigned long 
data)
}
GEM_TRACE("%s cs-irq head=%d [%d%s], tail=%d [%d%s]\n",
  engine->name,
- head, GEN8_CSB_READ_PTR(readl(dev_priv->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine, fw ? "" : "?",
- tail, GEN8_CSB_WRITE_PTR(readl(dev_priv->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine, fw ? "" : "?");
+ head, GEN8_CSB_READ_PTR(readl(i915->regs + 
i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine, fw ? "" : "?",
+