]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/amd/display: decouple dmcub execution to reduce lock granularity
authorJinZe.Xu <jinze.xu@amd.com>
Fri, 13 Oct 2023 01:50:00 +0000 (09:50 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 7 Nov 2023 16:16:01 +0000 (11:16 -0500)
[Why]
On some systems dmub commands run at high IRQ, so long running
commands will block other interrupts.

[How]
Decouple wait_for_idle from dmcub queue/execute/wait.

Reviewed-by: Josip Pavic <josip.pavic@amd.com>
Acked-by: Hersen Wu <hersenxs.wu@amd.com>
Signed-off-by: JinZe.Xu <jinze.xu@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h

index ba142bef626bf5910c52c04980055d999139cb47..e4c007203318bf0b9ad3f3f9b1d2fd73973ca4f9 100644 (file)
@@ -120,6 +120,80 @@ void dc_dmub_srv_send_inbox0_cmd(struct dc_dmub_srv *dc_dmub_srv,
        }
 }
 
+bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
+               unsigned int count,
+               union dmub_rb_cmd *cmd_list)
+{
+       struct dc_context *dc_ctx = dc_dmub_srv->ctx;
+       struct dmub_srv *dmub;
+       enum dmub_status status;
+       int i;
+
+       if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+               return false;
+
+       dmub = dc_dmub_srv->dmub;
+
+       for (i = 0 ; i < count; i++) {
+               // Queue command
+               status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+
+               if (status == DMUB_STATUS_QUEUE_FULL) {
+                       /* Execute and wait for queue to become empty again. */
+                       dmub_srv_cmd_execute(dmub);
+                       dmub_srv_wait_for_idle(dmub, 100000);
+
+                       /* Requeue the command. */
+                       status = dmub_srv_cmd_queue(dmub, &cmd_list[i]);
+               }
+
+               if (status != DMUB_STATUS_OK) {
+                       DC_ERROR("Error queueing DMUB command: status=%d\n", status);
+                       dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+                       return false;
+               }
+       }
+
+       status = dmub_srv_cmd_execute(dmub);
+       if (status != DMUB_STATUS_OK) {
+               DC_ERROR("Error starting DMUB execution: status=%d\n", status);
+               dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+               return false;
+       }
+
+       return true;
+}
+
+bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
+               enum dm_dmub_wait_type wait_type,
+               union dmub_rb_cmd *cmd_list)
+{
+       struct dmub_srv *dmub;
+       enum dmub_status status;
+
+       if (!dc_dmub_srv || !dc_dmub_srv->dmub)
+               return false;
+
+       dmub = dc_dmub_srv->dmub;
+
+       // Wait for DMUB to process command
+       if (wait_type != DM_DMUB_WAIT_TYPE_NO_WAIT) {
+               status = dmub_srv_wait_for_idle(dmub, 100000);
+
+               if (status != DMUB_STATUS_OK) {
+                       DC_LOG_DEBUG("No reply for DMUB command: status=%d\n", status);
+                       dc_dmub_srv_log_diagnostic_data(dc_dmub_srv);
+                       return false;
+               }
+
+               // Copy data back from ring buffer into command
+               if (wait_type == DM_DMUB_WAIT_TYPE_WAIT_WITH_REPLY)
+                       dmub_rb_get_return_data(&dmub->inbox1_rb, cmd_list);
+       }
+
+       return true;
+}
+
 bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type)
 {
        return dc_dmub_srv_cmd_run_list(dc_dmub_srv, 1, cmd, wait_type);
index 31150b21439484d2cf6eff186bc7c43a463dbcd7..d4a60f53faab12f69e3d09a78b54adade290d6fa 100644 (file)
@@ -56,6 +56,14 @@ void dc_dmub_srv_wait_idle(struct dc_dmub_srv *dc_dmub_srv);
 
 bool dc_dmub_srv_optimized_init_done(struct dc_dmub_srv *dc_dmub_srv);
 
+bool dc_dmub_srv_cmd_list_queue_execute(struct dc_dmub_srv *dc_dmub_srv,
+               unsigned int count,
+               union dmub_rb_cmd *cmd_list);
+
+bool dc_dmub_srv_wait_for_idle(struct dc_dmub_srv *dc_dmub_srv,
+               enum dm_dmub_wait_type wait_type,
+               union dmub_rb_cmd *cmd_list);
+
 bool dc_dmub_srv_cmd_run(struct dc_dmub_srv *dc_dmub_srv, union dmub_rb_cmd *cmd, enum dm_dmub_wait_type wait_type);
 
 bool dc_dmub_srv_cmd_run_list(struct dc_dmub_srv *dc_dmub_srv, unsigned int count, union dmub_rb_cmd *cmd_list, enum dm_dmub_wait_type wait_type);