drm/amd/display: decouple dmcub execution to reduce lock granularity
[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>
This commit is contained in:
parent
13c84bbe05
commit
028bac5834
2 changed files with 82 additions and 0 deletions
|
@ -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)
|
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);
|
return dc_dmub_srv_cmd_run_list(dc_dmub_srv, 1, cmd, wait_type);
|
||||||
|
|
|
@ -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_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(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);
|
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);
|
||||||
|
|
Loading…
Add table
Reference in a new issue