diff options
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_crtc_helper.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_fb_helper.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_modeset_helper.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_plane_helper.c | 5 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_probe_helper.c | 18 |
6 files changed, 92 insertions, 33 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 23767df..e2e15a9 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -94,9 +94,10 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, { struct drm_connector_state *conn_state; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; struct drm_encoder *encoder; unsigned encoder_mask = 0; - int i, ret; + int i, ret = 0; /* * First loop, find all newly assigned encoders from the connectors @@ -144,7 +145,8 @@ 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_connector_list_iter_get(state->dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct drm_crtc_state *crtc_state; if (drm_atomic_get_existing_connector_state(state, connector)) @@ -160,12 +162,15 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, connector->state->crtc->base.id, connector->state->crtc->name, connector->base.id, connector->name); - return -EINVAL; + ret = -EINVAL; + goto out; } conn_state = drm_atomic_get_connector_state(state, connector); - if (IS_ERR(conn_state)) - return PTR_ERR(conn_state); + if (IS_ERR(conn_state)) { + ret = PTR_ERR(conn_state); + goto out; + } DRM_DEBUG_ATOMIC("[ENCODER:%d:%s] in use on [CRTC:%d:%s], disabling [CONNECTOR:%d:%s]\n", encoder->base.id, encoder->name, @@ -176,19 +181,21 @@ static int handle_conflicting_encoders(struct drm_atomic_state *state, ret = drm_atomic_set_crtc_for_connector(conn_state, NULL); if (ret) - return ret; + goto out; if (!crtc_state->connector_mask) { ret = drm_atomic_set_mode_prop_for_crtc(crtc_state, NULL); if (ret < 0) - return ret; + goto out; crtc_state->active = false; } } +out: + drm_connector_list_iter_put(&conn_iter); - return 0; + return ret; } static void @@ -2442,6 +2449,7 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, { struct drm_atomic_state *state; struct drm_connector *conn; + struct drm_connector_list_iter conn_iter; int err; state = drm_atomic_state_alloc(dev); @@ -2450,7 +2458,8 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, state->acquire_ctx = ctx; - drm_for_each_connector(conn, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { struct drm_crtc *crtc = conn->state->crtc; struct drm_crtc_state *crtc_state; @@ -2468,6 +2477,7 @@ int drm_atomic_helper_disable_all(struct drm_device *dev, err = drm_atomic_commit(state); free: + drm_connector_list_iter_put(&conn_iter); drm_atomic_state_put(state); return err; } @@ -2840,6 +2850,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_list_iter conn_iter; int ret; bool active = false; int old_mode = connector->dpms; @@ -2867,7 +2878,8 @@ retry: WARN_ON(!drm_modeset_is_locked(&config->connection_mutex)); - drm_for_each_connector(tmp_connector, connector->dev) { + drm_connector_list_iter_get(connector->dev, &conn_iter); + drm_for_each_connector_iter(tmp_connector, &conn_iter) { if (tmp_connector->state->crtc != crtc) continue; @@ -2876,6 +2888,7 @@ retry: break; } } + drm_connector_list_iter_put(&conn_iter); crtc_state->active = active; ret = drm_atomic_commit(state); @@ -3253,6 +3266,7 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, { struct drm_atomic_state *state; struct drm_connector *conn; + struct drm_connector_list_iter conn_iter; struct drm_plane *plane; struct drm_crtc *crtc; int err = 0; @@ -3283,15 +3297,18 @@ drm_atomic_helper_duplicate_state(struct drm_device *dev, } } - drm_for_each_connector(conn, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(conn, &conn_iter) { struct drm_connector_state *conn_state; conn_state = drm_atomic_get_connector_state(state, conn); if (IS_ERR(conn_state)) { err = PTR_ERR(conn_state); + drm_connector_list_iter_put(&conn_iter); goto free; } } + drm_connector_list_iter_put(&conn_iter); /* clear the acquire context so that it isn't accidentally reused */ state->acquire_ctx = NULL; diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 2606175..923a17c 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c @@ -89,6 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder) { struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; struct drm_device *dev = encoder->dev; /* @@ -100,9 +101,15 @@ 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) - if (connector->encoder == encoder) + + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->encoder == encoder) { + drm_connector_list_iter_put(&conn_iter); return true; + } + } + drm_connector_list_iter_put(&conn_iter); return false; } EXPORT_SYMBOL(drm_helper_encoder_in_use); @@ -437,10 +444,13 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) /* Decouple all encoders and their attached connectors from this crtc */ drm_for_each_encoder(encoder, dev) { + struct drm_connector_list_iter conn_iter; + if (encoder->crtc != crtc) continue; - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder != encoder) continue; @@ -457,6 +467,7 @@ drm_crtc_helper_disable(struct drm_crtc *crtc) /* we keep a reference while the encoder is bound */ drm_connector_unreference(connector); } + drm_connector_list_iter_put(&conn_iter); } __drm_helper_disable_unused_functions(dev); @@ -508,6 +519,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) bool mode_changed = false; /* if true do a full mode set */ bool fb_changed = false; /* if true and !mode_changed just do a flip */ struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; int count = 0, ro, fail = 0; const struct drm_crtc_helper_funcs *crtc_funcs; struct drm_mode_set save_set; @@ -572,9 +584,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } count = 0; - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) save_connector_encoders[count++] = connector->encoder; - } + drm_connector_list_iter_put(&conn_iter); save_set.crtc = set->crtc; save_set.mode = &set->crtc->mode; @@ -616,7 +629,8 @@ 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_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { const struct drm_connector_helper_funcs *connector_funcs = connector->helper_private; new_encoder = connector->encoder; @@ -649,6 +663,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) connector->encoder = new_encoder; } } + drm_connector_list_iter_put(&conn_iter); if (fail) { ret = -EINVAL; @@ -656,7 +671,8 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) } count = 0; - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (!connector->encoder) continue; @@ -674,6 +690,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) if (new_crtc && !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { ret = -EINVAL; + drm_connector_list_iter_put(&conn_iter); goto fail; } if (new_crtc != connector->encoder->crtc) { @@ -690,6 +707,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set) connector->base.id, connector->name); } } + drm_connector_list_iter_put(&conn_iter); /* mode_set_base is not a required function */ if (fb_changed && !crtc_funcs->mode_set_base) @@ -744,9 +762,10 @@ fail: } count = 0; - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) connector->encoder = save_connector_encoders[count++]; - } + drm_connector_list_iter_put(&conn_iter); /* after fail drop reference on all unbound connectors in set, let * bound connectors keep their reference @@ -773,12 +792,16 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) { int dpms = DRM_MODE_DPMS_OFF; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; struct drm_device *dev = encoder->dev; - drm_for_each_connector(connector, dev) + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) if (connector->encoder == encoder) if (connector->dpms < dpms) dpms = connector->dpms; + drm_connector_list_iter_put(&conn_iter); + return dpms; } @@ -810,12 +833,16 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) { int dpms = DRM_MODE_DPMS_OFF; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; struct drm_device *dev = crtc->dev; - drm_for_each_connector(connector, dev) + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) if (connector->encoder && connector->encoder->crtc == crtc) if (connector->dpms < dpms) dpms = connector->dpms; + drm_connector_list_iter_put(&conn_iter); + return dpms; } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index bee5e41..145d55f 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -120,20 +120,22 @@ 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; - int i, ret; + struct drm_connector_list_iter conn_iter; + int i, ret = 0; if (!drm_fbdev_emulation) return 0; mutex_lock(&dev->mode_config.mutex); - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { ret = drm_fb_helper_add_one_connector(fb_helper, connector); if (ret) goto fail; } - mutex_unlock(&dev->mode_config.mutex); - return 0; + goto out; + fail: drm_fb_helper_for_each_connector(fb_helper, i) { struct drm_fb_helper_connector *fb_helper_connector = @@ -145,6 +147,8 @@ fail: fb_helper->connector_info[i] = NULL; } fb_helper->connector_count = 0; +out: + drm_connector_list_iter_put(&conn_iter); mutex_unlock(&dev->mode_config.mutex); return ret; diff --git a/drivers/gpu/drm/drm_modeset_helper.c b/drivers/gpu/drm/drm_modeset_helper.c index b4f3665..cc44a9a 100644 --- a/drivers/gpu/drm/drm_modeset_helper.c +++ b/drivers/gpu/drm/drm_modeset_helper.c @@ -48,6 +48,7 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) INIT_LIST_HEAD(&panel_list); + spin_lock_irq(&dev->mode_config.connector_list_lock); list_for_each_entry_safe(connector, tmp, &dev->mode_config.connector_list, head) { if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS || @@ -57,6 +58,7 @@ void drm_helper_move_panel_connectors_to_head(struct drm_device *dev) } list_splice(&panel_list, &dev->mode_config.connector_list); + spin_unlock_irq(&dev->mode_config.connector_list_lock); } EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c index 191a5f0..8b042a1 100644 --- a/drivers/gpu/drm/drm_plane_helper.c +++ b/drivers/gpu/drm/drm_plane_helper.c @@ -75,6 +75,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; int count = 0; /* @@ -84,7 +85,8 @@ 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_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder && connector->encoder->crtc == crtc) { if (connector_list != NULL && count < num_connectors) *(connector_list++) = connector; @@ -92,6 +94,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc, count++; } } + drm_connector_list_iter_put(&conn_iter); return count; } diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index ac953f0..7cff91e 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -129,6 +129,7 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev) { bool poll = false; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; unsigned long delay = DRM_OUTPUT_POLL_PERIOD; WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); @@ -136,11 +137,13 @@ void drm_kms_helper_poll_enable_locked(struct drm_device *dev) if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) return; - drm_for_each_connector(connector, dev) { + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT)) poll = true; } + drm_connector_list_iter_put(&conn_iter); if (dev->mode_config.delayed_event) { poll = true; @@ -382,6 +385,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_list_iter conn_iter; enum drm_connector_status old_status; bool repoll = false, changed; @@ -397,8 +401,8 @@ static void output_poll_execute(struct work_struct *work) goto out; } - drm_for_each_connector(connector, dev) { - + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { /* Ignore forced connectors. */ if (connector->force) continue; @@ -451,6 +455,7 @@ static void output_poll_execute(struct work_struct *work) changed = true; } } + drm_connector_list_iter_put(&conn_iter); mutex_unlock(&dev->mode_config.mutex); @@ -562,6 +567,7 @@ EXPORT_SYMBOL(drm_kms_helper_poll_fini); bool drm_helper_hpd_irq_event(struct drm_device *dev) { struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; enum drm_connector_status old_status; bool changed = false; @@ -569,8 +575,8 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) return false; mutex_lock(&dev->mode_config.mutex); - drm_for_each_connector(connector, dev) { - + drm_connector_list_iter_get(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { /* Only handle HPD capable connectors. */ if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) continue; @@ -586,7 +592,7 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev) if (old_status != connector->status) changed = true; } - + drm_connector_list_iter_put(&conn_iter); mutex_unlock(&dev->mode_config.mutex); if (changed) |