Commit 0e26cc72 authored by André Almeida's avatar André Almeida Committed by Simon Ser

drm: Refuse to async flip with atomic prop changes

Given that prop changes may lead to modesetting, which would defeat the
fast path of the async flip, refuse any atomic prop change for async
flips in atomic API. The only exception is the framebuffer ID to flip
to. Currently the only plane type supported is the primary one.
Signed-off-by: default avatarAndré Almeida <andrealmeid@igalia.com>
Reviewed-by: default avatarSimon Ser <contact@emersion.fr>
Signed-off-by: default avatarSimon Ser <contact@emersion.fr>
Link: https://patchwork.freedesktop.org/patch/msgid/20231122161941.320564-2-andrealmeid@igalia.com
parent 815d8b04
...@@ -1006,13 +1006,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state, ...@@ -1006,13 +1006,28 @@ int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
return ret; return ret;
} }
static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t prop_value,
struct drm_property *prop)
{
if (ret != 0 || old_val != prop_value) {
drm_dbg_atomic(prop->dev,
"[PROP:%d:%s] No prop can be changed during async flip\n",
prop->base.id, prop->name);
return -EINVAL;
}
return 0;
}
int drm_atomic_set_property(struct drm_atomic_state *state, int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_file *file_priv, struct drm_file *file_priv,
struct drm_mode_object *obj, struct drm_mode_object *obj,
struct drm_property *prop, struct drm_property *prop,
uint64_t prop_value) u64 prop_value,
bool async_flip)
{ {
struct drm_mode_object *ref; struct drm_mode_object *ref;
u64 old_val;
int ret; int ret;
if (!drm_property_change_valid_get(prop, prop_value, &ref)) if (!drm_property_change_valid_get(prop, prop_value, &ref))
...@@ -1029,6 +1044,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, ...@@ -1029,6 +1044,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
break; break;
} }
if (async_flip) {
ret = drm_atomic_connector_get_property(connector, connector_state,
prop, &old_val);
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
break;
}
ret = drm_atomic_connector_set_property(connector, ret = drm_atomic_connector_set_property(connector,
connector_state, file_priv, connector_state, file_priv,
prop, prop_value); prop, prop_value);
...@@ -1044,6 +1066,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state, ...@@ -1044,6 +1066,13 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
break; break;
} }
if (async_flip) {
ret = drm_atomic_crtc_get_property(crtc, crtc_state,
prop, &old_val);
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
break;
}
ret = drm_atomic_crtc_set_property(crtc, ret = drm_atomic_crtc_set_property(crtc,
crtc_state, prop, prop_value); crtc_state, prop, prop_value);
break; break;
...@@ -1051,6 +1080,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, ...@@ -1051,6 +1080,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
case DRM_MODE_OBJECT_PLANE: { case DRM_MODE_OBJECT_PLANE: {
struct drm_plane *plane = obj_to_plane(obj); struct drm_plane *plane = obj_to_plane(obj);
struct drm_plane_state *plane_state; struct drm_plane_state *plane_state;
struct drm_mode_config *config = &plane->dev->mode_config;
plane_state = drm_atomic_get_plane_state(state, plane); plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) { if (IS_ERR(plane_state)) {
...@@ -1058,6 +1088,21 @@ int drm_atomic_set_property(struct drm_atomic_state *state, ...@@ -1058,6 +1088,21 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
break; break;
} }
if (async_flip && prop != config->prop_fb_id) {
ret = drm_atomic_plane_get_property(plane, plane_state,
prop, &old_val);
ret = drm_atomic_check_prop_changes(ret, old_val, prop_value, prop);
break;
}
if (async_flip && plane_state->plane->type != DRM_PLANE_TYPE_PRIMARY) {
drm_dbg_atomic(prop->dev,
"[OBJECT:%d] Only primary planes can be changed during async flip\n",
obj->id);
ret = -EINVAL;
break;
}
ret = drm_atomic_plane_set_property(plane, ret = drm_atomic_plane_set_property(plane,
plane_state, file_priv, plane_state, file_priv,
prop, prop_value); prop, prop_value);
...@@ -1337,6 +1382,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, ...@@ -1337,6 +1382,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
struct drm_out_fence_state *fence_state; struct drm_out_fence_state *fence_state;
int ret = 0; int ret = 0;
unsigned int i, j, num_fences; unsigned int i, j, num_fences;
bool async_flip = false;
/* disallow for drivers not supporting atomic: */ /* disallow for drivers not supporting atomic: */
if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) if (!drm_core_check_feature(dev, DRIVER_ATOMIC))
...@@ -1450,8 +1496,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, ...@@ -1450,8 +1496,8 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
goto out; goto out;
} }
ret = drm_atomic_set_property(state, file_priv, ret = drm_atomic_set_property(state, file_priv, obj,
obj, prop, prop_value); prop, prop_value, async_flip);
if (ret) { if (ret) {
drm_mode_object_put(obj); drm_mode_object_put(obj);
goto out; goto out;
......
...@@ -253,7 +253,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state, ...@@ -253,7 +253,7 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_file *file_priv, struct drm_file *file_priv,
struct drm_mode_object *obj, struct drm_mode_object *obj,
struct drm_property *prop, struct drm_property *prop,
uint64_t prop_value); u64 prop_value, bool async_flip);
int drm_atomic_get_property(struct drm_mode_object *obj, int drm_atomic_get_property(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val); struct drm_property *property, uint64_t *val);
......
...@@ -538,7 +538,7 @@ static int set_property_atomic(struct drm_mode_object *obj, ...@@ -538,7 +538,7 @@ static int set_property_atomic(struct drm_mode_object *obj,
obj_to_connector(obj), obj_to_connector(obj),
prop_value); prop_value);
} else { } else {
ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value); ret = drm_atomic_set_property(state, file_priv, obj, prop, prop_value, false);
if (ret) if (ret)
goto out; goto out;
ret = drm_atomic_commit(state); ret = drm_atomic_commit(state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment