state->connectors[i].state);
state->connectors[i].ptr = NULL;
state->connectors[i].state = NULL;
- drm_connector_unreference(connector);
+ drm_connector_put(connector);
}
for (i = 0; i < config->num_crtc; i++) {
return ERR_PTR(-ENOMEM);
state->crtcs[index].state = 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;
if (mode && memcmp(&state->mode, mode, sizeof(*mode)) == 0)
return 0;
- drm_property_unreference_blob(state->mode_blob);
+ drm_property_blob_put(state->mode_blob);
state->mode_blob = NULL;
if (mode) {
if (blob == state->mode_blob)
return 0;
- drm_property_unreference_blob(state->mode_blob);
+ drm_property_blob_put(state->mode_blob);
state->mode_blob = NULL;
memset(&state->mode, 0, sizeof(state->mode));
blob->data))
return -EINVAL;
- state->mode_blob = drm_property_reference_blob(blob);
+ state->mode_blob = drm_property_blob_get(blob);
state->enable = true;
DRM_DEBUG_ATOMIC("Set [MODE:%s] for CRTC state %p\n",
state->mode.name, state);
if (old_blob == new_blob)
return;
- drm_property_unreference_blob(old_blob);
+ drm_property_blob_put(old_blob);
if (new_blob)
- drm_property_reference_blob(new_blob);
+ drm_property_blob_get(new_blob);
*blob = new_blob;
*replaced = true;
return -EINVAL;
if (expected_size > 0 && expected_size != new_blob->length) {
- drm_property_unreference_blob(new_blob);
+ drm_property_blob_put(new_blob);
return -EINVAL;
}
}
drm_atomic_replace_property_blob(blob, new_blob, replaced);
- drm_property_unreference_blob(new_blob);
+ drm_property_blob_put(new_blob);
return 0;
}
struct drm_property_blob *mode =
drm_property_lookup_blob(dev, val);
ret = drm_atomic_set_mode_prop_for_crtc(state, mode);
- drm_property_unreference_blob(mode);
+ drm_property_blob_put(mode);
return ret;
} else if (property == config->degamma_lut_property) {
ret = drm_atomic_replace_property_blob_from_id(crtc,
* pipe.
*/
if (state->event && !state->active && !crtc->state->active) {
- DRM_DEBUG_ATOMIC("[CRTC:%d] requesting event but off\n",
- crtc->base.id);
+ DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requesting event but off\n",
+ crtc->base.id, crtc->name);
return -EINVAL;
}
state->planes[index].state = plane_state;
state->planes[index].ptr = plane;
+ state->planes[index].old_state = plane->state;
+ state->planes[index].new_state = plane_state;
plane_state->state = state;
DRM_DEBUG_ATOMIC("Added [PLANE:%d:%s] %p state to %p\n",
struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val);
drm_atomic_set_fb_for_plane(state, fb);
if (fb)
- drm_framebuffer_unreference(fb);
+ drm_framebuffer_put(fb);
} else if (property == config->prop_in_fence_fd) {
if (state->fence)
return -EINVAL;
if (!connector_state)
return ERR_PTR(-ENOMEM);
- drm_connector_reference(connector);
+ drm_connector_get(connector);
state->connectors[index].state = connector_state;
+ state->connectors[index].old_state = connector->state;
+ state->connectors[index].new_state = connector_state;
state->connectors[index].ptr = connector;
connector_state->state = state;
- DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d] %p state to %p\n",
- connector->base.id, connector_state, state);
+ DRM_DEBUG_ATOMIC("Added [CONNECTOR:%d:%s] %p state to %p\n",
+ connector->base.id, connector->name,
+ connector_state, state);
if (connector_state->crtc) {
struct drm_crtc_state *crtc_state;
state->tv.saturation = val;
} else if (property == config->tv_hue_property) {
state->tv.hue = val;
+ } else if (property == config->link_status_property) {
+ /* Never downgrade from GOOD to BAD on userspace's request here,
+ * only hw issues can do that.
+ *
+ * For an atomic property the userspace doesn't need to be able
+ * to understand all the properties, but needs to be able to
+ * restore the state it wants on VT switch. So if the userspace
+ * tries to change the link_status from GOOD to BAD, driver
+ * silently rejects it and returns a 0. This prevents userspace
+ * from accidently breaking the display when it restores the
+ * state.
+ */
+ if (state->link_status != DRM_LINK_STATUS_GOOD)
+ state->link_status = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
*val = state->tv.saturation;
} else if (property == config->tv_hue_property) {
*val = state->tv.hue;
+ } else if (property == config->link_status_property) {
+ *val = state->link_status;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
return 0;
if (conn_state->crtc) {
- crtc_state = drm_atomic_get_existing_crtc_state(conn_state->state,
- conn_state->crtc);
+ crtc_state = drm_atomic_get_new_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);
+ drm_connector_put(conn_state->connector);
conn_state->crtc = NULL;
}
crtc_state->connector_mask |=
1 << drm_connector_index(conn_state->connector);
- drm_connector_reference(conn_state->connector);
+ drm_connector_get(conn_state->connector);
conn_state->crtc = crtc;
DRM_DEBUG_ATOMIC("Link connector state %p to [CRTC:%d:%s]\n",
struct drm_connector *connector;
struct drm_connector_state *conn_state;
struct drm_connector_list_iter conn_iter;
+ struct drm_crtc_state *crtc_state;
int ret;
+ crtc_state = drm_atomic_get_crtc_state(state, crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
ret = drm_modeset_lock(&config->connection_mutex, state->acquire_ctx);
if (ret)
return ret;
crtc->base.id, crtc->name, state);
/*
- * Changed connectors are already in @state, so only need to look at the
- * current configuration.
+ * Changed connectors are already in @state, so only need to look
+ * at the connector_mask in crtc_state.
*/
- drm_connector_list_iter_get(state->dev, &conn_iter);
+ drm_connector_list_iter_begin(state->dev, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
- if (connector->state->crtc != crtc)
+ if (!(crtc_state->connector_mask & (1 << drm_connector_index(connector))))
continue;
conn_state = drm_atomic_get_connector_state(state, connector);
if (IS_ERR(conn_state)) {
- drm_connector_list_iter_put(&conn_iter);
+ drm_connector_list_iter_end(&conn_iter);
return PTR_ERR(conn_state);
}
}
- drm_connector_list_iter_put(&conn_iter);
+ drm_connector_list_iter_end(&conn_iter);
return 0;
}
{
struct drm_plane *plane;
- WARN_ON(!drm_atomic_get_existing_crtc_state(state, crtc));
+ WARN_ON(!drm_atomic_get_new_crtc_state(state, crtc));
drm_for_each_plane_mask(plane, state->dev, crtc->state->plane_mask) {
struct drm_plane_state *plane_state =
void drm_atomic_legacy_backoff(struct drm_atomic_state *state)
{
struct drm_device *dev = state->dev;
- unsigned crtc_mask = 0;
- struct drm_crtc *crtc;
int ret;
bool global = false;
- drm_for_each_crtc(crtc, dev) {
- if (crtc->acquire_ctx != state->acquire_ctx)
- continue;
-
- crtc_mask |= drm_crtc_mask(crtc);
- crtc->acquire_ctx = NULL;
- }
-
if (WARN_ON(dev->mode_config.acquire_ctx == state->acquire_ctx)) {
global = true;
if (ret)
goto retry;
- drm_for_each_crtc(crtc, dev)
- if (drm_crtc_mask(crtc) & crtc_mask)
- crtc->acquire_ctx = state->acquire_ctx;
-
if (global)
dev->mode_config.acquire_ctx = state->acquire_ctx;
}
DRM_DEBUG_ATOMIC("checking %p\n", state);
- for_each_plane_in_state(state, plane, plane_state, i) {
+ for_each_new_plane_in_state(state, plane, plane_state, i) {
ret = drm_atomic_plane_check(plane, plane_state);
if (ret) {
DRM_DEBUG_ATOMIC("[PLANE:%d:%s] atomic core check failed\n",
}
}
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
ret = drm_atomic_crtc_check(crtc, crtc_state);
if (ret) {
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] atomic core check failed\n",
ret = config->funcs->atomic_check(state->dev, state);
if (!state->allow_modeset) {
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
DRM_DEBUG_ATOMIC("[CRTC:%d:%s] requires full modeset\n",
crtc->base.id, crtc->name);
DRM_DEBUG_ATOMIC("checking %p\n", state);
- for_each_plane_in_state(state, plane, plane_state, i)
+ for_each_new_plane_in_state(state, plane, plane_state, i)
drm_atomic_plane_print_state(&p, plane_state);
- for_each_crtc_in_state(state, crtc, crtc_state, i)
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i)
drm_atomic_crtc_print_state(&p, crtc_state);
- for_each_connector_in_state(state, connector, connector_state, i)
+ for_each_new_connector_in_state(state, connector, connector_state, i)
drm_atomic_connector_print_state(&p, connector_state);
}
+static void __drm_state_dump(struct drm_device *dev, struct drm_printer *p,
+ bool take_locks)
+{
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_plane *plane;
+ struct drm_crtc *crtc;
+ struct drm_connector *connector;
+ struct drm_connector_list_iter conn_iter;
+
+ if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
+ return;
+
+ list_for_each_entry(plane, &config->plane_list, head) {
+ if (take_locks)
+ drm_modeset_lock(&plane->mutex, NULL);
+ drm_atomic_plane_print_state(p, plane->state);
+ if (take_locks)
+ drm_modeset_unlock(&plane->mutex);
+ }
+
+ list_for_each_entry(crtc, &config->crtc_list, head) {
+ if (take_locks)
+ drm_modeset_lock(&crtc->mutex, NULL);
+ drm_atomic_crtc_print_state(p, crtc->state);
+ if (take_locks)
+ drm_modeset_unlock(&crtc->mutex);
+ }
+
+ drm_connector_list_iter_begin(dev, &conn_iter);
+ if (take_locks)
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+ drm_for_each_connector_iter(connector, &conn_iter)
+ drm_atomic_connector_print_state(p, connector->state);
+ if (take_locks)
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
+ drm_connector_list_iter_end(&conn_iter);
+}
+
/**
* drm_state_dump - dump entire device atomic state
* @dev: the drm device
*/
void drm_state_dump(struct drm_device *dev, struct drm_printer *p)
{
- struct drm_mode_config *config = &dev->mode_config;
- struct drm_plane *plane;
- struct drm_crtc *crtc;
- struct drm_connector *connector;
- struct drm_connector_list_iter conn_iter;
-
- if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
- return;
-
- list_for_each_entry(plane, &config->plane_list, head)
- drm_atomic_plane_print_state(p, plane->state);
-
- list_for_each_entry(crtc, &config->crtc_list, head)
- drm_atomic_crtc_print_state(p, crtc->state);
-
- drm_connector_list_iter_get(dev, &conn_iter);
- drm_for_each_connector_iter(connector, &conn_iter)
- drm_atomic_connector_print_state(p, connector->state);
- drm_connector_list_iter_put(&conn_iter);
+ __drm_state_dump(dev, p, false);
}
EXPORT_SYMBOL(drm_state_dump);
struct drm_device *dev = node->minor->dev;
struct drm_printer p = drm_seq_file_printer(m);
- drm_modeset_lock_all(dev);
- drm_state_dump(dev, &p);
- drm_modeset_unlock_all(dev);
+ __drm_state_dump(dev, &p, true);
return 0;
}
if (ret == 0) {
struct drm_framebuffer *new_fb = plane->state->fb;
if (new_fb)
- drm_framebuffer_reference(new_fb);
+ drm_framebuffer_get(new_fb);
plane->fb = new_fb;
plane->crtc = plane->state->crtc;
if (plane->old_fb)
- drm_framebuffer_unreference(plane->old_fb);
+ drm_framebuffer_put(plane->old_fb);
}
plane->old_fb = NULL;
}
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY)
return 0;
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
s32 __user *fence_ptr;
fence_ptr = get_out_fence_for_crtc(crtc_state->state, crtc);
return;
}
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
+ for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
struct drm_pending_vblank_event *event = crtc_state->event;
/*
* Free the allocated event. drm_atomic_helper_setup_commit
}
if (!obj->properties) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
ret = -ENOENT;
goto out;
}
if (get_user(count_props, count_props_ptr + copied_objs)) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
ret = -EFAULT;
goto out;
}
struct drm_property *prop;
if (get_user(prop_id, props_ptr + copied_props)) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
ret = -EFAULT;
goto out;
}
prop = drm_mode_obj_find_prop_id(obj, prop_id);
if (!prop) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
ret = -ENOENT;
goto out;
}
if (copy_from_user(&prop_value,
prop_values_ptr + copied_props,
sizeof(prop_value))) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
ret = -EFAULT;
goto out;
}
ret = atomic_set_prop(state, obj, prop, prop_value);
if (ret) {
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
goto out;
}
plane_mask |= (1 << drm_plane_index(plane));
plane->old_fb = plane->fb;
}
- drm_mode_object_unreference(obj);
+ drm_mode_object_put(obj);
}
ret = prepare_crtc_signaling(dev, state, arg, file_priv, &fence_state,