Skip to contentSkip to conversation

drm/i915/dp: link rate and lane count refactoring

PATCH Superseded Jani Nikula 4 participants 31 messages Jan 26, 2017 – Feb 7, 2017

Subsystems (2)

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover drm/i915/dp: link rate and lane count refactoring

This is kind of version 1½ of [1], basically just rebased on current git (including Manasi's test automation patches) and a couple of more cleanups slammed on top.

BR,
Jani.

[1] http://mid.mail-archive.com/[email protected]

Jani Nikula (13):
drm/i915/dp: use known correct array size in rate_to_index drm/i915/dp: return errors from rate_to_index() drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse drm/i915/dp: cache source rates at init
drm/i915/dp: generate and cache sink rate array for all DP, not just

    eDP 1.4

drm/i915/dp: use the sink rates array for max sink rates drm/i915/dp: cache common rates with sink rates drm/i915/dp: do not limit rate seek when not needed drm/i915/dp: don't call the link parameters sink parameters drm/i915/dp: add functions for max common link rate and lane count drm/i915/mst: use max link not sink lane count drm/i915/dp: localize link rate index variable more drm/i915/dp: use readb and writeb calls for single byte DPCD access

 drivers/gpu/drm/i915/intel_dp.c               | 275 ++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp_link_training.c |   3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c           |   4 +-
 drivers/gpu/drm/i915/intel_drv.h              |  19 +-
 4 files changed, 166 insertions(+), 135 deletions(-)
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#1 lore raw

PATCH 1/13 drm/i915/dp: use known correct array size in rate_to_index

I can't think of a real world bug this could cause now, but this will be required in follow-up work. While at it, change the parameter order to be slightly more sensible.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +6 -5
index 0fafbec6dacf..08eeb33cf63e 100644
@@ -1542,12 +1542,12 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 	return true;
 }
 
-static int rate_to_index(int find, const int *rates)
+static int rate_to_index(const int *rates, int len, int rate)
 {
-	int i = 0;
+	int i;
 
-	for (i = 0; i < DP_MAX_SUPPORTED_RATES; ++i)
-		if (find == rates[i])
+	for (i = 0; i < len; i++)
+		if (rate == rates[i])
 			break;
 
 	return i;
@@ -1568,7 +1568,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	return rate_to_index(rate, intel_dp->sink_rates);
+	return rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
+			     rate);
 }
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#2 lore raw

PATCH 2/13 drm/i915/dp: return errors from rate_to_index()

In reply to Jani Nikula

We shouldn't silently use the first element if we can't find the rate we're looking for. Make rate_to_index() more generally useful, and fallback to the first element in the caller, with a big warning.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +9 -4
index 08eeb33cf63e..1d66737a3a0f 100644
@@ -1548,9 +1548,9 @@ static int rate_to_index(const int *rates, int len, int rate)
 
 	for (i = 0; i < len; i++)
 		if (rate == rates[i])
-			break;
+			return i;
 
-	return i;
+	return -1;
 }
 
 int
@@ -1568,8 +1568,13 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	return rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
-			     rate);
+	int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
+			      rate);
+
+	if (WARN_ON(i < 0))
+		i = 0;
+
+	return i;
 }
 
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#3 lore raw

PATCH 3/13 drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse

In reply to Jani Nikula

Rename the function, move it at the top, and reuse in intel_dp_link_rate_index(). If there was a reason in the past to use reverse search order here, there isn't now.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +14 -19
index 1d66737a3a0f..f3068ff670a1 100644
@@ -266,6 +266,17 @@ static int intersect_rates(const int *source_rates, int source_len,
 	return k;
 }
 
+static int intel_dp_find_rate(const int *rates, int len, int rate)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (rate == rates[i])
+			return i;
+
+	return -1;
+}
+
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
@@ -284,15 +295,10 @@ static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
 				    int *common_rates, int link_rate)
 {
 	int common_len;
-	int index;
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	for (index = 0; index < common_len; index++) {
-		if (link_rate == common_rates[common_len - index - 1])
-			return common_len - index - 1;
-	}
 
-	return -1;
+	return intel_dp_find_rate(common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
@@ -1542,17 +1548,6 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 	return true;
 }
 
-static int rate_to_index(const int *rates, int len, int rate)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		if (rate == rates[i])
-			return i;
-
-	return -1;
-}
-
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
@@ -1568,8 +1563,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
-			      rate);
+	int i = intel_dp_find_rate(intel_dp->sink_rates,
+				   intel_dp->num_sink_rates, rate);
 
 	if (WARN_ON(i < 0))
 		i = 0;
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#4 lore raw

Re: [PATCH v1½ 03/13] drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse

Quoted 16 lines · Jani Nikula

Rename the function, move it at the top, and reuse in intel_dp_link_rate_index(). If there was a reason in the past to use reverse search order here, there isn't now.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -0
index 1d66737a3a0f..f3068ff670a1 100644

drivers/gpu/drm/i915/intel_dp.c static int intersect_rates(const int *source_rates, int source_len, · line 269

Quoted 4 lines
drivers/gpu/drm/i915/intel_dp.c +1 -0
@@ -266,6 +266,17 @@ static int intersect_rates(const int *source_rates, int source_len,
 	return k;
 }
 
+static int intel_dp_find_rate(const int *rates, int len, int rate)

I wonder if the function name can be more intuitive. The argument is rate and the function name indicates it also returns rate. I can't tell what the function does by it's name. Feel free to ignore this comment as I might be missing some context.

-DK

Quoted 49 lines
drivers/gpu/drm/i915/intel_dp.c +11 -17
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (rate == rates[i])
+			return i;
+
+	return -1;
+}
+
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
@@ -284,15 +295,10 @@ static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
 				    int *common_rates, int link_rate)
 {
 	int common_len;
-	int index;
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	for (index = 0; index < common_len; index++) {
-		if (link_rate == common_rates[common_len - index - 1])
-			return common_len - index - 1;
-	}
 
-	return -1;
+	return intel_dp_find_rate(common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
@@ -1542,17 +1548,6 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 	return true;
 }
 
-static int rate_to_index(const int *rates, int len, int rate)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		if (rate == rates[i])
-			return i;
-
-	return -1;
-}
-
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {

drivers/gpu/drm/i915/intel_dp.c intel_dp_max_link_rate(struct intel_dp *intel_dp) · line 1570

Quoted 10 lines
drivers/gpu/drm/i915/intel_dp.c +2 -2
@@ -1568,8 +1563,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
-			      rate);
+	int i = intel_dp_find_rate(intel_dp->sink_rates,
+				   intel_dp->num_sink_rates, rate);
 
 	if (WARN_ON(i < 0))
 		i = 0;

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#5 lore raw

Re: [PATCH v1½ 03/13] drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse

Quoted 20 lines · Dhinakaran
Quoted 19 lines · Jani Nikula

Rename the function, move it at the top, and reuse in intel_dp_link_rate_index(). If there was a reason in the past to use reverse search order here, there isn't now.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -0
index 1d66737a3a0f..f3068ff670a1 100644
@@ -266,6 +266,17 @@ static int intersect_rates(const int *source_rates, int source_len,
 	return k;
 }
 
Quoted 6 lines

drivers/gpu/drm/i915/intel_dp.c static int intersect_rates(const int *source_rates, int source_len, · line 269

Quoted 1 line
drivers/gpu/drm/i915/intel_dp.c +1 -0
+static int intel_dp_find_rate(const int *rates, int len, int rate)

I wonder if the function name can be more intuitive. The argument is rate and the function name indicates it also returns rate. I can't tell what the function does by it's name. Feel free to ignore this comment as I might be missing some context.

Naming is hard. intel_dp_rate_index?

BR,
Jani.

Quoted 63 lines

-DK

Quoted 59 lines
drivers/gpu/drm/i915/intel_dp.c +13 -19
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (rate == rates[i])
+			return i;
+
+	return -1;
+}
+
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
@@ -284,15 +295,10 @@ static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
 				    int *common_rates, int link_rate)
 {
 	int common_len;
-	int index;
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	for (index = 0; index < common_len; index++) {
-		if (link_rate == common_rates[common_len - index - 1])
-			return common_len - index - 1;
-	}
 
-	return -1;
+	return intel_dp_find_rate(common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
@@ -1542,17 +1548,6 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 	return true;
 }
 
-static int rate_to_index(const int *rates, int len, int rate)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		if (rate == rates[i])
-			return i;
-
-	return -1;
-}
-
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
@@ -1568,8 +1563,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
-			      rate);
+	int i = intel_dp_find_rate(intel_dp->sink_rates,
+				   intel_dp->num_sink_rates, rate);
 
 	if (WARN_ON(i < 0))
 		i = 0;
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#6 lore raw

Re: [PATCH v1½ 03/13] drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse

Quoted 28 lines · Jani Nikula
Quoted 20 lines · Dhinakaran
Quoted 19 lines · Jani Nikula

Rename the function, move it at the top, and reuse in intel_dp_link_rate_index(). If there was a reason in the past to use reverse search order here, there isn't now.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -0
index 1d66737a3a0f..f3068ff670a1 100644
@@ -266,6 +266,17 @@ static int intersect_rates(const int *source_rates, int source_len,
 	return k;
 }
 
Quoted 6 lines

drivers/gpu/drm/i915/intel_dp.c static int intersect_rates(const int *source_rates, int source_len, · line 269

Quoted 1 line
drivers/gpu/drm/i915/intel_dp.c +1 -0
+static int intel_dp_find_rate(const int *rates, int len, int rate)

I wonder if the function name can be more intuitive. The argument is rate and the function name indicates it also returns rate. I can't tell what the function does by it's name. Feel free to ignore this comment as I might be missing some context.

Quoted 6 lines

Naming is hard. intel_dp_rate_index?

BR,
Jani.

That does sounds good.

Quoted 60 lines
Quoted 60 lines

-DK

Quoted 57 lines
drivers/gpu/drm/i915/intel_dp.c +13 -19
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		if (rate == rates[i])
+			return i;
+
+	return -1;
+}
+
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
@@ -284,15 +295,10 @@ static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
 				    int *common_rates, int link_rate)
 {
 	int common_len;
-	int index;
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	for (index = 0; index < common_len; index++) {
-		if (link_rate == common_rates[common_len - index - 1])
-			return common_len - index - 1;
-	}
 
-	return -1;
+	return intel_dp_find_rate(common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
@@ -1542,17 +1548,6 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 	return true;
 }
 
-static int rate_to_index(const int *rates, int len, int rate)
-{
-	int i;
-
-	for (i = 0; i < len; i++)
-		if (rate == rates[i])
-			return i;
-
-	return -1;
-}
-
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
@@ -1568,8 +1563,8 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 {
-	int i = rate_to_index(intel_dp->sink_rates, intel_dp->num_sink_rates,
-			      rate);
+	int i = intel_dp_find_rate(intel_dp->sink_rates,
+				   intel_dp->num_sink_rates, rate);
 
Quoted 4 lines
Quoted 3 lines

drivers/gpu/drm/i915/intel_dp.c intel_dp_max_link_rate(struct intel_dp *intel_dp) · line 1570

Quoted 2 lines
drivers/gpu/drm/i915/intel_dp.c +0 -0
 	if (WARN_ON(i < 0))
 		i = 0;

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#7 lore raw

PATCH 4/13 drm/i915/dp: cache source rates at init

In reply to Jani Nikula

We need the source rates array so often that it makes sense to set it once at init. This reduces function calls when we need the rates, making the code easier to follow.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 35 +++++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_drv.h |  3 +++
 2 files changed, 24 insertions(+), 14 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +21 -14
index f3068ff670a1..cc2523363c8d 100644
@@ -218,21 +218,25 @@ intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
 	return (intel_dp->max_sink_link_bw >> 3) + 1;
 }
 
-static int
-intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
+static void
+intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	const int *source_rates;
 	int size;
 
+	/* This should only be done once */
+	WARN_ON(intel_dp->source_rates || intel_dp->num_source_rates);
+
 	if (IS_GEN9_LP(dev_priv)) {
-		*source_rates = bxt_rates;
+		source_rates = bxt_rates;
 		size = ARRAY_SIZE(bxt_rates);
 	} else if (IS_GEN9_BC(dev_priv)) {
-		*source_rates = skl_rates;
+		source_rates = skl_rates;
 		size = ARRAY_SIZE(skl_rates);
 	} else {
-		*source_rates = default_rates;
+		source_rates = default_rates;
 		size = ARRAY_SIZE(default_rates);
 	}
 
@@ -240,7 +244,8 @@ intel_dp_source_rates(struct intel_dp *intel_dp, const int **source_rates)
 	if (!intel_dp_source_supports_hbr2(intel_dp))
 		size--;
 
-	return size;
+	intel_dp->source_rates = source_rates;
+	intel_dp->num_source_rates = size;
 }
 
 static int intersect_rates(const int *source_rates, int source_len,
@@ -280,13 +285,13 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *source_rates, *sink_rates;
-	int source_len, sink_len;
+	const int *sink_rates;
+	int sink_len;
 
 	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	source_len = intel_dp_source_rates(intel_dp, &source_rates);
 
-	return intersect_rates(source_rates, source_len,
+	return intersect_rates(intel_dp->source_rates,
+			       intel_dp->num_source_rates,
 			       sink_rates, sink_len,
 			       common_rates);
 }
@@ -1496,16 +1501,16 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *source_rates, *sink_rates;
-	int source_len, sink_len, common_len;
+	const int *sink_rates;
+	int sink_len, common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
 	if ((drm_debug & DRM_UT_KMS) == 0)
 		return;
 
-	source_len = intel_dp_source_rates(intel_dp, &source_rates);
-	snprintf_int_array(str, sizeof(str), source_rates, source_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
 	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
@@ -5919,6 +5924,8 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
 		 intel_dig_port->max_lanes, port_name(port)))
 		return false;
 
