Re: [Intel-gfx] [V2 PATCH 2/2] drm/i915: start adding dp mst audio

2015-11-23 Thread Libin Yang



Best Regards,
Libin

On 11/23/2015 11:01 PM, Ander Conselvan De Oliveira wrote:

On Mon, 2015-11-23 at 14:04 +, Zanoni, Paulo R wrote:

Em Qui, 2015-11-19 às 13:07 +0200, Ander Conselvan De Oliveira
escreveu:

(Cc'ing Paulo for the audio power domain question)

On Wed, 2015-11-11 at 13:33 +0800, libin.y...@linux.intel.com wrote:

From: Libin Yang 

This patch adds support for DP MST audio in i915.

Enable audio codec when DP MST is enabled if has_audio flag is set.
Disable audio codec when DP MST is disabled if has_audio flag is
set.

Signed-off-by: Libin Yang 
Signed-off-by: Dave Airlie 
---
  drivers/gpu/drm/i915/i915_debugfs.c | 14 ++
  drivers/gpu/drm/i915/intel_audio.c  |  9 ++---
  drivers/gpu/drm/i915/intel_dp_mst.c | 25 +
  3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
b/drivers/gpu/drm/i915/i915_debugfs.c
index 5659d4c..38c7a5d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2873,6 +2873,18 @@ static void intel_dp_info(struct seq_file
*m,
intel_panel_info(m, &intel_connector->panel);
  }

+static void intel_dp_mst_info(struct seq_file *m,
+ struct intel_connector *intel_connector)
+{
+   struct intel_encoder *intel_encoder = intel_connector-

encoder;

+   struct intel_dp_mst_encoder *intel_mst =
+   enc_to_mst(&intel_encoder->base);
+   struct intel_digital_port *intel_dig_port = intel_mst-

primary;

+   struct intel_dp *intel_dp = &intel_dig_port->dp;
+
+   seq_printf(m, "\taudio support: %s\n",
drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector-

port) ? "yes" :

"no");


Too much going on in just one line. You can replace the ternary
operator with
yesno(). You could also add a has_audio bool:

bool has_audio = drm_dp_mst_port_has_audio(...);
seq_printf(..., yesno(has_audio));



+}
+
  static void intel_hdmi_info(struct seq_file *m,
struct intel_connector
*intel_connector)
  {
@@ -2916,6 +2928,8 @@ static void intel_connector_info(struct
seq_file *m,
intel_hdmi_info(m, intel_connector);
else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
intel_lvds_info(m, intel_connector);
+   else if (intel_encoder->type ==
INTEL_OUTPUT_DP_MST)
+   intel_dp_mst_info(m, intel_connector);
}

seq_printf(m, "\tmodes:\n");
diff --git a/drivers/gpu/drm/i915/intel_audio.c
b/drivers/gpu/drm/i915/intel_audio.c
index 63d4706..07b2aa6 100644
--- a/drivers/gpu/drm/i915/intel_audio.c
+++ b/drivers/gpu/drm/i915/intel_audio.c
@@ -262,7 +262,8 @@ static void hsw_audio_codec_disable(struct
intel_encoder
*encoder)
tmp |= AUD_CONFIG_N_PROG_ENABLE;
tmp &= ~AUD_CONFIG_UPPER_N_MASK;
tmp &= ~AUD_CONFIG_LOWER_N_MASK;
-   if (intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DISPLAYPORT))
+   if (intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DISPLAYPORT) ||
+   intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DP_MST))


The second line should be aligned with '('.


tmp |= AUD_CONFIG_N_VALUE_INDEX;
I915_WRITE(HSW_AUD_CFG(pipe), tmp);

@@ -478,7 +479,8 @@ static void ilk_audio_codec_enable(struct
drm_connector
*connector,
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
-   if (intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DISPLAYPORT))
+   if (intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DISPLAYPORT) ||
+   intel_pipe_has_type(intel_crtc,
INTEL_OUTPUT_DP_MST))


Same here.


tmp |= AUD_CONFIG_N_VALUE_INDEX;
else
tmp |=
audio_config_hdmi_pixel_clock(adjusted_mode);
@@ -516,7 +518,8 @@ void intel_audio_codec_enable(struct
intel_encoder
*intel_encoder)

/* ELD Conn_Type */
connector->eld[5] &= ~(3 << 2);
-   if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
+   if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
+   intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
connector->eld[5] |= (1 << 2);


And here.



connector->eld[6] = drm_av_sync_delay(connector,
adjusted_mode) / 2;
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c
b/drivers/gpu/drm/i915/intel_dp_mst.c
index 0639275..4ded0fb 100644
--- a/drivers/gpu/drm/i915/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/intel_dp_mst.c
@@ -78,6 +78,8 @@ static bool intel_dp_mst_compute_config(struct
intel_encoder
*encoder,
return false;
}

+   if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found-

port))

+   pipe_config->has_audio = true;
mst_pbn = drm_dp_calc_pbn_mode(adjusted_mode->crtc_clock,
bpp);

pipe_config->pbn = mst_pbn;
@@ -102,6 +104,11 @@ static void intel_mst_disable_dp(struct
intel_encoder
*e

Re: [Intel-gfx] [PATCH v4 3/5] drm: Add dispatcher and driver identification for DRM

2015-11-23 Thread Dmitry V. Levin
On Fri, Sep 11, 2015 at 12:57:06PM +0200, Patrik Jakobsson wrote:
> On Tue, Sep 08, 2015 at 03:36:25AM +0300, Dmitry V. Levin wrote:
> > On Mon, Aug 24, 2015 at 02:42:48PM +0200, Patrik Jakobsson wrote:
[...]
> > > +static char *drm_get_driver_name(struct tcb *tcp)
> > > +{
> > > + char path[PATH_MAX];
> > > + char link[PATH_MAX];
> > > + int ret;
> > > +
> > > + if (getfdpath(tcp, tcp->u_arg[0], path, PATH_MAX - 1) < 0)
> > > + return NULL;
> > > +
> > > + snprintf(link, PATH_MAX, "/sys/class/drm/%s/device/driver",
> > > +  basename(path));
> > 
> > if (snprintf(link, sizeof(link), ...) >= sizeof(link))
> > return NULL;
> > 
> 
> According to manpage snprintf never returns more than the specified size - 1.

Really?

"The functions snprintf() and vsnprintf() do not write more than size
bytes (including the terminating null byte ('\0')).  If the output was
truncated due to this limit, then the return value is the number of
characters (excluding the terminating null byte) which would have been
written to the final string if enough space had been available.  Thus,
a return value of size or more means that the output was truncated."


-- 
ldv


pgpGbjcYBUQdC.pgp
Description: PGP signature
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH v4 2/5] drm: Add private data field to trace control block

2015-11-23 Thread Dmitry V. Levin
On Mon, Sep 07, 2015 at 08:23:57PM +0200, Patrik Jakobsson wrote:
> On Mon, Sep 7, 2015 at 6:51 PM, Dmitry V. Levin wrote:
> > On Mon, Aug 31, 2015 at 02:37:07PM +0200, Patrik Jakobsson wrote:
> > [...]
> >> Here's my take on it (I assume it needs some discussion):
> >>
> >> int
> >> set_tcb_priv_data(struct tcb *tcp, void *priv_data)
> >> {
> >>   /* A free callback is required before setting private data and 
> >> private
> >>* data must be set back to NULL before being set again.
> >>*/
> >
> > I think a single function initializing both _priv_data and _free_priv_data
> > would suffice:
> >
> > int
> > set_tcb_priv_data(struct tcb *tcp, void *priv_data,
> >   void (*free_priv_data)(void *))
> > {
> > if (tcp->_priv_data)
> > return -1;
> >
> > tcp->_free_priv_data = free_priv_data;
> > tcp->_priv_data = priv_data;
> >
> > return 0;
> > }
> 
> Sure, and since they always come in a pairs it might be even better. If it 
> turns
> out we need it split up it is easily done later.

The discussion seems to be stalled.
Patrik, would you like to prepare a patch?


-- 
ldv


pgpJLCZWgilyc.pgp
Description: PGP signature
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Also disable PSR on Sink when disabling it on Source.

2015-11-23 Thread Jindal, Sonika
Reviewed-by: Sonika Jindal 

-Original Message-
From: Vivi, Rodrigo 
Sent: Tuesday, November 24, 2015 3:50 AM
To: intel-gfx@lists.freedesktop.org
Cc: Vivi, Rodrigo; Jindal, Sonika
Subject: [PATCH] drm/i915: Also disable PSR on Sink when disabling it on Source.

It is not a bad idea to disable the PSR feature on Sink when we are disabling 
on the Source.

v2: Move dpcd write inside mutex protected area as suggested by Sonika.

Cc: Sonika Jindal 
Suggested-by: Sonika Jindal 
Signed-off-by: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/intel_psr.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 2b2f84d..3bbb270 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -518,11 +518,15 @@ void intel_psr_disable(struct intel_dp *intel_dp)
return;
}
 
+   /* Disable PSR on Source */
if (HAS_DDI(dev))
hsw_psr_disable(intel_dp);
else
vlv_psr_disable(intel_dp);
 
+   /* Disable PSR on Sink */
+   drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+
dev_priv->psr.enabled = NULL;
mutex_unlock(&dev_priv->psr.lock);
 
--
2.4.3

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


Re: [Intel-gfx] [PATCH] drm/i915: Disable primary plane if we fail to reconstruct BIOS fb

2015-11-23 Thread Matt Roper
On Mon, Nov 23, 2015 at 04:53:55PM +, Chris Wilson wrote:
> On Mon, Nov 23, 2015 at 08:48:32AM -0800, Matt Roper wrote:
> > If we fail to reconstruct the BIOS fb (e.g., because the FB is too
> > large), we'll be left with plane state that indicates the primary plane
> > is visible yet has a NULL fb.  This mismatch causes problems later on
> > (e.g., for the watermark code).  Since we've failed to reconstruct the
> > BIOS FB, the best solution is to just disable the primary plane and
> > pretend the BIOS never had it enabled.
> > 
> > Cc: Daniel Vetter 
> > Cc: Ville Syrjälä 
> > Signed-off-by: Matt Roper 
> 
> There are a bunch of bugzillas open about this as it is a regression
> from about 3.2.
> -Chris
> 

Do you happen to know any of the bug ID's off the top of your head (or
keywords to look for)?  I skimmed through the bug list, but the only one
that jumped out at me as possibly related is

