mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
drm/amd/display: add workaround for riommu invalidation request hang
[Why] When an riommu invalidation request come at the same time as a pipe is disabled there can be a case where DCN cannot ACK the request if only one VMID is setup in the inuse list. [How] Setup a second unused VMID will work around the issue. Reviewed-by: Jun Lei <jun.lei@amd.com> Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Signed-off-by: Eric Yang <Eric.Yang2@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
ba16b22d42
commit
a4d5df1787
|
|
@ -570,6 +570,12 @@ void dcn20_plane_atomic_disable(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
|||
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
||||
struct dpp *dpp = pipe_ctx->plane_res.dpp;
|
||||
|
||||
if (hws->wa.early_riommu_invalidation) {
|
||||
struct hubbub *hubbub = dc->res_pool->hubbub;
|
||||
|
||||
hubbub->funcs->apply_invalidation_req_wa(hubbub, &hubbub->vmid_cache);
|
||||
}
|
||||
|
||||
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe_ctx);
|
||||
|
||||
/* In flip immediate with pipe splitting case GSL is used for
|
||||
|
|
|
|||
|
|
@ -880,6 +880,8 @@ static int hubbub31_init_dchub_sys_ctx(struct hubbub *hubbub,
|
|||
|
||||
dcn21_dchvm_init(hubbub);
|
||||
|
||||
hubbub->vmid_cache = *pa_config;
|
||||
|
||||
return NUM_VMID;
|
||||
}
|
||||
|
||||
|
|
@ -920,6 +922,23 @@ static void hubbub31_get_dchub_ref_freq(struct hubbub *hubbub,
|
|||
}
|
||||
}
|
||||
|
||||
static void hubbub31_apply_invalidation_req_wa(struct hubbub *hubbub,
|
||||
struct dcn_hubbub_phys_addr_config *pa_config)
|
||||
{
|
||||
struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
|
||||
struct dcn_vmid_page_table_config phys_config;
|
||||
|
||||
if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {
|
||||
phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;
|
||||
phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;
|
||||
phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr;
|
||||
phys_config.depth = 0;
|
||||
phys_config.block_size = 0;
|
||||
// Program an arbitrary unused VMID
|
||||
dcn20_vmid_setup(&hubbub1->vmid[15], &phys_config);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct hubbub_funcs hubbub31_funcs = {
|
||||
.update_dchub = hubbub2_update_dchub,
|
||||
.init_dchub_sys_ctx = hubbub31_init_dchub_sys_ctx,
|
||||
|
|
@ -936,6 +955,7 @@ static const struct hubbub_funcs hubbub31_funcs = {
|
|||
.program_compbuf_size = dcn31_program_compbuf_size,
|
||||
.init_crb = dcn31_init_crb,
|
||||
.hubbub_read_state = hubbub2_read_state,
|
||||
.apply_invalidation_req_wa = hubbub31_apply_invalidation_req_wa
|
||||
};
|
||||
|
||||
void hubbub31_construct(struct dcn20_hubbub *hubbub31,
|
||||
|
|
|
|||
|
|
@ -166,12 +166,15 @@ struct hubbub_funcs {
|
|||
void (*program_det_size)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_in_kbyte);
|
||||
void (*program_compbuf_size)(struct hubbub *hubbub, unsigned compbuf_size_kb, bool safe_to_increase);
|
||||
void (*init_crb)(struct hubbub *hubbub);
|
||||
void (*apply_invalidation_req_wa)(struct hubbub *hubbub,
|
||||
struct dcn_hubbub_phys_addr_config *pa_config);
|
||||
};
|
||||
|
||||
struct hubbub {
|
||||
const struct hubbub_funcs *funcs;
|
||||
struct dc_context *ctx;
|
||||
bool riommu_active;
|
||||
struct dcn_hubbub_phys_addr_config vmid_cache;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user