From: "Ville Syrjälä" <ville.syrjala@linux.intel.com>
To: intel-gfx@lists.freedesktop.org
Cc: intel-xe@lists.freedesktop.org
Subject: Re: [PATCH 4/8] drm/i915/de: Make mmio_debug lockless
Date: Fri, 13 Nov 2026 18:30:03 +0200 [thread overview]
Message-ID: <avc7C3GbK39VmAzo@intel.com> (raw)
In-Reply-To: <20261113134355.14579-5-ville.syrjala@linux.intel.com>
On Fri, Nov 13, 2026 at 03:43:51PM +0200, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
>
> Currently we protect the mmio_debug state using mmio.lock.
> We can't just drop the locks or we risk the read-modify-writes
> to the modparam to get out of whack. But if we get rid of the
> read-modify-writes and just switch to simple booleans all
> we need are loads and stores which are naturally atomic.
>
> This is of course racy, but quite harmlessly so. Perhaps the
> worst thing that can happen is that we mistake which register
> caused the unclaimed access, but that can already happen since
> we use the completely lockless intel_de_{read,write}_fw() in
> many places. And a pair of threads getting a bit confused
> about the state of the booleans should also be harmless. Perhaps
> we end up doing a few extra unclaimed mmio debug checks while the
> first thread is already about to disable the thing. No big deal.
>
> And for good measure, let's annotate the booleans with
> READ_ONCE()/WRITE_ONCE() to highlight the lockless nature,
> though I don't think we need those for correctness.
>
> With the booleans we do lose the capability to set mmio_debug
> to a specific value, and then automagically disable it once
> that many unclaimed register accesses have been detected.
> With the boolean it's mmio_debug all the time or none of
> the time. Not sure if anyone actually used that feature
> anyway, so doesn't seem like a big loss to me.
>
> I do want to preserve the oneshot detection thing automagically
> armed by intel_de_arm_unclaimed_mmio_detection(). So we need a
> second boolean for that.
>
> And the third boolean will be mmio.unclaimed_mmio_check. That
> was already effectively a boolean, but still being adjusted
> with rmw.
>
> The FPGA_DBG/CLAIM_ER accesses done from the read/write vfuncs
> will still be conditionally protected by the mmio.lock, based
> on mmio_flags. But the accesses from intel_de_unclaimed_mmio_detected()
> and intel_de_arm_unclaimed_mmio_detection() need another
> solution. For that I'm just adding another boolean into the
> mmio funcs that tells us whether the lock should be taken
> there or not. Calls to these functions are exceedingly rare
> so no need to come up with any clever solution here.
>
> Note that the modparam will now refuse any non-0/1 value, so
> if anyone has left this enabled accidentally the module will
> fail to load. But reminding people to turn this off in
> production is probably a good thing :P
Argh. Apparently igt uses the modparam for some reason. But it
only sets it to -1, which is the default w/ the debug .config
anyway. I guess it might make sense for people running the
w/o all the debug knobs enabled in .config...
>
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
> drivers/gpu/drm/i915/Kconfig.debug | 2 +-
> drivers/gpu/drm/i915/display/intel_de.c | 58 +++++++++----------
> drivers/gpu/drm/i915/display/intel_de.h | 1 +
> .../gpu/drm/i915/display/intel_display_core.h | 7 +--
> .../drm/i915/display/intel_display_params.c | 4 +-
> .../drm/i915/display/intel_display_params.h | 2 +-
> 6 files changed, 34 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/Kconfig.debug b/drivers/gpu/drm/i915/Kconfig.debug
> index dc43dcfbadb6..6a020adc43ee 100644
> --- a/drivers/gpu/drm/i915/Kconfig.debug
> +++ b/drivers/gpu/drm/i915/Kconfig.debug
> @@ -76,7 +76,7 @@ config DRM_I915_DEBUG_MMIO
> help
> By default, always enables the extra sanity checks (extra register
> reads) around every mmio (register) access that will slow the system
> - down. This sets the default value of i915.mmio_debug to -1 and can
> + down. This sets the default value of i915.mmio_debug to Y and can
> be overridden at module load.
>
> Recommended for driver developers only.
> diff --git a/drivers/gpu/drm/i915/display/intel_de.c b/drivers/gpu/drm/i915/display/intel_de.c
> index 06d91570bee2..5a74cf173cb8 100644
> --- a/drivers/gpu/drm/i915/display/intel_de.c
> +++ b/drivers/gpu/drm/i915/display/intel_de.c
> @@ -242,12 +242,16 @@ static bool vlv_check_for_unclaimed_mmio(struct intel_display *display)
> return true;
> }
>
> +static bool mmio_debug_is_enabled(struct intel_display *display)
> +{
> + return READ_ONCE(display->params.mmio_debug) ||
> + READ_ONCE(display->mmio.mmio_debug_oneshot);
> +}
> +
> static void check_unclaimed_mmio_pre(struct intel_display *display,
> intel_reg_t reg, bool write)
> {
> - lockdep_assert_held(&display->mmio.lock);
> -
> - if (!display->params.mmio_debug)
> + if (!mmio_debug_is_enabled(display))
> return;
>
> if (!display->mmio.funcs->check_for_unclaimed_mmio(display))
> @@ -262,9 +266,7 @@ static void check_unclaimed_mmio_pre(struct intel_display *display,
> static void check_unclaimed_mmio_post(struct intel_display *display,
> intel_reg_t reg, bool write)
> {
> - lockdep_assert_held(&display->mmio.lock);
> -
> - if (!display->params.mmio_debug)
> + if (!mmio_debug_is_enabled(display))
> return;
>
> if (!display->mmio.funcs->check_for_unclaimed_mmio(display))
> @@ -275,8 +277,7 @@ static void check_unclaimed_mmio_post(struct intel_display *display,
> write ? "write to" : "read from",
> i915_mmio_reg_offset(reg));
>
> - /* Only report the first N failures */
> - display->params.mmio_debug--;
> + WRITE_ONCE(display->mmio.mmio_debug_oneshot, false);
> }
>
> bool intel_de_unclaimed_mmio_detected(struct intel_display *display)
> @@ -286,43 +287,36 @@ bool intel_de_unclaimed_mmio_detected(struct intel_display *display)
> if (!display->mmio.funcs->check_for_unclaimed_mmio)
> return false;
>
> - spin_lock_irq(&display->mmio.lock);
> - ret = display->mmio.funcs->check_for_unclaimed_mmio(display);
> - spin_unlock_irq(&display->mmio.lock);
> + if (display->mmio.funcs->check_for_unclaimed_mmio_needs_lock) {
> + spin_lock_irq(&display->mmio.lock);
> + ret = display->mmio.funcs->check_for_unclaimed_mmio(display);
> + spin_unlock_irq(&display->mmio.lock);
> + } else {
> + ret = display->mmio.funcs->check_for_unclaimed_mmio(display);
> + }
>
> return ret;
> }
>
> bool intel_de_arm_unclaimed_mmio_detection(struct intel_display *display)
> {
> - bool ret = false;
> -
> - if (!display->mmio.funcs->check_for_unclaimed_mmio)
> + if (!READ_ONCE(display->mmio.unclaimed_mmio_check))
> return false;
>
> - spin_lock_irq(&display->mmio.lock);
> -
> - if (display->mmio.unclaimed_mmio_check <= 0)
> - goto out;
> -
> - if (!display->mmio.funcs->check_for_unclaimed_mmio(display))
> - goto out;
> + if (!intel_de_unclaimed_mmio_detected(display))
> + return false;
>
> - if (!display->params.mmio_debug) {
> + if (!READ_ONCE(display->params.mmio_debug)) {
> drm_dbg_kms(display->drm,
> "Unclaimed register detected, "
> "enabling oneshot unclaimed register reporting. "
> - "Please use i915.mmio_debug=N for more information.\n");
> - display->params.mmio_debug++;
> + "Please use i915.mmio_debug=Y for more information.\n");
> + WRITE_ONCE(display->mmio.mmio_debug_oneshot, true);
> }
>
> - display->mmio.unclaimed_mmio_check--;
> - ret = true;
> + WRITE_ONCE(display->mmio.unclaimed_mmio_check, false);
>
> -out:
> - spin_unlock_irq(&display->mmio.lock);
> -
> - return ret;
> + return true;
> }
>
> #define __MMIO_WAKELOCK BIT(0)
> @@ -474,12 +468,14 @@ static const struct intel_mmio_funcs hsw_mmio_funcs = {
> .read = hsw_mmio_read,
> .write = hsw_mmio_write,
> .check_for_unclaimed_mmio = hsw_check_for_unclaimed_mmio,
> + .check_for_unclaimed_mmio_needs_lock = true,
> };
>
> static const struct intel_mmio_funcs vlv_mmio_funcs = {
> .read = hsw_mmio_read,
> .write = hsw_mmio_write,
> .check_for_unclaimed_mmio = vlv_check_for_unclaimed_mmio,
> + .check_for_unclaimed_mmio_needs_lock = true,
> };
>
> #define LNL_MMIO_FLAGS __MMIO_WAKELOCK
> @@ -539,7 +535,7 @@ void intel_de_init(struct intel_display *display)
> }
>
> if (display->mmio.funcs->check_for_unclaimed_mmio)
> - display->mmio.unclaimed_mmio_check = 1;
> + WRITE_ONCE(display->mmio.unclaimed_mmio_check, true);
>
> /* clear out unclaimed reg detection bit someone else left behind */
> if (intel_de_unclaimed_mmio_detected(display))
> diff --git a/drivers/gpu/drm/i915/display/intel_de.h b/drivers/gpu/drm/i915/display/intel_de.h
> index 2c469a2d6a20..cbf44975dced 100644
> --- a/drivers/gpu/drm/i915/display/intel_de.h
> +++ b/drivers/gpu/drm/i915/display/intel_de.h
> @@ -13,6 +13,7 @@ struct intel_mmio_funcs {
> u32 (*read)(struct intel_display *display, intel_reg_t reg);
> void (*write)(struct intel_display *display, intel_reg_t reg, u32 val);
> bool (*check_for_unclaimed_mmio)(struct intel_display *display);
> + bool check_for_unclaimed_mmio_needs_lock;
> };
>
> void intel_de_init(struct intel_display *display);
> diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
> index d68ecc19b8a8..92a3ce4247b1 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_core.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_core.h
> @@ -539,17 +539,14 @@ struct intel_display {
> * serializes all display register accesses done
> * using intel_de_{read,write}(), but not those
> * done using intel_de_{read,write}_fw().
> - *
> - * The lock also protects mmio.unclaimed_mmio_check
> - * and read-modify-write of display->params.mmio_debug.
> */
> spinlock_t lock;
>
> struct intel_uncore *uncore;
> const struct intel_mmio_funcs *funcs;
>
> - /* protected by mmio.lock */
> - int unclaimed_mmio_check;
> + bool mmio_debug_oneshot;
> + bool unclaimed_mmio_check;
> } mmio;
>
> struct {
> diff --git a/drivers/gpu/drm/i915/display/intel_display_params.c b/drivers/gpu/drm/i915/display/intel_display_params.c
> index ace3081461de..7ef974861c8e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_params.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_params.c
> @@ -143,8 +143,8 @@ intel_display_param_named_unsafe(enable_dmc_wl, int, 0400,
> "(-1=use per-chip default, 0=disabled, 1=enabled, 2=match any register, 3=always locked) "
> "Default: -1");
>
> -intel_display_param_named(mmio_debug, int, 0400,
> - "Enable the MMIO debug code for the first N failures (default: off). "
> +intel_display_param_named(mmio_debug, bool, 0400,
> + "Enable MMIO debug code (default: false). "
> "This may negatively affect performance.");
>
> __maybe_unused
> diff --git a/drivers/gpu/drm/i915/display/intel_display_params.h b/drivers/gpu/drm/i915/display/intel_display_params.h
> index bcbca95318d6..f6b9c294840c 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_params.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_params.h
> @@ -51,7 +51,7 @@ struct drm_printer;
> param(bool, psr_safest_params, false, 0400) \
> param(bool, enable_psr2_sel_fetch, true, 0400) \
> param(int, enable_dmc_wl, -1, 0400) \
> - param(int, mmio_debug, -IS_ENABLED(CONFIG_DRM_I915_DEBUG_MMIO), 0600) \
> + param(bool, mmio_debug, IS_ENABLED(CONFIG_DRM_I915_DEBUG_MMIO), 0600) \
> /*
> * Debugfs-only knob (per-device): no matching module_param is registered
> * in intel_display_params.c on purpose. Runtime-toggle via debugfs.
> --
> 2.56.0
--
Ville Syrjälä
Intel
next prev parent reply other threads:[~2026-11-13 16:30 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 13:43 [PATCH 0/8] drm/{i915, xe}: Make unclaimed mmio detection lockless and enable it for xe Ville Syrjala
2026-11-13 13:43 ` [PATCH 1/8] drm/i915/de: Uninline intel_de_{read,write}_fw() Ville Syrjala
2026-11-13 14:11 ` Jani Nikula
2026-11-13 13:43 ` [PATCH 2/8] drm/i915/de: Pimp the intel_de_{read,write}_fw() docs Ville Syrjala
2026-11-13 14:12 ` [PATCH 2/8] drm/i915/de: Pimp the intel_de_{read, write}_fw() docs Jani Nikula
2026-11-13 14:31 ` Ville Syrjälä
2026-11-13 13:43 ` [PATCH 3/8] drm/i915/de: Flatten the unclaimed mmio code Ville Syrjala
2026-11-13 14:25 ` Jani Nikula
2026-11-13 13:43 ` [PATCH 4/8] drm/i915/de: Make mmio_debug lockless Ville Syrjala
2026-11-13 16:30 ` Ville Syrjälä [this message]
2026-11-13 13:43 ` [PATCH 5/8] drm/i915/de: Optimize the mmio_debug checks in intel_de_{read, write}() Ville Syrjala
2026-11-13 13:43 ` [PATCH 6/8] drm/i915/de: Make display registers unlocked for TGL+ on i915 Ville Syrjala
2026-11-13 13:43 ` [PATCH 7/8] drm/xe: Enable unclaimed register detection on xe Ville Syrjala
2026-11-13 13:43 ` [PATCH 8/8] drm/i915/de: Nuke driver_is_i915() Ville Syrjala
2026-11-13 14:33 ` ✗ CI.checkpatch: warning for drm/{i915, xe}: Make unclaimed mmio detection lockless and enable it for xe Patchwork
2026-11-13 14:35 ` ✓ CI.KUnit: success " Patchwork
2026-11-13 14:52 ` ✗ CI.checksparse: warning " Patchwork
2026-11-13 15:07 ` ✗ Xe.CI.BAT: failure " Patchwork
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=avc7C3GbK39VmAzo@intel.com \
--to=ville.syrjala@linux.intel.com \
--cc=intel-gfx@lists.freedesktop.org \
--cc=intel-xe@lists.freedesktop.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox