[PATCH 11/33] drm/amd/display: Update Link Training Fallback logic
Harry Wentland
harry.wentland at amd.com
Mon Feb 26 20:15:41 UTC 2018
From: Wenjing Liu <Wenjing.Liu at amd.com>
[Description]
When CR fails to minimum link rate,
we should reduce lane count to the number lowest cr_done lanes.
[Code Review]
Jun Lei
Signed-off-by: Wenjing Liu <Wenjing.Liu at amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng at amd.com>
Acked-by: Harry Wentland <harry.wentland at amd.com>
---
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c | 98 ++++++++++++++++------
drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c | 1 +
.../drm/amd/display/include/link_service_types.h | 5 +-
3 files changed, 79 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 604fb0171ee3..4c21da54a9d5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -709,6 +709,22 @@ static enum hw_dp_training_pattern get_supported_tp(struct dc_link *link)
return HW_DP_TRAINING_PATTERN_2;
}
+static enum link_training_result get_cr_failure(enum dc_lane_count ln_count,
+ union lane_status *dpcd_lane_status)
+{
+ enum link_training_result result = LINK_TRAINING_SUCCESS;
+
+ if (ln_count >= LANE_COUNT_ONE && !dpcd_lane_status[0].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE0;
+ else if (ln_count >= LANE_COUNT_TWO && !dpcd_lane_status[1].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE1;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[2].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ else if (ln_count >= LANE_COUNT_FOUR && !dpcd_lane_status[3].bits.CR_DONE_0)
+ result = LINK_TRAINING_CR_FAIL_LANE23;
+ return result;
+}
+
static enum link_training_result perform_channel_equalization_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
@@ -771,7 +787,7 @@ static enum link_training_result perform_channel_equalization_sequence(
}
-static bool perform_clock_recovery_sequence(
+static enum link_training_result perform_clock_recovery_sequence(
struct dc_link *link,
struct link_training_settings *lt_settings)
{
@@ -846,11 +862,11 @@ static bool perform_clock_recovery_sequence(
/* 5. check CR done*/
if (is_cr_done(lane_count, dpcd_lane_status))
- return true;
+ return LINK_TRAINING_SUCCESS;
/* 6. max VS reached*/
if (is_max_vs_reached(lt_settings))
- return false;
+ break;
/* 7. same voltage*/
/* Note: VS same for all lanes,
@@ -876,13 +892,13 @@ static bool perform_clock_recovery_sequence(
}
- return false;
+ return get_cr_failure(lane_count, dpcd_lane_status);
}
-static inline bool perform_link_training_int(
+static inline enum link_training_result perform_link_training_int(
struct dc_link *link,
struct link_training_settings *lt_settings,
- bool status)
+ enum link_training_result status)
{
union lane_count_set lane_count_set = { {0} };
union dpcd_training_pattern dpcd_pattern = { {0} };
@@ -903,9 +919,9 @@ static inline bool perform_link_training_int(
get_supported_tp(link) == HW_DP_TRAINING_PATTERN_4)
return status;
- if (status &&
+ if (status == LINK_TRAINING_SUCCESS &&
perform_post_lt_adj_req_sequence(link, lt_settings) == false)
- status = false;
+ status = LINK_TRAINING_LQA_FAIL;
lane_count_set.bits.LANE_COUNT_SET = lt_settings->link_settings.lane_count;
lane_count_set.bits.ENHANCED_FRAMING = 1;
@@ -928,6 +944,8 @@ enum link_training_result dc_link_dp_perform_link_training(
enum link_training_result status = LINK_TRAINING_SUCCESS;
char *link_rate = "Unknown";
+ char *lt_result = "Unknown";
+
struct link_training_settings lt_settings;
memset(<_settings, '\0', sizeof(lt_settings));
@@ -951,22 +969,16 @@ enum link_training_result dc_link_dp_perform_link_training(
/* 2. perform link training (set link training done
* to false is done as well)*/
- if (!perform_clock_recovery_sequence(link, <_settings)) {
- status = LINK_TRAINING_CR_FAIL;
- } else {
+ status = perform_clock_recovery_sequence(link, <_settings);
+ if (status == LINK_TRAINING_SUCCESS) {
status = perform_channel_equalization_sequence(link,
<_settings);
}
if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern) {
- if (!perform_link_training_int(link,
+ status = perform_link_training_int(link,
<_settings,
- status == LINK_TRAINING_SUCCESS)) {
- /* the next link training setting in this case
- * would be the same as CR failure case.
- */
- status = LINK_TRAINING_CR_FAIL;
- }
+ status);
}
/* 6. print status message*/
@@ -991,13 +1003,37 @@ enum link_training_result dc_link_dp_perform_link_training(
break;
}
+ switch (status) {
+ case LINK_TRAINING_SUCCESS:
+ lt_result = "pass";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ lt_result = "CR failed lane0";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ lt_result = "CR failed lane1";
+ break;
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ lt_result = "CR failed lane23";
+ break;
+ case LINK_TRAINING_EQ_FAIL_CR:
+ lt_result = "CR failed in EQ";
+ break;
+ case LINK_TRAINING_EQ_FAIL_EQ:
+ lt_result = "EQ failed";
+ break;
+ case LINK_TRAINING_LQA_FAIL:
+ lt_result = "LQA failed";
+ break;
+ default:
+ break;
+ }
+
/* Connectivity log: link training */
CONN_MSG_LT(link, "%sx%d %s VS=%d, PE=%d",
link_rate,
lt_settings.link_settings.lane_count,
- (status == LINK_TRAINING_SUCCESS) ? "pass" :
- ((status == LINK_TRAINING_CR_FAIL) ? "CR failed" :
- "EQ failed"),
+ lt_result,
lt_settings.lane_settings[0].VOLTAGE_SWING,
lt_settings.lane_settings[0].PRE_EMPHASIS);
@@ -1115,6 +1151,7 @@ bool dp_hbr_verify_link_cap(
dp_cs_id,
cur);
+
if (skip_link_training)
success = true;
else {
@@ -1279,7 +1316,10 @@ static bool decide_fallback_link_setting(
return false;
switch (training_result) {
- case LINK_TRAINING_CR_FAIL:
+ case LINK_TRAINING_CR_FAIL_LANE0:
+ case LINK_TRAINING_CR_FAIL_LANE1:
+ case LINK_TRAINING_CR_FAIL_LANE23:
+ case LINK_TRAINING_LQA_FAIL:
{
if (!reached_minimum_link_rate
(current_link_setting->link_rate)) {
@@ -1290,8 +1330,18 @@ static bool decide_fallback_link_setting(
(current_link_setting->lane_count)) {
current_link_setting->link_rate =
initial_link_settings.link_rate;
- current_link_setting->lane_count =
- reduce_lane_count(
+ if (training_result == LINK_TRAINING_CR_FAIL_LANE0)
+ return false;
+ else if (training_result == LINK_TRAINING_CR_FAIL_LANE1)
+ current_link_setting->lane_count =
+ LANE_COUNT_ONE;
+ else if (training_result ==
+ LINK_TRAINING_CR_FAIL_LANE23)
+ current_link_setting->lane_count =
+ LANE_COUNT_TWO;
+ else
+ current_link_setting->lane_count =
+ reduce_lane_count(
current_link_setting->lane_count);
} else {
return false;
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
index bae9b0587e12..7c866a7d5e77 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_hwss.c
@@ -279,6 +279,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
for (i = 0; i < MAX_PIPES; i++) {
if (pipes[i].stream != NULL &&
+ !pipes[i].top_pipe &&
pipes[i].stream->sink != NULL &&
pipes[i].stream->sink->link != NULL &&
pipes[i].stream_res.stream_enc != NULL &&
diff --git a/drivers/gpu/drm/amd/display/include/link_service_types.h b/drivers/gpu/drm/amd/display/include/link_service_types.h
index adea1a59f620..80f0d93cfd94 100644
--- a/drivers/gpu/drm/amd/display/include/link_service_types.h
+++ b/drivers/gpu/drm/amd/display/include/link_service_types.h
@@ -58,11 +58,14 @@ enum {
enum link_training_result {
LINK_TRAINING_SUCCESS,
- LINK_TRAINING_CR_FAIL,
+ LINK_TRAINING_CR_FAIL_LANE0,
+ LINK_TRAINING_CR_FAIL_LANE1,
+ LINK_TRAINING_CR_FAIL_LANE23,
/* CR DONE bit is cleared during EQ step */
LINK_TRAINING_EQ_FAIL_CR,
/* other failure during EQ step */
LINK_TRAINING_EQ_FAIL_EQ,
+ LINK_TRAINING_LQA_FAIL,
};
struct link_training_settings {
--
2.14.1
More information about the amd-gfx
mailing list