diff options
Diffstat (limited to 'drivers/gpu/drm/drm_atomic_helper.c')
-rw-r--r-- | drivers/gpu/drm/drm_atomic_helper.c | 362 |
1 files changed, 222 insertions, 140 deletions
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 4594477dee00..01d936b7be43 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -56,9 +56,9 @@ * implement these functions themselves but must use the provided helpers. * * The atomic helper uses the same function table structures as all other - * modesetting helpers. See the documentation for struct &drm_crtc_helper_funcs, - * struct &drm_encoder_helper_funcs and struct &drm_connector_helper_funcs. It - * also shares the struct &drm_plane_helper_funcs function table with the plane + * modesetting helpers. See the documentation for &struct drm_crtc_helper_funcs, + * struct &drm_encoder_helper_funcs and &struct drm_connector_helper_funcs. It + * also shares the &struct drm_plane_helper_funcs function table with the plane * helpers. */ static void @@ -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 @@ -362,7 +369,7 @@ mode_fixup(struct drm_atomic_state *state) struct drm_connector *connector; struct drm_connector_state *conn_state; int i; - bool ret; + int ret; for_each_crtc_in_state(state, crtc, crtc_state, i) { if (!crtc_state->mode_changed && @@ -451,22 +458,25 @@ mode_fixup(struct drm_atomic_state *state) * Check the state object to see if the requested state is physically possible. * This does all the crtc and connector related computations for an atomic * update and adds any additional connectors needed for full modesets and calls - * down into ->mode_fixup functions of the driver backend. - * - * crtc_state->mode_changed is set when the input mode is changed. - * crtc_state->connectors_changed is set when a connector is added or - * removed from the crtc. - * crtc_state->active_changed is set when crtc_state->active changes, - * which is used for dpms. + * down into &drm_crtc_helper_funcs.mode_fixup and + * &drm_encoder_helper_funcs.mode_fixup or + * &drm_encoder_helper_funcs.atomic_check functions of the driver backend. + * + * &drm_crtc_state.mode_changed is set when the input mode is changed. + * &drm_crtc_state.connectors_changed is set when a connector is added or + * removed from the crtc. &drm_crtc_state.active_changed is set when + * &drm_crtc_state.active changes, which is used for DPMS. * See also: drm_atomic_crtc_needs_modeset() * * IMPORTANT: * - * Drivers which set ->mode_changed (e.g. in their ->atomic_check hooks if a - * plane update can't be done without a full modeset) _must_ call this function - * afterwards after that change. It is permitted to call this function multiple - * times for the same update, e.g. when the ->atomic_check functions depend upon - * the adjusted dotclock for fifo space allocation and watermark computation. + * Drivers which set &drm_crtc_state.mode_changed (e.g. in their + * &drm_plane_helper_funcs.atomic_check hooks if a plane update can't be done + * without a full modeset) _must_ call this function afterwards after that + * change. It is permitted to call this function multiple times for the same + * update, e.g. when the &drm_crtc_helper_funcs.atomic_check functions depend + * upon the adjusted dotclock for fifo space allocation and watermark + * computation. * * RETURNS: * Zero for success or -errno @@ -577,9 +587,10 @@ EXPORT_SYMBOL(drm_atomic_helper_check_modeset); * * Check the state object to see if the requested state is physically possible. * This does all the plane update related checks using by calling into the - * ->atomic_check hooks provided by the driver. + * &drm_crtc_helper_funcs.atomic_check and &drm_plane_helper_funcs.atomic_check + * hooks provided by the driver. * - * It also sets crtc_state->planes_changed to indicate that a crtc has + * It also sets &drm_crtc_state.planes_changed to indicate that a crtc has * updated planes. * * RETURNS: @@ -641,14 +652,15 @@ EXPORT_SYMBOL(drm_atomic_helper_check_planes); * Check the state object to see if the requested state is physically possible. * Only crtcs and planes have check callbacks, so for any additional (global) * checking that a driver needs it can simply wrap that around this function. - * Drivers without such needs can directly use this as their ->atomic_check() - * callback. + * Drivers without such needs can directly use this as their + * &drm_mode_config_funcs.atomic_check callback. * * This just wraps the two parts of the state checking for planes and modeset * state in the default order: First it calls drm_atomic_helper_check_modeset() * and then drm_atomic_helper_check_planes(). The assumption is that the - * ->atomic_check functions depend upon an updated adjusted_mode.clock to - * e.g. properly compute watermarks. + * @drm_plane_helper_funcs.atomic_check and @drm_crtc_helper_funcs.atomic_check + * functions depend upon an updated adjusted_mode.clock to e.g. properly compute + * watermarks. * * RETURNS: * Zero for success or -errno @@ -1058,41 +1070,6 @@ int drm_atomic_helper_wait_for_fences(struct drm_device *dev, EXPORT_SYMBOL(drm_atomic_helper_wait_for_fences); /** - * drm_atomic_helper_framebuffer_changed - check if framebuffer has changed - * @dev: DRM device - * @old_state: atomic state object with old state structures - * @crtc: DRM crtc - * - * Checks whether the framebuffer used for this CRTC changes as a result of - * the atomic update. This is useful for drivers which cannot use - * drm_atomic_helper_wait_for_vblanks() and need to reimplement its - * functionality. - * - * Returns: - * true if the framebuffer changed. - */ -bool drm_atomic_helper_framebuffer_changed(struct drm_device *dev, - struct drm_atomic_state *old_state, - struct drm_crtc *crtc) -{ - struct drm_plane *plane; - struct drm_plane_state *old_plane_state; - int i; - - for_each_plane_in_state(old_state, plane, old_plane_state, i) { - if (plane->state->crtc != crtc && - old_plane_state->crtc != crtc) - continue; - - if (plane->state->fb != old_plane_state->fb) - return true; - } - - return false; -} -EXPORT_SYMBOL(drm_atomic_helper_framebuffer_changed); - -/** * drm_atomic_helper_wait_for_vblanks - wait for vblank on crtcs * @dev: DRM device * @old_state: atomic state object with old state structures @@ -1110,39 +1087,35 @@ drm_atomic_helper_wait_for_vblanks(struct drm_device *dev, struct drm_crtc *crtc; struct drm_crtc_state *old_crtc_state; int i, ret; + unsigned crtc_mask = 0; - for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { - /* No one cares about the old state, so abuse it for tracking - * and store whether we hold a vblank reference (and should do a - * vblank wait) in the ->enable boolean. */ - old_crtc_state->enable = false; - - if (!crtc->state->enable) - continue; + /* + * Legacy cursor ioctls are completely unsynced, and userspace + * relies on that (by doing tons of cursor updates). + */ + if (old_state->legacy_cursor_update) + return; - /* Legacy cursor ioctls are completely unsynced, and userspace - * relies on that (by doing tons of cursor updates). */ - if (old_state->legacy_cursor_update) - continue; + for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { + struct drm_crtc_state *new_crtc_state = crtc->state; - if (!drm_atomic_helper_framebuffer_changed(dev, - old_state, crtc)) + if (!new_crtc_state->active || !new_crtc_state->planes_changed) continue; ret = drm_crtc_vblank_get(crtc); if (ret != 0) continue; - old_crtc_state->enable = true; - old_crtc_state->last_vblank_count = drm_crtc_vblank_count(crtc); + crtc_mask |= drm_crtc_mask(crtc); + old_state->crtcs[i].last_vblank_count = drm_crtc_vblank_count(crtc); } for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) { - if (!old_crtc_state->enable) + if (!(crtc_mask & drm_crtc_mask(crtc))) continue; ret = wait_event_timeout(dev->vblank[i].queue, - old_crtc_state->last_vblank_count != + old_state->crtcs[i].last_vblank_count != drm_crtc_vblank_count(crtc), msecs_to_jiffies(50)); @@ -1157,8 +1130,8 @@ EXPORT_SYMBOL(drm_atomic_helper_wait_for_vblanks); * drm_atomic_helper_commit_tail - commit atomic update to hardware * @old_state: atomic state object with old state structures * - * This is the default implemenation for the ->atomic_commit_tail() hook of the - * &drm_mode_config_helper_funcs vtable. + * This is the default implementation for the + * &drm_mode_config_helper_funcs.atomic_commit_tail hook. * * Note that the default ordering of how the various stages are called is to * match the legacy modeset helper library closest. One peculiarity of that is @@ -1235,8 +1208,8 @@ static void commit_work(struct work_struct *work) * drm_atomic_helper_setup_commit() and related functions. * * Committing the actual hardware state is done through the - * ->atomic_commit_tail() callback of the &drm_mode_config_helper_funcs vtable, - * or it's default implementation drm_atomic_helper_commit_tail(). + * &drm_mode_config_helper_funcs.atomic_commit_tail callback, or it's default + * implementation drm_atomic_helper_commit_tail(). * * RETURNS: * Zero for success or -errno. @@ -1389,6 +1362,15 @@ static int stall_checks(struct drm_crtc *crtc, bool nonblock) return ret < 0 ? ret : 0; } +static void release_crtc_commit(struct completion *completion) +{ + struct drm_crtc_commit *commit = container_of(completion, + typeof(*commit), + flip_done); + + drm_crtc_commit_put(commit); +} + /** * drm_atomic_helper_setup_commit - setup possibly nonblocking commit * @state: new modeset state to be committed @@ -1396,14 +1378,15 @@ static int stall_checks(struct drm_crtc *crtc, bool nonblock) * * This function prepares @state to be used by the atomic helper's support for * nonblocking commits. Drivers using the nonblocking commit infrastructure - * should always call this function from their ->atomic_commit hook. + * should always call this function from their + * &drm_mode_config_funcs.atomic_commit hook. * * To be able to use this support drivers need to use a few more helper * functions. drm_atomic_helper_wait_for_dependencies() must be called before * actually committing the hardware state, and for nonblocking commits this call * must be placed in the async worker. See also drm_atomic_helper_swap_state() * and it's stall parameter, for when a driver's commit hooks look at the - * ->state pointers of struct &drm_crtc, &drm_plane or &drm_connector directly. + * &drm_crtc.state, &drm_plane.state or &drm_connector.state pointer directly. * * Completion of the hardware commit step must be signalled using * drm_atomic_helper_commit_hw_done(). After this step the driver is not allowed @@ -1481,6 +1464,8 @@ int drm_atomic_helper_setup_commit(struct drm_atomic_state *state, } crtc_state->event->base.completion = &commit->flip_done; + crtc_state->event->base.completion_release = release_crtc_commit; + drm_crtc_commit_get(commit); } return 0; @@ -1510,8 +1495,7 @@ static struct drm_crtc_commit *preceeding_commit(struct drm_crtc *crtc) * This function waits for all preceeding commits that touch the same CRTC as * @old_state to both be committed to the hardware (as signalled by * drm_atomic_helper_commit_hw_done) and executed by the hardware (as signalled - * by calling drm_crtc_vblank_send_event on the event member of - * &drm_crtc_state). + * by calling drm_crtc_vblank_send_event() on the &drm_crtc_state.event). * * This is part of the atomic helper support for nonblocking commits, see * drm_atomic_helper_setup_commit() for an overview. @@ -1648,8 +1632,9 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); * @state: atomic state object with new state structures * * This function prepares plane state, specifically framebuffers, for the new - * configuration. If any failure is encountered this function will call - * ->cleanup_fb on any already successfully prepared framebuffer. + * configuration, by calling &drm_plane_helper_funcs.prepare_fb. If any failure + * is encountered this function will call &drm_plane_helper_funcs.cleanup_fb on + * any already successfully prepared framebuffer. * * Returns: * 0 on success, negative error code on failure. @@ -1729,10 +1714,10 @@ static bool plane_crtc_active(const struct drm_plane_state *state) * * Drivers may set the NO_DISABLE_AFTER_MODESET flag in @flags if the relevant * display controllers require to disable a CRTC's planes when the CRTC is - * disabled. This function would skip the ->atomic_disable call for a plane if - * the CRTC of the old plane state needs a modesetting operation. Of course, - * the drivers need to disable the planes in their CRTC disable callbacks - * since no one else would do that. + * disabled. This function would skip the &drm_plane_helper_funcs.atomic_disable + * call for a plane if the CRTC of the old plane state needs a modesetting + * operation. Of course, the drivers need to disable the planes in their CRTC + * disable callbacks since no one else would do that. * * The drm_atomic_helper_commit() default implementation doesn't set the * ACTIVE_ONLY flag to most closely match the behaviour of the legacy helpers. @@ -1895,7 +1880,7 @@ EXPORT_SYMBOL(drm_atomic_helper_commit_planes_on_crtc); * planes. * * It is a bug to call this function without having implemented the - * ->atomic_disable() plane hook. + * &drm_plane_helper_funcs.atomic_disable plane hook. */ void drm_atomic_helper_disable_planes_on_crtc(struct drm_crtc_state *old_crtc_state, @@ -1982,8 +1967,8 @@ EXPORT_SYMBOL(drm_atomic_helper_cleanup_planes); * contains the old state. Also do any other cleanup required with that state. * * @stall must be set when nonblocking commits for this driver directly access - * the ->state pointer of &drm_plane, &drm_crtc or &drm_connector. With the - * current atomic helpers this is almost always the case, since the helpers + * the &drm_plane.state, &drm_crtc.state or &drm_connector.state pointer. With + * the current atomic helpers this is almost always the case, since the helpers * don't pass the right state structures to the callbacks. */ void drm_atomic_helper_swap_state(struct drm_atomic_state *state, @@ -2384,7 +2369,7 @@ int __drm_atomic_helper_set_config(struct drm_mode_set *set, if (ret != 0) return ret; - drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay); + drm_mode_get_hv_timing(set->mode, &hdisplay, &vdisplay); drm_atomic_set_fb_for_plane(primary_state, set->fb); primary_state->crtc_x = 0; @@ -2435,6 +2420,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); @@ -2443,7 +2429,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; @@ -2461,6 +2448,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; } @@ -2726,6 +2714,44 @@ backoff: } EXPORT_SYMBOL(drm_atomic_helper_connector_set_property); +static int page_flip_common( + struct drm_atomic_state *state, + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event) +{ + struct drm_plane *plane = crtc->primary; + struct drm_plane_state *plane_state; + struct drm_crtc_state *crtc_state; + int ret = 0; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); + + crtc_state->event = event; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); + + + ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); + if (ret != 0) + return ret; + drm_atomic_set_fb_for_plane(plane_state, fb); + + /* Make sure we don't accidentally do a full modeset. */ + state->allow_modeset = false; + if (!crtc_state->active) { + DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n", + crtc->base.id); + return -EINVAL; + } + + return ret; +} + /** * drm_atomic_helper_page_flip - execute a legacy page flip * @crtc: DRM crtc @@ -2733,7 +2759,8 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_set_property); * @event: optional DRM event to signal upon completion * @flags: flip flags for non-vblank sync'ed updates * - * Provides a default page flip implementation using the atomic driver interface. + * Provides a default &drm_crtc_funcs.page_flip implementation + * using the atomic driver interface. * * Note that for now so called async page flips (i.e. updates which are not * synchronized to vblank) are not supported, since the atomic interfaces have @@ -2741,6 +2768,9 @@ EXPORT_SYMBOL(drm_atomic_helper_connector_set_property); * * Returns: * Returns 0 on success, negative errno numbers on failure. + * + * See also: + * drm_atomic_helper_page_flip_target() */ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, @@ -2749,8 +2779,6 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, { struct drm_plane *plane = crtc->primary; struct drm_atomic_state *state; - struct drm_plane_state *plane_state; - struct drm_crtc_state *crtc_state; int ret = 0; if (flags & DRM_MODE_PAGE_FLIP_ASYNC) @@ -2761,35 +2789,86 @@ int drm_atomic_helper_page_flip(struct drm_crtc *crtc, return -ENOMEM; state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); + retry: - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) { - ret = PTR_ERR(crtc_state); + ret = page_flip_common(state, crtc, fb, event); + if (ret != 0) goto fail; - } - crtc_state->event = event; - plane_state = drm_atomic_get_plane_state(state, plane); - if (IS_ERR(plane_state)) { - ret = PTR_ERR(plane_state); - goto fail; - } + ret = drm_atomic_nonblocking_commit(state); - ret = drm_atomic_set_crtc_for_plane(plane_state, crtc); +fail: + if (ret == -EDEADLK) + goto backoff; + + drm_atomic_state_put(state); + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_atomic_legacy_backoff(state); + + /* + * Someone might have exchanged the framebuffer while we dropped locks + * in the backoff code. We need to fix up the fb refcount tracking the + * core does for us. + */ + plane->old_fb = plane->fb; + + goto retry; +} +EXPORT_SYMBOL(drm_atomic_helper_page_flip); + +/** + * drm_atomic_helper_page_flip_target - do page flip on target vblank period. + * @crtc: DRM crtc + * @fb: DRM framebuffer + * @event: optional DRM event to signal upon completion + * @flags: flip flags for non-vblank sync'ed updates + * @target: specifying the target vblank period when the flip to take effect + * + * Provides a default &drm_crtc_funcs.page_flip_target implementation. + * Similar to drm_atomic_helper_page_flip() with extra parameter to specify + * target vblank period to flip. + * + * Returns: + * Returns 0 on success, negative errno numbers on failure. + */ +int drm_atomic_helper_page_flip_target( + struct drm_crtc *crtc, + struct drm_framebuffer *fb, + struct drm_pending_vblank_event *event, + uint32_t flags, + uint32_t target) +{ + struct drm_plane *plane = crtc->primary; + struct drm_atomic_state *state; + struct drm_crtc_state *crtc_state; + int ret = 0; + + if (flags & DRM_MODE_PAGE_FLIP_ASYNC) + return -EINVAL; + + state = drm_atomic_state_alloc(plane->dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = drm_modeset_legacy_acquire_ctx(crtc); + +retry: + ret = page_flip_common(state, crtc, fb, event); if (ret != 0) goto fail; - drm_atomic_set_fb_for_plane(plane_state, fb); - /* Make sure we don't accidentally do a full modeset. */ - state->allow_modeset = false; - if (!crtc_state->active) { - DRM_DEBUG_ATOMIC("[CRTC:%d] disabled, rejecting legacy flip\n", - crtc->base.id); + crtc_state = drm_atomic_get_existing_crtc_state(state, crtc); + if (WARN_ON(!crtc_state)) { ret = -EINVAL; goto fail; } + crtc_state->target_vblank = target; ret = drm_atomic_nonblocking_commit(state); + fail: if (ret == -EDEADLK) goto backoff; @@ -2810,7 +2889,7 @@ backoff: goto retry; } -EXPORT_SYMBOL(drm_atomic_helper_page_flip); +EXPORT_SYMBOL(drm_atomic_helper_page_flip_target); /** * drm_atomic_helper_connector_dpms() - connector dpms helper implementation @@ -2819,8 +2898,8 @@ EXPORT_SYMBOL(drm_atomic_helper_page_flip); * * This is the main helper function provided by the atomic helper framework for * implementing the legacy DPMS connector interface. It computes the new desired - * ->active state for the corresponding CRTC (if the connector is enabled) and - * updates it. + * &drm_crtc_state.active state for the corresponding CRTC (if the connector is + * enabled) and updates it. * * Returns: * Returns 0 on success, negative errno numbers on failure. @@ -2833,6 +2912,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; @@ -2860,7 +2940,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; @@ -2869,6 +2950,7 @@ retry: break; } } + drm_connector_list_iter_put(&conn_iter); crtc_state->active = active; ret = drm_atomic_commit(state); @@ -2889,11 +2971,11 @@ backoff: EXPORT_SYMBOL(drm_atomic_helper_connector_dpms); /** - * drm_atomic_helper_best_encoder - Helper for &drm_connector_helper_funcs - * ->best_encoder callback + * drm_atomic_helper_best_encoder - Helper for + * &drm_connector_helper_funcs.best_encoder callback * @connector: Connector control structure * - * This is a &drm_connector_helper_funcs ->best_encoder callback helper for + * This is a &drm_connector_helper_funcs.best_encoder callback helper for * connectors that support exactly 1 encoder, statically determined at driver * init time. */ @@ -2927,7 +3009,7 @@ EXPORT_SYMBOL(drm_atomic_helper_best_encoder); */ /** - * drm_atomic_helper_crtc_reset - default ->reset hook for CRTCs + * drm_atomic_helper_crtc_reset - default &drm_crtc_funcs.reset hook for CRTCs * @crtc: drm CRTC * * Resets the atomic state for @crtc by freeing the state pointer (which might @@ -3034,7 +3116,7 @@ void drm_atomic_helper_crtc_destroy_state(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_atomic_helper_crtc_destroy_state); /** - * drm_atomic_helper_plane_reset - default ->reset hook for planes + * drm_atomic_helper_plane_reset - default &drm_plane_funcs.reset hook for planes * @plane: drm plane * * Resets the atomic state for @plane by freeing the state pointer (which might @@ -3138,8 +3220,9 @@ EXPORT_SYMBOL(drm_atomic_helper_plane_destroy_state); * @conn_state: connector state to assign * * Initializes the newly allocated @conn_state and assigns it to - * #connector ->state, usually required when initializing the drivers - * or when called from the ->reset hook. + * the &drm_conector->state pointer of @connector, usually required when + * initializing the drivers or when called from the &drm_connector_funcs.reset + * hook. * * This is useful for drivers that subclass the connector state. */ @@ -3155,7 +3238,7 @@ __drm_atomic_helper_connector_reset(struct drm_connector *connector, EXPORT_SYMBOL(__drm_atomic_helper_connector_reset); /** - * drm_atomic_helper_connector_reset - default ->reset hook for connectors + * drm_atomic_helper_connector_reset - default &drm_connector_funcs.reset hook for connectors * @connector: drm connector * * Resets the atomic state for @connector by freeing the state pointer (which @@ -3246,6 +3329,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; @@ -3276,15 +3360,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; @@ -3310,11 +3397,6 @@ EXPORT_SYMBOL(drm_atomic_helper_duplicate_state); void __drm_atomic_helper_connector_destroy_state(struct drm_connector_state *state) { - /* - * This is currently a placeholder so that drivers that subclass the - * state will automatically do the right thing if code is ever added - * to this function. - */ if (state->crtc) drm_connector_unreference(state->connector); } |