All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: "Jouni Högander" <jouni.hogander@intel.com>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH v5 2/2] drm/i915/display: Prevent DC6 while vblank is enabled for Panel Replay
Date: Fri, 27 Sep 2024 15:22:10 +0300	[thread overview]
Message-ID: <ZvajclHI38JFVw4V@intel.com> (raw)
In-Reply-To: <20240920062340.1333777-3-jouni.hogander@intel.com>

On Fri, Sep 20, 2024 at 09:23:40AM +0300, Jouni Högander wrote:
> We need to block DC6 entry in case of Panel Replay as enabling VBI doesn't
> prevent DC6 in case of Panel Replay. This causes problems if user-space is
> polling for vblank events.
> 
> Fix this by setting target DC state as DC_STATE_EN_UPTO_DC5 when both
> source and sink are supporting eDP Panel Replay and VBI is enabled.
> 
> v4:
>   - s/vblank_work/vblank_dc_work/
>   - changed type of block_dc_for_vblank to bool
> v3:
>   - do flush_work for vblank_work on intel_crtc_vblank_off
>   - no need to use READ_ONCE in bdw_enable_vblank
>   - check crtc->block_dc_for_vblank in bdw_disable_vblank as well
>   - move adding block_dc_for_vblank into this patch
> v2:
>   - use READ_ONCE in intel_display_vblank_work
>   - use DC_STATE_DISABLE instead of DC_STATE_EN_UPTO_DC6
>   - use intel_crtc->block_dc6_needed
> 
> Closes: https://gitlab.freedesktop.org/drm/xe/kernel/-/issues/2296
> Signed-off-by: Jouni Högander <jouni.hogander@intel.com>
> Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_crtc.c     |  7 +++++
>  .../gpu/drm/i915/display/intel_display_core.h |  2 ++
>  .../gpu/drm/i915/display/intel_display_irq.c  | 28 +++++++++++++++++++
>  .../drm/i915/display/intel_display_types.h    |  2 ++
>  4 files changed, 39 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
> index f95d169fc324a..3a28d8450a384 100644
> --- a/drivers/gpu/drm/i915/display/intel_crtc.c
> +++ b/drivers/gpu/drm/i915/display/intel_crtc.c
> @@ -124,6 +124,8 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
>  
> +	crtc->block_dc_for_vblank = intel_psr_needs_block_dc_vblank(crtc_state);
> +
>  	assert_vblank_disabled(&crtc->base);
>  	drm_crtc_set_max_vblank_count(&crtc->base,
>  				      intel_crtc_max_vblank_count(crtc_state));
> @@ -140,6 +142,7 @@ void intel_crtc_vblank_on(const struct intel_crtc_state *crtc_state)
>  void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +	struct intel_display *display = to_intel_display(crtc);
>  
>  	/*
>  	 * Should really happen exactly when we disable the pipe
> @@ -150,6 +153,10 @@ void intel_crtc_vblank_off(const struct intel_crtc_state *crtc_state)
>  
>  	drm_crtc_vblank_off(&crtc->base);
>  	assert_vblank_disabled(&crtc->base);
> +
> +	crtc->block_dc_for_vblank = false;
> +
> +	flush_work(&display->irq.vblank_dc_work);
>  }
>  
>  struct intel_crtc_state *intel_crtc_state_alloc(struct intel_crtc *crtc)
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> index 0a711114ff2b4..ac4c005fe3489 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -457,6 +457,8 @@ struct intel_display {
>  		/* For i915gm/i945gm vblank irq workaround */
>  		u8 vblank_enabled;
>  
> +		struct work_struct vblank_dc_work;
> +
>  		u32 de_irq_mask[I915_MAX_PIPES];
>  		u32 pipestat_irq_mask[I915_MAX_PIPES];
>  	} irq;
> diff --git a/drivers/gpu/drm/i915/display/intel_display_irq.c b/drivers/gpu/drm/i915/display/intel_display_irq.c
> index 0ccbf7a1f2bf6..6878dde85031c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_irq.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_irq.c
> @@ -1360,9 +1360,27 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
>  	return true;
>  }
>  
> +static void intel_display_vblank_dc_work(struct work_struct *work)
> +{
> +	struct intel_display *display =
> +		container_of(work, typeof(*display), irq.vblank_dc_work);
> +	struct drm_i915_private *i915 = to_i915(display->drm);
> +	u8 vblank_enabled = READ_ONCE(display->irq.vblank_enabled);
> +
> +	/*
> +	 * NOTE: intel_display_power_set_target_dc_state is used only by PSR
> +	 * code for DC3CO handling. DC3CO target state is currently disabled in
> +	 * PSR code. If DC3CO is taken into use we need take that into account
> +	 * here as well.
> +	 */
> +	intel_display_power_set_target_dc_state(i915, vblank_enabled ? DC_STATE_DISABLE :
> +						DC_STATE_EN_UPTO_DC6);
> +}
> +
>  int bdw_enable_vblank(struct drm_crtc *_crtc)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> +	struct intel_display *display = to_intel_display(crtc);
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  	enum pipe pipe = crtc->pipe;
>  	unsigned long irqflags;
> @@ -1370,6 +1388,9 @@ int bdw_enable_vblank(struct drm_crtc *_crtc)
>  	if (gen11_dsi_configure_te(crtc, true))
>  		return 0;
>  
> +	if (display->irq.vblank_enabled++ == 0 && crtc->block_dc_for_vblank)
> +		schedule_work(&display->irq.vblank_dc_work);

