]> Git Repo - linux.git/commitdiff
drm/amd/display: Verify disallow bits were cleared for idle
authorNicholas Kazlauskas <[email protected]>
Thu, 14 Dec 2023 21:46:35 +0000 (16:46 -0500)
committerAlex Deucher <[email protected]>
Wed, 3 Jan 2024 15:47:49 +0000 (10:47 -0500)
[Why]
A hang was observed where a read-modify-write access occurred due to the
register for idle state being shared between DMCUB and driver.

dmcub read - idle allow / no commit
driver read - idle allow / no commit
driver write - idle disallow / no commit
dmcub write - idle allow / commit

Resulting in DMCUB re-entering IPS after a disable and keeping the allow
high.

[How]
Long term we need to split commit/allow into two registers or use shared
DRAM state, but short term we can reduce the repro rate by ensuring that
the disallow went through by bounding the expected worst case scenario.

Tested-by: Daniel Wheeler <[email protected]>
Reviewed-by: Hansen Dsouza <[email protected]>
Reviewed-by: Ovidiu Bunea <[email protected]>
Acked-by: Rodrigo Siqueira <[email protected]>
Signed-off-by: Nicholas Kazlauskas <[email protected]>
Signed-off-by: Alex Deucher <[email protected]>
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c

index dadeaa9c92dd528ac9455ca8bc7b981faa385e8b..a65c485b0b49aff7e70179439c7fa9f9ae8153e6 100644 (file)
@@ -1233,8 +1233,16 @@ static void dc_dmub_srv_exit_low_power_state(const struct dc *dc)
 
                if (!(allow_state & DMUB_IPS2_ALLOW_MASK)) {
                        // Wait for evaluation time
-                       udelay(dc->debug.ips2_eval_delay_us);
-                       commit_state = dc->hwss.get_idle_state(dc);
+                       for (;;) {
+                               udelay(dc->debug.ips2_eval_delay_us);
+                               commit_state = dc->hwss.get_idle_state(dc);
+                               if (commit_state & DMUB_IPS2_ALLOW_MASK)
+                                       break;
+
+                               /* allow was still set, retry eval delay */
+                               dc->hwss.set_idle_state(dc, false);
+                       }
+
                        if (!(commit_state & DMUB_IPS2_COMMIT_MASK)) {
                                // Tell PMFW to exit low power state
                                dc->clk_mgr->funcs->exit_low_power_state(dc->clk_mgr);
This page took 0.064919 seconds and 4 git commands to generate.