drm/amd/display: Add additional checks for PSP footer size

[WHY & HOW]
Newer ASICs have different PSP footer sizes which lead to driver
failing to locate the DMCUB FW meta info, which in turn causes
improper DMCUB FW loading and causes DMCUB to crash.

Add support for custom PSP footer sizes and check 512B by default
as well.

Reviewed-by: Charlene Liu <charlene.liu@amd.com>
Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com>
Signed-off-by: Alex Hung <alex.hung@amd.com>
Tested-by: Dan Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
Ovidiu Bunea
2025-11-11 15:44:08 -05:00
committed by Alex Deucher
parent c7062be338
commit e1b385726f
5 changed files with 119 additions and 30 deletions

View File

@@ -134,7 +134,7 @@ dmub_get_fw_meta_info_from_blob(const uint8_t *blob, uint32_t blob_size, uint32_
}
static const struct dmub_fw_meta_info *
dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
dmub_get_fw_meta_info(const struct dmub_srv_fw_meta_info_params *params)
{
const struct dmub_fw_meta_info *info = NULL;
@@ -159,6 +159,46 @@ dmub_get_fw_meta_info(const struct dmub_srv_region_params *params)
return info;
}
enum dmub_status
dmub_srv_get_fw_meta_info_from_raw_fw(struct dmub_srv_fw_meta_info_params *params,
struct dmub_fw_meta_info *fw_info_out)
{
const struct dmub_fw_meta_info *fw_info = NULL;
uint32_t inst_const_size_temp = params->inst_const_size;
/* First try custom psp footer size, if present */
if (params->custom_psp_footer_size) {
params->inst_const_size -= params->custom_psp_footer_size;
fw_info = dmub_get_fw_meta_info(params);
if (fw_info) {
memcpy(fw_info_out, fw_info, sizeof(*fw_info));
return DMUB_STATUS_OK;
}
params->inst_const_size = inst_const_size_temp;
}
/* Try 256-byte psp footer size */
params->inst_const_size -= PSP_FOOTER_BYTES_256;
fw_info = dmub_get_fw_meta_info(params);
if (fw_info) {
memcpy(fw_info_out, fw_info, sizeof(*fw_info));
return DMUB_STATUS_OK;
}
/* Try 512-byte psp footer size - final attempt */
params->inst_const_size -= PSP_FOOTER_BYTES_256; // 256 bytes already subtracted, subtract 256 again
fw_info = dmub_get_fw_meta_info(params);
if (fw_info) {
memcpy(fw_info_out, fw_info, sizeof(*fw_info));
return DMUB_STATUS_OK;
}
/* Restore original inst_const_size and subtract default PSP footer size - default behaviour */
params->inst_const_size = inst_const_size_temp - PSP_FOOTER_BYTES_256;
return DMUB_STATUS_INVALID;
}
static bool dmub_srv_hw_setup(struct dmub_srv *dmub, enum dmub_asic asic)
{
struct dmub_srv_hw_funcs *funcs = &dmub->hw_funcs;
@@ -524,7 +564,6 @@ enum dmub_status
const struct dmub_srv_region_params *params,
struct dmub_srv_region_info *out)
{
const struct dmub_fw_meta_info *fw_info;
uint32_t fw_state_size = DMUB_FW_STATE_SIZE;
uint32_t trace_buffer_size = DMUB_TRACE_BUFFER_SIZE;
uint32_t shared_state_size = DMUB_FW_HEADER_SHARED_STATE_SIZE;
@@ -538,14 +577,12 @@ enum dmub_status
out->num_regions = DMUB_NUM_WINDOWS;
fw_info = dmub_get_fw_meta_info(params);
if (params->fw_info) {
memcpy(&dmub->meta_info, params->fw_info, sizeof(*params->fw_info));
if (fw_info) {
memcpy(&dmub->meta_info, fw_info, sizeof(*fw_info));
fw_state_size = fw_info->fw_region_size;
trace_buffer_size = fw_info->trace_buffer_size;
shared_state_size = fw_info->shared_state_size;
fw_state_size = params->fw_info->fw_region_size;
trace_buffer_size = params->fw_info->trace_buffer_size;
shared_state_size = params->fw_info->shared_state_size;
/**
* If DM didn't fill in a version, then fill it in based on
@@ -555,7 +592,7 @@ enum dmub_status
* pass during creation.
*/
if (dmub->fw_version == 0)
dmub->fw_version = fw_info->fw_version;
dmub->fw_version = params->fw_info->fw_version;
}
window_sizes[DMUB_WINDOW_0_INST_CONST] = params->inst_const_size;