All of lore.kernel.org
 help / color / mirror / Atom feed
From: Imre Deak <imre.deak@intel.com>
To: <intel-gfx@lists.freedesktop.org>, <intel-xe@lists.freedesktop.org>
Subject: [PATCH v2 04/34] drm/i915/dp_link_caps: Add link configuration iterator
Date: Wed, 1 Jul 2026 18:31:33 +0300	[thread overview]
Message-ID: <20260701153204.4124150-5-imre.deak@intel.com> (raw)
In-Reply-To: <20260701153204.4124150-1-imre.deak@intel.com>

Add helpers to iterate over the allowed and optionally filtered set of
link configurations in a given order.

Taking into account disabled configurations will be added later when
adding support for disabling configurations.

Use the BW order in descending direction by default.

v2:
- Keep the iteration state in an iteration object. (Jani)
- Use a filter object instead of exposing configuration indices. (Jani)
- Move changes adding helpers required to setup the iteration object to
  this patch.

Signed-off-by: Imre Deak <imre.deak@intel.com>
---
 .../gpu/drm/i915/display/intel_dp_link_caps.c | 213 ++++++++++++++++++
 .../gpu/drm/i915/display/intel_dp_link_caps.h | 106 +++++++++
 2 files changed, 319 insertions(+)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
index fe5a11efbe67b..d46b9d505a847 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.c
@@ -16,6 +16,7 @@
 
 #include "intel_display_core.h"
 #include "intel_display_types.h"
+#include "intel_display_utils.h"
 #include "intel_dp.h"
 #include "intel_dp_link_caps.h"
 
@@ -146,6 +147,18 @@ struct intel_dp_link_caps {
 	 */
 	struct intel_dp_link_config max_limits;
 };
