]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: Fix 64-bit state pointer passed as 32-bit GPINT response buffer
authorSrinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Wed, 10 Dec 2025 06:45:56 +0000 (12:15 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 16 Dec 2025 18:19:17 +0000 (13:19 -0500)
edp_pr_get_state() incorrectly casts a uint64_t * to uint32_t * when
calling dc_wake_and_execute_gpint(). The GPINT path writes only 32 bits,
leaving the upper 32 bits of the u64 output uninitialized. Replace the
cast with a u32 temporary and copy the result into the u64 pointer.

Fixes the below:
drivers/gpu/drm/amd/amdgpu/../display/dc/link/protocols/link_edp_panel_control.c
    1448 bool edp_pr_get_state(const struct dc_link *link, uint64_t *state)
                                                           ^^^^^^^^^^^^^^^
    1449 {

    ...

    1457         do {
    1458                 // Send gpint command and wait for ack
--> 1459                 if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst,
    1460                                                (uint32_t *)state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
                                                        ^^^^^^^^^^^^^^^^^

The dc_wake_and_execute_gpint() function doesn't take a u64, it takes a
u32.  It tries to initialize the state to zero at the start but that's
not going to work because of the type mismatch.  It suggests that
callers are allowed to pass uninitialized data to edp_pr_get_state() but
at present there are no callers so this is only a bug in the code but
doesn't affect runtime.

    1461                         // Return invalid state when GPINT times out
    1462                         *state = PR_STATE_INVALID;
    1463                 }

Fixes: 74ce00932e7e ("drm/amd/display: Refactor panel replay set dmub cmd flow")
Reported by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Robin Chen <robin.chen@amd.com>
Cc: Jack Chang <jack.chang@amd.com>
Cc: Leon Huang <Leon.Huang1@amd.com>
Cc: Alex Hung <alex.hung@amd.com>
Cc: Aurabindo Pillai <aurabindo.pillai@amd.com>
Cc: Roman Li <roman.li@amd.com>
Cc: Harry Wentland <harry.wentland@amd.com>
Cc: Tom Chung <chiahsuan.chung@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/link/protocols/link_edp_panel_control.c

index 0b05ee9f6ea1a5085f7acb106e5565348917fc92..cf06b9b62e1d3fa263fa54c7f56adcec4adab215 100644 (file)
@@ -1450,6 +1450,7 @@ bool edp_pr_get_state(const struct dc_link *link, uint64_t *state)
        const struct dc  *dc = link->ctx->dc;
        unsigned int panel_inst = 0;
        uint32_t retry_count = 0;
+       uint32_t replay_state = 0;
 
        if (!dc_get_edp_link_panel_inst(dc, link, &panel_inst))
                return false;
@@ -1457,10 +1458,12 @@ bool edp_pr_get_state(const struct dc_link *link, uint64_t *state)
        do {
                // Send gpint command and wait for ack
                if (!dc_wake_and_execute_gpint(dc->ctx, DMUB_GPINT__GET_REPLAY_STATE, panel_inst,
-                                              (uint32_t *)state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
+                                              &replay_state, DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)) {
                        // Return invalid state when GPINT times out
-                       *state = PR_STATE_INVALID;
+                       replay_state = PR_STATE_INVALID;
                }
+               /* Copy 32-bit result into 64-bit output */
+               *state = replay_state;
        } while (++retry_count <= 1000 && *state == PR_STATE_INVALID);
 
        // Assert if max retry hit