drm/amd/display: Generalize DMUB memory flushes from host

[WHY&HOW]
Add DMUB service context to aid in platform abstraction when
flushing memory from the host.

Reviewed-by: Nicholas Kazlauskas <nicholas.kazlauskas@amd.com>
Signed-off-by: Dillon Varone <Dillon.Varone@amd.com>
Signed-off-by: George Zhang <george.zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Dillon Varone 2026-06-23 15:42:34 -04:00 committed by Alex Deucher
parent b48b1cad84
commit 5b69770e94
5 changed files with 46 additions and 31 deletions

View File

@ -147,7 +147,7 @@ int dm_dmub_hw_init(struct amdgpu_device *adev)
struct dmub_srv_hw_params hw_params;
enum dmub_status status;
const unsigned char *fw_inst_const, *fw_bss_data;
u32 i, fw_inst_const_size, fw_bss_data_size;
u32 fw_inst_const_size, fw_bss_data_size;
bool has_hw_support;
if (!dmub_srv)
@ -243,8 +243,7 @@ int dm_dmub_hw_init(struct amdgpu_device *adev)
if (dmcu)
hw_params.psp_version = dmcu->psp_version;
for (i = 0; i < fb_info->num_fb; ++i)
hw_params.fb[i] = &fb_info->fb[i];
hw_params.fb_info = fb_info;
/* Enable usb4 dpia in the FW APU */
if (dc->caps.is_apu &&

View File

@ -1908,6 +1908,8 @@ static void dc_dmub_srv_ib_based_fams2_update_config(struct dc *dc,
config->global.features.bits.enable = enable && context->bw_ctx.bw.dcn.fams2_global_config.features.bits.enable;
config->global.features.bits.enable_ppt_check = dc->debug.fams2_config.bits.enable_ppt_check;
dmub_srv_flush_buffer_mem(dc->ctx->dmub_srv->dmub, &dc->ctx->dmub_srv->dmub->ib_mem_gart);
dm_execute_dmub_cmd_list(dc->ctx, 1, &cmd, DM_DMUB_WAIT_TYPE_WAIT);
}
@ -2073,7 +2075,7 @@ bool dc_dmub_srv_ips_query_residency_info(const struct dc_context *ctx, uint8_t
union dmub_rb_cmd cmd;
uint32_t bytes = sizeof(struct dmub_ips_residency_info);
dmub_flush_buffer_mem(&ctx->dmub_srv->dmub->scratch_mem_fb);
dmub_srv_flush_buffer_mem(ctx->dmub_srv->dmub, &ctx->dmub_srv->dmub->scratch_mem_fb);
memset(&cmd, 0, sizeof(cmd));
cmd.ips_query_residency_info.header.type = DMUB_CMD__IPS;

View File

@ -166,7 +166,7 @@ void dmub_abm_init_config(struct abm *abm,
uint8_t panel_mask = 0x01 << inst;
// TODO: Optimize by only reading back final 4 bytes
dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
dmub_srv_flush_buffer_mem(dc->dmub_srv->dmub, &dc->dmub_srv->dmub->scratch_mem_fb);
// Copy iramtable into cw7
memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)src, bytes);
@ -227,7 +227,7 @@ bool dmub_abm_save_restore(
unsigned int bytes = sizeof(struct abm_save_restore);
// TODO: Optimize by only reading back final 4 bytes
dmub_flush_buffer_mem(&dc->dmub_srv->dmub->scratch_mem_fb);
dmub_srv_flush_buffer_mem(dc->dmub_srv->dmub, &dc->dmub_srv->dmub->scratch_mem_fb);
// Copy iramtable into cw7
memcpy(dc->dmub_srv->dmub->scratch_mem_fb.cpu_addr, (void *)pData, bytes);

View File

@ -329,7 +329,7 @@ struct dmub_soc_fb_info {
* @load_inst_const: true if DMUB should load inst const fw
*/
struct dmub_srv_hw_params {
struct dmub_fb *fb[DMUB_WINDOW_TOTAL];
struct dmub_srv_fb_info *fb_info;
struct dmub_soc_fb_info soc_fb_info;
uint32_t psp_version;
bool load_inst_const;
@ -592,9 +592,11 @@ struct dmub_srv {
void *user_ctx;
uint32_t fw_version;
bool is_virtual;
bool no_ext_reg_access;
struct dmub_fb scratch_mem_fb;
struct dmub_fb ib_mem_gart;
struct dmub_fb cursor_offload_fb;
const struct dmub_srv_fb_info *fb_info;
volatile struct dmub_shared_state_feature_block *shared_state;
volatile struct dmub_cursor_offload_v1 *cursor_offload_v1;
volatile const struct dmub_fw_state *fw_state;
@ -954,14 +956,15 @@ enum dmub_status dmub_srv_get_gpint_dataout(struct dmub_srv *dmub,
uint32_t *dataout);
/**
* dmub_flush_buffer_mem() - Read back entire frame buffer region.
* dmub_srv_flush_buffer_mem() - Read back entire frame buffer region.
* This ensures that the write from x86 has been flushed and will not
* hang the DMCUB.
* @dmub: the dmub service
* @fb: frame buffer to flush
*
* Can be called after software initialization.
*/
void dmub_flush_buffer_mem(const struct dmub_fb *fb);
void dmub_srv_flush_buffer_mem(struct dmub_srv *dmub, const struct dmub_fb *fb);
/**
* dmub_srv_get_fw_boot_status() - Returns the DMUB boot status bits.

View File

@ -96,7 +96,7 @@ static inline uint32_t dmub_align(uint32_t val, uint32_t factor)
return (val + factor - 1) / factor * factor;
}
void dmub_flush_buffer_mem(const struct dmub_fb *fb)
void dmub_srv_flush_buffer_mem(struct dmub_srv *dmub, const struct dmub_fb *fb)
{
const uint8_t *base = (const uint8_t *)fb->cpu_addr;
uint8_t buf[64];
@ -114,6 +114,8 @@ void dmub_flush_buffer_mem(const struct dmub_fb *fb)
/* Read anything leftover into the buffer. */
if (end < fb->size)
dmub_memcpy(buf, base + pos, fb->size - end);
(void)dmub;
}
static const struct dmub_fw_meta_info *
@ -748,31 +750,38 @@ enum dmub_status dmub_srv_is_hw_init(struct dmub_srv *dmub, bool *is_hw_init)
enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
const struct dmub_srv_hw_params *params)
{
struct dmub_fb *inst_fb = params->fb[DMUB_WINDOW_0_INST_CONST];
struct dmub_fb *stack_fb = params->fb[DMUB_WINDOW_1_STACK];
struct dmub_fb *data_fb = params->fb[DMUB_WINDOW_2_BSS_DATA];
struct dmub_fb *bios_fb = params->fb[DMUB_WINDOW_3_VBIOS];
struct dmub_fb *mail_fb = params->fb[DMUB_WINDOW_4_MAILBOX];
struct dmub_fb *tracebuff_fb = params->fb[DMUB_WINDOW_5_TRACEBUFF];
struct dmub_fb *fw_state_fb = params->fb[DMUB_WINDOW_6_FW_STATE];
struct dmub_fb *shared_state_fb = params->fb[DMUB_WINDOW_SHARED_STATE];
struct dmub_fb *inst_fb;
struct dmub_fb *stack_fb;
struct dmub_fb *data_fb;
struct dmub_fb *bios_fb;
struct dmub_fb *mail_fb;
struct dmub_fb *tracebuff_fb;
struct dmub_fb *fw_state_fb;
struct dmub_fb *shared_state_fb;
struct dmub_rb_init_params rb_params, outbox0_rb_params;
struct dmub_window cw0, cw1, cw2, cw3, cw4, cw5, cw6, region6;
struct dmub_region inbox1, outbox1, outbox0;
uint32_t i;
if (!dmub->sw_init)
return DMUB_STATUS_INVALID;
for (i = 0; i < DMUB_WINDOW_TOTAL; ++i) {
if (!params->fb[i]) {
ASSERT(0);
return DMUB_STATUS_INVALID;
}
if (!params->fb_info || params->fb_info->num_fb < DMUB_WINDOW_TOTAL) {
ASSERT(0);
return DMUB_STATUS_INVALID;
}
inst_fb = &params->fb_info->fb[DMUB_WINDOW_0_INST_CONST];
stack_fb = &params->fb_info->fb[DMUB_WINDOW_1_STACK];
data_fb = &params->fb_info->fb[DMUB_WINDOW_2_BSS_DATA];
bios_fb = &params->fb_info->fb[DMUB_WINDOW_3_VBIOS];
mail_fb = &params->fb_info->fb[DMUB_WINDOW_4_MAILBOX];
tracebuff_fb = &params->fb_info->fb[DMUB_WINDOW_5_TRACEBUFF];
fw_state_fb = &params->fb_info->fb[DMUB_WINDOW_6_FW_STATE];
shared_state_fb = &params->fb_info->fb[DMUB_WINDOW_SHARED_STATE];
dmub->fb_info = params->fb_info;
memcpy(&dmub->soc_fb_info, &params->soc_fb_info, sizeof(params->soc_fb_info));
dmub->psp_version = params->psp_version;
@ -800,7 +809,7 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
* flushed yet. This only occurs in backdoor loading.
*/
if (params->mem_access_type == DMUB_MEMORY_ACCESS_CPU)
dmub_flush_buffer_mem(inst_fb);
dmub_srv_flush_buffer_mem(dmub, inst_fb);
if (params->fw_in_system_memory && dmub->hw_funcs.backdoor_load_zfb_mode)
dmub->hw_funcs.backdoor_load_zfb_mode(dmub, &cw0, &cw1);
@ -851,10 +860,10 @@ enum dmub_status dmub_srv_hw_init(struct dmub_srv *dmub,
dmub->shared_state = shared_state_fb->cpu_addr;
dmub->scratch_mem_fb = *params->fb[DMUB_WINDOW_7_SCRATCH_MEM];
dmub->ib_mem_gart = *params->fb[DMUB_WINDOW_IB_MEM];
dmub->scratch_mem_fb = params->fb_info->fb[DMUB_WINDOW_7_SCRATCH_MEM];
dmub->ib_mem_gart = params->fb_info->fb[DMUB_WINDOW_IB_MEM];
dmub->cursor_offload_fb = *params->fb[DMUB_WINDOW_CURSOR_OFFLOAD];
dmub->cursor_offload_fb = params->fb_info->fb[DMUB_WINDOW_CURSOR_OFFLOAD];
dmub->cursor_offload_v1 = (struct dmub_cursor_offload_v1 *)dmub->cursor_offload_fb.cpu_addr;
if (dmub->hw_funcs.setup_windows)
@ -1014,13 +1023,14 @@ enum dmub_status dmub_srv_wait_for_hw_pwr_up(struct dmub_srv *dmub,
enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
uint32_t timeout_us)
{
const uint32_t delay_us = 100;
uint32_t i;
bool hw_on = true;
if (!dmub->hw_init)
return DMUB_STATUS_INVALID;
for (i = 0; i <= timeout_us; i += 100) {
for (i = 0; i <= timeout_us; i += delay_us) {
union dmub_fw_boot_status status = dmub->hw_funcs.get_fw_status(dmub);
if (dmub->hw_funcs.is_hw_powered_up)
@ -1029,7 +1039,7 @@ enum dmub_status dmub_srv_wait_for_auto_load(struct dmub_srv *dmub,
if (status.bits.dal_fw && status.bits.mailbox_rdy && hw_on)
return DMUB_STATUS_OK;
udelay(100);
udelay(delay_us);
}
return DMUB_STATUS_TIMEOUT;
@ -1258,6 +1268,7 @@ bool dmub_srv_get_diagnostic_data(struct dmub_srv *dmub)
if (!dmub || !dmub->hw_funcs.get_diagnostic_data)
return false;
dmub->hw_funcs.get_diagnostic_data(dmub);
return true;
}