+static_assert(BITS_PER_TYPE(((struct intel_dp_link_caps_filter *)NULL)->config_mask) >=
+	      ARRAY_SIZE(((struct intel_dp_link_caps *)NULL)->configs));
+
+static struct intel_dp_link_caps_order bw_desc_config_order(void)
+{
+	struct intel_dp_link_caps_order order = {
+		.key = INTEL_DP_LINK_CAPS_ORDER_KEY_BW,
+		.dir = INTEL_DP_LINK_CAPS_ORDER_DIR_DESC,
+	};
+
+	return order;
+}
 
 /* Get length of common rates array potentially limited by max_rate. */
 int intel_dp_common_len_rate_limit(struct intel_dp_link_caps *link_caps,
@@ -252,6 +265,206 @@ to_intel_dp_link_config(struct intel_dp_link_caps *link_caps,
 	config->lane_count = intel_dp_link_config_lane_count(lce);
 }
 
+static int
+iter_pos_to_idx(struct intel_dp_link_caps *link_caps,
+		struct intel_dp_link_caps_order config_order,
+		int iter_pos)
+{
+	int config_idx;
+
+	if (!in_range(iter_pos, 0, link_caps->num_configs))
+		return -1;
+
+	switch (config_order.dir) {
+	case INTEL_DP_LINK_CAPS_ORDER_DIR_ASC:
+		break;
+	case INTEL_DP_LINK_CAPS_ORDER_DIR_DESC:
+		iter_pos = link_caps->num_configs - 1 - iter_pos;
+
+		break;
+	default:
+		MISSING_CASE(config_order.dir);
+
+		return -1;
+	}
+
+	switch (config_order.key) {
+	case INTEL_DP_LINK_CAPS_ORDER_KEY_BW:
+		config_idx = iter_pos;
+
+		break;
+	case INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE:
+		config_idx = link_caps->rate_lane_map[iter_pos];
+
+		break;
+	case INTEL_DP_LINK_CAPS_ORDER_KEY_LANE_RATE:
+		config_idx = link_caps->lane_rate_map[iter_pos];
+
+		break;
+	default:
+		MISSING_CASE(config_order.key);
+
+		return -1;
+	}
+
+	return config_idx;
+}
+
+static bool iter_get_next_config(struct intel_dp_link_caps_iter *iter,
+				 struct intel_dp_link_config *config)
+{
+	while (true) {
+		int config_idx;
+
+		iter->pos++;
+
+		config_idx = iter_pos_to_idx(iter->link_caps, iter->order, iter->pos);
+		if (config_idx < 0) {
+			iter->pos = -1;
+			*config = INTEL_DP_LINK_CONFIG_NULL;
+
+			break;
+		}
+
+		if (!(BIT(config_idx) & iter->filter.config_mask))
+			continue;
+
+		to_intel_dp_link_config(iter->link_caps, config_idx, config);
+
+		break;
+	}
+
+	return iter->pos >= 0;
+}
+
+static void iter_start(struct intel_dp_link_caps_iter *iter,
+		       struct intel_dp_link_caps *link_caps,
+		       struct intel_dp_link_caps_order order,
+		       struct intel_dp_link_caps_filter filter)
+{
+	iter->link_caps = link_caps;
+	iter->pos = -1;
+	iter->order = order;
+	iter->filter = filter;
+
+	iter->get_next_config = iter_get_next_config;
+}
+
+static struct intel_dp_link_caps_filter
+calc_allowed_config_filter(struct intel_dp_link_caps *link_caps,
+			   struct intel_dp_link_caps_filter enabled_configs,
+			   const struct intel_dp_link_config *max_limits,
+			   const struct intel_dp_link_config *forced_params)
+{
+	struct intel_dp_link_caps_filter allowed_configs = INTEL_DP_LINK_CAPS_FILTER_NONE;
+	struct intel_dp_link_caps_order order = bw_desc_config_order();
+	struct intel_dp_link_caps_iter iter;
+	struct intel_dp_link_config config;
+
+	iter_start(&iter, link_caps, order, enabled_configs);
+	for_each_dp_link_config(&iter, &config) {
+		if (forced_params->rate &&
+		    forced_params->rate != config.rate)
+			continue;
+
+		if (forced_params->lane_count &&
+		    forced_params->lane_count != config.lane_count)
+			continue;
+
+		if (config.rate > max_limits->rate)
+			continue;
+
+		if (config.lane_count > max_limits->lane_count)
+			continue;
+
+		allowed_configs.config_mask |= BIT(iter_pos_to_idx(link_caps, order, iter.pos));
+	}
+	intel_dp_link_caps_iter_end(&iter);
+
+	return allowed_configs;
+}
+
+/*
+ * get_allowed_config_filter - get filter for the currently allowed configs
+ * @link_caps: link capabilities state
+ *
+ * Return:
+ * Filter of link configurations allowed after applying the current
+ * maximum link limits, and further narrowing them by removing any disabled
+ * configuration and limiting to forced link parameters.
+ *
+ * See also:
+ * - intel_dp_link_caps_get_max_limits()
+ * - intel_dp_link_caps_get_forced_params()
+ */
+static struct intel_dp_link_caps_filter
+get_allowed_config_filter(struct intel_dp_link_caps *link_caps)
+{
+	struct intel_dp_link_config forced_params;
+
+	intel_dp_link_caps_get_forced_params(link_caps, &forced_params);
+
+	/* TODO: Get filter for enabled configs. */
+	return calc_allowed_config_filter(link_caps, INTEL_DP_LINK_CAPS_FILTER_ALL,
+					  &link_caps->max_limits, &forced_params);
+}
+
+void intel_dp_link_caps_iter_start(struct intel_dp_link_caps_iter *iter,
+				   struct intel_dp_link_caps *link_caps,
+				   struct intel_dp_link_caps_order order,
+				   struct intel_dp_link_caps_filter filter)
+{
+	filter.config_mask &= get_allowed_config_filter(link_caps).config_mask;
+
+	iter_start(iter, link_caps, order, filter);
+}
+
+void intel_dp_link_caps_iter_end(struct intel_dp_link_caps_iter *iter)
+{
+	memset(iter, 0, sizeof(*iter));
+}
+
+static int find_config_idx(struct intel_dp_link_caps *link_caps,
+			   struct intel_dp_link_caps_filter filter,
+			   const struct intel_dp_link_config *link_config)
+{
+	struct intel_dp_link_caps_order order = bw_desc_config_order();
+	struct intel_dp_link_config iter_config;
+	struct intel_dp_link_caps_iter iter;
+	int pos = -1;
+
+	intel_dp_link_caps_iter_start(&iter, link_caps, order, filter);
+	for_each_dp_link_config(&iter, &iter_config) {
+		if (iter_config.rate == link_config->rate &&
+		    iter_config.lane_count == link_config->lane_count) {
+			pos = iter.pos;
+
+			break;
+		}
+	}
+	intel_dp_link_caps_iter_end(&iter);
+
+	if (pos < 0)
+		return pos;
+
+	return iter_pos_to_idx(link_caps, order, pos);
+}
+
+bool intel_dp_link_caps_filter_add(struct intel_dp_link_caps *link_caps,
+				   struct intel_dp_link_caps_filter *filter,
+				   const struct intel_dp_link_config *config)
+{
+	int idx;
+
+	idx = find_config_idx(link_caps, get_allowed_config_filter(link_caps), config);
+	if (idx < 0)
+		return false;
+
+	filter->config_mask |= BIT(idx);
+
+	return true;
+}
+
 static void set_max_link_limits_no_update(struct intel_dp_link_caps *link_caps,
 					  const struct intel_dp_link_config *max_link_limits)
 {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
index af9028e7cb987..5ea87f112c13a 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
+++ b/drivers/gpu/drm/i915/display/intel_dp_link_caps.h
@@ -4,6 +4,7 @@
 #ifndef __INTEL_DP_LINK_CAPS_H__
 #define __INTEL_DP_LINK_CAPS_H__
 
+#include <linux/bitops.h>
 #include <linux/types.h>
 
 struct intel_connector;
@@ -11,6 +12,107 @@ struct intel_dp;
 struct intel_dp_link_caps;
 struct intel_dp_link_config;
 
+/**
+ * enum intel_dp_link_caps_order_key - key used to order configurations
+ * @INTEL_DP_LINK_CAPS_ORDER_KEY_BW:
+ *   Order configurations by bandwidth, then by link rate.
+ * @INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE:
+ *   Order configurations by link rate, then by lane count.
+ * @INTEL_DP_LINK_CAPS_ORDER_KEY_LANE_RATE:
+ *   Order configurations by lane count, then by link rate.
+ * @INTEL_DP_LINK_CAPS_ORDER_KEY_NUM:
+ *   Number of ordering keys.
+ *
+ * Selects how a caller wants the configuration table to be ordered,
+ * together with an &enum intel_dp_link_caps_order_direction, for
+ * iteration queries.
+ *
+ * See also:
+ *  - &struct intel_dp_link_caps_order
+ */
+enum intel_dp_link_caps_order_key {
+	INTEL_DP_LINK_CAPS_ORDER_KEY_BW,
+	INTEL_DP_LINK_CAPS_ORDER_KEY_RATE_LANE,
+	INTEL_DP_LINK_CAPS_ORDER_KEY_LANE_RATE,
+
+	INTEL_DP_LINK_CAPS_ORDER_KEY_NUM
+};
+
+/**
+ * enum intel_dp_link_caps_order_direction - iteration direction
+ * @INTEL_DP_LINK_CAPS_ORDER_DIR_ASC:
+ *   Iterate in ascending order according to the selected ordering key.
+ * @INTEL_DP_LINK_CAPS_ORDER_DIR_DESC:
+ *   Iterate in descending order according to the selected ordering key.
+ * @INTEL_DP_LINK_CAPS_ORDER_DIR_NUM:
+ *   Number of ordering directions.
+ *
+ * Selects the direction associated with an
+ * &enum intel_dp_link_caps_order_key for iteration queries.
+ *
+ * See also:
+ *  - &struct intel_dp_link_caps_order
+ */
+enum intel_dp_link_caps_order_direction {
+	INTEL_DP_LINK_CAPS_ORDER_DIR_ASC,
+	INTEL_DP_LINK_CAPS_ORDER_DIR_DESC,
+
+	INTEL_DP_LINK_CAPS_ORDER_DIR_NUM
+};
+
+/**
+ * struct intel_dp_link_caps_order - configuration ordering
+ * @key:
+ *   Key used to order configurations.
+ * @dir:
+ *   Direction of the selected ordering.
+ *
+ * Describes an iteration order for link configurations.
+ *
+ * See also:
+ *  - for_each_dp_link_config()
+ */
+struct intel_dp_link_caps_order {
+	enum intel_dp_link_caps_order_key key;
+	enum intel_dp_link_caps_order_direction dir;
+};
+
+struct intel_dp_link_caps_filter {
+	u32 config_mask;
+};
+
+#define INTEL_DP_LINK_CAPS_FILTER_NONE	\
+	((struct intel_dp_link_caps_filter){ .config_mask = 0 })
+#define INTEL_DP_LINK_CAPS_FILTER_ALL	\
+	((struct intel_dp_link_caps_filter){ .config_mask = (u32)-1 })
+
+struct intel_dp_link_caps_iter {
+	struct intel_dp_link_caps *link_caps;
+	int pos;
+	struct intel_dp_link_caps_order order;
+	struct intel_dp_link_caps_filter filter;
+
+	bool (*get_next_config)(struct intel_dp_link_caps_iter *iter,
+				struct intel_dp_link_config *config);
+};
+
+/**
+ * for_each_dp_link_config - iterate allowed link configurations
+ * @__iter:
+ *   &struct intel_dp_link_caps_iter being iterated
+ * @__config:
+ *   pointer to &struct intel_dp_link_config filled for each match
+ */
+#define for_each_dp_link_config(__iter, __config) \
+	while ((__iter)->get_next_config((__iter), (__config)))
+
+void intel_dp_link_caps_iter_start(struct intel_dp_link_caps_iter *iter,
+				   struct intel_dp_link_caps *link_caps,
+				   struct intel_dp_link_caps_order order,
+				   struct intel_dp_link_caps_filter filter);
+
+void intel_dp_link_caps_iter_end(struct intel_dp_link_caps_iter *iter);
+
 int intel_dp_common_len_rate_limit(struct intel_dp_link_caps *link_caps,
 				   int max_rate);
 int intel_dp_common_rate(struct intel_dp_link_caps *link_caps, int index);
@@ -29,6 +131,10 @@ int intel_dp_link_config_index(struct intel_dp_link_caps *link_caps,
 void intel_dp_link_config_get(struct intel_dp_link_caps *link_caps,
 			      int idx, int *link_rate, int *lane_count);
 
+bool intel_dp_link_caps_filter_add(struct intel_dp_link_caps *link_caps,
+				   struct intel_dp_link_caps_filter *filter,
+				   const struct intel_dp_link_config *config);
+
 void intel_dp_link_caps_get_max_limits(struct intel_dp_link_caps *link_caps,
 				       struct intel_dp_link_config *max_link_limits);
 bool intel_dp_link_caps_set_max_limits(struct intel_dp_link_caps *link_caps,
-- 
2.49.1


  parent reply	other threads:[~2026-07-01 15:32 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-01 15:31 [PATCH v2 00/34] drm/i915/dp_link: Unify modeset/fallback config selection Imre Deak
2026-07-01 15:31 ` [PATCH v2 01/34] drm/i915/doc: Document DP link capabilities Imre Deak
2026-07-02  5:17   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 02/34] drm/i915/dp_link_caps: Factor out helper to get link config by index Imre Deak
2026-07-03  2:55   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 03/34] drm/i915/dp_link_caps: Add support for link rate, lane count iteration orders Imre Deak
2026-07-07  4:06   ` Kandpal, Suraj
2026-07-01 15:31 ` Imre Deak [this message]
2026-07-07  4:17   ` [PATCH v2 04/34] drm/i915/dp_link_caps: Add link configuration iterator Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 05/34] drm/i915/dp_link_caps: Add helper to get iteration order for a connector Imre Deak
2026-07-07  5:13   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 06/34] drm/i915/dp_link_caps: Validate max link limits Imre Deak
2026-07-06  8:17   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 07/34] drm/i915/dp_link_caps: Add filter for enabled link configurations Imre Deak
2026-07-06  8:08   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 08/34] drm/i915/dp_link_caps: Re-enable link configurations after a link reset Imre Deak
2026-07-06  8:09   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 09/34] drm/i915/dp_link_caps: Re-enable link configurations after sink caps change Imre Deak
2026-07-06  8:14   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 10/34] drm/i915/dp_link_caps: Drop noupdate postfix from max link limit set helpers Imre Deak
2026-07-06  8:16   ` Kandpal, Suraj
2026-07-01 15:31 ` [PATCH v2 11/34] drm/i915/dp_link_caps: Add debugfs entry showing allowed configurations Imre Deak
2026-07-02 10:35   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 12/34] drm/i915/dp: Add link configuration filter for modeset computation Imre Deak
2026-07-02 11:03   ` Luca Coelho
2026-07-06  7:52     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 13/34] drm/i915/dp_link_caps: Add helper to query max BW link configuration Imre Deak
2026-07-02 11:06   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 14/34] drm/i915/dp: Query max BW config via link_caps during mode validation Imre Deak
2026-07-02 11:22   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 15/34] drm/i915/dp_tunnel: Query max BW config via link_caps for BW computation Imre Deak
2026-07-02 11:23   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 16/34] drm/i915/dp_test: Use link caps for compliance link configs Imre Deak
2026-07-02 16:19   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 17/34] drm/i915/dp: Iterate configurations via link_caps for SST non-DSC Imre Deak
2026-07-06 10:42   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 18/34] drm/i915/dp: Iterate configurations via link_caps for SST DSC Imre Deak
2026-07-06 10:48   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 19/34] drm/i915/dp: Use link caps for eDP DSC config selection Imre Deak
2026-07-06 10:49   ` Luca Coelho
2026-07-06 15:03     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 20/34] drm/i915/dp_mst: Use link caps for non-DSC " Imre Deak
2026-07-06 16:45   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 21/34] drm/i915/dp_mst: Use link caps for MST DSC " Imre Deak
2026-07-07  6:49   ` Luca Coelho
2026-07-01 15:31 ` [PATCH v2 22/34] drm/i915/dp: Remove min/max link config limits Imre Deak
2026-07-01 15:31 ` [PATCH v2 23/34] drm/i915/dp_link_training: Reset the max link limits in the fallback code Imre Deak
2026-07-01 15:31 ` [PATCH v2 24/34] drm/i915/dp_link_training: Use config iterator for fallback Imre Deak
2026-07-01 15:31 ` [PATCH v2 25/34] drm/i915/dp_link_training: Disable failed config during fallback Imre Deak
2026-07-01 15:31 ` [PATCH v2 26/34] drm/i915/kunit: Enable KUnit tests Imre Deak
2026-07-04 10:48   ` Michał Grzelak
2026-07-06  7:07     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 27/34] drm/i915/kunit: Add DP link test stub Imre Deak
2026-07-04 10:48   ` Michał Grzelak
2026-07-01 15:31 ` [PATCH v2 28/34] drm/xe/kunit: Add display test config Imre Deak
2026-07-04 10:49   ` Michał Grzelak
2026-07-01 15:31 ` [PATCH v2 29/34] drm/xe/kunit: Build DP link display tests Imre Deak
2026-07-04 10:49   ` Michał Grzelak
2026-07-06  7:14     ` Imre Deak
2026-07-01 15:31 ` [PATCH v2 30/34] drm/i915/kunit: Setup DP link test context Imre Deak
2026-07-04 10:50   ` Michał Grzelak
2026-07-06  7:18     ` Imre Deak
2026-07-01 15:32 ` [PATCH v2 31/34] drm/i915/kunit: Export link training and caps funcs for testing Imre Deak
2026-07-04 10:52   ` Michał Grzelak
2026-07-01 15:32 ` [PATCH v2 32/34] drm/i915/kunit: DP link: add baseline fixed table reference test Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:31     ` Imre Deak
2026-07-01 15:32 ` [PATCH v2 33/34] drm/i915/kunit: DP link: add update config tests Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:46     ` Imre Deak
2026-07-01 15:32 ` [PATCH v2 34/34] drm/i915/kunit: DP link: add fallback tests Imre Deak
2026-07-04 10:51   ` Michał Grzelak
2026-07-06  7:51     ` Imre Deak
2026-07-01 16:39 ` ✗ CI.checkpatch: warning for drm/i915/dp_link: Unify modeset/fallback config selection Patchwork
2026-07-01 16:40 ` ✓ CI.KUnit: success " Patchwork
2026-07-01 16:59 ` ✗ CI.checksparse: warning " Patchwork
2026-07-01 17:43 ` ✓ Xe.CI.BAT: success " Patchwork
2026-07-02  1:54 ` ✓ i915.CI.BAT: " Patchwork
2026-07-02 12:25 ` ✓ Xe.CI.FULL: " Patchwork
2026-07-02 19:43 ` ✓ i915.CI.Full: " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260701153204.4124150-5-imre.deak@intel.com \
    --to=imre.deak@intel.com \
    --cc=intel-gfx@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.