+	intel_dp_set_source_rates(intel_dp);
+
 	intel_dp->pps_pipe = INVALID_PIPE;
 	intel_dp->active_pipe = INVALID_PIPE;
 
drivers/gpu/drm/i915/intel_drv.h +3 -0
index 393f24340e74..f132d4aea1ad 100644
@@ -930,6 +930,9 @@ struct intel_dp {
 	uint8_t psr_dpcd[EDP_PSR_RECEIVER_CAP_SIZE];
 	uint8_t downstream_ports[DP_MAX_DOWNSTREAM_PORTS];
 	uint8_t edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE];
+	/* source rates */
+	int num_source_rates;
+	const int *source_rates;
 	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
 	uint8_t num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#8 lore raw

PATCH 5/13 drm/i915/dp: generate and cache sink rate array for all DP, not just eDP 1.4

In reply to Jani Nikula

There is some conflation related to sink rates, making this change more complicated than it would otherwise have to be. There are three changes here that are rather difficult to split up:

1) Use the intel_dp->sink_rates array for all DP, not just eDP 1.4. We initialize it from DPCD on eDP 1.4 like before, but generate it based on DP_MAX_LINK_RATE on others. This reduces code complexity when we need to use the sink rates; they are all always in the sink_rates array.

2) Update the sink rate array whenever we read DPCD, and use the information from there. This increases code readability when we need the sink rates.

3) Disentangle fallback rate limiting from sink rates. In the code, the max rate is a dynamic property of the *link*, not of the *sink*. Do the limiting after intersecting the source and sink rates, which are static properties of the devices.

This paves the way for follow-up refactoring that I've refrained from doing here to keep this change as simple as it possibly can.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c               | 76 ++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h              |  4 +-
 3 files changed, 55 insertions(+), 28 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +51 -25
index cc2523363c8d..d13ce6746542 100644
@@ -133,6 +133,34 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static int intel_dp_num_rates(u8 link_bw_code)
+{
+	switch (link_bw_code) {
+	default:
+		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
+		     link_bw_code);
+	case DP_LINK_BW_1_62:
+		return 1;
+	case DP_LINK_BW_2_7:
+		return 2;
+	case DP_LINK_BW_5_4:
+		return 3;
+	}
+}
+
+/* update sink rates from dpcd */
+static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
+{
+	int i, num_rates;
+
+	num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+	for (i = 0; i < num_rates; i++)
+		intel_dp->sink_rates[i] = default_rates[i];
+
+	intel_dp->num_sink_rates = num_rates;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -205,19 +233,6 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp->max_sink_link_bw >> 3) + 1;
-}
-
 static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
@@ -285,15 +300,22 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *sink_rates;
-	int sink_len;
+	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int i, common_len;
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	common_len = intersect_rates(intel_dp->source_rates,
+				     intel_dp->num_source_rates,
+				     intel_dp->sink_rates,
+				     intel_dp->num_sink_rates,
+				     common_rates);
 
-	return intersect_rates(intel_dp->source_rates,
-			       intel_dp->num_source_rates,
-			       sink_rates, sink_len,
-			       common_rates);
+	/* Limit results by potentially reduced max rate */
+	for (i = 0; i < common_len; i++) {
+		if (common_rates[common_len - i - 1] <= max_rate)
+			return common_len - i;
+	}
+
+	return 0;
 }
 
 static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
@@ -1501,8 +1523,7 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *sink_rates;
-	int sink_len, common_len;
+	int common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
@@ -1513,8 +1534,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	snprintf_int_array(str, sizeof(str), sink_rates, sink_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
@@ -1580,7 +1601,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   uint8_t *link_bw, uint8_t *rate_select)
 {
-	if (intel_dp->num_sink_rates) {
+	/* eDP 1.4 rate select method. */
+	if (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03) {
 		*link_bw = 0;
 		*rate_select =
 			intel_dp_rate_select(intel_dp, port_clock);
@@ -3713,6 +3735,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 			intel_dp->sink_rates[i] = (val * 200) / 10;
 		}
 		intel_dp->num_sink_rates = i;
+	} else {
+		intel_dp_set_sink_rates(intel_dp);
 	}
 
 	return true;
@@ -3725,6 +3749,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!intel_dp_read_dpcd(intel_dp))
 		return false;
 
+	intel_dp_set_sink_rates(intel_dp);
+
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
 		return false;
drivers/gpu/drm/i915/intel_dp_link_training.c +2 -1
index 0048b520baf7..694ad0ffb523 100644
@@ -146,7 +146,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
 
-	if (intel_dp->num_sink_rates)
+	/* eDP 1.4 rate select method. */
+	if (!link_bw)
 		drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
 				  &rate_select, 1);
 
drivers/gpu/drm/i915/intel_drv.h +2 -2
index f132d4aea1ad..b914dd543362 100644
@@ -933,8 +933,8 @@ struct intel_dp {
 	/* source rates */
 	int num_source_rates;
 	const int *source_rates;
-	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
-	uint8_t num_sink_rates;
+	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
+	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#9 lore raw

Re: [PATCH v1½ 05/13] drm/i915/dp: generate and cache sink rate array for all DP, not just eDP 1.4

Quoted 142 lines · Jani Nikula

There is some conflation related to sink rates, making this change more complicated than it would otherwise have to be. There are three changes here that are rather difficult to split up:

1) Use the intel_dp->sink_rates array for all DP, not just eDP 1.4. We initialize it from DPCD on eDP 1.4 like before, but generate it based on DP_MAX_LINK_RATE on others. This reduces code complexity when we need to use the sink rates; they are all always in the sink_rates array.

2) Update the sink rate array whenever we read DPCD, and use the information from there. This increases code readability when we need the sink rates.

3) Disentangle fallback rate limiting from sink rates. In the code, the max rate is a dynamic property of the *link*, not of the *sink*. Do the limiting after intersecting the source and sink rates, which are static properties of the devices.

This paves the way for follow-up refactoring that I've refrained from doing here to keep this change as simple as it possibly can.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c               | 76 ++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h              |  4 +-
 3 files changed, 55 insertions(+), 28 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +45 -24
index cc2523363c8d..d13ce6746542 100644
@@ -133,6 +133,34 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static int intel_dp_num_rates(u8 link_bw_code)
+{
+	switch (link_bw_code) {
+	default:
+		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
+		     link_bw_code);
+	case DP_LINK_BW_1_62:
+		return 1;
+	case DP_LINK_BW_2_7:
+		return 2;
+	case DP_LINK_BW_5_4:
+		return 3;
+	}
+}
+
+/* update sink rates from dpcd */
+static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
+{
+	int i, num_rates;
+
+	num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+	for (i = 0; i < num_rates; i++)
+		intel_dp->sink_rates[i] = default_rates[i];
+
+	intel_dp->num_sink_rates = num_rates;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -205,19 +233,6 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp->max_sink_link_bw >> 3) + 1;
-}
-
 static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
@@ -285,15 +300,22 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *sink_rates;
-	int sink_len;
+	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int i, common_len;
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	common_len = intersect_rates(intel_dp->source_rates,
+				     intel_dp->num_source_rates,
+				     intel_dp->sink_rates,
+				     intel_dp->num_sink_rates,
+				     common_rates);
 
-	return intersect_rates(intel_dp->source_rates,
-			       intel_dp->num_source_rates,
-			       sink_rates, sink_len,
-			       common_rates);
+	/* Limit results by potentially reduced max rate */
+	for (i = 0; i < common_len; i++) {
+		if (common_rates[common_len - i - 1] <= max_rate)
+			return common_len - i;
+	}
+
+	return 0;
 }
 
 static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
@@ -1501,8 +1523,7 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *sink_rates;
-	int sink_len, common_len;
+	int common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
@@ -1513,8 +1534,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	snprintf_int_array(str, sizeof(str), sink_rates, sink_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);

drivers/gpu/drm/i915/intel_dp.c int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) · line 1605

Quoted 6 lines
drivers/gpu/drm/i915/intel_dp.c +2 -1
@@ -1580,7 +1601,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   uint8_t *link_bw, uint8_t *rate_select)
 {
-	if (intel_dp->num_sink_rates) {
+	/* eDP 1.4 rate select method. */
+	if (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03) {

I was convinced that this wasn't a mandatory feature, but the spec does seem to say "The table must contain at least one non-zero value at the first (lowest DPCD address) location."

But given historical evidence I'm still 99% convinced we'll eventually run into some panel somewhere that does this wrong, so I don't really like this idea.

Quoted 52 lines
drivers/gpu/drm/i915/intel_dp.c +4 -0
 		*link_bw = 0;
 		*rate_select =
 			intel_dp_rate_select(intel_dp, port_clock);
@@ -3713,6 +3735,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 			intel_dp->sink_rates[i] = (val * 200) / 10;
 		}
 		intel_dp->num_sink_rates = i;
+	} else {
+		intel_dp_set_sink_rates(intel_dp);
 	}
 
 	return true;
@@ -3725,6 +3749,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!intel_dp_read_dpcd(intel_dp))
 		return false;
 
+	intel_dp_set_sink_rates(intel_dp);
+
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
 		return false;
drivers/gpu/drm/i915/intel_dp_link_training.c +2 -1
index 0048b520baf7..694ad0ffb523 100644
@@ -146,7 +146,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
 
-	if (intel_dp->num_sink_rates)
+	/* eDP 1.4 rate select method. */
+	if (!link_bw)
 		drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
 				  &rate_select, 1);
 
drivers/gpu/drm/i915/intel_drv.h +2 -2
index f132d4aea1ad..b914dd543362 100644
@@ -933,8 +933,8 @@ struct intel_dp {
 	/* source rates */
 	int num_source_rates;
 	const int *source_rates;
-	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
-	uint8_t num_sink_rates;
+	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
+	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
Signature · 1 line
2.1.4
Signature · 6 lines
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#10 lore raw

Re: [PATCH v1½ 05/13] drm/i915/dp: generate and cache sink rate array for all DP, not just eDP 1.4

Quoted 154 lines · Ville Syrjälä
Quoted 142 lines · Jani Nikula

There is some conflation related to sink rates, making this change more complicated than it would otherwise have to be. There are three changes here that are rather difficult to split up:

1) Use the intel_dp->sink_rates array for all DP, not just eDP 1.4. We initialize it from DPCD on eDP 1.4 like before, but generate it based on DP_MAX_LINK_RATE on others. This reduces code complexity when we need to use the sink rates; they are all always in the sink_rates array.

2) Update the sink rate array whenever we read DPCD, and use the information from there. This increases code readability when we need the sink rates.

3) Disentangle fallback rate limiting from sink rates. In the code, the max rate is a dynamic property of the *link*, not of the *sink*. Do the limiting after intersecting the source and sink rates, which are static properties of the devices.

This paves the way for follow-up refactoring that I've refrained from doing here to keep this change as simple as it possibly can.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c               | 76 ++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h              |  4 +-
 3 files changed, 55 insertions(+), 28 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +45 -24
index cc2523363c8d..d13ce6746542 100644
@@ -133,6 +133,34 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static int intel_dp_num_rates(u8 link_bw_code)
+{
+	switch (link_bw_code) {
+	default:
+		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
+		     link_bw_code);
+	case DP_LINK_BW_1_62:
+		return 1;
+	case DP_LINK_BW_2_7:
+		return 2;
+	case DP_LINK_BW_5_4:
+		return 3;
+	}
+}
+
+/* update sink rates from dpcd */
+static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
+{
+	int i, num_rates;
+
+	num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+	for (i = 0; i < num_rates; i++)
+		intel_dp->sink_rates[i] = default_rates[i];
+
+	intel_dp->num_sink_rates = num_rates;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -205,19 +233,6 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp->max_sink_link_bw >> 3) + 1;
-}
-
 static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
@@ -285,15 +300,22 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *sink_rates;
-	int sink_len;
+	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int i, common_len;
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	common_len = intersect_rates(intel_dp->source_rates,
+				     intel_dp->num_source_rates,
+				     intel_dp->sink_rates,
+				     intel_dp->num_sink_rates,
+				     common_rates);
 
-	return intersect_rates(intel_dp->source_rates,
-			       intel_dp->num_source_rates,
-			       sink_rates, sink_len,
-			       common_rates);
+	/* Limit results by potentially reduced max rate */
+	for (i = 0; i < common_len; i++) {
+		if (common_rates[common_len - i - 1] <= max_rate)
+			return common_len - i;
+	}
+
+	return 0;
 }
 
 static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
@@ -1501,8 +1523,7 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *sink_rates;
-	int sink_len, common_len;
+	int common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
@@ -1513,8 +1534,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	snprintf_int_array(str, sizeof(str), sink_rates, sink_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);

drivers/gpu/drm/i915/intel_dp.c int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) · line 1605

Quoted 6 lines
drivers/gpu/drm/i915/intel_dp.c +2 -1
@@ -1580,7 +1601,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   uint8_t *link_bw, uint8_t *rate_select)
 {
-	if (intel_dp->num_sink_rates) {
+	/* eDP 1.4 rate select method. */
+	if (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03) {

I was convinced that this wasn't a mandatory feature, but the spec does seem to say "The table must contain at least one non-zero value at the first (lowest DPCD address) location."

Quoted 3 lines

But given historical evidence I'm still 99% convinced we'll eventually run into some panel somewhere that does this wrong, so I don't really like this idea.

Then I think this should be fixed in intel_edp_init_dpcd() by a) checking that there is at least one non-zero value, falling back to intel_dp_set_source_rates() if not, and b) setting a new intel_dp->use_rate_selet field at that time, which will be used instead of (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03). Sound good?

BR,
Jani.

Quoted 53 lines
Quoted 53 lines
drivers/gpu/drm/i915/intel_dp.c +4 -0
 		*link_bw = 0;
 		*rate_select =
 			intel_dp_rate_select(intel_dp, port_clock);
@@ -3713,6 +3735,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 			intel_dp->sink_rates[i] = (val * 200) / 10;
 		}
 		intel_dp->num_sink_rates = i;
+	} else {
+		intel_dp_set_sink_rates(intel_dp);
 	}
 
 	return true;
@@ -3725,6 +3749,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!intel_dp_read_dpcd(intel_dp))
 		return false;
 
+	intel_dp_set_sink_rates(intel_dp);
+
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
 		return false;
drivers/gpu/drm/i915/intel_dp_link_training.c +2 -1
index 0048b520baf7..694ad0ffb523 100644
@@ -146,7 +146,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
 
-	if (intel_dp->num_sink_rates)
+	/* eDP 1.4 rate select method. */
+	if (!link_bw)
 		drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
 				  &rate_select, 1);
 
drivers/gpu/drm/i915/intel_drv.h +2 -2
index f132d4aea1ad..b914dd543362 100644
@@ -933,8 +933,8 @@ struct intel_dp {
 	/* source rates */
 	int num_source_rates;
 	const int *source_rates;
-	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
-	uint8_t num_sink_rates;
+	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
+	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
Signature · 1 line
2.1.4
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#11 lore raw

Re: [PATCH v1½ 05/13] drm/i915/dp: generate and cache sink rate array for all DP, not just eDP 1.4

Quoted 159 lines · Jani Nikula
Quoted 154 lines · Ville Syrjälä
Quoted 142 lines · Jani Nikula

There is some conflation related to sink rates, making this change more complicated than it would otherwise have to be. There are three changes here that are rather difficult to split up:

1) Use the intel_dp->sink_rates array for all DP, not just eDP 1.4. We initialize it from DPCD on eDP 1.4 like before, but generate it based on DP_MAX_LINK_RATE on others. This reduces code complexity when we need to use the sink rates; they are all always in the sink_rates array.

2) Update the sink rate array whenever we read DPCD, and use the information from there. This increases code readability when we need the sink rates.

3) Disentangle fallback rate limiting from sink rates. In the code, the max rate is a dynamic property of the *link*, not of the *sink*. Do the limiting after intersecting the source and sink rates, which are static properties of the devices.

This paves the way for follow-up refactoring that I've refrained from doing here to keep this change as simple as it possibly can.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c               | 76 ++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h              |  4 +-
 3 files changed, 55 insertions(+), 28 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +45 -24
index cc2523363c8d..d13ce6746542 100644
@@ -133,6 +133,34 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static int intel_dp_num_rates(u8 link_bw_code)
+{
+	switch (link_bw_code) {
+	default:
+		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
+		     link_bw_code);
+	case DP_LINK_BW_1_62:
+		return 1;
+	case DP_LINK_BW_2_7:
+		return 2;
+	case DP_LINK_BW_5_4:
+		return 3;
+	}
+}
+
+/* update sink rates from dpcd */
+static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
+{
+	int i, num_rates;
+
+	num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+	for (i = 0; i < num_rates; i++)
+		intel_dp->sink_rates[i] = default_rates[i];
+
+	intel_dp->num_sink_rates = num_rates;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -205,19 +233,6 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp->max_sink_link_bw >> 3) + 1;
-}
-
 static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
@@ -285,15 +300,22 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *sink_rates;
-	int sink_len;
+	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int i, common_len;
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	common_len = intersect_rates(intel_dp->source_rates,
+				     intel_dp->num_source_rates,
+				     intel_dp->sink_rates,
+				     intel_dp->num_sink_rates,
+				     common_rates);
 
-	return intersect_rates(intel_dp->source_rates,
-			       intel_dp->num_source_rates,
-			       sink_rates, sink_len,
-			       common_rates);
+	/* Limit results by potentially reduced max rate */
+	for (i = 0; i < common_len; i++) {
+		if (common_rates[common_len - i - 1] <= max_rate)
+			return common_len - i;
+	}
+
+	return 0;
 }
 
 static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
@@ -1501,8 +1523,7 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *sink_rates;
-	int sink_len, common_len;
+	int common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
@@ -1513,8 +1534,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	snprintf_int_array(str, sizeof(str), sink_rates, sink_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);

drivers/gpu/drm/i915/intel_dp.c int intel_dp_rate_select(struct intel_dp *intel_dp, int rate) · line 1605

Quoted 6 lines
drivers/gpu/drm/i915/intel_dp.c +2 -1
@@ -1580,7 +1601,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   uint8_t *link_bw, uint8_t *rate_select)
 {
-	if (intel_dp->num_sink_rates) {
+	/* eDP 1.4 rate select method. */
+	if (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03) {

I was convinced that this wasn't a mandatory feature, but the spec does seem to say "The table must contain at least one non-zero value at the first (lowest DPCD address) location."

Quoted 3 lines

But given historical evidence I'm still 99% convinced we'll eventually run into some panel somewhere that does this wrong, so I don't really like this idea.

Quoted 5 lines

Then I think this should be fixed in intel_edp_init_dpcd() by a) checking that there is at least one non-zero value, falling back to intel_dp_set_source_rates() if not, and b) setting a new intel_dp->use_rate_selet field at that time, which will be used instead of (is_edp(intel_dp) && intel_dp->edp_dpcd[0] >= 0x03). Sound good?

Yep. That should preserve the current behaviour.

Signature · 6 lines
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#12 lore raw

PATCH v2 1/1 drm/i915/dp: generate and cache sink rate array for all DP, not just eDP 1.4

In reply to Jani Nikula

There is some conflation related to sink rates, making this change more complicated than it would otherwise have to be. There are three changes here that are rather difficult to split up:

1) Use the intel_dp->sink_rates array for all DP, not just eDP 1.4. We initialize it from DPCD on eDP 1.4 like before, but generate it based on DP_MAX_LINK_RATE on others. This reduces code complexity when we need to use the sink rates; they are all always in the sink_rates array.

2) Update the sink rate array whenever we read DPCD, and use the information from there. This increases code readability when we need the sink rates.

3) Disentangle fallback rate limiting from sink rates. In the code, the max rate is a dynamic property of the *link*, not of the *sink*. Do the limiting after intersecting the source and sink rates, which are static properties of the devices.

This paves the way for follow-up refactoring that I've refrained from doing here to keep this change as simple as it possibly can.

v2: introduce use_rate_select and handle non-confirming eDP (Ville)

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c               | 79 ++++++++++++++++++---------
 drivers/gpu/drm/i915/intel_dp_link_training.c |  3 +-
 drivers/gpu/drm/i915/intel_drv.h              |  5 +-
 3 files changed, 59 insertions(+), 28 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +54 -25
index 2e0592377cab..ec89e1fcd641 100644
@@ -133,6 +133,34 @@ static void vlv_steal_power_sequencer(struct drm_device *dev,
 				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
+static int intel_dp_num_rates(u8 link_bw_code)
+{
+	switch (link_bw_code) {
+	default:
+		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
+		     link_bw_code);
+	case DP_LINK_BW_1_62:
+		return 1;
+	case DP_LINK_BW_2_7:
+		return 2;
+	case DP_LINK_BW_5_4:
+		return 3;
+	}
+}
+
+/* update sink rates from dpcd */
+static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
+{
+	int i, num_rates;
+
+	num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]);
+
+	for (i = 0; i < num_rates; i++)
+		intel_dp->sink_rates[i] = default_rates[i];
+
+	intel_dp->num_sink_rates = num_rates;
+}
+
 static int
 intel_dp_max_link_bw(struct intel_dp  *intel_dp)
 {
@@ -205,19 +233,6 @@ intel_dp_downstream_max_dotclock(struct intel_dp *intel_dp)
 	return max_dotclk;
 }
 
-static int
-intel_dp_sink_rates(struct intel_dp *intel_dp, const int **sink_rates)
-{
-	if (intel_dp->num_sink_rates) {
-		*sink_rates = intel_dp->sink_rates;
-		return intel_dp->num_sink_rates;
-	}
-
-	*sink_rates = default_rates;
-
-	return (intel_dp->max_sink_link_bw >> 3) + 1;
-}
-
 static void
 intel_dp_set_source_rates(struct intel_dp *intel_dp)
 {
@@ -285,15 +300,22 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	const int *sink_rates;
-	int sink_len;
+	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int i, common_len;
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
+	common_len = intersect_rates(intel_dp->source_rates,
+				     intel_dp->num_source_rates,
+				     intel_dp->sink_rates,
+				     intel_dp->num_sink_rates,
+				     common_rates);
 
-	return intersect_rates(intel_dp->source_rates,
-			       intel_dp->num_source_rates,
-			       sink_rates, sink_len,
-			       common_rates);
+	/* Limit results by potentially reduced max rate */
+	for (i = 0; i < common_len; i++) {
+		if (common_rates[common_len - i - 1] <= max_rate)
+			return common_len - i;
+	}
+
+	return 0;
 }
 
 static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
@@ -1501,8 +1523,7 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	const int *sink_rates;
-	int sink_len, common_len;
+	int common_len;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
@@ -1513,8 +1534,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->source_rates, intel_dp->num_source_rates);
 	DRM_DEBUG_KMS("source rates: %s\n", str);
 
-	sink_len = intel_dp_sink_rates(intel_dp, &sink_rates);
-	snprintf_int_array(str, sizeof(str), sink_rates, sink_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
 	common_len = intel_dp_common_rates(intel_dp, common_rates);
@@ -1580,7 +1601,8 @@ int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
 void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
 			   uint8_t *link_bw, uint8_t *rate_select)
 {
-	if (intel_dp->num_sink_rates) {
+	/* eDP 1.4 rate select method. */
+	if (intel_dp->use_rate_select) {
 		*link_bw = 0;
 		*rate_select =
 			intel_dp_rate_select(intel_dp, port_clock);
@@ -3717,6 +3739,11 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 		intel_dp->num_sink_rates = i;
 	}
 
+	if (intel_dp->num_sink_rates)
+		intel_dp->use_rate_select = true;
+	else
+		intel_dp_set_sink_rates(intel_dp);
+
 	return true;
 }
 
@@ -3727,6 +3754,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	if (!intel_dp_read_dpcd(intel_dp))
 		return false;
 
+	intel_dp_set_sink_rates(intel_dp);
+
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
 		return false;
drivers/gpu/drm/i915/intel_dp_link_training.c +2 -1
index 0048b520baf7..694ad0ffb523 100644
@@ -146,7 +146,8 @@ intel_dp_link_training_clock_recovery(struct intel_dp *intel_dp)
 		link_config[1] |= DP_LANE_COUNT_ENHANCED_FRAME_EN;
 	drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_BW_SET, link_config, 2);
 
-	if (intel_dp->num_sink_rates)
+	/* eDP 1.4 rate select method. */
+	if (!link_bw)
 		drm_dp_dpcd_write(&intel_dp->aux, DP_LINK_RATE_SET,
 				  &rate_select, 1);
 
drivers/gpu/drm/i915/intel_drv.h +3 -2
index f132d4aea1ad..3a6f092a2ec3 100644
@@ -933,9 +933,10 @@ struct intel_dp {
 	/* source rates */
 	int num_source_rates;
 	const int *source_rates;
-	/* sink rates as reported by DP_SUPPORTED_LINK_RATES */
-	uint8_t num_sink_rates;
+	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
+	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
+	bool use_rate_select;
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
 	/* Max link BW for the sink as per DPCD registers */
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#13 lore raw

PATCH 6/13 drm/i915/dp: use the sink rates array for max sink rates

In reply to Jani Nikula

Looking at DPCD DP_MAX_LINK_RATE may be completely bogus for eDP 1.4 which is allowed to use link rate select method and have 0 in max link rate. With this change, it makes sense to store the max rate as the actual rate rather than as a bw code.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 28 +++++++---------------------
 drivers/gpu/drm/i915/intel_drv.h |  2 +-
 2 files changed, 8 insertions(+), 22 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +7 -21
index d13ce6746542..f163391e61fa 100644
@@ -161,23 +161,9 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
 	intel_dp->num_sink_rates = num_rates;
 }
 
-static int
-intel_dp_max_link_bw(struct intel_dp  *intel_dp)
+static int intel_dp_max_sink_rate(struct intel_dp *intel_dp)
 {
-	int max_link_bw = intel_dp->dpcd[DP_MAX_LINK_RATE];
-
-	switch (max_link_bw) {
-	case DP_LINK_BW_1_62:
-	case DP_LINK_BW_2_7:
-	case DP_LINK_BW_5_4:
-		break;
-	default:
-		WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n",
-		     max_link_bw);
-		max_link_bw = DP_LINK_BW_1_62;
-		break;
-	}
-	return max_link_bw;
+	return intel_dp->sink_rates[intel_dp->num_sink_rates - 1];
 }
 
 static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp)
@@ -300,7 +286,7 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 static int intel_dp_common_rates(struct intel_dp *intel_dp,
 				 int *common_rates)
 {
-	int max_rate = drm_dp_bw_code_to_link_rate(intel_dp->max_sink_link_bw);
+	int max_rate = intel_dp->max_sink_link_rate;
 	int i, common_len;
 
 	common_len = intersect_rates(intel_dp->source_rates,
@@ -338,10 +324,10 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 						   common_rates,
 						   link_rate);
 	if (link_rate_index > 0) {
-		intel_dp->max_sink_link_bw = drm_dp_link_rate_to_bw_code(common_rates[link_rate_index - 1]);
+		intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1];
 		intel_dp->max_sink_lane_count = lane_count;
 	} else if (lane_count > 1) {
-		intel_dp->max_sink_link_bw = intel_dp_max_link_bw(intel_dp);
+		intel_dp->max_sink_link_rate = intel_dp_max_sink_rate(intel_dp);
 		intel_dp->max_sink_lane_count = lane_count >> 1;
 	} else {
 		DRM_ERROR("Link Training Unsuccessful\n");
@@ -4657,8 +4643,8 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 	/* Set the max lane count for sink */
 	intel_dp->max_sink_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
 
-	/* Set the max link BW for sink */
-	intel_dp->max_sink_link_bw = intel_dp_max_link_bw(intel_dp);
+	/* Set the max link rate for sink */
+	intel_dp->max_sink_link_rate = intel_dp_max_sink_rate(intel_dp);
 
 	intel_dp_print_rates(intel_dp);
 
drivers/gpu/drm/i915/intel_drv.h +1 -1
index b914dd543362..ae7259eda420 100644
@@ -939,7 +939,7 @@ struct intel_dp {
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
 	/* Max link BW for the sink as per DPCD registers */
-	int max_sink_link_bw;
+	int max_sink_link_rate;
 	/* sink or branch descriptor */
 	struct intel_dp_desc desc;
 	struct drm_dp_aux aux;
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#14 lore raw

PATCH 7/13 drm/i915/dp: cache common rates with sink rates

In reply to Jani Nikula

Now that source rates are static and sink rates are updated whenever DPCD is updated, we can do and cache the intersection of them whenever sink rates are updated. This reduces code complexity, as we don't have to keep calling the functions to intersect. We also get rid of several common rates arrays on stack.

Limiting the common rates by a max link rate can be done by picking the first N elements of the cached common rates.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 66 ++++++++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_drv.h |  3 ++
 2 files changed, 40 insertions(+), 29 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +37 -29
index f163391e61fa..7d3ff92000c3 100644
@@ -283,17 +283,29 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 	return -1;
 }
 
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
-				 int *common_rates)
+static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
 {
-	int max_rate = intel_dp->max_sink_link_rate;
-	int i, common_len;
+	WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates);
 
-	common_len = intersect_rates(intel_dp->source_rates,
-				     intel_dp->num_source_rates,
-				     intel_dp->sink_rates,
-				     intel_dp->num_sink_rates,
-				     common_rates);
+	intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates,
+						     intel_dp->num_source_rates,
+						     intel_dp->sink_rates,
+						     intel_dp->num_sink_rates,
+						     intel_dp->common_rates);
+
+	/* Paranoia, there should always be something in common. */
+	if (WARN_ON(intel_dp->num_common_rates == 0)) {
+		intel_dp->common_rates[0] = default_rates[0];
+		intel_dp->num_common_rates = 1;
+	}
+}
+
+/* get length of common rates potentially limited by max_rate */
+static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp,
+					  int max_rate)
+{
+	const int *common_rates = intel_dp->common_rates;
+	int i, common_len = intel_dp->num_common_rates;
 
 	/* Limit results by potentially reduced max rate */
 	for (i = 0; i < common_len; i++) {
@@ -304,25 +316,23 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
-				    int *common_rates, int link_rate)
+static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int link_rate)
 {
 	int common_len;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
-	return intel_dp_find_rate(common_rates, common_len, link_rate);
+	return intel_dp_find_rate(intel_dp->common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 					    int link_rate, uint8_t lane_count)
 {
-	int common_rates[DP_MAX_SUPPORTED_RATES];
+	const int *common_rates = intel_dp->common_rates;
 	int link_rate_index;
 
-	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
-						   link_rate);
+	link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate);
 	if (link_rate_index > 0) {
 		intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1];
 		intel_dp->max_sink_lane_count = lane_count;
@@ -1509,8 +1519,6 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	int common_len;
-	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
 	if ((drm_debug & DRM_UT_KMS) == 0)
@@ -1524,8 +1532,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	snprintf_int_array(str, sizeof(str), common_rates, common_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->common_rates, intel_dp->num_common_rates);
 	DRM_DEBUG_KMS("common rates: %s\n", str);
 }
 
@@ -1563,14 +1571,14 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
-	int rates[DP_MAX_SUPPORTED_RATES] = {};
 	int len;
 
-	len = intel_dp_common_rates(intel_dp, rates);
+	len = intel_dp_common_len_rate_limit(intel_dp,
+					     intel_dp->max_sink_link_rate);
 	if (WARN_ON(len <= 0))
 		return 162000;
 
-	return rates[len - 1];
+	return intel_dp->common_rates[len - 1];
 }
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
@@ -1639,11 +1647,12 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
+	const int *common_rates = intel_dp->common_rates;
 	int common_len;
 	uint8_t link_bw, rate_select;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
 	/* No common link rates between source and sink */
 	WARN_ON(common_len <= 0);
@@ -1681,7 +1690,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
 		link_rate_index = intel_dp_link_rate_index(intel_dp,
-							   common_rates,
 							   intel_dp->compliance.test_link_rate);
 		if (link_rate_index >= 0)
 			min_clock = max_clock = link_rate_index;
@@ -3724,6 +3732,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 	} else {
 		intel_dp_set_sink_rates(intel_dp);
 	}
+	intel_dp_set_common_rates(intel_dp);
 
 	return true;
 }
@@ -3736,6 +3745,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 		return false;
 
 	intel_dp_set_sink_rates(intel_dp);
+	intel_dp_set_common_rates(intel_dp);
 
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
@@ -3958,7 +3968,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
 	int status = 0;
 	int min_lane_count = 1;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
 	int link_rate_index, test_link_rate;
 	uint8_t test_lane_count, test_link_bw;
 	/* (DP CTS 1.2)
@@ -3987,7 +3996,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 	/* Validate the requested link rate */
 	test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
 	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
 						   test_link_rate);
 	if (link_rate_index < 0)
 		return DP_TEST_NAK;
drivers/gpu/drm/i915/intel_drv.h +3 -0
index ae7259eda420..3578a7dd584a 100644
@@ -936,6 +936,9 @@ struct intel_dp {
 	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
 	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
+	/* intersection of source and sink rates */
+	int num_common_rates;
+	int common_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
 	/* Max link BW for the sink as per DPCD registers */
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#15 lore raw

Re: [PATCH v1½ 07/13] drm/i915/dp: cache common rates with sink rates

Quoted 33 lines · Jani Nikula

Now that source rates are static and sink rates are updated whenever DPCD is updated, we can do and cache the intersection of them whenever sink rates are updated. This reduces code complexity, as we don't have to keep calling the functions to intersect. We also get rid of several common rates arrays on stack.

Limiting the common rates by a max link rate can be done by picking the first N elements of the cached common rates.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 66 ++++++++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_drv.h |  3 ++
 2 files changed, 40 insertions(+), 29 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +2 -4
index f163391e61fa..7d3ff92000c3 100644
@@ -283,17 +283,29 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 	return -1;
 }
 
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
-				 int *common_rates)
+static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
 {
-	int max_rate = intel_dp->max_sink_link_rate;
-	int i, common_len;
+	WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates);
 

drivers/gpu/drm/i915/intel_dp.c static int intel_dp_find_rate(const int *rates, int len, int rate) · line 294

Quoted 10 lines
drivers/gpu/drm/i915/intel_dp.c +5 -5
-	common_len = intersect_rates(intel_dp->source_rates,
-				     intel_dp->num_source_rates,
-				     intel_dp->sink_rates,
-				     intel_dp->num_sink_rates,
-				     common_rates);
+	intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates,
+						     intel_dp->num_source_rates,
+						     intel_dp->sink_rates,
+						     intel_dp->num_sink_rates,
+						     intel_dp->common_rates);

Do we need to pass all these args given that all of them are now available in intel_dp and intersect_rates() is not used anywhere else?

-DK

Quoted 147 lines
drivers/gpu/drm/i915/intel_dp.c +30 -20
+
+	/* Paranoia, there should always be something in common. */
+	if (WARN_ON(intel_dp->num_common_rates == 0)) {
+		intel_dp->common_rates[0] = default_rates[0];
+		intel_dp->num_common_rates = 1;
+	}
+}
+
+/* get length of common rates potentially limited by max_rate */
+static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp,
+					  int max_rate)
+{
+	const int *common_rates = intel_dp->common_rates;
+	int i, common_len = intel_dp->num_common_rates;
 
 	/* Limit results by potentially reduced max rate */
 	for (i = 0; i < common_len; i++) {
@@ -304,25 +316,23 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
-				    int *common_rates, int link_rate)
+static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int link_rate)
 {
 	int common_len;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
-	return intel_dp_find_rate(common_rates, common_len, link_rate);
+	return intel_dp_find_rate(intel_dp->common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 					    int link_rate, uint8_t lane_count)
 {
-	int common_rates[DP_MAX_SUPPORTED_RATES];
+	const int *common_rates = intel_dp->common_rates;
 	int link_rate_index;
 
-	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
-						   link_rate);
+	link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate);
 	if (link_rate_index > 0) {
 		intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1];
 		intel_dp->max_sink_lane_count = lane_count;
@@ -1509,8 +1519,6 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	int common_len;
-	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
 	if ((drm_debug & DRM_UT_KMS) == 0)
@@ -1524,8 +1532,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	snprintf_int_array(str, sizeof(str), common_rates, common_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->common_rates, intel_dp->num_common_rates);
 	DRM_DEBUG_KMS("common rates: %s\n", str);
 }
 
@@ -1563,14 +1571,14 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
-	int rates[DP_MAX_SUPPORTED_RATES] = {};
 	int len;
 
-	len = intel_dp_common_rates(intel_dp, rates);
+	len = intel_dp_common_len_rate_limit(intel_dp,
+					     intel_dp->max_sink_link_rate);
 	if (WARN_ON(len <= 0))
 		return 162000;
 
-	return rates[len - 1];
+	return intel_dp->common_rates[len - 1];
 }
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
@@ -1639,11 +1647,12 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
+	const int *common_rates = intel_dp->common_rates;
 	int common_len;
 	uint8_t link_bw, rate_select;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
 	/* No common link rates between source and sink */
 	WARN_ON(common_len <= 0);
@@ -1681,7 +1690,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
 		link_rate_index = intel_dp_link_rate_index(intel_dp,
-							   common_rates,
 							   intel_dp->compliance.test_link_rate);
 		if (link_rate_index >= 0)
 			min_clock = max_clock = link_rate_index;
@@ -3724,6 +3732,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 	} else {
 		intel_dp_set_sink_rates(intel_dp);
 	}
+	intel_dp_set_common_rates(intel_dp);
 
 	return true;
 }
@@ -3736,6 +3745,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 		return false;
 
 	intel_dp_set_sink_rates(intel_dp);
+	intel_dp_set_common_rates(intel_dp);
 
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
@@ -3958,7 +3968,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
 	int status = 0;
 	int min_lane_count = 1;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
 	int link_rate_index, test_link_rate;
 	uint8_t test_lane_count, test_link_bw;
 	/* (DP CTS 1.2)
@@ -3987,7 +3996,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 	/* Validate the requested link rate */
 	test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
 	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
 						   test_link_rate);
 	if (link_rate_index < 0)
 		return DP_TEST_NAK;
drivers/gpu/drm/i915/intel_drv.h +0 -0
index ae7259eda420..3578a7dd584a 100644

drivers/gpu/drm/i915/intel_drv.h struct intel_dp { · line 944

Quoted 9 lines
drivers/gpu/drm/i915/intel_drv.h +3 -0
@@ -936,6 +936,9 @@ struct intel_dp {
 	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
 	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
+	/* intersection of source and sink rates */
+	int num_common_rates;
+	int common_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
 	/* Max link BW for the sink as per DPCD registers */

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#16 lore raw

Re: [PATCH v1½ 07/13] drm/i915/dp: cache common rates with sink rates

Quoted 34 lines · Dhinakaran
Quoted 33 lines · Jani Nikula

Now that source rates are static and sink rates are updated whenever DPCD is updated, we can do and cache the intersection of them whenever sink rates are updated. This reduces code complexity, as we don't have to keep calling the functions to intersect. We also get rid of several common rates arrays on stack.

Limiting the common rates by a max link rate can be done by picking the first N elements of the cached common rates.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 66 ++++++++++++++++++++++------------------
 drivers/gpu/drm/i915/intel_drv.h |  3 ++
 2 files changed, 40 insertions(+), 29 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +2 -4
index f163391e61fa..7d3ff92000c3 100644
@@ -283,17 +283,29 @@ static int intel_dp_find_rate(const int *rates, int len, int rate)
 	return -1;
 }
 
-static int intel_dp_common_rates(struct intel_dp *intel_dp,
-				 int *common_rates)
+static void intel_dp_set_common_rates(struct intel_dp *intel_dp)
 {
-	int max_rate = intel_dp->max_sink_link_rate;
-	int i, common_len;
+	WARN_ON(!intel_dp->num_source_rates || !intel_dp->num_sink_rates);
 
Quoted 14 lines

drivers/gpu/drm/i915/intel_dp.c static int intel_dp_find_rate(const int *rates, int len, int rate) · line 294

Quoted 10 lines
drivers/gpu/drm/i915/intel_dp.c +5 -5
-	common_len = intersect_rates(intel_dp->source_rates,
-				     intel_dp->num_source_rates,
-				     intel_dp->sink_rates,
-				     intel_dp->num_sink_rates,
-				     common_rates);
+	intel_dp->num_common_rates = intersect_rates(intel_dp->source_rates,
+						     intel_dp->num_source_rates,
+						     intel_dp->sink_rates,
+						     intel_dp->num_sink_rates,
+						     intel_dp->common_rates);

Do we need to pass all these args given that all of them are now available in intel_dp and intersect_rates() is not used anywhere else?

My reasoning is that with this interface intersect_rates remains generic, independent of intel_dp or anything else, and you can be sure it's stateless.

BR,
Jani.

Quoted 159 lines

-DK

Quoted 156 lines
drivers/gpu/drm/i915/intel_dp.c +30 -20
+
+	/* Paranoia, there should always be something in common. */
+	if (WARN_ON(intel_dp->num_common_rates == 0)) {
+		intel_dp->common_rates[0] = default_rates[0];
+		intel_dp->num_common_rates = 1;
+	}
+}
+
+/* get length of common rates potentially limited by max_rate */
+static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp,
+					  int max_rate)
+{
+	const int *common_rates = intel_dp->common_rates;
+	int i, common_len = intel_dp->num_common_rates;
 
 	/* Limit results by potentially reduced max rate */
 	for (i = 0; i < common_len; i++) {
@@ -304,25 +316,23 @@ static int intel_dp_common_rates(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static int intel_dp_link_rate_index(struct intel_dp *intel_dp,
-				    int *common_rates, int link_rate)
+static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int link_rate)
 {
 	int common_len;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
-	return intel_dp_find_rate(common_rates, common_len, link_rate);
+	return intel_dp_find_rate(intel_dp->common_rates, common_len, link_rate);
 }
 
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 					    int link_rate, uint8_t lane_count)
 {
-	int common_rates[DP_MAX_SUPPORTED_RATES];
+	const int *common_rates = intel_dp->common_rates;
 	int link_rate_index;
 
-	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
-						   link_rate);
+	link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate);
 	if (link_rate_index > 0) {
 		intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1];
 		intel_dp->max_sink_lane_count = lane_count;
@@ -1509,8 +1519,6 @@ static void snprintf_int_array(char *str, size_t len,
 
 static void intel_dp_print_rates(struct intel_dp *intel_dp)
 {
-	int common_len;
-	int common_rates[DP_MAX_SUPPORTED_RATES];
 	char str[128]; /* FIXME: too big for stack? */
 
 	if ((drm_debug & DRM_UT_KMS) == 0)
@@ -1524,8 +1532,8 @@ static void intel_dp_print_rates(struct intel_dp *intel_dp)
 			   intel_dp->sink_rates, intel_dp->num_sink_rates);
 	DRM_DEBUG_KMS("sink rates: %s\n", str);
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
-	snprintf_int_array(str, sizeof(str), common_rates, common_len);
+	snprintf_int_array(str, sizeof(str),
+			   intel_dp->common_rates, intel_dp->num_common_rates);
 	DRM_DEBUG_KMS("common rates: %s\n", str);
 }
 
@@ -1563,14 +1571,14 @@ bool intel_dp_read_desc(struct intel_dp *intel_dp)
 int
 intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
-	int rates[DP_MAX_SUPPORTED_RATES] = {};
 	int len;
 
-	len = intel_dp_common_rates(intel_dp, rates);
+	len = intel_dp_common_len_rate_limit(intel_dp,
+					     intel_dp->max_sink_link_rate);
 	if (WARN_ON(len <= 0))
 		return 162000;
 
-	return rates[len - 1];
+	return intel_dp->common_rates[len - 1];
 }
 
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate)
@@ -1639,11 +1647,12 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
+	const int *common_rates = intel_dp->common_rates;
 	int common_len;
 	uint8_t link_bw, rate_select;
 
-	common_len = intel_dp_common_rates(intel_dp, common_rates);
+	common_len = intel_dp_common_len_rate_limit(intel_dp,
+						    intel_dp->max_sink_link_rate);
 
 	/* No common link rates between source and sink */
 	WARN_ON(common_len <= 0);
@@ -1681,7 +1690,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
 		link_rate_index = intel_dp_link_rate_index(intel_dp,
-							   common_rates,
 							   intel_dp->compliance.test_link_rate);
 		if (link_rate_index >= 0)
 			min_clock = max_clock = link_rate_index;
@@ -3724,6 +3732,7 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 	} else {
 		intel_dp_set_sink_rates(intel_dp);
 	}
+	intel_dp_set_common_rates(intel_dp);
 
 	return true;
 }
@@ -3736,6 +3745,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 		return false;
 
 	intel_dp_set_sink_rates(intel_dp);
+	intel_dp_set_common_rates(intel_dp);
 
 	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
 			     &intel_dp->sink_count, 1) < 0)
@@ -3958,7 +3968,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 {
 	int status = 0;
 	int min_lane_count = 1;
-	int common_rates[DP_MAX_SUPPORTED_RATES] = {};
 	int link_rate_index, test_link_rate;
 	uint8_t test_lane_count, test_link_bw;
 	/* (DP CTS 1.2)
@@ -3987,7 +3996,6 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 	/* Validate the requested link rate */
 	test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
 	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   common_rates,
 						   test_link_rate);
 	if (link_rate_index < 0)
 		return DP_TEST_NAK;
drivers/gpu/drm/i915/intel_drv.h +3 -0
index ae7259eda420..3578a7dd584a 100644
@@ -936,6 +936,9 @@ struct intel_dp {
 	/* sink rates as reported by DP_MAX_LINK_RATE/DP_SUPPORTED_LINK_RATES */
 	int num_sink_rates;
 	int sink_rates[DP_MAX_SUPPORTED_RATES];
+	/* intersection of source and sink rates */
+	int num_common_rates;
+	int common_rates[DP_MAX_SUPPORTED_RATES];
 	/* Max lane count for the sink as per DPCD registers */
 	uint8_t max_sink_lane_count;
 	/* Max link BW for the sink as per DPCD registers */
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#17 lore raw

PATCH 8/13 drm/i915/dp: do not limit rate seek when not needed

In reply to Jani Nikula

In link training fallback, we're trying to find a rate that we know is in a sorted array of common link rates. We don't need to limit the array using the max rate. For test request, the DP CTS doesn't say we should limit the rate based on earlier fallback.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 31 ++++++++++++-------------------
 1 file changed, 12 insertions(+), 19 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +12 -19
index 7d3ff92000c3..6404455a0ab5 100644
@@ -316,25 +316,16 @@ static int intel_dp_common_len_rate_limit(struct intel_dp *intel_dp,
 	return 0;
 }
 
-static int intel_dp_link_rate_index(struct intel_dp *intel_dp, int link_rate)
-{
-	int common_len;
-
-	common_len = intel_dp_common_len_rate_limit(intel_dp,
-						    intel_dp->max_sink_link_rate);
-
-	return intel_dp_find_rate(intel_dp->common_rates, common_len, link_rate);
-}
-
 int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 					    int link_rate, uint8_t lane_count)
 {
-	const int *common_rates = intel_dp->common_rates;
-	int link_rate_index;
+	int index;
 
-	link_rate_index = intel_dp_link_rate_index(intel_dp, link_rate);
-	if (link_rate_index > 0) {
-		intel_dp->max_sink_link_rate = common_rates[link_rate_index - 1];
+	index = intel_dp_find_rate(intel_dp->common_rates,
+				   intel_dp->num_common_rates,
+				   link_rate);
+	if (index > 0) {
+		intel_dp->max_sink_link_rate = intel_dp->common_rates[index - 1];
 		intel_dp->max_sink_lane_count = lane_count;
 	} else if (lane_count > 1) {
 		intel_dp->max_sink_link_rate = intel_dp_max_sink_rate(intel_dp);
@@ -1689,8 +1680,9 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_link_rate_index(intel_dp,
-							   intel_dp->compliance.test_link_rate);
+		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
+						     intel_dp->num_common_rates,
+						     intel_dp->compliance.test_link_rate);
 		if (link_rate_index >= 0)
 			min_clock = max_clock = link_rate_index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
@@ -3995,8 +3987,9 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 	}
 	/* Validate the requested link rate */
 	test_link_rate = drm_dp_bw_code_to_link_rate(test_link_bw);
-	link_rate_index = intel_dp_link_rate_index(intel_dp,
-						   test_link_rate);
+	link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
+					     intel_dp->num_common_rates,
+					     test_link_rate);
 	if (link_rate_index < 0)
 		return DP_TEST_NAK;
 
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#18 lore raw

PATCH 9/13 drm/i915/dp: don't call the link parameters sink parameters

In reply to Jani Nikula

If we modify these on the fly depending on the link conditions, don't pretend they are sink properties.

Some link vs. sink confusion still remains, but we'll take care of them in follow-up patches.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c  | 25 ++++++++++++-------------
 drivers/gpu/drm/i915/intel_drv.h |  8 ++++----
 2 files changed, 16 insertions(+), 17 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +12 -13
index 6404455a0ab5..af99d0926ca5 100644
@@ -172,7 +172,7 @@ static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp)
 	u8 source_max, sink_max;
 
 	source_max = intel_dig_port->max_lanes;
-	sink_max = intel_dp->max_sink_lane_count;
+	sink_max = intel_dp->max_link_lane_count;
 
 	return min(source_max, sink_max);
 }
@@ -325,11 +325,11 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 				   intel_dp->num_common_rates,
 				   link_rate);
 	if (index > 0) {
-		intel_dp->max_sink_link_rate = intel_dp->common_rates[index - 1];
-		intel_dp->max_sink_lane_count = lane_count;
+		intel_dp->max_link_rate = intel_dp->common_rates[index - 1];
+		intel_dp->max_link_lane_count = lane_count;
 	} else if (lane_count > 1) {
-		intel_dp->max_sink_link_rate = intel_dp_max_sink_rate(intel_dp);
-		intel_dp->max_sink_lane_count = lane_count >> 1;
+		intel_dp->max_link_rate = intel_dp_max_sink_rate(intel_dp);
+		intel_dp->max_link_lane_count = lane_count >> 1;
 	} else {
 		DRM_ERROR("Link Training Unsuccessful\n");
 		return -1;
@@ -1564,8 +1564,7 @@ intel_dp_max_link_rate(struct intel_dp *intel_dp)
 {
 	int len;
 
-	len = intel_dp_common_len_rate_limit(intel_dp,
-					     intel_dp->max_sink_link_rate);
+	len = intel_dp_common_len_rate_limit(intel_dp, intel_dp->max_link_rate);
 	if (WARN_ON(len <= 0))
 		return 162000;
 
@@ -1643,7 +1642,7 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	uint8_t link_bw, rate_select;
 
 	common_len = intel_dp_common_len_rate_limit(intel_dp,
-						    intel_dp->max_sink_link_rate);
+						    intel_dp->max_link_rate);
 
 	/* No common link rates between source and sink */
 	WARN_ON(common_len <= 0);
@@ -3976,7 +3975,7 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 	test_lane_count &= DP_MAX_LANE_COUNT_MASK;
 	/* Validate the requested lane count */
 	if (test_lane_count < min_lane_count ||
-	    test_lane_count > intel_dp->max_sink_lane_count)
+	    test_lane_count > intel_dp->max_link_lane_count)
 		return DP_TEST_NAK;
 
 	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_LINK_RATE,
@@ -4641,11 +4640,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
 		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
 
-	/* Set the max lane count for sink */
-	intel_dp->max_sink_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+	/* Set the max lane count for link */
+	intel_dp->max_link_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
 
-	/* Set the max link rate for sink */
-	intel_dp->max_sink_link_rate = intel_dp_max_sink_rate(intel_dp);
+	/* Set the max link rate for link */
+	intel_dp->max_link_rate = intel_dp_max_sink_rate(intel_dp);
 
 	intel_dp_print_rates(intel_dp);
 
drivers/gpu/drm/i915/intel_drv.h +4 -4
index 3578a7dd584a..04868046c84f 100644
@@ -939,10 +939,10 @@ struct intel_dp {
 	/* intersection of source and sink rates */
 	int num_common_rates;
 	int common_rates[DP_MAX_SUPPORTED_RATES];
-	/* Max lane count for the sink as per DPCD registers */
-	uint8_t max_sink_lane_count;
-	/* Max link BW for the sink as per DPCD registers */
-	int max_sink_link_rate;
+	/* Max lane count for the current link */
+	int max_link_lane_count;
+	/* Max rate for the current link */
+	int max_link_rate;
 	/* sink or branch descriptor */
 	struct intel_dp_desc desc;
 	struct drm_dp_aux aux;
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#19 lore raw

PATCH 10/13 drm/i915/dp: add functions for max common link rate and lane count

In reply to Jani Nikula

These are the theoretical maximums common for source and sink. These are the maximums we should start with. They may be degraded in case of link training failures, and the dynamic link values are stored separately.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 29 +++++++++++++++++------------
 1 file changed, 17 insertions(+), 12 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +17 -12
index af99d0926ca5..84b8123a26d3 100644
@@ -161,22 +161,27 @@ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp)
 	intel_dp->num_sink_rates = num_rates;
 }
 
-static int intel_dp_max_sink_rate(struct intel_dp *intel_dp)
+/* Theoretical max between source and sink */
+static int intel_dp_max_common_rate(struct intel_dp *intel_dp)
 {
-	return intel_dp->sink_rates[intel_dp->num_sink_rates - 1];
+	return intel_dp->common_rates[intel_dp->num_common_rates - 1];
 }
 
-static u8 intel_dp_max_lane_count(struct intel_dp *intel_dp)
+/* Theoretical max between source and sink */
+static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
-	u8 source_max, sink_max;
-
-	source_max = intel_dig_port->max_lanes;
-	sink_max = intel_dp->max_link_lane_count;
+	int source_max = intel_dig_port->max_lanes;
+	int sink_max = drm_dp_max_lane_count(intel_dp->dpcd);
 
 	return min(source_max, sink_max);
 }
 
+static int intel_dp_max_lane_count(struct intel_dp *intel_dp)
+{
+	return intel_dp->max_link_lane_count;
+}
+
 int
 intel_dp_link_required(int pixel_clock, int bpp)
 {
@@ -328,7 +333,7 @@ int intel_dp_get_link_train_fallback_values(struct intel_dp *intel_dp,
 		intel_dp->max_link_rate = intel_dp->common_rates[index - 1];
 		intel_dp->max_link_lane_count = lane_count;
 	} else if (lane_count > 1) {
-		intel_dp->max_link_rate = intel_dp_max_sink_rate(intel_dp);
+		intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
 		intel_dp->max_link_lane_count = lane_count >> 1;
 	} else {
 		DRM_ERROR("Link Training Unsuccessful\n");
@@ -4640,11 +4645,11 @@ intel_dp_long_pulse(struct intel_connector *intel_connector)
 		      yesno(intel_dp_source_supports_hbr2(intel_dp)),
 		      yesno(drm_dp_tps3_supported(intel_dp->dpcd)));
 
-	/* Set the max lane count for link */
-	intel_dp->max_link_lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+	/* Initial max link lane count */
+	intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp);
 
-	/* Set the max link rate for link */
-	intel_dp->max_link_rate = intel_dp_max_sink_rate(intel_dp);
+	/* Initial max link rate */
+	intel_dp->max_link_rate = intel_dp_max_common_rate(intel_dp);
 
 	intel_dp_print_rates(intel_dp);
 
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#20 lore raw

PATCH 11/13 drm/i915/mst: use max link not sink lane count

In reply to Jani Nikula

The source might not support as many lanes as the sink, or the link training might have failed at higher lane counts. Take these into account.

Cc Dhinakaran Pandiyan <[email protected]>
Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c     | 2 +-
 drivers/gpu/drm/i915/intel_dp_mst.c | 4 ++--
 drivers/gpu/drm/i915/intel_drv.h    | 1 +
 3 files changed, 4 insertions(+), 3 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +1 -1
index 84b8123a26d3..7704d32286a3 100644
@@ -177,7 +177,7 @@ static int intel_dp_max_common_lane_count(struct intel_dp *intel_dp)
 	return min(source_max, sink_max);
 }
 
-static int intel_dp_max_lane_count(struct intel_dp *intel_dp)
+int intel_dp_max_lane_count(struct intel_dp *intel_dp)
 {
 	return intel_dp->max_link_lane_count;
 }
drivers/gpu/drm/i915/intel_dp_mst.c +2 -2
index 95267fcef71b..dfdc32e11b44 100644
@@ -56,7 +56,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
 	 * for MST we always configure max link bw - the spec doesn't
 	 * seem to suggest we should do otherwise.
 	 */
-	lane_count = drm_dp_max_lane_count(intel_dp->dpcd);
+	lane_count = intel_dp_max_lane_count(intel_dp);
 
 	pipe_config->lane_count = lane_count;
 
@@ -362,7 +362,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
 	int max_rate, mode_rate, max_lanes, max_link_clock;
 
 	max_link_clock = intel_dp_max_link_rate(intel_dp);
-	max_lanes = drm_dp_max_lane_count(intel_dp->dpcd);
+	max_lanes = intel_dp_max_lane_count(intel_dp);
 
 	max_rate = intel_dp_max_data_rate(max_link_clock, max_lanes);
 	mode_rate = intel_dp_link_required(mode->clock, bpp);
drivers/gpu/drm/i915/intel_drv.h +1 -0
index 04868046c84f..ea07212e3154 100644
@@ -1467,6 +1467,7 @@ void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *co
 void intel_dp_mst_suspend(struct drm_device *dev);
 void intel_dp_mst_resume(struct drm_device *dev);
 int intel_dp_max_link_rate(struct intel_dp *intel_dp);
+int intel_dp_max_lane_count(struct intel_dp *intel_dp);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
 void intel_dp_hot_plug(struct intel_encoder *intel_encoder);
 void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#21 lore raw

PATCH 12/13 drm/i915/dp: localize link rate index variable more

In reply to Jani Nikula

Localize link_rate_index to the if block, and rename to just index to reduce indent.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +7 -6
index 7704d32286a3..429dc70c251a 100644
@@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
-	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	const int *common_rates = intel_dp->common_rates;
@@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
-						     intel_dp->num_common_rates,
-						     intel_dp->compliance.test_link_rate);
-		if (link_rate_index >= 0)
-			min_clock = max_clock = link_rate_index;
+		int index;
+
+		index = intel_dp_find_rate(intel_dp->common_rates,
+					   intel_dp->num_common_rates,
+					   intel_dp->compliance.test_link_rate);
+		if (index >= 0)
+			min_clock = max_clock = index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
 	}
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#22 lore raw

Re: [PATCH v1½ 12/13] drm/i915/dp: localize link rate index variable more

Quoted 23 lines · Jani Nikula

Localize link_rate_index to the if block, and rename to just index to reduce indent.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -1
index 7704d32286a3..429dc70c251a 100644
@@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
-	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	const int *common_rates = intel_dp->common_rates;

drivers/gpu/drm/i915/intel_dp.c intel_dp_compute_config(struct intel_encoder *encoder, · line 1689

Quoted 6 lines
drivers/gpu/drm/i915/intel_dp.c +0 -3
@@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
-						     intel_dp->num_common_rates,
-						     intel_dp->compliance.test_link_rate);

Can we not pass just the common_rates as an argument to this function since common_rates is already assigned intel_dp->common_rates.

Regards
Manasi

Quoted 15 lines
drivers/gpu/drm/i915/intel_dp.c +7 -2
-		if (link_rate_index >= 0)
-			min_clock = max_clock = link_rate_index;
+		int index;
+
+		index = intel_dp_find_rate(intel_dp->common_rates,
+					   intel_dp->num_common_rates,
+					   intel_dp->compliance.test_link_rate);
+		if (index >= 0)
+			min_clock = max_clock = index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
 	}
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#23 lore raw

Re: [PATCH v1½ 12/13] drm/i915/dp: localize link rate index variable more

Quoted 25 lines · Manasi Navare
Quoted 24 lines · Jani Nikula

Localize link_rate_index to the if block, and rename to just index to reduce indent.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -1
index 7704d32286a3..429dc70c251a 100644
@@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
-	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	const int *common_rates = intel_dp->common_rates;
@@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
Quoted 8 lines

drivers/gpu/drm/i915/intel_dp.c intel_dp_compute_config(struct intel_encoder *encoder, · line 1689

Quoted 5 lines
drivers/gpu/drm/i915/intel_dp.c +0 -3
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
-						     intel_dp->num_common_rates,
-						     intel_dp->compliance.test_link_rate);

Can we not pass just the common_rates as an argument to this function since common_rates is already assigned intel_dp->common_rates.

Do you mean just pass intel_dp to intel_dp_find_rate? If yes, I think this keeps intel_dp_find_rate generic, independent of intel_dp or anything else, and you can be sure it's stateless (same as intersect_rates).

If you don't mean that, I don't know what you mean... please explain.

BR,
Jani.

Quoted 24 lines

Regards
Manasi

Quoted 15 lines
drivers/gpu/drm/i915/intel_dp.c +7 -2
-		if (link_rate_index >= 0)
-			min_clock = max_clock = link_rate_index;
+		int index;
+
+		index = intel_dp_find_rate(intel_dp->common_rates,
+					   intel_dp->num_common_rates,
+					   intel_dp->compliance.test_link_rate);
+		if (index >= 0)
+			min_clock = max_clock = index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
 	}
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#24 lore raw

Re: [PATCH v1½ 12/13] drm/i915/dp: localize link rate index variable more

Quoted 40 lines · Jani Nikula
Quoted 25 lines · Manasi Navare
Quoted 24 lines · Jani Nikula

Localize link_rate_index to the if block, and rename to just index to reduce indent.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -1
index 7704d32286a3..429dc70c251a 100644
@@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
-	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	const int *common_rates = intel_dp->common_rates;
@@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
Quoted 8 lines

drivers/gpu/drm/i915/intel_dp.c intel_dp_compute_config(struct intel_encoder *encoder, · line 1689

Quoted 5 lines
drivers/gpu/drm/i915/intel_dp.c +0 -3
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
-						     intel_dp->num_common_rates,
-						     intel_dp->compliance.test_link_rate);

Can we not pass just the common_rates as an argument to this function since common_rates is already assigned intel_dp->common_rates.

Do you mean just pass intel_dp to intel_dp_find_rate? If yes, I think this keeps intel_dp_find_rate generic, independent of intel_dp or anything else, and you can be sure it's stateless (same as intersect_rates).

Quoted 6 lines

If you don't mean that, I don't know what you mean... please explain.

BR,
Jani.

I agree that it needs to be stateless and hence we dont pass intel_dp directly. What I was saying was that at the beginning of the function we do initialize common_rates = intel_dp->common_rates;
so why cant we pass just common_rates to this function instead of intel_dp->common_rates? Not sure if this optimization will make any big impact but just a thought.

Regards
Manasi

Quoted 16 lines
Quoted 16 lines

Regards
Manasi

Quoted 11 lines
drivers/gpu/drm/i915/intel_dp.c +7 -2
-		if (link_rate_index >= 0)
-			min_clock = max_clock = link_rate_index;
+		int index;
+
+		index = intel_dp_find_rate(intel_dp->common_rates,
+					   intel_dp->num_common_rates,
+					   intel_dp->compliance.test_link_rate);
+		if (index >= 0)
+			min_clock = max_clock = index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
 	}
Quoted 11 lines
Quoted 8 lines
Quoted 4 lines
drivers/gpu/drm/i915/intel_dp.c +0 -0
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Signature · 1 line
Jani Nikula, Intel Open Source Technology Center

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#25 lore raw

Re: [PATCH v1½ 12/13] drm/i915/dp: localize link rate index variable more

Quoted 48 lines · Manasi Navare
Quoted 40 lines · Jani Nikula
Quoted 25 lines · Manasi Navare
Quoted 24 lines · Jani Nikula

Localize link_rate_index to the if block, and rename to just index to reduce indent.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +0 -1
index 7704d32286a3..429dc70c251a 100644
@@ -1639,7 +1639,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 	/* Conveniently, the link BW constants become indices with a shift...*/
 	int min_clock = 0;
 	int max_clock;
-	int link_rate_index;
 	int bpp, mode_rate;
 	int link_avail, link_clock;
 	const int *common_rates = intel_dp->common_rates;
@@ -1684,11 +1683,13 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
Quoted 8 lines

drivers/gpu/drm/i915/intel_dp.c intel_dp_compute_config(struct intel_encoder *encoder, · line 1689

Quoted 5 lines
drivers/gpu/drm/i915/intel_dp.c +0 -3
 	/* Use values requested by Compliance Test Request */
 	if (intel_dp->compliance.test_type == DP_TEST_LINK_TRAINING) {
-		link_rate_index = intel_dp_find_rate(intel_dp->common_rates,
-						     intel_dp->num_common_rates,
-						     intel_dp->compliance.test_link_rate);

Can we not pass just the common_rates as an argument to this function since common_rates is already assigned intel_dp->common_rates.

Do you mean just pass intel_dp to intel_dp_find_rate? If yes, I think this keeps intel_dp_find_rate generic, independent of intel_dp or anything else, and you can be sure it's stateless (same as intersect_rates).

Quoted 6 lines

If you don't mean that, I don't know what you mean... please explain.

BR,
Jani.

Quoted 5 lines

I agree that it needs to be stateless and hence we dont pass intel_dp directly. What I was saying was that at the beginning of the function we do initialize common_rates = intel_dp->common_rates;
so why cant we pass just common_rates to this function instead of intel_dp->common_rates? Not sure if this optimization will make any big impact but just a thought.

Due to the function already being so big and having so many local variables, I ended up throwing the local common_rates away altogether, and changing everything in the function to use intel_dp->common_rates.

BR,
Jani.

Quoted 30 lines

Regards
Manasi

Quoted 27 lines
Quoted 24 lines

Regards
Manasi

Quoted 15 lines
drivers/gpu/drm/i915/intel_dp.c +7 -2
-		if (link_rate_index >= 0)
-			min_clock = max_clock = link_rate_index;
+		int index;
+
+		index = intel_dp_find_rate(intel_dp->common_rates,
+					   intel_dp->num_common_rates,
+					   intel_dp->compliance.test_link_rate);
+		if (index >= 0)
+			min_clock = max_clock = index;
 		min_lane_count = max_lane_count = intel_dp->compliance.test_lane_count;
 	}
 	DRM_DEBUG_KMS("DP link computation with max lane count %i "
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Signature · 1 line
Jani Nikula, Intel Open Source Technology Center
Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#26 lore raw

PATCH 13/13 drm/i915/dp: use readb and writeb calls for single byte DPCD access

In reply to Jani Nikula

This is what we have the readb and writeb variants for. Do some minor return value and variable cleanup while at it.

Cc Manasi Navare <[email protected]>
Cc Ville Syrjälä <[email protected]>
---
 drivers/gpu/drm/i915/intel_dp.c | 37 +++++++++++++++++--------------------
 1 file changed, 17 insertions(+), 20 deletions(-)
drivers/gpu/drm/i915/intel_dp.c +17 -20
index 429dc70c251a..62e8ba12ff8a 100644
@@ -3675,9 +3675,9 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)
 		uint8_t frame_sync_cap;
 
 		dev_priv->psr.sink_support = true;
-		drm_dp_dpcd_read(&intel_dp->aux,
-				 DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
-				 &frame_sync_cap, 1);
+		drm_dp_dpcd_readb(&intel_dp->aux,
+				  DP_SINK_DEVICE_AUX_FRAME_SYNC_CAP,
+				  &frame_sync_cap);
 		dev_priv->psr.aux_frame_sync = frame_sync_cap ? true : false;
 		/* PSR2 needs frame sync as well */
 		dev_priv->psr.psr2_support = dev_priv->psr.aux_frame_sync;
@@ -3744,8 +3744,8 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 	intel_dp_set_sink_rates(intel_dp);
 	intel_dp_set_common_rates(intel_dp);
 
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT,
-			     &intel_dp->sink_count, 1) < 0)
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_SINK_COUNT,
+			      &intel_dp->sink_count) <= 0)
 		return false;
 
 	/*
@@ -3782,7 +3782,7 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
 static bool
 intel_dp_can_mst(struct intel_dp *intel_dp)
 {
-	u8 buf[1];
+	u8 mstm_cap;
 
 	if (!i915.enable_dp_mst)
 		return false;
@@ -3793,10 +3793,10 @@ intel_dp_can_mst(struct intel_dp *intel_dp)
 	if (intel_dp->dpcd[DP_DPCD_REV] < 0x12)
 		return false;
 
-	if (drm_dp_dpcd_read(&intel_dp->aux, DP_MSTM_CAP, buf, 1) != 1)
+	if (drm_dp_dpcd_readb(&intel_dp->aux, DP_MSTM_CAP, &mstm_cap) != 1)
 		return false;
 
-	return buf[0] & DP_MST_CAP;
+	return mstm_cap & DP_MST_CAP;
 }
 
 static void
@@ -3942,9 +3942,8 @@ int intel_dp_sink_crc(struct intel_dp *intel_dp, u8 *crc)
 static bool
 intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector)
 {
-	return drm_dp_dpcd_read(&intel_dp->aux,
-				       DP_DEVICE_SERVICE_IRQ_VECTOR,
-				       sink_irq_vector, 1) == 1;
+	return drm_dp_dpcd_readb(&intel_dp->aux, DP_DEVICE_SERVICE_IRQ_VECTOR,
+				 sink_irq_vector) == 1;
 }
 
 static bool
@@ -4007,13 +4006,13 @@ static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp)
 static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
 {
 	uint8_t test_pattern;
-	uint16_t test_misc;
+	uint8_t test_misc;
 	__be16 h_width, v_height;
 	int status = 0;
 
 	/* Read the TEST_PATTERN (DP CTS 3.1.5) */
-	status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_PATTERN,
-				  &test_pattern, 1);
+	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_PATTERN,
+				   &test_pattern);
 	if (status <= 0) {
 		DRM_DEBUG_KMS("Test pattern read failed\n");
 		return DP_TEST_NAK;
@@ -4035,8 +4034,8 @@ static uint8_t intel_dp_autotest_video_pattern(struct intel_dp *intel_dp)
 		return DP_TEST_NAK;
 	}
 
-	status = drm_dp_dpcd_read(&intel_dp->aux, DP_TEST_MISC0,
-				  &test_misc, 1);
+	status = drm_dp_dpcd_readb(&intel_dp->aux, DP_TEST_MISC0,
+				   &test_misc);
 	if (status <= 0) {
 		DRM_DEBUG_KMS("TEST MISC read failed\n");
 		return DP_TEST_NAK;
@@ -4095,10 +4094,8 @@ static uint8_t intel_dp_autotest_edid(struct intel_dp *intel_dp)
 		 */
 		block += intel_connector->detect_edid->extensions;
 
-		if (!drm_dp_dpcd_write(&intel_dp->aux,
-					DP_TEST_EDID_CHECKSUM,
-					&block->checksum,
-					1))
+		if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_TEST_EDID_CHECKSUM,
+				       block->checksum) <= 0)
 			DRM_DEBUG_KMS("Failed to write EDID checksum\n");
 
 		test_result = DP_TEST_ACK | DP_TEST_EDID_CHECKSUM_WRITE;
Signature · 6 lines
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
#27 lore raw
In reply to Jani Nikula
Quoted 1 line · Jani Nikula

This is kind of version 1½ of [1], basically just rebased on current git

Looks like this version didn't make it into patchwork.

-DK

Quoted 26 lines

(including Manasi's test automation patches) and a couple of more cleanups slammed on top.

BR,
Jani.

[1] http://mid.mail-archive.com/[email protected]

Jani Nikula (13):
drm/i915/dp: use known correct array size in rate_to_index drm/i915/dp: return errors from rate_to_index() drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse drm/i915/dp: cache source rates at init
drm/i915/dp: generate and cache sink rate array for all DP, not just

    eDP 1.4

drm/i915/dp: use the sink rates array for max sink rates drm/i915/dp: cache common rates with sink rates drm/i915/dp: do not limit rate seek when not needed drm/i915/dp: don't call the link parameters sink parameters drm/i915/dp: add functions for max common link rate and lane count drm/i915/mst: use max link not sink lane count drm/i915/dp: localize link rate index variable more drm/i915/dp: use readb and writeb calls for single byte DPCD access

Quoted 6 lines
 drivers/gpu/drm/i915/intel_dp.c               | 275 ++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp_link_training.c |   3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c           |   4 +-
 drivers/gpu/drm/i915/intel_drv.h              |  19 +-
 4 files changed, 166 insertions(+), 135 deletions(-)

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#28 lore raw
In reply to Jani Nikula

Are you planning on submitting a v2 for these pretty soon that can make it to patchwork/

Regards
Manasi

Quoted 27 lines · Jani Nikula

This is kind of version 1½ of [1], basically just rebased on current git (including Manasi's test automation patches) and a couple of more cleanups slammed on top.

BR,
Jani.

[1] http://mid.mail-archive.com/[email protected]

Jani Nikula (13):
drm/i915/dp: use known correct array size in rate_to_index drm/i915/dp: return errors from rate_to_index() drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse drm/i915/dp: cache source rates at init
drm/i915/dp: generate and cache sink rate array for all DP, not just

    eDP 1.4

drm/i915/dp: use the sink rates array for max sink rates drm/i915/dp: cache common rates with sink rates drm/i915/dp: do not limit rate seek when not needed drm/i915/dp: don't call the link parameters sink parameters drm/i915/dp: add functions for max common link rate and lane count drm/i915/mst: use max link not sink lane count drm/i915/dp: localize link rate index variable more drm/i915/dp: use readb and writeb calls for single byte DPCD access

Quoted 9 lines
 drivers/gpu/drm/i915/intel_dp.c               | 275 ++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp_link_training.c |   3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c           |   4 +-
 drivers/gpu/drm/i915/intel_drv.h              |  19 +-
 4 files changed, 166 insertions(+), 135 deletions(-)
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#29 lore raw
Quoted 14 lines · Manasi Navare

Are you planning on submitting a v2 for these pretty soon that can make it to patchwork/

Regards
Manasi

Quoted 7 lines · Jani Nikula

This is kind of version 1½ of [1], basically just rebased on current git (including Manasi's test automation patches) and a couple of more cleanups slammed on top.

BR,
Jani.

So the problem we still have with link rate fallback after link failure->uevent-> fetch new modes->link retrain is that after we send a uevent, userspace fetches new modes which calls drm_helper_probe_single_connector_modes() that calls dp_detect which ends up calling intel_dp_long_pulse(). So while userspace is just trying to fetch new modes it overwrites the max_link_rate and max_lane_count values through intel_dp_long_pulse(). So while retraining, when it calls intel_dp_compute_config(), it will use the overwritten values of common_rates/max_link_rate/max_lane_count as opposed to the ones set in intel_dp_get_fallback_values().
I wonder if this patch series solves this problem somehow...
else, do you have any insight on how we can solve this?

Regards
Manasi

Quoted 26 lines
Quoted 26 lines

[1] http://mid.mail-archive.com/[email protected]

Jani Nikula (13):
drm/i915/dp: use known correct array size in rate_to_index drm/i915/dp: return errors from rate_to_index() drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse drm/i915/dp: cache source rates at init
drm/i915/dp: generate and cache sink rate array for all DP, not just

    eDP 1.4

drm/i915/dp: use the sink rates array for max sink rates drm/i915/dp: cache common rates with sink rates drm/i915/dp: do not limit rate seek when not needed drm/i915/dp: don't call the link parameters sink parameters drm/i915/dp: add functions for max common link rate and lane count drm/i915/mst: use max link not sink lane count drm/i915/dp: localize link rate index variable more drm/i915/dp: use readb and writeb calls for single byte DPCD access

 drivers/gpu/drm/i915/intel_dp.c               | 275 ++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp_link_training.c |   3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c           |   4 +-
 drivers/gpu/drm/i915/intel_drv.h              |  19 +-
 4 files changed, 166 insertions(+), 135 deletions(-)
Quoted 7 lines
Quoted 3 lines
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

#30 lore raw
Quoted 16 lines · Manasi Navare
Quoted 14 lines · Manasi Navare

Are you planning on submitting a v2 for these pretty soon that can make it to patchwork/

Regards
Manasi

Quoted 7 lines · Jani Nikula

This is kind of version 1½ of [1], basically just rebased on current git (including Manasi's test automation patches) and a couple of more cleanups slammed on top.

BR,
Jani.

Quoted 12 lines

So the problem we still have with link rate fallback after link failure->uevent-> fetch new modes->link retrain is that after we send a uevent, userspace fetches new modes which calls drm_helper_probe_single_connector_modes() that calls dp_detect which ends up calling intel_dp_long_pulse(). So while userspace is just trying to fetch new modes it overwrites the max_link_rate and max_lane_count values through intel_dp_long_pulse(). So while retraining, when it calls intel_dp_compute_config(), it will use the overwritten values of common_rates/max_link_rate/max_lane_count as opposed to the ones set in intel_dp_get_fallback_values(). I wonder if this patch series solves this problem somehow... else, do you have any insight on how we can solve this?

I'm not sure this does solve that, but this series certainly makes it easier to follow through the code and see what happens where. ;)

Writing this patch has also highlighted the problem with merging preparatory patches that don't actually do anything, in this case the intel_dp_get_link_train_fallback_values() function. How is one supposed to know how it can be refactored when it doesn't have a single user?

BR,
Jani.

Quoted 38 lines

Regards
Manasi

Quoted 33 lines
Quoted 20 lines

[1] http://mid.mail-archive.com/[email protected]

Jani Nikula (13):
drm/i915/dp: use known correct array size in rate_to_index drm/i915/dp: return errors from rate_to_index() drm/i915/dp: rename rate_to_index() to intel_dp_find_rate() and reuse drm/i915/dp: cache source rates at init
drm/i915/dp: generate and cache sink rate array for all DP, not just

    eDP 1.4

drm/i915/dp: use the sink rates array for max sink rates drm/i915/dp: cache common rates with sink rates drm/i915/dp: do not limit rate seek when not needed drm/i915/dp: don't call the link parameters sink parameters drm/i915/dp: add functions for max common link rate and lane count drm/i915/mst: use max link not sink lane count drm/i915/dp: localize link rate index variable more drm/i915/dp: use readb and writeb calls for single byte DPCD access

Quoted 9 lines
 drivers/gpu/drm/i915/intel_dp.c               | 275 ++++++++++++++------------
 drivers/gpu/drm/i915/intel_dp_link_training.c |   3 +-
 drivers/gpu/drm/i915/intel_dp_mst.c           |   4 +-
 drivers/gpu/drm/i915/intel_drv.h              |  19 +-
 4 files changed, 166 insertions(+), 135 deletions(-)
Signature · 1 line
2.1.4

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Signature · 5 lines
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx