From: Chenyu Chen <chen-yu.chen@amd.com>
To: <amd-gfx@lists.freedesktop.org>
Cc: Harry Wentland <harry.wentland@amd.com>,
Leo Li <sunpeng.li@amd.com>,
Aurabindo Pillai <aurabindo.pillai@amd.com>,
Roman Li <roman.li@amd.com>, Wayne Lin <wayne.lin@amd.com>,
Tom Chung <chiahsuan.chung@amd.com>,
"Fangzhi Zuo" <jerry.zuo@amd.com>,
Dan Wheeler <daniel.wheeler@amd.com>, Ray Wu <Ray.Wu@amd.com>,
Ivan Lipski <ivan.lipski@amd.com>, Alex Hung <alex.hung@amd.com>,
James Lin <PingLei.Lin@amd.com>,
Chenyu Chen <Chen-Yu.Chen@amd.com>, <stable@vger.kernel.org>,
Mario Limonciello <mario.limonciello@amd.com>,
Chenyu Chen <chen-yu.chen@amd.com>
Subject: [PATCH 58/66] drm/amd/display: Atomize IRQ register read/modify/write ops
Date: Tue, 8 Sep 2026 19:31:51 +0800 [thread overview]
Message-ID: <20260908113338.2433445-59-chen-yu.chen@amd.com> (raw)
In-Reply-To: <20260908113338.2433445-1-chen-yu.chen@amd.com>
From: Leo Li <sunpeng.li@amd.com>
[Why]
The OTG_GLOBAL_SYNC_STATUS register controls various HW IRQ sources for
the output timing generator (OTG). VUPDATE_NO_LOCK is one of them.
To enable the IRQ, driver sets the VUPDATE_NO_LOCK_EN bit in the
GLOBAL_SYNC_STATUS register.
To ack the IRQ after it fires, the driver sets the VUPDATE_NO_LOCK_CLEAR
bit in the same GLOBAL_SYNC_STATUS register.
The bit sets are done through read/modify/write operations, which are
not atomic. Thus, the following race is possible:
Thread A: IRQ handler:
*HW IRQ fires*
# IRQ disable
val = read(GLOBAL_SYNC_STATUS)
unset(val, VUPDATE_NO_LOCK_EN)
write(val, GLOBAL_SYNC_STATUS)
# ACK reads VUPDATE_NO_LOCK_EN unset
val1 = read(GLOBAL_SYNC_STATUS)
set(val1, VUPDATE_NO_LOCK_CLEAR)
# IRQ enable
val = read(GLOBAL_SYNC_STATUS)
set(val, VUPDATE_NO_LOCK_EN)
write(val, GLOBAL_SYNC_STATUS)
# BAD! clears VUPDATE_NO_LOCK_EN
write(val1, GLOBAL_SYNC_STATUS)
Regarding the tagged Fixes: change, it appears the change made this race
more likely to occur. Since VUPDATE_NO_LOCK is now the sole IRQ source
for vblank handling, a single race on high refresh panels can lead to a
time out.
[How]
The GLOBAL_SYNC_STATUS register is only one example, other IRQ control
registers also share the same scheme. On top of GLOBAL_SYNC_STATUS,
let's clean up those as well.
To keep things simple, Let's atomize the IRQ rmw ops via a single
driver-wide spinlock. Due to the small scope of this lock, it is
unlikely to cause noticeable overhead on top of all the existing locking
within the IRQ set/handle paths.
Since DM is responsible for locking, wrap dc_interrupt_set/ack with the
spinlock in the new amdgpu_dm_irq_set/ack functions. Migrate/drop all
references in DM to dc_interrupt_set/ack to use amdgpu_dm_irq_set/ack
instead.
Closes: https://gitlab.freedesktop.org/drm/amd/-/work_items/5616
Cc: stable@vger.kernel.org
Fixes: 8382cd234981 ("drm/amd/display: consolidate DCN vblank/flip handling onto vupdate_no_lock")
Reviewed-by: Mario Limonciello <mario.limonciello@amd.com>
Signed-off-by: Leo Li <sunpeng.li@amd.com>
Signed-off-by: Chenyu Chen <chen-yu.chen@amd.com>
---
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 4 +-
.../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h | 12 ++++
.../amd/display/amdgpu_dm/amdgpu_dm_crtc.c | 3 +-
.../amd/display/amdgpu_dm/amdgpu_dm_helpers.c | 3 +-
.../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 64 +++++++++++--------
.../drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h | 28 ++++++++
.../amdgpu_dm/tests/amdgpu_dm_crtc_test.c | 16 +++--
.../amdgpu_dm/tests/amdgpu_dm_helpers_test.c | 8 ++-
.../amdgpu_dm/tests/amdgpu_dm_irq_test.c | 34 +++++-----
9 files changed, 117 insertions(+), 55 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 607aa5ae9b67..ca795cda8084 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -1472,7 +1472,7 @@ STATIC_IFN_KUNIT void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
if (acrtc && state->stream_status[i].plane_count != 0 &&
amdgpu_ip_version(adev, DCE_HWIP, 0) == 0) {
irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst;
- rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
+ rc = amdgpu_dm_irq_set(adev, irq_source, enable) ? 0 : -EBUSY;
if (rc)
drm_warn(adev_to_drm(adev), "Failed to %s pflip interrupts\n",
enable ? "enable" : "disable");
@@ -1496,7 +1496,7 @@ STATIC_IFN_KUNIT void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev,
/* During gpu-reset we disable and then enable vblank irq, so
* don't use amdgpu_irq_get/put() to avoid refcount change.
*/
- if (!dc_interrupt_set(adev->dm.dc, irq_source, enable))
+ if (!amdgpu_dm_irq_set(adev, irq_source, enable))
drm_warn(adev_to_drm(adev), "Failed to %sable vblank interrupt\n", enable ? "en" : "dis");
} else if (acrtc && state->stream_status[i].plane_count != 0) {
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
index 7b8941b44895..4aebf0231fee 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -555,6 +555,18 @@ struct amdgpu_display_manager {
struct common_irq_params
vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
+ /**
+ * @irq_reg_lock:
+ *
+ * Serializes the read-modify-writes of the HW interrupt control
+ * registers. Several interrupt sources share one register - e.g. the
+ * enable and clear bits of both VSTARTUP (vblank) and VUPDATE_NO_LOCK
+ * live in OTG_GLOBAL_SYNC_STATUS. Therefore, enabling one source must
+ * not race with acking another. Held only across amdgpu_dm_irq_set()
+ * and amdgpu_dm_irq_ack().
+ */
+ spinlock_t irq_reg_lock;
+
/**
* @dmub_trace_params:
*
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
index a7979b418c2b..fa6a481c8765 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
@@ -31,6 +31,7 @@
#include "amdgpu_dm_psr.h"
#include "amdgpu_dm_replay.h"
#include "amdgpu_dm_crtc.h"
+#include "amdgpu_dm_irq.h"
#include "amdgpu_dm_plane.h"
#include "amdgpu_dm_trace.h"
#include "amdgpu_dm_debugfs.h"
@@ -91,7 +92,7 @@ int amdgpu_dm_crtc_set_vupdate_irq(struct drm_crtc *crtc, bool enable)
irq_source = IRQ_TYPE_VUPDATE + acrtc->otg_inst;
- rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY;
+ rc = amdgpu_dm_irq_set(adev, irq_source, enable) ? 0 : -EBUSY;
DRM_DEBUG_VBL("crtc %d - vupdate irq %sabling: r=%d\n",
acrtc->crtc_id, enable ? "en" : "dis", rc);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index 836c06772a68..d47811665e46 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -1469,12 +1469,13 @@ EXPORT_IF_KUNIT(dm_helpers_free_gpu_mem);
bool dm_helpers_dmub_outbox_interrupt_control(struct dc_context *ctx, bool enable)
{
+ struct amdgpu_device *adev = ctx->driver_context;
enum dc_irq_source irq_source;
bool ret;
irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX;
- ret = dc_interrupt_set(ctx->dc, irq_source, enable);
+ ret = amdgpu_dm_irq_set(adev, irq_source, enable);
DRM_DEBUG_DRIVER("Dmub trace irq %sabling: r=%d\n",
enable ? "en" : "dis", ret);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
index f997a50c1293..c3ed63843202 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
@@ -396,6 +396,7 @@ int amdgpu_dm_irq_init(struct amdgpu_device *adev)
DRM_DEBUG_KMS("DM_IRQ\n");
spin_lock_init(&adev->dm.irq_handler_list_table_lock);
+ spin_lock_init(&adev->dm.irq_reg_lock);
adev->dm.irq_wq = alloc_workqueue("amdgpu_dm_irq",
WQ_UNBOUND | WQ_HIGHPRI, 0);
@@ -530,7 +531,7 @@ void amdgpu_dm_irq_suspend(struct amdgpu_device *adev)
*/
for (src = DC_IRQ_SOURCE_HPD1; src <= DC_IRQ_SOURCE_HPD6RX; src++) {
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src];
- dc_interrupt_set(adev->dm.dc, src, false);
+ amdgpu_dm_irq_set(adev, src, false);
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
@@ -568,7 +569,7 @@ void amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src];
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
- dc_interrupt_set(adev->dm.dc, src, true);
+ amdgpu_dm_irq_set(adev, src, true);
}
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
@@ -594,7 +595,7 @@ void amdgpu_dm_irq_resume_late(struct amdgpu_device *adev)
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src];
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
- dc_interrupt_set(adev->dm.dc, src, true);
+ amdgpu_dm_irq_set(adev, src, true);
}
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
@@ -693,6 +694,23 @@ STATIC_IFN_KUNIT void amdgpu_dm_irq_immediate_work(struct amdgpu_device *adev,
}
EXPORT_IF_KUNIT(amdgpu_dm_irq_immediate_work);
+bool amdgpu_dm_irq_set(struct amdgpu_device *adev, enum dc_irq_source src,
+ bool enable)
+{
+ guard(spinlock_irqsave)(&adev->dm.irq_reg_lock);
+
+ return dc_interrupt_set(adev->dm.dc, src, enable);
+}
+EXPORT_IF_KUNIT(amdgpu_dm_irq_set);
+
+void amdgpu_dm_irq_ack(struct amdgpu_device *adev, enum dc_irq_source src)
+{
+ guard(spinlock_irqsave)(&adev->dm.irq_reg_lock);
+
+ dc_interrupt_ack(adev->dm.dc, src);
+}
+EXPORT_IF_KUNIT(amdgpu_dm_irq_ack);
+
/**
* amdgpu_dm_irq_handler - Generic DM IRQ handler
* @adev: amdgpu base driver device containing the DM device
@@ -718,7 +736,7 @@ STATIC_IFN_KUNIT int amdgpu_dm_irq_handler(struct amdgpu_device *adev,
return 0;
}
- dc_interrupt_ack(adev->dm.dc, src);
+ amdgpu_dm_irq_ack(adev, src);
/* Call high irq work immediately */
amdgpu_dm_irq_immediate_work(adev, src);
@@ -758,7 +776,7 @@ STATIC_IFN_KUNIT int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev,
enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type);
bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
- dc_interrupt_set(adev->dm.dc, src, st);
+ amdgpu_dm_irq_set(adev, src, st);
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_set_hpd_irq_state);
@@ -793,7 +811,7 @@ static inline int dm_irq_state(struct amdgpu_device *adev,
if (dc && dc->caps.ips_support && dc->idle_optimizations_allowed)
dc_allow_idle_optimizations(dc, false);
- dc_interrupt_set(adev->dm.dc, irq_source, st);
+ amdgpu_dm_irq_set(adev, irq_source, st);
return 0;
}
@@ -850,7 +868,7 @@ STATIC_IFN_KUNIT int amdgpu_dm_set_dmub_outbox_irq_state(struct amdgpu_device *a
enum dc_irq_source irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX;
bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
- dc_interrupt_set(adev->dm.dc, irq_source, st);
+ amdgpu_dm_irq_set(adev, irq_source, st);
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_set_dmub_outbox_irq_state);
@@ -878,7 +896,7 @@ STATIC_IFN_KUNIT int amdgpu_dm_set_dmub_trace_irq_state(struct amdgpu_device *ad
enum dc_irq_source irq_source = DC_IRQ_SOURCE_DMCUB_OUTBOX0;
bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
- dc_interrupt_set(adev->dm.dc, irq_source, st);
+ amdgpu_dm_irq_set(adev, irq_source, st);
return 0;
}
EXPORT_IF_KUNIT(amdgpu_dm_set_dmub_trace_irq_state);
@@ -945,9 +963,7 @@ EXPORT_IF_KUNIT(amdgpu_dm_set_irq_funcs);
void amdgpu_dm_outbox_init(struct amdgpu_device *adev)
{
- dc_interrupt_set(adev->dm.dc,
- DC_IRQ_SOURCE_DMCUB_OUTBOX,
- true);
+ amdgpu_dm_irq_set(adev, DC_IRQ_SOURCE_DMCUB_OUTBOX, true);
}
EXPORT_IF_KUNIT(amdgpu_dm_outbox_init);
@@ -970,7 +986,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
/* First, clear all hpd and hpdrx interrupts */
for (i = DC_IRQ_SOURCE_HPD1; i <= DC_IRQ_SOURCE_HPD6RX; i++) {
- if (!dc_interrupt_set(adev->dm.dc, i, false))
+ if (!amdgpu_dm_irq_set(adev, i, false))
drm_err(dev, "Failed to clear hpd(rx) source=%d on init\n",
i);
}
@@ -999,7 +1015,7 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
* of dm. Note that only hpd interrupt types are registered with
* base driver; hpd_rx types aren't. IOW, amdgpu_irq_get/put on
* hpd_rx isn't available. DM currently controls hpd_rx
- * explicitly with dc_interrupt_set()
+ * explicitly with amdgpu_dm_irq_set()
*/
if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1;
@@ -1008,23 +1024,21 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
* and what bios reports as the # of connectors with hpd
* sources. Since the # of hpd source types registered
* with base driver == mode_info.num_hpd, we have to
- * fallback to dc_interrupt_set for the remaining types.
+ * fallback to amdgpu_dm_irq_set for the remaining types.
*/
if (irq_type < adev->mode_info.num_hpd) {
if (amdgpu_irq_get(adev, &adev->hpd_irq, irq_type))
drm_err(dev, "DM_IRQ: Failed get HPD for source=%d)!\n",
dc_link->irq_source_hpd);
} else {
- dc_interrupt_set(adev->dm.dc,
- dc_link->irq_source_hpd,
- true);
+ amdgpu_dm_irq_set(adev, dc_link->irq_source_hpd,
+ true);
}
}
if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
- dc_interrupt_set(adev->dm.dc,
- dc_link->irq_source_hpd_rx,
- true);
+ amdgpu_dm_irq_set(adev, dc_link->irq_source_hpd_rx,
+ true);
}
}
drm_connector_list_iter_end(&iter);
@@ -1069,16 +1083,14 @@ void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
drm_err(dev, "DM_IRQ: Failed put HPD for source=%d!\n",
dc_link->irq_source_hpd);
} else {
- dc_interrupt_set(adev->dm.dc,
- dc_link->irq_source_hpd,
- false);
+ amdgpu_dm_irq_set(adev, dc_link->irq_source_hpd,
+ false);
}
}
if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
- dc_interrupt_set(adev->dm.dc,
- dc_link->irq_source_hpd_rx,
- false);
+ amdgpu_dm_irq_set(adev, dc_link->irq_source_hpd_rx,
+ false);
}
}
drm_connector_list_iter_end(&iter);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h
index 4c200a9614a7..bc16ecc67329 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.h
@@ -89,6 +89,34 @@ void amdgpu_dm_irq_unregister_interrupt(struct amdgpu_device *adev,
enum dc_irq_source irq_source,
void *ih_index);
+/**
+ * amdgpu_dm_irq_set - enable or disable a DC interrupt source.
+ *
+ * @adev: AMD DRM device
+ * @src: DC interrupt source to toggle
+ * @enable: true to enable the source, false to disable it
+ *
+ * DM-wide replacement for dc_interrupt_set(). As locking is DM's
+ * responsibility, this is a thin wrapper serializes the underlying
+ * read-modify-write against the other interrupt sources sharing HW control
+ * registers with @src, so DM must never call dc_interrupt_set() directly.
+ *
+ * Returns: true if the source was toggled.
+ */
+bool amdgpu_dm_irq_set(struct amdgpu_device *adev, enum dc_irq_source src,
+ bool enable);
+
+/**
+ * amdgpu_dm_irq_ack - acknowledge a DC interrupt source.
+ *
+ * @adev: AMD DRM device
+ * @src: DC interrupt source to acknowledge
+ *
+ * DM-wide replacement for dc_interrupt_ack(), serialized the same way as
+ * amdgpu_dm_irq_set().
+ */
+void amdgpu_dm_irq_ack(struct amdgpu_device *adev, enum dc_irq_source src);
+
void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev);
void amdgpu_dm_outbox_init(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
index 544445fbc770..f9457fc9e31b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_crtc_test.c
@@ -439,7 +439,7 @@ static void dm_test_crtc_set_vupdate_irq_no_otg(struct kunit *test)
* dm_test_crtc_set_vupdate_irq_dc_busy - Test vupdate irq when DC rejects request
* @test: The KUnit test context
*
- * With an OTG instance assigned but no DC attached, dc_interrupt_set() returns
+ * With an OTG instance assigned but no DC attached, amdgpu_dm_irq_set() returns
* false and the function must report the request as busy (-EBUSY).
*/
static void dm_test_crtc_set_vupdate_irq_dc_busy(struct kunit *test)
@@ -456,12 +456,12 @@ static void dm_test_crtc_set_vupdate_irq_dc_busy(struct kunit *test)
acrtc->base.dev = &adev->ddev;
acrtc->otg_inst = 0;
- /* adev->dm.dc is NULL, so dc_interrupt_set() returns false. */
+ /* adev->dm.dc is NULL, so amdgpu_dm_irq_set() returns false. */
KUNIT_EXPECT_EQ(test,
amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true), -EBUSY);
}
-/* Per-source funcs let dc_interrupt_set() succeed without register access. */
+/* Per-source funcs let amdgpu_dm_irq_set() succeed without register access. */
static bool dm_test_vupdate_irq_src_set(struct irq_service *irq_service,
const struct irq_source_info *info,
bool enable)
@@ -480,7 +480,7 @@ static struct irq_source_info_funcs dm_test_vupdate_irq_src_funcs = {
.ack = dm_test_vupdate_irq_src_ack,
};
-/* A .set that fails so dc_interrupt_set() reports the source as busy. */
+/* A .set that fails so amdgpu_dm_irq_set() reports the source as busy. */
static bool dm_test_vupdate_irq_src_set_busy(struct irq_service *irq_service,
const struct irq_source_info *info,
bool enable)
@@ -522,7 +522,9 @@ static void dm_test_crtc_set_vupdate_irq_enable(struct kunit *test)
irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
- /* Populate the per-source info table so dc_interrupt_set() succeeds. */
+ /*
+ * Populate the per-source info table so amdgpu_dm_irq_set() succeeds.
+ */
info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
@@ -1021,7 +1023,9 @@ static void dm_test_crtc_enable_vblank_vupdate_busy(struct kunit *test)
irqs = kunit_kzalloc(test, sizeof(*irqs), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
- /* Per-source .set fails so dc_interrupt_set() reports the source busy. */
+ /*
+ * Per-source .set fails so amdgpu_dm_irq_set() reports the source busy.
+ */
info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, info);
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
index ceedb8745267..b18486fa5645 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_helpers_test.c
@@ -2592,17 +2592,21 @@ static void dm_test_is_dp_sink_present_null_priv(struct kunit *test)
* dm_test_dmub_outbox_interrupt_control_null_dc - Test outbox irq control with NULL dc
* @test: The KUnit test context
*
- * dc_interrupt_set() is NULL-safe and returns false when dc is NULL, so the
+ * amdgpu_dm_irq_set() is NULL-safe and returns false when dc is NULL, so the
* helper returns false without touching real interrupt hardware.
*/
static void dm_test_dmub_outbox_interrupt_control_null_dc(struct kunit *test)
{
+ struct amdgpu_device *adev;
struct dc_context *ctx;
+ adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, adev);
ctx = kunit_kzalloc(test, sizeof(*ctx), GFP_KERNEL);
KUNIT_ASSERT_NOT_NULL(test, ctx);
+ ctx->driver_context = adev;
- /* ctx->dc is NULL → dc_interrupt_set returns false */
+ /* adev->dm.dc is NULL → amdgpu_dm_irq_set returns false */
KUNIT_EXPECT_FALSE(test, dm_helpers_dmub_outbox_interrupt_control(ctx, true));
KUNIT_EXPECT_FALSE(test, dm_helpers_dmub_outbox_interrupt_control(ctx, false));
}
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
index d7d2dd49b1f0..c1b5c442ad0d 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/tests/amdgpu_dm_irq_test.c
@@ -360,7 +360,7 @@ static bool dm_test_irq_src_ack(struct irq_service *irq_service,
return true;
}
-/* Per-source funcs let dc_interrupt_set() succeed without register access. */
+/* Per-source funcs let amdgpu_dm_irq_set() succeed without register access. */
static struct irq_source_info_funcs dm_test_irq_src_funcs = {
.set = dm_test_irq_src_set,
.ack = dm_test_irq_src_ack,
@@ -382,7 +382,7 @@ static struct dc *dm_test_alloc_dc_with_irq_service(struct kunit *test,
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, irqs);
/*
- * Populate the per-source info table so dc_interrupt_set()/_ack()
+ * Populate the per-source info table so amdgpu_dm_irq_set()/_ack()
* succeed without touching hardware registers.
*/
info = kunit_kzalloc(test, sizeof(*info) * DAL_IRQ_SOURCES_NUMBER,
@@ -1351,7 +1351,7 @@ static void dm_test_irq_suspend_empty(struct kunit *test)
KUNIT_ASSERT_EQ(test, amdgpu_dm_irq_init(adev), 0);
/*
- * With no registered handlers the HW dc_interrupt_set() calls are
+ * With no registered handlers the amdgpu_dm_irq_set() calls are
* skipped, so suspend must complete without touching the (absent) DC.
*/
amdgpu_dm_irq_suspend(adev);
@@ -1399,11 +1399,11 @@ static void dm_test_irq_resume_late_empty(struct kunit *test)
}
/**
- * dm_test_irq_suspend_registered - Test suspend reaches the dc_interrupt_set path
+ * dm_test_irq_suspend_registered - Test suspend reaches the irq set path
* @test: The KUnit test context
*
* Registers a low-context HPD handler so the handler list is non-empty,
- * forcing amdgpu_dm_irq_suspend() to call dc_interrupt_set() (NULL-safe with
+ * forcing amdgpu_dm_irq_suspend() to call amdgpu_dm_irq_set() (NULL-safe with
* no DC) and flush_work() on the registered handler.
*/
static void dm_test_irq_suspend_registered(struct kunit *test)
@@ -1454,11 +1454,11 @@ static void dm_test_irq_suspend_disables_polling(struct kunit *test)
}
/**
- * dm_test_irq_resume_early_registered - Test early resume reaches dc_interrupt_set
+ * dm_test_irq_resume_early_registered - Test early resume reaches irq set
* @test: The KUnit test context
*
* Registers a low-context HPD RX handler so early resume calls
- * dc_interrupt_set() for the short-pulse interrupt source.
+ * amdgpu_dm_irq_set() for the short-pulse interrupt source.
*/
static void dm_test_irq_resume_early_registered(struct kunit *test)
{
@@ -1482,10 +1482,10 @@ static void dm_test_irq_resume_early_registered(struct kunit *test)
}
/**
- * dm_test_irq_resume_late_registered - Test late resume reaches dc_interrupt_set
+ * dm_test_irq_resume_late_registered - Test late resume reaches irq set
* @test: The KUnit test context
*
- * Registers a low-context HPD handler so late resume calls dc_interrupt_set()
+ * Registers a low-context HPD handler so late resume calls amdgpu_dm_irq_set()
* for the HPD interrupt source.
*/
static void dm_test_irq_resume_late_registered(struct kunit *test)
@@ -1716,7 +1716,7 @@ static void dm_test_set_crtc_irq_state_enable(struct kunit *test)
/*
* otg_inst >= 0 computes the irq source and reaches the NULL-safe
- * dc_interrupt_set(); the ips_support branch is skipped (dc == NULL).
+ * amdgpu_dm_irq_set(); the ips_support branch is skipped (dc == NULL).
*/
acrtc->otg_inst = 3;
adev->mode_info.crtcs[0] = acrtc;
@@ -1795,8 +1795,8 @@ static void dm_test_set_vupdate_irq_state_enable(struct kunit *test)
*
* With a non-NULL DC that advertises IPS support and currently allows idle
* optimizations, dm_irq_state() must call dc_allow_idle_optimizations() before
- * dc_interrupt_set(). disable_idle_power_optimizations makes that call a safe
- * early return, and per-source stub funcs let dc_interrupt_set() succeed.
+ * amdgpu_dm_irq_set(). disable_idle_power_optimizations makes that call a safe
+ * early return, and per-source stub funcs let amdgpu_dm_irq_set() succeed.
*/
static void dm_test_set_crtc_irq_state_allows_idle(struct kunit *test)
{
@@ -2048,7 +2048,7 @@ static void dm_test_set_hpd_irq_state_null_dc(struct kunit *test)
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
- /* dc_interrupt_set() is a no-op when dc is NULL, so both states
+ /* amdgpu_dm_irq_set() is a no-op when dc is NULL, so both states
* return 0 without dereferencing the (absent) DC.
*/
KUNIT_EXPECT_EQ(test, amdgpu_dm_set_hpd_irq_state(adev, NULL, AMDGPU_HPD_1,
@@ -2108,7 +2108,7 @@ static void dm_test_outbox_init_null_dc(struct kunit *test)
adev = kunit_kzalloc(test, sizeof(*adev), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, adev);
- /* Single dc_interrupt_set() call must be skipped when dc is NULL. */
+ /* Single amdgpu_dm_irq_set() call must be skipped when dc is NULL. */
amdgpu_dm_outbox_init(adev);
}
@@ -2126,7 +2126,7 @@ static void dm_test_hpd_init_empty_connectors(struct kunit *test)
/*
* With an empty connector list the per-connector loop is skipped and
- * the initial clear loop relies on dc_interrupt_set() being a no-op
+ * the initial clear loop relies on amdgpu_dm_irq_set() being a no-op
* for a NULL dc, so init must complete without touching the DC.
*/
amdgpu_dm_hpd_init(adev);
@@ -2161,7 +2161,7 @@ static void dm_test_hpd_init_fini_with_connectors(struct kunit *test)
/*
* num_hpd = 0 forces irq_type >= num_hpd so the loop takes the HW
- * fallback (dc_interrupt_set()) instead of amdgpu_irq_get(); with a
+ * fallback (amdgpu_dm_irq_set()) instead of amdgpu_irq_get(); with a
* NULL dc that fallback is a safe no-op.
*/
adev->mode_info.num_hpd = 0;
@@ -2247,7 +2247,7 @@ static void dm_test_hpd_init_fini_irq_ref(struct kunit *test)
/*
* num_hpd >= 1 makes irq_type (0) < num_hpd, so the loop takes the
* amdgpu_irq_get()/amdgpu_irq_put() branch instead of the
- * dc_interrupt_set() fallback. The mock device has irq.installed ==
+ * amdgpu_dm_irq_set() fallback. The mock device has irq.installed ==
* false, so both calls fail early with -ENOENT (logging an error)
* without touching the base-driver irq state.
*/
--
2.43.0
next prev parent reply other threads:[~2026-09-08 11:43 UTC|newest]
Thread overview: 67+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-08 11:30 [PATCH 00/66] DC Patches Sep 14 2026 Chenyu Chen
2026-09-08 11:30 ` [PATCH 01/66] drm/amd/display: Decouple cursor offload hwss executors from pipe context Chenyu Chen
2026-09-08 11:30 ` [PATCH 02/66] drm/amd/display: Update LLS and UPSP programming paths Chenyu Chen
2026-09-08 11:30 ` [PATCH 03/66] drm/amd/display: Refactor RMCM into a separate module Chenyu Chen
2026-09-08 11:30 ` [PATCH 04/66] drm/amd/display: Remove SDPIF_PORT_CONTROL programming for DCN31/35/42 Chenyu Chen
2026-09-08 11:30 ` [PATCH 05/66] drm/amd/display: Test sink stream creation Chenyu Chen
2026-09-08 11:30 ` [PATCH 06/66] drm/amd/display: Test connector init helper Chenyu Chen
2026-09-08 11:31 ` [PATCH 07/66] drm/amd/display: Test HDMI connector init Chenyu Chen
2026-09-08 11:31 ` [PATCH 08/66] drm/amd/display: Test FreeSync caps update Chenyu Chen
2026-09-08 11:31 ` [PATCH 09/66] drm/amd/display: Test connector init Chenyu Chen
2026-09-08 11:31 ` [PATCH 10/66] drm/amd/display: Test forced atomic commit Chenyu Chen
2026-09-08 11:31 ` [PATCH 11/66] drm/amd/display: Test DCC reject for multi-plane format Chenyu Chen
2026-09-08 11:31 ` [PATCH 12/66] drm/amd/display: Test modifier list growth failure Chenyu Chen
2026-09-08 11:31 ` [PATCH 13/66] drm/amd/display: Test pre-GFX9 plane buffer attributes Chenyu Chen
2026-09-08 11:31 ` [PATCH 14/66] drm/amd/display: Test accepted plane atomic check Chenyu Chen
2026-09-08 11:31 ` [PATCH 15/66] drm/amd/display: Test cursor update without DC stream Chenyu Chen
2026-09-08 11:31 ` [PATCH 16/66] drm/amd/display: Test panic flush DCC teardown Chenyu Chen
2026-09-08 11:31 ` [PATCH 17/66] drm/amd/display: Test optional plane property creation Chenyu Chen
2026-09-08 11:31 ` [PATCH 18/66] drm/amd/display: Add option for certain panels to disable FEC Chenyu Chen
2026-09-08 11:31 ` [PATCH 19/66] drm/amd/display: Build MST DSC helpers for KUnit Chenyu Chen
2026-09-08 11:31 ` [PATCH 20/66] drm/amd/display: Test oversized AUX transfer Chenyu Chen
2026-09-08 11:31 ` [PATCH 21/66] drm/amd/display: Test MST connector creation Chenyu Chen
2026-09-08 11:31 ` [PATCH 22/66] drm/amd/display: Test link bandwidth readback Chenyu Chen
2026-09-08 11:31 ` [PATCH 23/66] drm/amd/display: Test cascaded Panamera check Chenyu Chen
2026-09-08 11:31 ` [PATCH 24/66] drm/amd/display: Test DSC caps validation Chenyu Chen
2026-09-08 11:31 ` [PATCH 25/66] drm/amd/display: Test MST port mode support Chenyu Chen
2026-09-08 11:31 ` [PATCH 26/66] drm/amd/display: Test FRL bandwidth lookup Chenyu Chen
2026-09-08 11:31 ` [PATCH 27/66] drm/amd/display: Test DSC precompute helpers Chenyu Chen
2026-09-08 11:31 ` [PATCH 28/66] drm/amd/display: Test DSC recompute check Chenyu Chen
2026-09-08 11:31 ` [PATCH 29/66] drm/amd/display: Test DSC config computation Chenyu Chen
2026-09-08 11:31 ` [PATCH 30/66] drm/amd/display: Test per-link DSC configs Chenyu Chen
2026-09-08 11:31 ` [PATCH 31/66] drm/amd/display: Add urgent assertion counter probe Chenyu Chen
2026-09-08 11:31 ` [PATCH 32/66] drm/amd/display: Add debug option to force optional UCLK support Chenyu Chen
2026-09-08 11:31 ` [PATCH 33/66] drm/amd/display: Honor forced RGB pixel encoding Chenyu Chen
2026-09-08 11:31 ` [PATCH 34/66] drm/amd/display: Add Replay cumulative residency query Chenyu Chen
2026-09-08 11:31 ` [PATCH 35/66] drm/amd/display: Force DSC to 8bpp for MST DP tunneling over USB4 Chenyu Chen
2026-09-08 11:31 ` [PATCH 36/66] drm/amd/display: Force DSC to 8bpp for SST " Chenyu Chen
2026-09-08 11:31 ` [PATCH 37/66] drm/amd/display: Fix peak bandwidth measurement sequence Chenyu Chen
2026-09-08 11:31 ` [PATCH 38/66] drm/amd/display: Add instance field to struct mpc Chenyu Chen
2026-09-08 11:31 ` [PATCH 39/66] drm/amd/display: Enable back alt-ch Chenyu Chen
2026-09-08 11:31 ` [PATCH 40/66] drm/amd/display: Decouple HUBP_UPDATE_PLANE_ADDR from pipe_ctx Chenyu Chen
2026-09-08 11:31 ` [PATCH 41/66] drm/amd/display: Cleanup DMUB command submission interfaces Chenyu Chen
2026-09-08 11:31 ` [PATCH 42/66] drm/amd/display: Enable power gating on dcn42b Chenyu Chen
2026-09-08 11:31 ` [PATCH 43/66] drm/amd/display: Bound DSC power gating loop by num_dsc Chenyu Chen
2026-09-08 11:31 ` [PATCH 44/66] drm/amd/display: Add lock-free memory pool Chenyu Chen
2026-09-08 11:31 ` [PATCH 45/66] drm/amd/display: Rename lock_and_validation_needed to needs_dc_state_realloc Chenyu Chen
2026-09-08 11:31 ` [PATCH 46/66] drm/amd/display: Attach only plane updates that actually changed Chenyu Chen
2026-09-08 11:31 ` [PATCH 47/66] drm/amd/display: Request DMUB HW cursor offload Chenyu Chen
2026-09-08 11:31 ` [PATCH 48/66] drm/amd/display: Send stream_update to DC only when it changed Chenyu Chen
2026-09-08 11:31 ` [PATCH 49/66] drm/amd/display: Drop dead update_type param from update_planes_and_stream_adapter Chenyu Chen
2026-09-08 11:31 ` [PATCH 50/66] drm/amd/display: Flush ISM work before releasing the stream Chenyu Chen
2026-09-08 11:31 ` [PATCH 51/66] drm/amd/display: Cap DML2.1 vmin ODM combine at 2:1 for eDP Chenyu Chen
2026-09-08 11:31 ` [PATCH 52/66] drm/amd/display: Add is_odm_enabled callback to skip init_odm on active ODM pipes Chenyu Chen
2026-09-08 11:31 ` [PATCH 53/66] drm/amd/display: Program DCC as part of address update Chenyu Chen
2026-09-08 11:31 ` [PATCH 54/66] drm/amd/display: Add instance field to struct dccg Chenyu Chen
2026-09-08 11:31 ` [PATCH 55/66] drm/amd/display: Add SPDX license identifier to dcn30_dpp_cm.c Chenyu Chen
2026-09-08 11:31 ` [PATCH 56/66] drm/amd/display: Remove MALL capabilities from DCN42B Chenyu Chen
2026-09-08 11:31 ` [PATCH 57/66] drm/amd/display: Remove MALL capabilities from DCN42B bounding box Chenyu Chen
2026-09-08 11:31 ` Chenyu Chen [this message]
2026-09-08 11:31 ` [PATCH 59/66] drm/amd/display: Return success status from check_mode_supported Chenyu Chen
2026-09-08 11:31 ` [PATCH 60/66] drm/amd/display: Add condition to skip MALL calculations if there is no MALL Chenyu Chen
2026-09-08 11:31 ` [PATCH 61/66] drm/amd/display: Fix HDMI FRL audio enable Chenyu Chen
2026-09-08 11:31 ` [PATCH 62/66] drm/amd/display: Cast DP DTO pixel clock math to avoid overflow and narrowing Chenyu Chen
2026-09-08 11:31 ` [PATCH 63/66] drm/amd/display: Add inbox0 HW lock helpers for DCN35 Chenyu Chen
2026-09-08 11:31 ` [PATCH 64/66] drm/amd/display: Unify fast update classification paths Chenyu Chen
2026-09-08 11:31 ` [PATCH 65/66] drm/amd/display: Use unsigned types for FRL cap check params and HPO read_state Chenyu Chen
2026-09-08 11:31 ` [PATCH 66/66] drm/amd/display: Promote DC to 3.2.398 Chenyu Chen
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=20260908113338.2433445-59-chen-yu.chen@amd.com \
--to=chen-yu.chen@amd.com \
--cc=PingLei.Lin@amd.com \
--cc=Ray.Wu@amd.com \
--cc=alex.hung@amd.com \
--cc=amd-gfx@lists.freedesktop.org \
--cc=aurabindo.pillai@amd.com \
--cc=chiahsuan.chung@amd.com \
--cc=daniel.wheeler@amd.com \
--cc=harry.wentland@amd.com \
--cc=ivan.lipski@amd.com \
--cc=jerry.zuo@amd.com \
--cc=mario.limonciello@amd.com \
--cc=roman.li@amd.com \
--cc=stable@vger.kernel.org \
--cc=sunpeng.li@amd.com \
--cc=wayne.lin@amd.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