Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Gustavo Sousa <gustavo.sousa@intel.com>
To: intel-gfx@lists.freedesktop.org, intel-xe@lists.freedesktop.org
Cc: Luca Coelho <luciano.coelho@intel.com>,
	Jani Nikula <jani.nikula@intel.com>
Subject: [PATCH v2 09/17] drm/i915/dmc_wl: Track registers touched by the DMC
Date: Wed,  6 Nov 2024 18:50:35 -0300	[thread overview]
Message-ID: <20241106215231.103474-10-gustavo.sousa@intel.com> (raw)
In-Reply-To: <20241106215231.103474-1-gustavo.sousa@intel.com>

There are extra registers that require the DMC wakelock when specific
dynamic DC states are in place. Those are registers that are touched by
the DMC and require DC exit for proper access. Add the range tables for
them and use the correct one depending on the enabled DC state.

v2:
  - Do not look into power domains guts (i.e.
    display->power.domains.dc_state). (Jani)
  - Come up with better names for variables containing register ranges.
    (Luca)
  - Keep a copy of dc_state in struct intel_dmc_wl.
  - Update commit message for a clearer explanation for the need of
    these new tables.

Bspec: 71583
Cc: Jani Nikula <jani.nikula@intel.com>
Cc: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Gustavo Sousa <gustavo.sousa@intel.com>
---
 .../i915/display/intel_display_power_well.c   |   4 +-
 drivers/gpu/drm/i915/display/intel_dmc_wl.c   | 126 ++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_dmc_wl.h   |  11 +-
 3 files changed, 128 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c
index 0c77b6252969..578959ff2d75 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -833,7 +833,7 @@ void gen9_enable_dc5(struct intel_display *display)
 		intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
 			     0, SKL_SELECT_ALTERNATE_DC_EXIT);
 
-	intel_dmc_wl_enable(display);
+	intel_dmc_wl_enable(display, DC_STATE_EN_UPTO_DC5);
 
 	gen9_set_dc_state(display, DC_STATE_EN_UPTO_DC5);
 }
@@ -866,7 +866,7 @@ void skl_enable_dc6(struct intel_display *display)
 		intel_de_rmw(display, GEN8_CHICKEN_DCPR_1,
 			     0, SKL_SELECT_ALTERNATE_DC_EXIT);
 
-	intel_dmc_wl_enable(display);
+	intel_dmc_wl_enable(display, DC_STATE_EN_UPTO_DC6);
 
 	gen9_set_dc_state(display, DC_STATE_EN_UPTO_DC6);
 }
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.c b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
index 1877a89affab..db01b65cb05d 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_wl.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.c
@@ -5,6 +5,7 @@
 
 #include <linux/kernel.h>
 
+#include "i915_reg.h"
 #include "intel_de.h"
 #include "intel_dmc.h"
 #include "intel_dmc_regs.h"
@@ -56,6 +57,87 @@ static struct intel_dmc_wl_range powered_off_ranges[] = {
 	{},
 };
 