https://bugs.freedesktop.org/show_bug.cgi?id=91751
("Display still active even though primary plane is disabled and kills
the GPU")

Thanks!


Matt


> -- 
> Chris Wilson, Intel Open Source Technology Centre

-- 
Matt Roper
Graphics Software Engineer
IoTG Platform Enabling & Development
Intel Corporation
(916) 356-2795
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Try to fix MST for SKL

2015-11-23 Thread Bish, Jim
On Thu, 2015-11-19 at 22:28 +0100, Kenneth Johansson wrote:
> On 2015-11-10 21:15, Jesse Barnes wrote:
> > On 08/17/2015 08:46 AM, ville.syrj...@linux.intel.com wrote:
> > > From: Ville Syrjälä 
> > > 
> > > Set up the DDI->PLL mapping on SKL also for MST links. Might help
> > > make
> > > MST operational on SKL.
> > > 
> > > Cc: Maarten Lankhorst 
> > > Signed-off-by: Ville Syrjälä 
> > > ---
> > >   drivers/gpu/drm/i915/intel_ddi.c| 49 ++
> > > ---
> > >   drivers/gpu/drm/i915/intel_dp_mst.c |  8 +-
> > >   drivers/gpu/drm/i915/intel_drv.h|  2 ++
> > >   3 files changed, 32 insertions(+), 27 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
> > > b/drivers/gpu/drm/i915/intel_ddi.c
> > > index 5dff8b7..10a5a98 100644
> > > --- a/drivers/gpu/drm/i915/intel_ddi.c
> > > +++ b/drivers/gpu/drm/i915/intel_ddi.c
> > > @@ -2258,30 +2258,21 @@ uint32_t ddi_signal_levels(struct
> > > intel_dp *intel_dp)
> > >   return DDI_BUF_TRANS_SELECT(level);
> > >   }
> > >   
> > > -static void intel_ddi_pre_enable(struct intel_encoder
> > > *intel_encoder)
> > > +void intel_ddi_clk_select(struct intel_encoder *encoder,
> > > +   const struct intel_crtc_state
> > > *pipe_config)
> > >   {
> > > - struct drm_encoder *encoder = &intel_encoder->base;
> > > - struct drm_device *dev = encoder->dev;
> > > - struct drm_i915_private *dev_priv = dev->dev_private;
> > > - struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
> > > - enum port port =
> > > intel_ddi_get_encoder_port(intel_encoder);
> > > - int type = intel_encoder->type;
> > > - int hdmi_level;
> > > -
> > > - if (type == INTEL_OUTPUT_EDP) {
> > > - struct intel_dp *intel_dp =
> > > enc_to_intel_dp(encoder);
> > > - intel_edp_panel_on(intel_dp);
> > > - }
> > > + struct drm_i915_private *dev_priv = to_i915(encoder
> > > ->base.dev);
> > > + enum port port = intel_ddi_get_encoder_port(encoder);
> > >   
> > > - if (IS_SKYLAKE(dev)) {
> > > - uint32_t dpll = crtc->config->ddi_pll_sel;
> > > + if (IS_SKYLAKE(dev_priv)) {
> > > + uint32_t dpll = pipe_config->ddi_pll_sel;
> > >   uint32_t val;
> > >   
> > >   /*
> > >* DPLL0 is used for eDP and is the only
> > > "private" DPLL (as
> > >* opposed to shared) on SKL
> > >*/
> > > - if (type == INTEL_OUTPUT_EDP) {
> > > + if (encoder->type == INTEL_OUTPUT_EDP) {
> > >   WARN_ON(dpll != SKL_DPLL0);
> > >   
> > >   val = I915_READ(DPLL_CTRL1);
> > > @@ -2289,7 +2280,7 @@ static void intel_ddi_pre_enable(struct
> > > intel_encoder *intel_encoder)
> > >   val &= ~(DPLL_CTRL1_HDMI_MODE(dpll) |
> > >DPLL_CTRL1_SSC(dpll) |
> > >DPLL_CTRL1_LINK_RATE_MASK(dpll
> > > ));
> > > - val |= crtc->config->dpll_hw_state.ctrl1
> > > << (dpll * 6);
> > > + val |= pipe_config->dpll_hw_state.ctrl1
> > > << (dpll * 6);
> > >   
> > >   I915_WRITE(DPLL_CTRL1, val);
> > >   POSTING_READ(DPLL_CTRL1);
> > > @@ -2305,11 +2296,29 @@ static void intel_ddi_pre_enable(struct
> > > intel_encoder *intel_encoder)
> > >   
> > >   I915_WRITE(DPLL_CTRL2, val);
> > >   
> > > - } else if (INTEL_INFO(dev)->gen < 9) {
> > > - WARN_ON(crtc->config->ddi_pll_sel ==
> > > PORT_CLK_SEL_NONE);
> > > - I915_WRITE(PORT_CLK_SEL(port), crtc->config
> > > ->ddi_pll_sel);
> > > + } else if (INTEL_INFO(dev_priv)->gen < 9) {
> > > + WARN_ON(pipe_config->ddi_pll_sel ==
> > > PORT_CLK_SEL_NONE);
> > > + I915_WRITE(PORT_CLK_SEL(port), pipe_config
> > > ->ddi_pll_sel);
> > > + }
> > > +}
> > > +
> > > +static void intel_ddi_pre_enable(struct intel_encoder
> > > *intel_encoder)
> > > +{
> > > + struct drm_encoder *encoder = &intel_encoder->base;
> > > + struct drm_device *dev = encoder->dev;
> > > + struct drm_i915_private *dev_priv = dev->dev_private;
> > > + struct intel_crtc *crtc = to_intel_crtc(encoder->crtc);
> > > + enum port port =
> > > intel_ddi_get_encoder_port(intel_encoder);
> > > + int type = intel_encoder->type;
> > > + int hdmi_level;
> > > +
> > > + if (type == INTEL_OUTPUT_EDP) {
> > > + struct intel_dp *intel_dp =
> > > enc_to_intel_dp(encoder);
> > > + intel_edp_panel_on(intel_dp);
> > >   }
> > >   
> > > + intel_ddi_clk_select(intel_encoder, crtc->config);
> > > +
> > >   if (type == INTEL_OUTPUT_DISPLAYPORT || type ==
> > > INTEL_OUTPUT_EDP) {
> > >   struct intel_dp *intel_dp =
> > > enc_to_intel_dp(encoder);
> > >   
> > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > index ebf2054..fd25aeb7 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > +++ b/drivers/

Re: [Intel-gfx] [PATCH v4 10/12] drm/i915/gen9: Turn DC handling into a power well

2015-11-23 Thread Imre Deak
On Mon, 2015-11-23 at 14:58 -0800, Matt Roper wrote:
> On Mon, Nov 16, 2015 at 04:20:01PM +0100, Patrik Jakobsson wrote:
> > Handle DC off as a power well where enabling the power well will
> > prevent
> > the DMC to enter selected DC states (required around modesets and
> > Aux
> > A). Disabling the power well will allow DC states again. For now
> > the
> > highest DC state is DC6 for Skylake and DC5 for Broxton but will be
> > configurable for Skylake in a later patch.
> > 
> > v2: Check both DC5 and DC6 bits in power well enabled function
> > (Ville)
> > v3:
> > - Remove unneeded DC_OFF case in skl_set_power_well() (Imre)
> > - Add PW2 dependency to DC_OFF (Imre)
> > v4: Put DC_OFF before PW2 in BXT power well array
> > 
> > Signed-off-by: Patrik Jakobsson 
> > Reviewed-by: Imre Deak 
> 
> I've been seeing a BXT regression on recent di-nightly where DPMS off
> causes the entire platform to power down[1] instead of just the
> display;
> my bisect lands on this commit as the culprit.  Any idea what the
> cause
> could be?  I can reproduce by either letting the system sit idle long
> enough at an fb console, or by doing an "xset dpms force off" in X.
> Unfortunately I don't have a functioning serial console on this
> platform, so I can't get any messages that may show up around the
> DPMS
> operation.  I've attached my boot-time dmesg output in case that
> helps.
> 
> Subsequent commits seem to depend on the changes here, so I haven't
> reverted this commit directly on di-nightly, but I confirmed that if
> I
> checkout this commit directly I see DPMS problems, whereas its HEAD~1
> works as expected.

The power well support on BXT is not stable atm, we need to apply at
least a similar set of fixes as we did for SKL. So for now I would
suggest disabling it, by booting with i915.disable_power_well=0 until
things are fixed. This should've been made the default option earlier,
I forgot about this. I will follow up with the patch to that extent.

Thanks for the report,
Imre

> Matt
> 
> 
> [1] My BIOS and/or hardware is a bit flaky so even when operating
> "normally" most attempts to reboot/poweroff/S3 suspend all result in
> the
> platform going into some "mostly off" state with an error LED lit and
> require a full power cycle to resurrect.  That's the same state I
> wind
> up in after DPMS off when this patch is present.
> 
> > ---
> >  drivers/gpu/drm/i915/i915_drv.c |   6 --
> >  drivers/gpu/drm/i915/i915_reg.h |   1 +
> >  drivers/gpu/drm/i915/intel_display.c|   6 ++
> >  drivers/gpu/drm/i915/intel_runtime_pm.c | 110
> > +++-
> >  4 files changed, 88 insertions(+), 35 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c
> > b/drivers/gpu/drm/i915/i915_drv.c
> > index 5a63f9a..0c7f435 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1072,9 +1072,6 @@ static int i915_pm_resume(struct device *dev)
> >  
> >  static int skl_suspend_complete(struct drm_i915_private *dev_priv)
> >  {
> > -   if (dev_priv->csr.dmc_payload)
> > -   skl_enable_dc6(dev_priv);
> > -
> >     return 0;
> >  }
> >  
> > @@ -1119,9 +1116,6 @@ static int bxt_resume_prepare(struct
> > drm_i915_private *dev_priv)
> >  
> >  static int skl_resume_prepare(struct drm_i915_private *dev_priv)
> >  {
> > -   if (dev_priv->csr.dmc_payload)
> > -   skl_disable_dc6(dev_priv);
> > -
> >     return 0;
> >  }
> >  
> > diff --git a/drivers/gpu/drm/i915/i915_reg.h
> > b/drivers/gpu/drm/i915/i915_reg.h
> > index 0f3849f..b6a3525 100644
> > --- a/drivers/gpu/drm/i915/i915_reg.h
> > +++ b/drivers/gpu/drm/i915/i915_reg.h
> > @@ -638,6 +638,7 @@ enum skl_disp_power_wells {
> >  
> >     /* Not actual bit groups. Used as IDs for
> > lookup_power_well() */
> >     SKL_DISP_PW_ALWAYS_ON,
> > +   SKL_DISP_PW_DC_OFF,
> >  };
> >  
> >  #define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2))
> > diff --git a/drivers/gpu/drm/i915/intel_display.c
> > b/drivers/gpu/drm/i915/intel_display.c
> > index 978b1b9..21385a0 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -13323,6 +13323,9 @@ static int intel_atomic_commit(struct
> > drm_device *dev,
> >     to_intel_crtc_state(crtc->state)-
> > >update_pipe;
> >     unsigned long put_domains = 0;
> >  
> > +   if (modeset)
> > +   intel_display_power_get(dev_priv,
> > POWER_DOMAIN_MODESET);
> > +
> >     if (modeset && crtc->state->active) {
> >     update_scanline_offset(to_intel_crtc(crtc)
> > );
> >     dev_priv->display.crtc_enable(crtc);
> > @@ -13346,6 +13349,9 @@ static int intel_atomic_commit(struct
> > drm_device *dev,
> >     modeset_put_power_domains(dev_priv,
> > put_domains);
> >  
> >     intel_post_plane_update(intel_crtc);
> > +
> > +   if (modeset)
> > +   intel_display_power_put(dev_priv,
> > P

[Intel-gfx] [PATCH] drm/i915/guc: Move wait for GuC out of spinlock/unlock

2015-11-23 Thread yu . dai
From: Alex Dai 

When GuC Work Queue is full, driver will wait GuC for avaliable
space by delaying 1ms. The wait needs to be out of spinlockirq /
unlock. Otherwise, lockup happens because jiffies won't be updated
dur to irq is disabled.

Issue is found in igt/gem_close_race.

Signed-off-by: Alex Dai 
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 27 +--
 1 file changed, 17 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 0a6b007..1418397 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -201,10 +201,13 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
union guc_doorbell_qw *db;
void *base;
int attempt = 2, ret = -EAGAIN;
+   unsigned long flags;
 
base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
desc = base + gc->proc_desc_offset;
 
+   spin_lock_irqsave(&gc->wq_lock, flags);
+
/* Update the tail so it is visible to GuC */
desc->tail = gc->wq_tail;
 
@@ -248,7 +251,10 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
db_exc.cookie = 1;
}
 
+   spin_unlock_irqrestore(&gc->wq_lock, flags);
+
kunmap_atomic(base);
+
return ret;
 }
 
@@ -487,16 +493,16 @@ static int guc_get_workqueue_space(struct i915_guc_client 
*gc, u32 *offset)
struct guc_process_desc *desc;
void *base;
u32 size = sizeof(struct guc_wq_item);
-   int ret = 0, timeout_counter = 200;
+   int ret = -ETIMEDOUT, timeout_counter = 200;
+   unsigned long flags;
 
base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, 0));
desc = base + gc->proc_desc_offset;
 
while (timeout_counter-- > 0) {
-   ret = wait_for_atomic(CIRC_SPACE(gc->wq_tail, desc->head,
-   gc->wq_size) >= size, 1);
+   spin_lock_irqsave(&gc->wq_lock, flags);
 
-   if (!ret) {
+   if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) {
*offset = gc->wq_tail;
 
/* advance the tail for next workqueue item */
@@ -505,7 +511,13 @@ static int guc_get_workqueue_space(struct i915_guc_client 
*gc, u32 *offset)
 
/* this will break the loop */
timeout_counter = 0;
+   ret = 0;
}
+
+   spin_unlock_irqrestore(&gc->wq_lock, flags);
+
+   if (timeout_counter)
+   usleep_range(1000, 2000);
};
 
kunmap_atomic(base);
@@ -597,19 +609,17 @@ int i915_guc_submit(struct i915_guc_client *client,
 {
struct intel_guc *guc = client->guc;
enum intel_ring_id ring_id = rq->ring->id;
-   unsigned long flags;
int q_ret, b_ret;
 
/* Need this because of the deferred pin ctx and ring */
/* Shall we move this right after ring is pinned? */
lr_context_update(rq);
 
-   spin_lock_irqsave(&client->wq_lock, flags);
-
q_ret = guc_add_workqueue_item(client, rq);
if (q_ret == 0)
b_ret = guc_ring_doorbell(client);
 
+   spin_lock(&guc->host2guc_lock);
client->submissions[ring_id] += 1;
if (q_ret) {
client->q_fail += 1;
@@ -620,9 +630,6 @@ int i915_guc_submit(struct i915_guc_client *client,
} else {
client->retcode = 0;
}
-   spin_unlock_irqrestore(&client->wq_lock, flags);
-
-   spin_lock(&guc->host2guc_lock);
guc->submissions[ring_id] += 1;
guc->last_seqno[ring_id] = rq->seqno;
spin_unlock(&guc->host2guc_lock);
-- 
2.5.0

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


Re: [Intel-gfx] [PATCH v4 10/12] drm/i915/gen9: Turn DC handling into a power well

2015-11-23 Thread Matt Roper
On Mon, Nov 16, 2015 at 04:20:01PM +0100, Patrik Jakobsson wrote:
> Handle DC off as a power well where enabling the power well will prevent
> the DMC to enter selected DC states (required around modesets and Aux
> A). Disabling the power well will allow DC states again. For now the
> highest DC state is DC6 for Skylake and DC5 for Broxton but will be
> configurable for Skylake in a later patch.
> 
> v2: Check both DC5 and DC6 bits in power well enabled function (Ville)
> v3:
> - Remove unneeded DC_OFF case in skl_set_power_well() (Imre)
> - Add PW2 dependency to DC_OFF (Imre)
> v4: Put DC_OFF before PW2 in BXT power well array
> 
> Signed-off-by: Patrik Jakobsson 
> Reviewed-by: Imre Deak 

I've been seeing a BXT regression on recent di-nightly where DPMS off
causes the entire platform to power down[1] instead of just the display;
my bisect lands on this commit as the culprit.  Any idea what the cause
could be?  I can reproduce by either letting the system sit idle long
enough at an fb console, or by doing an "xset dpms force off" in X.
Unfortunately I don't have a functioning serial console on this
platform, so I can't get any messages that may show up around the DPMS
operation.  I've attached my boot-time dmesg output in case that helps.

Subsequent commits seem to depend on the changes here, so I haven't
reverted this commit directly on di-nightly, but I confirmed that if I
checkout this commit directly I see DPMS problems, whereas its HEAD~1
works as expected.


Matt


[1] My BIOS and/or hardware is a bit flaky so even when operating
"normally" most attempts to reboot/poweroff/S3 suspend all result in the
platform going into some "mostly off" state with an error LED lit and
require a full power cycle to resurrect.  That's the same state I wind
up in after DPMS off when this patch is present.

> ---
>  drivers/gpu/drm/i915/i915_drv.c |   6 --
>  drivers/gpu/drm/i915/i915_reg.h |   1 +
>  drivers/gpu/drm/i915/intel_display.c|   6 ++
>  drivers/gpu/drm/i915/intel_runtime_pm.c | 110 
> +++-
>  4 files changed, 88 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 5a63f9a..0c7f435 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1072,9 +1072,6 @@ static int i915_pm_resume(struct device *dev)
>  
>  static int skl_suspend_complete(struct drm_i915_private *dev_priv)
>  {
> - if (dev_priv->csr.dmc_payload)
> - skl_enable_dc6(dev_priv);
> -
>   return 0;
>  }
>  
> @@ -1119,9 +1116,6 @@ static int bxt_resume_prepare(struct drm_i915_private 
> *dev_priv)
>  
>  static int skl_resume_prepare(struct drm_i915_private *dev_priv)
>  {
> - if (dev_priv->csr.dmc_payload)
> - skl_disable_dc6(dev_priv);
> -
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
> index 0f3849f..b6a3525 100644
> --- a/drivers/gpu/drm/i915/i915_reg.h
> +++ b/drivers/gpu/drm/i915/i915_reg.h
> @@ -638,6 +638,7 @@ enum skl_disp_power_wells {
>  
>   /* Not actual bit groups. Used as IDs for lookup_power_well() */
>   SKL_DISP_PW_ALWAYS_ON,
> + SKL_DISP_PW_DC_OFF,
>  };
>  
>  #define SKL_POWER_WELL_STATE(pw) (1 << ((pw) * 2))
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index 978b1b9..21385a0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -13323,6 +13323,9 @@ static int intel_atomic_commit(struct drm_device *dev,
>   to_intel_crtc_state(crtc->state)->update_pipe;
>   unsigned long put_domains = 0;
>  
> + if (modeset)
> + intel_display_power_get(dev_priv, POWER_DOMAIN_MODESET);
> +
>   if (modeset && crtc->state->active) {
>   update_scanline_offset(to_intel_crtc(crtc));
>   dev_priv->display.crtc_enable(crtc);
> @@ -13346,6 +13349,9 @@ static int intel_atomic_commit(struct drm_device *dev,
>   modeset_put_power_domains(dev_priv, put_domains);
>  
>   intel_post_plane_update(intel_crtc);
> +
> + if (modeset)
> + intel_display_power_put(dev_priv, POWER_DOMAIN_MODESET);
>   }
>  
>   /* FIXME: add subpixel order */
> diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c 
> b/drivers/gpu/drm/i915/intel_runtime_pm.c
> index edf753e..0ff1646 100644
> --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> @@ -49,9 +49,6 @@
>   * present for a given platform.
>   */
>  
> -#define GEN9_ENABLE_DC5(dev) 0
> -#define SKL_ENABLE_DC6(dev) IS_SKYLAKE(dev)
> -
>  #define for_each_power_well(i, power_well, domain_mask, power_domains)   
> \
>   for (i = 0; \
>i < (power_domains)->power_well_count &

Re: [Intel-gfx] [PATCH v1] drm/i915: Fix a false alert of memory leak when free LRC

2015-11-23 Thread Yu Dai



On 11/23/2015 02:34 AM, Tvrtko Ursulin wrote:

On 20/11/15 08:31, Daniel Vetter wrote:
> On Thu, Nov 19, 2015 at 04:10:26PM -0800, yu@intel.com wrote:
>> From: Alex Dai 
>>
>> There is a memory leak warning message from i915_gem_context_clean
>> when GuC submission is enabled. The reason is that when LRC is
>> released, its ppgtt could be still referenced. The assumption that
>> all VMAs are unbound during release of LRC is not true.
>>
>> v1: Move the code inside i915_gem_context_clean() to where ppgtt is
>> released because it is not cleaning context anyway but ppgtt.
>>
>> Signed-off-by: Alex Dai 
>
> retire__read drops the ctx (and hence ppgtt) reference too early,
> resulting in us hitting the WARNING. See the giant thread with Tvrtko,
> Chris and me:
>
> http://www.spinics.net/lists/intel-gfx/msg78918.html
>
> Would be great if someone could test the diff I posted in there.

It doesn't work - I have posted my IGT snippet which I thought explained it.


I thought moving the VMA list clean up into i915_ppgtt_release() should 
work. However, it creates a chicken & egg problem. ppgtt_release() rely 
on vma_unbound() to be called first to decrease its refcount. So calling 
vma_unbound() inside ppgtt_release() is not right.

Problem req unreference in obj->active case. When it hits that path it
will not move the VMA to inactive and the
intel_execlists_retire_requests will be the last unreference from the
retire worker which will trigger the WARN.


I still think the problem comes from the assumption that when lrc is 
released, its all VMAs should be unbound. Precisely I mean the comments 
made for i915_gem_context_clean() - "This context is going away and we 
need to remove all VMAs still around." Really the lrc life cycle is 
different from ppgtt / VMAs. Check the line after 
i915_gem_context_clean(). It is ppgtt_put(). In the case lrc is freed 
early, It won't release ppgtt anyway because it is still referenced by 
VMAs. An it will be freed when no ref of GEM obj.



I posted an IGT which hits that ->
http://patchwork.freedesktop.org/patch/65369/

And posted one give up on the active VMA mem leak patch ->
http://patchwork.freedesktop.org/patch/65529/


This patch will silent the warning. But I think the 
i915_gem_context_clean() itself is unnecessary. I don't see any issue by 
deleting it. The check of VMA list is inside ppgtt_release() and the 
unbound should be aligned to GEM obj's life cycle but not lrc life cycle.

I have no idea yet of GuC implications, I just spotted this parallel thread.

And Mika has proposed something interesting - that we could just clean
up the active VMA in context cleanup since we know it is a false one.

However, again I don't know how that interacts with the GuC. Surely it
cannot be freeing the context with stuff genuinely still active in the GuC?



There is no interacts with GuC though. Just very easy to see the warning 
when GuC is enabled, says when run gem_close_race. The reason is that 
GuC does not use the execlist_queue (execlist_retired_req_list) which is 
deferred to retire worker. Same as ring submission mode, when GuC is 
enabled, whenever driver submits a new batch, it will try to release 
previous request. I don't know why  intel_execlists_retire_requests is 
not called for this case. Probably because of the unpin. Deferring the 
retirement may just hide the issue. I bet you will see the warning more 
often if you change i915_gem_retire_requests_ring() to 
i915_gem_retire_requests() in i915_gem_execbuffer_reserve().


Thanks,
Alex
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Also disable PSR on Sink when disabling it on Source.

2015-11-23 Thread Rodrigo Vivi
It is not a bad idea to disable the PSR feature on Sink
when we are disabling on the Source.

v2: Move dpcd write inside mutex protected area as suggested by Sonika.

Cc: Sonika Jindal 
Suggested-by: Sonika Jindal 
Signed-off-by: Rodrigo Vivi 
---
 drivers/gpu/drm/i915/intel_psr.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c
index 2b2f84d..3bbb270 100644
--- a/drivers/gpu/drm/i915/intel_psr.c
+++ b/drivers/gpu/drm/i915/intel_psr.c
@@ -518,11 +518,15 @@ void intel_psr_disable(struct intel_dp *intel_dp)
return;
}
 
+   /* Disable PSR on Source */
if (HAS_DDI(dev))
hsw_psr_disable(intel_dp);
else
vlv_psr_disable(intel_dp);
 
+   /* Disable PSR on Sink */
+   drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0);
+
dev_priv->psr.enabled = NULL;
mutex_unlock(&dev_priv->psr.lock);
 
-- 
2.4.3

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


[Intel-gfx] [PATCH] drm/i915: Remove PSR Perf Counter for SKL+

2015-11-23 Thread Rodrigo Vivi
Whenever DMC firmware put the HW into DC State a bunch
of registers including this perf counter is reset to 0.

Even with PSR active and working we could still read
"Performance_Counter: 0" what will misslead people to believe
PSR is broken. For instance on SKL we can only see PC10
residency with screen on if PSR is working properly.
However Performance_Counter was showing 0.

Even if it restored properly on DC6 exit we don't want to
give users the wrong impression that PSR is not working
while we know for sure it is.

So, it is better to remove this counter information while
we don't have a better way to track PSR residency.

Signed-off-by: Rodrigo Vivi 
Reviewed-by: Durgadoss R 
---
 drivers/gpu/drm/i915/i915_debugfs.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index b28da6f..a728ff1 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2582,8 +2582,11 @@ static int i915_edp_psr_status(struct seq_file *m, void 
*data)
}
seq_puts(m, "\n");
 
-   /* CHV PSR has no kind of performance counter */
-   if (HAS_DDI(dev)) {
+   /*
+* VLV/CHV PSR has no kind of performance counter
+* SKL+ Perf counter is reset to 0 everytime DC state is entered
+*/
+   if (IS_HASWELL(dev) || IS_BROADWELL(dev)) {
psrperf = I915_READ(EDP_PSR_PERF_CNT) &
EDP_PSR_PERF_CNT_MASK;
 
-- 
2.4.3

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


Re: [Intel-gfx] [PATCH 2/2] drm/i915: PSR: Mask LPSP hw tracking back again.

2015-11-23 Thread Rodrigo Vivi
Hi Daniel

Would you please consider merging patches 2,3 and 4 from this series
that are ready to get merged?
They don't depend on patch 1 that is under review yet.

Thanks,

On Wed, Nov 18, 2015 at 1:49 PM, Rodrigo Vivi  wrote:
> When we introduced PSR we let LPSP masked allowing us to get PSR
> independently from the audio runtime PM. However in one of the
> attempts to get PSR enabled by default one user reported one specific
> case where he would miss screen updates if scrolling the firefox in a
> Gnome environment when i915 runtime pm was enabled. So for
> this specific case that (I could never create an i-g-t test case)
> we decided to remove the LPSP mask and let HW tracking taking care of
> this case. The mask got removed later by my
> commit 09108b90f04 ("drm/i915: PSR: Remove Low Power HW tracking mask.")
>
> So we started depending on audio driver again, what is bad.
>
> With previous commit
> "drm/i915: PSR: Let's rely more on frontbuffer tracking."
> we transfered the PSR exit responsability totally to SW frontbuffer
> tracking. So now can safelly shut off a bit the HW tracking, or
> at least this case that makes us to depend on other drivers.
>
> v2: Update commit message since this patch by itself doesn't solve
> the bugzilla entries.
>
> v3: Another attempt to improve commit message.
>
> Cc: Paulo Zanoni 
> Tested-by: Brian Norris 
> Signed-off-by: Rodrigo Vivi 
> ---
>  drivers/gpu/drm/i915/intel_psr.c | 9 +++--
>  1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_psr.c 
> b/drivers/gpu/drm/i915/intel_psr.c
> index b0e343c..b1b88d1 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -400,9 +400,14 @@ void intel_psr_enable(struct intel_dp *intel_dp)
> skl_psr_setup_su_vsc(intel_dp);
> }
>
> -   /* Avoid continuous PSR exit by masking memup and hpd */
> +   /*
> +* Per Spec: Avoid continuous PSR exit by masking MEMUP and 
> HPD.
> +* Also mask LPSP to avoid dependency on other drivers that
> +* might block runtime_pm besides preventing other hw tracking
> +* issues now we can rely on frontbuffer tracking.
> +*/
> I915_WRITE(EDP_PSR_DEBUG_CTL(dev), EDP_PSR_DEBUG_MASK_MEMUP |
> -  EDP_PSR_DEBUG_MASK_HPD);
> +  EDP_PSR_DEBUG_MASK_HPD | EDP_PSR_DEBUG_MASK_LPSP);
>
> /* Enable PSR on the panel */
> hsw_psr_enable_sink(intel_dp);
> --
> 2.4.3
>
> ___
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Force PSR exit when IRQ_HPD is detected on eDP.

2015-11-23 Thread Rodrigo Vivi
Hi Ville,

Is it better now?
Could you please review this patch?

Thanks,
Rodrigo.

On Wed, Nov 18, 2015 at 11:19 AM, Rodrigo Vivi  wrote:
> According to VESA spec: "If a Source device receives and IRQ_HPD
> while in a PSR active state, and cannot identify what caused the
> IRQ_HPD to be generated, based on Sink device status registers,
> the Source device can take implementation-specific action.
> One such action can be to exit and then re-enter a PSR active
> state."
>
> Since we aren't checking for any sink status registers and we
>  aren't looking for any other implementation-specific action,
> in case we receive any IRQ_HPD and psr is active let's force
> the exit and reschedule it back.
>
> v2: IRQ_HPD means short HPD so handle it correctly
> as Ville pointed out.
>
> Cc: Ville Syrjälä 
> Signed-off-by: Rodrigo Vivi 
> ---
>  drivers/gpu/drm/i915/intel_dp.c  |  3 +++
>  drivers/gpu/drm/i915/intel_drv.h |  1 +
>  drivers/gpu/drm/i915/intel_psr.c | 33 +
>  3 files changed, 37 insertions(+)
>
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index bec443a..ca7a798 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -5004,6 +5004,9 @@ intel_dp_hpd_pulse(struct intel_digital_port 
> *intel_dig_port, bool long_hpd)
> goto mst_fail;
> }
> } else {
> +   if (intel_dig_port->base.type == INTEL_OUTPUT_EDP)
> +   intel_psr_irq_hpd(dev);
> +
> if (intel_dp->is_mst) {
> if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
> goto mst_fail;
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index ab5c147..1d61551 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1401,6 +1401,7 @@ void intel_psr_flush(struct drm_device *dev,
>  void intel_psr_init(struct drm_device *dev);
>  void intel_psr_single_frame_update(struct drm_device *dev,
>unsigned frontbuffer_bits);
> +void intel_psr_irq_hpd(struct drm_device *dev);
>
>  /* intel_runtime_pm.c */
>  int intel_power_domains_init(struct drm_i915_private *);
> diff --git a/drivers/gpu/drm/i915/intel_psr.c 
> b/drivers/gpu/drm/i915/intel_psr.c
> index bc5ea2a..465d36b 100644
> --- a/drivers/gpu/drm/i915/intel_psr.c
> +++ b/drivers/gpu/drm/i915/intel_psr.c
> @@ -765,6 +765,39 @@ void intel_psr_flush(struct drm_device *dev,
>  }
>
>  /**
> + * intel_psr_irq_hpd - Let PSR aware of IRQ_HPD
> + * @dev: DRM device
> + *
> + * This function is called when IRQ_HPD is received on eDP.
> + */
> +void intel_psr_irq_hpd(struct drm_device *dev)
> +{
> +   struct drm_i915_private *dev_priv = dev->dev_private;
> +   int delay_ms = HAS_DDI(dev) ? 100 : 500;
> +
> +   mutex_lock(&dev_priv->psr.lock);
> +
> +   /*
> +* According to VESA spec "If a Source device receives and IRQ_HPD
> +* while in a PSR active state, and cannot identify what caused the
> +* IRQ_HPD to be generated, based on Sink device status registers,
> +* the Source device can take implementation-specific action.
> +* One such action can be to exit and then re-enter a PSR active
> +* state." Since we aren't checking for any sink status registers
> +* and we aren't looking for any other implementation-specific
> +* action, in case we receive any IRQ_HPD and psr is active let's
> +* force the exit and reschedule it back.
> +*/
> +   if (dev_priv->psr.active) {
> +   intel_psr_exit(dev);
> +   schedule_delayed_work(&dev_priv->psr.work,
> + msecs_to_jiffies(delay_ms));
> +   }
> +
> +   mutex_unlock(&dev_priv->psr.lock);
> +}
> +
> +/**
>   * intel_psr_init - Init basic PSR work and mutex.
>   * @dev: DRM device
>   *
> --
> 2.4.3
>
> ___
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx



-- 
Rodrigo Vivi
Blog: http://blog.vivi.eng.br
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 13/29] drm/armada: Use a private mutex to protect priv->linear

2015-11-23 Thread Daniel Vetter
On Mon, Nov 23, 2015 at 6:40 PM, Russell King - ARM Linux
 wrote:
> On Mon, Nov 23, 2015 at 10:32:46AM +0100, Daniel Vetter wrote:
>> diff --git a/drivers/gpu/drm/armada/armada_gem.c 
>> b/drivers/gpu/drm/armada/armada_gem.c
>> index e3a86b96af2a..a43690ab18b9 100644
>> --- a/drivers/gpu/drm/armada/armada_gem.c
>> +++ b/drivers/gpu/drm/armada/armada_gem.c
>> @@ -46,7 +46,7 @@ static size_t roundup_gem_size(size_t size)
>>   return roundup(size, PAGE_SIZE);
>>  }
>>
>> -/* dev->struct_mutex is held here */
>> +/* dev_priv->linear_lock is held here */
>>  void armada_gem_free_object(struct drm_gem_object *obj)
>
> This is wrong (unless there's changes which I'm not aware of.)
>
> This function is called from drm_gem_object_free(), which is called from
> drm_gem_object_unreference(), both of which contain:
>
> WARN_ON(!mutex_is_locked(&dev->struct_mutex));
>
> Now, unless you're changing the conditions on which
> drm_gem_object_unreference() to be under dev_priv->linear_lock, the
> above comment becomes misleading.
>
> It'd also need drm_gem_object_unreference_unlocked() to become per-
> driver, so it can take dev_priv->linear_lock, and I don't see anything
> in the patches which I've received which does that.
>
> So, I suspect the new comment is basically false.

Well the patch is false. I should have grabbed the new
dev_priv->linear_lock around the cleanup functions in
armada_gem_free_object. Which is possible since armada never calls an
gem unref function while holding the new lock. Sorry for not
double-checking what I've done, I'll revise.
-Daniel
-- 
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 13/29] drm/armada: Use a private mutex to protect priv->linear

2015-11-23 Thread Russell King - ARM Linux
On Mon, Nov 23, 2015 at 10:32:46AM +0100, Daniel Vetter wrote:
> diff --git a/drivers/gpu/drm/armada/armada_gem.c 
> b/drivers/gpu/drm/armada/armada_gem.c
> index e3a86b96af2a..a43690ab18b9 100644
> --- a/drivers/gpu/drm/armada/armada_gem.c
> +++ b/drivers/gpu/drm/armada/armada_gem.c
> @@ -46,7 +46,7 @@ static size_t roundup_gem_size(size_t size)
>   return roundup(size, PAGE_SIZE);
>  }
>  
> -/* dev->struct_mutex is held here */
> +/* dev_priv->linear_lock is held here */
>  void armada_gem_free_object(struct drm_gem_object *obj)

This is wrong (unless there's changes which I'm not aware of.)

This function is called from drm_gem_object_free(), which is called from
drm_gem_object_unreference(), both of which contain:

WARN_ON(!mutex_is_locked(&dev->struct_mutex));

Now, unless you're changing the conditions on which
drm_gem_object_unreference() to be under dev_priv->linear_lock, the
above comment becomes misleading.

It'd also need drm_gem_object_unreference_unlocked() to become per-
driver, so it can take dev_priv->linear_lock, and I don't see anything
in the patches which I've received which does that.

So, I suspect the new comment is basically false.

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915: Disable primary plane if we fail to reconstruct BIOS fb

2015-11-23 Thread Chris Wilson
On Mon, Nov 23, 2015 at 08:48:32AM -0800, Matt Roper wrote:
> If we fail to reconstruct the BIOS fb (e.g., because the FB is too
> large), we'll be left with plane state that indicates the primary plane
> is visible yet has a NULL fb.  This mismatch causes problems later on
> (e.g., for the watermark code).  Since we've failed to reconstruct the
> BIOS FB, the best solution is to just disable the primary plane and
> pretend the BIOS never had it enabled.
> 
> Cc: Daniel Vetter 
> Cc: Ville Syrjälä 
> Signed-off-by: Matt Roper 

There are a bunch of bugzillas open about this as it is a regression
from about 3.2.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Disable primary plane if we fail to reconstruct BIOS fb

2015-11-23 Thread Matt Roper
If we fail to reconstruct the BIOS fb (e.g., because the FB is too
large), we'll be left with plane state that indicates the primary plane
is visible yet has a NULL fb.  This mismatch causes problems later on
(e.g., for the watermark code).  Since we've failed to reconstruct the
BIOS FB, the best solution is to just disable the primary plane and
pretend the BIOS never had it enabled.

Cc: Daniel Vetter 
Cc: Ville Syrjälä 
Signed-off-by: Matt Roper 
---
Ville indicated that it might also be worth dropping the BIOS FB size test we
have today.  I'm not sure what the status of FBC is today (which I believe is
why we have the size check), so we should probably wait for Paulo to weigh in
on that part and potentially follow up with an additional patch.

 drivers/gpu/drm/i915/intel_display.c | 13 +
 1 file changed, 13 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 68fb449..ed659e2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2597,6 +2597,8 @@ intel_find_initial_plane_obj(struct intel_crtc 
*intel_crtc,
struct drm_i915_gem_object *obj;
struct drm_plane *primary = intel_crtc->base.primary;
struct drm_plane_state *plane_state = primary->state;
+   struct drm_crtc_state *crtc_state = intel_crtc->base.state;
+   struct intel_plane *intel_plane = to_intel_plane(primary);
struct drm_framebuffer *fb;
 
if (!plane_config->fb)
@@ -2633,6 +2635,17 @@ intel_find_initial_plane_obj(struct intel_crtc 
*intel_crtc,
}
}
 
+   /*
+* We've failed to reconstruct the BIOS FB.  Current display state
+* indicates that the primary plane is visible, but has a NULL FB,
+* which will lead to problems later if we don't fix it up.  The
+* simplest solution is to just disable the primary plane now and
+* pretend the BIOS never had it enabled.
+*/
+   to_intel_plane_state(plane_state)->visible = false;
+   crtc_state->plane_mask &= ~(1 << drm_plane_index(primary));
+   intel_plane->disable_plane(primary, &intel_crtc->base);
+
return;
 
 valid_fb:
-- 
2.1.4

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


[Intel-gfx] [PATCH 0/3] drm/i915: Display irq enable/disable OCD

2015-11-23 Thread ville . syrjala
From: Ville Syrjälä 

I spotted that we're duplicating the BDW+ pipe IMR frobbing a few
places, so I figured I'd consolidate that. And while doing that I
also cleaned up the ibx/ilk stuff a bit as well.

Ville Syrjälä (3):
  drm/i915: Make ibx_{enable,disable}_display_interrupt() static inlines
  drm/i915: Make ironlake_{enable,disable}_display_irq() static inlines
  drm/i915: Introduce bdw_{update,enable,disable}_pipe_irq()

 drivers/gpu/drm/i915/i915_drv.h| 46 +
 drivers/gpu/drm/i915/i915_irq.c| 65 +++---
 drivers/gpu/drm/i915/intel_fifo_underrun.c | 16 +++-
 3 files changed, 85 insertions(+), 42 deletions(-)

-- 
2.4.10

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


[Intel-gfx] [PATCH 3/3] drm/i915: Introduce bdw_{update, enable, disable}_pipe_irq()

2015-11-23 Thread ville . syrjala
From: Ville Syrjälä 

Pull the BDW+ DE pipe interrupt mask frobbing into a central place,
like we have for other platforms.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_drv.h| 14 ++
 drivers/gpu/drm/i915/i915_irq.c| 41 +-
 drivers/gpu/drm/i915/intel_fifo_underrun.c |  8 ++
 3 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b9f86a73c543..c3330ff5016d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2762,6 +2762,20 @@ ilk_disable_display_irq(struct drm_i915_private 
*dev_priv, uint32_t bits)
 {
ilk_update_display_irq(dev_priv, bits, 0);
 }
+void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
+enum pipe pipe,
+uint32_t interrupt_mask,
+uint32_t enabled_irq_mask);
+static inline void bdw_enable_pipe_irq(struct drm_i915_private *dev_priv,
+  enum pipe pipe, uint32_t bits)
+{
+   bdw_update_pipe_irq(dev_priv, pipe, bits, bits);
+}
+static inline void bdw_disable_pipe_irq(struct drm_i915_private *dev_priv,
+   enum pipe pipe, uint32_t bits)
+{
+   bdw_update_pipe_irq(dev_priv, pipe, bits, 0);
+}
 void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
  uint32_t interrupt_mask,
  uint32_t enabled_irq_mask);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 5aea557f3776..92389a9bb301 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -438,6 +438,38 @@ static void bdw_update_port_irq(struct drm_i915_private 
*dev_priv,
 }
 
 /**
+  * bdw_update_pipe_irq - update DE pipe interrupt
+  * @dev_priv: driver private
+  * @pipe: pipe whose interrupt to update
+  * @interrupt_mask: mask of interrupt bits to update
+  * @enabled_irq_mask: mask of interrupt bits to enable
+  */
+void bdw_update_pipe_irq(struct drm_i915_private *dev_priv,
+enum pipe pipe,
+uint32_t interrupt_mask,
+uint32_t enabled_irq_mask)
+{
+   uint32_t new_val;
+
+   assert_spin_locked(&dev_priv->irq_lock);
+
+   WARN_ON(enabled_irq_mask & ~interrupt_mask);
+
+   if (WARN_ON(!intel_irqs_enabled(dev_priv)))
+   return;
+
+   new_val = dev_priv->de_irq_mask[pipe];
+   new_val &= ~interrupt_mask;
+   new_val |= (~enabled_irq_mask & interrupt_mask);
+
+   if (new_val != dev_priv->de_irq_mask[pipe]) {
+   dev_priv->de_irq_mask[pipe] = new_val;
+   I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
+   POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+   }
+}
+
+/**
  * ibx_display_interrupt_update - update SDEIMR
  * @dev_priv: driver private
  * @interrupt_mask: mask of interrupt bits to update
@@ -2658,10 +2690,9 @@ static int gen8_enable_vblank(struct drm_device *dev, 
unsigned int pipe)
unsigned long irqflags;
 
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-   dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_VBLANK;
-   I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
-   POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+   bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
return 0;
 }
 
@@ -2709,9 +2740,7 @@ static void gen8_disable_vblank(struct drm_device *dev, 
unsigned int pipe)
unsigned long irqflags;
 
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-   dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_VBLANK;
-   I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
-   POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+   bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c 
b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 48bd079bdb06..bda526660e20 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -178,14 +178,10 @@ static void broadwell_set_fifo_underrun_reporting(struct 
drm_device *dev,
 {
struct drm_i915_private *dev_priv = dev->dev_private;
 
-   assert_spin_locked(&dev_priv->irq_lock);
-
if (enable)
-   dev_priv->de_irq_mask[pipe] &= ~GEN8_PIPE_FIFO_UNDERRUN;
+   bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
else
-   dev_priv->de_irq_mask[pipe] |= GEN8_PIPE_FIFO_UNDERRUN;
-   I915_WRITE(GEN8_DE_PIPE_IMR(pipe), dev_priv->de_irq_mask[pipe]);
-   POSTING_READ(GEN8_DE_PIPE_IMR(pipe));
+   bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_FIFO_UNDERRUN);
 }
 
 stat

[Intel-gfx] [PATCH 2/3] drm/i915: Make ironlake_{enable, disable}_display_irq() static inlines

2015-11-23 Thread ville . syrjala
From: Ville Syrjälä 

ironlake_{enable,disable}_display_irq() each just call
ilk_update_display_irq() so let's make them static inlines.

While at it s/ironlake/ilk/ to make things shorter, and a bit more
consistent with the ibx functions.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_drv.h| 17 +
 drivers/gpu/drm/i915/i915_irq.c| 24 ++--
 drivers/gpu/drm/i915/intel_fifo_underrun.c |  8 
 3 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 43087d513637..b9f86a73c543 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2749,10 +2749,19 @@ void valleyview_disable_display_irqs(struct 
drm_i915_private *dev_priv);
 void i915_hotplug_interrupt_update(struct drm_i915_private *dev_priv,
   uint32_t mask,
   uint32_t bits);
-void
-ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask);
-void
-ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask);
+void ilk_update_display_irq(struct drm_i915_private *dev_priv,
+   uint32_t interrupt_mask,
+   uint32_t enabled_irq_mask);
+static inline void
+ilk_enable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits)
+{
+   ilk_update_display_irq(dev_priv, bits, bits);
+}
+static inline void
+ilk_disable_display_irq(struct drm_i915_private *dev_priv, uint32_t bits)
+{
+   ilk_update_display_irq(dev_priv, bits, 0);
+}
 void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
  uint32_t interrupt_mask,
  uint32_t enabled_irq_mask);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index c8ba94968aaf..5aea557f3776 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -215,9 +215,9 @@ void i915_hotplug_interrupt_update(struct drm_i915_private 
*dev_priv,
  * @interrupt_mask: mask of interrupt bits to update
  * @enabled_irq_mask: mask of interrupt bits to enable
  */
-static void ilk_update_display_irq(struct drm_i915_private *dev_priv,
-  uint32_t interrupt_mask,
-  uint32_t enabled_irq_mask)
+void ilk_update_display_irq(struct drm_i915_private *dev_priv,
+   uint32_t interrupt_mask,
+   uint32_t enabled_irq_mask)
 {
uint32_t new_val;
 
@@ -239,18 +239,6 @@ static void ilk_update_display_irq(struct drm_i915_private 
*dev_priv,
}
 }
 
-void
-ironlake_enable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
-{
-   ilk_update_display_irq(dev_priv, mask, mask);
-}
-
-void
-ironlake_disable_display_irq(struct drm_i915_private *dev_priv, u32 mask)
-{
-   ilk_update_display_irq(dev_priv, mask, 0);
-}
-
 /**
  * ilk_update_gt_irq - update GTIMR
  * @dev_priv: driver private
@@ -2645,7 +2633,7 @@ static int ironlake_enable_vblank(struct drm_device *dev, 
unsigned int pipe)
 DE_PIPE_VBLANK(pipe);
 
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-   ironlake_enable_display_irq(dev_priv, bit);
+   ilk_enable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
return 0;
@@ -2700,7 +2688,7 @@ static void ironlake_disable_vblank(struct drm_device 
*dev, unsigned int pipe)
 DE_PIPE_VBLANK(pipe);
 
spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-   ironlake_disable_display_irq(dev_priv, bit);
+   ilk_disable_display_irq(dev_priv, bit);
spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
@@ -3452,7 +3440,7 @@ static int ironlake_irq_postinstall(struct drm_device 
*dev)
 * setup is guaranteed to run in single-threaded context. But we
 * need it to make the assert_spin_locked happy. */
spin_lock_irq(&dev_priv->irq_lock);
-   ironlake_enable_display_irq(dev_priv, DE_PCU_EVENT);
+   ilk_enable_display_irq(dev_priv, DE_PCU_EVENT);
spin_unlock_irq(&dev_priv->irq_lock);
}
 
diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c 
b/drivers/gpu/drm/i915/intel_fifo_underrun.c
index 7ae182d0594b..48bd079bdb06 100644
--- a/drivers/gpu/drm/i915/intel_fifo_underrun.c
+++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c
@@ -128,9 +128,9 @@ static void ironlake_set_fifo_underrun_reporting(struct 
drm_device *dev,
  DE_PIPEB_FIFO_UNDERRUN;
 
if (enable)
-   ironlake_enable_display_irq(dev_priv, bit);
+   ilk_enable_display_irq(dev_priv, bit);
else
-   ironlake_disable_display_irq(dev_priv, bit);

[Intel-gfx] [PATCH 1/3] drm/i915: Make ibx_{enable, disable}_display_interrupt() static inlines

2015-11-23 Thread ville . syrjala
From: Ville Syrjälä 

No reason why ibx_{enable,disable}_display_interrupt() couldn't be
static inlines instead of cpp macros.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/i915_drv.h | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a47e0f4fab56..43087d513637 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2756,10 +2756,17 @@ ironlake_disable_display_irq(struct drm_i915_private 
*dev_priv, u32 mask);
 void ibx_display_interrupt_update(struct drm_i915_private *dev_priv,
  uint32_t interrupt_mask,
  uint32_t enabled_irq_mask);
-#define ibx_enable_display_interrupt(dev_priv, bits) \
-   ibx_display_interrupt_update((dev_priv), (bits), (bits))
-#define ibx_disable_display_interrupt(dev_priv, bits) \
-   ibx_display_interrupt_update((dev_priv), (bits), 0)
+static inline void
+ibx_enable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
+{
+   ibx_display_interrupt_update(dev_priv, bits, bits);
+}
+static inline void
+ibx_disable_display_interrupt(struct drm_i915_private *dev_priv, uint32_t bits)
+{
+   ibx_display_interrupt_update(dev_priv, bits, 0);
+}
+
 
 /* i915_gem.c */
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
-- 
2.4.10

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


Re: [Intel-gfx] [PATCH v2 2/2] drm/i915/pm: Print offending domain in refcount failure

2015-11-23 Thread Imre Deak
On ma, 2015-11-23 at 12:31 +0200, Jani Nikula wrote:
> On Fri, 20 Nov 2015, Ville Syrjälä 
> wrote:
> > On Fri, Nov 20, 2015 at 03:55:34PM +, Daniel Stone wrote:
> > > If we experience a refcounting failure in a power domain/well
> > > (unref'ing at
> > > least one too many times), log the name of the offending domain
> > > or well.
> > > 
> > > Signed-off-by: Daniel Stone 
> > 
> > Both patches look OK to me
> > Reviewed-by: Ville Syrjälä 
> 
> Acked-by: Jani Nikula 

Push both patches to dinq, thanks for the patch and review.

--Imre

> > > ---
> > >  drivers/gpu/drm/i915/intel_runtime_pm.c | 8 ++--
> > >  1 file changed, 6 insertions(+), 2 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > index 754f9bd..7237dea 100644
> > > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > > @@ -1499,11 +1499,15 @@ void intel_display_power_put(struct
> > > drm_i915_private *dev_priv,
> > >  
> > >   mutex_lock(&power_domains->lock);
> > >  
> > > - WARN_ON(!power_domains->domain_use_count[domain]);
> > > + WARN(!power_domains->domain_use_count[domain],
> > > +  "Use count on domain %s is already zero\n",
> > > +  intel_display_power_domain_str(domain));
> > >   power_domains->domain_use_count[domain]--;
> > >  
> > >   for_each_power_well_rev(i, power_well, BIT(domain),
> > > power_domains) {
> > > - WARN_ON(!power_well->count);
> > > + WARN(!power_well->count,
> > > +  "Use count on power well %s is already
> > > zero",
> > > +  power_well->name);
> > >  
> > >   if (!--power_well->count)
> > >   intel_power_well_disable(dev_priv,
> > > power_well);
> > > -- 
> > > 2.5.0
> > > 
> > > ___
> > > Intel-gfx mailing list
> > > Intel-gfx@lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/intel-gfx
> 
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


[Intel-gfx] [PATCH] drm/i915: Move VMAs to inactive as request are retired

2015-11-23 Thread Tvrtko Ursulin
From: Tvrtko Ursulin 

Current code moves _any_ VMA to the inactive list only when
_all_ rendering on an object (so from any context or VM) has
been completed.

This creates an un-natural situation where the context (and
VM) destructors can run with VMAs still on the respective
active list.

Change here is to move VMAs to the inactive list as the
requests are getting retired.

Signed-off-by: Tvrtko Ursulin 
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92638
Testcase: igt/gem_request_retire/retire-vma-not-inactive
Cc: Daniel Vetter 
Cc: Chris Wilson 
---
 drivers/gpu/drm/i915/i915_gem.c | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index cd7e102720f4..47a743246d2c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2413,17 +2413,32 @@ static void
 i915_gem_object_retire__read(struct drm_i915_gem_object *obj, int ring)
 {
struct i915_vma *vma;
+   struct i915_address_space *vm;
 
RQ_BUG_ON(obj->last_read_req[ring] == NULL);
RQ_BUG_ON(!(obj->active & (1 << ring)));
 
list_del_init(&obj->ring_list[ring]);
-   i915_gem_request_assign(&obj->last_read_req[ring], NULL);
 
if (obj->last_write_req && obj->last_write_req->ring->id == ring)
i915_gem_object_retire__write(obj);
 
obj->active &= ~(1 << ring);
+
+   if (obj->last_read_req[ring]->ctx->ppgtt)
+   vm = &obj->last_read_req[ring]->ctx->ppgtt->base;
+   else
+   vm = &obj->last_read_req[ring]->i915->gtt.base;
+
+   list_for_each_entry(vma, &obj->vma_list, vma_link) {
+   if (vma->vm == vm &&
+   vma->ggtt_view.type == I915_GGTT_VIEW_NORMAL &&
+   !list_empty(&vma->mm_list))
+   list_move_tail(&vma->mm_list, &vma->vm->inactive_list);
+   }
+
+   i915_gem_request_assign(&obj->last_read_req[ring], NULL);
+
if (obj->active)
return;
 
-- 
1.9.1

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


Re: [Intel-gfx] [PATCH] drm/i915: Don't register CRT connector when it's fused off

2015-11-23 Thread Ville Syrjälä
On Sat, Nov 21, 2015 at 10:44:12AM +, Chris Wilson wrote:
> On Fri, Nov 20, 2015 at 10:35:41PM +0200, ville.syrj...@linux.intel.com wrote:
> > From: Ville Syrjälä 
> > 
> > On some machines the CRT connector may be fused off. The weird thing
> > about this setup is that the ADPA register works otherwise normally,
> > except the enable bit is hardwired to 0. No one knows of any fuse
> > register that would tell us if this is the case, so the only thing we
> > can do (apart from a blacklist) is to try and set the enable bit and see
> > if it sticks. If not, we don't register the connector at all. Obviously
> > if the bit is already set when loading the driver we can just assume it
> > works.
> > 
> > I've smoke tested this approach on several machines (GMCH and PCH),
> > some with actual CRT connectors, some with shadow connectors, and
> > obviously the machine (IVB) with the fused off connector. So far
> > I've not seen any ill effects from this probe.
> > 
> > The main benefit is that we can actually run igt on machines with
> > fused off connectors, without totally upsetting the state checker.
> > 
> > Signed-off-by: Ville Syrjälä 
> 
> If we can't enable the VGA port, there's not much we can do with it.
> 
> Acked-by: Chris Wilson 
> 
> I'm just a bit hesistant, in case there are machine out there that
> simply do not report the hw state back (doubtful) or there are people
> who make use of the false VGA as a fake output (like me, or perhaps
> kvm-over-ip). I'll survive, I just use a fake HDMI output if there is no
> VGA.

Based on my experience most machines that lack the physical connector
still have a fully working ADPA register. I have two such machines
myself. There's just this one machine at our office where it's
totally fused off, and running igt on it is no fun unless we get rid
of the connector.

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH] drm/i915/skl: re-enable power well support

2015-11-23 Thread Imre Deak
On to, 2015-11-19 at 19:06 +0100, Patrik Jakobsson wrote:
> On Wed, Nov 18, 2015 at 07:53:50PM +0200, Imre Deak wrote:
> > Now that the known DMC/DC issues are fixed, let's try again and
> > re-enable the power well support.
> > 
> > Signed-off-by: Imre Deak 
> 
> Together with the PC9/10 fix this is:
> 
> Reviewed-by: Patrik Jakobsson 

Pushed both patches to dinq, thanks for the review.

> > ---
> >  drivers/gpu/drm/i915/intel_runtime_pm.c | 5 -
> >  1 file changed, 5 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > index a1dc815..10154a7 100644
> > --- a/drivers/gpu/drm/i915/intel_runtime_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
> > @@ -1841,11 +1841,6 @@ sanitize_disable_power_well_option(const
> > struct drm_i915_private *dev_priv,
> >     if (disable_power_well >= 0)
> >     return !!disable_power_well;
> >  
> > -   if (IS_SKYLAKE(dev_priv)) {
> > -   DRM_DEBUG_KMS("Disabling display power well
> > support\n");
> > -   return 0;
> > -   }
> > -
> >     return 1;
> >  }
> >  
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [V2 PATCH 2/2] drm/i915: start adding dp mst audio

2015-11-23 Thread Ander Conselvan De Oliveira
On Mon, 2015-11-23 at 14:04 +, Zanoni, Paulo R wrote:
> Em Qui, 2015-11-19 às 13:07 +0200, Ander Conselvan De Oliveira
> escreveu:
> > (Cc'ing Paulo for the audio power domain question)
> > 
> > On Wed, 2015-11-11 at 13:33 +0800, libin.y...@linux.intel.com wrote:
> > > From: Libin Yang 
> > > 
> > > This patch adds support for DP MST audio in i915.
> > > 
> > > Enable audio codec when DP MST is enabled if has_audio flag is set.
> > > Disable audio codec when DP MST is disabled if has_audio flag is
> > > set.
> > > 
> > > Signed-off-by: Libin Yang 
> > > Signed-off-by: Dave Airlie 
> > > ---
> > >  drivers/gpu/drm/i915/i915_debugfs.c | 14 ++
> > >  drivers/gpu/drm/i915/intel_audio.c  |  9 ++---
> > >  drivers/gpu/drm/i915/intel_dp_mst.c | 25 +
> > >  3 files changed, 45 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > > b/drivers/gpu/drm/i915/i915_debugfs.c
> > > index 5659d4c..38c7a5d 100644
> > > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > > @@ -2873,6 +2873,18 @@ static void intel_dp_info(struct seq_file
> > > *m,
> > >   intel_panel_info(m, &intel_connector->panel);
> > >  }
> > >  
> > > +static void intel_dp_mst_info(struct seq_file *m,
> > > +   struct intel_connector *intel_connector)
> > > +{
> > > + struct intel_encoder *intel_encoder = intel_connector-
> > > > encoder;
> > > + struct intel_dp_mst_encoder *intel_mst =
> > > + enc_to_mst(&intel_encoder->base);
> > > + struct intel_digital_port *intel_dig_port = intel_mst-
> > > > primary;
> > > + struct intel_dp *intel_dp = &intel_dig_port->dp;
> > > +
> > > + seq_printf(m, "\taudio support: %s\n",
> > > drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector-
> > > > port) ? "yes" :
> > > "no");
> > 
> > Too much going on in just one line. You can replace the ternary
> > operator with
> > yesno(). You could also add a has_audio bool:
> > 
> > bool has_audio = drm_dp_mst_port_has_audio(...);
> > seq_printf(..., yesno(has_audio));
> > 
> > 
> > > +}
> > > +
> > >  static void intel_hdmi_info(struct seq_file *m,
> > >   struct intel_connector
> > > *intel_connector)
> > >  {
> > > @@ -2916,6 +2928,8 @@ static void intel_connector_info(struct
> > > seq_file *m,
> > >   intel_hdmi_info(m, intel_connector);
> > >   else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
> > >   intel_lvds_info(m, intel_connector);
> > > + else if (intel_encoder->type ==
> > > INTEL_OUTPUT_DP_MST)
> > > + intel_dp_mst_info(m, intel_connector);
> > >   }
> > >  
> > >   seq_printf(m, "\tmodes:\n");
> > > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > > b/drivers/gpu/drm/i915/intel_audio.c
> > > index 63d4706..07b2aa6 100644
> > > --- a/drivers/gpu/drm/i915/intel_audio.c
> > > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > > @@ -262,7 +262,8 @@ static void hsw_audio_codec_disable(struct
> > > intel_encoder
> > > *encoder)
> > >   tmp |= AUD_CONFIG_N_PROG_ENABLE;
> > >   tmp &= ~AUD_CONFIG_UPPER_N_MASK;
> > >   tmp &= ~AUD_CONFIG_LOWER_N_MASK;
> > > - if (intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DISPLAYPORT))
> > > + if (intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DISPLAYPORT) ||
> > > + intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DP_MST))
> > 
> > The second line should be aligned with '('.
> > 
> > >   tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > >   I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> > >  
> > > @@ -478,7 +479,8 @@ static void ilk_audio_codec_enable(struct
> > > drm_connector
> > > *connector,
> > >   tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
> > >   tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
> > >   tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
> > > - if (intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DISPLAYPORT))
> > > + if (intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DISPLAYPORT) ||
> > > + intel_pipe_has_type(intel_crtc,
> > > INTEL_OUTPUT_DP_MST))
> > 
> > Same here.
> > 
> > >   tmp |= AUD_CONFIG_N_VALUE_INDEX;
> > >   else
> > >   tmp |=
> > > audio_config_hdmi_pixel_clock(adjusted_mode);
> > > @@ -516,7 +518,8 @@ void intel_audio_codec_enable(struct
> > > intel_encoder
> > > *intel_encoder)
> > >  
> > >   /* ELD Conn_Type */
> > >   connector->eld[5] &= ~(3 << 2);
> > > - if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
> > > + if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> > > + intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
> > >   connector->eld[5] |= (1 << 2);
> > 
> > And here.
> > 
> > >  
> > >   connector->eld[6] = drm_av_sync_delay(connector,
> > > adjusted_mode) / 2;
> > > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > index 0639275..4ded0fb 100644
> > > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > > @@ -78,6

Re: [Intel-gfx] [PATCH 1/3] drm/i915: Suppress spurious CPU FIFO underruns on ILK-IVB

2015-11-23 Thread Ville Syrjälä
On Mon, Nov 23, 2015 at 02:28:29PM +, Chris Wilson wrote:
> On Mon, Nov 23, 2015 at 04:22:08PM +0200, Ville Syrjälä wrote:
> > On Sat, Nov 21, 2015 at 10:51:50AM +, Chris Wilson wrote:
> > > On Fri, Nov 20, 2015 at 10:09:18PM +0200, ville.syrj...@linux.intel.com 
> > > wrote:
> > > > From: Ville Syrjälä 
> > > > 
> > > > We still get spurious pipe underruns on ILK/SNB/IVB under two
> > > > circumstances when dealing with PCH ports:
> > > > * When the pipe has been disabled, but FDI RX/TX is still enabled
> > > > * During FDI link training
> > > > 
> > > > Both cases seem to happen at least when we do VGA+HDMI cloning
> > > > from the same pipe. I don't think I've seen them when not cloning,
> > > > but can't be 100% sure.
> > > > 
> > > > Disable underrun reporting around those places to eliminate the
> > > > dmesg errors.
> > > > 
> > > > Testcase: igt/kms_setmode/basic-clone-single-crtc
> > > > Signed-off-by: Ville Syrjälä 
> > > Acked-by: Chris Wilson 
> > > 
> > > I wondered if logging the suppressed errors would be of any use?
> > 
> > Hmm. Maybe just to confirm that they still happen, and thus suppressing
> > is still neded.
> > 
> > > Does
> > > the check_cpu_fifo work if the reporting is disabled? Could we do a
> > > manual check and DRM_DEBUG_KMS() if the enable did generate a failure.
> > > If the check_cpu_fifo does work, won't we still get the error from the
> > > added check in atomic_commit()?
> > 
> > The check only looks at pipes that have underrun reporting enabled. I
> > suppose it might be possible to have it check all the pipes. At the
> > point where we call it no explicit suppression should be happening, so
> > the only reason why underrun reporting would be disabled on any pipe is
> > due to detecting a previous underrun via the interrupt.
> 
> Does the hw flag the underrun even if the interrupt is disabled?
> (Playing games with PIPESTAT_IER?) Could we then report (debug) that an
> underrun happened before we re-enable reporting?

Hmm. We use the IMR to disable this stuff on many platforms, so we
do lose the IIR. So we'd need to frob IER instead to make this work
universally. Currently it would only work for GMCH, IVB/HSW,
CPT/PPT/LPT/WPT since PIPESTAT/ERR_INT/SERR_INT don't have IMR.

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 3/3] drm/i915: Check for underruns after crtc disable

2015-11-23 Thread Chris Wilson
On Mon, Nov 23, 2015 at 04:10:32PM +0200, Ville Syrjälä wrote:
> On Sat, Nov 21, 2015 at 10:49:04AM +, Chris Wilson wrote:
> > On Fri, Nov 20, 2015 at 10:09:20PM +0200, ville.syrj...@linux.intel.com 
> > wrote:
> > > From: Ville Syrjälä 
> > > 
> > > To get a better idea if underruns occurred during crtc disabling,
> > > let's check for them explicitly. This helps in cases where the
> > > error interrupt isn't active, or there is no underrun interrupt
> > > support at all.
> > > 
> > > Signed-off-by: Ville Syrjälä 
> > 
> > Would this be better the vblank after enabling?
> 
> We do that too.

Oh, crtc disabling. I can't read.
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/3] drm/i915: Suppress spurious CPU FIFO underruns on ILK-IVB

2015-11-23 Thread Chris Wilson
On Mon, Nov 23, 2015 at 04:22:08PM +0200, Ville Syrjälä wrote:
> On Sat, Nov 21, 2015 at 10:51:50AM +, Chris Wilson wrote:
> > On Fri, Nov 20, 2015 at 10:09:18PM +0200, ville.syrj...@linux.intel.com 
> > wrote:
> > > From: Ville Syrjälä 
> > > 
> > > We still get spurious pipe underruns on ILK/SNB/IVB under two
> > > circumstances when dealing with PCH ports:
> > > * When the pipe has been disabled, but FDI RX/TX is still enabled
> > > * During FDI link training
> > > 
> > > Both cases seem to happen at least when we do VGA+HDMI cloning
> > > from the same pipe. I don't think I've seen them when not cloning,
> > > but can't be 100% sure.
> > > 
> > > Disable underrun reporting around those places to eliminate the
> > > dmesg errors.
> > > 
> > > Testcase: igt/kms_setmode/basic-clone-single-crtc
> > > Signed-off-by: Ville Syrjälä 
> > Acked-by: Chris Wilson 
> > 
> > I wondered if logging the suppressed errors would be of any use?
> 
> Hmm. Maybe just to confirm that they still happen, and thus suppressing
> is still neded.
> 
> > Does
> > the check_cpu_fifo work if the reporting is disabled? Could we do a
> > manual check and DRM_DEBUG_KMS() if the enable did generate a failure.
> > If the check_cpu_fifo does work, won't we still get the error from the
> > added check in atomic_commit()?
> 
> The check only looks at pipes that have underrun reporting enabled. I
> suppose it might be possible to have it check all the pipes. At the
> point where we call it no explicit suppression should be happening, so
> the only reason why underrun reporting would be disabled on any pipe is
> due to detecting a previous underrun via the interrupt.

Does the hw flag the underrun even if the interrupt is disabled?
(Playing games with PIPESTAT_IER?) Could we then report (debug) that an
underrun happened before we re-enable reporting?
-Chris

-- 
Chris Wilson, Intel Open Source Technology Centre
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 1/3] drm/i915: Suppress spurious CPU FIFO underruns on ILK-IVB

2015-11-23 Thread Ville Syrjälä
On Sat, Nov 21, 2015 at 10:51:50AM +, Chris Wilson wrote:
> On Fri, Nov 20, 2015 at 10:09:18PM +0200, ville.syrj...@linux.intel.com wrote:
> > From: Ville Syrjälä 
> > 
> > We still get spurious pipe underruns on ILK/SNB/IVB under two
> > circumstances when dealing with PCH ports:
> > * When the pipe has been disabled, but FDI RX/TX is still enabled
> > * During FDI link training
> > 
> > Both cases seem to happen at least when we do VGA+HDMI cloning
> > from the same pipe. I don't think I've seen them when not cloning,
> > but can't be 100% sure.
> > 
> > Disable underrun reporting around those places to eliminate the
> > dmesg errors.
> > 
> > Testcase: igt/kms_setmode/basic-clone-single-crtc
> > Signed-off-by: Ville Syrjälä 
> Acked-by: Chris Wilson 
> 
> I wondered if logging the suppressed errors would be of any use?

Hmm. Maybe just to confirm that they still happen, and thus suppressing
is still neded.

> Does
> the check_cpu_fifo work if the reporting is disabled? Could we do a
> manual check and DRM_DEBUG_KMS() if the enable did generate a failure.
> If the check_cpu_fifo does work, won't we still get the error from the
> added check in atomic_commit()?

The check only looks at pipes that have underrun reporting enabled. I
suppose it might be possible to have it check all the pipes. At the
point where we call it no explicit suppression should be happening, so
the only reason why underrun reporting would be disabled on any pipe is
due to detecting a previous underrun via the interrupt.

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [PATCH 3/3] drm/i915: Check for underruns after crtc disable

2015-11-23 Thread Ville Syrjälä
On Sat, Nov 21, 2015 at 10:49:04AM +, Chris Wilson wrote:
> On Fri, Nov 20, 2015 at 10:09:20PM +0200, ville.syrj...@linux.intel.com wrote:
> > From: Ville Syrjälä 
> > 
> > To get a better idea if underruns occurred during crtc disabling,
> > let's check for them explicitly. This helps in cases where the
> > error interrupt isn't active, or there is no underrun interrupt
> > support at all.
> > 
> > Signed-off-by: Ville Syrjälä 
> 
> Would this be better the vblank after enabling?

We do that too.

-- 
Ville Syrjälä
Intel OTC
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [V2 PATCH 2/2] drm/i915: start adding dp mst audio

2015-11-23 Thread Zanoni, Paulo R
Em Qui, 2015-11-19 às 13:07 +0200, Ander Conselvan De Oliveira
escreveu:
> (Cc'ing Paulo for the audio power domain question)
> 
> On Wed, 2015-11-11 at 13:33 +0800, libin.y...@linux.intel.com wrote:
> > From: Libin Yang 
> > 
> > This patch adds support for DP MST audio in i915.
> > 
> > Enable audio codec when DP MST is enabled if has_audio flag is set.
> > Disable audio codec when DP MST is disabled if has_audio flag is
> > set.
> > 
> > Signed-off-by: Libin Yang 
> > Signed-off-by: Dave Airlie 
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c | 14 ++
> >  drivers/gpu/drm/i915/intel_audio.c  |  9 ++---
> >  drivers/gpu/drm/i915/intel_dp_mst.c | 25 +
> >  3 files changed, 45 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c
> > b/drivers/gpu/drm/i915/i915_debugfs.c
> > index 5659d4c..38c7a5d 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -2873,6 +2873,18 @@ static void intel_dp_info(struct seq_file
> > *m,
> >     intel_panel_info(m, &intel_connector->panel);
> >  }
> >  
> > +static void intel_dp_mst_info(struct seq_file *m,
> > +     struct intel_connector *intel_connector)
> > +{
> > +   struct intel_encoder *intel_encoder = intel_connector-
> > >encoder;
> > +   struct intel_dp_mst_encoder *intel_mst =
> > +   enc_to_mst(&intel_encoder->base);
> > +   struct intel_digital_port *intel_dig_port = intel_mst-
> > >primary;
> > +   struct intel_dp *intel_dp = &intel_dig_port->dp;
> > +
> > +   seq_printf(m, "\taudio support: %s\n",
> > drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, intel_connector-
> > >port) ? "yes" :
> > "no");
> 
> Too much going on in just one line. You can replace the ternary
> operator with
> yesno(). You could also add a has_audio bool:
> 
> bool has_audio = drm_dp_mst_port_has_audio(...);
> seq_printf(..., yesno(has_audio));
> 
> 
> > +}
> > +
> >  static void intel_hdmi_info(struct seq_file *m,
> >     struct intel_connector
> > *intel_connector)
> >  {
> > @@ -2916,6 +2928,8 @@ static void intel_connector_info(struct
> > seq_file *m,
> >     intel_hdmi_info(m, intel_connector);
> >     else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
> >     intel_lvds_info(m, intel_connector);
> > +   else if (intel_encoder->type ==
> > INTEL_OUTPUT_DP_MST)
> > +   intel_dp_mst_info(m, intel_connector);
> >     }
> >  
> >     seq_printf(m, "\tmodes:\n");
> > diff --git a/drivers/gpu/drm/i915/intel_audio.c
> > b/drivers/gpu/drm/i915/intel_audio.c
> > index 63d4706..07b2aa6 100644
> > --- a/drivers/gpu/drm/i915/intel_audio.c
> > +++ b/drivers/gpu/drm/i915/intel_audio.c
> > @@ -262,7 +262,8 @@ static void hsw_audio_codec_disable(struct
> > intel_encoder
> > *encoder)
> >     tmp |= AUD_CONFIG_N_PROG_ENABLE;
> >     tmp &= ~AUD_CONFIG_UPPER_N_MASK;
> >     tmp &= ~AUD_CONFIG_LOWER_N_MASK;
> > -   if (intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DISPLAYPORT))
> > +   if (intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DISPLAYPORT) ||
> > +   intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DP_MST))
> 
> The second line should be aligned with '('.
> 
> >     tmp |= AUD_CONFIG_N_VALUE_INDEX;
> >     I915_WRITE(HSW_AUD_CFG(pipe), tmp);
> >  
> > @@ -478,7 +479,8 @@ static void ilk_audio_codec_enable(struct
> > drm_connector
> > *connector,
> >     tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
> >     tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
> >     tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
> > -   if (intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DISPLAYPORT))
> > +   if (intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DISPLAYPORT) ||
> > +   intel_pipe_has_type(intel_crtc,
> > INTEL_OUTPUT_DP_MST))
> 
> Same here.
> 
> >     tmp |= AUD_CONFIG_N_VALUE_INDEX;
> >     else
> >     tmp |=
> > audio_config_hdmi_pixel_clock(adjusted_mode);
> > @@ -516,7 +518,8 @@ void intel_audio_codec_enable(struct
> > intel_encoder
> > *intel_encoder)
> >  
> >     /* ELD Conn_Type */
> >     connector->eld[5] &= ~(3 << 2);
> > -   if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT))
> > +   if (intel_pipe_has_type(crtc, INTEL_OUTPUT_DISPLAYPORT) ||
> > +   intel_pipe_has_type(crtc, INTEL_OUTPUT_DP_MST))
> >     connector->eld[5] |= (1 << 2);
> 
> And here.
> 
> >  
> >     connector->eld[6] = drm_av_sync_delay(connector,
> > adjusted_mode) / 2;
> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c
> > b/drivers/gpu/drm/i915/intel_dp_mst.c
> > index 0639275..4ded0fb 100644
> > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
> > @@ -78,6 +78,8 @@ static bool intel_dp_mst_compute_config(struct
> > intel_encoder
> > *encoder,
> >     return false;
> >     }
> >  
> > +   if (drm_dp_mst_port_has_audio(&intel_dp->mst_mgr, found-
> > >port))
> > +   pipe_config->has_audio = 

Re: [Intel-gfx] [PATCH i-g-t v2] lib/igt_kms: Introduce get_first_connected_output macro

2015-11-23 Thread Ander Conselvan De Oliveira
On Fri, 2015-11-20 at 18:56 -0800, Vivek Kasireddy wrote:
> In some cases, we just need one valid (connected) output to perform
> a test. This macro can help in these situations by not having to
> put the test code inside a for loop that iterates over all the outputs.
> 
> v2: Added a brief documentation for this macro.
> 
> Suggested-by: Matt Roper 
> Cc: Thomas Wood 
> Signed-off-by: Vivek Kasireddy 
> ---
>  lib/igt_kms.h | 12 
>  1 file changed, 12 insertions(+)
> 
> diff --git a/lib/igt_kms.h b/lib/igt_kms.h
> index 965c47c..a0bb066 100644
> --- a/lib/igt_kms.h
> +++ b/lib/igt_kms.h
> @@ -279,6 +279,18 @@ void igt_wait_for_vblank(int drm_fd, enum pipe pipe);
>   for (int i__ = 0; (plane) = &(display)->pipes[(pipe)].planes[i__], \
>i__ < (display)->pipes[(pipe)].n_planes; i__++)
>  
> +/**
> + * get_first_connected_output:
> + * @display: Initialized igt_display_t type object
> + * @output: igt_output_t type object
> + *
> + * Returns: First valid (connected) output.
> + */
> +#define get_first_connected_output(display, output)  \
> + for (int i__ = 0;  i__ < (display)->n_outputs; i__++)   \
> + if ((output = &(display)->outputs[i__]), output->valid) \
> + break
> +

Is it possible that there is no valid output?

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


Re: [Intel-gfx] [RFC 02/12] staging/android/sync: add sync_fence_create_dma

2015-11-23 Thread Maarten Lankhorst
Op 23-11-15 om 14:44 schreef Tvrtko Ursulin:
>
> On 23/11/15 13:38, John Harrison wrote:
>> On 23/11/2015 13:27, Maarten Lankhorst wrote:
>>> Op 23-11-15 om 12:34 schreef john.c.harri...@intel.com:
 From: Maarten Lankhorst 

 This allows users of dma fences to create a android fence.

 v2: Added kerneldoc. (Tvrtko Ursulin).

 Signed-off-by: Maarten Lankhorst 
 Signed-off-by: Tvrtko Ursulin 
 Cc: Maarten Lankhorst 
 Cc: Daniel Vetter 
 Cc: Jesse Barnes 
 Cc: de...@driverdev.osuosl.org
 Cc: Riley Andrews 
 Cc: Greg Kroah-Hartman 
 Cc: Arve Hjønnevåg 
 ---
   drivers/staging/android/sync.c | 13 +
   drivers/staging/android/sync.h | 12 +++-
   2 files changed, 20 insertions(+), 5 deletions(-)

 diff --git a/drivers/staging/android/sync.c
 b/drivers/staging/android/sync.c
 index f83e00c..7f0e919 100644
 --- a/drivers/staging/android/sync.c
 +++ b/drivers/staging/android/sync.c
 @@ -188,7 +188,7 @@ static void fence_check_cb_func(struct fence *f,
 struct fence_cb *cb)
   }
   /* TODO: implement a create which takes more that one sync_pt */
 -struct sync_fence *sync_fence_create(const char *name, struct
 sync_pt *pt)
 +struct sync_fence *sync_fence_create_dma(const char *name, struct
 fence *pt)
   {
   struct sync_fence *fence;
 @@ -199,16 +199,21 @@ struct sync_fence *sync_fence_create(const char
 *name, struct sync_pt *pt)
   fence->num_fences = 1;
   atomic_set(&fence->status, 1);
 -fence->cbs[0].sync_pt = &pt->base;
 +fence->cbs[0].sync_pt = pt;
   fence->cbs[0].fence = fence;
 -if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
 -   fence_check_cb_func))
 +if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func))
   atomic_dec(&fence->status);
   sync_fence_debug_add(fence);
   return fence;
   }
 +EXPORT_SYMBOL(sync_fence_create_dma);
 +
 +struct sync_fence *sync_fence_create(const char *name, struct
 sync_pt *pt)
 +{
 +return sync_fence_create_dma(name, &pt->base);
 +}
   EXPORT_SYMBOL(sync_fence_create);
   struct sync_fence *sync_fence_fdget(int fd)
 diff --git a/drivers/staging/android/sync.h
 b/drivers/staging/android/sync.h
 index 61f8a3a..798cd56 100644
 --- a/drivers/staging/android/sync.h
 +++ b/drivers/staging/android/sync.h
 @@ -250,10 +250,20 @@ void sync_pt_free(struct sync_pt *pt);
* @pt:sync_pt to add to the fence
*
* Creates a fence containg @pt.  Once this is called, the fence takes
 - * ownership of @pt.
 + * a reference on @pt.
*/
   struct sync_fence *sync_fence_create(const char *name, struct
 sync_pt *pt);
>>> No it doesn't.
 +/**
 + * sync_fence_create_dma() - creates a sync fence from dma-fence
 + * @name:name of fence to create
 + * @pt:dma-fence to add to the fence
 + *
 + * Creates a fence containg @pt.  Once this is called, the fence takes
 + * a reference on @pt.
 + */
>>> No it doesn't.
>> This is your patch isn't it? Or is this something Tvrtko added on the
>> way past? Either way, what should the correct description be? It takes a
>
> It is Maarten's patch, I just copied the comment over from one function to 
> another. The one I picked up was 
> https://patchwork.freedesktop.org/patch/38074/, December 2014.
>
>> copy of the pointer to 'pt'. Is the comment meaning a reference in the
>> sense of 'pass by reference', i.e. a pointer? But you are meaning a
>> reference in the sense of incrementing a usage count?
>
> Maybe he means it is still taking ownership, not reference?
Indeed. See commit 3ea411c56ef "android: fix reference leak in 
sync_fence_create".

This broke compatibility with android by creating a ref leak. :)

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


Re: [Intel-gfx] [RFC 02/12] staging/android/sync: add sync_fence_create_dma

2015-11-23 Thread Tvrtko Ursulin


On 23/11/15 13:38, John Harrison wrote:

On 23/11/2015 13:27, Maarten Lankhorst wrote:

Op 23-11-15 om 12:34 schreef john.c.harri...@intel.com:

From: Maarten Lankhorst 

This allows users of dma fences to create a android fence.

v2: Added kerneldoc. (Tvrtko Ursulin).

Signed-off-by: Maarten Lankhorst 
Signed-off-by: Tvrtko Ursulin 
Cc: Maarten Lankhorst 
Cc: Daniel Vetter 
Cc: Jesse Barnes 
Cc: de...@driverdev.osuosl.org
Cc: Riley Andrews 
Cc: Greg Kroah-Hartman 
Cc: Arve Hjønnevåg 
---
  drivers/staging/android/sync.c | 13 +
  drivers/staging/android/sync.h | 12 +++-
  2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/android/sync.c
b/drivers/staging/android/sync.c
index f83e00c..7f0e919 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -188,7 +188,7 @@ static void fence_check_cb_func(struct fence *f,
struct fence_cb *cb)
  }
  /* TODO: implement a create which takes more that one sync_pt */
-struct sync_fence *sync_fence_create(const char *name, struct
sync_pt *pt)
+struct sync_fence *sync_fence_create_dma(const char *name, struct
fence *pt)
  {
  struct sync_fence *fence;
@@ -199,16 +199,21 @@ struct sync_fence *sync_fence_create(const char
*name, struct sync_pt *pt)
  fence->num_fences = 1;
  atomic_set(&fence->status, 1);
-fence->cbs[0].sync_pt = &pt->base;
+fence->cbs[0].sync_pt = pt;
  fence->cbs[0].fence = fence;
-if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
-   fence_check_cb_func))
+if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func))
  atomic_dec(&fence->status);
  sync_fence_debug_add(fence);
  return fence;
  }
+EXPORT_SYMBOL(sync_fence_create_dma);
+
+struct sync_fence *sync_fence_create(const char *name, struct
sync_pt *pt)
+{
+return sync_fence_create_dma(name, &pt->base);
+}
  EXPORT_SYMBOL(sync_fence_create);
  struct sync_fence *sync_fence_fdget(int fd)
diff --git a/drivers/staging/android/sync.h
b/drivers/staging/android/sync.h
index 61f8a3a..798cd56 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -250,10 +250,20 @@ void sync_pt_free(struct sync_pt *pt);
   * @pt:sync_pt to add to the fence
   *
   * Creates a fence containg @pt.  Once this is called, the fence takes
- * ownership of @pt.
+ * a reference on @pt.
   */
  struct sync_fence *sync_fence_create(const char *name, struct
sync_pt *pt);

No it doesn't.

+/**
+ * sync_fence_create_dma() - creates a sync fence from dma-fence
+ * @name:name of fence to create
+ * @pt:dma-fence to add to the fence
+ *
+ * Creates a fence containg @pt.  Once this is called, the fence takes
+ * a reference on @pt.
+ */

No it doesn't.

This is your patch isn't it? Or is this something Tvrtko added on the
way past? Either way, what should the correct description be? It takes a


It is Maarten's patch, I just copied the comment over from one function 
to another. The one I picked up was 
https://patchwork.freedesktop.org/patch/38074/, December 2014.



copy of the pointer to 'pt'. Is the comment meaning a reference in the
sense of 'pass by reference', i.e. a pointer? But you are meaning a
reference in the sense of incrementing a usage count?


Maybe he means it is still taking ownership, not reference?

Regards,

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


Re: [Intel-gfx] [RFC 02/12] staging/android/sync: add sync_fence_create_dma

2015-11-23 Thread John Harrison

On 23/11/2015 13:27, Maarten Lankhorst wrote:

Op 23-11-15 om 12:34 schreef john.c.harri...@intel.com:

From: Maarten Lankhorst 

This allows users of dma fences to create a android fence.

v2: Added kerneldoc. (Tvrtko Ursulin).

Signed-off-by: Maarten Lankhorst 
Signed-off-by: Tvrtko Ursulin 
Cc: Maarten Lankhorst 
Cc: Daniel Vetter 
Cc: Jesse Barnes 
Cc: de...@driverdev.osuosl.org
Cc: Riley Andrews 
Cc: Greg Kroah-Hartman 
Cc: Arve Hjønnevåg 
---
  drivers/staging/android/sync.c | 13 +
  drivers/staging/android/sync.h | 12 +++-
  2 files changed, 20 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
index f83e00c..7f0e919 100644
--- a/drivers/staging/android/sync.c
+++ b/drivers/staging/android/sync.c
@@ -188,7 +188,7 @@ static void fence_check_cb_func(struct fence *f, struct 
fence_cb *cb)
  }
  
  /* TODO: implement a create which takes more that one sync_pt */

-struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
+struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt)
  {
struct sync_fence *fence;
  
@@ -199,16 +199,21 @@ struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)

fence->num_fences = 1;
atomic_set(&fence->status, 1);
  
-	fence->cbs[0].sync_pt = &pt->base;

+   fence->cbs[0].sync_pt = pt;
fence->cbs[0].fence = fence;
-   if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
-  fence_check_cb_func))
+   if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func))
atomic_dec(&fence->status);
  
  	sync_fence_debug_add(fence);
  
  	return fence;

  }
+EXPORT_SYMBOL(sync_fence_create_dma);
+
+struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
+{
+   return sync_fence_create_dma(name, &pt->base);
+}
  EXPORT_SYMBOL(sync_fence_create);
  
  struct sync_fence *sync_fence_fdget(int fd)

diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
index 61f8a3a..798cd56 100644
--- a/drivers/staging/android/sync.h
+++ b/drivers/staging/android/sync.h
@@ -250,10 +250,20 @@ void sync_pt_free(struct sync_pt *pt);
   * @pt:   sync_pt to add to the fence
   *
   * Creates a fence containg @pt.  Once this is called, the fence takes
- * ownership of @pt.
+ * a reference on @pt.
   */
  struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);

No it doesn't.

+/**
+ * sync_fence_create_dma() - creates a sync fence from dma-fence
+ * @name:  name of fence to create
+ * @pt:dma-fence to add to the fence
+ *
+ * Creates a fence containg @pt.  Once this is called, the fence takes
+ * a reference on @pt.
+ */

No it doesn't.
This is your patch isn't it? Or is this something Tvrtko added on the 
way past? Either way, what should the correct description be? It takes a 
copy of the pointer to 'pt'. Is the comment meaning a reference in the 
sense of 'pass by reference', i.e. a pointer? But you are meaning a 
reference in the sense of incrementing a usage count?



+struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt);
+
  /*
   * API for sync_fence consumers
   */


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


Re: [Intel-gfx] [RFC 01/12] staging/android/sync: Support sync points created from dma-fences

2015-11-23 Thread Tvrtko Ursulin


Hi,

On 23/11/15 11:34, john.c.harri...@intel.com wrote:

From: Tvrtko Ursulin 


This is actually Maarten's patch, I guess authorship got lost over time 
moving through different trees.


Tvrtko


Debug output assumes all sync points are built on top of Android sync points
and when we start creating them from dma-fences will NULL ptr deref unless
taught about this.

Signed-off-by: Tvrtko Ursulin 
Cc: Maarten Lankhorst 
Cc: de...@driverdev.osuosl.org
Cc: Riley Andrews 
Cc: Greg Kroah-Hartman 
Cc: Arve Hjønnevåg 
---
  drivers/staging/android/sync_debug.c | 42 +++-
  1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/android/sync_debug.c 
b/drivers/staging/android/sync_debug.c
index 91ed2c4..f45d13c 100644
--- a/drivers/staging/android/sync_debug.c
+++ b/drivers/staging/android/sync_debug.c
@@ -82,36 +82,42 @@ static const char *sync_status_str(int status)
return "error";
  }

-static void sync_print_pt(struct seq_file *s, struct sync_pt *pt, bool fence)
+static void sync_print_pt(struct seq_file *s, struct fence *pt, bool fence)
  {
int status = 1;
-   struct sync_timeline *parent = sync_pt_parent(pt);

-   if (fence_is_signaled_locked(&pt->base))
-   status = pt->base.status;
+   if (fence_is_signaled_locked(pt))
+   status = pt->status;

seq_printf(s, "  %s%spt %s",
-  fence ? parent->name : "",
+  fence && pt->ops->get_timeline_name ?
+  pt->ops->get_timeline_name(pt) : "",
   fence ? "_" : "",
   sync_status_str(status));

if (status <= 0) {
struct timespec64 ts64 =
-   ktime_to_timespec64(pt->base.timestamp);
+   ktime_to_timespec64(pt->timestamp);

seq_printf(s, "@%lld.%09ld", (s64)ts64.tv_sec, ts64.tv_nsec);
}

-   if (parent->ops->timeline_value_str &&
-   parent->ops->pt_value_str) {
+   if ((!fence || pt->ops->timeline_value_str) &&
+   pt->ops->fence_value_str) {
char value[64];
+   bool success;

-   parent->ops->pt_value_str(pt, value, sizeof(value));
-   seq_printf(s, ": %s", value);
-   if (fence) {
-   parent->ops->timeline_value_str(parent, value,
-   sizeof(value));
-   seq_printf(s, " / %s", value);
+   pt->ops->fence_value_str(pt, value, sizeof(value));
+   success = strlen(value);
+
+   if (success)
+   seq_printf(s, ": %s", value);
+
+   if (success && fence) {
+   pt->ops->timeline_value_str(pt, value, sizeof(value));
+
+   if (strlen(value))
+   seq_printf(s, " / %s", value);
}
}

@@ -138,7 +144,7 @@ static void sync_print_obj(struct seq_file *s, struct 
sync_timeline *obj)
list_for_each(pos, &obj->child_list_head) {
struct sync_pt *pt =
container_of(pos, struct sync_pt, child_list);
-   sync_print_pt(s, pt, false);
+   sync_print_pt(s, &pt->base, false);
}
spin_unlock_irqrestore(&obj->child_list_lock, flags);
  }
@@ -153,11 +159,7 @@ static void sync_print_fence(struct seq_file *s, struct 
sync_fence *fence)
   sync_status_str(atomic_read(&fence->status)));

for (i = 0; i < fence->num_fences; ++i) {
-   struct sync_pt *pt =
-   container_of(fence->cbs[i].sync_pt,
-struct sync_pt, base);
-
-   sync_print_pt(s, pt, true);
+   sync_print_pt(s, fence->cbs[i].sync_pt, true);
}

spin_lock_irqsave(&fence->wq.lock, flags);


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


Re: [Intel-gfx] [RFC 01/12] staging/android/sync: Support sync points created from dma-fences

2015-11-23 Thread Maarten Lankhorst
Op 23-11-15 om 12:34 schreef john.c.harri...@intel.com:
> From: Tvrtko Ursulin 
>
> Debug output assumes all sync points are built on top of Android sync points
> and when we start creating them from dma-fences will NULL ptr deref unless
> taught about this.
>
> Signed-off-by: Tvrtko Ursulin 
> Cc: Maarten Lankhorst 
> Cc: de...@driverdev.osuosl.org
> Cc: Riley Andrews 
> Cc: Greg Kroah-Hartman 
> Cc: Arve Hjønnevåg 
>
Could this be upstreamed already? It makes the second patch possible and 
doesn't break current staging..
Signed-off-by: Maarten Lankhorst 
___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx


Re: [Intel-gfx] [RFC 02/12] staging/android/sync: add sync_fence_create_dma

2015-11-23 Thread Maarten Lankhorst
Op 23-11-15 om 12:34 schreef john.c.harri...@intel.com:
> From: Maarten Lankhorst 
>
> This allows users of dma fences to create a android fence.
>
> v2: Added kerneldoc. (Tvrtko Ursulin).
>
> Signed-off-by: Maarten Lankhorst 
> Signed-off-by: Tvrtko Ursulin 
> Cc: Maarten Lankhorst 
> Cc: Daniel Vetter 
> Cc: Jesse Barnes 
> Cc: de...@driverdev.osuosl.org
> Cc: Riley Andrews 
> Cc: Greg Kroah-Hartman 
> Cc: Arve Hjønnevåg 
> ---
>  drivers/staging/android/sync.c | 13 +
>  drivers/staging/android/sync.h | 12 +++-
>  2 files changed, 20 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c
> index f83e00c..7f0e919 100644
> --- a/drivers/staging/android/sync.c
> +++ b/drivers/staging/android/sync.c
> @@ -188,7 +188,7 @@ static void fence_check_cb_func(struct fence *f, struct 
> fence_cb *cb)
>  }
>  
>  /* TODO: implement a create which takes more that one sync_pt */
> -struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
> +struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt)
>  {
>   struct sync_fence *fence;
>  
> @@ -199,16 +199,21 @@ struct sync_fence *sync_fence_create(const char *name, 
> struct sync_pt *pt)
>   fence->num_fences = 1;
>   atomic_set(&fence->status, 1);
>  
> - fence->cbs[0].sync_pt = &pt->base;
> + fence->cbs[0].sync_pt = pt;
>   fence->cbs[0].fence = fence;
> - if (fence_add_callback(&pt->base, &fence->cbs[0].cb,
> -fence_check_cb_func))
> + if (fence_add_callback(pt, &fence->cbs[0].cb, fence_check_cb_func))
>   atomic_dec(&fence->status);
>  
>   sync_fence_debug_add(fence);
>  
>   return fence;
>  }
> +EXPORT_SYMBOL(sync_fence_create_dma);
> +
> +struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt)
> +{
> + return sync_fence_create_dma(name, &pt->base);
> +}
>  EXPORT_SYMBOL(sync_fence_create);
>  
>  struct sync_fence *sync_fence_fdget(int fd)
> diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h
> index 61f8a3a..798cd56 100644
> --- a/drivers/staging/android/sync.h
> +++ b/drivers/staging/android/sync.h
> @@ -250,10 +250,20 @@ void sync_pt_free(struct sync_pt *pt);
>   * @pt:  sync_pt to add to the fence
>   *
>   * Creates a fence containg @pt.  Once this is called, the fence takes
> - * ownership of @pt.
> + * a reference on @pt.
>   */
>  struct sync_fence *sync_fence_create(const char *name, struct sync_pt *pt);
No it doesn't.
> +/**
> + * sync_fence_create_dma() - creates a sync fence from dma-fence
> + * @name:name of fence to create
> + * @pt:  dma-fence to add to the fence
> + *
> + * Creates a fence containg @pt.  Once this is called, the fence takes
> + * a reference on @pt.
> + */
No it doesn't.
> +struct sync_fence *sync_fence_create_dma(const char *name, struct fence *pt);
> +
>  /*
>   * API for sync_fence consumers
>   */

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


Re: [Intel-gfx] [PATCH i-g-t v6] lib/igt_core: Prefer CLOCK_MONOTONIC_RAW

2015-11-23 Thread Joonas Lahtinen
This could be merged?

On pe, 2015-11-20 at 13:57 +0200, Joonas Lahtinen wrote:
> CLOCK_MONOTONIC_RAW is not affected by NTP, so it should be THE clock
> used for timing execution of tests.
> 
> When fetching either the starting or ending time of a test, show the
> time as -1.000s.
> 
> v6:
> - Whitespace corrections (Chris)
> 
> v5:
> - Do not use C99 style comments (Chris)
> 
> v4:
> - Introduce time_valid macro (Chris)
> - Reduce amount of boilerplate code for calculating elapsed time
> 
> v3:
> - Do not exit directly from handler (Chris)
> - Show elapsed time as -1 if it is not calculable
> 
> v2:
> - Cache the used clock (Chris)
> - Do not change the clock during execution
> - Spit out and error if monotonic time can not be read
> 
> Cc: Thomas Wood 
> Reviewed-by: Chris Wilson 
> Signed-off-by: Joonas Lahtinen 
> ---
>  lib/igt_core.c | 54 +---
> --
>  1 file changed, 41 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/igt_core.c b/lib/igt_core.c
> index 04a0ab2..84cf8d2 100644
> --- a/lib/igt_core.c
> +++ b/lib/igt_core.c
> @@ -220,6 +220,7 @@ static char *run_single_subtest = NULL;
>  static bool run_single_subtest_found = false;
>  static const char *in_subtest = NULL;
>  static struct timespec subtest_time;
> +static clockid_t igt_clock = (clockid_t)-1;
>  static bool in_fixture = false;
>  static bool test_with_subtests = false;
>  static bool in_atexit_handler = false;
> @@ -337,14 +338,49 @@ static void kmsg(const char *format, ...)
>   fclose(file);
>  }
>  
> -static void gettime(struct timespec *ts)
> +#define time_valid(ts) ((ts)->tv_sec || (ts)->tv_nsec)
> +
> +static double
> +time_elapsed(struct timespec *then,
> +  struct timespec* now)
> +{
> + double elapsed = -1.;
> +
> + if (time_valid(then) && time_valid(now)) {
> + elapsed = now->tv_sec - then->tv_sec;
> + elapsed += (now->tv_nsec - then->tv_nsec) * 1e-9;
> + }
> +
> + return elapsed;
> +}
> +
> +static int gettime(struct timespec *ts)
>  {
>   memset(ts, 0, sizeof(*ts));
> + errno = 0;
>  
> + /* Stay on the same clock for consistency. */
> + if (igt_clock != (clockid_t)-1) {
> + if (clock_gettime(igt_clock, ts))
> + goto error;
> + return 0;
> + }
> +
> +#ifdef CLOCK_MONOTONIC_RAW
> + if (!clock_gettime(igt_clock = CLOCK_MONOTONIC_RAW, ts))
> + return 0;
> +#endif
>  #ifdef CLOCK_MONOTONIC_COARSE
> - if (clock_gettime(CLOCK_MONOTONIC_COARSE, ts))
> + if (!clock_gettime(igt_clock = CLOCK_MONOTONIC_COARSE, ts))
> + return 0;
>  #endif
> - clock_gettime(CLOCK_MONOTONIC, ts);
> + if (!clock_gettime(igt_clock = CLOCK_MONOTONIC, ts))
> + return 0;
> +error:
> + igt_warn("Could not read monotonic time: %s\n",
> +  strerror(errno));
> +
> + return -errno;
>  }
>  
>  bool __igt_fixture(void)
> @@ -831,15 +867,11 @@ static void exit_subtest(const char *)
> __attribute__((noreturn));
>  static void exit_subtest(const char *result)
>  {
>   struct timespec now;
> - double elapsed;
>  
>   gettime(&now);
> - elapsed = now.tv_sec - subtest_time.tv_sec;
> - elapsed += (now.tv_nsec - subtest_time.tv_nsec) * 1e-9;
> -
>   printf("%sSubtest %s: %s (%.3fs)%s\n",
>  (!__igt_plain_output) ? "\x1b[1m" : "",
> -in_subtest, result, elapsed,
> +in_subtest, result, time_elapsed(&subtest_time,
> &now),
>  (!__igt_plain_output) ? "\x1b[0m" : "");
>   fflush(stdout);
>  
> @@ -1088,12 +1120,9 @@ void igt_exit(void)
>  
>   if (!test_with_subtests) {
>   struct timespec now;
> - double elapsed;
>   const char *result;
>  
>   gettime(&now);
> - elapsed = now.tv_sec - subtest_time.tv_sec;
> - elapsed += (now.tv_nsec - subtest_time.tv_nsec) * 1e
> -9;
>  
>   switch (igt_exitcode) {
>   case IGT_EXIT_SUCCESS:
> @@ -1109,8 +1138,7 @@ void igt_exit(void)
>   result = "FAIL";
>   }
>  
> -
> - printf("%s (%.3fs)\n", result, elapsed);
> + printf("%s (%.3fs)\n", result,
> time_elapsed(&subtest_time, &now));
>   exit(igt_exitcode);
>   }
>  
-- 
Joonas Lahtinen
Open Source Technology Center
Intel Corporation

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


[Intel-gfx] [RFC 23/37] drm/i915: set request 'head' on allocation not in add_request()

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

The current setting of request 'head' in add_request() isn't useful
and has been replaced for purposes of knowing how full the ring is
by 'postfix'. So we can instead use 'head' to define and locate the
entire range spanned by a request.

Pictorially,
headpostfix   tail
   |  ||
   v  vv
ringbuffer: [..S..P...I.]

where S, P, and I are the Start of the request, start of the Postfix,
and the user-Interrupt respectively. To help with debugging, this
request's tail should also be the next request's head, this showing
that all ringbuffer usage is accounted for.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1131fe3..55317b1ca 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2555,7 +2555,6 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
struct intel_engine_cs *ring;
struct drm_i915_private *dev_priv;
struct intel_ringbuffer *ringbuf;
-   u32 request_start;
int ret;
 
if (WARN_ON(request == NULL))
@@ -2572,7 +2571,6 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
 */
intel_ring_reserved_space_use(ringbuf);
 
-   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
@@ -2624,8 +2622,6 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
/* Not allowed to fail! */
WARN(ret, "emit|add_request failed: %d!\n", ret);
 
-   request->head = request_start;
-
/* Whilst this request exists, batch_obj will be on the
 * active_list, and so will hold the active reference. Only when this
 * request is retired will the the batch_obj be moved onto the
@@ -3127,6 +3123,7 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring,
i915_gem_request_cancel(req);
return ret;
}
+   req->head = intel_ring_get_tail(req->ringbuf);
 
*req_out = req;
return 0;
-- 
1.9.1

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


[Intel-gfx] [RFC 15/37] drm/i915: add i915_wait_request() call after i915_add_request_no_flush()

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Per-context initialisation GPU instructions (which are injected directly
into the ringbuffer rather than being submitted as a batch) should not
be allowed to mix with user-generated batches in the same submission; it
will cause confusion for the GuC (which might merge a subsequent
preemptive request with the non-preemptive iniitalisation code), and for
the scheduler, which wouldn't know how to reinject a non-batch request
if it were the victim of preemption.

Therefore, we should wait for the iniitalisation request to complete
before making the newly-initialised context available for user-mode
submissions.

Here, we add a call to i915_wait_request() after each existing call to
i915_add_request_no_flush() (in i915_gem_init_hw(), for the default
per-engine contexts, and intel_lr_context_deferred_create(), for all
others).

Adapted from Alex's earlier patch, which added the wait only to
intel_lr_context_render_state_init(), and which John Harrison was
dubious about:
"JH thinks this isn't a good idea. Why do we need to wait?".
But we will need to after all, if only because of preemption.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem.c  | 7 +++
 drivers/gpu/drm/i915/intel_lrc.c | 7 +++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 785310c..895f1e5 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5332,6 +5332,13 @@ i915_gem_init_hw(struct drm_device *dev)
}
 
i915_add_request_no_flush(req);
+
+   /* GuC firmware will try to collapse its DPC work queue if the 
new one
+* is for same context. So the following breadcrumb could be 
amended to
+* this batch and submitted as one batch. Wait here to make 
sure the
+* context state init is finished before any other submission 
to GuC. */
+   if (i915.enable_guc_submission)
+   ret = i915_wait_request(req);
}
 
 out:
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e99ae53..ca7bc61 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2635,6 +2635,13 @@ int intel_lr_context_deferred_alloc(struct intel_context 
*ctx,
goto error_ringbuf;
}
i915_add_request_no_flush(req);
+
+   /* GuC firmware will try to collapse its DPC work queue if the 
new one
+* is for same context. So the following breadcrumb could be 
amended to
+* this batch and submitted as one batch. Wait here to make 
sure the
+* context state init is finished before any other submission 
to GuC. */
+   if (i915.enable_guc_submission)
+   ret = i915_wait_request(req);
}
 
intel_runtime_pm_put(dev->dev_private);
-- 
1.9.1

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


[Intel-gfx] [RFC 32/37] drm/i915/preempt: add hook to catch 'unexpected' ring submissions

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Author: John Harrison 
Date:   Thu Apr 10 10:41:06 2014 +0100

