/* * Copyright (C) 2014 Red Hat * Copyright (C) 2014 Intel Corp. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rob Clark <robdclark@gmail.com> * Daniel Vetter <daniel.vetter@ffwll.ch> */ #include <linux/export.h>#include <linux/sync_file.h> #include <drm/drm_atomic.h>#include <drm/drm_atomic_uapi.h>#include <drm/drm_blend.h>#include <drm/drm_bridge.h>#include <drm/drm_debugfs.h>#include <drm/drm_device.h>#include <drm/drm_drv.h>#include <drm/drm_file.h>#include <drm/drm_fourcc.h>#include <drm/drm_framebuffer.h>#include <drm/drm_mode.h>#include <drm/drm_print.h>#include <drm/drm_writeback.h>#include <drm/drm_colorop.h> #include "drm_crtc_internal.h"#include "drm_internal.h" /** * DOC: state lifetime * * &drm_atomic_commit represents an update to modeset pipeline state. * It's a transient object that holds a state update as a collection of * pointers to individual objects' states. &drm_atomic_commit has a much * shorter lifetime than the objects' states, since it's only allocated * while preparing, checking or committing the update, while object * states are allocated when preparing the update and kept alive as long * as they are active in the device. * * Their respective lifetimes are: * * - at driver initialization time, the driver calls * drm_mode_config_create_initial_state() to allocate an initial, * pristine, state for each object and stores it in the objects state * pointer. Historically, this was one of drm_mode_config_reset() job, * so one might still encounter it in a driver. * * - When resuming from suspend, drm_mode_config_reset() resets the * software and hardware state to a known default and stores it in the * object's state pointer. Not all objects are affected by * drm_mode_config_reset() though. * * - whenever a new update is needed: * * + drm_atomic_commit_alloc() allocates a new &drm_atomic_commit * instance. * * + The code triggering the commit (ioctl, client modeset, * drm_atomic_helper_reset_crtc(), etc.) copies the current active * state of all entities affected by the update into this new * &drm_atomic_commit using drm_atomic_get_plane_state(), * drm_atomic_get_crtc_state(), drm_atomic_get_connector_state(), or * drm_atomic_get_private_obj_state(). This new state can then be * modified. * * At that point, &drm_atomic_commit stores three state pointers for * any affected entity: the "old" and "new" states, and * state_to_destroy. The old state is the state currently active in * the hardware, which is either the one initialized by reset() or a * newer one if a commit has been made. The new state is the state * we just allocated and we might eventually commit to the hardware. * The state_to_destroy points to the state we'll eventually have to * free when the drm_atomic_commit will be destroyed, and points to * the new state for now since the old state is still the active * state. * * + After the calling code populated the commit with the entities * states, it updates the new states with the new values we need to * commit. The new commit instance is now ready. * * + Then we have two branches depending on the calling code intent: * * - If the calling code only wants to check that the commit would * work (for example because of the DRM_MODE_ATOMIC_TEST_ONLY * flag). It calls drm_atomic_check_only(), which in turn checks * all these states by invoking atomic_check on all affected * pipeline stages. * * - If the calling code actually wants to trigger a commit, it * calls drm_atomic_commit(). The first stage is the check * mentioned above, and if the check is successful, it performs * the commit. Part of the commit is a call to * drm_atomic_helper_swap_state() which turns the new states into * the active states. After swapping states, each object's state * pointer now refers to the formerly new state. The * state_to_destroy now refers to the formerly old state. * * + Once done, and when the last reference to our &drm_atomic_commit * is given up through drm_atomic_commit_put(), it calls * __drm_atomic_commit_free(). In turn, __drm_atomic_commit_free() * calls drm_atomic_commit_clear() that will free all * state_to_destroy (ie. old states), and it finally frees * &drm_atomic_commit instance. * * + Now, we don't have any active &drm_atomic_commit anymore, and * only the entity active states remain allocated. */ void __drm_crtc_commit_free(struct kref *kref){ struct drm_crtc_commit *commit = container_of(kref, struct drm_crtc_commit, ref); kfree(commit);}EXPORT_SYMBOL(__drm_crtc_commit_free); /** * drm_crtc_commit_wait - Waits for a commit to complete * @commit: &drm_crtc_commit to wait for * * Waits for a given &drm_crtc_commit to be programmed into the * hardware and flipped to. * * Returns: * 0 on success, a negative error code otherwise. */int drm_crtc_commit_wait(struct drm_crtc_commit *commit){ unsigned long timeout = 10 * HZ; int ret; if (!commit) return 0; ret = wait_for_completion_timeout(&commit->hw_done, timeout); if (!ret) { drm_err(commit->crtc->dev, "hw_done timed out\n"); return -ETIMEDOUT; } /* * Currently no support for overwriting flips, hence * stall for previous one to execute completely. */ ret = wait_for_completion_timeout(&commit->flip_done, timeout); if (!ret) { drm_err(commit->crtc->dev, "flip_done timed out\n"); return -ETIMEDOUT; } return 0;}EXPORT_SYMBOL(drm_crtc_commit_wait); /** * drm_atomic_commit_default_release - * release memory initialized by drm_atomic_commit_init * @state: atomic state * * Free all the memory allocated by drm_atomic_commit_init. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */void drm_atomic_commit_default_release(struct drm_atomic_commit *state){ kfree(state->connectors); kfree(state->crtcs); kfree(state->planes); kfree(state->colorops); kfree(state->private_objs);}EXPORT_SYMBOL(drm_atomic_commit_default_release); /** * drm_atomic_commit_init - init new atomic state * @dev: DRM device * @state: atomic state * * Default implementation for filling in a new atomic state. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */intdrm_atomic_commit_init(struct drm_device *dev, struct drm_atomic_commit *state){ kref_init(&state->ref); /* TODO legacy paths should maybe do a better job about * setting this appropriately? */ state->allow_modeset = true; state->crtcs = kzalloc_objs(*state->crtcs, dev->mode_config.num_crtc); if (!state->crtcs) goto fail; state->planes = kzalloc_objs(*state->planes, dev->mode_config.num_total_plane); if (!state->planes) goto fail; state->colorops = kzalloc_objs(*state->colorops, dev->mode_config.num_colorop); if (!state->colorops) goto fail; /* * Because drm_atomic_commit can be committed asynchronously we need our * own reference and cannot rely on the on implied by drm_file in the * ioctl call. */ drm_dev_get(dev); state->dev = dev; drm_dbg_atomic(dev, "Allocated atomic state %p\n", state); return 0;fail: drm_atomic_commit_default_release(state); return -ENOMEM;}EXPORT_SYMBOL(drm_atomic_commit_init); /** * drm_atomic_commit_alloc - allocate atomic state * @dev: DRM device * * This allocates an empty atomic state to track updates. */struct drm_atomic_commit *drm_atomic_commit_alloc(struct drm_device *dev){ struct drm_mode_config *config = &dev->mode_config; if (!config->funcs->atomic_state_alloc) { struct drm_atomic_commit *state; state = kzalloc_obj(*state); if (!state) return NULL; if (drm_atomic_commit_init(dev, state) < 0) { kfree(state); return NULL; } return state; } return config->funcs->atomic_state_alloc(dev);}EXPORT_SYMBOL(drm_atomic_commit_alloc); /** * drm_atomic_commit_default_clear - clear base atomic state * @state: atomic state * * Default implementation for clearing atomic state. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */void drm_atomic_commit_default_clear(struct drm_atomic_commit *state){ struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; int i; drm_dbg_atomic(dev, "Clearing atomic state %p\n", state); state->checked = false; for (i = 0; i < state->num_connector; i++) { struct drm_connector *connector = state->connectors[i].ptr; if (!connector) continue; connector->funcs->atomic_destroy_state(connector, state->connectors[i].state_to_destroy); state->connectors[i].ptr = NULL; state->connectors[i].state_to_destroy = NULL; state->connectors[i].old_state = NULL; state->connectors[i].new_state = NULL; drm_connector_put(connector); } for (i = 0; i < config->num_crtc; i++) { struct drm_crtc *crtc = state->crtcs[i].ptr; if (!crtc) continue; crtc->funcs->atomic_destroy_state(crtc, state->crtcs[i].state_to_destroy); state->crtcs[i].ptr = NULL; state->crtcs[i].state_to_destroy = NULL; state->crtcs[i].old_state = NULL; state->crtcs[i].new_state = NULL; if (state->crtcs[i].commit) { drm_crtc_commit_put(state->crtcs[i].commit); state->crtcs[i].commit = NULL; } } for (i = 0; i < config->num_total_plane; i++) { struct drm_plane *plane = state->planes[i].ptr; if (!plane) continue; plane->funcs->atomic_destroy_state(plane, state->planes[i].state_to_destroy); state->planes[i].ptr = NULL; state->planes[i].state_to_destroy = NULL; state->planes[i].old_state = NULL; state->planes[i].new_state = NULL; } for (i = 0; i < config->num_colorop; i++) { struct drm_colorop *colorop = state->colorops[i].ptr; if (!colorop) continue; drm_colorop_atomic_destroy_state(colorop, state->colorops[i].state); state->colorops[i].ptr = NULL; state->colorops[i].state = NULL; state->colorops[i].old_state = NULL; state->colorops[i].new_state = NULL; } for (i = 0; i < state->num_private_objs; i++) { struct drm_private_obj *obj = state->private_objs[i].ptr; obj->funcs->atomic_destroy_state(obj, state->private_objs[i].state_to_destroy); state->private_objs[i].ptr = NULL; state->private_objs[i].state_to_destroy = NULL; state->private_objs[i].old_state = NULL; state->private_objs[i].new_state = NULL; } state->num_private_objs = 0; if (state->fake_commit) { drm_crtc_commit_put(state->fake_commit); state->fake_commit = NULL; }}EXPORT_SYMBOL(drm_atomic_commit_default_clear); /** * drm_atomic_commit_clear - clear state object * @state: atomic state * * When the w/w mutex algorithm detects a deadlock we need to back off and drop * all locks. So someone else could sneak in and change the current modeset * configuration. Which means that all the state assembled in @state is no * longer an atomic update to the current state, but to some arbitrary earlier * state. Which could break assumptions the driver's * &drm_mode_config_funcs.atomic_check likely relies on. * * Hence we must clear all cached state and completely start over, using this * function. */void drm_atomic_commit_clear(struct drm_atomic_commit *state){ struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; if (config->funcs->atomic_state_clear) config->funcs->atomic_state_clear(state); else drm_atomic_commit_default_clear(state);}EXPORT_SYMBOL(drm_atomic_commit_clear); /** * __drm_atomic_commit_free - free all memory for an atomic state * @ref: This atomic state to deallocate * * This frees all memory associated with an atomic state, including all the * per-object state for planes, CRTCs and connectors. */void __drm_atomic_commit_free(struct kref *ref){ struct drm_atomic_commit *state = container_of(ref, typeof(*state), ref); struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; drm_atomic_commit_clear(state); drm_dbg_atomic(state->dev, "Freeing atomic state %p\n", state); if (config->funcs->atomic_state_free) { config->funcs->atomic_state_free(state); } else { drm_atomic_commit_default_release(state); kfree(state); } drm_dev_put(dev);}EXPORT_SYMBOL(__drm_atomic_commit_free); /** * drm_atomic_get_crtc_state - get CRTC state * @state: global atomic state object * @crtc: CRTC to get state object for * * This function returns the CRTC state for the given CRTC, allocating it if * needed. It will also grab the relevant CRTC lock to make sure that the state * is consistent. * * WARNING: Drivers may only add new CRTC states to a @state if * drm_atomic_commit.allow_modeset is set, or if it's a driver-internal commit * not created by userspace through an IOCTL call. * * Returns: * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. */struct drm_crtc_state *drm_atomic_get_crtc_state(struct drm_atomic_commit *state, struct drm_crtc *crtc){ int ret, index = drm_crtc_index(crtc); struct drm_crtc_state *crtc_state; WARN_ON(!state->acquire_ctx); drm_WARN_ON(state->dev, state->checked); crtc_state = drm_atomic_get_new_crtc_state(state, crtc); if (crtc_state) return crtc_state; ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx); if (ret) return ERR_PTR(ret); crtc_state = crtc->funcs->atomic_duplicate_state(crtc); if (!crtc_state) return ERR_PTR(-ENOMEM); state->crtcs[index].state_to_destroy = crtc_state; state->crtcs[index].old_state = crtc->state; state->crtcs[index].new_state = crtc_state; state->crtcs[index].ptr = crtc; crtc_state->state = state; drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n", crtc->base.id, crtc->name, crtc_state, state); return crtc_state;}EXPORT_SYMBOL(drm_atomic_get_crtc_state); static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, const struct drm_crtc_state *new_crtc_state){ struct drm_crtc *crtc = new_crtc_state->crtc; /* NOTE: we explicitly don't enforce constraints such as primary * layer covering entire screen, since that is something we want * to allow (on hw that supports it). For hw that does not, it * should be checked in driver's crtc->atomic_check() vfunc. * * TODO: Add generic modeset state checks once we support those. */ if (new_crtc_state->active && !new_crtc_state->enable) { drm_dbg_atomic(crtc->dev, "[CRTC:%d:%s] active without enabled\n", crtc->base.id, crtc->name); return -EINVAL; } /* The state->enable vs. state->mode_blob checks can be WARN_ON, * as this is a kernel-internal detail that userspace should neverLines 1–500 of 2223. Load more
/* * Copyright (C) 2014 Red Hat * Copyright (C) 2014 Intel Corp. * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: * Rob Clark <robdclark@gmail.com> * Daniel Vetter <daniel.vetter@ffwll.ch> */ #include <linux/export.h> #include <linux/sync_file.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_blend.h> #include <drm/drm_bridge.h> #include <drm/drm_debugfs.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_fourcc.h> #include <drm/drm_framebuffer.h> #include <drm/drm_mode.h> #include <drm/drm_print.h> #include <drm/drm_writeback.h> #include <drm/drm_colorop.h> #include "drm_crtc_internal.h" #include "drm_internal.h" /** * DOC: state lifetime * * &drm_atomic_commit represents an update to modeset pipeline state. * It's a transient object that holds a state update as a collection of * pointers to individual objects' states. &drm_atomic_commit has a much * shorter lifetime than the objects' states, since it's only allocated * while preparing, checking or committing the update, while object * states are allocated when preparing the update and kept alive as long * as they are active in the device. * * Their respective lifetimes are: * * - at driver initialization time, the driver calls * drm_mode_config_create_initial_state() to allocate an initial, * pristine, state for each object and stores it in the objects state * pointer. Historically, this was one of drm_mode_config_reset() job, * so one might still encounter it in a driver. * * - When resuming from suspend, drm_mode_config_reset() resets the * software and hardware state to a known default and stores it in the * object's state pointer. Not all objects are affected by * drm_mode_config_reset() though. * * - whenever a new update is needed: * * + drm_atomic_commit_alloc() allocates a new &drm_atomic_commit * instance. * * + The code triggering the commit (ioctl, client modeset, * drm_atomic_helper_reset_crtc(), etc.) copies the current active * state of all entities affected by the update into this new * &drm_atomic_commit using drm_atomic_get_plane_state(), * drm_atomic_get_crtc_state(), drm_atomic_get_connector_state(), or * drm_atomic_get_private_obj_state(). This new state can then be * modified. * * At that point, &drm_atomic_commit stores three state pointers for * any affected entity: the "old" and "new" states, and * state_to_destroy. The old state is the state currently active in * the hardware, which is either the one initialized by reset() or a * newer one if a commit has been made. The new state is the state * we just allocated and we might eventually commit to the hardware. * The state_to_destroy points to the state we'll eventually have to * free when the drm_atomic_commit will be destroyed, and points to * the new state for now since the old state is still the active * state. * * + After the calling code populated the commit with the entities * states, it updates the new states with the new values we need to * commit. The new commit instance is now ready. * * + Then we have two branches depending on the calling code intent: * * - If the calling code only wants to check that the commit would * work (for example because of the DRM_MODE_ATOMIC_TEST_ONLY * flag). It calls drm_atomic_check_only(), which in turn checks * all these states by invoking atomic_check on all affected * pipeline stages. * * - If the calling code actually wants to trigger a commit, it * calls drm_atomic_commit(). The first stage is the check * mentioned above, and if the check is successful, it performs * the commit. Part of the commit is a call to * drm_atomic_helper_swap_state() which turns the new states into * the active states. After swapping states, each object's state * pointer now refers to the formerly new state. The * state_to_destroy now refers to the formerly old state. * * + Once done, and when the last reference to our &drm_atomic_commit * is given up through drm_atomic_commit_put(), it calls * __drm_atomic_commit_free(). In turn, __drm_atomic_commit_free() * calls drm_atomic_commit_clear() that will free all * state_to_destroy (ie. old states), and it finally frees * &drm_atomic_commit instance. * * + Now, we don't have any active &drm_atomic_commit anymore, and * only the entity active states remain allocated. */ void __drm_crtc_commit_free(struct kref *kref) { struct drm_crtc_commit *commit = container_of(kref, struct drm_crtc_commit, ref); kfree(commit); } EXPORT_SYMBOL(__drm_crtc_commit_free); /** * drm_crtc_commit_wait - Waits for a commit to complete * @commit: &drm_crtc_commit to wait for * * Waits for a given &drm_crtc_commit to be programmed into the * hardware and flipped to. * * Returns: * 0 on success, a negative error code otherwise. */ int drm_crtc_commit_wait(struct drm_crtc_commit *commit) { unsigned long timeout = 10 * HZ; int ret; if (!commit) return 0; ret = wait_for_completion_timeout(&commit->hw_done, timeout); if (!ret) { drm_err(commit->crtc->dev, "hw_done timed out\n"); return -ETIMEDOUT; } /* * Currently no support for overwriting flips, hence * stall for previous one to execute completely. */ ret = wait_for_completion_timeout(&commit->flip_done, timeout); if (!ret) { drm_err(commit->crtc->dev, "flip_done timed out\n"); return -ETIMEDOUT; } return 0; } EXPORT_SYMBOL(drm_crtc_commit_wait); /** * drm_atomic_commit_default_release - * release memory initialized by drm_atomic_commit_init * @state: atomic state * * Free all the memory allocated by drm_atomic_commit_init. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */ void drm_atomic_commit_default_release(struct drm_atomic_commit *state) { kfree(state->connectors); kfree(state->crtcs); kfree(state->planes); kfree(state->colorops); kfree(state->private_objs); } EXPORT_SYMBOL(drm_atomic_commit_default_release); /** * drm_atomic_commit_init - init new atomic state * @dev: DRM device * @state: atomic state * * Default implementation for filling in a new atomic state. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */ int drm_atomic_commit_init(struct drm_device *dev, struct drm_atomic_commit *state) { kref_init(&state->ref); /* TODO legacy paths should maybe do a better job about * setting this appropriately? */ state->allow_modeset = true; state->crtcs = kzalloc_objs(*state->crtcs, dev->mode_config.num_crtc); if (!state->crtcs) goto fail; state->planes = kzalloc_objs(*state->planes, dev->mode_config.num_total_plane); if (!state->planes) goto fail; state->colorops = kzalloc_objs(*state->colorops, dev->mode_config.num_colorop); if (!state->colorops) goto fail; /* * Because drm_atomic_commit can be committed asynchronously we need our * own reference and cannot rely on the on implied by drm_file in the * ioctl call. */ drm_dev_get(dev); state->dev = dev; drm_dbg_atomic(dev, "Allocated atomic state %p\n", state); return 0; fail: drm_atomic_commit_default_release(state); return -ENOMEM; } EXPORT_SYMBOL(drm_atomic_commit_init); /** * drm_atomic_commit_alloc - allocate atomic state * @dev: DRM device * * This allocates an empty atomic state to track updates. */ struct drm_atomic_commit * drm_atomic_commit_alloc(struct drm_device *dev) { struct drm_mode_config *config = &dev->mode_config; if (!config->funcs->atomic_state_alloc) { struct drm_atomic_commit *state; state = kzalloc_obj(*state); if (!state) return NULL; if (drm_atomic_commit_init(dev, state) < 0) { kfree(state); return NULL; } return state; } return config->funcs->atomic_state_alloc(dev); } EXPORT_SYMBOL(drm_atomic_commit_alloc); /** * drm_atomic_commit_default_clear - clear base atomic state * @state: atomic state * * Default implementation for clearing atomic state. * This should only be used by drivers which are still subclassing * &drm_atomic_commit and haven't switched to &drm_private_state yet. */ void drm_atomic_commit_default_clear(struct drm_atomic_commit *state) { struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; int i; drm_dbg_atomic(dev, "Clearing atomic state %p\n", state); state->checked = false; for (i = 0; i < state->num_connector; i++) { struct drm_connector *connector = state->connectors[i].ptr; if (!connector) continue; connector->funcs->atomic_destroy_state(connector, state->connectors[i].state_to_destroy); state->connectors[i].ptr = NULL; state->connectors[i].state_to_destroy = NULL; state->connectors[i].old_state = NULL; state->connectors[i].new_state = NULL; drm_connector_put(connector); } for (i = 0; i < config->num_crtc; i++) { struct drm_crtc *crtc = state->crtcs[i].ptr; if (!crtc) continue; crtc->funcs->atomic_destroy_state(crtc, state->crtcs[i].state_to_destroy); state->crtcs[i].ptr = NULL; state->crtcs[i].state_to_destroy = NULL; state->crtcs[i].old_state = NULL; state->crtcs[i].new_state = NULL; if (state->crtcs[i].commit) { drm_crtc_commit_put(state->crtcs[i].commit); state->crtcs[i].commit = NULL; } } for (i = 0; i < config->num_total_plane; i++) { struct drm_plane *plane = state->planes[i].ptr; if (!plane) continue; plane->funcs->atomic_destroy_state(plane, state->planes[i].state_to_destroy); state->planes[i].ptr = NULL; state->planes[i].state_to_destroy = NULL; state->planes[i].old_state = NULL; state->planes[i].new_state = NULL; } for (i = 0; i < config->num_colorop; i++) { struct drm_colorop *colorop = state->colorops[i].ptr; if (!colorop) continue; drm_colorop_atomic_destroy_state(colorop, state->colorops[i].state); state->colorops[i].ptr = NULL; state->colorops[i].state = NULL; state->colorops[i].old_state = NULL; state->colorops[i].new_state = NULL; } for (i = 0; i < state->num_private_objs; i++) { struct drm_private_obj *obj = state->private_objs[i].ptr; obj->funcs->atomic_destroy_state(obj, state->private_objs[i].state_to_destroy); state->private_objs[i].ptr = NULL; state->private_objs[i].state_to_destroy = NULL; state->private_objs[i].old_state = NULL; state->private_objs[i].new_state = NULL; } state->num_private_objs = 0; if (state->fake_commit) { drm_crtc_commit_put(state->fake_commit); state->fake_commit = NULL; } } EXPORT_SYMBOL(drm_atomic_commit_default_clear); /** * drm_atomic_commit_clear - clear state object * @state: atomic state * * When the w/w mutex algorithm detects a deadlock we need to back off and drop * all locks. So someone else could sneak in and change the current modeset * configuration. Which means that all the state assembled in @state is no * longer an atomic update to the current state, but to some arbitrary earlier * state. Which could break assumptions the driver's * &drm_mode_config_funcs.atomic_check likely relies on. * * Hence we must clear all cached state and completely start over, using this * function. */ void drm_atomic_commit_clear(struct drm_atomic_commit *state) { struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; if (config->funcs->atomic_state_clear) config->funcs->atomic_state_clear(state); else drm_atomic_commit_default_clear(state); } EXPORT_SYMBOL(drm_atomic_commit_clear); /** * __drm_atomic_commit_free - free all memory for an atomic state * @ref: This atomic state to deallocate * * This frees all memory associated with an atomic state, including all the * per-object state for planes, CRTCs and connectors. */ void __drm_atomic_commit_free(struct kref *ref) { struct drm_atomic_commit *state = container_of(ref, typeof(*state), ref); struct drm_device *dev = state->dev; struct drm_mode_config *config = &dev->mode_config; drm_atomic_commit_clear(state); drm_dbg_atomic(state->dev, "Freeing atomic state %p\n", state); if (config->funcs->atomic_state_free) { config->funcs->atomic_state_free(state); } else { drm_atomic_commit_default_release(state); kfree(state); } drm_dev_put(dev); } EXPORT_SYMBOL(__drm_atomic_commit_free); /** * drm_atomic_get_crtc_state - get CRTC state * @state: global atomic state object * @crtc: CRTC to get state object for * * This function returns the CRTC state for the given CRTC, allocating it if * needed. It will also grab the relevant CRTC lock to make sure that the state * is consistent. * * WARNING: Drivers may only add new CRTC states to a @state if * drm_atomic_commit.allow_modeset is set, or if it's a driver-internal commit * not created by userspace through an IOCTL call. * * Returns: * Either the allocated state or the error code encoded into the pointer. When * the error is EDEADLK then the w/w mutex code has detected a deadlock and the * entire atomic sequence must be restarted. All other errors are fatal. */ struct drm_crtc_state * drm_atomic_get_crtc_state(struct drm_atomic_commit *state, struct drm_crtc *crtc) { int ret, index = drm_crtc_index(crtc); struct drm_crtc_state *crtc_state; WARN_ON(!state->acquire_ctx); drm_WARN_ON(state->dev, state->checked); crtc_state = drm_atomic_get_new_crtc_state(state, crtc); if (crtc_state) return crtc_state; ret = drm_modeset_lock(&crtc->mutex, state->acquire_ctx); if (ret) return ERR_PTR(ret); crtc_state = crtc->funcs->atomic_duplicate_state(crtc); if (!crtc_state) return ERR_PTR(-ENOMEM); state->crtcs[index].state_to_destroy = crtc_state; state->crtcs[index].old_state = crtc->state; state->crtcs[index].new_state = crtc_state; state->crtcs[index].ptr = crtc; crtc_state->state = state; drm_dbg_atomic(state->dev, "Added [CRTC:%d:%s] %p state to %p\n", crtc->base.id, crtc->name, crtc_state, state); return crtc_state; } EXPORT_SYMBOL(drm_atomic_get_crtc_state); static int drm_atomic_crtc_check(const struct drm_crtc_state *old_crtc_state, const struct drm_crtc_state *new_crtc_state) { struct drm_crtc *crtc = new_crtc_state->crtc; /* NOTE: we explicitly don't enforce constraints such as primary * layer covering entire screen, since that is something we want * to allow (on hw that supports it). For hw that does not, it * should be checked in driver's crtc->atomic_check() vfunc. * * TODO: Add generic modeset state checks once we support those. */ if (new_crtc_state->active && !new_crtc_state->enable) { drm_dbg_atomic(crtc->dev, "[CRTC:%d:%s] active without enabled\n", crtc->base.id, crtc->name); return -EINVAL; } /* The state->enable vs. state->mode_blob checks can be WARN_ON, * as this is a kernel-internal detail that userspace should never