From: "JinZe.Xu" <[email protected]>

[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 <[email protected]>
Acked-by: Hersen Wu <[email protected]>
Signed-off-by: JinZe.Xu <[email protected]>
---
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c | 74 ++++++++++++++++++++
 drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h |  8 +++
 2 files changed, 82 insertions(+)

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 ba142bef626b..e4c007203318 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -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);
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 31150b214394..d4a60f53faab 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.h
@@ -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);
-- 
2.25.1

Reply via email to