[Intel-gfx] [PATCH] drm/i915: Explicit Raw and Adjusted WM latencies.

Rodrigo Vivi rodrigo.vivi at intel.com
Wed Feb 21 15:53:12 UTC 2018


On Wed, Feb 21, 2018 at 03:09:30PM +0200, Ville Syrjälä wrote:
> On Tue, Feb 20, 2018 at 05:51:47PM -0800, Rodrigo Vivi wrote:
> > Current code has some limitations:
> >
> > 1. debugfs only shows raw latency we read from PCODE,
> > not the ones we are configuring.
> >
> > 2. When determining if SAGV can be enabled we only
> > apply adjusted wa, but we don't apply the IPC one.
> > So there is the risk of enabling SAGV when we should
> > actually disable it.
> >
> > Cc: Mahesh Kumar <mahesh1.kumar at intel.com>
> > Cc: Ashar Shaikh <azhar.shaikh at intel.com>
> > Signed-off-by: Rodrigo Vivi <rodrigo.vivi at intel.com>
> > ---
> >  drivers/gpu/drm/i915/i915_debugfs.c | 48 ++++++++++++++++++-------------------
> >  drivers/gpu/drm/i915/i915_drv.h     |  7 ++++--
> >  drivers/gpu/drm/i915/intel_pm.c     | 31 ++++++++++++------------
> >  3 files changed, 43 insertions(+), 43 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
> > index f260bb39d733..94fcb0360b14 100644
> > --- a/drivers/gpu/drm/i915/i915_debugfs.c
> > +++ b/drivers/gpu/drm/i915/i915_debugfs.c
> > @@ -3664,7 +3664,8 @@ static const struct file_operations i915_displayport_test_type_fops = {
> >  	.release = single_release
> >  };
> >
> > -static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
> > +static void wm_latency_show(struct seq_file *m, const uint16_t wm[8],
> > +			    const char *header)
> >  {
> >  	struct drm_i915_private *dev_priv = m->private;
> >  	struct drm_device *dev = &dev_priv->drm;
> > @@ -3680,6 +3681,9 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
> >  	else
> >  		num_levels = ilk_wm_max_level(dev_priv) + 1;
> >
> > +	if (header)
> > +		seq_printf(m, "%s\n", header);
> > +
> >  	drm_modeset_lock_all(dev);
> >
> >  	for (level = 0; level < num_levels; level++) {
> > @@ -3707,14 +3711,12 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
> >  static int pri_wm_latency_show(struct seq_file *m, void *data)
> >  {
> >  	struct drm_i915_private *dev_priv = m->private;
> > -	const uint16_t *latencies;
> > -
> > -	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > -	else
> > -		latencies = dev_priv->wm.pri_latency;
> >
> > -	wm_latency_show(m, latencies);
> > +	if (INTEL_GEN(dev_priv) >= 9) {
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.raw, "Raw");
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.adjusted, "Adjusted");
> > +	} else
> > +		wm_latency_show(m, dev_priv->wm.pri_latency, NULL);
> >
> >  	return 0;
> >  }
> > @@ -3722,14 +3724,12 @@ static int pri_wm_latency_show(struct seq_file *m, void *data)
> >  static int spr_wm_latency_show(struct seq_file *m, void *data)
> >  {
> >  	struct drm_i915_private *dev_priv = m->private;
> > -	const uint16_t *latencies;
> > -
> > -	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > -	else
> > -		latencies = dev_priv->wm.spr_latency;
> >
> > -	wm_latency_show(m, latencies);
> > +	if (INTEL_GEN(dev_priv) >= 9) {
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.raw, "Raw");
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.adjusted, "Adjusted");
> > +	} else
> > +		wm_latency_show(m, dev_priv->wm.spr_latency, NULL);
> >
> >  	return 0;
> >  }
> > @@ -3737,14 +3737,12 @@ static int spr_wm_latency_show(struct seq_file *m, void *data)
> >  static int cur_wm_latency_show(struct seq_file *m, void *data)
> >  {
> >  	struct drm_i915_private *dev_priv = m->private;
> > -	const uint16_t *latencies;
> > -
> > -	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > -	else
> > -		latencies = dev_priv->wm.cur_latency;
> >
> > -	wm_latency_show(m, latencies);
> > +	if (INTEL_GEN(dev_priv) >= 9) {
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.raw, "Raw");
> > +		wm_latency_show(m, dev_priv->wm.skl_latency.adjusted, "Adjusted");
> > +	} else
> > +		wm_latency_show(m, dev_priv->wm.cur_latency, NULL);
> >
> >  	return 0;
> >  }
> > @@ -3833,7 +3831,7 @@ static ssize_t pri_wm_latency_write(struct file *file, const char __user *ubuf,
> >  	uint16_t *latencies;
> >
> >  	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > +		latencies = dev_priv->wm.skl_latency.raw;
> >  	else
> >  		latencies = dev_priv->wm.pri_latency;
> >
> > @@ -3848,7 +3846,7 @@ static ssize_t spr_wm_latency_write(struct file *file, const char __user *ubuf,
> >  	uint16_t *latencies;
> >
> >  	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > +		latencies = dev_priv->wm.skl_latency.raw;
> >  	else
> >  		latencies = dev_priv->wm.spr_latency;
> >
> > @@ -3863,7 +3861,7 @@ static ssize_t cur_wm_latency_write(struct file *file, const char __user *ubuf,
> >  	uint16_t *latencies;
> >
> >  	if (INTEL_GEN(dev_priv) >= 9)
> > -		latencies = dev_priv->wm.skl_latency;
> > +		latencies = dev_priv->wm.skl_latency.raw;
> >  	else
> >  		latencies = dev_priv->wm.cur_latency;
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> > index 490ff041fb1e..6969bbb203bc 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.h
> > +++ b/drivers/gpu/drm/i915/i915_drv.h
> > @@ -2136,11 +2136,14 @@ struct drm_i915_private {
> >  		/* cursor */
> >  		uint16_t cur_latency[5];
> >  		/*
> > -		 * Raw watermark memory latency values
> > +		 * Watermark memory latency values
> >  		 * for SKL for all 8 levels
> >  		 * in 1us units.
> >  		 */
> > -		uint16_t skl_latency[8];
> > +		struct {
> > +			uint16_t raw[8];
> > +			uint16_t adjusted[8];
> > +		} skl_latency;
> >
> >  		/* current hardware state */
> >  		union {
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
> > index a0a6b4b7c47b..78b52e5a1f8e 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -3030,8 +3030,9 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)
> >
> >  static void skl_setup_wm_latency(struct drm_i915_private *dev_priv)
> >  {
> > -	intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency);
> > -	intel_print_wm_latency(dev_priv, "Gen9 Plane", dev_priv->wm.skl_latency);
> > +	intel_read_wm_latency(dev_priv, dev_priv->wm.skl_latency.raw);
> > +	intel_print_wm_latency(dev_priv, "Gen9 Plane",
> > +			       dev_priv->wm.skl_latency.raw);
> >  }
> >
> >  static bool ilk_validate_pipe_wm(struct drm_device *dev,
> > @@ -3745,12 +3746,7 @@ bool intel_can_enable_sagv(struct drm_atomic_state *state)
> >  		     !wm->wm[level].plane_en; --level)
> >  		     { }
> >
> > -		latency = dev_priv->wm.skl_latency[level];
> > -
> > -		if (skl_needs_memory_bw_wa(intel_state) &&
> > -		    plane->base.state->fb->modifier ==
> > -		    I915_FORMAT_MOD_X_TILED)
> > -			latency += 15;
> > +		latency = dev_priv->wm.skl_latency.adjusted[level];
>
> The latency adjustment depends on plane configuratiuon so we can't just
> stick into a global array.

Duh! Indeed...

> I would suggest that for cases like this we
> should either stuck into the plane state and dump it out alongside the
> rest (if we had decent plane state dumps... as usual I have a branch
> somewhere that converts us over to the atomic state dump framework), or
> we just have a debug print when computing the thing.

on debug side a debug message is ok.

But I see other bugs on the current code:

SAGV adjusted latency is missing some cases that we consider for latency++
on plane calculation.

So I thought that for this we could simply have an unified function.

But also I'm not sure if this will actually be effective. I don't believe
we are executing the disable sequence as expected when some plane has latency below
that threshhold.

So, maybe add this unified function but also on atomic_commit_tail we do more of
  if (!intel_can_enable_sagv(state))
                        intel_disable_sagv(dev_priv);

not only on full modeset...

maybe something like:
  if (intel_can_enable_sagv(state)) {
     if (disabled) intel_enable_sagv()
  } else {
    if (enabled) intel_disable_sagv()
  }

?! :/

I really believe we can be smarter there... I'm just out of good ideas.

>
> >
> >  		/*
> >  		 * If any of the planes on this pipe don't enable wm levels that
> > @@ -4503,7 +4499,7 @@ skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv,
> >  	return 0;
> >  }
> >
> > -static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> > +static int skl_compute_plane_wm(struct drm_i915_private *dev_priv,
> >  				struct intel_crtc_state *cstate,
> >  				const struct intel_plane_state *intel_pstate,
> >  				uint16_t ddb_allocation,
> > @@ -4514,7 +4510,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> >  				bool *enabled /* out */)
> >  {
> >  	const struct drm_plane_state *pstate = &intel_pstate->base;
> > -	uint32_t latency = dev_priv->wm.skl_latency[level];
> > +	uint16_t latency = dev_priv->wm.skl_latency.raw[level];
> >  	uint_fixed_16_16_t method1, method2;
> >  	uint_fixed_16_16_t selected_result;
> >  	uint32_t res_blocks, res_lines;
> > @@ -4538,11 +4534,14 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> >  	if (apply_memory_bw_wa && wp->x_tiled)
> >  		latency += 15;
> >
> > -	method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate,
> > -				 wp->cpp, latency, wp->dbuf_block_size);
> > +	dev_priv->wm.skl_latency.adjusted[level] = latency;
> > +
> > +	method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, wp->cpp,
> > +				 dev_priv->wm.skl_latency.adjusted[level],
> > +				 wp->dbuf_block_size);
> >  	method2 = skl_wm_method2(wp->plane_pixel_rate,
> >  				 cstate->base.adjusted_mode.crtc_htotal,
> > -				 latency,
> > +				 dev_priv->wm.skl_latency.adjusted[level],
> >  				 wp->plane_blocks_per_line);
> >
> >  	if (wp->y_tiled) {
> > @@ -4555,7 +4554,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> >  		else if (ddb_allocation >=
> >  			 fixed16_to_u32_round_up(wp->plane_blocks_per_line))
> >  			selected_result = min_fixed16(method1, method2);
> > -		else if (latency >= wp->linetime_us)
> > +		else if (dev_priv->wm.skl_latency.adjusted[level] >= wp->linetime_us)
> >  			selected_result = min_fixed16(method1, method2);
> >  		else
> >  			selected_result = method1;
> > @@ -4634,7 +4633,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
> >  }
> >
> >  static int
> > -skl_compute_wm_levels(const struct drm_i915_private *dev_priv,
> > +skl_compute_wm_levels(struct drm_i915_private *dev_priv,
> >  		      struct skl_ddb_allocation *ddb,
> >  		      struct intel_crtc_state *cstate,
> >  		      const struct intel_plane_state *intel_pstate,
> > @@ -4756,7 +4755,7 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate,
> >  {
> >  	struct drm_device *dev = cstate->base.crtc->dev;
> >  	struct drm_crtc_state *crtc_state = &cstate->base;
> > -	const struct drm_i915_private *dev_priv = to_i915(dev);
> > +	struct drm_i915_private *dev_priv = to_i915(dev);
> >  	struct drm_plane *plane;
> >  	const struct drm_plane_state *pstate;
> >  	struct skl_plane_wm *wm;
> > --
> > 2.13.6
> >
> > _______________________________________________
> > Intel-gfx mailing list
> > Intel-gfx at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/intel-gfx
>
> --
> Ville Syrjälä
> Intel OTC


More information about the Intel-gfx mailing list