There's various proposals floating around for how to exactly fix
the connector_list locking issue. Most of them need a more fancy
iterator, with a bit more state. Prep for that by creating a
dummy struct drm_connector_iter and add is as a paramter everywhere.

To appease gcc have a dummy member and assign that - avoids a dreaded
unused variable warning.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/drm_atomic.c            |  3 ++-
 drivers/gpu/drm/drm_atomic_helper.c     | 12 ++++++++----
 drivers/gpu/drm/drm_crtc.c              | 12 ++++++++----
 drivers/gpu/drm/drm_crtc_helper.c       | 21 +++++++++++++--------
 drivers/gpu/drm/drm_edid.c              |  3 ++-
 drivers/gpu/drm/drm_fb_helper.c         |  3 ++-
 drivers/gpu/drm/drm_plane_helper.c      |  3 ++-
 drivers/gpu/drm/drm_probe_helper.c      |  9 ++++++---
 drivers/gpu/drm/exynos/exynos_drm_drv.c |  6 ++++--
 drivers/gpu/drm/i915/intel_display.c    |  6 ++++--
 drivers/gpu/drm/vc4/vc4_crtc.c          |  3 ++-
 include/drm/drm_crtc.h                  |  9 +++++++--
 12 files changed, 60 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index dac0875e669c..24d473fbf6ae 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1224,6 +1224,7 @@ drm_atomic_add_affected_connectors(struct 
drm_atomic_state *state,
        struct drm_mode_config *config = &state->dev->mode_config;
        struct drm_connector *connector;
        struct drm_connector_state *conn_state;
+       struct drm_connector_iter iter;
        int ret;

        ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
@@ -1237,7 +1238,7 @@ drm_atomic_add_affected_connectors(struct 
drm_atomic_state *state,
         * Changed connectors are already in @state, so only need to look at the
         * current configuration.
         */
-       drm_for_each_connector(connector, state->dev) {
+       drm_for_each_connector(connector, state->dev, iter) {
                if (connector->state->crtc != crtc)
                        continue;

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index de7fddce3cef..02eee8164a55 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -93,6 +93,7 @@ static int handle_conflicting_encoders(struct 
drm_atomic_state *state,
        struct drm_connector_state *conn_state;
        struct drm_connector *connector;
        struct drm_encoder *encoder;
+       struct drm_connector_iter iter;
        unsigned encoder_mask = 0;
        int i, ret;

@@ -142,7 +143,7 @@ static int handle_conflicting_encoders(struct 
drm_atomic_state *state,
         * and the crtc is disabled if no encoder is left. This preserves
         * compatibility with the legacy set_config behavior.
         */
-       drm_for_each_connector(connector, state->dev) {
+       drm_for_each_connector(connector, state->dev, iter) {
                struct drm_crtc_state *crtc_state;

                if (drm_atomic_get_existing_connector_state(state, connector))
@@ -2390,6 +2391,7 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,
 {
        struct drm_atomic_state *state;
        struct drm_connector *conn;
+       struct drm_connector_iter iter;
        int err;

        state = drm_atomic_state_alloc(dev);
@@ -2398,7 +2400,7 @@ int drm_atomic_helper_disable_all(struct drm_device *dev,

        state->acquire_ctx = ctx;

-       drm_for_each_connector(conn, dev) {
+       drm_for_each_connector(conn, dev, iter) {
                struct drm_crtc *crtc = conn->state->crtc;
                struct drm_crtc_state *crtc_state;

@@ -2811,6 +2813,7 @@ int drm_atomic_helper_connector_dpms(struct drm_connector 
*connector,
        struct drm_crtc_state *crtc_state;
        struct drm_crtc *crtc;
        struct drm_connector *tmp_connector;
+       struct drm_connector_iter iter;
        int ret;
        bool active = false;
        int old_mode = connector->dpms;
@@ -2838,7 +2841,7 @@ retry:

        WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));

-       drm_for_each_connector(tmp_connector, connector->dev) {
+       drm_for_each_connector(tmp_connector, connector->dev, iter) {
                if (tmp_connector->state->crtc != crtc)
                        continue;

@@ -3225,6 +3228,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
        struct drm_connector *conn;
        struct drm_plane *plane;
        struct drm_crtc *crtc;
+       struct drm_connector_iter iter;
        int err = 0;

        state = drm_atomic_state_alloc(dev);
@@ -3253,7 +3257,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev,
                }
        }

-       drm_for_each_connector(conn, dev) {
+       drm_for_each_connector(conn, dev, iter) {
                struct drm_connector_state *conn_state;

                conn_state = drm_atomic_get_connector_state(state, conn);
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 4f18299dc630..2a927488ec26 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1068,11 +1068,12 @@ EXPORT_SYMBOL(drm_connector_unregister);
 int drm_connector_register_all(struct drm_device *dev)
 {
        struct drm_connector *connector;
+       struct drm_connector_iter iter;
        int ret;

        mutex_lock(&dev->mode_config.mutex);

-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                ret = drm_connector_register(connector);
                if (ret)
                        goto err;
@@ -1841,6 +1842,7 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
        struct drm_connector *connector;
        struct drm_crtc *crtc;
        struct drm_encoder *encoder;
+       struct drm_connector_iter iter;
        int ret = 0;
        int connector_count = READ_ONCE(dev->mode_config.num_connector);
        int crtc_count = dev->mode_config.num_crtc;
@@ -1921,7 +1923,7 @@ int drm_mode_getresources(struct drm_device *dev, void 
*data,
        if (card_res->count_connectors >= connector_count) {
                copied = 0;
                connector_id = (uint32_t __user *)(unsigned 
long)card_res->connector_id_ptr;
-               drm_for_each_connector(connector, dev) {
+               drm_for_each_connector(connector, dev, iter) {
                        if (put_user(connector->base.id,
                                     connector_id + copied)) {
                                ret = -EFAULT;
@@ -2188,11 +2190,12 @@ static struct drm_crtc *drm_encoder_get_crtc(struct 
drm_encoder *encoder)
 {
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
+       struct drm_connector_iter iter;
        bool uses_atomic = false;

        /* For atomic drivers only state objects are synchronously updated and
         * protected by modeset locks, so check those first. */
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                if (!connector->state)
                        continue;

@@ -5379,6 +5382,7 @@ void drm_mode_config_reset(struct drm_device *dev)
        struct drm_plane *plane;
        struct drm_encoder *encoder;
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

        drm_for_each_plane(plane, dev)
                if (plane->funcs->reset)
@@ -5393,7 +5397,7 @@ void drm_mode_config_reset(struct drm_device *dev)
                        encoder->funcs->reset(encoder);

        mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_connector(connector, dev)
+       drm_for_each_connector(connector, dev, iter)
                if (connector->funcs->reset)
                        connector->funcs->reset(connector);
        mutex_unlock(&dev->mode_config.mutex);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index 604d3ef72ffa..ef3ccbec8a5b 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -118,6 +118,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
 {
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
+       struct drm_connector_iter iter;

        /*
         * We can expect this mutex to be locked if we are not panicking.
@@ -128,7 +129,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
                
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
        }

-       drm_for_each_connector(connector, dev)
+       drm_for_each_connector(connector, dev, iter)
                if (connector->encoder == encoder)
                        return true;
        return false;
@@ -462,13 +463,14 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct drm_connector *connector;
        struct drm_encoder *encoder;
+       struct drm_connector_iter iter;

        /* Decouple all encoders and their attached connectors from this crtc */
        drm_for_each_encoder(encoder, dev) {
                if (encoder->crtc != crtc)
                        continue;

-               drm_for_each_connector(connector, dev) {
+               drm_for_each_connector(connector, dev, iter) {
                        if (connector->encoder != encoder)
                                continue;

@@ -539,6 +541,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        int count = 0, ro, fail = 0;
        const struct drm_crtc_helper_funcs *crtc_funcs;
        struct drm_mode_set save_set;
+       struct drm_connector_iter iter;
        int ret;
        int i;

@@ -600,7 +603,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        }

        count = 0;
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                save_connector_encoders[count++] = connector->encoder;
        }

@@ -645,7 +648,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)

        /* a) traverse passed in connector list and get encoders for them */
        count = 0;
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                const struct drm_connector_helper_funcs *connector_funcs =
                        connector->helper_private;
                new_encoder = connector->encoder;
@@ -685,7 +688,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        }

        count = 0;
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                if (!connector->encoder)
                        continue;

@@ -773,7 +776,7 @@ fail:
        }

        count = 0;
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                connector->encoder = save_connector_encoders[count++];
        }

@@ -803,8 +806,9 @@ static int drm_helper_choose_encoder_dpms(struct 
drm_encoder *encoder)
        int dpms = DRM_MODE_DPMS_OFF;
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
+       struct drm_connector_iter iter;

-       drm_for_each_connector(connector, dev)
+       drm_for_each_connector(connector, dev, iter)
                if (connector->encoder == encoder)
                        if (connector->dpms < dpms)
                                dpms = connector->dpms;
@@ -840,8 +844,9 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc 
*crtc)
        int dpms = DRM_MODE_DPMS_OFF;
        struct drm_connector *connector;
        struct drm_device *dev = crtc->dev;
+       struct drm_connector_iter iter;

-       drm_for_each_connector(connector, dev)
+       drm_for_each_connector(connector, dev, iter)
                if (connector->encoder && connector->encoder->crtc == crtc)
                        if (connector->dpms < dpms)
                                dpms = connector->dpms;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 553390fae803..bc07e4817471 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3600,11 +3600,12 @@ struct drm_connector *drm_select_eld(struct drm_encoder 
*encoder)
 {
        struct drm_connector *connector;
        struct drm_device *dev = encoder->dev;
+       struct drm_connector_iter iter;

        WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
        WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));

-       drm_for_each_connector(connector, dev)
+       drm_for_each_connector(connector, dev, iter)
                if (connector->encoder == encoder && connector->eld[0])
                        return connector;

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a06f9120b5a..966ea19a02b8 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -113,13 +113,14 @@ int drm_fb_helper_single_add_all_connectors(struct 
drm_fb_helper *fb_helper)
 {
        struct drm_device *dev = fb_helper->dev;
        struct drm_connector *connector;
+       struct drm_connector_iter iter;
        int i, ret;

        if (!drm_fbdev_emulation)
                return 0;

        mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                ret = drm_fb_helper_add_one_connector(fb_helper, connector);

                if (ret)
diff --git a/drivers/gpu/drm/drm_plane_helper.c 
b/drivers/gpu/drm/drm_plane_helper.c
index 16c4a7bd7465..f334c70b1044 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -86,6 +86,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
 {
        struct drm_device *dev = crtc->dev;
        struct drm_connector *connector;
+       struct drm_connector_iter iter;
        int count = 0;

        /*
@@ -95,7 +96,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
         */
        WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));

-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                if (connector->encoder && connector->encoder->crtc == crtc) {
                        if (connector_list != NULL && count < num_connectors)
                                *(connector_list++) = connector;
diff --git a/drivers/gpu/drm/drm_probe_helper.c 
b/drivers/gpu/drm/drm_probe_helper.c
index a0df377d7d1c..f113ed87fefb 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -129,13 +129,14 @@ void drm_kms_helper_poll_enable_locked(struct drm_device 
*dev)
 {
        bool poll = false;
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

        WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));

        if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll)
                return;

-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT |
                                         DRM_CONNECTOR_POLL_DISCONNECT))
                        poll = true;
@@ -368,6 +369,7 @@ static void output_poll_execute(struct work_struct *work)
        struct delayed_work *delayed_work = to_delayed_work(work);
        struct drm_device *dev = container_of(delayed_work, struct drm_device, 
mode_config.output_poll_work);
        struct drm_connector *connector;
+       struct drm_connector_iter iter;
        enum drm_connector_status old_status;
        bool repoll = false, changed;

@@ -379,7 +381,7 @@ static void output_poll_execute(struct work_struct *work)
                goto out;

        mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {

                /* Ignore forced connectors. */
                if (connector->force)
@@ -545,13 +547,14 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
 {
        struct drm_connector *connector;
        enum drm_connector_status old_status;
+       struct drm_connector_iter iter;
        bool changed = false;

        if (!dev->mode_config.poll_enabled)
                return false;

        mutex_lock(&dev->mode_config.mutex);
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {

                /* Only handle HPD capable connectors. */
                if (!(connector->polled & DRM_CONNECTOR_POLL_HPD))
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c 
b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 13d28d4229e2..4f4fa0e17e82 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -439,12 +439,13 @@ static int exynos_drm_suspend(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

        if (pm_runtime_suspended(dev) || !drm_dev)
                return 0;

        drm_modeset_lock_all(drm_dev);
-       drm_for_each_connector(connector, drm_dev) {
+       drm_for_each_connector(connector, drm_dev, iter) {
                int old_dpms = connector->dpms;

                if (connector->funcs->dpms)
@@ -462,12 +463,13 @@ static int exynos_drm_resume(struct device *dev)
 {
        struct drm_device *drm_dev = dev_get_drvdata(dev);
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

        if (pm_runtime_suspended(dev) || !drm_dev)
                return 0;

        drm_modeset_lock_all(drm_dev);
-       drm_for_each_connector(connector, drm_dev) {
+       drm_for_each_connector(connector, drm_dev, iter) {
                if (connector->funcs->dpms) {
                        int dpms = connector->dpms;

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 0b2cd669ac05..dc33bf278cc2 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -12412,6 +12412,7 @@ static bool check_digital_port_conflicts(struct 
drm_atomic_state *state)
 {
        struct drm_device *dev = state->dev;
        struct drm_connector *connector;
+       struct drm_connector_iter iter;
        unsigned int used_ports = 0;

        /*
@@ -12419,7 +12420,7 @@ static bool check_digital_port_conflicts(struct 
drm_atomic_state *state)
         * list to detect the problem on ddi platforms
         * where there's just one encoder per digital port.
         */
-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                struct drm_connector_state *connector_state;
                struct intel_encoder *encoder;

@@ -12997,8 +12998,9 @@ static void
 verify_connector_state(struct drm_device *dev, struct drm_crtc *crtc)
 {
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

-       drm_for_each_connector(connector, dev) {
+       drm_for_each_connector(connector, dev, iter) {
                struct drm_encoder *encoder = connector->encoder;
                struct drm_connector_state *state = connector->state;

diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index c82d468d178b..72f2962e9d70 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -218,8 +218,9 @@ static u32 vc4_get_fifo_full_level(u32 format)
 static int vc4_get_clock_select(struct drm_crtc *crtc)
 {
        struct drm_connector *connector;
+       struct drm_connector_iter iter;

-       drm_for_each_connector(connector, crtc->dev) {
+       drm_for_each_connector(connector, crtc->dev, iter) {
                if (connector->state->crtc == crtc) {
                        struct drm_encoder *encoder = connector->encoder;
                        struct vc4_encoder *vc4_encoder =
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index efef0614703a..ba574b9c1ec4 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -2849,8 +2849,13 @@ assert_drm_connector_list_read_locked(struct 
drm_mode_config *mode_config)
                !drm_modeset_is_locked(&mode_config->connection_mutex));
 }

-#define drm_for_each_connector(connector, dev) \
-       for (assert_drm_connector_list_read_locked(&(dev)->mode_config),        
\
+struct drm_connector_iter {
+       struct drm_mode_config *mode_config;
+};
+
+#define drm_for_each_connector(connector, dev, iter) \
+       for ((iter).mode_config = NULL,                                         
\
+            assert_drm_connector_list_read_locked(&(dev)->mode_config),        
\
             connector = list_first_entry(&(dev)->mode_config.connector_list,   
\
                                          struct drm_connector, head);          
\
             &connector->head != (&(dev)->mode_config.connector_list);          
\
-- 
2.8.1

Reply via email to