+static struct intel_dmc_wl_range xe3lpd_dc5_dc6_dmc_ranges[] = {
+	{ .start = 0x45500, .end = 0x45500 }, /* DC_STATE_SEL */
+	{ .start = 0x457a0, .end = 0x457b0 }, /* DC*_RESIDENCY_COUNTER */
+	{ .start = 0x45504, .end = 0x45504 }, /* DC_STATE_EN */
+	{ .start = 0x45400, .end = 0x4540c }, /* PWR_WELL_CTL_* */
+	{ .start = 0x454f0, .end = 0x454f0 }, /* RETENTION_CTRL */
+
+	/* DBUF_CTL_* */
+	{ .start = 0x44300, .end = 0x44300 },
+	{ .start = 0x44304, .end = 0x44304 },
+	{ .start = 0x44f00, .end = 0x44f00 },
+	{ .start = 0x44f04, .end = 0x44f04 },
+	{ .start = 0x44fe8, .end = 0x44fe8 },
+	{ .start = 0x45008, .end = 0x45008 },
+
+	{ .start = 0x46070, .end = 0x46070 }, /* CDCLK_PLL_ENABLE */
+	{ .start = 0x46000, .end = 0x46000 }, /* CDCLK_CTL */
+	{ .start = 0x46008, .end = 0x46008 }, /* CDCLK_SQUASH_CTL */
+
+	/* TRANS_CMTG_CTL_* */
+	{ .start = 0x6fa88, .end = 0x6fa88 },
+	{ .start = 0x6fb88, .end = 0x6fb88 },
+
+	{ .start = 0x46430, .end = 0x46430 }, /* CHICKEN_DCPR_1 */
+	{ .start = 0x46434, .end = 0x46434 }, /* CHICKEN_DCPR_2 */
+	{ .start = 0x454a0, .end = 0x454a0 }, /* CHICKEN_DCPR_4 */
+	{ .start = 0x42084, .end = 0x42084 }, /* CHICKEN_MISC_2 */
+	{ .start = 0x42088, .end = 0x42088 }, /* CHICKEN_MISC_3 */
+	{ .start = 0x46160, .end = 0x46160 }, /* CMTG_CLK_SEL */
+	{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
+
+	{},
+};
+
+static struct intel_dmc_wl_range xe3lpd_dc3co_dmc_ranges[] = {
+	{ .start = 0x454a0, .end = 0x454a0 }, /* CHICKEN_DCPR_4 */
+
+	{ .start = 0x45504, .end = 0x45504 }, /* DC_STATE_EN */
+
+	/* DBUF_CTL_* */
+	{ .start = 0x44300, .end = 0x44300 },
+	{ .start = 0x44304, .end = 0x44304 },
+	{ .start = 0x44f00, .end = 0x44f00 },
+	{ .start = 0x44f04, .end = 0x44f04 },
+	{ .start = 0x44fe8, .end = 0x44fe8 },
+	{ .start = 0x45008, .end = 0x45008 },
+
+	{ .start = 0x46070, .end = 0x46070 }, /* CDCLK_PLL_ENABLE */
+	{ .start = 0x46000, .end = 0x46000 }, /* CDCLK_CTL */
+	{ .start = 0x46008, .end = 0x46008 }, /* CDCLK_SQUASH_CTL */
+	{ .start = 0x8f000, .end = 0x8ffff }, /* Main DMC registers */
+
+	/* Scanline registers */
+	{ .start = 0x70000, .end = 0x70000 },
+	{ .start = 0x70004, .end = 0x70004 },
+	{ .start = 0x70014, .end = 0x70014 },
+	{ .start = 0x70018, .end = 0x70018 },
+	{ .start = 0x71000, .end = 0x71000 },
+	{ .start = 0x71004, .end = 0x71004 },
+	{ .start = 0x71014, .end = 0x71014 },
+	{ .start = 0x71018, .end = 0x71018 },
+	{ .start = 0x72000, .end = 0x72000 },
+	{ .start = 0x72004, .end = 0x72004 },
+	{ .start = 0x72014, .end = 0x72014 },
+	{ .start = 0x72018, .end = 0x72018 },
+	{ .start = 0x73000, .end = 0x73000 },
+	{ .start = 0x73004, .end = 0x73004 },
+	{ .start = 0x73014, .end = 0x73014 },
+	{ .start = 0x73018, .end = 0x73018 },
+	{ .start = 0x7b000, .end = 0x7b000 },
+	{ .start = 0x7b004, .end = 0x7b004 },
+	{ .start = 0x7b014, .end = 0x7b014 },
+	{ .start = 0x7b018, .end = 0x7b018 },
+	{ .start = 0x7c000, .end = 0x7c000 },
+	{ .start = 0x7c004, .end = 0x7c004 },
+	{ .start = 0x7c014, .end = 0x7c014 },
+	{ .start = 0x7c018, .end = 0x7c018 },
+
+	{},
+};
+
 static void __intel_dmc_wl_release(struct intel_display *display)
 {
 	struct drm_i915_private *i915 = to_i915(display->drm);
@@ -112,13 +194,37 @@ static bool intel_dmc_wl_reg_in_range(i915_reg_t reg,
 	return false;
 }
 
-static bool intel_dmc_wl_check_range(i915_reg_t reg)
+static bool intel_dmc_wl_check_range(i915_reg_t reg, u32 dc_state)
 {
+	const struct intel_dmc_wl_range *ranges;
+
 	/*
 	 * Check that the offset is in one of the ranges for which
 	 * registers are powered off during DC states.
 	 */
-	return intel_dmc_wl_reg_in_range(reg, powered_off_ranges);
+	if (intel_dmc_wl_reg_in_range(reg, powered_off_ranges))
+		return true;
+
+	/*
+	 * Check that the offset is for a register that is touched by
+	 * the DMC and requires a DC exit for proper access.
+	 */
+	switch (dc_state) {
+	case DC_STATE_EN_DC3CO:
+		ranges = xe3lpd_dc3co_dmc_ranges;
+		break;
+	case DC_STATE_EN_UPTO_DC5:
+	case DC_STATE_EN_UPTO_DC6:
+		ranges = xe3lpd_dc5_dc6_dmc_ranges;
+		break;
+	default:
+		ranges = NULL;
+	}
+
+	if (ranges && intel_dmc_wl_reg_in_range(reg, ranges))
+		return true;
+
+	return false;
 }
 
 static bool __intel_dmc_wl_supported(struct intel_display *display)
@@ -144,7 +250,7 @@ void intel_dmc_wl_init(struct intel_display *display)
 	refcount_set(&wl->refcount, 0);
 }
 
-void intel_dmc_wl_enable(struct intel_display *display)
+void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state)
 {
 	struct intel_dmc_wl *wl = &display->wl;
 	unsigned long flags;
@@ -154,6 +260,8 @@ void intel_dmc_wl_enable(struct intel_display *display)
 
 	spin_lock_irqsave(&wl->lock, flags);
 
+	wl->dc_state = dc_state;
+
 	if (wl->enabled)
 		goto out_unlock;
 
@@ -205,11 +313,11 @@ void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg)
 	if (!__intel_dmc_wl_supported(display))
 		return;
 