The scheduler needs to know what each seqno that pops out of the ring is
referring to. This change adds a hook into the the 'submit some random
work that got forgotten about' clean up code to inform the scheduler
that a new seqno has been sent to the ring for some non-batch buffer
operation.

Reworked for latest scheduler+preemption by Dave Gordon: with the newer
implementation, knowing about untracked requests is merely helpful for
debugging rather than being mandatory, as we have already taken steps to
prevent untracked requests intruding at awkward moments!

For: VIZ-2021
Signed-off-by: John Harrison 
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem.c   |  4 
 drivers/gpu/drm/i915/i915_gpu_error.c |  2 ++
 drivers/gpu/drm/i915/i915_scheduler.c | 24 
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 4 files changed, 31 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 48a57c0..59de18e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2601,6 +2601,10 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
WARN_ON(request->seqno != dev_priv->last_seqno);
}
 
+   /* Notify the scheduler, if it doesn't already track this request */
+   if (!request->scheduler_qe)
+   i915_scheduler_fly_request(request);
+
/* 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
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 2d9dd3f..72c861e 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1331,6 +1331,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->ringbuffer_gtt = 
i915_gem_obj_ggtt_offset(request->ringbuf->obj);
erq->scheduler_state = !sqe ? 'u' :
i915_scheduler_queue_status_chr(sqe->status);
+   if (request->scheduler_flags & i915_req_sf_untracked)
+   erq->scheduler_state = 'U';
}
}
 }
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 0c2344e..e1d9390 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -432,6 +432,30 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
return 0;
 }
 
+/* An untracked request is being launched ... */
+void i915_scheduler_fly_request(struct drm_i915_gem_request *req)
+{
+   struct drm_i915_private *dev_priv = req->i915;
+   struct i915_scheduler *scheduler = dev_priv->scheduler;
+
+   DRM_DEBUG_DRIVER("%s: uniq %d, seqno %08x snuck in ...\n",
+   req->ring->name, req->uniq, req->seqno);
+
+   BUG_ON(!scheduler);
+   BUG_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
+
+   /* This shouldn't happen */
+   WARN_ON(i915_scheduler_is_ring_busy(req->ring));
+
+   /* We don't expect to see nodes that are already tracked */
+   if (!WARN_ON(req->scheduler_qe)) {
+   /* Untracked node, must not be inside scheduler submission path 
*/
+   WARN_ON((scheduler->flags[req->ring->id] & i915_sf_submitting));
+   scheduler->stats[req->ring->id].non_batch++;
+   req->scheduler_flags |= i915_req_sf_untracked;
+   }
+}
+
 static int i915_scheduler_fly_node(struct i915_scheduler_queue_entry *node)
 {
struct drm_i915_private *dev_priv = node->params.dev->dev_private;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 2ca5433..f1ff067 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -198,6 +198,7 @@ booli915_scheduler_is_ring_flying(struct 
intel_engine_cs *ring);
 booli915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
 booli915_scheduler_is_ring_busy(struct intel_engine_cs *ring);
 voidi915_gem_scheduler_work_handler(struct work_struct *work);
+voidi915_scheduler_fly_request(struct drm_i915_gem_request *req);
 int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
 int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
   unsigned long stamp, bool is_locked);
-- 
1.9.1

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


[Intel-gfx] [RFC 36/37] drm/i915/preempt: update scheduler parameters to enable preemption

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_params.c| 4 ++--
 drivers/gpu/drm/i915/i915_scheduler.c | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c 
b/drivers/gpu/drm/i915/i915_params.c
index 72dff7c..7db0f83 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -54,7 +54,7 @@ struct i915_params i915 __read_mostly = {
.edp_vswing = 0,
.enable_guc_submission = true,
.guc_log_level = -1,
-   .scheduler_override = i915_so_no_preemption,
+   .scheduler_override = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -194,4 +194,4 @@ MODULE_PARM_DESC(guc_log_level,
"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
 
 module_param_named(scheduler_override, i915.scheduler_override, int, 0600);
-MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 4)");
+MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 0)");
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 65e321d..9bc9614 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -208,7 +208,7 @@ int i915_scheduler_init(struct drm_device *dev)
scheduler->priority_level_max = 1023;
scheduler->priority_level_bump= 50;
scheduler->priority_level_preempt = 900;
-   scheduler->min_flying = 2;
+   scheduler->min_flying = 8;
scheduler->file_queue_max = 64;
scheduler->dump_flags = i915_sf_dump_force   |
i915_sf_dump_details |
-- 
1.9.1

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


[Intel-gfx] [RFC 30/37] drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is busy

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

If the scheduler is busy (e.g. processing a preemption) it will need to
be able to acquire the struct_mutex, so we can't allow untracked
requests to bypass the scheduler and go directly to the hardware (much
confusion will result). Since untracked requests are used only for
initialisation of logical contexts, we can avoid the problem by forcing
any thread trying to initialise a context at an unfortunate time to drop
the mutex and retry later.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 6 ++
 drivers/gpu/drm/i915/i915_scheduler.h | 1 +
 drivers/gpu/drm/i915/intel_lrc.c  | 8 
 3 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 81ac88b..a037ba2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -1778,6 +1778,12 @@ bool i915_scheduler_is_ring_preempting(struct 
intel_engine_cs *ring)
return false;
 }
 
+bool i915_scheduler_is_ring_busy(struct intel_engine_cs *ring)
+{
+   /* Currently only pre-emption ties up the scheduler. */
+   return i915_scheduler_is_ring_preempting(ring);
+}
+
 /*
  * Used by TDR to distinguish hung rings (not moving but with work to do)
  * from idle rings (not moving because there is nothing to do).
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 569215a..d5f4af3 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -195,6 +195,7 @@ booli915_scheduler_notify_request(struct 
drm_i915_gem_request *req);
 voidi915_scheduler_wakeup(struct drm_device *dev);
 booli915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
 booli915_scheduler_is_ring_preempting(struct intel_engine_cs *ring);
+booli915_scheduler_is_ring_busy(struct intel_engine_cs *ring);
 voidi915_gem_scheduler_work_handler(struct work_struct *work);
 int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
 int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index b7d9fbd..1ccb50d 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2582,6 +2582,14 @@ int intel_lr_context_deferred_alloc(struct intel_context 
*ctx,
WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
WARN_ON(ctx->engine[ring->id].state);
 
+   /* Don't submit non-scheduler requests while the scheduler is busy */
+   if (i915_scheduler_is_ring_busy(ring)) {
+   mutex_unlock(&dev->struct_mutex);
+   msleep(1);
+   mutex_lock(&dev->struct_mutex);
+   return -EAGAIN;
+   }
+
intel_runtime_pm_get(dev->dev_private);
 
context_size = round_up(intel_lr_context_size(ring), 4096);
-- 
1.9.1

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


[Intel-gfx] [RFC 27/37] drm/i915/preempt: scheduler logic for queueing preemptive requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This is the very first stage of the scheduler's preemption logic, where
it determines whether a request should be marked as potentially
preemptive, at the point where it is added to the scheduler's queue.
Subsequent logic will determine how to handle the request on the basis
of the flags set here.

Actually-preemptive requests are disabled via a module parameter at this
early stage, as the rest of the logic to process them isn't in place
yet.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_params.c|  4 +--
 drivers/gpu/drm/i915/i915_scheduler.c | 53 +++
 2 files changed, 49 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c 
b/drivers/gpu/drm/i915/i915_params.c
index 7db0f83..72dff7c 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -54,7 +54,7 @@ struct i915_params i915 __read_mostly = {
.edp_vswing = 0,
.enable_guc_submission = true,
.guc_log_level = -1,
-   .scheduler_override = 0,
+   .scheduler_override = i915_so_no_preemption,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -194,4 +194,4 @@ MODULE_PARM_DESC(guc_log_level,
"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
 
 module_param_named(scheduler_override, i915.scheduler_override, int, 0600);
-MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 0)");
+MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 4)");
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 16d067e..50ff8b7 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -58,10 +58,13 @@ bool i915_scheduler_is_enabled(struct drm_device *dev)
 
 const char *i915_qe_state_str(struct i915_scheduler_queue_entry *node)
 {
+   uint32_t sched_flags = node->params.request->scheduler_flags;
static char str[50];
char*ptr = str;
 
*(ptr++) = node->bumped ? 'B' : '-',
+   *(ptr++) = (sched_flags & i915_req_sf_preempt) ? 'P' : '-';
+   *(ptr++) = (sched_flags & i915_req_sf_was_preempt) ? 'p' : '-';
*(ptr++) = i915_gem_request_completed(node->params.request) ? 'C' : '-';
 
*ptr = 0;
@@ -84,6 +87,12 @@ char i915_scheduler_queue_status_chr(enum 
i915_scheduler_queue_status status)
case i915_sqs_flying:
return 'F';
 
+   case i915_sqs_overtaking:
+   return 'O';
+
+   case i915_sqs_preempted:
+   return 'P';
+
case i915_sqs_complete:
return 'C';
 
@@ -115,6 +124,12 @@ const char *i915_scheduler_queue_status_str(
case i915_sqs_flying:
return "Flying";
 
+   case i915_sqs_overtaking:
+   return "Overtaking";
+
+   case i915_sqs_preempted:
+   return "Preempted";
+
case i915_sqs_complete:
return "Complete";
 
@@ -213,7 +228,7 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
struct i915_scheduler_queue_entry  *node;
struct i915_scheduler_queue_entry  *test;
unsigned long   flags;
-   boolnot_flying, found;
+   boolnot_flying, want_preempt, found;
int i, j, r;
int incomplete = 0;
 
@@ -385,6 +400,25 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
not_flying = i915_scheduler_count_flying(scheduler, ring) <
 scheduler->min_flying;
 
+   want_preempt = node->priority >= scheduler->priority_level_preempt;
+
+   if (i915.scheduler_override & i915_so_no_preemption)
+   want_preempt = false;
+
+   /* Pre-emption is not yet implemented in non-execlist mode */
+   if (!i915.enable_execlists)
+   want_preempt = false;
+
+   /* Pre-emption is not yet implemented in non-GUC mode */
+   if (!i915.enable_guc_submission)
+   want_preempt = false;
+
+   if (want_preempt) {
+   node->params.request->scheduler_flags |=
+   i915_req_sf_was_preempt | i915_req_sf_preempt;
+   scheduler->stats[ring->id].preempts_queued++;
+   }
+
scheduler->stats[ring->id].queued++;
 
trace_i915_scheduler_queue(ring, node);
@@ -392,7 +426,7 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
 
spin_unlock_irqrestore(&scheduler->lock, flags);
 
-   if (not_flying)
+   if (not_flying || want_preempt)
i915_scheduler_submit(ring, true);
 
return 0;
@@ -403,19 +437,26 @@ static int i915_scheduler_fly_node(struct 
i915_scheduler_queue_entry *node)
struct drm_i915_private *dev_priv = node->params.dev->dev_private;
struct i915_scheduler   *scheduler = dev_priv->scheduler;
struct intel_

[Intel-gfx] [RFC 25/37] drm/i915/sched: include scheduler state in error capture

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   | 1 +
 drivers/gpu/drm/i915/i915_gpu_error.c | 5 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9bece1e..06dff5a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -584,6 +584,7 @@ struct drm_i915_error_state {
u32 tail;
u32 submission_count;
u64 ringbuffer_gtt;
+   char scheduler_state;
} *requests;
 
struct {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 346c831..2d9dd3f 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -614,10 +614,12 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
err_printf(m, "  seqno 0x%08x, ringbuf 0x%llx "
  "head 0x%08x tail 0x%08x, "
  "emitted %ld, %d submissions, "
+ "sched %c "
  "ctx_desc 0x%08x_%08x\n",
erq->seqno, erq->ringbuffer_gtt,
erq->head, erq->tail,
erq->jiffies, erq->submission_count,
+   erq->scheduler_state,
upper_32_bits(erq->ctx_desc),
lower_32_bits(erq->ctx_desc));
}
@@ -1296,6 +1298,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
 
count = 0;
list_for_each_entry(request, &ring->request_list, list) {
+   struct i915_scheduler_queue_entry *sqe = 
request->scheduler_qe;
struct intel_context *ctx = request->ctx;
struct drm_i915_error_request *erq;
 
@@ -1326,6 +1329,8 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->head = request->head;
erq->submission_count = request->elsp_submitted;
erq->ringbuffer_gtt = 
i915_gem_obj_ggtt_offset(request->ringbuf->obj);
+   erq->scheduler_state = !sqe ? 'u' :
+   i915_scheduler_queue_status_chr(sqe->status);
}
}
 }
-- 
1.9.1

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


[Intel-gfx] [RFC 20/37] drm/i915/error: enhanced error capture of requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Record a few more things about the requests outstanding at the time of
capture ...

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |  6 +-
 drivers/gpu/drm/i915/i915_gpu_error.c | 20 +++-
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9b4ab5d..9e0e9da 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -570,8 +570,9 @@ struct drm_i915_error_state {
struct intel_ringbuffer req_ring;
 
struct drm_i915_error_object {
-   int page_count;
u64 gtt_offset;
+   bool is_ppgtt;
+   int page_count;
u32 *pages[0];
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, 
*wa_batchbuffer, *ctx, *hws_page;
 
@@ -579,7 +580,10 @@ struct drm_i915_error_state {
u64 ctx_desc;
long jiffies;
u32 seqno;
+   u32 head;
u32 tail;
+   u32 submission_count;
+   u64 ringbuffer_gtt;
} *requests;
 
struct {
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index a40c947..e3777ba 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -490,7 +490,8 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf 
*m,
err_printf(m, " (submitted by %s [%d])",
   error->ring[i].comm,
   error->ring[i].pid);
-   err_printf(m, " --- gtt_offset = 0x%08x %08x; %d 
pages\n",
+   err_printf(m, " --- %sgtt_offset = 0x%08x %08x; %d 
pages\n",
+  obj->is_ppgtt ? "pp" : "g",
   upper_32_bits(obj->gtt_offset),
   lower_32_bits(obj->gtt_offset),
   obj->page_count);
@@ -513,9 +514,13 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
for (j = 0; j < error->ring[i].num_requests; j++) {
struct drm_i915_error_request *erq;
erq = &error->ring[i].requests[j];
-   err_printf(m, "  seqno 0x%08x, tail 0x%08x, "
-   "emitted %ld, ctx_desc 0x%08x_%08x\n",
-   erq->seqno, erq->tail, erq->jiffies,
+   err_printf(m, "  seqno 0x%08x, ringbuf 0x%llx "
+ "head 0x%08x tail 0x%08x, "
+ "emitted %ld, %d submissions, "
+ "ctx_desc 0x%08x_%08x\n",
+   erq->seqno, erq->ringbuffer_gtt,
+   erq->head, erq->tail,
+   erq->jiffies, erq->submission_count,
upper_32_bits(erq->ctx_desc),
lower_32_bits(erq->ctx_desc));
}
@@ -708,6 +713,8 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
reloc_offset = dst->gtt_offset;
if (i915_is_ggtt(vm))
vma = i915_gem_obj_to_ggtt(src);
+   else
+   dst->is_ppgtt = true;
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
   vma && (vma->bound & GLOBAL_BIND) &&
   reloc_offset + num_pages * PAGE_SIZE <= 
dev_priv->gtt.mappable_end);
@@ -1218,7 +1225,10 @@ static void i915_gem_record_rings(struct drm_device *dev,
erq->ctx_desc = intel_lr_context_descriptor(ctx, ring);
erq->jiffies = request->emitted_jiffies;
erq->seqno = request->seqno;
-   erq->tail = request->postfix;
+   erq->tail = request->tail;
+   erq->head = request->head;
+   erq->submission_count = request->elsp_submitted;
+   erq->ringbuffer_gtt = 
i915_gem_obj_ggtt_offset(request->ringbuf->obj);
}
}
 }
-- 
1.9.1

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


[Intel-gfx] [RFC 33/37] drm/i915/preempt: Refactor intel_lr_context_reset()

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

After preemption, we need to empty out the ringbuffers associated
with preempted requests, so that the scheduler has a clean ring
into which to (re-)insert requests (not necessarily in the same
order as before they were preempted).

So this patch refactors the existing routine intel_lr_context_reset()
into a new inner core intel_lr_context_resync() which just updates
a context and the associated ringbuffer, and an outer wrapper which
implements the original operation of intel_lr_context_reset() in
terms of resync().

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem_context.c |  2 +-
 drivers/gpu/drm/i915/intel_lrc.c| 77 +
 drivers/gpu/drm/i915/intel_lrc.h|  6 ++-
 3 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index a4dda23..3726cd8 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -341,7 +341,7 @@ void i915_gem_context_reset(struct drm_device *dev)
struct intel_context *ctx;
 
list_for_each_entry(ctx, &dev_priv->context_list, link) {
-   intel_lr_context_reset(dev, ctx);
+   intel_lr_context_reset(ctx);
}
 
return;
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 1ccb50d..e00d9385 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2669,39 +2669,62 @@ error_pm:
return ret;
 }
 
-void intel_lr_context_reset(struct drm_device *dev,
-   struct intel_context *ctx)
+/*
+ * Empty the ringbuffer associated with the specified request
+ * by updating the ringbuffer 'head' to the value of 'tail', or,
+ * if 'rezero' is true, setting both 'head' and 'tail' to zero.
+ * Then propagate the change to the associated context image.
+ */
+void intel_lr_context_resync(struct intel_context *ctx,
+struct intel_engine_cs *ring,
+bool rezero)
 {
-   struct drm_i915_private *dev_priv = dev->dev_private;
-   struct intel_engine_cs *ring;
-   int i;
+   enum intel_ring_id ring_id = ring->id;
+   struct drm_i915_gem_object *ctx_obj;
+   struct intel_ringbuffer *ringbuf;
+   struct page *page;
+   uint32_t *reg_state;
 
-   for_each_ring(ring, dev_priv, i) {
-   struct drm_i915_gem_object *ctx_obj =
-   ctx->engine[ring->id].state;
-   struct intel_ringbuffer *ringbuf =
-   ctx->engine[ring->id].ringbuf;
-   uint32_t *reg_state;
-   struct page *page;
+   ctx_obj = ctx->engine[ring_id].state;
+   ringbuf = ctx->engine[ring_id].ringbuf;
 
-   if (!ctx_obj)
-   continue;
+   /*
+* When resetting, a hardware context might be as-yet-unused
+* and therefore not-yet-allocated. In other situations, the
+* ringbuffer and context object must already exist.
+*/
+   if (WARN_ON(!ringbuf != !ctx_obj))
+   return;
+   if (!i915_reset_in_progress(&ctx->i915->gpu_error))
+   WARN_ON(!ringbuf || !ctx_obj);
+   if (!ringbuf || !ctx_obj)
+   return;
+   if (WARN_ON(i915_gem_object_get_pages(ctx_obj)))
+   return;
 
-   if (i915_gem_object_get_pages(ctx_obj)) {
-   WARN(1, "Failed get_pages for context obj\n");
-   continue;
-   }
-   page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
-   reg_state = kmap_atomic(page);
+   page = i915_gem_object_get_page(ctx_obj, LRC_STATE_PN);
+   reg_state = kmap_atomic(page);
 
-   reg_state[CTX_RING_HEAD+1] = 0;
-   reg_state[CTX_RING_TAIL+1] = 0;
+   if (rezero)
+   ringbuf->tail = 0;
+   ringbuf->head = ringbuf->tail;
+   ringbuf->last_retired_head = -1;
+   intel_ring_update_space(ringbuf);
 
-   kunmap_atomic(reg_state);
+   reg_state[CTX_RING_HEAD+1] = ringbuf->head;
+   reg_state[CTX_RING_TAIL+1] = ringbuf->tail;
 
-   ringbuf->head = 0;
-   ringbuf->tail = 0;
-   ringbuf->last_retired_head = -1;
-   intel_ring_update_space(ringbuf);
+   kunmap_atomic(reg_state);
+}
+
+void intel_lr_context_reset(struct intel_context *ctx)
+{
+   struct drm_i915_private *dev_priv = ctx->i915;
+   struct intel_engine_cs *ring;
+   int i;
+
+   for_each_ring(ring, dev_priv, i) {
+   intel_lr_context_resync(ctx, ring, true);
}
 }
+
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 8ed6c18..fa2f814 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/g

[Intel-gfx] [RFC 35/37] drm/i915/preempt: update (LRC) ringbuffer-filling code to create preemptive requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This patch refactors the rinbuffer-level code (in execlists/GuC mode
only) and enhances it so that it can emit the proper sequence of opcode
for preemption requests.

A preemption request is similar to an batch submission, but doesn't
actually invoke a batchbuffer, the purpose being simply to get the
engine to stop what it's doing so that the scheduler can then send it a
new workload instead.

Preemption requests use different locations in the hardware status page
to hold the 'active' and 'done' seqnos from regular batches, so that
information pertaining to a preempted batch is not overwritten. Also,
whereas a regular batch clears its 'active' flag when it finishes (so
that TDR knows it's no longer to blame), preemption requests leave this
set and the driver clears it once the completion of the preemption
request has been noticed. Only one preemption (per ring) can be in
progress at one time, so this handshake ensures correct sequencing of
the request between the GPU and CPU.

Actually-preemptive requests are still disabled via a module parameter
at this stage, but all the components should now be ready for us to turn
it on :)

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/intel_lrc.c | 175 ++-
 1 file changed, 134 insertions(+), 41 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index e00d9385..e13491e 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -748,7 +748,7 @@ intel_logical_ring_advance_and_submit(struct 
drm_i915_gem_request *request)
struct drm_i915_private *dev_priv = request->i915;
struct i915_guc_client *client = dev_priv->guc.execbuf_client;
const static bool fake = false; /* true => only pretend to preempt */
-   bool preemptive = false;/* for now */
+   bool preemptive;
 
intel_logical_ring_advance(request->ringbuf);
 
@@ -757,6 +757,7 @@ intel_logical_ring_advance_and_submit(struct 
drm_i915_gem_request *request)
if (intel_ring_stopped(ring))
return;
 
+   preemptive = (request->scheduler_flags & i915_req_sf_preempt) != 0;
if (preemptive && dev_priv->guc.preempt_client && !fake)
client = dev_priv->guc.preempt_client;
 
@@ -951,6 +952,117 @@ int intel_execlists_submission(struct 
i915_execbuffer_params *params,
 }
 
 /*
+ * This function stores the specified constant value in the (index)th DWORD of 
the
+ * hardware status page (execlist mode only). See separate code for legacy 
mode.
+ */
+static void
+emit_store_dw_index(struct drm_i915_gem_request *req, uint32_t value, uint32_t 
index)
+{
+   struct intel_ringbuffer *ringbuf = req->ringbuf;
+   uint64_t hwpa = req->ring->status_page.gfx_addr;
+   hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+   intel_logical_ring_emit(ringbuf, MI_STORE_DWORD_IMM_GEN4 | 
MI_GLOBAL_GTT);
+   intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+   intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+   intel_logical_ring_emit(ringbuf, value);
+
+   req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * This function stores the specified register value in the (index)th DWORD
+ * of the hardware status page (execlist mode only). See separate code for
+ * legacy mode.
+ */
+static void
+emit_store_reg_index(struct drm_i915_gem_request *req, uint32_t reg, uint32_t 
index)
+{
+   struct intel_ringbuffer *ringbuf = req->ringbuf;
+   uint64_t hwpa = req->ring->status_page.gfx_addr;
+   hwpa += index << MI_STORE_DWORD_INDEX_SHIFT;
+
+   intel_logical_ring_emit(ringbuf, (MI_STORE_REG_MEM+1) | MI_GLOBAL_GTT);
+   intel_logical_ring_emit(ringbuf, reg);
+   intel_logical_ring_emit(ringbuf, lower_32_bits(hwpa));
+   intel_logical_ring_emit(ringbuf, upper_32_bits(hwpa)); /* GEN8+ */
+
+   req->ring->gpu_caches_dirty = true;
+}
+
+/*
+ * Emit the commands to execute when preparing to start a batch
+ *
+ * The GPU will log the seqno of the batch before it starts
+ * running any of the commands to actually execute that batch
+ */
+static void
+emit_preamble(struct drm_i915_gem_request *req)
+{
+   struct intel_ringbuffer *ringbuf = req->ringbuf;
+   uint32_t seqno = i915_gem_request_get_seqno(req);
+
+   BUG_ON(!seqno);
+   if (req->scheduler_flags & i915_req_sf_preempt)
+   emit_store_dw_index(req, seqno, I915_PREEMPTIVE_ACTIVE_SEQNO);
+   else
+   emit_store_dw_index(req, seqno, I915_BATCH_ACTIVE_SEQNO);
+
+   intel_logical_ring_emit(ringbuf, MI_REPORT_HEAD);
+   intel_logical_ring_emit(ringbuf, MI_NOOP);
+
+   req->ring->gpu_caches_dirty = true;
+}
+
+static void
+emit_relconsts_mode(struct i915_execbuffer_params *params)
+{
+   if (params->ctx->relative_constants_mode != params->instp_mode) {
+   struct intel_ringbuffer *ringbuf = params->request->ringbuf;
+
+

[Intel-gfx] [RFC 24/37] drm/i915/sched: set request 'head' on at start of ring submission

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

With the scheduler, request allocation can happen long before
the ring is filled in, and in a different order. So for that case,
we update the request head at the start of _final (the initialisation
on allocation is stull useful for the direct-submission mode).

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 3 +++
 drivers/gpu/drm/i915/intel_lrc.c   | 3 +++
 2 files changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 2d94442..aa4829a 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1292,6 +1292,9 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
if (ret)
goto error;
 
+   /* record where we start filling the ring */
+   params->request->head = intel_ring_get_tail(params->request->ringbuf);
+
/*
 * Unconditionally invalidate gpu caches and ensure that we do flush
 * any residual writes from the previous batch.
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7a8c340..b7d9fbd 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1010,6 +1010,9 @@ int intel_execlists_submission_final(struct 
i915_execbuffer_params *params)
if (ret)
goto err;
 
+   /* record where we start filling the ring */
+   params->request->head = intel_ring_get_tail(params->request->ringbuf);
+
/*
 * Unconditionally invalidate gpu caches and ensure that we do flush
 * any residual writes from the previous batch.
-- 
1.9.1

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


[Intel-gfx] [RFC 29/37] drm/i915/preempt: scheduler logic for preventing recursive preemption

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Once a preemptive request has been dispatched to the hardware-layer
submission mechanism, the scheduler must not send any further requests
to the same ring until the preemption completes. Here we add the logic
that ensure that only one preemption per ring can be in progress at one
time.

Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the logic to process completion isn't in place
yet.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 53 +--
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 61eabc6..81ac88b 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -576,6 +576,10 @@ bool i915_scheduler_notify_request(struct 
drm_i915_gem_request *req)
 
/* Node was in flight so mark it as complete. */
if (req->cancelled) {
+   /* If a preemption was in progress, it won't complete now. */
+   if (node->status == i915_sqs_overtaking)
+   scheduler->flags[req->ring->id] &= 
~(i915_sf_preempting|i915_sf_preempted);
+
node->status = i915_sqs_dead;
scheduler->stats[req->ring->id].kill_flying++;
} else {
@@ -1487,6 +1491,15 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
 
spin_lock_irqsave(&scheduler->lock, flags);
 
+   /*
+* If pre-emption is in progress on an engine then no further work
+* may be submitted to that same engine. Come back later ...
+*/
+   if (i915_scheduler_is_ring_preempting(ring)) {
+   ret = -EAGAIN;
+   goto exit;
+   }
+
/* First time around, complain if anything unexpected occurs: */
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
if (ret)
@@ -1526,7 +1539,15 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
 * list. So add it back in and mark it as in flight. */
i915_scheduler_fly_node(node);
 
-   scheduler->stats[ring->id].submitted++;
+   if (req->scheduler_flags & i915_req_sf_preempt) {
+   /* If this batch is pre-emptive then it will tie the 
hardware
+* up at least until it has begun to be executed. That 
is,
+* if a pre-emption request is in flight then no other 
work
+* may be submitted until it resolves. */
+   scheduler->flags[ring->id] |= i915_sf_preempting;
+   scheduler->stats[ring->id].preempts_submitted++;
+   } else
+   scheduler->stats[ring->id].submitted++;
 
scheduler->flags[ring->id] |= i915_sf_submitting;
spin_unlock_irqrestore(&scheduler->lock, flags);
@@ -1539,7 +1560,9 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
 
/* Oh dear! Either the node is broken or the ring is
 * busy. So need to kill the node or requeue it and try
-* again later as appropriate. */
+* again later as appropriate. Either way, clear the
+* pre-emption flag as it ain't happening. */
+   scheduler->flags[ring->id] &= ~i915_sf_preempting;
 
switch (-ret) {
case ENODEV:
@@ -1582,6 +1605,10 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
i915_scheduler_node_kill(scheduler, node);
}
 
+   /* If pre-emption is now in progress then stop launching */
+   if (i915_scheduler_is_ring_preempting(ring))
+   break;
+
/* Keep launching until the sky is sufficiently full. */
if (i915_scheduler_count_flying(scheduler, ring) >=
scheduler->min_flying)
@@ -1729,6 +1756,28 @@ int i915_scheduler_closefile(struct drm_device *dev, 
struct drm_file *file)
return 0;
 }
 
+bool i915_scheduler_is_ring_preempting(struct intel_engine_cs *ring)
+{
+   struct drm_i915_private *dev_priv = ring->dev->dev_private;
+   struct i915_scheduler *scheduler = dev_priv->scheduler;
+   uint32_t sched_flags = scheduler->flags[ring->id];
+
+   /*
+* The scheduler is prevented from sending batches to the hardware
+* while preemption is in progress (flag bit i915_sf_preempting).
+*
+* Post-preemption (i915_sf_preempted), the hardware ring will be
+* empty, and the scheduler therefore needs a chance to run the
+

[Intel-gfx] [RFC 19/37] drm/i915/error: capture errored context based on request context-id

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Context capture hasn't worked for a while now, probably since the
introduction of execlists; this patch makes it work again by using
a different way of identifying the context of interest.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gpu_error.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 0697fc3..a40c947 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1084,13 +1084,12 @@ static void i915_gem_record_active_context(struct 
intel_engine_cs *ring,
continue;
}
 
-   if (!error->ccid)
-   continue;
-
if (i915.enable_execlists)
base += LRC_PPHWSP_PN * PAGE_SIZE;
 
-   if (base == (error->ccid & PAGE_MASK))
+   if (error->ccid && base == (error->ccid & PAGE_MASK))
+   ering->ctx = i915_error_ggtt_object_create(dev_priv, 
obj);
+   else if (((base ^ ering->ctx_desc) & 0xF000ULL) == 
0)
ering->ctx = i915_error_ggtt_object_create(dev_priv, 
obj);
}
 }
-- 
1.9.1

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


[Intel-gfx] [RFC 37/37] drm/i915: Added preemption info to various trace points

2015-11-23 Thread John . C . Harrison
From: John Harrison 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem.c   |  8 +---
 drivers/gpu/drm/i915/i915_scheduler.c |  2 +-
 drivers/gpu/drm/i915/i915_trace.h | 31 +++
 3 files changed, 25 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index d4a236f..d6094f1 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2878,24 +2878,25 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
u32 seqno;
 
if (list_empty(&ring->fence_signal_list)) {
-   trace_i915_gem_request_notify(ring, 0);
+   trace_i915_gem_request_notify(ring, 0, 0, 0);
return;
}
 
seqno   = ring->get_seqno(ring, false);
preempt = i915_scheduler_is_ring_preempting(ring) ?
  intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO) : 
0;
-   trace_i915_gem_request_notify(ring, seqno);
 
if (preempt) {
u32 preempt_done;
 
preempt_done = intel_read_status_page(ring, 
I915_PREEMPTIVE_DONE_SEQNO);
+   trace_i915_gem_request_notify(ring, seqno, preempt, 
preempt_done);
 
/* A mismatch indicates an in-progress operation so ignore it 
for now */
if (preempt_done != preempt)
preempt = 0;
-   }
+   } else
+   trace_i915_gem_request_notify(ring, seqno, 0, 0);
 
/* Is there anything new to process? */
if ((seqno == ring->last_irq_seqno) && !preempt)
@@ -2955,6 +2956,7 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
 
preempt = intel_read_status_page(ring, 
I915_PREEMPTIVE_ACTIVE_SEQNO);
preempt_done = intel_read_status_page(ring, 
I915_PREEMPTIVE_DONE_SEQNO);
+   trace_i915_gem_request_notify(ring, seqno, preempt, 
preempt_done);
 
/* A mismatch indicates an in-progress operation so ignore it 
for now */
if (preempt_done != preempt)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 9bc9614..b20b763 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -593,7 +593,7 @@ bool i915_scheduler_notify_request(struct 
drm_i915_gem_request *req,
unsigned long flags;
bool result;
 
-   trace_i915_scheduler_landing(req);
+   trace_i915_scheduler_landing(req, preempt);
 
spin_lock_irqsave(&scheduler->lock, flags);
 
diff --git a/drivers/gpu/drm/i915/i915_trace.h 
b/drivers/gpu/drm/i915/i915_trace.h
index 73b0ee9..61367e4 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -569,13 +569,16 @@ DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
 );
 
 TRACE_EVENT(i915_gem_request_notify,
-   TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno),
-   TP_ARGS(ring, seqno),
+   TP_PROTO(struct intel_engine_cs *ring, uint32_t seqno,
+uint32_t preempt, uint32_t preempt_done),
+   TP_ARGS(ring, seqno, preempt, preempt_done),
 
TP_STRUCT__entry(
 __field(u32, dev)
 __field(u32, ring)
 __field(u32, seqno)
+__field(u32, preempt)
+__field(u32, preempt_done)
 __field(bool, is_empty)
 ),
 
@@ -583,12 +586,14 @@ TRACE_EVENT(i915_gem_request_notify,
   __entry->dev = ring->dev->primary->index;
   __entry->ring = ring->id;
   __entry->seqno = seqno;
+  __entry->preempt = preempt;
+  __entry->preempt = preempt_done;
   __entry->is_empty = 
list_empty(&ring->fence_signal_list);
   ),
 
-   TP_printk("dev=%u, ring=%u, seqno=%u, empty=%d",
+   TP_printk("dev=%u, ring=%u, seqno=%u, preempt=%u, preempt_done=%u, 
empty=%d",
  __entry->dev, __entry->ring, __entry->seqno,
- __entry->is_empty)
+ __entry->preempt, __entry->preempt_done, 
__entry->is_empty)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
@@ -887,25 +892,27 @@ TRACE_EVENT(i915_scheduler_unfly,
 );
 
 TRACE_EVENT(i915_scheduler_landing,
-   TP_PROTO(struct drm_i915_gem_request *req),
-   TP_ARGS(req),
+   TP_PROTO(struct drm_i915_gem_request *req, bool preempt),
+   TP_ARGS(req, preempt),
 
TP_STRUCT__entry(
 __field(u32, ring)
 __field(u32, uniq)
 __field(u32, seqno)
   

[Intel-gfx] [RFC 09/37] drm/i915/error: track, capture & print ringbuffer submission activity

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h |  2 ++
 drivers/gpu/drm/i915/i915_gem.c | 11 +--
 drivers/gpu/drm/i915/i915_gpu_error.c   |  9 +
 drivers/gpu/drm/i915/intel_ringbuffer.h | 14 ++
 4 files changed, 34 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 779fc70..9b4ab5d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -567,6 +567,8 @@ struct drm_i915_error_state {
 
u64 ctx_desc;
 
+   struct intel_ringbuffer req_ring;
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ab6064e..785310c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2634,8 +2634,15 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
 */
request->batch_obj = obj;
 
-   request->emitted_jiffies = jiffies;
-   ring->last_submitted_seqno = request->seqno;
+   if (ring->last_submitted_ringbuf == ringbuf)
+   ringbuf->resubmission_count += 1;
+   else
+   ringbuf->resubmission_count = 1;
+   ring->last_submitted_ringbuf = ringbuf;
+   ringbuf->total_submission_count += 1;
+   ringbuf->last_submitted_tail = request->tail;
+   ringbuf->last_submitted_seqno = ring->last_submitted_seqno = 
request->seqno;
+   ringbuf->last_submitted_jiffies = request->emitted_jiffies = jiffies;
list_add_tail(&request->list, &ring->request_list);
 
trace_i915_gem_request_add(request);
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index bafaadd..0697fc3 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -522,12 +522,20 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
}
 
if ((obj = error->ring[i].req_ringbuffer)) {
+   struct intel_ringbuffer *irb = &error->ring[i].req_ring;
+
err_printf(m, "%s --- ringbuffer = 0x%08x; %d pages 
(ctx_desc 0x%08x_%08x)\n",
   dev_priv->ring[i].name,
   lower_32_bits(obj->gtt_offset),
   obj->page_count,
   upper_32_bits(error->ring[i].ctx_desc),
   lower_32_bits(error->ring[i].ctx_desc));
+   err_printf(m, "\t\tringbuffer head 0x%08x tail 0x%08x 
space 0x%08x lrh 0x%08x\n",
+  irb->head, irb->tail, irb->space, 
irb->last_retired_head);
+   err_printf(m, "\t\t%llu submission(s), %d consecutive, 
last at %ld: tail 0x%08x seqno %08x (%d)\n",
+  irb->total_submission_count, 
irb->resubmission_count,
+  irb->last_submitted_jiffies, 
irb->last_submitted_tail,
+  irb->last_submitted_seqno, 
irb->last_submitted_seqno);
print_error_obj(m, obj);
}
 
@@ -1163,6 +1171,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].ctx_desc = ctx_desc;
error->ring[i].req_ringbuffer =
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
+   error->ring[i].req_ring = *rbuf;
 
error->ring[i].hws_page =
i915_error_ggtt_object_create(dev_priv, 
ring->status_page.obj);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h 
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index c472f8a..6bdc1ad 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -126,6 +126,19 @@ struct intel_ringbuffer {
 * we can detect new retirements.
 */
u32 last_retired_head;
+
+   /*
+* Consecutive resubmissions are opportunities for the h/w to do
+* a 'lite restore' rather than a full context switch. Let's note
+* when that happens, in case it's useful for hang diagnosis.
+*/
+   u32 resubmission_count;
+   u64 total_submission_count;
+
+   /* Info about last time this ringbuffer was submitted (to GuC) */
+   unsigned long last_submitted_jiffies;
+   u32 last_submitted_seqno;
+   u32 last_submitted_tail;
 };
 
 struct intel_context;
@@ -306,6 +319,7 @@ struct  intel_engine_cs {
 * inspecting request list.
 */
u32 last_submitted_seqno;
+   struct intel_ringbuffer *last_submitted_ringbuf;
 
/* deferred free list to allow unreferencing requests outside the 
driver */
struct list_head delayed_free_list;
-- 
1.9.1


[Intel-gfx] [RFC 10/37] drm/i915/guc: Tidy up GuC proc/ctx descriptor setup

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_debugfs.c|  2 +-
 drivers/gpu/drm/i915/i915_guc_submission.c | 49 --
 drivers/gpu/drm/i915/intel_guc.h   | 16 +-
 3 files changed, 28 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 1c1c4bd..fefe73c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2666,7 +2666,7 @@ static void i915_guc_client_info(struct seq_file *m,
seq_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
client->priority, client->ctx_index, client->proc_desc_offset);
seq_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n",
-   client->doorbell_id, client->doorbell_offset, client->cookie);
+   client->doorbell_id, client->doorbell_offset, 
client->doorbell_cookie);
seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
client->wq_size, client->wq_offset, client->wq_tail);
 
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 0a6b007..55e10eb 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -210,11 +210,11 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
 
/* current cookie */
db_cmp.db_status = GUC_DOORBELL_ENABLED;
-   db_cmp.cookie = gc->cookie;
+   db_cmp.cookie = gc->doorbell_cookie;
 
/* cookie to be updated */
db_exc.db_status = GUC_DOORBELL_ENABLED;
-   db_exc.cookie = gc->cookie + 1;
+   db_exc.cookie = gc->doorbell_cookie + 1;
if (db_exc.cookie == 0)
db_exc.cookie = 1;
 
@@ -229,7 +229,7 @@ static int guc_ring_doorbell(struct i915_guc_client *gc)
/* if the exchange was successfully executed */
if (db_ret.value_qw == db_cmp.value_qw) {
/* db was successfully rung */
-   gc->cookie = db_exc.cookie;
+   gc->doorbell_cookie = db_exc.cookie;
ret = 0;
break;
}
@@ -385,7 +385,9 @@ static void guc_init_proc_desc(struct intel_guc *guc,
 static void guc_init_ctx_desc(struct intel_guc *guc,
  struct i915_guc_client *client)
 {
+   struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct intel_context *ctx = client->owner;
+   struct intel_engine_cs *ring;
struct guc_context_desc desc;
struct sg_table *sg;
int i;
@@ -397,12 +399,10 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
desc.priority = client->priority;
desc.db_id = client->doorbell_id;
 
-   for (i = 0; i < I915_NUM_RINGS; i++) {
+   for_each_ring(ring, dev_priv, i) {
struct guc_execlist_context *lrc = &desc.lrc[i];
struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
-   struct intel_engine_cs *ring;
-   struct drm_i915_gem_object *obj;
-   uint64_t ctx_desc;
+   struct drm_i915_gem_object *obj = ctx->engine[i].state;
 
/* TODO: We have a design issue to be solved here. Only when we
 * receive the first batch, we know which engine is used by the
@@ -411,22 +411,16 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
 * for now who owns a GuC client. But for future owner of GuC
 * client, need to make sure lrc is pinned prior to enter here.
 */
-   obj = ctx->engine[i].state;
if (!obj)
-   break;  /* XXX: continue? */
-
-   ring = ringbuf->ring;
-   ctx_desc = intel_lr_context_descriptor(ctx, ring);
-   lrc->context_desc = (u32)ctx_desc;
+   continue;
 
-   /* The state page is after PPHWSP */
+   lrc->context_desc = (u32)intel_lr_context_descriptor(ctx, ring);
lrc->ring_lcra = i915_gem_obj_ggtt_offset(obj) +
-   LRC_STATE_PN * PAGE_SIZE;
+   LRC_STATE_PN * PAGE_SIZE;
lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
-   (ring->id << GUC_ELC_ENGINE_OFFSET);
+   (ring->id << GUC_ELC_ENGINE_OFFSET);
 
obj = ringbuf->obj;
-
lrc->ring_begin = i915_gem_obj_ggtt_offset(obj);
lrc->ring_end = lrc->ring_begin + obj->base.size - 1;
lrc->ring_next_free_location = lrc->ring_begin;
@@ -438,22 +432,16 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
WARN_ON(desc.engines_used == 0);
 
/*
-* The CPU address is only needed at certa

[Intel-gfx] [RFC 02/37] drm/i915: recalculate ring space after reset

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

To reinitialise a ringbuffer after a hang (or preemption), we need to not
only to not only set both h/w and s/w HEAD and TAIL to 0, but also clear
last_retired_head and recalculate the available space.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/intel_lrc.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index f64283f..296d900 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2675,5 +2675,7 @@ void intel_lr_context_reset(struct drm_device *dev,
 
ringbuf->head = 0;
ringbuf->tail = 0;
+   ringbuf->last_retired_head = -1;
+   intel_ring_update_space(ringbuf);
}
 }
-- 
1.9.1

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


[Intel-gfx] [RFC 14/37] drm/i915/guc: Expose GuC-maintained statistics

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 19 ++-
 drivers/gpu/drm/i915/intel_guc_fwif.h  |  7 ++-
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 38c431d..d11bba9 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -170,9 +170,26 @@ host2guc_preempt(struct i915_guc_client *client,
data[4] = guc->execbuf_client->priority;// victim 
priority
data[5] = guc->execbuf_client->ctx_index;   // victim ctx/wq
data[6] = i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE;
+   data[7] = 0;
 
ret = host2guc_action(guc, data, 7);
-   WARN_ON(ret);
+   if (WARN_ON(ret)) {
+   u32 *gsp = kmap_atomic(i915_gem_object_get_page(ctx_obj, 
LRC_GUCSHR_PN));
+   int i;
+
+   DRM_DEBUG_DRIVER("GuC preemption request data:\n");
+   for (i = 0; i < 8; i += 4)
+   DRM_DEBUG_DRIVER("\t%08x %08x  %08x %08x\n",
+   data[i+0], data[i+1], data[i+2], data[i+3]);
+
+   DRM_DEBUG_DRIVER("GuC per-context shared data @ 0x%llx:\n",
+   i915_gem_obj_ggtt_offset(ctx_obj) + 
LRC_GUCSHR_PN*PAGE_SIZE);
+   for (i = 0; i < 32; i += 4)
+   DRM_DEBUG_DRIVER("\t%08x %08x  %08x %08x\n",
+   gsp[i+0], gsp[i+1], gsp[i+2], gsp[i+3]);
+
+   kunmap_atomic(gsp);
+   }
return ret;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 48da20d..110496a 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -233,7 +233,12 @@ struct guc_process_desc {
u32 wq_status;
u32 engine_presence;
u32 priority;
-   u32 reserved[30];
+   u32 reserved1[4];
+   u32 reserved2[5];
+   u32 items_parsed,
+   items_collaped,
+   items_cancelled;
+   u32 reserved3[18];
 } __packed;
 
 /* engine id and context id is packed into guc_execlist_context.context_id*/
-- 
1.9.1

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


[Intel-gfx] [RFC 05/37] drm/i915/error: capture ringbuffer pointed to by START

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |  2 +-
 drivers/gpu/drm/i915/i915_gpu_error.c | 36 +--
 2 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 782591f8..7d2d642 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -569,7 +569,7 @@ struct drm_i915_error_state {
int page_count;
u64 gtt_offset;
u32 *pages[0];
-   } *ringbuffer, *batchbuffer, *wa_batchbuffer, *ctx, *hws_page;
+   } *req_ringbuffer, *hw_ringbuffer, *batchbuffer, 
*wa_batchbuffer, *ctx, *hws_page;
 
struct drm_i915_error_request {
long jiffies;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index fcb9487..b7c889c 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -471,13 +471,20 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
}
}
 
-   if ((obj = error->ring[i].ringbuffer)) {
+   if ((obj = error->ring[i].req_ringbuffer)) {
err_printf(m, "%s --- ringbuffer = 0x%08x\n",
   dev_priv->ring[i].name,
   lower_32_bits(obj->gtt_offset));
print_error_obj(m, obj);
}
 
+   if ((obj = error->ring[i].hw_ringbuffer)) {
+   err_printf(m, "%s --- HW ringbuffer = 0x%08x\n",
+  dev_priv->ring[i].name,
+  lower_32_bits(obj->gtt_offset));
+   print_error_obj(m, obj);
+   }
+
if ((obj = error->ring[i].hws_page)) {
u64 hws_offset = obj->gtt_offset;
u32 *hws_page = &obj->pages[0][0];
@@ -588,7 +595,8 @@ static void i915_error_state_free(struct kref *error_ref)
for (i = 0; i < ARRAY_SIZE(error->ring); i++) {
i915_error_object_free(error->ring[i].batchbuffer);
i915_error_object_free(error->ring[i].wa_batchbuffer);
-   i915_error_object_free(error->ring[i].ringbuffer);
+   i915_error_object_free(error->ring[i].req_ringbuffer);
+   i915_error_object_free(error->ring[i].hw_ringbuffer);
i915_error_object_free(error->ring[i].hws_page);
i915_error_object_free(error->ring[i].ctx);
kfree(error->ring[i].requests);
@@ -1000,19 +1008,27 @@ static void i915_gem_record_active_context(struct 
intel_engine_cs *ring,
 {
struct drm_i915_private *dev_priv = ring->dev->dev_private;
struct drm_i915_gem_object *obj;
-
-   /* Currently render ring is the only HW context user */
-   if (ring->id != RCS || !error->ccid)
-   return;
+   u64 base;
 
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
if (!i915_gem_obj_ggtt_bound(obj))
continue;
 
-   if ((error->ccid & PAGE_MASK) == i915_gem_obj_ggtt_offset(obj)) 
{
-   ering->ctx = i915_error_ggtt_object_create(dev_priv, 
obj);
-   break;
+   base = i915_gem_obj_ggtt_offset(obj);
+
+   if (base == ering->start) {
+   ering->hw_ringbuffer = 
i915_error_ggtt_object_create(dev_priv, obj);
+   continue;
}
+
+   if (!error->ccid)
+   continue;
+
+   if (i915.enable_execlists)
+   base += LRC_PPHWSP_PN * PAGE_SIZE;
+
+   if (base == (error->ccid & PAGE_MASK))
+   ering->ctx = i915_error_ggtt_object_create(dev_priv, 
obj);
}
 }
 
@@ -1087,7 +1103,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
error->ring[i].cpu_ring_head = rbuf->head;
error->ring[i].cpu_ring_tail = rbuf->tail;
 
-   error->ring[i].ringbuffer =
+   error->ring[i].req_ringbuffer =
i915_error_ggtt_object_create(dev_priv, rbuf->obj);
 
error->ring[i].hws_page =
-- 
1.9.1

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


[Intel-gfx] [RFC 21/37] drm/i915/error: add GuC state error capture & decode

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |   4 ++
 drivers/gpu/drm/i915/i915_gpu_error.c | 110 ++
 2 files changed, 114 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9e0e9da..df01863 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -617,6 +617,10 @@ struct drm_i915_error_state {
 
u32 *active_bo_count, *pinned_bo_count;
u32 vm_count;
+
+   struct intel_guc guc;
+   struct i915_guc_client execbuf_client;
+   struct i915_guc_client preempt_client;
 };
 
 struct intel_connector;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index e3777ba..346c831 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -362,6 +362,100 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
}
 }
 
+static void i915_guc_firmware_info(struct drm_i915_error_state_buf *m,
+  struct drm_i915_private *dev_priv,
+  struct intel_guc_fw *guc_fw)
+{
+   err_printf(m, "GuC firmware status:\n");
+   err_printf(m, "\tpath: %s\n",
+   guc_fw->guc_fw_path);
+   err_printf(m, "\tfetch: %s\n",
+   intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
+   err_printf(m, "\tload: %s\n",
+   intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
+   err_printf(m, "\tversion wanted: %d.%d\n",
+   guc_fw->guc_fw_major_wanted, guc_fw->guc_fw_minor_wanted);
+   err_printf(m, "\tversion found: %d.%d\n",
+   guc_fw->guc_fw_major_found, guc_fw->guc_fw_minor_found);
+}
+
+static void i915_guc_action_info(struct drm_i915_error_state_buf *m,
+struct drm_i915_private *dev_priv,
+struct intel_guc *guc)
+{
+   struct intel_engine_cs *ring;
+   u64 total = 0, preempts = 0;
+   int i;
+
+   err_printf(m, "GuC action status:\n");
+   err_printf(m, "\ttotal action count: %llu\n", guc->action_count);
+   err_printf(m, "\tlast action command: 0x%x\n", guc->action_cmd);
+   err_printf(m, "\tlast action status: 0x%x\n", guc->action_status);
+
+   err_printf(m, "\taction failure count: %u\n", guc->action_fail_count);
+   err_printf(m, "\tlast failed action: 0x%x\n", guc->action_fail_cmd);
+   err_printf(m, "\tlast failed status: 0x%x\n", guc->action_fail_status);
+   err_printf(m, "\tlast error code: %d\n", guc->action_err);
+
+   err_printf(m, "GuC submissions:\n");
+   for_each_ring(ring, dev_priv, i) {
+   err_printf(m, "\t%-24s: %10llu, last %-8s 0x%08x %9d\n",
+   ring->name, guc->submissions[i], "seqno",
+   guc->last_seqno[i], guc->last_seqno[i]);
+   err_printf(m, "\t%-24s: %10u, last %-8s 0x%08x %9d\n",
+   "preemptions", guc->preemptions[i], "preempt",
+   guc->last_preempt[i], guc->last_preempt[i]);
+   total += guc->submissions[i];
+   preempts += guc->preemptions[i];
+   }
+   err_printf(m, "\t%s: %10llu\n", "Total regular", total);
+   err_printf(m, "\t%s: %10llu\n", " preempts", preempts);
+}
+
+static void i915_guc_client_info(struct drm_i915_error_state_buf *m,
+struct drm_i915_private *dev_priv,
+struct i915_guc_client *client)
+{
+   struct intel_engine_cs *ring;
+   uint64_t tot = 0;
+   uint32_t i;
+
+   err_printf(m, "\tPriority %d, GuC ctx index: %u, PD offset 0x%x\n",
+   client->priority, client->ctx_index, client->proc_desc_offset);
+   err_printf(m, "\tDoorbell id %d, offset: 0x%x, cookie 0x%x\n",
+   client->doorbell_id, client->doorbell_offset, 
client->doorbell_cookie);
+   err_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
+   client->wq_size, client->wq_offset, client->wq_tail);
+
+   err_printf(m, "\tFailed to queue: %u\n", client->q_fail);
+   err_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
+   err_printf(m, "\tLast submission result: %d\n", client->retcode);
+
+   for_each_ring(ring, dev_priv, i) {
+   err_printf(m, "\tSubmissions: %llu %s\n",
+   client->submissions[i],
+   ring->name);
+   tot += client->submissions[i];
+   }
+   err_printf(m, "\tTotal: %llu\n", tot);
+}
+
+static void i915_guc_error_state(struct drm_i915_error_state_buf *m,
+struct drm_i915_private *dev_priv,
+struct drm_i915_error_state *error)
+{
+   struct intel_guc *guc = &error->guc;
+
+   i915_guc_firmware_info(m, dev_priv,

[Intel-gfx] [RFC 13/37] drm/i915/guc: Improve action error reporting, add preemption debug

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_debugfs.c| 20 +--
 drivers/gpu/drm/i915/i915_guc_submission.c | 32 --
 drivers/gpu/drm/i915/intel_guc.h   | 12 +--
 3 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 9e8f624..e9372ac 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2693,7 +2693,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
struct i915_guc_client preempt = {};
struct intel_engine_cs *ring;
enum intel_ring_id i;
-   u64 total = 0;
+   u64 total = 0, preempts = 0;
 
if (!HAS_GUC_SCHED(dev_priv->dev))
return 0;
@@ -2714,19 +2714,27 @@ static int i915_guc_info(struct seq_file *m, void *data)
spin_unlock(&dev_priv->guc.host2guc_lock);
 
seq_printf(m, "GuC total action count: %llu\n", guc.action_count);
-   seq_printf(m, "GuC action failure count: %u\n", guc.action_fail);
seq_printf(m, "GuC last action command: 0x%x\n", guc.action_cmd);
seq_printf(m, "GuC last action status: 0x%x\n", guc.action_status);
-   seq_printf(m, "GuC last action error code: %d\n", guc.action_err);
+
+   seq_printf(m, "GuC action failure count: %u\n", guc.action_fail_count);
+   seq_printf(m, "GuC last failed action: 0x%x\n", guc.action_fail_cmd);
+   seq_printf(m, "GuC last failed status: 0x%x\n", guc.action_fail_status);
+   seq_printf(m, "GuC last error code: %d\n", guc.action_err);
 
seq_printf(m, "\nGuC submissions:\n");
for_each_ring(ring, dev_priv, i) {
-   seq_printf(m, "\t%-24s: %10llu, last seqno 0x%08x %9d\n",
-   ring->name, guc.submissions[i],
+   seq_printf(m, "\t%-24s: %10llu, last %-8s 0x%08x %9d\n",
+   ring->name, guc.submissions[i], "seqno",
guc.last_seqno[i], guc.last_seqno[i]);
+   seq_printf(m, "\t%-24s: %10u, last %-8s 0x%08x %9d\n",
+   "preemptions", guc.preemptions[i], "preempt",
+   guc.last_preempt[i], guc.last_preempt[i]);
total += guc.submissions[i];
+   preempts += guc.preemptions[i];
}
-   seq_printf(m, "\t%s: %llu\n", "Total", total);
+   seq_printf(m, "\t%s: %10llu\n", "Total regular", total);
+   seq_printf(m, "\t%s: %10llu\n", " preempts", preempts);
 
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
i915_guc_client_info(m, dev_priv, &client);
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 4035ac6..38c431d 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -78,9 +78,8 @@ static inline bool host2guc_action_response(struct 
drm_i915_private *dev_priv,
 static int host2guc_action(struct intel_guc *guc, u32 *data, u32 len)
 {
struct drm_i915_private *dev_priv = guc_to_i915(guc);
-   u32 status;
-   int i;
-   int ret;
+   u32 status, response;
+   int ret, i;
 
if (WARN_ON(len < 1 || len > 15))
return -EINVAL;
@@ -101,6 +100,8 @@ static int host2guc_action(struct intel_guc *guc, u32 
*data, u32 len)
 
/* No HOST2GUC command should take longer than 10ms */
ret = wait_for_atomic(host2guc_action_response(dev_priv, &status), 10);
+   response = I915_READ(SOFT_SCRATCH(15));
+   dev_priv->guc.action_status = status;
if (status != GUC2HOST_STATUS_SUCCESS) {
/*
 * Either the GuC explicitly returned an error (which
@@ -110,15 +111,15 @@ static int host2guc_action(struct intel_guc *guc, u32 
*data, u32 len)
if (ret != -ETIMEDOUT)
ret = -EIO;
 
-   DRM_ERROR("GUC: host2guc action 0x%X failed. ret=%d "
+   DRM_ERROR("GuC: host2guc action 0x%X failed. ret=%d "
"status=0x%08X response=0x%08X\n",
-   data[0], ret, status,
-   I915_READ(SOFT_SCRATCH(15)));
+   data[0], ret, status, response);
 
-   dev_priv->guc.action_fail += 1;
+   dev_priv->guc.action_fail_count += 1;
+   dev_priv->guc.action_fail_cmd = data[0];
+   dev_priv->guc.action_fail_status = status;
dev_priv->guc.action_err = ret;
}
-   dev_priv->guc.action_status = status;
 
spin_unlock(&dev_priv->guc.host2guc_lock);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
@@ -141,7 +142,7 @@ host2guc_preempt(struct i915_guc_client *client,
struct intel_ringbuffer *ringbuf = ctx->engine[engine_id].ringbuf;
struct guc_proc

[Intel-gfx] [RFC 28/37] drm/i915/preempt: scheduler logic for selecting preemptive requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This patch adds the scheduler logic for managing potentially preemptive
requests, including validating dependencies and working out when a
request can be downgraded to non-preemptive (e.g. when there's nothing
ahead for it to preempt).

Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 76 ---
 1 file changed, 61 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 50ff8b7..61eabc6 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -498,6 +498,9 @@ static inline bool i915_scheduler_is_dependency_valid(
if (I915_SQS_IS_FLYING(dep)) {
if (node->params.ring != dep->params.ring)
return true;
+
+   if (node->params.request->scheduler_flags & i915_req_sf_preempt)
+   return true;
}
 
return false;
@@ -1317,10 +1320,11 @@ static int i915_scheduler_pop_from_queue_locked(struct 
intel_engine_cs *ring,
struct i915_scheduler_queue_entry  *best_wait, *fence_wait = NULL;
struct i915_scheduler_queue_entry  *best;
struct i915_scheduler_queue_entry  *node;
+   struct drm_i915_gem_request*req;
int ret;
int i;
boolsignalled, any_queued;
-   boolhas_local, has_remote, only_remote;
+   boolhas_local, has_remote, only_remote, local_preempt_only;
 
*pop_node = NULL;
ret = -ENODATA;
@@ -1346,18 +1350,40 @@ static int i915_scheduler_pop_from_queue_locked(struct 
intel_engine_cs *ring,
scheduler->stats[node->params.ring->id].fence_ignore++;
}
 
+   /* Attempt to re-enable pre-emption if a node wants to pre-empt
+* but previously got downgraded. */
+   req = node->params.request;
+   if (req->scheduler_flags & i915_req_sf_was_preempt)
+   req->scheduler_flags |= i915_req_sf_preempt;
+
has_local  = false;
has_remote = false;
+   local_preempt_only = (req->scheduler_flags & 
i915_req_sf_preempt) != 0;
for (i = 0; i < node->num_deps; i++) {
if (!i915_scheduler_is_dependency_valid(node, i))
continue;
 
-   if (node->dep_list[i]->params.ring == node->params.ring)
+   if (node->dep_list[i]->params.ring == 
node->params.ring) {
has_local = true;
-   else
+
+   if (local_preempt_only) {
+   req->scheduler_flags &= 
~i915_req_sf_preempt;
+   if 
(i915_scheduler_is_dependency_valid(node, i))
+   local_preempt_only = false;
+   req->scheduler_flags |= 
i915_req_sf_preempt;
+   }
+   } else
has_remote = true;
}
 
+   if (has_local && local_preempt_only) {
+   /* If a preemptive node's local dependencies are all
+* flying, then they can be ignored by un-preempting
+* the node. */
+   req->scheduler_flags &= ~i915_req_sf_preempt;
+   has_local = false;
+   }
+
if (has_remote && !has_local)
only_remote = true;
 
@@ -1447,6 +1473,7 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_scheduler   *scheduler = dev_priv->scheduler;
struct i915_scheduler_queue_entry  *node;
+   struct drm_i915_gem_request *req;
unsigned long   flags;
int ret = 0, count = 0;
 
@@ -1462,14 +1489,8 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
 
/* First time around, complain if anything unexpected occurs: */
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
-   if (ret) {
-   spin_unlock_irqrestore(&scheduler->lock, flags);
-
-   if (!was_locked)
-   mutex_unlock(&dev->struct_mutex);
-
-   return ret;
-   }
+   if (ret)
+   goto exit;
 
do {
BUG_ON(!node);
@@ -1477,6 +1498,30 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
BUG_ON(node->status != i915_sqs_p

[Intel-gfx] [RFC 12/37] drm/i915/guc: implement submission via REQUEST_PREEMPTION action

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

If a batch is submitted via the preemptive (KMD_HIGH-priority) client
then instead of ringing the doorbell we dispatch it using the GuC
"REQUEST_PREEMPTION" action. Also, we specify "clear work queue" and
"clear submit queue" in that request, so the scheduler can reconsider
what is to be done next after preemption.

Note that the preemption request requires a reference to the GuC per-
context shared data, which in early versions of the GuC firmware was at
the end of the context object but nowadays is at the start.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 64 --
 drivers/gpu/drm/i915/intel_guc_fwif.h  |  7 
 drivers/gpu/drm/i915/intel_lrc.c   | 26 +++-
 3 files changed, 84 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index d8fd644..4035ac6 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -94,7 +94,8 @@ static int host2guc_action(struct intel_guc *guc, u32 *data, 
u32 len)
for (i = 0; i < len; i++)
I915_WRITE(SOFT_SCRATCH(i), data[i]);
 
-   POSTING_READ(SOFT_SCRATCH(i - 1));
+   I915_WRITE(SOFT_SCRATCH(15), 0);
+   POSTING_READ(SOFT_SCRATCH(0));
 
I915_WRITE(HOST2GUC_INTERRUPT, HOST2GUC_TRIGGER);
 
@@ -126,6 +127,55 @@ static int host2guc_action(struct intel_guc *guc, u32 
*data, u32 len)
 }
 
 /*
+ * Tell the GuC to submit a request pre-emptively
+ */
+static int
+host2guc_preempt(struct i915_guc_client *client,
+struct intel_context *ctx,
+struct intel_engine_cs *ring)
+{
+   struct drm_i915_private *dev_priv = ring->dev->dev_private;
+   struct intel_guc *guc = &dev_priv->guc;
+   uint32_t engine_id = ring->id;
+   struct drm_i915_gem_object *ctx_obj = ctx->engine[engine_id].state;
+   struct intel_ringbuffer *ringbuf = ctx->engine[engine_id].ringbuf;
+   struct guc_process_desc *desc;
+   void *base;
+   u32 data[7];
+   int ret;
+
+   if (WARN_ON(!ctx_obj || !ringbuf))
+   return -EINVAL;
+
+   WARN_ON(!i915_gem_obj_is_pinned(ctx_obj));
+   WARN_ON(!i915_gem_obj_is_pinned(ringbuf->obj));
+
+   WARN_ON(guc->preempt_client != client);
+
+   base = kmap_atomic(i915_gem_object_get_page(client->client_obj, 0));
+   desc = base + client->proc_desc_offset;
+
+   /* Update the tail so it is visible to GuC */
+   desc->tail = client->wq_tail;
+   kunmap_atomic(base);
+
+   data[0] = HOST2GUC_ACTION_REQUEST_PREEMPTION;
+   data[1] = guc->preempt_client->ctx_index;   // preemptive 
client
+   data[2] = /* PREEMPT_ENGINE_OPTIONS */
+ HOST2GUC_PREEMPT_OPTION_IMMEDIATE |   // submit 
before return
+ HOST2GUC_PREEMPT_OPTION_DROP_WORK_Q | // drop wq for 
client data[5]
+ HOST2GUC_PREEMPT_OPTION_DROP_SUBMIT_Q;// drop 
submitted (engine, priority)
+   data[3] = engine_id;// target engine
+   data[4] = guc->execbuf_client->priority;// victim 
priority
+   data[5] = guc->execbuf_client->ctx_index;   // victim ctx/wq
+   data[6] = i915_gem_obj_ggtt_offset(ctx_obj) + LRC_GUCSHR_PN*PAGE_SIZE;
+
+   ret = host2guc_action(guc, data, 7);
+   WARN_ON(ret);
+   return ret;
+}
+
+/*
  * Tell the GuC to allocate or deallocate a specific doorbell
  */
 
@@ -585,8 +635,9 @@ static void lr_context_update(struct drm_i915_gem_request 
*rq)
 int i915_guc_submit(struct i915_guc_client *client,
struct drm_i915_gem_request *rq)
 {
-   struct intel_guc *guc = client->guc;
+   bool preemptive = client->priority <= GUC_CTX_PRIORITY_HIGH;
enum intel_ring_id ring_id = rq->ring->id;
+   struct intel_guc *guc = client->guc;
unsigned long flags;
int q_ret, b_ret;
 
@@ -600,8 +651,12 @@ int i915_guc_submit(struct i915_guc_client *client,
spin_lock_irqsave(&client->wq_lock, flags);
 
q_ret = guc_add_workqueue_item(client, rq);
-   if (q_ret == 0)
-   b_ret = guc_ring_doorbell(client);
+   if (q_ret == 0) {
+   if (preemptive)
+   b_ret = host2guc_preempt(client, rq->ctx, rq->ring);
+   else
+   b_ret = guc_ring_doorbell(client);
+   }
 
client->submissions[ring_id] += 1;
if (q_ret) {
@@ -612,6 +667,7 @@ int i915_guc_submit(struct i915_guc_client *client,
client->retcode = q_ret = b_ret;
} else {
client->retcode = 0;
+   rq->elsp_submitted += 1;
}
spin_unlock_irqrestore(&client->wq_lock, flags);
 
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 40b2ea5..48

[Intel-gfx] [RFC 22/37] drm/i915: track relative-constants-mode per-context not per-device

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

'relative_constants_mode' has always been tracked per-device, but this
is wrong in execlists (or GuC) mode, as INSTPM is saved and restored
with the logical context, and the per-context value could therefore get
out of sync with the tracked value. This patch moves the tracking
element from the dev_priv structure into the intel_context structure,
with corresponding adjustments to the code that initialises and uses it.

Test case (if anyone wants to write it) would be to create two contexts,
submit a batch with a non-default mode in the first context, submit a
batch with the default mode in the other context, submit another batch
in the first context, but this time in default mode. The driver will
fail to insert the instructions to reset INSTPM into the first context's
ringbuffer.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92448

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h| 4 ++--
 drivers/gpu/drm/i915/i915_gem.c| 2 --
 drivers/gpu/drm/i915/i915_gem_context.c| 3 +++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 6 +++---
 drivers/gpu/drm/i915/intel_lrc.c   | 6 +++---
 5 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index df01863..9bece1e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -921,6 +921,8 @@ struct intel_context {
struct i915_ctx_sched_info sched_info;
struct i915_hw_ppgtt *ppgtt;
 
+   int relative_constants_mode;
+
/* Legacy ring buffer submission */
struct {
struct drm_i915_gem_object *rcs_state;
@@ -1761,8 +1763,6 @@ struct drm_i915_private {
 
const struct intel_device_info info;
 
-   int relative_constants_mode;
-
void __iomem *regs;
 
struct intel_uncore uncore;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 895f1e5..1131fe3 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -5490,8 +5490,6 @@ i915_gem_load(struct drm_device *dev)
i915_gem_scheduler_work_handler);
init_waitqueue_head(&dev_priv->gpu_error.reset_queue);
 
-   dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
-
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
dev_priv->num_fence_regs = 32;
else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) 
|| IS_G33(dev))
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index b226e6d..a4dda23 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -246,6 +246,9 @@ __create_hw_context(struct drm_device *dev,
 * is no remap info, it will be a NOP. */
ctx->remap_slice = (1 << NUM_L3_SLICES(dev)) - 1;
 
+   /* First execbuffer will override this */
+   ctx->relative_constants_mode = -1;
+
ctx->hang_stats.ban_period_seconds = DRM_I915_CTX_BAN_PERIOD;
 
return ctx;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 20693c3..2d94442 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1192,7 +1192,7 @@ i915_gem_ringbuffer_submission(struct 
i915_execbuffer_params *params,
return -EINVAL;
}
 
-   if (params->instp_mode != dev_priv->relative_constants_mode) {
+   if (params->instp_mode != params->ctx->relative_constants_mode) 
{
if (INTEL_INFO(dev)->gen < 4) {
DRM_DEBUG("no rel constants on pre-gen4\n");
return -EINVAL;
@@ -1309,14 +1309,14 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
 "%s didn't clear reload\n", ring->name);
 
if (ring == &dev_priv->ring[RCS] &&
-   params->instp_mode != dev_priv->relative_constants_mode) {
+   params->instp_mode != params->ctx->relative_constants_mode) {
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, INSTPM);
intel_ring_emit(ring, params->instp_mask << 16 | 
params->instp_mode);
intel_ring_advance(ring);
 
-   dev_priv->relative_constants_mode = params->instp_mode;
+   params->ctx->relative_constants_mode = params->instp_mode;
}
 
if (params->args_flags & I915_EXEC_GEN7_SOL_RESET) {
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 2bc402f..7a8c340 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -914,7 +914,7 @@ int intel_execlists_submission(struct 
i915_execbuffer_pa

[Intel-gfx] [RFC 16/37] drm/i915/guc: Expose (intel)_lr_context_size()

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

The GuC code needs to know the size of a logical context, so we
expose get_lr_context_size(), renaming it intel_lr_context__size()
to fit the naming conventions for nonstatic functions.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/intel_lrc.c | 4 ++--
 drivers/gpu/drm/i915/intel_lrc.h | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index ca7bc61..2bc402f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -2511,7 +2511,7 @@ void intel_lr_context_free(struct intel_context *ctx)
}
 }
 
-static uint32_t get_lr_context_size(struct intel_engine_cs *ring)
+uint32_t intel_lr_context_size(struct intel_engine_cs *ring)
 {
int ret = 0;
 
@@ -2581,7 +2581,7 @@ int intel_lr_context_deferred_alloc(struct intel_context 
*ctx,
 
intel_runtime_pm_get(dev->dev_private);
 
-   context_size = round_up(get_lr_context_size(ring), 4096);
+   context_size = round_up(intel_lr_context_size(ring), 4096);
 
/* One extra page as the sharing data between driver and GuC */
context_size += PAGE_SIZE * LRC_PPHWSP_PN;
diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h
index 8d9bad7..8ed6c18 100644
--- a/drivers/gpu/drm/i915/intel_lrc.h
+++ b/drivers/gpu/drm/i915/intel_lrc.h
@@ -79,6 +79,7 @@ static inline void intel_logical_ring_emit(struct 
intel_ringbuffer *ringbuf,
 #define LRC_STATE_PN   (LRC_PPHWSP_PN + 1)
 
 void intel_lr_context_free(struct intel_context *ctx);
+uint32_t intel_lr_context_size(struct intel_engine_cs *ring);
 int intel_lr_context_deferred_alloc(struct intel_context *ctx,
struct intel_engine_cs *ring);
 void intel_lr_context_unpin(struct drm_i915_gem_request *req);
-- 
1.9.1

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


[Intel-gfx] [RFC 34/37] drm/i915/preempt: scheduler logic for postprocessing preemptive requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This patch adds the scheduler logic for postprocessing of completed
preemption requests. It cleans out both the fence_signal list (dropping
references as it goes) and the primary request_list. Requests that
didn't complete are put into the 'preempted' state for resubmission by
the scheduler, and their ringbuffers are emptied by setting head==tail
so thers is no pending work in any preempted context. The (dummy)
preemption request itself is also recycled in the same way, and should
then be (re)selected by the scheduler to be submitted next (unless
anything with even hogher priority as been queued in the meantime); but
because there are now no requests flying, the next-submitted batch will
not need to preempt, and so will be launched 'for real' as a regular
non-preemptive batch.

Actually-preemptive requests are still disabled via a module parameter
at this stage, as we don't yet have the code to emit preemption requests
into the ringbuffer.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |   2 +-
 drivers/gpu/drm/i915/i915_gem.c   |  33 +++
 drivers/gpu/drm/i915/i915_scheduler.c | 161 ++
 3 files changed, 195 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7b5778b..06ae3f5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2341,7 +2341,7 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring,
   struct intel_context *ctx,
   struct drm_i915_gem_request **req_out);
 void i915_gem_request_cancel(struct drm_i915_gem_request *req);
-
+void i915_gem_request_dequeue(struct drm_i915_gem_request *req);
 void i915_gem_request_submit(struct drm_i915_gem_request *req);
 void i915_gem_request_enable_interrupt(struct drm_i915_gem_request *req,
   bool fence_locked);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 59de18e..d4a236f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1224,6 +1224,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
might_sleep();
WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
 
+   /* Lightweight check first of all */
if (i915_gem_request_completed(req))
return 0;
 
@@ -1232,6 +1233,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
 */
fence_enable_sw_signaling(&req->fence);
 
+   /* Recheck - call above may have updated completion status */
if (i915_gem_request_completed(req))
return 0;
 
@@ -1405,6 +1407,11 @@ static void i915_gem_request_retire(struct 
drm_i915_gem_request *request)
 */
request->ringbuf->last_retired_head = request->postfix;
 
+   /*
+* Must use list_del_init() not list_del() because some other
+* code tests (list_empty(&request->list)) to see whether the
+* request is (still) on the ring->request_list!
+*/
list_del_init(&request->list);
i915_gem_request_remove_from_client(request);
 
@@ -1435,10 +1442,18 @@ __i915_gem_request_retire__upto(struct 
drm_i915_gem_request *req)
 
lockdep_assert_held(&engine->dev->struct_mutex);
 
+   /*
+* If the request is not on any list, then presumably
+* it's already been retired?
+* */
if (list_empty(&req->list))
return;
 
do {
+   /* Don't blindly assume that the request will be found! */
+   if (WARN_ON(list_empty(&engine->request_list)))
+   break;
+
tmp = list_first_entry(&engine->request_list,
   typeof(*tmp), list);
 
@@ -2666,6 +2681,24 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
intel_ring_reserved_space_end(ringbuf);
 }
 
+void i915_gem_request_dequeue(struct drm_i915_gem_request *request)
+{
+   /*
+* The request has been de-queued from the hardware in some manner
+* (e.g. through pre-emption). So it needs to be removed from the
+* active request list (the request list doesn't contribute to
+* refcounting, so we don't also have to unreference it here).
+*
+* It also needs to have its seqno cleared as that will not be
+* valid any longer. However, the expectation is that the request
+* will be resubmitted later. At that time it will be assigned a
+* shiny new seqno.
+*/
+   WARN_ON(i915_gem_request_completed(request));
+   list_del_init(&request->list);
+   request->seqno = 0;
+}
+
 static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
   const struct intel_context *ctx)
 {
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_sched

[Intel-gfx] [RFC 06/37] drm/i915/error: report ctx id & desc for each request in the queue

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Also decode and output CSB entries, in time order

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |  1 +
 drivers/gpu/drm/i915/i915_gpu_error.c | 37 +++
 2 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 7d2d642..41999cc 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -572,6 +572,7 @@ struct drm_i915_error_state {
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, 
*wa_batchbuffer, *ctx, *hws_page;
 
struct drm_i915_error_request {
+   uint64_t ctx_desc;
long jiffies;
u32 seqno;
u32 tail;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index b7c889c..56078c5 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -311,9 +311,25 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
err_printf(m, "  EXECLIST_CSB_WR: 0x%08x\n", 
ring->execlist_csb_write_pointer);
err_printf(m, "  EXECLIST_CSB_RD: 0x%08x\n", 
ring->execlist_csb_read_pointer);
 
-   for (i = 0; i < 6; i++) {
-   err_printf(m, "  EXECLIST_CSB[%d]: 0x%08x\n", i, 
ring->execlist_csb[i]);
-   err_printf(m, "  EXECLIST_CTX[%d]: 0x%08x\n", i, 
ring->execlist_ctx[i]);
+#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)
+
+   for (i = 1; i <= 6; ++i) {
+   int n = (ring->execlist_csb_write_pointer + i) % 6;
+   u32 csb = ring->execlist_csb[n];
+   err_printf(m, "  EXECLIST_CTX/CSB[%d]:  0x%08x  0x%08x  ",
+   n, ring->execlist_ctx[n], csb);
+   err_printf(m, "%s %s %s %s %s %s\n",
+   csb & GEN8_CTX_STATUS_IDLE_ACTIVE   ? "I->A" : "
",
+   csb & GEN8_CTX_STATUS_PREEMPTED ? "PRMT" : "
",
+   csb & GEN8_CTX_STATUS_ELEMENT_SWITCH? "ELSW" : "
",
+   csb & GEN8_CTX_STATUS_ACTIVE_IDLE   ? "A->I" : "
",
+   csb & GEN8_CTX_STATUS_COMPLETE  ? "DONE" : "
",
+   csb & GEN8_CTX_STATUS_LITE_RESTORE  ? "LITE" : "
");
}
 }
 
@@ -464,10 +480,13 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
   dev_priv->ring[i].name,
   error->ring[i].num_requests);
for (j = 0; j < error->ring[i].num_requests; j++) {
-   err_printf(m, "  seqno 0x%08x, emitted %ld, 
tail 0x%08x\n",
-  error->ring[i].requests[j].seqno,
-  error->ring[i].requests[j].jiffies,
-  error->ring[i].requests[j].tail);
+   struct drm_i915_error_request *erq;
+   erq = &error->ring[i].requests[j];
+   err_printf(m, "  seqno 0x%08x, tail 0x%08x, "
+   "emitted %ld, ctx_desc 0x%08x_%08x\n",
+   erq->seqno, erq->tail, erq->jiffies,
+   upper_32_bits(erq->ctx_desc),
+   lower_32_bits(erq->ctx_desc));
}
}
 
@@ -1126,6 +1145,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
 
count = 0;
list_for_each_entry(request, &ring->request_list, list) {
+   struct intel_context *ctx = request->ctx;
struct drm_i915_error_request *erq;
 
if (count >= error->ring[i].num_requests) {
@@ -1148,8 +1168,9 @@ static void i915_gem_record_rings(struct drm_device *dev,
}
 
erq = &error->ring[i].requests[count++];
-   erq->seqno = request->seqno;
+   erq->ctx_desc = intel_lr_context_descriptor(ctx, ring);
erq->jiffies = request->emitted_jiffies;
+   erq->seqno = request->seqno;
erq->tail = request->postfix;
}
}
-- 
1.9.1

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


[Intel-gfx] [RFC 26/37] drm/i915/preempt: preemption-related definitions and statistics

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_debugfs.c   | 18 
 drivers/gpu/drm/i915/i915_drv.h   |  1 +
 drivers/gpu/drm/i915/i915_scheduler.h | 40 +--
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index e9372ac..7137439 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3690,6 +3690,7 @@ static int i915_scheduler_info(struct seq_file *m, void 
*unused)
struct intel_engine_cs *ring;
char   str[50 * (I915_NUM_RINGS + 1)], name[50], *ptr;
int ret, i, r;
+   uint32_t pa[I915_NUM_RINGS], pd[I915_NUM_RINGS];
 
ret = mutex_lock_interruptible(&dev->mode_config.mutex);
if (ret)
@@ -3706,17 +3707,32 @@ static int i915_scheduler_info(struct seq_file *m, void 
*unused)
seq_printf(m, "%s\n", str); \
} while (0)
 
+   for_each_ring(ring, dev_priv, r) {
+   pa[r] = intel_read_status_page(ring, 
I915_PREEMPTIVE_ACTIVE_SEQNO);
+   pd[r] = intel_read_status_page(ring, 
I915_PREEMPTIVE_DONE_SEQNO);
+   }
+
PRINT_VAR("Ring name:", "s", dev_priv->ring[r].name);
PRINT_VAR("  Ring seqno",   "d", ring->get_seqno(ring, false));
+   PRINT_VAR("  Preemption active","d", pa[r]);
+   PRINT_VAR("  Preemption done",  "d", pd[r]);
seq_putc(m, '\n');
 
seq_puts(m, "Batch submissions:\n");
PRINT_VAR("  Queued",   "u", stats[r].queued);
PRINT_VAR("  Submitted","u", stats[r].submitted);
+   PRINT_VAR("  Preempted","u", stats[r].preempted);
PRINT_VAR("  Completed","u", stats[r].completed);
PRINT_VAR("  Expired",  "u", stats[r].expired);
seq_putc(m, '\n');
 
+   seq_puts(m, "Preemptions:\n");
+   PRINT_VAR("  Preempts queued",  "u", stats[r].preempts_queued);
+   PRINT_VAR("  Preempts submitted",   "u", stats[r].preempts_submitted);
+   PRINT_VAR("  Preempts completed",   "u", stats[r].preempts_completed);
+   PRINT_VAR("  Max preempted","u", stats[r].max_preempted);
+   seq_putc(m, '\n');
+
seq_puts(m, "Flush counts:\n");
PRINT_VAR("  By object","u", stats[r].flush_obj);
PRINT_VAR("  By request",   "u", stats[r].flush_req);
@@ -3727,6 +3743,8 @@ static int i915_scheduler_info(struct seq_file *m, void 
*unused)
seq_putc(m, '\n');
 
seq_puts(m, "Miscellaneous:\n");
+   PRINT_VAR("  Non batch launched",   "u", stats[r].non_batch);
+   PRINT_VAR("  Non batch landed", "u", stats[r].non_batch_done);
PRINT_VAR("  ExecEarly retry",  "u", stats[r].exec_early);
PRINT_VAR("  ExecFinal requeue","u", stats[r].exec_again);
PRINT_VAR("  ExecFinal killed", "u", stats[r].exec_dead);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 06dff5a..7b5778b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2314,6 +2314,7 @@ struct drm_i915_gem_request {
struct pid *pid;
 
struct i915_scheduler_queue_entry   *scheduler_qe;
+   uint32_tscheduler_flags;
 
/**
 * The ELSP only accepts two elements at a time, so we queue
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 5257f5c..1597a15 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -25,6 +25,16 @@
 #ifndef _I915_SCHEDULER_H_
 #define _I915_SCHEDULER_H_
 
+/* Flag bits for drm_i915_gem_request::scheduler_flags */
+enum {
+   /* Request not submitted via scheduler */
+   i915_req_sf_untracked= (1 << 0),
+   /* Request was originally preemptive */
+   i915_req_sf_was_preempt  = (1 << 1),
+   /* Request is preemptive */
+   i915_req_sf_preempt  = (1 << 2),
+};
+
 enum i915_scheduler_queue_status {
/* Limbo: */
i915_sqs_none = 0,
@@ -34,6 +44,10 @@ enum i915_scheduler_queue_status {
i915_sqs_popped,
/* Sent to hardware for processing: */
i915_sqs_flying,
+   /* Sent to hardware for high-priority processing: */
+   i915_sqs_overtaking,
+   /* Previously submitted, but not completed */
+   i915_sqs_preempted,
/* Finished processing on the hardware: */
i915_sqs_complete,
/* Killed by watchdog or catastrophic submission failure: */
@@ -45,11 +59,20 @@ char i915_scheduler_queue_status_chr(enum 
i915_scheduler_queue_status status);
 const char *i915_scheduler_queue_status_str(
enum i915_scheduler_queue_status status);
 
-#define I915_SQS_IS_QUEUED(node)   (((node)->s

[Intel-gfx] [RFC 31/37] drm/i915/preempt: scheduler logic for landing preemptive requests

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This patch adds the GEM & scheduler logic for detection and first-stage
processing of completed preemption requests. Similar to regular batches,
they deposit their sequence number in the hardware status page when
starting and again when finished, but using different locations so that
information pertaining to a preempted batch is not overwritten. Also,
the in-progress flag is not by the GPU cleared at the end of the batch;
instead driver software is responsible for clearing this once the
request completion has been noticed.

Actually-preemptive requests are still disabled via a module parameter
at this early stage, as the rest of the logic to deal with the
consequences of preemption isn't in place yet.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gem.c   | 68 --
 drivers/gpu/drm/i915/i915_scheduler.c | 70 ++-
 drivers/gpu/drm/i915/i915_scheduler.h |  3 +-
 3 files changed, 120 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 55317b1ca..48a57c0 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2493,6 +2493,14 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
ring->last_irq_seqno = 0;
}
 
+   /* Also reset sw batch tracking state */
+   for_each_ring(ring, dev_priv, i) {
+   intel_write_status_page(ring, I915_BATCH_DONE_SEQNO, 0);
+   intel_write_status_page(ring, I915_BATCH_ACTIVE_SEQNO, 0);
+   intel_write_status_page(ring, I915_PREEMPTIVE_DONE_SEQNO, 0);
+   intel_write_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO, 0);
+   }
+
return 0;
 }
 
@@ -2829,6 +2837,7 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
struct drm_i915_gem_request *req, *req_next;
unsigned long flags;
bool wake_sched = false;
+   u32 preempt;
u32 seqno;
 
if (list_empty(&ring->fence_signal_list)) {
@@ -2836,9 +2845,23 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
return;
}
 
-   seqno = ring->get_seqno(ring, false);
+   seqno   = ring->get_seqno(ring, false);
+   preempt = i915_scheduler_is_ring_preempting(ring) ?
+ intel_read_status_page(ring, I915_PREEMPTIVE_ACTIVE_SEQNO) : 
0;
trace_i915_gem_request_notify(ring, seqno);
-   if (seqno == ring->last_irq_seqno)
+
+   if (preempt) {
+   u32 preempt_done;
+
+   preempt_done = intel_read_status_page(ring, 
I915_PREEMPTIVE_DONE_SEQNO);
+
+   /* A mismatch indicates an in-progress operation so ignore it 
for now */
+   if (preempt_done != preempt)
+   preempt = 0;
+   }
+
+   /* Is there anything new to process? */
+   if ((seqno == ring->last_irq_seqno) && !preempt)
return;
ring->last_irq_seqno = seqno;
 
@@ -2866,7 +2889,7 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
 * and call scheduler_clean() while the scheduler
 * thinks it is still active.
 */
-   wake_sched |= i915_scheduler_notify_request(req);
+   wake_sched |= i915_scheduler_notify_request(req, false);
 
if (!req->cancelled) {
fence_signal_locked(&req->fence);
@@ -2882,6 +2905,45 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
list_add_tail(&req->unsignal_link, &ring->fence_unsignal_list);
}
 
+   /*
+* Note that doing the pre-emption seqno check before acquiring the
+* spinlock means that there could be multiple request_notify() calls
+* attempting to process preemption concurrently. The advantage is
+* not needing to grab the spinlock when there is nothing to do.
+* The disadvantage is needed to re-check to see if the preemption
+* event has already been processed.
+*/
+   if (preempt) {
+   u32 preempt_done;
+
+   preempt = intel_read_status_page(ring, 
I915_PREEMPTIVE_ACTIVE_SEQNO);
+   preempt_done = intel_read_status_page(ring, 
I915_PREEMPTIVE_DONE_SEQNO);
+
+   /* A mismatch indicates an in-progress operation so ignore it 
for now */
+   if (preempt_done != preempt)
+   preempt = 0;
+   }
+
+   /* If a (completed) preemption has occurred then process it now. */
+   if (preempt) {
+   bool sched_ack = false;
+
+   list_for_each_entry_safe(req, req_next, 
&ring->fence_signal_list, signal_link) {
+   if (req->seqno == preempt) {
+   /* De-list and notify the scheduler, but don't 
signal yet */
+   

[Intel-gfx] [RFC 17/37] drm/i915/guc: Add support for GuC ADS (Addition Data Structure)

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

The GuC firmware uses this for various purposes; it seems to be
required for preemption to work.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_guc_reg.h|  1 +
 drivers/gpu/drm/i915/i915_guc_submission.c | 57 ++-
 drivers/gpu/drm/i915/intel_guc.h   |  2 +
 drivers/gpu/drm/i915/intel_guc_fwif.h  | 73 +-
 drivers/gpu/drm/i915/intel_guc_loader.c| 14 --
 5 files changed, 141 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_guc_reg.h 
b/drivers/gpu/drm/i915/i915_guc_reg.h
index b51b828..10947de 100644
--- a/drivers/gpu/drm/i915/i915_guc_reg.h
+++ b/drivers/gpu/drm/i915/i915_guc_reg.h
@@ -40,6 +40,7 @@
 #define   GS_MIA_CORE_STATE  (1 << GS_MIA_SHIFT)
 
 #define SOFT_SCRATCH(n)(0xc180 + ((n) * 4))
+#define SOFT_SCRATCH_COUNT 16
 
 #define UOS_RSA_SCRATCH(i) (0xc200 + (i) * 4)
 #define   UOS_RSA_SCRATCH_MAX_COUNT  64
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index d11bba9..035f126 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -611,9 +611,10 @@ static int guc_add_workqueue_item(struct i915_guc_client 
*gc,
wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, rq->ring);
 
/* The GuC firmware wants the tail index in QWords, not bytes */
+   WARN_ON(rq->ringbuf->tail & 7);
tail = rq->ringbuf->tail >> 3;
wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
-   wqi->fence_id = 0; /*XXX: what fence to be here */
+   wqi->fence_id = rq->seqno; /*XXX: what fence to be here */
 
kunmap_atomic(base);
 
@@ -926,6 +927,57 @@ static void guc_create_log(struct intel_guc *guc)
guc->log_flags = (offset << GUC_LOG_BUF_ADDR_SHIFT) | flags;
 }
 
+static void guc_create_addon(struct intel_guc *guc)
+{
+   struct drm_i915_private *dev_priv = guc_to_i915(guc);
+   struct drm_i915_gem_object *obj;
+   struct guc_ads *ads;
+   struct intel_engine_cs *ring;
+   struct page *page;
+   u32 size, i;
+
+   /* The ads obj includes the struct itself, plus memory for GuC to use
+* internally to save MMIO registers and states when reset or PM state
+* change happens. */
+   size = PAGE_ALIGN(sizeof(struct guc_ads)) +
+   PAGE_ALIGN(sizeof(struct guc_mmio_reg_state)) +
+   GUC_MAX_S3_SAVE_SPACE_PAGES * PAGE_SIZE;
+
+   obj = guc->ads_obj;
+   if (!obj) {
+   obj = gem_allocate_guc_obj(dev_priv->dev, size);
+   if (!obj)
+   return;
+
+   guc->ads_obj = obj;
+   }
+
+   page = i915_gem_object_get_page(obj, 0);
+   ads = kmap_atomic(page);
+   if (!ads) {
+   guc->ads_obj = NULL;
+   gem_release_guc_obj(obj);
+   return;
+   }
+
+   /* TODO: Fill up the register table here */
+   ads->mmio_reg_state_addr = i915_gem_obj_ggtt_offset(obj) +
+   PAGE_ALIGN(sizeof(struct guc_ads));
+
+   ads->guc_state_saved_buffer = ads->mmio_reg_state_addr +
+   PAGE_ALIGN(sizeof(struct guc_mmio_reg_state));
+
+   /* TODO: a Goldern Context is needed by GuC to initialize lrc context
+* after reset. Here we use the render ring default context. */
+   ring = &dev_priv->ring[RCS];
+   ads->golden_context_lrca = ring->status_page.gfx_addr;
+
+   for_each_ring(ring, dev_priv, i)
+   ads->eng_state_size[i] = intel_lr_context_size(ring);
+
+   kunmap_atomic(ads);
+}
+
 /*
  * Set up the memory resources to be shared with the GuC.  At this point,
  * we require just one object that can be mapped through the GGTT.
@@ -953,6 +1005,7 @@ int i915_guc_submission_init(struct drm_device *dev)
ida_init(&guc->ctx_ids);
 
guc_create_log(guc);
+   guc_create_addon(guc);
 
return 0;
 }
@@ -1000,6 +1053,8 @@ void i915_guc_submission_fini(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
 
+   gem_release_guc_obj(dev_priv->guc.ads_obj);
+   guc->ads_obj = NULL;
gem_release_guc_obj(dev_priv->guc.log_obj);
guc->log_obj = NULL;
 
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 0793713..150d596 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -90,6 +90,8 @@ struct intel_guc {
uint32_t log_flags;
struct drm_i915_gem_object *log_obj;
 
+   struct drm_i915_gem_object *ads_obj;
+
struct drm_i915_gem_object *ctx_pool_obj;
struct ida ctx_ids;
 
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 110496a..9f5be1d 100644
--- a/drivers/gpu/drm/i915/in

[Intel-gfx] [RFC 11/37] drm/i915/guc: Add a second client, to be used for preemption

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

This second client is created with priority KMD_HIGH, and marked
as preemptive.

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_debugfs.c|  9 +
 drivers/gpu/drm/i915/i915_guc_submission.c | 15 ++-
 drivers/gpu/drm/i915/intel_guc.h   |  1 +
 3 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index fefe73c..9e8f624 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2690,6 +2690,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc guc;
struct i915_guc_client client = {};
+   struct i915_guc_client preempt = {};
struct intel_engine_cs *ring;
enum intel_ring_id i;
u64 total = 0;
@@ -2705,6 +2706,11 @@ static int i915_guc_info(struct seq_file *m, void *data)
client = *guc.execbuf_client;
spin_unlock(&guc.execbuf_client->wq_lock);
}
+   if (guc.preempt_client) {
+   spin_lock(&guc.preempt_client->wq_lock);
+   preempt = *guc.preempt_client;
+   spin_unlock(&guc.preempt_client->wq_lock);
+   }
spin_unlock(&dev_priv->guc.host2guc_lock);
 
seq_printf(m, "GuC total action count: %llu\n", guc.action_count);
@@ -2725,6 +2731,9 @@ static int i915_guc_info(struct seq_file *m, void *data)
seq_printf(m, "\nGuC execbuf client @ %p:\n", guc.execbuf_client);
i915_guc_client_info(m, dev_priv, &client);
 
+   seq_printf(m, "\nGuC preempt client @ %p:\n", guc.preempt_client);
+   i915_guc_client_info(m, dev_priv, &preempt);
+
/* Add more as required ... */
 
return 0;
diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 55e10eb..d8fd644 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -395,6 +395,8 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
memset(&desc, 0, sizeof(desc));
 
desc.attribute = GUC_CTX_DESC_ATTR_ACTIVE | GUC_CTX_DESC_ATTR_KERNEL;
+   if (client->priority <= GUC_CTX_PRIORITY_HIGH)
+   desc.attribute |= GUC_CTX_DESC_ATTR_PREEMPT;
desc.context_id = client->ctx_index;
desc.priority = client->priority;
desc.db_id = client->doorbell_id;
@@ -588,6 +590,9 @@ int i915_guc_submit(struct i915_guc_client *client,
unsigned long flags;
int q_ret, b_ret;
 
+   if (WARN_ON(ring_id >= I915_NUM_RINGS))
+   return -ENXIO;
+
/* Need this because of the deferred pin ctx and ring */
/* Shall we move this right after ring is pinned? */
lr_context_update(rq);
@@ -882,9 +887,15 @@ int i915_guc_submission_enable(struct drm_device *dev)
DRM_ERROR("Failed to create execbuf guc_client\n");
return -ENOMEM;
}
-
guc->execbuf_client = client;
 
+   /* 2nd client for preemptive submission */
+   client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_HIGH, ctx);
+   if (!client) {
+   DRM_ERROR("Failed to create preemptive guc_client\n");
+   }
+   guc->preempt_client = client;
+
host2guc_sample_forcewake(guc, client);
 
return 0;
@@ -895,6 +906,8 @@ void i915_guc_submission_disable(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
 
+   guc_client_free(dev, guc->preempt_client);
+   guc->preempt_client = NULL;
guc_client_free(dev, guc->execbuf_client);
guc->execbuf_client = NULL;
 }
diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h
index 386e79a..f56e0d9 100644
--- a/drivers/gpu/drm/i915/intel_guc.h
+++ b/drivers/gpu/drm/i915/intel_guc.h
@@ -94,6 +94,7 @@ struct intel_guc {
struct ida ctx_ids;
 
struct i915_guc_client *execbuf_client;
+   struct i915_guc_client *preempt_client;
 
spinlock_t host2guc_lock;   /* Protects all data below  */
 
-- 
1.9.1

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


[Intel-gfx] [RFC 04/37] drm/i915/error: capture execlist state on error

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

At present, execlist status/ctx_id and CSBs, not the submission queue

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |  9 +
 drivers/gpu/drm/i915/i915_gpu_error.c | 38 +--
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 809816a..782591f8 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -556,6 +556,15 @@ struct drm_i915_error_state {
u32 rc_psmi; /* sleep state */
u32 semaphore_mboxes[I915_NUM_RINGS - 1];
 
+   /* Execlists */
+   u32 execlist_status;
+   u32 execlist_ctx_id;
+   u32 execlist_csb_raw_pointer;
+   u32 execlist_csb_write_pointer;
+   u32 execlist_csb_read_pointer;
+   u32 execlist_csb[6];
+   u32 execlist_ctx[6];
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 27b6ac9..fcb9487 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -247,6 +247,7 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
  int ring_idx)
 {
struct drm_i915_error_ring *ring = &error->ring[ring_idx];
+   int i;
 
if (!ring->valid)
return;
@@ -288,7 +289,6 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
err_printf(m, "  GFX_MODE: 0x%08x\n", ring->vm_info.gfx_mode);
 
if (INTEL_INFO(dev)->gen >= 8) {
-   int i;
for (i = 0; i < 4; i++)
err_printf(m, "  PDP%d: 0x%016llx\n",
   i, ring->vm_info.pdp[i]);
@@ -304,6 +304,17 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
err_printf(m, "  hangcheck: %s [%d]\n",
   hangcheck_action_to_str(ring->hangcheck_action),
   ring->hangcheck_score);
+
+   err_printf(m, "  EXECLIST_STATUS: 0x%08x\n", ring->execlist_status);
+   err_printf(m, "  EXECLIST_CTX_ID: 0x%08x\n", ring->execlist_ctx_id);
+   err_printf(m, "  EXECLIST_CSBPTR: 0x%08x\n", 
ring->execlist_csb_raw_pointer);
+   err_printf(m, "  EXECLIST_CSB_WR: 0x%08x\n", 
ring->execlist_csb_write_pointer);
+   err_printf(m, "  EXECLIST_CSB_RD: 0x%08x\n", 
ring->execlist_csb_read_pointer);
+
+   for (i = 0; i < 6; i++) {
+   err_printf(m, "  EXECLIST_CSB[%d]: 0x%08x\n", i, 
ring->execlist_csb[i]);
+   err_printf(m, "  EXECLIST_CTX[%d]: 0x%08x\n", i, 
ring->execlist_ctx[i]);
+   }
 }
 
 void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...)
@@ -871,6 +882,7 @@ static void i915_record_ring_state(struct drm_device *dev,
   struct drm_i915_error_ring *ering)
 {
struct drm_i915_private *dev_priv = dev->dev_private;
+   int i;
 
if (INTEL_INFO(dev)->gen >= 6) {
ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
@@ -961,8 +973,26 @@ static void i915_record_ring_state(struct drm_device *dev,
I915_READ(GEN8_RING_PDP_LDW(ring, i));
}
}
-}
 
+   if (i915.enable_execlists) {
+   u32 status_pointer = I915_READ(RING_CONTEXT_STATUS_PTR(ring));
+   u8 write_pointer = status_pointer & 0x07;
+   u8 read_pointer = ring->next_context_status_buffer;
+   if (read_pointer > write_pointer)
+   write_pointer += 6;
+
+   ering->execlist_status = 
I915_READ(RING_EXECLIST_STATUS_LO(ring));
+   ering->execlist_ctx_id = 
I915_READ(RING_EXECLIST_STATUS_HI(ring));
+   ering->execlist_csb_raw_pointer = status_pointer;
+   ering->execlist_csb_write_pointer = write_pointer;
+   ering->execlist_csb_read_pointer = read_pointer;
+
+   for (i = 0; i < 6; i++) {
+   ering->execlist_csb[i] = 
I915_READ(RING_CONTEXT_STATUS_BUF_LO(ring, i));
+   ering->execlist_ctx[i] = 
I915_READ(RING_CONTEXT_STATUS_BUF_HI(ring, i));
+   }
+   }
+}
 
 static void i915_gem_record_active_context(struct intel_engine_cs *ring,
   struct drm_i915_error_state *error,
@@ -1248,6 +1278,10 @@ static void i915_capture_reg_state(struct 
drm_i915_private *dev_priv,
if (HAS_HW_CONTEXTS(dev))
error->ccid = I915_READ(CCID);
 
+   if (HAS_LOGICAL_RING_CONTEXTS(dev)) {
+   // Surely something to capture here ...
+   }
+
if (IN

[Intel-gfx] [RFC 00/37] Preemption support for GPU scheduler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

Added pre-emption support to the i915 GPU scheduler.

Note that this patch series was written by David Gordon. I have simply
ported it onto a more recent set of scheduler patches and am uploading
it as part of that work so that everything can be viewed at once. Also
because David is on extended vacation at the moment. Not that the
series is being sent as an RFC as there are still some things to be
tidied up. Most notably the commit messages are missing in a few
places. I am leaving those to be filled in by David when he returns.

Also, the series includes a few general fix up and improvement patches
that are not directly related to pre-emption. E.g. for improving the
error capture state. However, the pre-emption code is built upon them
so right now it is much simpler to just send the whole lot out as a
single series. It can be broken up into separate patch sets if/when
people decide it is all good stuff to be doing.

Re the pre-emption itself. It is functional and working but with the
caveat that it requires the GuC. Hence it is only operation on SKL or
later hardware. If the GuC is not available then the pre-emption
support is simply disabled in the scheduler.

[Patches against drm-intel-nightly tree fetched 17/11/2015 with struct fence
conversion and GPU scheduler patches applied]

Dave Gordon (36):
  drm/i915: update ring space correctly
  drm/i915: recalculate ring space after reset
  drm/i915: hangcheck=idle should wake_up_all every time, not just once
  drm/i915/error: capture execlist state on error
  drm/i915/error: capture ringbuffer pointed to by START
  drm/i915/error: report ctx id & desc for each request in the queue
  drm/i915/error: improve CSB reporting
  drm/i915/error: report size in pages for each object dumped
  drm/i915/error: track, capture & print ringbuffer submission activity
  drm/i915/guc: Tidy up GuC proc/ctx descriptor setup
  drm/i915/guc: Add a second client, to be used for preemption
  drm/i915/guc: implement submission via REQUEST_PREEMPTION action
  drm/i915/guc: Improve action error reporting, add preemption debug
  drm/i915/guc: Expose GuC-maintained statistics
  drm/i915: add i915_wait_request() call after i915_add_request_no_flush()
  drm/i915/guc: Expose (intel)_lr_context_size()
  drm/i915/guc: Add support for GuC ADS (Addition Data Structure)
  drm/i915/guc: Fill in (part of?) the ADS whitelist
  drm/i915/error: capture errored context based on request context-id
  drm/i915/error: enhanced error capture of requests
  drm/i915/error: add GuC state error capture & decode
  drm/i915: track relative-constants-mode per-context not per-device
  drm/i915: set request 'head' on allocation not in add_request()
  drm/i915/sched: set request 'head' on at start of ring submission
  drm/i915/sched: include scheduler state in error capture
  drm/i915/preempt: preemption-related definitions and statistics
  drm/i915/preempt: scheduler logic for queueing preemptive requests
  drm/i915/preempt: scheduler logic for selecting preemptive requests
  drm/i915/preempt: scheduler logic for preventing recursive preemption
  drm/i915/preempt: don't allow nonbatch ctx init when the scheduler is
busy
  drm/i915/preempt: scheduler logic for landing preemptive requests
  drm/i915/preempt: add hook to catch 'unexpected' ring submissions
  drm/i915/preempt: Refactor intel_lr_context_reset()
  drm/i915/preempt: scheduler logic for postprocessing preemptive
requests
  drm/i915/preempt: update (LRC) ringbuffer-filling code to create
preemptive requests
  drm/i915/preempt: update scheduler parameters to enable preemption

John Harrison (1):
  drm/i915: Added preemption info to various trace points

 drivers/gpu/drm/i915/i915_debugfs.c|  49 +++-
 drivers/gpu/drm/i915/i915_drv.h|  34 ++-
 drivers/gpu/drm/i915/i915_gem.c| 136 -
 drivers/gpu/drm/i915/i915_gem_context.c|   5 +-
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   9 +-
 drivers/gpu/drm/i915/i915_gpu_error.c  | 307 ++--
 drivers/gpu/drm/i915/i915_guc_reg.h|   1 +
 drivers/gpu/drm/i915/i915_guc_submission.c | 243 +---
 drivers/gpu/drm/i915/i915_irq.c|  23 +-
 drivers/gpu/drm/i915/i915_scheduler.c  | 445 ++---
 drivers/gpu/drm/i915/i915_scheduler.h  |  46 ++-
 drivers/gpu/drm/i915/i915_trace.h  |  31 +-
 drivers/gpu/drm/i915/intel_guc.h   |  31 +-
 drivers/gpu/drm/i915/intel_guc_fwif.h  |  93 +-
 drivers/gpu/drm/i915/intel_guc_loader.c|  14 +-
 drivers/gpu/drm/i915/intel_lrc.c   | 282 +-
 drivers/gpu/drm/i915/intel_lrc.h   |   7 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c|   2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.h|  14 +
 19 files changed, 1511 insertions(+), 261 deletions(-)

-- 
1.9.1

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org

[Intel-gfx] [RFC 18/37] drm/i915/guc: Fill in (part of?) the ADS whitelist

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_guc_submission.c | 11 +++
 drivers/gpu/drm/i915/intel_guc_fwif.h  |  6 ++
 2 files changed, 17 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c 
b/drivers/gpu/drm/i915/i915_guc_submission.c
index 035f126..59116fb 100644
--- a/drivers/gpu/drm/i915/i915_guc_submission.c
+++ b/drivers/gpu/drm/i915/i915_guc_submission.c
@@ -931,6 +931,7 @@ static void guc_create_addon(struct intel_guc *guc)
 {
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct drm_i915_gem_object *obj;
+   struct guc_mmio_reg_state *reg_state;
struct guc_ads *ads;
struct intel_engine_cs *ring;
struct page *page;
@@ -964,6 +965,16 @@ static void guc_create_addon(struct intel_guc *guc)
ads->mmio_reg_state_addr = i915_gem_obj_ggtt_offset(obj) +
PAGE_ALIGN(sizeof(struct guc_ads));
 
+   i = PAGE_ALIGN(sizeof(struct guc_ads)) / PAGE_SIZE;
+   page = i915_gem_object_get_page(obj, i);
+
+   reg_state = kmap_atomic(page);
+   for (i = 0; i < I915_NUM_RINGS; i++)
+   reg_state->mmio_white_list[i].mmio_start =
+   dev_priv->ring[i].mmio_base + 
KM_GEN8_MMIO_WHITE_LIST_START;
+
+   kunmap_atomic(reg_state);
+
ads->guc_state_saved_buffer = ads->mmio_reg_state_addr +
PAGE_ALIGN(sizeof(struct guc_mmio_reg_state));
 
diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h 
b/drivers/gpu/drm/i915/intel_guc_fwif.h
index 9f5be1d..649f6d8 100644
--- a/drivers/gpu/drm/i915/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/intel_guc_fwif.h
@@ -333,6 +333,12 @@ struct guc_context_desc {
 #define GUC_REGSET_MAX_REGISTERS_PER_SET   20
 
 #define KM_MMIO_WHITE_LIST_MAX_OFFSETS 12
+
+#define KM_GEN8_MMIO_WHITE_LIST_START   0x24d0  // BSPEC Name: 
FORCE_TO_NONPRIV
+#define KM_GEN8_MMIO_WHITE_LIST_END 0x24ff
+#define KM_GEN8_MMIO_WHITE_LIST_DEFAULT 0x2094
+#define KM_GEN8_MMIO_WHITE_LIST_NONFUNCTONAL_INDEX  4   // The fifth element 
doesn't work but the index would be 4
+
 struct guc_mmio_white_list {
u32 mmio_start;
u32 offsets[KM_MMIO_WHITE_LIST_MAX_OFFSETS];
-- 
1.9.1

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


[Intel-gfx] [RFC 01/37] drm/i915: update ring space correctly

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/intel_lrc.c| 2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 7a3fb219..f64283f 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -728,7 +728,7 @@ static int logical_ring_wait_for_space(struct 
drm_i915_gem_request *req,
if (ret)
return ret;
 
-   ringbuf->space = space;
+   intel_ring_update_space(ringbuf);
return 0;
 }
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 97b9dfa..a709427 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2260,7 +2260,7 @@ static int ring_wait_for_space(struct intel_engine_cs 
*ring, int n)
if (ret)
return ret;
 
-   ringbuf->space = space;
+   intel_ring_update_space(ringbuf);
return 0;
 }
 
-- 
1.9.1

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


[Intel-gfx] [RFC 03/37] drm/i915: hangcheck=idle should wake_up_all every time, not just once

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_irq.c | 23 ---
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index d280e05..eb55a41 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -2973,23 +2973,24 @@ static void i915_hangcheck_elapsed(struct work_struct 
*work)
 
if (ring->hangcheck.seqno == seqno) {
if (ring_idle(ring, seqno)) {
+   busy = false;
ring->hangcheck.action = HANGCHECK_IDLE;
 
if (waitqueue_active(&ring->irq_queue)) {
+   if 
(!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
+   DRM_ERROR("Hangcheck timer 
elapsed... %s idle\n",
+ ring->name);
+   else
+   DRM_INFO("Fake missed irq on 
%s\n",
+ring->name);
+
/* Issue a wake-up to catch stuck h/w. 
*/
-   if (!test_and_set_bit(ring->id, 
&dev_priv->gpu_error.missed_irq_rings)) {
-   if 
(!(dev_priv->gpu_error.test_irq_rings & intel_ring_flag(ring)))
-   DRM_ERROR("Hangcheck 
timer elapsed... %s idle\n",
- ring->name);
-   else
-   DRM_INFO("Fake missed 
irq on %s\n",
-ring->name);
-   wake_up_all(&ring->irq_queue);
-   }
+   set_bit(ring->id, 
&dev_priv->gpu_error.missed_irq_rings);
+   wake_up_all(&ring->irq_queue);
/* Safeguard against driver failure */
ring->hangcheck.score += BUSY;
-   } else
-   busy = false;
+   busy = true;
+   }
} else {
/* We always increment the hangcheck score
 * if the ring is busy and still processing
-- 
1.9.1

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


[Intel-gfx] [RFC 08/37] drm/i915/error: report size in pages for each object dumped

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_gpu_error.c | 23 ++-
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 52def4e..bafaadd 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -490,17 +490,19 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
err_printf(m, " (submitted by %s [%d])",
   error->ring[i].comm,
   error->ring[i].pid);
-   err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
+   err_printf(m, " --- gtt_offset = 0x%08x %08x; %d 
pages\n",
   upper_32_bits(obj->gtt_offset),
-  lower_32_bits(obj->gtt_offset));
+  lower_32_bits(obj->gtt_offset),
+  obj->page_count);
print_error_obj(m, obj);
}
 
obj = error->ring[i].wa_batchbuffer;
if (obj) {
-   err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x\n",
+   err_printf(m, "%s (w/a) --- gtt_offset = 0x%08x; %d 
pages\n",
   dev_priv->ring[i].name,
-  lower_32_bits(obj->gtt_offset));
+  lower_32_bits(obj->gtt_offset),
+  obj->page_count);
print_error_obj(m, obj);
}
 
@@ -520,18 +522,20 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
}
 
if ((obj = error->ring[i].req_ringbuffer)) {
-   err_printf(m, "%s --- ringbuffer = 0x%08x (ctx_desc 
0x%08x_%08x)\n",
+   err_printf(m, "%s --- ringbuffer = 0x%08x; %d pages 
(ctx_desc 0x%08x_%08x)\n",
   dev_priv->ring[i].name,
   lower_32_bits(obj->gtt_offset),
+  obj->page_count,
   upper_32_bits(error->ring[i].ctx_desc),
   lower_32_bits(error->ring[i].ctx_desc));
print_error_obj(m, obj);
}
 
if ((obj = error->ring[i].hw_ringbuffer)) {
-   err_printf(m, "%s --- HW ringbuffer = 0x%08x\n",
+   err_printf(m, "%s --- HW ringbuffer = 0x%08x; %d 
pages\n",
   dev_priv->ring[i].name,
-  lower_32_bits(obj->gtt_offset));
+  lower_32_bits(obj->gtt_offset),
+  obj->page_count);
print_error_obj(m, obj);
}
 
@@ -558,9 +562,10 @@ int i915_error_state_to_str(struct 
drm_i915_error_state_buf *m,
}
 
if ((obj = error->ring[i].ctx)) {
-   err_printf(m, "%s --- HW Context = 0x%08x\n",
+   err_printf(m, "%s --- HW Context = 0x%08x; %d pages\n",
   dev_priv->ring[i].name,
-  lower_32_bits(obj->gtt_offset));
+  lower_32_bits(obj->gtt_offset),
+  obj->page_count);
print_error_obj(m, obj);
}
}
-- 
1.9.1

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


[Intel-gfx] [RFC 07/37] drm/i915/error: improve CSB reporting

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

For: VIZ-2021
Signed-off-by: Dave Gordon 
---
 drivers/gpu/drm/i915/i915_drv.h   |  4 +-
 drivers/gpu/drm/i915/i915_gpu_error.c | 88 ---
 2 files changed, 64 insertions(+), 28 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 41999cc..779fc70 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -565,6 +565,8 @@ struct drm_i915_error_state {
u32 execlist_csb[6];
u32 execlist_ctx[6];
 
+   u64 ctx_desc;
+
struct drm_i915_error_object {
int page_count;
u64 gtt_offset;
@@ -572,7 +574,7 @@ struct drm_i915_error_state {
} *req_ringbuffer, *hw_ringbuffer, *batchbuffer, 
*wa_batchbuffer, *ctx, *hws_page;
 
struct drm_i915_error_request {
-   uint64_t ctx_desc;
+   u64 ctx_desc;
long jiffies;
u32 seqno;
u32 tail;
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c 
b/drivers/gpu/drm/i915/i915_gpu_error.c
index 56078c5..52def4e 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -305,31 +305,60 @@ static void i915_ring_error_state(struct 
drm_i915_error_state_buf *m,
   hangcheck_action_to_str(ring->hangcheck_action),
   ring->hangcheck_score);
 
-   err_printf(m, "  EXECLIST_STATUS: 0x%08x\n", ring->execlist_status);
-   err_printf(m, "  EXECLIST_CTX_ID: 0x%08x\n", ring->execlist_ctx_id);
-   err_printf(m, "  EXECLIST_CSBPTR: 0x%08x\n", 
ring->execlist_csb_raw_pointer);
-   err_printf(m, "  EXECLIST_CSB_WR: 0x%08x\n", 
ring->execlist_csb_write_pointer);
-   err_printf(m, "  EXECLIST_CSB_RD: 0x%08x\n", 
ring->execlist_csb_read_pointer);
+   {
+   u32 csb_rd = (ring->execlist_csb_raw_pointer >> 8) & 7;
+
+   err_printf(m, "  EXECLIST_STATUS: 0x%08x\n", 
ring->execlist_status);
+   err_printf(m, "  EXECLIST_CTX_ID: 0x%08x\n", 
ring->execlist_ctx_id);
+   err_printf(m, "  EXECLIST_CSBPTR: 0x%08x\n", 
ring->execlist_csb_raw_pointer);
+   err_printf(m, "  EXECLIST_CSB_WR: %d\n", 
ring->execlist_csb_write_pointer);
+   err_printf(m, "  EXECLIST_CSB_RD: %d\n", csb_rd);
+   err_printf(m, "  EXECLIST_SWL_RD: %d\n", 
ring->execlist_csb_read_pointer);
+
+   for (i = 1; i <= 6; ++i) {
+   int n = (ring->execlist_csb_write_pointer + i) % 6;
+   u32 ctxid = ring->execlist_ctx[n];
+   u32 csb = ring->execlist_csb[n];
+   u32 tag = 0;
+   char dot = '.';
+   err_printf(m, "  EXECLIST_CTX/CSB[%d]: ", n);
+
+   if (ctxid && i915.enable_guc_submission) {
+   /* GuC CtxID is ring + flags + (lrca >> 12) */
+   tag = ((ring_idx << 9) | 1);
+   }
+   if ((ctxid >> 20) != tag)
+   dot = '?';  /* flag unexpected 
value */
+   err_printf(m, "0x%03x%c%05x / ",
+   ctxid >> 20, dot, ctxid & 0x000f);
 
+/* CSB status bits */
 #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)
-
-   for (i = 1; i <= 6; ++i) {
-   int n = (ring->execlist_csb_write_pointer + i) % 6;
-   u32 csb = ring->execlist_csb[n];
-   err_printf(m, "  EXECLIST_CTX/CSB[%d]:  0x%08x  0x%08x  ",
-   n, ring->execlist_ctx[n], csb);
-   err_printf(m, "%s %s %s %s %s %s\n",
-   csb & GEN8_CTX_STATUS_IDLE_ACTIVE   ? "I->A" : "
",
-   csb & GEN8_CTX_STATUS_PREEMPTED ? "PRMT" : "
",
-   csb & GEN8_CTX_STATUS_ELEMENT_SWITCH? "ELSW" : "
",
-   csb & GEN8_CTX_STATUS_ACTIVE_IDLE   ? "A->I" : "
",
-   csb & GEN8_CTX_STATUS_COMPLETE  ? "DONE" : "
",
-   csb & GEN8_CTX_STATUS_LITE_RESTORE  ? "LITE" : "
");
+#define GEN8_CTX_STATUS_UNKNOWN(~0x801f)   /* any other */
+
+   err_printf(m, "0x%08x  %s %s %s %s %s %s %s\n",
+   csb,
+   csb & GEN8_CTX_STATUS_IDLE_ACTIVE   ? 
"I->A" : "",
+   csb & GEN8_CTX_STATUS_PREEMPTED ? 
"PRMT" : "",
+   csb & G

[Intel-gfx] [PATCH 29/39] drm/i915: Added debugfs interface to scheduler tuning parameters

2015-11-23 Thread John . C . Harrison
From: John Harrison 

There are various parameters within the scheduler which can be tuned
to improve performance, reduce memory footprint, etc. This change adds
support for altering these via debugfs.

v2: Updated for priorities now being signed values.

Change-Id: I6c26765269ae7173ff4d3a5c20921eaaca7c36ed
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_debugfs.c | 141 
 1 file changed, 141 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index ecab9b8..8f1c10c 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -39,6 +39,7 @@
 #include "intel_ringbuffer.h"
 #include 
 #include "i915_drv.h"
+#include "i915_scheduler.h"
 
 enum {
ACTIVE_LIST,
@@ -1122,6 +1123,141 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops,
i915_next_seqno_get, i915_next_seqno_set,
"0x%llx\n");
 
+static int
+i915_scheduler_priority_min_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->priority_level_min;
+   return 0;
+}
+
+static int
+i915_scheduler_priority_min_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->priority_level_min = (int32_t) val;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_min_fops,
+   i915_scheduler_priority_min_get,
+   i915_scheduler_priority_min_set,
+   "%lld\n");
+
+static int
+i915_scheduler_priority_max_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->priority_level_max;
+   return 0;
+}
+
+static int
+i915_scheduler_priority_max_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->priority_level_max = (int32_t) val;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_max_fops,
+   i915_scheduler_priority_max_get,
+   i915_scheduler_priority_max_set,
+   "%lld\n");
+
+static int
+i915_scheduler_priority_preempt_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->priority_level_preempt;
+   return 0;
+}
+
+static int
+i915_scheduler_priority_preempt_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->priority_level_preempt = (u32) val;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_preempt_fops,
+   i915_scheduler_priority_preempt_get,
+   i915_scheduler_priority_preempt_set,
+   "%lld\n");
+
+static int
+i915_scheduler_min_flying_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->min_flying;
+   return 0;
+}
+
+static int
+i915_scheduler_min_flying_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->min_flying = (u32) val;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_min_flying_fops,
+   i915_scheduler_min_flying_get,
+   i915_scheduler_min_flying_set,
+   "%llu\n");
+
+static int
+i915_scheduler_file_queue_max_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->file_queue_max;
+   return 0;
+}
+
+static int
+i915_scheduler_file_queue_max_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *sched

[Intel-gfx] [PATCH 35/39] drm/i915: GPU priority bumping to prevent starvation

2015-11-23 Thread John . C . Harrison
From: John Harrison 

If a high priority task was to continuously submit batch buffers to
the driver, it could starve out any lower priority task from getting
any GPU time at all. To prevent this, the priority of a queued batch
buffer is bumped each time it does not get submitted to the hardware.

v2: Updated for signed priority values.

Change-Id: I0319c7d2f306c61a283f03edda9b5d09a6d3b621
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_debugfs.c   | 28 
 drivers/gpu/drm/i915/i915_scheduler.c | 14 ++
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 3 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 9e7d67d..66a2202 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1178,6 +1178,33 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_max_fops,
"%lld\n");
 
 static int
+i915_scheduler_priority_bump_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = (u64) scheduler->priority_level_bump;
+   return 0;
+}
+
+static int
+i915_scheduler_priority_bump_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->priority_level_bump = (u32) val;
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_priority_bump_fops,
+   i915_scheduler_priority_bump_get,
+   i915_scheduler_priority_bump_set,
+   "%lld\n");
+
+static int
 i915_scheduler_priority_preempt_get(void *data, u64 *val)
 {
struct drm_device   *dev   = data;
@@ -5672,6 +5699,7 @@ static const struct i915_debugfs_files {
{"i915_next_seqno", &i915_next_seqno_fops},
{"i915_scheduler_priority_min", &i915_scheduler_priority_min_fops},
{"i915_scheduler_priority_max", &i915_scheduler_priority_max_fops},
+   {"i915_scheduler_priority_bump", &i915_scheduler_priority_bump_fops},
{"i915_scheduler_priority_preempt", 
&i915_scheduler_priority_preempt_fops},
{"i915_scheduler_min_flying", &i915_scheduler_min_flying_fops},
{"i915_scheduler_file_queue_max", &i915_scheduler_file_queue_max_fops},
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 1f1dfa78..9035cdb 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -191,6 +191,7 @@ int i915_scheduler_init(struct drm_device *dev)
/* Default tuning values: */
scheduler->priority_level_min = -1023;
scheduler->priority_level_max = 1023;
+   scheduler->priority_level_bump= 50;
scheduler->priority_level_preempt = 900;
scheduler->min_flying = 2;
scheduler->file_queue_max = 64;
@@ -1502,6 +1503,19 @@ static int i915_scheduler_submit(struct intel_engine_cs 
*ring, bool was_locked)
ret = i915_scheduler_pop_from_queue_locked(ring, &node, &flags);
} while (ret == 0);
 
+   /*
+* Bump the priority of everything that was not submitted to prevent
+* starvation of low priority tasks by a spamming high priority task.
+*/
+   i915_scheduler_priority_bump_clear(scheduler);
+   list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+   if (!I915_SQS_IS_QUEUED(node))
+   continue;
+
+   i915_scheduler_priority_bump(scheduler, node,
+scheduler->priority_level_bump);
+   }
+
spin_unlock_irqrestore(&scheduler->lock, flags);
 
if (!was_locked)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index adaefa6..6e0dfa9 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -114,6 +114,7 @@ struct i915_scheduler {
/* Tuning parameters: */
int32_t priority_level_min;
int32_t priority_level_max;
+   int32_t priority_level_bump;
int32_t priority_level_preempt;
uint32_tmin_flying;
uint32_tfile_queue_max;
-- 
1.9.1

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


[Intel-gfx] [PATCH 17/39] drm/i915: Hook scheduler node clean up into retire requests

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler keeps its own lock on various DRM objects in order to guarantee
safe access long after the original execbuff IOCTL has completed. This is
especially important when pre-emption is enabled as the batch buffer might need
to be submitted to the hardware multiple times. This patch hooks the clean up of
these locks into the request retire function. The request can only be retired
after it has completed on the hardware and thus is no longer eligible for
re-submission. Thus there is no point holding on to the locks beyond that time.

For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem.c   |  3 +++
 drivers/gpu/drm/i915/i915_scheduler.c | 51 ---
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 3 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f625d88..451ae6d 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1402,6 +1402,9 @@ static void i915_gem_request_retire(struct 
drm_i915_gem_request *request)
fence_signal_locked(&request->fence);
}
 
+   if (request->scheduler_qe)
+   i915_gem_scheduler_clean_node(request->scheduler_qe);
+
i915_gem_request_unreference(request);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index cd69f53..5dc3497 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -383,6 +383,38 @@ void i915_scheduler_wakeup(struct drm_device *dev)
queue_work(dev_priv->wq, &dev_priv->mm.scheduler_work);
 }
 
+void i915_gem_scheduler_clean_node(struct i915_scheduler_queue_entry *node)
+{
+   uint32_t i;
+
+   if (WARN(!I915_SQS_IS_COMPLETE(node), "Incomplete node: %d!\n", 
node->status))
+   return;
+
+   if (node->params.batch_obj) {
+   /* The batch buffer must be unpinned before it is unreferenced
+* otherwise the unpin fails with a missing vma!? */
+   if (node->params.dispatch_flags & I915_DISPATCH_SECURE)
+   
i915_gem_execbuff_release_batch_obj(node->params.batch_obj);
+
+   node->params.batch_obj = NULL;
+   }
+
+   /* Release the locked buffers: */
+   for (i = 0; i < node->num_objs; i++) {
+   drm_gem_object_unreference(
+   &node->saved_objects[i].obj->base);
+   }
+   kfree(node->saved_objects);
+   node->saved_objects = NULL;
+   node->num_objs = 0;
+
+   /* Context too: */
+   if (node->params.ctx) {
+   i915_gem_context_unreference(node->params.ctx);
+   node->params.ctx = NULL;
+   }
+}
+
 static int i915_scheduler_remove(struct intel_engine_cs *ring)
 {
struct drm_i915_private *dev_priv = ring->dev->dev_private;
@@ -392,7 +424,7 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
int flying = 0, queued = 0;
int ret = 0;
booldo_submit;
-   uint32_ti, min_seqno;
+   uint32_tmin_seqno;
struct list_headremove;
 
if (list_empty(&scheduler->node_queue[ring->id]))
@@ -491,21 +523,8 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
node = list_first_entry(&remove, typeof(*node), link);
list_del(&node->link);
 
-   /* The batch buffer must be unpinned before it is unreferenced
-* otherwise the unpin fails with a missing vma!? */
-   if (node->params.dispatch_flags & I915_DISPATCH_SECURE)
-   
i915_gem_execbuff_release_batch_obj(node->params.batch_obj);
-
-   /* Release the locked buffers: */
-   for (i = 0; i < node->num_objs; i++) {
-   drm_gem_object_unreference(
-   &node->saved_objects[i].obj->base);
-   }
-   kfree(node->saved_objects);
-
-   /* Context too: */
-   if (node->params.ctx)
-   i915_gem_context_unreference(node->params.ctx);
+   /* Free up all the DRM object references */
+   i915_gem_scheduler_clean_node(node);
 
/* And anything else owned by the node: */
node->params.request->scheduler_qe = NULL;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index da095f9..8469270 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -87,6 +87,7 @@ booli915_scheduler_is_enabled(struct drm_device *dev);
 int i915_scheduler_init(struct drm_device *dev);
 int i915_scheduler_closefile(struct drm_device *dev,
 struct drm_file *file);
+

[Intel-gfx] [PATCH 25/39] drm/i915: Add sync wait support to scheduler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

There is a sync framework to allow work for multiple independent
systems to be synchronised with each other but without stalling
the CPU whether in the application or the driver. This patch adds
support for this framework to the GPU scheduler.

Batch buffers can now have sync framework fence objects associated with
them. The scheduler will look at this fence when deciding what to
submit next to the hardware. If the fence is outstanding then that
batch buffer will be passed over in preference of one that is ready to
run. If no other batches are ready then the scheduler will queue an
asynchronous callback to be woken up when the fence has been
signalled. The callback will wake the scheduler and submit the now
ready batch buffer.

v2: Updated to use the new sync_fence_is_signaled() API rather than
having to know about the internals of a fence object.

Also removed the spin lock from the fence wait callback function. This
was used to clear the 'waiting' flag. However, it causes a problem
with the TDR code. Specifically, when cancelling work packets due to a
TDR there is a code path where the fence can be signalled while the
spinlock is already held. It is not really necessary to clear the flag
anyway as it's purpose is solely to prevent multiple waits being
issued. Once the fence has been signalled, no further waits will be
attempted so it doesn't matter whether the fence is marked as having
an outstanding wait or not.

For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h   |   1 +
 drivers/gpu/drm/i915/i915_scheduler.c | 144 --
 drivers/gpu/drm/i915/i915_scheduler.h |   6 ++
 3 files changed, 146 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 15dee41..4187e75 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1698,6 +1698,7 @@ struct i915_execbuffer_params {
uint64_tbatch_obj_vm_offset;
struct intel_engine_cs  *ring;
struct drm_i915_gem_object  *batch_obj;
+   struct sync_fence   *fence_wait;
struct drm_clip_rect*cliprects;
uint32_tinstp_mask;
int instp_mode;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index d4d2466..939dc2b 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -25,6 +25,7 @@
 #include "i915_drv.h"
 #include "intel_drv.h"
 #include "i915_scheduler.h"
+#include <../drivers/android/sync.h>
 
 static int i915_scheduler_fly_node(struct i915_scheduler_queue_entry 
*node);
 static int i915_scheduler_remove_dependent(struct i915_scheduler 
*scheduler,
@@ -96,6 +97,9 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
if (i915.scheduler_override & i915_so_direct_submit) {
int ret;
 
+   WARN_ON(qe->params.fence_wait &&
+   (!sync_fence_is_signaled(qe->params.fence_wait)));
+
intel_ring_reserved_space_cancel(qe->params.request->ringbuf);
 
scheduler->flags[qe->params.ring->id] |= i915_sf_submitting;
@@ -130,6 +134,9 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
if (qe->params.dispatch_flags & I915_DISPATCH_SECURE)

i915_gem_execbuff_release_batch_obj(qe->params.batch_obj);
 
+   if (qe->params.fence_wait)
+   sync_fence_put(qe->params.fence_wait);
+
return 0;
}
 
@@ -531,6 +538,9 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
node = list_first_entry(&remove, typeof(*node), link);
list_del(&node->link);
 
+   if (node->params.fence_wait)
+   sync_fence_put(node->params.fence_wait);
+
/* Free up all the DRM object references */
i915_gem_scheduler_clean_node(node);
 
@@ -796,17 +806,94 @@ static int i915_scheduler_submit_max_priority(struct 
intel_engine_cs *ring,
return count;
 }
 
+/* Use a private structure in order to pass the 'dev' pointer through */
+struct i915_sync_fence_waiter {
+   struct sync_fence_waiter sfw;
+   struct drm_device*dev;
+   struct i915_scheduler_queue_entry *node;
+};
+
+/*
+ * NB: This callback can be executed at interrupt time. Further, it can be
+ * called from within the TDR reset sequence during a scheduler 'kill_all'
+ * and thus be called while the scheduler spinlock is already held. Thus
+ * it can grab neither the driver mutex nor the scheduler spinlock.
+ */
+static void i915_scheduler_wait_fence_signaled(struct sync_fence *fence,
+  struct sync_fence_waiter *waiter)
+{
+   struct i915_sync_fe

[Intel-gfx] [PATCH 36/39] drm/i915: Scheduler state dump via debugfs

2015-11-23 Thread John . C . Harrison
From: John Harrison 

Added a facility for triggering the scheduler state dump via a debugfs
entry.

v2: New patch in series.

For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_debugfs.c   | 33 +
 drivers/gpu/drm/i915/i915_scheduler.c |  9 +
 drivers/gpu/drm/i915/i915_scheduler.h |  6 ++
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 66a2202..1c1c4bd 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -1285,6 +1285,38 @@ 
DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_file_queue_max_fops,
i915_scheduler_file_queue_max_set,
"%llu\n");
 
+static int
+i915_scheduler_dump_flags_get(void *data, u64 *val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   *val = scheduler->dump_flags;
+
+   return 0;
+}
+
+static int
+i915_scheduler_dump_flags_set(void *data, u64 val)
+{
+   struct drm_device   *dev   = data;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   scheduler->dump_flags = lower_32_bits(val) & i915_sf_dump_mask;
+
+   if (val & 1)
+   i915_scheduler_dump_all(dev, "DebugFS");
+
+   return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(i915_scheduler_dump_flags_fops,
+   i915_scheduler_dump_flags_get,
+   i915_scheduler_dump_flags_set,
+   "0x%llx\n");
+
 static int i915_frequency_info(struct seq_file *m, void *unused)
 {
struct drm_info_node *node = m->private;
@@ -5703,6 +5735,7 @@ static const struct i915_debugfs_files {
{"i915_scheduler_priority_preempt", 
&i915_scheduler_priority_preempt_fops},
{"i915_scheduler_min_flying", &i915_scheduler_min_flying_fops},
{"i915_scheduler_file_queue_max", &i915_scheduler_file_queue_max_fops},
+   {"i915_scheduler_dump_flags", &i915_scheduler_dump_flags_fops},
{"i915_display_crc_ctl", &i915_display_crc_ctl_fops},
{"i915_pri_wm_latency", &i915_pri_wm_latency_fops},
{"i915_spr_wm_latency", &i915_spr_wm_latency_fops},
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 9035cdb..16d067e 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -195,6 +195,10 @@ int i915_scheduler_init(struct drm_device *dev)
scheduler->priority_level_preempt = 900;
scheduler->min_flying = 2;
scheduler->file_queue_max = 64;
+   scheduler->dump_flags = i915_sf_dump_force   |
+   i915_sf_dump_details |
+   i915_sf_dump_seqno   |
+   i915_sf_dump_dependencies;
 
dev_priv->scheduler = scheduler;
 
@@ -760,10 +764,7 @@ static int i915_scheduler_dump_all_locked(struct 
drm_device *dev, const char *ms
int i, r, ret = 0;
 
for_each_ring(ring, dev_priv, i) {
-   scheduler->flags[ring->id] |= i915_sf_dump_force   |
- i915_sf_dump_details |
- i915_sf_dump_seqno   |
- i915_sf_dump_dependencies;
+   scheduler->flags[ring->id] |= scheduler->dump_flags & 
i915_sf_dump_mask;
r = i915_scheduler_dump_locked(ring, msg);
if (ret == 0)
ret = r;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 6e0dfa9..5257f5c 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -118,6 +118,7 @@ struct i915_scheduler {
int32_t priority_level_preempt;
uint32_tmin_flying;
uint32_tfile_queue_max;
+   uint32_tdump_flags;
 
/* Statistics: */
struct i915_scheduler_stats stats[I915_NUM_RINGS];
@@ -134,6 +135,11 @@ enum {
i915_sf_dump_details= (1 << 9),
i915_sf_dump_dependencies   = (1 << 10),
i915_sf_dump_seqno  = (1 << 11),
+
+   i915_sf_dump_mask   = i915_sf_dump_force|
+ i915_sf_dump_details  |
+ i915_sf_dump_dependencies |
+ i915_sf_dump_seqno,
 };
 const char *i915_scheduler_flag_str(uint32_t flags);
 
-- 
1.9.1

___
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman

[Intel-gfx] [PATCH 22/39] drm/i915: Support for 'unflushed' ring idle

2015-11-23 Thread John . C . Harrison
From: John Harrison 

When the seqno wraps around zero, the entire GPU is forced to be idle
for some reason (possibly only to work around issues with hardware
semaphores but no-one seems too sure!). This causes a problem if the
force idle occurs at an inopportune moment such as in the middle of
submitting a batch buffer. Specifically, it would lead to recursive
submits - submitting work requires a new seqno, the new seqno requires
idling the ring, idling the ring requires submitting work, submitting
work requires a new seqno...

This change adds a 'flush' parameter to the idle function call which
specifies whether the scheduler queues should be flushed out. I.e. is
the call intended to just idle the ring as it is right now (no flush)
or is it intended to force all outstanding work out of the system
(with flush).

In the seqno wrap case, pending work is not an issue because the next
operation will be to submit it. However, in other cases, the intention
is to make sure everything that could be done has been done.

Change-Id: I182e9a5853666c64ecc9e84d8a8b820a7f8e8836
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem.c |  4 ++--
 drivers/gpu/drm/i915/intel_lrc.c|  2 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 17 +++--
 drivers/gpu/drm/i915/intel_ringbuffer.h |  2 +-
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 16bd82c..ebb8e0c 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2477,7 +2477,7 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 
/* Carefully retire all requests without writing to the rings */
for_each_ring(ring, dev_priv, i) {
-   ret = intel_ring_idle(ring);
+   ret = intel_ring_idle(ring, false);
if (ret)
return ret;
}
@@ -3788,7 +3788,7 @@ int i915_gpu_idle(struct drm_device *dev)
i915_add_request_no_flush(req);
}
 
-   ret = intel_ring_idle(ring);
+   ret = intel_ring_idle(ring, true);
if (ret)
return ret;
}
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 16c5302..191a118 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/intel_lrc.c
@@ -1014,7 +1014,7 @@ void intel_logical_ring_stop(struct intel_engine_cs *ring)
if (!intel_ring_initialized(ring))
return;
 
-   ret = intel_ring_idle(ring);
+   ret = intel_ring_idle(ring, true);
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);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c 
b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 4d77886..2d8dc54 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -2278,9 +2278,22 @@ static void __wrap_ring_buffer(struct intel_ringbuffer 
*ringbuf)
intel_ring_update_space(ringbuf);
 }
 
-int intel_ring_idle(struct intel_engine_cs *ring)
+int intel_ring_idle(struct intel_engine_cs *ring, bool flush)
 {
struct drm_i915_gem_request *req;
+   int ret;
+
+   /*
+* NB: Must not flush the scheduler if this idle request is from
+* within an execbuff submission (i.e. due to 'get_seqno' calling
+* 'wrap_seqno' calling 'idle'). As that would lead to recursive
+* flushes!
+*/
+   if (flush) {
+   ret = i915_scheduler_flush(ring, true);
+   if (ret)
+   return ret;
+   }
 
/* Wait upon the last request to be completed */
if (list_empty(&ring->request_list))
@@ -3085,7 +3098,7 @@ intel_stop_ring_buffer(struct intel_engine_cs *ring)
if (!intel_ring_initialized(ring))
return;
 
-   ret = intel_ring_idle(ring);
+   ret = intel_ring_idle(ring, true);
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);
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h 
b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 48f60cc..d31c94f 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -488,7 +488,7 @@ void intel_ring_update_space(struct intel_ringbuffer 
*ringbuf);
 int intel_ring_space(struct intel_ringbuffer *ringbuf);
 bool intel_ring_stopped(struct intel_engine_cs *ring);
 
-int __must_check intel_ring_idle(struct intel_engine_cs *ring);
+int __must_check intel_ring_idle(struct intel_engine_cs *ring, bool flush);
 void intel_ring_init_seqno(struct intel_engine_cs *ring, u32 seqno);
 int intel_ring_flush_all_caches(struct 

[Intel-gfx] [PATCH 39/39] drm/i915: Allow scheduler to manage inter-ring object synchronisation

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler has always tracked batch buffer dependencies based on
DRM object usage. This means that it will not submit a batch on one
ring that has outstanding dependencies still executing on other rings.
This is exactly the same synchronisation performed by
i915_gem_object_sync() using hardware semaphores where available and
CPU stalls where not (e.g. in execlist mode and/or on Gen8 hardware).

Unfortunately, when a batch buffer is submitted to the driver the
_object_sync() call happens first. Thus in case where hardware
semaphores are disabled, the driver has already stalled until the
dependency has been resolved.

This patch adds an optimisation to _object_sync() to ignore the
synchronisation in the case where it will subsequently be handled by
the scheduler. This removes the driver stall and (in the single
application case) provides near hardware semaphore performance even
when hardware semaphores are disabled. In a busy system where there is
other work that can be executed on the stalling ring, it provides
better than hardware semaphore performance as it removes the stall
from both the driver and from the hardware. There is also a theory
that this method should improve power usage as hardware semaphores are
apparently not very power efficient - the stalled ring does not go
into as low a power a state as when it is genuinely idle.

The optimisation is to check whether both ends of the synchronisation
are batch buffer requests. If they are, then the scheduler will have
the inter-dependency tracked and managed. If one or other end is not a
batch buffer request (e.g. a page flip) then the code falls back to
the CPU stall or hardware semaphore as appropriate.

To check whether the existing usage is a batch buffer, the code simply
calls the 'are you tracking this request' function of the scheduler on
the object's last_read_req member. To check whether the new usage is a
batch buffer, a flag is passed in from the caller.

Change-Id: Idc16e19b5a4dc8b3782ce9db44dd3df445f396c1
Issue: VIZ-5566
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h|  2 +-
 drivers/gpu/drm/i915/i915_gem.c| 17 ++---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  2 +-
 drivers/gpu/drm/i915/intel_display.c   |  2 +-
 drivers/gpu/drm/i915/intel_lrc.c   |  2 +-
 5 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9de831b..809816a 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2971,7 +2971,7 @@ int __must_check i915_mutex_lock_interruptible(struct 
drm_device *dev);
 #endif
 int i915_gem_object_sync(struct drm_i915_gem_object *obj,
 struct intel_engine_cs *to,
-struct drm_i915_gem_request **to_req);
+struct drm_i915_gem_request **to_req, bool to_batch);
 void i915_vma_move_to_active(struct i915_vma *vma,
 struct drm_i915_gem_request *req);
 int i915_gem_dumb_create(struct drm_file *file_priv,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 9c08035..ab6064e 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3555,7 +3555,7 @@ static int
 __i915_gem_object_sync(struct drm_i915_gem_object *obj,
   struct intel_engine_cs *to,
   struct drm_i915_gem_request *from_req,
-  struct drm_i915_gem_request **to_req)
+  struct drm_i915_gem_request **to_req, bool to_batch)
 {
struct intel_engine_cs *from;
int ret;
@@ -3567,6 +3567,15 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj,
if (i915_gem_request_completed(from_req))
return 0;
 
+   /*
+* The scheduler will manage inter-ring object dependencies
+* as long as both to and from requests are scheduler managed
+* (i.e. batch buffers).
+*/
+   if (to_batch &&
+   i915_scheduler_is_request_tracked(from_req, NULL, NULL))
+   return 0;
+
if (!i915_semaphore_is_enabled(obj->base.dev)) {
struct drm_i915_private *i915 = to_i915(obj->base.dev);
ret = __i915_wait_request(from_req,
@@ -3617,6 +3626,8 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj,
  * @to_req: request we wish to use the object for. See below.
  *  This will be allocated and returned if a request is
  *  required but not passed in.
+ * @to_batch: is the sync request on behalf of batch buffer submission?
+ * If so then the scheduler can (potentially) manage the synchronisation.
  *
  * This code is meant to abstract object synchronization with the GPU.
  * Calling with NULL implies synchronizing the object with the CPU
@@ -3647,7 +3658,7 @@ __i915_gem_object_sync(struct drm_i915_gem_object *obj,
 int
 i915_gem_object_syn

[Intel-gfx] [PATCH 19/39] drm/i915: Added scheduler support to page fault handler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

GPU page faults can now require scheduler operation in order to complete. For
example, in order to free up sufficient memory to handle the fault the handler
must wait for a batch buffer to complete that has not even been sent to the
hardware yet. Thus EAGAIN no longer means a GPU hang, it can occur under normal
operation.

Change-Id: Iff6bd2744ef12bb7405fbcd6b43c286caad4141f
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 3994b47..067f213 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1916,10 +1916,15 @@ out:
}
case -EAGAIN:
/*
-* EAGAIN means the gpu is hung and we'll wait for the error
-* handler to reset everything when re-faulting in
+* EAGAIN can mean the gpu is hung and we'll have to wait for
+* the error handler to reset everything when re-faulting in
 * i915_mutex_lock_interruptible.
+*
+* It can also indicate various other nonfatal errors for which
+* the best response is to give other threads a chance to run,
+* and then retry the failing operation in its entirety.
 */
+   /*FALLTHRU*/
case 0:
case -ERESTARTSYS:
case -EINTR:
-- 
1.9.1

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


[Intel-gfx] [PATCH 28/39] drm/i915: Added scheduler queue throttling by DRM file handle

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler decouples the submission of batch buffers to the driver from their
subsequent submission to the hardware. This means that an application which is
continuously submitting buffers as fast as it can could potentialy flood the
driver. To prevent this, the driver now tracks how many buffers are in progress
(queued in software or executing in hardware) and limits this to a given
(tunable) number. If this number is exceeded then the queue to the driver will
return EAGAIN and thus prevent the scheduler's queue becoming arbitrarily large.

Change-Id: I83258240aec7c810db08c006a3062d46aa91363f
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h|  2 ++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  8 +++
 drivers/gpu/drm/i915/i915_scheduler.c  | 34 ++
 drivers/gpu/drm/i915/i915_scheduler.h  |  2 ++
 4 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4187e75..4ecb6e4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -342,6 +342,8 @@ struct drm_i915_file_private {
} rps;
 
struct intel_engine_cs *bsd_ring;
+
+   u32 scheduler_queue_length;
 };
 
 enum intel_dpll_id {
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index e748fd3..8aca374 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1857,6 +1857,10 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
return -EINVAL;
}
 
+   /* Throttle batch requests per device file */
+   if (i915_scheduler_file_queue_is_full(file))
+   return -EAGAIN;
+
/* Copy in the exec list from userland */
exec_list = drm_malloc_ab(sizeof(*exec_list), args->buffer_count);
exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
@@ -1940,6 +1944,10 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
return -EINVAL;
}
 
+   /* Throttle batch requests per device file */
+   if (i915_scheduler_file_queue_is_full(file))
+   return -EAGAIN;
+
exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count,
 GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (exec2_list == NULL)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 098f69a..ff6460e 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -40,6 +40,8 @@ static voidi915_scheduler_priority_bump_clear(struct 
i915_scheduler *sch
 static int i915_scheduler_priority_bump(struct i915_scheduler 
*scheduler,
struct 
i915_scheduler_queue_entry *target,
uint32_t bump);
+static voidi915_scheduler_file_queue_inc(struct drm_file *file);
+static voidi915_scheduler_file_queue_dec(struct drm_file *file);
 
 bool i915_scheduler_is_enabled(struct drm_device *dev)
 {
@@ -74,6 +76,7 @@ int i915_scheduler_init(struct drm_device *dev)
scheduler->priority_level_max = 1023;
scheduler->priority_level_preempt = 900;
scheduler->min_flying = 2;
+   scheduler->file_queue_max = 64;
 
dev_priv->scheduler = scheduler;
 
@@ -244,6 +247,8 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
 
list_add_tail(&node->link, &scheduler->node_queue[ring->id]);
 
+   i915_scheduler_file_queue_inc(node->params.file);
+
if (i915.scheduler_override & i915_so_submit_on_queue)
not_flying = true;
else
@@ -523,6 +528,12 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
/* Strip the dependency info while the mutex is still locked */
i915_scheduler_remove_dependent(scheduler, node);
 
+   /* Likewise clean up the file descriptor before it might 
disappear. */
+   if (node->params.file) {
+   i915_scheduler_file_queue_dec(node->params.file);
+   node->params.file = NULL;
+   }
+
continue;
}
 
@@ -1256,3 +1267,26 @@ int i915_scheduler_closefile(struct drm_device *dev, 
struct drm_file *file)
 
return 0;
 }
+
+bool i915_scheduler_file_queue_is_full(struct drm_file *file)
+{
+   struct drm_i915_file_private *file_priv = file->driver_priv;
+   struct drm_i915_private  *dev_priv  = file_priv->dev_priv;
+   struct i915_scheduler*scheduler = dev_priv->scheduler;
+
+   return file_priv->scheduler_queue_length >= scheduler->file_queue_max;
+}
+
+static void i915_scheduler_file_queue_inc(struct drm_file *file)
+{
+   struct drm_i915_file_private *file_

[Intel-gfx] [PATCH 16/39] drm/i915: Added tracking/locking of batch buffer objects

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler needs to track interdependencies between batch buffers. These are
calculated by analysing the object lists of the buffers and looking for
commonality. The scheduler also needs to keep those buffers locked long after
the initial IOCTL call has returned to user land.

Change-Id: I31e3677ecfc2c9b5a908bda6acc4850432d55f1e
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 48 --
 drivers/gpu/drm/i915/i915_scheduler.c  | 33 ++--
 2 files changed, 76 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 12b34d7..fe90571 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1417,7 +1417,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct i915_execbuffer_params *params = &qe.params;
const u32 ctx_id = i915_execbuffer2_get_context_id(*args);
u32 dispatch_flags;
-   int ret;
+   int ret, i;
bool need_relocs;
int fd_fence_complete = -1;
int fd_fence_wait = lower_32_bits(args->rsvd2);
@@ -1552,6 +1552,14 @@ i915_gem_do_execbuffer(struct drm_device *dev, void 
*data,
goto pre_mutex_err;
}
 
+   qe.saved_objects = kzalloc(
+   sizeof(*qe.saved_objects) * args->buffer_count,
+   GFP_KERNEL);
+   if (!qe.saved_objects) {
+   ret = -ENOMEM;
+   goto err;
+   }
+
/* Look up object handles */
ret = eb_lookup_vmas(eb, exec, args, vm, file);
if (ret)
@@ -1672,7 +1680,26 @@ i915_gem_do_execbuffer(struct drm_device *dev, void 
*data,
params->args_DR1= args->DR1;
params->args_DR4= args->DR4;
params->batch_obj   = batch_obj;
-   params->ctx = ctx;
+
+   /*
+* Save away the list of objects used by this batch buffer for the
+* purpose of tracking inter-buffer dependencies.
+*/
+   for (i = 0; i < args->buffer_count; i++) {
+   /*
+* NB: 'drm_gem_object_lookup()' increments the object's
+* reference count and so must be matched by a
+* 'drm_gem_object_unreference' call.
+*/
+   qe.saved_objects[i].obj =
+   to_intel_bo(drm_gem_object_lookup(dev, file,
+ exec[i].handle));
+   }
+   qe.num_objs = i;
+
+   /* Lock and save the context object as well. */
+   i915_gem_context_reference(ctx);
+   params->ctx = ctx;
 
if (args->flags & I915_EXEC_CREATE_FENCE) {
/*
@@ -1737,6 +1764,23 @@ err:
i915_gem_context_unreference(ctx);
eb_destroy(eb);
 
+   if (qe.saved_objects) {
+   /* Need to release the objects: */
+   for (i = 0; i < qe.num_objs; i++) {
+   if (!qe.saved_objects[i].obj)
+   continue;
+
+   drm_gem_object_unreference(
+   &qe.saved_objects[i].obj->base);
+   }
+
+   kfree(qe.saved_objects);
+
+   /* Context too */
+   if (params->ctx)
+   i915_gem_context_unreference(params->ctx);
+   }
+
/*
 * If the request was created but not successfully submitted then it
 * must be freed again. If it was submitted then it is being tracked
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 79d02d7..cd69f53 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -104,7 +104,23 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
if (ret)
return ret;
 
-   /* Free everything that is owned by the QE structure: */
+   /* Need to release the objects: */
+   for (i = 0; i < qe->num_objs; i++) {
+   if (!qe->saved_objects[i].obj)
+   continue;
+
+   
drm_gem_object_unreference(&qe->saved_objects[i].obj->base);
+   }
+
+   kfree(qe->saved_objects);
+   qe->saved_objects = NULL;
+   qe->num_objs = 0;
+
+   /* Free the context object too: */
+   if (qe->params.ctx)
+   i915_gem_context_unreference(qe->params.ctx);
+
+   /* And anything else owned by the QE structure: */
kfree(qe->params.cliprects);
if (qe->params.dispatch_flags & I915_DISPATCH_SECURE)

i915_gem_execbuff_release_batch_obj(qe->params.batch_obj);
@@ -376,7 

[Intel-gfx] [PATCH 37/39] drm/i915: Enable GPU scheduler by default

2015-11-23 Thread John . C . Harrison
From: John Harrison 

Now that all the scheduler patches have been applied, it is safe to enable.

Change-Id: I128042e85a30fca765ce1eb46c837c62dee66089
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_params.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_params.c 
b/drivers/gpu/drm/i915/i915_params.c
index be2e16c..7db0f83 100644
--- a/drivers/gpu/drm/i915/i915_params.c
+++ b/drivers/gpu/drm/i915/i915_params.c
@@ -54,7 +54,7 @@ struct i915_params i915 __read_mostly = {
.edp_vswing = 0,
.enable_guc_submission = true,
.guc_log_level = -1,
-   .scheduler_override = 1,
+   .scheduler_override = 0,
 };
 
 module_param_named(modeset, i915.modeset, int, 0400);
@@ -194,4 +194,4 @@ MODULE_PARM_DESC(guc_log_level,
"GuC firmware logging level (-1:disabled (default), 0-3:enabled)");
 
 module_param_named(scheduler_override, i915.scheduler_override, int, 0600);
-MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (0 = none, 1 = 
direct submission [default])");
+MODULE_PARM_DESC(scheduler_override, "Scheduler override mask (default: 0)");
-- 
1.9.1

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


[Intel-gfx] [PATCH 18/39] drm/i915: Added scheduler support to __wait_request() calls

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler can cause batch buffers, and hence requests, to be
submitted to the ring out of order and asynchronously to their
submission to the driver. Thus at the point of waiting for the
completion of a given request, it is not even guaranteed that the
request has actually been sent to the hardware yet. Even it is has
been sent, it is possible that it could be pre-empted and thus
'unsent'.

This means that it is necessary to be able to submit requests to the
hardware during the wait call itself. Unfortunately, while some
callers of __wait_request() release the mutex lock first, others do
not (and apparently can not). Hence there is the ability to deadlock
as the wait stalls for submission but the asynchronous submission is
stalled for the mutex lock.

This change hooks the scheduler in to the __wait_request() code to
ensure correct behaviour. That is, flush the target batch buffer
through to the hardware and do not deadlock waiting for something that
cannot currently be submitted. Instead, the wait call must return
EAGAIN at least as far back as necessary to release the mutex lock and
allow the scheduler's asynchronous processing to get in and handle the
pre-emption operation and eventually (re-)submit the work.

Change-Id: I31fe6bc7e38f6ffdd843fcae16e7cc8b1e52a931
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h |   3 +-
 drivers/gpu/drm/i915/i915_gem.c |  37 +--
 drivers/gpu/drm/i915/i915_scheduler.c   | 111 
 drivers/gpu/drm/i915/i915_scheduler.h   |   4 ++
 drivers/gpu/drm/i915/intel_display.c|   5 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c |   2 +-
 6 files changed, 151 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 9a67f7c..5ed600c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3029,7 +3029,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
unsigned reset_counter,
bool interruptible,
s64 *timeout,
-   struct intel_rps_client *rps);
+   struct intel_rps_client *rps,
+   bool is_locked);
 int __must_check i915_wait_request(struct drm_i915_gem_request *req);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int __must_check
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 451ae6d..3994b47 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1207,7 +1207,8 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
unsigned reset_counter,
bool interruptible,
s64 *timeout,
-   struct intel_rps_client *rps)
+   struct intel_rps_client *rps,
+   bool is_locked)
 {
struct intel_engine_cs *ring = i915_gem_request_get_ring(req);
struct drm_device *dev = ring->dev;
@@ -1217,8 +1218,10 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
DEFINE_WAIT(wait);
unsigned long timeout_expire;
s64 before, now;
-   int ret;
+   int ret = 0;
+   boolbusy;
 
+   might_sleep();
WARN(!intel_irqs_enabled(dev_priv), "IRQs disabled");
 
if (i915_gem_request_completed(req))
@@ -1269,6 +1272,22 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
break;
}
 
+   if (is_locked) {
+   /* If this request is being processed by the scheduler
+* then it is unsafe to sleep with the mutex lock held
+* as the scheduler may require the lock in order to
+* progress the request. */
+   if (i915_scheduler_is_request_tracked(req, NULL, 
&busy)) {
+   if (busy) {
+   ret = -EAGAIN;
+   break;
+   }
+   }
+
+   /* If the request is not tracked by the scheduler then 
the
+* regular test can be done. */
+   }
+
if (i915_gem_request_completed(req)) {
ret = 0;
break;
@@ -1449,13 +1468,17 @@ i915_wait_request(struct drm_i915_gem_request *req)
 
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 
+   ret = i915_scheduler_flush_request(req, true);
+   if (ret < 0)
+   return ret;
+
ret = i915_gem_check_wedge(&dev_priv->gpu_error, interruptible);
if (ret)
return ret;
 
ret = __i915_wait_request(req,
  
atomic_read(&dev_priv->gpu_error.reset_counter),
-

[Intel-gfx] [PATCH 33/39] drm/i915: Added seqno values to scheduler status dump

2015-11-23 Thread John . C . Harrison
From: John Harrison 

It is useful to be able to see what seqnos have actually popped out of the
hardware when viewing the scheduler status.

Change-Id: Ie93e51c64328be2606b8b43440f6344d5f225426
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 10 ++
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 2 files changed, 11 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 2acc798..ebb9ab3 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -153,6 +153,7 @@ const char *i915_scheduler_flag_str(uint32_t flags)
TEST_FLAG(i915_sf_dump_force, "DumpForce|");
TEST_FLAG(i915_sf_dump_details,   "DumpDetails|");
TEST_FLAG(i915_sf_dump_dependencies,  "DumpDeps|");
+   TEST_FLAG(i915_sf_dump_seqno, "DumpSeqno|");
 
 #undef TEST_FLAG
 
@@ -760,6 +761,7 @@ static int i915_scheduler_dump_all_locked(struct drm_device 
*dev, const char *ms
for_each_ring(ring, dev_priv, i) {
scheduler->flags[ring->id] |= i915_sf_dump_force   |
  i915_sf_dump_details |
+ i915_sf_dump_seqno   |
  i915_sf_dump_dependencies;
r = i915_scheduler_dump_locked(ring, msg);
if (ret == 0)
@@ -841,6 +843,14 @@ static int i915_scheduler_dump_locked(struct 
intel_engine_cs *ring, const char *
return 0;
}
 
+   if (scheduler->flags[ring->id] & i915_sf_dump_seqno) {
+   uint32_tseqno;
+
+   seqno= ring->get_seqno(ring, true);
+
+   DRM_DEBUG_DRIVER("<%s> Seqno = %d\n", ring->name, seqno);
+   }
+
if (scheduler->flags[ring->id] & i915_sf_dump_details) {
int i, deps;
uint32_tcount, counts[i915_sqs_MAX];
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index ea70a3f..46d2503 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -132,6 +132,7 @@ enum {
i915_sf_dump_force  = (1 << 8),
i915_sf_dump_details= (1 << 9),
i915_sf_dump_dependencies   = (1 << 10),
+   i915_sf_dump_seqno  = (1 << 11),
 };
 const char *i915_scheduler_flag_str(uint32_t flags);
 
-- 
1.9.1

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


[Intel-gfx] [PATCH 38/39] drm/i915: Add scheduling priority to per-context parameters

2015-11-23 Thread John . C . Harrison
From: Dave Gordon 

Added an interface for user land applications/libraries/services to
set their GPU scheduler priority. This extends the existing context
parameter IOCTL interface to add a scheduler priority parameter. The
range is +/-1023 with +ve numbers meaning higher priority. Only
system processes may set a higher priority than the default (zero),
normal applications may only lower theirs.

v2: New patch in series.

For: VIZ-1587
Signed-off-by: Dave Gordon 
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h| 14 ++
 drivers/gpu/drm/i915/i915_gem_context.c| 24 
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |  3 +++
 include/uapi/drm/i915_drm.h|  1 +
 4 files changed, 42 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 4ecb6e4..9de831b 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -843,6 +843,19 @@ struct i915_ctx_hang_stats {
bool banned;
 };
 
+/*
+ * User-settable GFX scheduler priorities are on a scale of -1023 (I don't
+ * care about running) to +1023 (I'm the most important thing in existence)
+ * with zero being the default. Any process may decrease its scheduling
+ * priority, but only a sufficiently privileged process may increase it
+ * beyond zero.
+ */
+
+struct i915_ctx_sched_info {
+   /* Scheduling priority */
+   int32_t priority;
+};
+
 struct i915_fence_timeline {
charname[32];
unsignedfence_context;
@@ -883,6 +896,7 @@ struct intel_context {
int flags;
struct drm_i915_file_private *file_priv;
struct i915_ctx_hang_stats hang_stats;
+   struct i915_ctx_sched_info sched_info;
struct i915_hw_ppgtt *ppgtt;
 
/* Legacy ring buffer submission */
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c 
b/drivers/gpu/drm/i915/i915_gem_context.c
index 2798ddc..b226e6d 100644
--- a/drivers/gpu/drm/i915/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/i915_gem_context.c
@@ -946,6 +946,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, 
void *data,
else
args->value = to_i915(dev)->gtt.base.total;
break;
+   case I915_CONTEXT_PARAM_PRIORITY:
+   args->value = (__u64) ctx->sched_info.priority;
+   break;
default:
ret = -EINVAL;
break;
@@ -983,6 +986,7 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, 
void *data,
else
ctx->hang_stats.ban_period_seconds = args->value;
break;
+
case I915_CONTEXT_PARAM_NO_ZEROMAP:
if (args->size) {
ret = -EINVAL;
@@ -991,6 +995,26 @@ int i915_gem_context_setparam_ioctl(struct drm_device 
*dev, void *data,
ctx->flags |= args->value ? CONTEXT_NO_ZEROMAP : 0;
}
break;
+
+   case I915_CONTEXT_PARAM_PRIORITY:
+   {
+   int32_t priority = (int32_t) args->value;
+   struct drm_i915_private *dev_priv  = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+
+   if (args->size)
+   ret = -EINVAL;
+   else if ((priority > scheduler->priority_level_max) ||
+(priority < scheduler->priority_level_min))
+   ret = -EINVAL;
+   else if ((priority > 0) &&
+!capable(CAP_SYS_ADMIN))
+   ret = -EPERM;
+   else
+   ctx->sched_info.priority = priority;
+   break;
+   }
+
default:
ret = -EINVAL;
break;
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index dfd9c29..8553297 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1725,6 +1725,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
params->args_DR4= args->DR4;
params->batch_obj   = batch_obj;
 
+   /* Start with the context's priority level */
+   qe.priority = ctx->sched_info.priority;
+
/*
 * Save away the list of objects used by this batch buffer for the
 * purpose of tracking inter-buffer dependencies.
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 86f7921..5f35f89 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1138,6 +1138,7 @@ struct drm_i915_gem_context_param {
 #define I915_CONTEXT_PARAM_BAN_PERIOD  0x1
 #define I915_CONTEXT_PARAM_NO_ZEROMAP  0x2
 #define I915_CONTEXT_PARAM_GTT_SIZE0x3
+#define I915_CONTEXT_PARAM_PRIORITY0x4
__u64 value;
 };
 
-- 
1.9.1

___
In

[Intel-gfx] [PATCH 32/39] drm/i915: Added scheduler statistic reporting to debugfs

2015-11-23 Thread John . C . Harrison
From: John Harrison 

It is useful for know what the scheduler is doing for both debugging
and performance analysis purposes. This change adds a bunch of
counters and such that keep track of various scheduler operations
(batches submitted, completed, flush requests, etc.). The data can
then be read in userland via the debugfs mechanism.

v2: Updated to match changes to scheduler implementation.

Change-Id: I3266c631cd70c9eeb2c235f88f493e60462f85d7
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_debugfs.c| 77 ++
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 +++-
 drivers/gpu/drm/i915/i915_scheduler.c  | 87 +++---
 drivers/gpu/drm/i915/i915_scheduler.h  | 36 +
 4 files changed, 203 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c 
b/drivers/gpu/drm/i915/i915_debugfs.c
index 8f1c10c..9e7d67d 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -3603,6 +3603,82 @@ static int i915_drrs_status(struct seq_file *m, void 
*unused)
return 0;
 }
 
+static int i915_scheduler_info(struct seq_file *m, void *unused)
+{
+   struct drm_info_node *node = (struct drm_info_node *) m->private;
+   struct drm_device *dev = node->minor->dev;
+   struct drm_i915_private *dev_priv = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+   struct i915_scheduler_stats *stats = scheduler->stats;
+   struct i915_scheduler_stats_nodes node_stats[I915_NUM_RINGS];
+   struct intel_engine_cs *ring;
+   char   str[50 * (I915_NUM_RINGS + 1)], name[50], *ptr;
+   int ret, i, r;
+
+   ret = mutex_lock_interruptible(&dev->mode_config.mutex);
+   if (ret)
+   return ret;
+
+#define PRINT_VAR(name, fmt, var)  \
+   do {\
+   sprintf(str, "%-22s", name);\
+   ptr = str + strlen(str);\
+   for_each_ring(ring, dev_priv, r) {  \
+   sprintf(ptr, " %10" fmt, var);  \
+   ptr += strlen(ptr); \
+   }   \
+   seq_printf(m, "%s\n", str); \
+   } while (0)
+
+   PRINT_VAR("Ring name:", "s", dev_priv->ring[r].name);
+   PRINT_VAR("  Ring seqno",   "d", ring->get_seqno(ring, false));
+   seq_putc(m, '\n');
+
+   seq_puts(m, "Batch submissions:\n");
+   PRINT_VAR("  Queued",   "u", stats[r].queued);
+   PRINT_VAR("  Submitted","u", stats[r].submitted);
+   PRINT_VAR("  Completed","u", stats[r].completed);
+   PRINT_VAR("  Expired",  "u", stats[r].expired);
+   seq_putc(m, '\n');
+
+   seq_puts(m, "Flush counts:\n");
+   PRINT_VAR("  By object","u", stats[r].flush_obj);
+   PRINT_VAR("  By request",   "u", stats[r].flush_req);
+   PRINT_VAR("  By stamp", "u", stats[r].flush_stamp);
+   PRINT_VAR("  Blanket",  "u", stats[r].flush_all);
+   PRINT_VAR("  Entries bumped",   "u", stats[r].flush_bump);
+   PRINT_VAR("  Entries submitted","u", stats[r].flush_submit);
+   seq_putc(m, '\n');
+
+   seq_puts(m, "Miscellaneous:\n");
+   PRINT_VAR("  ExecEarly retry",  "u", stats[r].exec_early);
+   PRINT_VAR("  ExecFinal requeue","u", stats[r].exec_again);
+   PRINT_VAR("  ExecFinal killed", "u", stats[r].exec_dead);
+   PRINT_VAR("  Fence wait",   "u", stats[r].fence_wait);
+   PRINT_VAR("  Fence wait again", "u", stats[r].fence_again);
+   PRINT_VAR("  Fence wait ignore","u", stats[r].fence_ignore);
+   PRINT_VAR("  Fence supplied",   "u", stats[r].fence_got);
+   PRINT_VAR("  Hung flying",  "u", stats[r].kill_flying);
+   PRINT_VAR("  Hung queued",  "u", stats[r].kill_queued);
+   seq_putc(m, '\n');
+
+   seq_puts(m, "Queue contents:\n");
+   for_each_ring(ring, dev_priv, i)
+   i915_scheduler_query_stats(ring, node_stats + ring->id);
+
+   for (i = 0; i < (i915_sqs_MAX + 1); i++) {
+   sprintf(name, "  %s", i915_scheduler_queue_status_str(i));
+   PRINT_VAR(name, "d", node_stats[r].counts[i]);
+   }
+   seq_putc(m, '\n');
+
+#undef PRINT_VAR
+
+   mutex_unlock(&dev->mode_config.mutex);
+
+   return 0;
+}
+
 struct pipe_crc_info {
const char *name;
struct drm_device *dev;
@@ -5571,6 +5647,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
{"i915_semaphore_status", i915_semaphore_status, 0},
{"i915_shared_dplls_info", i915_s

[Intel-gfx] [PATCH 31/39] drm/i915: Add early exit to execbuff_final() if insufficient ring space

2015-11-23 Thread John . C . Harrison
From: John Harrison 

One of the major purposes of the GPU scheduler is to avoid stalling the CPU when
the GPU is busy and unable to accept more work. This change adds support to the
ring submission code to allow a ring space check to be performed before
attempting to submit a batch buffer to the hardware. If insufficient space is
available then the scheduler can go away and come back later, letting the CPU
get on with other work, rather than stalling and waiting for the hardware to
catch up.

Change-Id: I267159ce1150cb6714d34a49b841bcbe4bf66326
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 42 --
 drivers/gpu/drm/i915/intel_lrc.c   | 57 +++---
 drivers/gpu/drm/i915/intel_ringbuffer.c| 24 +
 drivers/gpu/drm/i915/intel_ringbuffer.h|  1 +
 4 files changed, 109 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 8aca374..ca57147 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1101,25 +1101,19 @@ i915_reset_gen7_sol_offsets(struct drm_device *dev,
 {
struct intel_engine_cs *ring = req->ring;
struct drm_i915_private *dev_priv = dev->dev_private;
-   int ret, i;
+   int i;
 
if (!IS_GEN7(dev) || ring != &dev_priv->ring[RCS]) {
DRM_DEBUG("sol reset is gen7/rcs only\n");
return -EINVAL;
}
 
-   ret = intel_ring_begin(req, 4 * 3);
-   if (ret)
-   return ret;
-
for (i = 0; i < 4; i++) {
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, GEN7_SO_WRITE_OFFSET(i));
intel_ring_emit(ring, 0);
}
 
-   intel_ring_advance(ring);
-
return 0;
 }
 
@@ -1246,6 +1240,7 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
struct intel_engine_cs  *ring = params->ring;
u64 exec_start, exec_len;
int ret;
+   uint32_t min_space;
 
/* The mutex must be acquired before calling this function */
BUG_ON(!mutex_is_locked(¶ms->dev->struct_mutex));
@@ -1267,8 +1262,36 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
if (ret)
return ret;
 
+   /*
+* It would be a bad idea to run out of space while writing commands
+* to the ring. One of the major aims of the scheduler is to not stall
+* at any point for any reason. However, doing an early exit half way
+* through submission could result in a partial sequence being written
+* which would leave the engine in an unknown state. Therefore, check in
+* advance that there will be enough space for the entire submission
+* whether emitted by the code below OR by any other functions that may
+* be executed before the end of final().
+*
+* NB: This test deliberately overestimates, because that's easier than
+* tracing every potential path that could be taken!
+*
+* Current measurements suggest that we may need to emit up to 744 bytes
+* (186 dwords), so this is rounded up to 256 dwords here. Then we 
double
+* that to get the free space requirement, because the block isn't 
allowed
+* to span the transition from the end to the beginning of the ring.
+*/
+#define I915_BATCH_EXEC_MAX_LEN 256/* max dwords emitted here  
*/
+   min_space = I915_BATCH_EXEC_MAX_LEN * 2 * sizeof(uint32_t);
+   ret = intel_ring_test_space(params->request->ringbuf, min_space);
+   if (ret)
+   goto early_error;
+
intel_runtime_pm_get(dev_priv);
 
+   ret = intel_ring_begin(params->request, I915_BATCH_EXEC_MAX_LEN);
+   if (ret)
+   goto error;
+
/*
 * Unconditionally invalidate gpu caches and ensure that we do flush
 * any residual writes from the previous batch.
@@ -1287,10 +1310,6 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
 
if (ring == &dev_priv->ring[RCS] &&
params->instp_mode != dev_priv->relative_constants_mode) {
-   ret = intel_ring_begin(params->request, 4);
-   if (ret)
-   goto error;
-
intel_ring_emit(ring, MI_NOOP);
intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
intel_ring_emit(ring, INSTPM);
@@ -1327,6 +1346,7 @@ error:
 */
intel_runtime_pm_put(dev_priv);
 
+early_error:
if (ret)
intel_ring_reserved_space_cancel(params->request->ringbuf);
 
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c
index 6c01f6c..b5abea4 100644
--- a/drivers/gpu/drm/i915/intel_lrc.c
+++ b/drivers/gpu/drm/i915/inte

[Intel-gfx] [PATCH 23/39] drm/i915: Defer seqno allocation until actual hardware submission time

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The seqno value is now only used for the final test for completion of a request.
It is no longer used to track the request through the software stack. Thus it is
no longer necessary to allocate the seqno immediately with the request. Instead,
it can be done lazily and left until the request is actually sent to the
hardware. This is particular advantageous with a GPU scheduler as the requests
can then be re-ordered between their creation and their hardware submission
without having out of order seqnos.

v2: i915_add_request() can't fail!

v3: combine with 'drm/i915: Assign seqno at start of exec_final()'
Various bits of code during the execbuf code path need a seqno value to be
assigned to the request. This change makes this assignment explicit at the start
of submission_final() rather than relying on an auto-generated seqno to have
happened already. This is in preparation for a future patch which changes seqno
values to be assigned lazily (during add_request).

Change-Id: I0d922b84c517611a79fa6c2b9e730d4fe3671d6a
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_drv.h|  1 +
 drivers/gpu/drm/i915/i915_gem.c| 21 -
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 13 +
 drivers/gpu/drm/i915/intel_lrc.c   | 13 +
 4 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 5b893a6..15dee41 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2225,6 +2225,7 @@ struct drm_i915_gem_request {
 
/** GEM sequence number associated with this request. */
uint32_t seqno;
+   uint32_t reserved_seqno;
 
/* Unique identifier which can be used for trace points & debug */
uint32_t uniq;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ebb8e0c..9c08035 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2529,6 +2529,9 @@ i915_gem_get_seqno(struct drm_device *dev, u32 *seqno)
 
/* reserve 0 for non-seqno */
if (dev_priv->next_seqno == 0) {
+   /* Why is the full re-initialisation required? Is it only for
+* hardware semaphores? If so, could skip it in the case where
+* semaphores are disabled? */
int ret = i915_gem_init_seqno(dev, 0);
if (ret)
return ret;
@@ -2586,6 +2589,12 @@ void __i915_add_request(struct drm_i915_gem_request 
*request,
WARN(ret, "*_ring_flush_all_caches failed: %d!\n", ret);
}
 
+   /* Make the request's seqno 'live': */
+   if(!request->seqno) {
+   request->seqno = request->reserved_seqno;
+   WARN_ON(request->seqno != dev_priv->last_seqno);
+   }
+
/* 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
@@ -2835,6 +2844,9 @@ void i915_gem_request_notify(struct intel_engine_cs 
*ring, bool fence_locked)
 
list_for_each_entry_safe(req, req_next, &ring->fence_signal_list, 
signal_link) {
if (!req->cancelled) {
+   /* How can this happen? */
+   WARN_ON(req->seqno == 0);
+
if (!i915_seqno_passed(seqno, req->seqno))
break;
}
@@ -3057,7 +3069,14 @@ int i915_gem_request_alloc(struct intel_engine_cs *ring,
if (req == NULL)
return -ENOMEM;
 
-   ret = i915_gem_get_seqno(ring->dev, &req->seqno);
+   /*
+* Assign an identifier to track this request through the hardware
+* but don't make it live yet. It could change in the future if this
+* request gets overtaken. However, it still needs to be allocated
+* in advance because the point of submission must not fail and seqno
+* allocation can fail.
+*/
+   ret = i915_gem_get_seqno(ring->dev, &req->reserved_seqno);
if (ret)
goto err;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index fe90571..1c249d0 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1248,6 +1248,19 @@ int i915_gem_ringbuffer_submission_final(struct 
i915_execbuffer_params *params)
/* The mutex must be acquired before calling this function */
BUG_ON(!mutex_is_locked(¶ms->dev->struct_mutex));
 
+   /* Make sure the request's seqno is the latest and greatest: */
+   if(params->request->reserved_seqno != dev_priv->last_seqno) {
+   ret = i915_gem_get_seqno(ring->dev, 
¶ms->request->reserved_seqno);
+   if (ret)
+   return ret;
+   }
+

[Intel-gfx] [PATCH 26/39] drm/i915: Connecting execbuff fences to scheduler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

The scheduler now supports sync framework fences being associated with
batch buffers. The execbuff IOCTL allows such fences to be passed in
from user land. This patch wires the two together so that the IOCTL no
longer needs to stall on the fence immediately. Instead the stall is
now swallowed by the scheduler's scheduling algorithm.

For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c | 19 ++-
 drivers/gpu/drm/i915/i915_scheduler.c  |  3 +++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index 1c249d0..a247d50 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1529,7 +1529,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
/*
 * Without a GPU scheduler, any fence waits must be done up front.
 */
-   if (args->flags & I915_EXEC_WAIT_FENCE) {
+   if ((args->flags & I915_EXEC_WAIT_FENCE) &&
+   (i915.scheduler_override & i915_so_direct_submit))
+   {
ret = i915_early_fence_wait(ring, fd_fence_wait);
if (ret < 0)
return ret;
@@ -1714,6 +1716,18 @@ i915_gem_do_execbuffer(struct drm_device *dev, void 
*data,
i915_gem_context_reference(ctx);
params->ctx = ctx;
 
+   if (args->flags & I915_EXEC_WAIT_FENCE) {
+   if (fd_fence_wait < 0) {
+   DRM_ERROR("Wait fence for ring %d has invalid id %d\n",
+ (int) ring->id, fd_fence_wait);
+   } else {
+   params->fence_wait = sync_fence_fdget(fd_fence_wait);
+   if (params->fence_wait == NULL)
+   DRM_ERROR("Invalid wait fence %d\n",
+ fd_fence_wait);
+   }
+   }
+
if (args->flags & I915_EXEC_CREATE_FENCE) {
/*
 * Caller has requested a sync fence.
@@ -1794,6 +1808,9 @@ err:
i915_gem_context_unreference(params->ctx);
}
 
+   if (params->fence_wait)
+   sync_fence_put(params->fence_wait);
+
/*
 * If the request was created but not successfully submitted then it
 * must be freed again. If it was submitted then it is being tracked
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index 939dc2b..ddd21b2 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -915,6 +915,9 @@ static int i915_scheduler_pop_from_queue_locked(struct 
intel_engine_cs *ring,
else
signalled = true;
 
+   if (!signalled)
+   signalled = i915_safe_to_ignore_fence(ring, 
node->params.fence_wait);
+
has_local  = false;
has_remote = false;
for (i = 0; i < node->num_deps; i++) {
-- 
1.9.1

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


[Intel-gfx] [PATCH 30/39] drm/i915: Added debug state dump facilities to scheduler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

When debugging batch buffer submission issues, it is useful to be able to see
what the current state of the scheduler is. This change adds functions for
decoding the internal scheduler state and reporting it.

Change-Id: I0634168e3f3465ff023f5a673165c90b07e535b6
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 276 ++
 drivers/gpu/drm/i915/i915_scheduler.h |  14 ++
 2 files changed, 290 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index ff6460e..5eec217 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -36,6 +36,9 @@ static int i915_scheduler_submit_max_priority(struct 
intel_engine_cs *ri
  bool is_locked);
 static uint32_ti915_scheduler_count_flying(struct i915_scheduler 
*scheduler,
   struct intel_engine_cs *ring);
+static int i915_scheduler_dump_locked(struct intel_engine_cs *ring,
+ const char *msg);
+static int i915_scheduler_dump_all_locked(struct drm_device *dev, 
const char *msg);
 static voidi915_scheduler_priority_bump_clear(struct i915_scheduler 
*scheduler);
 static int i915_scheduler_priority_bump(struct i915_scheduler 
*scheduler,
struct 
i915_scheduler_queue_entry *target,
@@ -53,6 +56,116 @@ bool i915_scheduler_is_enabled(struct drm_device *dev)
return dev_priv->scheduler != NULL;
 }
 
+const char *i915_qe_state_str(struct i915_scheduler_queue_entry *node)
+{
+   static char str[50];
+   char*ptr = str;
+
+   *(ptr++) = node->bumped ? 'B' : '-',
+   *(ptr++) = i915_gem_request_completed(node->params.request) ? 'C' : '-';
+
+   *ptr = 0;
+
+   return str;
+}
+
+char i915_scheduler_queue_status_chr(enum i915_scheduler_queue_status status)
+{
+   switch (status) {
+   case i915_sqs_none:
+   return 'N';
+
+   case i915_sqs_queued:
+   return 'Q';
+
+   case i915_sqs_popped:
+   return 'X';
+
+   case i915_sqs_flying:
+   return 'F';
+
+   case i915_sqs_complete:
+   return 'C';
+
+   case i915_sqs_dead:
+   return 'D';
+
+   default:
+   break;
+   }
+
+   return '?';
+}
+
+const char *i915_scheduler_queue_status_str(
+   enum i915_scheduler_queue_status status)
+{
+   static char str[50];
+
+   switch (status) {
+   case i915_sqs_none:
+   return "None";
+
+   case i915_sqs_queued:
+   return "Queued";
+
+   case i915_sqs_popped:
+   return "Popped";
+
+   case i915_sqs_flying:
+   return "Flying";
+
+   case i915_sqs_complete:
+   return "Complete";
+
+   case i915_sqs_dead:
+   return "Dead";
+
+   default:
+   break;
+   }
+
+   sprintf(str, "[Unknown_%d!]", status);
+   return str;
+}
+
+const char *i915_scheduler_flag_str(uint32_t flags)
+{
+   static char str[100];
+   char   *ptr = str;
+
+   *ptr = 0;
+
+#define TEST_FLAG(flag, msg)   \
+   do {\
+   if (flags & (flag)) {   \
+   strcpy(ptr, msg);   \
+   ptr += strlen(ptr); \
+   flags &= ~(flag);   \
+   }   \
+   } while (0)
+
+   TEST_FLAG(i915_sf_interrupts_enabled, "IntOn|");
+   TEST_FLAG(i915_sf_submitting, "Submitting|");
+   TEST_FLAG(i915_sf_dump_force, "DumpForce|");
+   TEST_FLAG(i915_sf_dump_details,   "DumpDetails|");
+   TEST_FLAG(i915_sf_dump_dependencies,  "DumpDeps|");
+
+#undef TEST_FLAG
+
+   if (flags) {
+   sprintf(ptr, "Unknown_0x%X!", flags);
+   ptr += strlen(ptr);
+   }
+
+   if (ptr == str)
+   strcpy(str, "-");
+   else
+   ptr[-1] = 0;
+
+   return str;
+};
+
 int i915_scheduler_init(struct drm_device *dev)
 {
struct drm_i915_private *dev_priv = dev->dev_private;
@@ -603,6 +716,169 @@ void i915_gem_scheduler_work_handler(struct work_struct 
*work)
}
 }
 
+int i915_scheduler_dump_all(struct drm_device *dev, const char *msg)
+{
+   struct drm_i915_private *dev_priv = dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+   unsigned long   flags;
+   int ret;
+
+   spin_lock_irqsave(&scheduler->lock, flags);
+   ret = i915_scheduler_dump_all_locked(dev, msg);
+   spin_unlock_irqrestore(&scheduler

[Intel-gfx] [PATCH 34/39] drm/i915: Add scheduler support functions for TDR

2015-11-23 Thread John . C . Harrison
From: John Harrison 

Change-Id: I720463f01c4edd3579ce52e315a85e4d7874d7e5
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_scheduler.c | 31 +++
 drivers/gpu/drm/i915/i915_scheduler.h |  1 +
 2 files changed, 32 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index ebb9ab3..1f1dfa78 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -1627,6 +1627,37 @@ int i915_scheduler_closefile(struct drm_device *dev, 
struct drm_file *file)
return 0;
 }
 
+/*
+ * Used by TDR to distinguish hung rings (not moving but with work to do)
+ * from idle rings (not moving because there is nothing to do).
+ */
+bool i915_scheduler_is_ring_flying(struct intel_engine_cs *ring)
+{
+   struct drm_i915_private *dev_priv = ring->dev->dev_private;
+   struct i915_scheduler   *scheduler = dev_priv->scheduler;
+   struct i915_scheduler_queue_entry *node;
+   unsigned long   flags;
+   boolfound = false;
+
+   /* With the scheduler in bypass mode, no information can be returned. */
+   if (i915.scheduler_override & i915_so_direct_submit) {
+   return true;
+   }
+
+   spin_lock_irqsave(&scheduler->lock, flags);
+
+   list_for_each_entry(node, &scheduler->node_queue[ring->id], link) {
+   if (I915_SQS_IS_FLYING(node)) {
+   found = true;
+   break;
+   }
+   }
+
+   spin_unlock_irqrestore(&scheduler->lock, flags);
+
+   return found;
+}
+
 bool i915_scheduler_file_queue_is_full(struct drm_file *file)
 {
struct drm_i915_file_private *file_priv = file->driver_priv;
diff --git a/drivers/gpu/drm/i915/i915_scheduler.h 
b/drivers/gpu/drm/i915/i915_scheduler.h
index 46d2503..adaefa6 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.h
+++ b/drivers/gpu/drm/i915/i915_scheduler.h
@@ -150,6 +150,7 @@ voidi915_gem_scheduler_clean_node(struct 
i915_scheduler_queue_entry *nod
 int i915_scheduler_queue_execbuffer(struct i915_scheduler_queue_entry 
*qe);
 booli915_scheduler_notify_request(struct drm_i915_gem_request *req);
 voidi915_scheduler_wakeup(struct drm_device *dev);
+booli915_scheduler_is_ring_flying(struct intel_engine_cs *ring);
 voidi915_gem_scheduler_work_handler(struct work_struct *work);
 int i915_scheduler_flush(struct intel_engine_cs *ring, bool is_locked);
 int i915_scheduler_flush_stamp(struct intel_engine_cs *ring,
-- 
1.9.1

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


[Intel-gfx] [PATCH 27/39] drm/i915: Added trace points to scheduler

2015-11-23 Thread John . C . Harrison
From: John Harrison 

Added trace points to the scheduler to track all the various events,
node state transitions and other interesting things that occur.

v2: Updated for new request completion tracking implementation.

Change-Id: I9886390cfc7897bc1faf50a104bc651d8baed8a5
For: VIZ-1587
Signed-off-by: John Harrison 
---
 drivers/gpu/drm/i915/i915_gem_execbuffer.c |   2 +
 drivers/gpu/drm/i915/i915_scheduler.c  |  24 
 drivers/gpu/drm/i915/i915_trace.h  | 190 +
 drivers/gpu/drm/i915/intel_lrc.c   |   2 +
 4 files changed, 218 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c 
b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index a247d50..e748fd3 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -1226,6 +1226,8 @@ i915_gem_ringbuffer_submission(struct 
i915_execbuffer_params *params,
 
i915_gem_execbuffer_move_to_active(vmas, params->request);
 
+   trace_i915_gem_ring_queue(ring, params);
+
qe = container_of(params, typeof(*qe), params);
ret = i915_scheduler_queue_execbuffer(qe);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c 
b/drivers/gpu/drm/i915/i915_scheduler.c
index ddd21b2..098f69a 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -97,6 +97,8 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
if (i915.scheduler_override & i915_so_direct_submit) {
int ret;
 
+   trace_i915_scheduler_queue(qe->params.ring, qe);
+
WARN_ON(qe->params.fence_wait &&
(!sync_fence_is_signaled(qe->params.fence_wait)));
 
@@ -248,6 +250,9 @@ int i915_scheduler_queue_execbuffer(struct 
i915_scheduler_queue_entry *qe)
not_flying = i915_scheduler_count_flying(scheduler, ring) <
 scheduler->min_flying;
 
+   trace_i915_scheduler_queue(ring, node);
+   trace_i915_scheduler_node_state_change(ring, node);
+
spin_unlock_irqrestore(&scheduler->lock, flags);
 
if (not_flying)
@@ -275,6 +280,9 @@ static int i915_scheduler_fly_node(struct 
i915_scheduler_queue_entry *node)
 
node->status = i915_sqs_flying;
 
+   trace_i915_scheduler_fly(ring, node);
+   trace_i915_scheduler_node_state_change(ring, node);
+
if (!(scheduler->flags[ring->id] & i915_sf_interrupts_enabled)) {
boolsuccess = true;
 
@@ -340,6 +348,8 @@ static void i915_scheduler_node_requeue(struct 
i915_scheduler_queue_entry *node)
 
node->status = i915_sqs_queued;
node->params.request->seqno = 0;
+   trace_i915_scheduler_unfly(node->params.ring, node);
+   trace_i915_scheduler_node_state_change(node->params.ring, node);
 }
 
 /* Give up on a popped node completely. For example, because it is causing the
@@ -350,6 +360,8 @@ static void i915_scheduler_node_kill(struct 
i915_scheduler_queue_entry *node)
BUG_ON(!I915_SQS_IS_FLYING(node));
 
node->status = i915_sqs_dead;
+   trace_i915_scheduler_unfly(node->params.ring, node);
+   trace_i915_scheduler_node_state_change(node->params.ring, node);
 }
 
 /*
@@ -369,6 +381,8 @@ bool i915_scheduler_notify_request(struct 
drm_i915_gem_request *req)
struct i915_scheduler_queue_entry *node = req->scheduler_qe;
unsigned long   flags;
 
+   trace_i915_scheduler_landing(req);
+
if (!node)
return false;
 
@@ -382,6 +396,8 @@ bool i915_scheduler_notify_request(struct 
drm_i915_gem_request *req)
else
node->status = i915_sqs_complete;
 
+   trace_i915_scheduler_node_state_change(req->ring, node);
+
spin_unlock_irqrestore(&scheduler->lock, flags);
 
return true;
@@ -524,6 +540,8 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
/* Launch more packets now? */
do_submit = (queued > 0) && (flying < scheduler->min_flying);
 
+   trace_i915_scheduler_remove(ring, min_seqno, do_submit);
+
spin_unlock_irqrestore(&scheduler->lock, flags);
 
if (!do_submit && list_empty(&remove))
@@ -538,6 +556,8 @@ static int i915_scheduler_remove(struct intel_engine_cs 
*ring)
node = list_first_entry(&remove, typeof(*node), link);
list_del(&node->link);
 
+   trace_i915_scheduler_destroy(ring, node);
+
if (node->params.fence_wait)
sync_fence_put(node->params.fence_wait);
 
@@ -952,6 +972,8 @@ static int i915_scheduler_pop_from_queue_locked(struct 
intel_engine_cs *ring,
INIT_LIST_HEAD(&best->link);
best->status  = i915_sqs_popped;
 
+   trace_i915_scheduler_node_state_change(ring, best);
+
ret = 0;
} else {
/* Can only get here if:
@@ -1005,6 +1027,8 @@ stat

  1   2   >