drm/atomic: Ensure that drm_connector_index is stable
authorDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 19 Nov 2014 17:38:06 +0000 (18:38 +0100)
committerDave Airlie <airlied@redhat.com>
Thu, 20 Nov 2014 01:35:18 +0000 (11:35 +1000)
I've totally forgotten that with DP MST connectors can now be
hotplugged. And failed to adapt Rob's drm_atomic_state code (which
predates connector hotplugging) to the new realities.

The first step is to make sure that the connector indices used to
access the arrays of pointers are stable. The connection mutex gives
us enough guarantees for that, which means we won't unecessarily block
on concurrent modesets or background probing.

So add a locking WARN_ON and shuffle the code slightly to make sure we
always hold the right lock.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Reviewed-by: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_crtc.c

index ed22a719440f78d5a082287e955bb0782dee8cf8..90b2d1644bd7578597a121b608f58d9dea5f41ef 100644 (file)
@@ -295,15 +295,15 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
        struct drm_mode_config *config = &connector->dev->mode_config;
        struct drm_connector_state *connector_state;
 
+       ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
+       if (ret)
+               return ERR_PTR(ret);
+
        index = drm_connector_index(connector);
 
        if (state->connector_states[index])
                return state->connector_states[index];
 
-       ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
-       if (ret)
-               return ERR_PTR(ret);
-
        connector_state = connector->funcs->atomic_duplicate_state(connector);
        if (!connector_state)
                return ERR_PTR(-ENOMEM);
index 56737e74b59def3d825030a72ed9100e48847e3f..5c878f172365217ff8b93e564738f9795f8e9afa 100644 (file)
@@ -867,6 +867,8 @@ int drm_connector_init(struct drm_device *dev,
 
        drm_connector_get_cmdline_mode(connector);
 
+       /* We should add connectors at the end to avoid upsetting the connector
+        * index too much. */
        list_add_tail(&connector->head, &dev->mode_config.connector_list);
        dev->mode_config.num_connector++;
 
@@ -930,6 +932,9 @@ unsigned int drm_connector_index(struct drm_connector *connector)
 {
        unsigned int index = 0;
        struct drm_connector *tmp;
+       struct drm_mode_config *config = &connector->dev->mode_config;
+
+       WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));
 
        list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
                if (tmp == connector)