The driver might pull connectors which weren't submitted by
user-space into the atomic state. For instance,
intel_dp_mst_atomic_master_trans_check() pulls in connectors
sharing the same DP-MST stream. However, if the connector is
unregistered, this later fails with:

    [  559.425658] i915 0000:00:02.0: [drm:drm_atomic_helper_check_modeset] 
[CONNECTOR:378:DP-7] is not registered

Skip the unregistered connector check to allow user-space to turn
off connectors one-by-one.

See this wlroots issue:
https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3407

Previous discussion:
https://lore.kernel.org/intel-gfx/y6gx7z17wmdsk...@ideak-desk.fi.intel.com/

Signed-off-by: Simon Ser <cont...@emersion.fr>
Cc: Ville Syrjälä <ville.syrj...@linux.intel.com>
Cc: Jani Nikula <jani.nik...@intel.com>
Cc: Lyude Paul <ly...@redhat.com>
Cc: Imre Deak <imre.d...@intel.com>
---
 drivers/gpu/drm/drm_atomic_helper.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 71d399397107..c9b8343eaa20 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -290,7 +290,8 @@ static int
 update_connector_routing(struct drm_atomic_state *state,
                         struct drm_connector *connector,
                         struct drm_connector_state *old_connector_state,
-                        struct drm_connector_state *new_connector_state)
+                        struct drm_connector_state *new_connector_state,
+                        bool added_by_user)
 {
        const struct drm_connector_helper_funcs *funcs;
        struct drm_encoder *new_encoder;
@@ -339,9 +340,13 @@ update_connector_routing(struct drm_atomic_state *state,
         * there's a chance the connector may have been destroyed during the
         * process, but it's better to ignore that then cause
         * drm_atomic_helper_resume() to fail.
+        *
+        * Last, we want to ignore connector registration when the connector
+        * was not pulled in the atomic state by user-space (ie, was pulled
+        * in by the driver, e.g. when updating a DP-MST stream).
         */
        if (!state->duplicated && drm_connector_is_unregistered(connector) &&
-           crtc_state->active) {
+           added_by_user && crtc_state->active) {
                drm_dbg_atomic(connector->dev,
                               "[CONNECTOR:%d:%s] is not registered\n",
                               connector->base.id, connector->name);
@@ -620,7 +625,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
        struct drm_connector *connector;
        struct drm_connector_state *old_connector_state, *new_connector_state;
        int i, ret;
-       unsigned int connectors_mask = 0;
+       unsigned int connectors_mask = 0, user_connectors_mask = 0;
+
+       for_each_oldnew_connector_in_state(state, connector, 
old_connector_state, new_connector_state, i)
+               user_connectors_mask |= BIT(i);
 
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, 
new_crtc_state, i) {
                bool has_connectors =
@@ -685,7 +693,8 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
                 */
                ret = update_connector_routing(state, connector,
                                               old_connector_state,
-                                              new_connector_state);
+                                              new_connector_state,
+                                                  BIT(i) & 
user_connectors_mask);
                if (ret)
                        return ret;
                if (old_connector_state->crtc) {
-- 
2.42.0

Reply via email to