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 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.