]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
drm/amd/display: dynamically clock gate before and after prefetch
authorLeo Chen <leo.chen@amd.com>
Fri, 31 Oct 2025 19:25:47 +0000 (15:25 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 12 Nov 2025 02:54:16 +0000 (21:54 -0500)
[Why]
An invalidation request arriving during prefetch can potentially hang
the system if dynamic clock gating is enabled and memory power requests
are disabled.

[How]
• Disable clock gating and enable memory power requests for the duration
of the prefetch.
• Turn on clock gating and disable memory power requests again after
prefetch is complete.

Limit the scope for DCN35 and DCN42 only.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Leo Chen <leo.chen@amd.com>
Signed-off-by: Fangzhi Zuo <jerry.zuo@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/hubbub/dcn31/dcn31_hubbub.c
drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.c
drivers/gpu/drm/amd/display/dc/hubbub/dcn35/dcn35_hubbub.h
drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h

index d1aaa58b7db35810e63c9f997b3811a077e22e7c..5a03758e3de6f0ea7bd78affac0ddf88f37a8c39 100644 (file)
@@ -933,8 +933,8 @@ int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,
 
                dcn20_vmid_setup(&hubbub2->vmid[15], &phys_config);
        }
-
-       dcn21_dchvm_init(hubbub);
+       if (hubbub->funcs->dchvm_init)
+               hubbub->funcs->dchvm_init(hubbub);
 
        return NUM_VMID;
 }
@@ -1071,7 +1071,8 @@ static const struct hubbub_funcs hubbub31_funcs = {
        .program_compbuf_size = dcn31_program_compbuf_size,
        .init_crb = dcn31_init_crb,
        .hubbub_read_state = hubbub2_read_state,
-       .hubbub_read_reg_state = hubbub3_read_reg_state
+       .hubbub_read_reg_state = hubbub3_read_reg_state,
+       .dchvm_init  = dcn21_dchvm_init
 };
 
 void hubbub31_construct(struct dcn20_hubbub *hubbub31,
index 1b7746a6549ab8c0eaf48857e34c6ded21de8272..43ba399f48226491dbb51978f52b67df246f93f8 100644 (file)
@@ -549,6 +549,55 @@ void hubbub35_init(struct hubbub *hubbub)
        memset(&hubbub2->watermarks.a.cstate_pstate, 0, sizeof(hubbub2->watermarks.a.cstate_pstate));
 }
 
+void dcn35_dchvm_init(struct hubbub *hubbub)
+{
+       struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+       uint32_t riommu_active;
+       int i;
+
+       //Init DCHVM block
+       REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
+
+       //Poll until RIOMMU_ACTIVE = 1
+       for (i = 0; i < 100; i++) {
+               REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
+
+               if (riommu_active)
+                       break;
+               else
+                       udelay(5);
+       }
+
+       if (riommu_active) {
+               // Disable gating and memory power requests
+               REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 1);
+               REG_UPDATE_4(DCHVM_CLK_CTRL,
+                                               HVM_DISPCLK_R_GATE_DIS, 1,
+                                               HVM_DISPCLK_G_GATE_DIS, 1,
+                                               HVM_DCFCLK_R_GATE_DIS, 1,
+                                               HVM_DCFCLK_G_GATE_DIS, 1);
+
+               //Reflect the power status of DCHUBBUB
+               REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
+
+               //Start rIOMMU prefetching
+               REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
+
+               //Poll until HOSTVM_PREFETCH_DONE = 1
+               REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
+
+               //Enable memory power requests
+               REG_UPDATE(DCHVM_MEM_CTRL, HVM_GPUVMRET_PWR_REQ_DIS, 0);
+               // Enable dynamic clock gating
+               REG_UPDATE_4(DCHVM_CLK_CTRL,
+                                               HVM_DISPCLK_R_GATE_DIS, 0,
+                                               HVM_DISPCLK_G_GATE_DIS, 0,
+                                               HVM_DCFCLK_R_GATE_DIS, 0,
+                                               HVM_DCFCLK_G_GATE_DIS, 0);
+               hubbub->riommu_active = true;
+       }
+}
+
 /*static void hubbub35_set_request_limit(struct hubbub *hubbub,
                                       int memory_channel_count,
                                       int words_per_channel)
@@ -589,7 +638,8 @@ static const struct hubbub_funcs hubbub35_funcs = {
        .hubbub_read_state = hubbub2_read_state,
        .force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
        .dchubbub_init = hubbub35_init,
-       .hubbub_read_reg_state = hubbub3_read_reg_state
+       .hubbub_read_reg_state = hubbub3_read_reg_state,
+       .dchvm_init = dcn35_dchvm_init
 };
 
 void hubbub35_construct(struct dcn20_hubbub *hubbub2,
index 23fecf88556c8757fae804d07c7f862bab27d174..9f65fff1bd4d571cbed0645bcbcc472a52800099 100644 (file)
@@ -168,4 +168,5 @@ void dcn35_program_compbuf_size(struct hubbub *hubbub,
        unsigned int compbuf_size_kb, bool safe_to_increase);
 void dcn35_init_crb(struct hubbub *hubbub);
 void hubbub35_init(struct hubbub *hubbub);
+void dcn35_dchvm_init(struct hubbub *hubbub);
 #endif
index dafc8490efb5ddddbac52569a36b48f15ff33c25..1ddfa30411c836246cfee44ebcf1cddc78568e83 100644 (file)
@@ -252,6 +252,8 @@ struct hubbub_funcs {
        void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
        void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
        bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
+       void (*dchvm_init)(struct hubbub *hubbub);
+
        struct hubbub_perfmon_funcs {
                void (*reset)(struct hubbub *hubbub);
                void (*start_measuring_max_memory_latency_ns)(