drm/amd/display: dsc validate fail not pass to atomic check
[Why] when 4k@144hz dp connect to dp1.4 dsc mst hub, requested bandwidth exceeds caps of dsc hub. but dsc bw valid functions, increase_dsc_bpp, try_disable_dsc, pre_validate_dsc, compute_mst_dsc_configs_for_state, do not return false to atomic check. this cause user mode initiate mode set to kernel, then cause kernel assert, system hang. [How] dsc bandwidth valid functions return pass or fail to atomic check. Reviewed-by: Wayne Lin <Wayne.Lin@amd.com> Reviewed-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com> Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com> Signed-off-by: hersen wu <hersenxs.wu@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
b840b64bc8
commit
71be4b16d3
@ -11255,7 +11255,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pre_validate_dsc(state, &dm_state, vars);
|
if (!pre_validate_dsc(state, &dm_state, vars)) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
|
||||||
@ -11501,6 +11504,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
|
|||||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||||
if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
|
if (!compute_mst_dsc_configs_for_state(state, dm_state->context, vars)) {
|
||||||
DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
|
DRM_DEBUG_DRIVER("compute_mst_dsc_configs_for_state() failed\n");
|
||||||
|
ret = -EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
|
|||||||
return dsc_config.bits_per_pixel;
|
return dsc_config.bits_per_pixel;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void increase_dsc_bpp(struct drm_atomic_state *state,
|
static bool increase_dsc_bpp(struct drm_atomic_state *state,
|
||||||
struct dc_link *dc_link,
|
struct dc_link *dc_link,
|
||||||
struct dsc_mst_fairness_params *params,
|
struct dsc_mst_fairness_params *params,
|
||||||
struct dsc_mst_fairness_vars *vars,
|
struct dsc_mst_fairness_vars *vars,
|
||||||
@ -730,7 +730,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
pbn_per_timeslot) < 0)
|
pbn_per_timeslot) < 0)
|
||||||
return;
|
return false;
|
||||||
if (!drm_dp_mst_atomic_check(state)) {
|
if (!drm_dp_mst_atomic_check(state)) {
|
||||||
vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
|
vars[next_index].bpp_x16 = bpp_x16_from_pbn(params[next_index], vars[next_index].pbn);
|
||||||
} else {
|
} else {
|
||||||
@ -740,7 +740,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
pbn_per_timeslot) < 0)
|
pbn_per_timeslot) < 0)
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vars[next_index].pbn += initial_slack[next_index];
|
vars[next_index].pbn += initial_slack[next_index];
|
||||||
@ -749,7 +749,7 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
pbn_per_timeslot) < 0)
|
pbn_per_timeslot) < 0)
|
||||||
return;
|
return false;
|
||||||
if (!drm_dp_mst_atomic_check(state)) {
|
if (!drm_dp_mst_atomic_check(state)) {
|
||||||
vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
|
vars[next_index].bpp_x16 = params[next_index].bw_range.max_target_bpp_x16;
|
||||||
} else {
|
} else {
|
||||||
@ -759,16 +759,17 @@ static void increase_dsc_bpp(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
pbn_per_timeslot) < 0)
|
pbn_per_timeslot) < 0)
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bpp_increased[next_index] = true;
|
bpp_increased[next_index] = true;
|
||||||
remaining_to_increase--;
|
remaining_to_increase--;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void try_disable_dsc(struct drm_atomic_state *state,
|
static bool try_disable_dsc(struct drm_atomic_state *state,
|
||||||
struct dc_link *dc_link,
|
struct dc_link *dc_link,
|
||||||
struct dsc_mst_fairness_params *params,
|
struct dsc_mst_fairness_params *params,
|
||||||
struct dsc_mst_fairness_vars *vars,
|
struct dsc_mst_fairness_vars *vars,
|
||||||
@ -816,7 +817,7 @@ static void try_disable_dsc(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
dm_mst_get_pbn_divider(dc_link)) < 0)
|
dm_mst_get_pbn_divider(dc_link)) < 0)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
if (!drm_dp_mst_atomic_check(state)) {
|
if (!drm_dp_mst_atomic_check(state)) {
|
||||||
vars[next_index].dsc_enabled = false;
|
vars[next_index].dsc_enabled = false;
|
||||||
@ -828,12 +829,13 @@ static void try_disable_dsc(struct drm_atomic_state *state,
|
|||||||
params[next_index].port,
|
params[next_index].port,
|
||||||
vars[next_index].pbn,
|
vars[next_index].pbn,
|
||||||
dm_mst_get_pbn_divider(dc_link)) < 0)
|
dm_mst_get_pbn_divider(dc_link)) < 0)
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
tried[next_index] = true;
|
tried[next_index] = true;
|
||||||
remaining_to_try--;
|
remaining_to_try--;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
||||||
@ -949,9 +951,11 @@ static bool compute_mst_dsc_configs_for_link(struct drm_atomic_state *state,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Optimize degree of compression */
|
/* Optimize degree of compression */
|
||||||
increase_dsc_bpp(state, dc_link, params, vars, count, k);
|
if (!increase_dsc_bpp(state, dc_link, params, vars, count, k))
|
||||||
|
return false;
|
||||||
|
|
||||||
try_disable_dsc(state, dc_link, params, vars, count, k);
|
if (!try_disable_dsc(state, dc_link, params, vars, count, k))
|
||||||
|
return false;
|
||||||
|
|
||||||
set_dsc_configs_from_fairness_vars(params, vars, count, k);
|
set_dsc_configs_from_fairness_vars(params, vars, count, k);
|
||||||
|
|
||||||
@ -1223,21 +1227,22 @@ static bool is_dsc_precompute_needed(struct drm_atomic_state *state)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pre_validate_dsc(struct drm_atomic_state *state,
|
bool pre_validate_dsc(struct drm_atomic_state *state,
|
||||||
struct dm_atomic_state **dm_state_ptr,
|
struct dm_atomic_state **dm_state_ptr,
|
||||||
struct dsc_mst_fairness_vars *vars)
|
struct dsc_mst_fairness_vars *vars)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct dm_atomic_state *dm_state;
|
struct dm_atomic_state *dm_state;
|
||||||
struct dc_state *local_dc_state = NULL;
|
struct dc_state *local_dc_state = NULL;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
if (!is_dsc_precompute_needed(state)) {
|
if (!is_dsc_precompute_needed(state)) {
|
||||||
DRM_INFO_ONCE("DSC precompute is not needed.\n");
|
DRM_INFO_ONCE("DSC precompute is not needed.\n");
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
if (dm_atomic_get_state(state, dm_state_ptr)) {
|
if (dm_atomic_get_state(state, dm_state_ptr)) {
|
||||||
DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
|
DRM_INFO_ONCE("dm_atomic_get_state() failed\n");
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
dm_state = *dm_state_ptr;
|
dm_state = *dm_state_ptr;
|
||||||
|
|
||||||
@ -1249,7 +1254,7 @@ void pre_validate_dsc(struct drm_atomic_state *state,
|
|||||||
|
|
||||||
local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
|
local_dc_state = kmemdup(dm_state->context, sizeof(struct dc_state), GFP_KERNEL);
|
||||||
if (!local_dc_state)
|
if (!local_dc_state)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
for (i = 0; i < local_dc_state->stream_count; i++) {
|
for (i = 0; i < local_dc_state->stream_count; i++) {
|
||||||
struct dc_stream_state *stream = dm_state->context->streams[i];
|
struct dc_stream_state *stream = dm_state->context->streams[i];
|
||||||
@ -1275,11 +1280,19 @@ void pre_validate_dsc(struct drm_atomic_state *state,
|
|||||||
&state->crtcs[ind].new_state->mode,
|
&state->crtcs[ind].new_state->mode,
|
||||||
dm_new_conn_state,
|
dm_new_conn_state,
|
||||||
dm_old_crtc_state->stream);
|
dm_old_crtc_state->stream);
|
||||||
|
if (local_dc_state->streams[i] == NULL) {
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret != 0)
|
||||||
|
goto clean_exit;
|
||||||
|
|
||||||
if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
|
if (!pre_compute_mst_dsc_configs_for_state(state, local_dc_state, vars)) {
|
||||||
DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
|
DRM_INFO_ONCE("pre_compute_mst_dsc_configs_for_state() failed\n");
|
||||||
|
ret = -EINVAL;
|
||||||
goto clean_exit;
|
goto clean_exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1309,5 +1322,7 @@ clean_exit:
|
|||||||
}
|
}
|
||||||
|
|
||||||
kfree(local_dc_state);
|
kfree(local_dc_state);
|
||||||
|
|
||||||
|
return (ret == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,7 +59,7 @@ bool compute_mst_dsc_configs_for_state(struct drm_atomic_state *state,
|
|||||||
|
|
||||||
bool needs_dsc_aux_workaround(struct dc_link *link);
|
bool needs_dsc_aux_workaround(struct dc_link *link);
|
||||||
|
|
||||||
void pre_validate_dsc(struct drm_atomic_state *state,
|
bool pre_validate_dsc(struct drm_atomic_state *state,
|
||||||
struct dm_atomic_state **dm_state_ptr,
|
struct dm_atomic_state **dm_state_ptr,
|
||||||
struct dsc_mst_fairness_vars *vars);
|
struct dsc_mst_fairness_vars *vars);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user