summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorNicholas Kazlauskas <nicholas.kazlauskas@amd.com>2024-02-16 14:42:05 -0500
committerAlex Deucher <alexander.deucher@amd.com>2024-03-20 13:37:37 -0400
commitf57269f85b284f3a8154e208d7b1eb2abe652eb2 (patch)
treeab800ffd4d1072ab7fd3a096a4d850fa38e64355 /drivers/gpu
parent97d5aa60306d286326026a40e1e3b992b5b31538 (diff)
downloadlinux-stable-f57269f85b284f3a8154e208d7b1eb2abe652eb2.tar.gz
linux-stable-f57269f85b284f3a8154e208d7b1eb2abe652eb2.tar.bz2
linux-stable-f57269f85b284f3a8154e208d7b1eb2abe652eb2.zip
drm/amd/display: Add guards for idle on reg read/write
[WHY] If DCN is in idle then we should not be accessing DCN registers or it can lead to hangs. [HOW] Log the error and return 0 or drop the write if it's in idle. This is skipped in the exit sequence itself since the boolean flips before it starts. It also does not cover accesses from external clients outside of DM/DC like firmware or the kernel mode driver. Reviewed-by: Duncan Ma <duncan.ma@amd.com> Acked-by: Alex Hung <alex.hung@amd.com> Signed-off-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com> Tested-by: Daniel Wheeler <daniel.wheeler@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h1
2 files changed, 10 insertions, 0 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
index b168dfc79381..938e8cb2fec1 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -1270,6 +1270,10 @@ static void dc_dmub_srv_notify_idle(const struct dc *dc, bool allow_idle)
/* NOTE: This does not use the "wake" interface since this is part of the wake path. */
/* We also do not perform a wait since DMCUB could enter idle after the notification. */
dm_execute_dmub_cmd(dc->ctx, &cmd, allow_idle ? DM_DMUB_WAIT_TYPE_NO_WAIT : DM_DMUB_WAIT_TYPE_WAIT);
+
+ /* Register access should stop at this point. */
+ if (allow_idle)
+ dc_dmub_srv->needs_idle_wake = true;
}
static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
@@ -1301,6 +1305,11 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
ips_fw->signals.bits.ips1_commit,
ips_fw->signals.bits.ips2_commit);
+ /* Note: register access has technically not resumed for DCN here, but we
+ * need to be message PMFW through our standard register interface.
+ */
+ dc_dmub_srv->needs_idle_wake = false;
+
if (prev_driver_signals.bits.allow_ips2) {
DC_LOG_IPS(
"wait IPS2 eval (ips1_commit=%d ips2_commit=%d)",
diff --git a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
index 952bfb368886..60c93e9e3533 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -52,6 +52,7 @@ struct dc_dmub_srv {
void *dm;
bool idle_allowed;
+ bool needs_idle_wake;
};
void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);