It occurred to me that this is a little bit broken. If the
first crtc to increment the count does not need the w/a
then we'll not enable the w/a, and it will not get enabled
for other crtcs either until the count has dropped back down
to 0.

I think simply checking crtc->block_dc_for_vblank before
the increment/decrement should fix it.

Yes, that does mean vblank_enabled isn't actually counting
how many crtc have their vblank enabled, but rather how
many crtcs are applying the w/a. To avoid too much
confusion we could simply rename it to something like
vblank_wa_pipes/etc.

> +
>  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  	bdw_enable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
>  	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> @@ -1435,6 +1456,7 @@ void ilk_disable_vblank(struct drm_crtc *crtc)
>  void bdw_disable_vblank(struct drm_crtc *_crtc)
>  {
>  	struct intel_crtc *crtc = to_intel_crtc(_crtc);
> +	struct intel_display *display = to_intel_display(crtc);
>  	struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
>  	enum pipe pipe = crtc->pipe;
>  	unsigned long irqflags;
> @@ -1445,6 +1467,9 @@ void bdw_disable_vblank(struct drm_crtc *_crtc)
>  	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
>  	bdw_disable_pipe_irq(dev_priv, pipe, GEN8_PIPE_VBLANK);
>  	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
> +
> +	if (--display->irq.vblank_enabled == 0 && crtc->block_dc_for_vblank)
> +		schedule_work(&display->irq.vblank_dc_work);
>  }
>  
>  void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
> @@ -1881,4 +1906,7 @@ void intel_display_irq_init(struct drm_i915_private *i915)
>  		i915->display.irq.display_irqs_enabled = false;
>  
>  	intel_hotplug_irq_init(i915);
> +
> +	INIT_WORK(&i915->display.irq.vblank_dc_work,
> +		  intel_display_vblank_dc_work);
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 3e694c1204dbf..513e843e19b9e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1413,6 +1413,8 @@ struct intel_crtc {
>  #ifdef CONFIG_DEBUG_FS
>  	struct intel_pipe_crc pipe_crc;
>  #endif
> +
> +	bool block_dc_for_vblank;
>  };
>  
>  struct intel_plane {
> -- 
> 2.34.1

-- 
Ville Syrjälä
Intel

  reply	other threads:[~2024-09-27 12:22 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-20  6:23 [PATCH v5 0/2] Block DC6 on Vblank enable for Panel Replay Jouni Högander
2024-09-20  6:23 ` [PATCH v5 1/2] drm/i915/psr: Add intel_psr_needs_block_dc_vblank for blocking dc entry Jouni Högander
2024-09-20  6:23 ` [PATCH v5 2/2] drm/i915/display: Prevent DC6 while vblank is enabled for Panel Replay Jouni Högander
2024-09-27 12:22   ` Ville Syrjälä [this message]
2024-09-20  7:40 ` ✗ Fi.CI.SPARSE: warning for Block DC6 on Vblank enable for Panel Replay (rev5) Patchwork
2024-09-20  7:48 ` ✓ Fi.CI.BAT: success " Patchwork
2024-09-20 23:37 ` ✓ Fi.CI.IGT: " Patchwork
2024-09-23  4:25 ` [PATCH v5 0/2] Block DC6 on Vblank enable for Panel Replay Hogander, Jouni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZvajclHI38JFVw4V@intel.com \
    --to=ville.syrjala@linux.intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=jouni.hogander@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.