[PATCH i-g-t v5 1/4] lib/i915/i915_dp: Add UHBR helpers and const-correct set_link_params

Sowmiya S <[email protected]>
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <[email protected]>
Add i915_dp_is_uhbr_rate() and i915_dp_get_next_lower_rate(), prep for
the UHBR-to-HBR fallback subtest later in this series; no caller yet.

i915_dp_get_next_lower_rate() parses intel_dp_allowed_link_configs
(source & sink & current limits) rather than i915_dp_force_link_rate,
since the latter is source-only and lets the kernel silently clamp a
rate the sink never advertised.

Also take link_rate/lane_count as const char * in
i915_dp_set_link_params() so callers can pass string literals.

v4: - name the UHBR10 threshold and make i915_dp_is_uhbr_rate() a
      static inline in the header to avoid a cross-TU call (Kunal)
    - parse intel_dp_allowed_link_configs instead of the source-only
      i915_dp_force_link_rate list in i915_dp_get_next_lower_rate()
      (Kunal)
    - avoid the implicit long to int narrowing on the return value
      (Kunal)

Signed-off-by: Sowmiya S <[email protected]>
---
 lib/i915/i915_dp.c | 58 +++++++++++++++++++++++++++++++++++++++++++++-
 lib/i915/i915_dp.h | 24 ++++++++++++++++++-
 2 files changed, 80 insertions(+), 2 deletions(-)

diff --git a/lib/i915/i915_dp.c b/lib/i915/i915_dp.c
index e54058580..3d570f7cc 100644
--- a/lib/i915/i915_dp.c
+++ b/lib/i915/i915_dp.c
@@ -334,7 +334,7 @@ void i915_dp_reset_link_params(int drm_fd, igt_output_t *output)
  * to set link rate and lane count to auto on exit
  */
 void i915_dp_set_link_params(int drm_fd, igt_output_t *output,
-			     char *link_rate, char *lane_count)
+			     const char *link_rate, const char *lane_count)
 {
 	bool valid;
 	drmModeConnector *temp;
@@ -390,3 +390,59 @@ int i915_dp_get_max_supported_rate(int drm_fd, const igt_output_t *output)
 
 	return max_rate;
 }
+
+/**
+ * i915_dp_get_next_lower_rate:
+ * @drm_fd: A drm file descriptor
+ * @output: Target output
+ * @rate: reference link rate in 10 kbit/s units
+ *
+ * Parse the intel_dp_allowed_link_configs debugfs file and return the highest
+ * allowed link rate strictly below @rate.
+ *
+ * This file lists the configurations the driver would actually pick from, i.e.
+ * the intersection of the source rates, the rates the sink advertises and the
+ * current link limits, as "<lanes>x<rate>" entries. The i915_dp_force_link_rate
+ * list is only the source rates: writing a rate from it that the sink never
+ * advertised still succeeds and the kernel silently clamps the effective rate
+ * down, so the caller would report a rate the link was never trained at.
+ *
+ * Returns: highest allowed rate below @rate in 10 kbit/s units, or 0 if none.
+ */
+int i915_dp_get_next_lower_rate(int drm_fd, igt_output_t *output, int rate)
+{
+	char buf[4096];
+	const char *p;
+	int res, next = 0;
+
+	res = igt_debugfs_read_connector_file(drm_fd, igt_output_name(output),
+					      "intel_dp_allowed_link_configs",
+					      buf, sizeof(buf));
+	igt_assert_f(res == 0,
+		     "Unable to read %s/intel_dp_allowed_link_configs\n",
+		     igt_output_name(output));
+
+	/*
+	 * Entries are "<lanes>x<rate>". Key off the 'x' separator rather than
+	 * tokenising the whole file, so the header and any decoration around
+	 * the list are skipped without having to model them.
+	 */
+	for (p = buf; (p = strchr(p, 'x')); p++) {
+		char *endptr;
+		long r;
+
+		/* Must be preceded by the lane count to be a config entry. */
+		if (p == buf || !isdigit((unsigned char)p[-1]))
+			continue;
+
+		errno = 0;
+		r = strtol(p + 1, &endptr, 10);
+		if (errno || endptr == p + 1)
+			continue;
+
+		if (r < rate && r > next)
+			next = (int)r;
+	}
+
+	return next;
+}
diff --git a/lib/i915/i915_dp.h b/lib/i915/i915_dp.h
index b13629147..5d17713e2 100644
--- a/lib/i915/i915_dp.h
+++ b/lib/i915/i915_dp.h
@@ -3,8 +3,29 @@
 #ifndef _I915_DP_H_
 #define _I915_DP_H_
 
+#include <stdbool.h>
+
 #include "igt_kms.h"
 
+/* DP link rates are in 10 kbit/s units; UHBR10 is 10 Gbps. */
+#define I915_DP_UHBR10_LINK_RATE	1000000
+
+/**
+ * i915_dp_is_uhbr_rate:
+ * @link_rate: DP link rate in 10 kbit/s units, as reported by the
+ *	       i915_dp_*_link_rate debugfs files
+ *
+ * UHBR (Ultra High Bit Rate) link rates use 128b/132b channel encoding,
+ * everything below uses legacy 8b/10b. Mirrors the kernel's
+ * drm_dp_is_uhbr_rate().
+ *
+ * Returns: true if @link_rate is a UHBR rate, false otherwise.
+ */
+static inline bool i915_dp_is_uhbr_rate(int link_rate)
+{
+	return link_rate >= I915_DP_UHBR10_LINK_RATE;
+}
+
 int i915_dp_get_current_link_rate(int drm_fd, igt_output_t *output);
 int i915_dp_get_current_lane_count(int drm_fd, igt_output_t *output);
 int i915_dp_get_max_link_rate(int drm_fd, igt_output_t *output);
@@ -17,7 +38,8 @@ int i915_dp_get_pending_lt_failures(int drm_fd, igt_output_t *output);
 int i915_dp_get_pending_retrain(int drm_fd, igt_output_t *output);
 void i915_dp_reset_link_params(int drm_fd, igt_output_t *output);
 void i915_dp_set_link_params(int drm_fd, igt_output_t *output,
-			     char *link_rate, char *lane_count);
+			     const char *link_rate, const char *lane_count);
 int i915_dp_get_max_supported_rate(int drm_fd, const igt_output_t *output);
+int i915_dp_get_next_lower_rate(int drm_fd, igt_output_t *output, int rate);
 
 #endif
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.