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@xxxxxxxx> --- 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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx