Hi Maxime,
At 2025-03-04 19:10:47, "Maxime Ripard" <mrip...@kernel.org> wrote: >With the bridges switching over to drm_bridge_connector, the direct >association between a bridge driver and its connector was lost. > >This is mitigated for atomic bridge drivers by the fact you can access >the encoder, and then call drm_atomic_get_old_connector_for_encoder() or >drm_atomic_get_new_connector_for_encoder() with drm_atomic_state. > >This was also made easier by providing drm_atomic_state directly to all >atomic hooks bridges can implement. > >However, bridge drivers don't have a way to access drm_atomic_state >outside of the modeset path, like from the hotplug interrupt path or any >interrupt handler. > >Let's introduce a function to retrieve the connector currently assigned >to an encoder, without using drm_atomic_state, to make these drivers' >life easier. > >Reviewed-by: Dmitry Baryshkov <dmitry.barysh...@linaro.org> >Co-developed-by: Simona Vetter <simona.vet...@ffwll.ch> >Signed-off-by: Maxime Ripard <mrip...@kernel.org> >--- > drivers/gpu/drm/drm_atomic.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ > include/drm/drm_atomic.h | 3 +++ > 2 files changed, 48 insertions(+) > >diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c >index >9ea2611770f43ce7ccba410406d5f2c528aab022..b926b132590e78f8d41d48eb4da4bccf170ee236 > 100644 >--- a/drivers/gpu/drm/drm_atomic.c >+++ b/drivers/gpu/drm/drm_atomic.c >@@ -985,10 +985,55 @@ drm_atomic_get_new_connector_for_encoder(const struct >drm_atomic_state *state, > > return NULL; > } > EXPORT_SYMBOL(drm_atomic_get_new_connector_for_encoder); > >+/** >+ * drm_atomic_get_connector_for_encoder - Get connector currently assigned to >an encoder >+ * @encoder: The encoder to find the connector of >+ * @ctx: Modeset locking context >+ * >+ * This function finds and returns the connector currently assigned to >+ * an @encoder. >+ * >+ * Returns: >+ * The connector connected to @encoder, or an error pointer otherwise. >+ * When the error is EDEADLK, a deadlock has been detected and the >+ * sequence must be restarted. >+ */ >+struct drm_connector * >+drm_atomic_get_connector_for_encoder(const struct drm_encoder *encoder, >+ struct drm_modeset_acquire_ctx *ctx) >+{ >+ struct drm_connector_list_iter conn_iter; >+ struct drm_connector *out_connector = ERR_PTR(-EINVAL); >+ struct drm_connector *connector; >+ struct drm_device *dev = encoder->dev; >+ int ret; >+ >+ ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); >+ if (ret) >+ return ERR_PTR(ret); It seems that this will cause a deadlock when called from a hotplug handling path, I have a WIP DP diver[0], which suggested by Dmitry to use this API from a &drm_bridge_funcs.detect callback to get the connector, as detect is called by drm_helper_probe_detect, which will hold connection_mutex first, so the deaklock happens: drm_helper_probe_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force) { const struct drm_connector_helper_funcs *funcs = connector->helper_private; struct drm_device *dev = connector->dev; int ret; if (!ctx) return drm_helper_probe_detect_ctx(connector, force); ret = drm_modeset_lock(&dev->mode_config.connection_mutex, ctx); if (ret) return ret; if (funcs->detect_ctx) ret = funcs->detect_ctx(connector, ctx, force); else if (connector->funcs->detect) ret = connector->funcs->detect(connector, force); else ret = connector_status_connected; if (ret != connector->status) connector->epoch_counter += 1; So I wonder can we let drm_bridge_funcs.detect pass a connector for this case ? [0]https://lore.kernel.org/linux-rockchip/047eecfc-7e55-44ec-896f-13fe04333...@gmail.com/T/#m25bc53b79f5cc7bddfcb7aae5656f68df396f094 >+ >+ drm_connector_list_iter_begin(dev, &conn_iter); >+ drm_for_each_connector_iter(connector, &conn_iter) { >+ if (!connector->state) >+ continue; >+ >+ if (encoder == connector->state->best_encoder) { >+ out_connector = connector; >+ break; >+ } >+ } >+ drm_connector_list_iter_end(&conn_iter); >+ drm_modeset_unlock(&dev->mode_config.connection_mutex); >+ >+ return out_connector; >+} >+EXPORT_SYMBOL(drm_atomic_get_connector_for_encoder); >+ >+ > /** > * drm_atomic_get_old_crtc_for_encoder - Get old crtc for an encoder > * @state: Atomic state > * @encoder: The encoder to fetch the crtc state for > * >diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h >index >4c673f0698fef6b60f77db980378d5e88e0e250e..38636a593c9d98cadda85ccd67326cb152f0dd27 > 100644 >--- a/include/drm/drm_atomic.h >+++ b/include/drm/drm_atomic.h >@@ -623,10 +623,13 @@ struct drm_connector * > drm_atomic_get_old_connector_for_encoder(const struct drm_atomic_state *state, > struct drm_encoder *encoder); > struct drm_connector * > drm_atomic_get_new_connector_for_encoder(const struct drm_atomic_state *state, > struct drm_encoder *encoder); >+struct drm_connector * >+drm_atomic_get_connector_for_encoder(const struct drm_encoder *encoder, >+ struct drm_modeset_acquire_ctx *ctx); > > struct drm_crtc * > drm_atomic_get_old_crtc_for_encoder(struct drm_atomic_state *state, > struct drm_encoder *encoder); > struct drm_crtc * > >-- >2.48.1