#include <drm/drm_mode.h>
#include <drm/drm_plane_helper.h>
+#include "drm_crtc_internal.h"
+
/**
* drm_atomic_state_default_release -
* release memory initialized by drm_atomic_state_init
if (!connector)
continue;
- /*
- * FIXME: Async commits can race with connector unplugging and
- * there's currently nothing that prevents cleanup up state for
- * deleted connectors. As long as the callback doesn't look at
- * the connector we'll be fine though, so make sure that's the
- * case by setting all connector pointers to NULL.
- */
- state->connector_states[i]->connector = NULL;
- connector->funcs->atomic_destroy_state(NULL,
+ connector->funcs->atomic_destroy_state(connector,
state->connector_states[i]);
state->connectors[i] = NULL;
state->connector_states[i] = NULL;
+ drm_connector_unreference(connector);
}
for (i = 0; i < config->num_crtc; i++) {
int ret, index = drm_crtc_index(crtc);
struct drm_crtc_state *crtc_state;
+ WARN_ON(!state->acquire_ctx);
+
crtc_state = drm_atomic_get_existing_crtc_state(state, crtc);
if (crtc_state)
return crtc_state;
int ret, index = drm_plane_index(plane);
struct drm_plane_state *plane_state;
+ WARN_ON(!state->acquire_ctx);
+
plane_state = drm_atomic_get_existing_plane_state(state, plane);
if (plane_state)
return plane_state;
struct drm_mode_config *config = &connector->dev->mode_config;
struct drm_connector_state *connector_state;
+ WARN_ON(!state->acquire_ctx);
+
ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
if (ret)
return ERR_PTR(ret);
if (!connector_state)
return ERR_PTR(-ENOMEM);
+ drm_connector_reference(connector);
state->connector_states[index] = connector_state;
state->connectors[index] = connector;
connector_state->state = state;
{
struct drm_crtc_state *crtc_state;
- if (conn_state->crtc && conn_state->crtc != crtc) {
+ if (conn_state->crtc == crtc)
+ return 0;
+
+ if (conn_state->crtc) {
crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state,
conn_state->crtc);
crtc_state->connector_mask &=
~(1 << drm_connector_index(conn_state->connector));
+
+ drm_connector_unreference(conn_state->connector);
+ conn_state->crtc = NULL;
}
if (crtc) {
crtc_state->connector_mask |=
1 << drm_connector_index(conn_state->connector);
- }
- conn_state->crtc = crtc;
+ drm_connector_reference(conn_state->connector);
+ conn_state->crtc = crtc;
- if (crtc)
DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
conn_state, crtc->base.id, crtc->name);
- else
+ } else {
DRM_DEBUG_ATOMIC("Link connector state %p to [NOCRTC]\n",
conn_state);
+ }
return 0;
}
EXPORT_SYMBOL(drm_atomic_commit);
/**
- * drm_atomic_async_commit - atomic&async configuration commit
+ * drm_atomic_nonblocking_commit - atomic&nonblocking configuration commit
* @state: atomic configuration to check
*
* Note that this function can return -EDEADLK if the driver needed to acquire
* Returns:
* 0 on success, negative error code on failure.
*/
-int drm_atomic_async_commit(struct drm_atomic_state *state)
+int drm_atomic_nonblocking_commit(struct drm_atomic_state *state)
{
struct drm_mode_config *config = &state->dev->mode_config;
int ret;
if (ret)
return ret;
- DRM_DEBUG_ATOMIC("commiting %p asynchronously\n", state);
+ DRM_DEBUG_ATOMIC("commiting %p nonblocking\n", state);
return config->funcs->atomic_commit(state->dev, state, true);
}
-EXPORT_SYMBOL(drm_atomic_async_commit);
+EXPORT_SYMBOL(drm_atomic_nonblocking_commit);
/*
* The big monstor ioctl
}
obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
- if (!obj || !obj->properties) {
+ if (!obj) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ if (!obj->properties) {
+ drm_mode_object_unreference(obj);
ret = -ENOENT;
goto out;
}
if (get_user(count_props, count_props_ptr + copied_objs)) {
+ drm_mode_object_unreference(obj);
ret = -EFAULT;
goto out;
}
struct drm_property *prop;
if (get_user(prop_id, props_ptr + copied_props)) {
+ drm_mode_object_unreference(obj);
ret = -EFAULT;
goto out;
}
prop = drm_property_find(dev, prop_id);
if (!prop) {
+ drm_mode_object_unreference(obj);
ret = -ENOENT;
goto out;
}
if (copy_from_user(&prop_value,
prop_values_ptr + copied_props,
sizeof(prop_value))) {
+ drm_mode_object_unreference(obj);
ret = -EFAULT;
goto out;
}
ret = atomic_set_prop(state, obj, prop, prop_value);
- if (ret)
+ if (ret) {
+ drm_mode_object_unreference(obj);
goto out;
+ }
copied_props++;
}
plane_mask |= (1 << drm_plane_index(plane));
plane->old_fb = plane->fb;
}
+ drm_mode_object_unreference(obj);
}
if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
*/
ret = drm_atomic_check_only(state);
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
- ret = drm_atomic_async_commit(state);
+ ret = drm_atomic_nonblocking_commit(state);
} else {
ret = drm_atomic_commit(state);
}