-	if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg))
-		return;
-
 	spin_lock_irqsave(&wl->lock, flags);
 
+	if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
+		goto out_unlock;
+
 	if (!wl->enabled)
 		goto out_unlock;
 
@@ -257,11 +365,11 @@ void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg)
 	if (!__intel_dmc_wl_supported(display))
 		return;
 
-	if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg))
-		return;
-
 	spin_lock_irqsave(&wl->lock, flags);
 
+	if (i915_mmio_reg_valid(reg) && !intel_dmc_wl_check_range(reg, wl->dc_state))
+		goto out_unlock;
+
 	if (!wl->enabled)
 		goto out_unlock;
 
diff --git a/drivers/gpu/drm/i915/display/intel_dmc_wl.h b/drivers/gpu/drm/i915/display/intel_dmc_wl.h
index 9aa72a4bf153..147eeb4d8432 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc_wl.h
+++ b/drivers/gpu/drm/i915/display/intel_dmc_wl.h
@@ -15,15 +15,22 @@
 struct intel_display;
 
 struct intel_dmc_wl {
-	spinlock_t lock; /* protects enabled, taken  and refcount */
+	spinlock_t lock; /* protects enabled, taken, dc_state and refcount */
 	bool enabled;
 	bool taken;
 	refcount_t refcount;
+	/*
+	 * We are keeping a copy of the enabled DC state because
+	 * intel_display.power.domains is protected by a mutex and we do
+	 * not want call mutex_lock() in atomic context, where some of
+	 * the tracked MMIO operations happen.
+	 */
+	u32 dc_state;
 	struct delayed_work work;
 };
 
 void intel_dmc_wl_init(struct intel_display *display);
-void intel_dmc_wl_enable(struct intel_display *display);
+void intel_dmc_wl_enable(struct intel_display *display, u32 dc_state);
 void intel_dmc_wl_disable(struct intel_display *display);
 void intel_dmc_wl_get(struct intel_display *display, i915_reg_t reg);
 void intel_dmc_wl_put(struct intel_display *display, i915_reg_t reg);
-- 
2.47.0


  parent reply	other threads:[~2024-11-06 21:52 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-11-06 21:50 [PATCH v2 00/17] drm/i915/dmc_wl: Fixes and enablement for Xe3_LPD Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 01/17] drm/i915/dmc_wl: Use i915_mmio_reg_offset() instead of reg.reg Gustavo Sousa
2024-11-07  9:23   ` Jani Nikula
2024-11-07 10:39   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 02/17] drm/xe: Mimic i915 behavior for non-sleeping MMIO wait Gustavo Sousa
2024-11-07 10:40   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 03/17] drm/i915/dmc_wl: Use non-sleeping variant of " Gustavo Sousa
2024-11-07 10:42   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 04/17] drm/i915/dmc_wl: Check for non-zero refcount in release work Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 05/17] drm/i915/dmc_wl: Get wakelock when disabling dynamic DC states Gustavo Sousa
2024-11-07 10:43   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 06/17] drm/i915/dmc_wl: Use sentinel item for range tables Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 07/17] drm/i915/dmc_wl: Extract intel_dmc_wl_reg_in_range() Gustavo Sousa
2024-11-07 10:44   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 08/17] drm/i915/dmc_wl: Rename lnl_wl_range to powered_off_ranges Gustavo Sousa
2024-11-07 10:46   ` Luca Coelho
2024-11-06 21:50 ` Gustavo Sousa [this message]
2024-11-07 10:47   ` [PATCH v2 09/17] drm/i915/dmc_wl: Track registers touched by the DMC Luca Coelho
2024-11-06 21:50 ` [PATCH v2 10/17] drm/i915/dmc_wl: Allow simpler syntax for single reg in range tables Gustavo Sousa
2024-11-07 10:48   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 11/17] drm/i915/dmc_wl: Deal with existing references when disabling Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 12/17] drm/i915/dmc_wl: Couple enable/disable with dynamic DC states Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 13/17] drm/i915/dmc_wl: Add and use HAS_DMC_WAKELOCK() Gustavo Sousa
2024-11-07 10:49   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 14/17] drm/i915/dmc_wl: Init only after we have runtime device info Gustavo Sousa
2024-11-07 10:50   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 15/17] drm/i915/dmc_wl: Use HAS_DMC() in HAS_DMC_WAKELOCK() Gustavo Sousa
2024-11-07 10:51   ` Luca Coelho
2024-11-06 21:50 ` [PATCH v2 16/17] drm/i915/dmc_wl: Sanitize enable_dmc_wl according to hardware support Gustavo Sousa
2024-11-06 21:50 ` [PATCH v2 17/17] drm/i915/xe3lpd: Use DMC wakelock by default Gustavo Sousa
2024-11-07 10:51   ` Luca Coelho
2024-11-07  1:23 ` ✓ CI.Patch_applied: success for drm/i915/dmc_wl: Fixes and enablement for Xe3_LPD (rev2) Patchwork
2024-11-07  1:24 ` ✗ CI.checkpatch: warning " Patchwork
2024-11-07  1:25 ` ✓ CI.KUnit: success " Patchwork
2024-11-07  1:37 ` ✓ CI.Build: " Patchwork
2024-11-07  1:39 ` ✓ CI.Hooks: " Patchwork
2024-11-07  1:40 ` ✗ CI.checksparse: warning " Patchwork
2024-11-07  2:00 ` ✓ CI.BAT: success " Patchwork
2024-11-08  7:06 ` ✗ CI.FULL: 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=20241106215231.103474-10-gustavo.sousa@intel.com \
    --to=gustavo.sousa@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=jani.nikula@intel.com \
    --cc=luciano.coelho@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox