[PATCH i-g-t v3 1/3] lib/i915/i915_dp: add UHBR helpers and const-correct set_link_params

Sowmiya S <[email protected]> Wed, 5 Aug 2026 14:14:25 +0530
Newsgroups org.freedesktop.lists.igt-dev
Message-ID <[email protected]>
- const char * for i915_dp_set_link_params() to allow string literals
- Add i915_dp_is_uhbr_rate(): returns true for link rates >= 10 Gbps
- Add i915_dp_get_next_lower_rate(): parses force_link_rate debugfs list
  using strtok_r(), base-10 strtol() with errno/endptr checks

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

diff --git a/lib/i915/i915_dp.c b/lib/i915/i915_dp.c
index e54058580..bf66347f5 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,63 @@ int i915_dp_get_max_supported_rate(int drm_fd, const igt_output_t *output)
 
 	return max_rate;
 }
+
+/**
+ * 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. UHBR10 is 10 Gbps, i.e. 1000000 in
+ * 10 kbit/s units. Mirrors the kernel's drm_dp_is_uhbr_rate().
+ *
+ * Returns: true if @link_rate is a UHBR rate, false otherwise.
+ */
+bool i915_dp_is_uhbr_rate(int link_rate)
+{
+	return link_rate >= 1000000;
+}
+
+/**
+ * i915_dp_get_next_lower_rate:
+ * @drm_fd: A drm file descriptor
+ * @output: Target output
+ * @rate: reference link rate in 10 kbit/s units
+ *
+ * Parses the i915_dp_force_link_rate debugfs list (the source rates, printed
+ * with an "auto" entry and "[..]"/"*" markers) and returns the highest
+ * supported link rate strictly below @rate.
+ *
+ * Returns: highest supported 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[512], *token, *saveptr = NULL;
+	int res, next = 0;
+
+	res = igt_debugfs_read_connector_file(drm_fd, igt_output_name(output),
+					      "i915_dp_force_link_rate",
+					      buf, sizeof(buf));
+	igt_assert_f(res == 0, "Unable to read %s/i915_dp_force_link_rate\n",
+		     igt_output_name(output));
+
+	/* Delimiters strip the "auto" whitespace and the [ ] * markers. */
+	for (token = strtok_r(buf, " \t\n[]*", &saveptr); token;
+	     token = strtok_r(NULL, " \t\n[]*", &saveptr)) {
+		char *endptr;
+		long r;
+
+		if (!strcmp(token, "auto"))
+			continue;
+
+		errno = 0;
+		r = strtol(token, &endptr, 10);
+		if (errno || endptr == token || *endptr)
+			continue;
+
+		if (r < rate && r > next)
+			next = r;
+	}
+
+	return next;
+}
diff --git a/lib/i915/i915_dp.h b/lib/i915/i915_dp.h
index b13629147..6b39d0560 100644
--- a/lib/i915/i915_dp.h
+++ b/lib/i915/i915_dp.h
@@ -17,7 +17,9 @@ 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);
+bool i915_dp_is_uhbr_rate(int link_rate);
 
 #endif
-- 
2.51.0