From 88a48e297b3a3bac6022c03babfb038f1a886cea Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:50 -0500 Subject: drm: add atomic properties Once a driver is using atomic helpers for modeset, the next step is to switch over to atomic properties. To do this, make sure that any modeset objects have their ->atomic_{get,set}_property() vfuncs suitably populated if they have custom properties (you did already remember to plug in atomic-helper func for the legacy ->set_property() vfuncs, right?), and then set DRIVER_ATOMIC bit in driver_features flag. A new cap is introduced, DRM_CLIENT_CAP_ATOMIC, for the purposes of shielding legacy userspace from atomic properties. Mostly for the benefit of legacy DDX drivers that do silly things like getting/setting each property at startup (since some of the new atomic properties will be able to trigger modeset). Signed-off-by: Rob Clark [danvet: Squash in fixup patch to check for DRM_MODE_PROP_ATOMIC instaed of the CAP define when filtering properties. Reported by Tvrtko Uruslin, acked by Rob.] Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers/gpu/drm/drm_ioctl.c') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 00587a1e3c83..adc822312f6c 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -345,6 +345,16 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; file_priv->universal_planes = req->value; break; + case DRM_CLIENT_CAP_ATOMIC: + /* for now, hide behind experimental drm.atomic moduleparam */ + if (!drm_atomic) + return -EINVAL; + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + if (req->value > 1) + return -EINVAL; + file_priv->atomic = req->value; + break; default: return -EINVAL; } -- cgit v1.2.3 From d34f20d6e2f21bd3531b969dc40913181a8ae31a Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 18 Dec 2014 16:01:56 -0500 Subject: drm: Atomic modeset ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The atomic modeset ioctl can be used to push any number of new values for object properties. The driver can then check the full device configuration as single unit, and try to apply the changes atomically. The ioctl simply takes a list of object IDs and property IDs and their values. Originally based on a patch from Ville Syrjälä, although it has mutated (mutilated?) enough since then that you probably shouldn't blame it on him ;-) The atomic support is hidden behind the DRM_CLIENT_CAP_ATOMIC cap (to protect legacy userspace) and drm.atomic module param (for now). v2: Check for file_priv->atomic to make sure we only allow userspace in-the-know to use atomic. Signed-off-by: Rob Clark Reviewed-by: Sean Paul Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 331 +++++++++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/drm_crtc.c | 4 +- drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_crtc.h | 10 +- include/uapi/drm/drm.h | 1 + include/uapi/drm/drm_mode.h | 23 +++ 6 files changed, 366 insertions(+), 4 deletions(-) (limited to 'drivers/gpu/drm/drm_ioctl.c') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 57cc68177f09..67f64bd1058f 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -56,6 +56,11 @@ drm_atomic_state_alloc(struct drm_device *dev) if (!state) return NULL; + /* TODO legacy paths should maybe do a better job about + * setting this appropriately? + */ + state->allow_modeset = true; + state->num_connector = ACCESS_ONCE(dev->mode_config.num_connector); state->crtcs = kcalloc(dev->mode_config.num_crtc, @@ -1003,6 +1008,22 @@ int drm_atomic_check_only(struct drm_atomic_state *state) if (config->funcs->atomic_check) ret = config->funcs->atomic_check(state->dev, state); + if (!state->allow_modeset) { + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc *crtc = state->crtcs[i]; + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + + if (!crtc) + continue; + + if (crtc_state->mode_changed) { + DRM_DEBUG_KMS("[CRTC:%d] requires full modeset\n", + crtc->base.id); + return -EINVAL; + } + } + } + return ret; } EXPORT_SYMBOL(drm_atomic_check_only); @@ -1068,3 +1089,313 @@ int drm_atomic_async_commit(struct drm_atomic_state *state) return config->funcs->atomic_commit(state->dev, state, true); } EXPORT_SYMBOL(drm_atomic_async_commit); + +/* + * The big monstor ioctl + */ + +static struct drm_pending_vblank_event *create_vblank_event( + struct drm_device *dev, struct drm_file *file_priv, uint64_t user_data) +{ + struct drm_pending_vblank_event *e = NULL; + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + if (file_priv->event_space < sizeof e->event) { + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + file_priv->event_space -= sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + + e = kzalloc(sizeof *e, GFP_KERNEL); + if (e == NULL) { + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + goto out; + } + + e->event.base.type = DRM_EVENT_FLIP_COMPLETE; + e->event.base.length = sizeof e->event; + e->event.user_data = user_data; + e->base.event = &e->event.base; + e->base.file_priv = file_priv; + e->base.destroy = (void (*) (struct drm_pending_event *)) kfree; + +out: + return e; +} + +static void destroy_vblank_event(struct drm_device *dev, + struct drm_file *file_priv, struct drm_pending_vblank_event *e) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->event_lock, flags); + file_priv->event_space += sizeof e->event; + spin_unlock_irqrestore(&dev->event_lock, flags); + kfree(e); +} + +static int atomic_set_prop(struct drm_atomic_state *state, + struct drm_mode_object *obj, struct drm_property *prop, + uint64_t prop_value) +{ + struct drm_mode_object *ref; + int ret; + + if (!drm_property_change_valid_get(prop, prop_value, &ref)) + return -EINVAL; + + switch (obj->type) { + case DRM_MODE_OBJECT_CONNECTOR: { + struct drm_connector *connector = obj_to_connector(obj); + struct drm_connector_state *connector_state; + + connector_state = drm_atomic_get_connector_state(state, connector); + if (IS_ERR(connector_state)) { + ret = PTR_ERR(connector_state); + break; + } + + ret = drm_atomic_connector_set_property(connector, + connector_state, prop, prop_value); + break; + } + case DRM_MODE_OBJECT_CRTC: { + struct drm_crtc *crtc = obj_to_crtc(obj); + struct drm_crtc_state *crtc_state; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + break; + } + + ret = drm_atomic_crtc_set_property(crtc, + crtc_state, prop, prop_value); + break; + } + case DRM_MODE_OBJECT_PLANE: { + struct drm_plane *plane = obj_to_plane(obj); + struct drm_plane_state *plane_state; + + plane_state = drm_atomic_get_plane_state(state, plane); + if (IS_ERR(plane_state)) { + ret = PTR_ERR(plane_state); + break; + } + + ret = drm_atomic_plane_set_property(plane, + plane_state, prop, prop_value); + break; + } + default: + ret = -EINVAL; + break; + } + + drm_property_change_valid_put(prop, ref); + return ret; +} + +int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv) +{ + struct drm_mode_atomic *arg = data; + uint32_t __user *objs_ptr = (uint32_t __user *)(unsigned long)(arg->objs_ptr); + uint32_t __user *count_props_ptr = (uint32_t __user *)(unsigned long)(arg->count_props_ptr); + uint32_t __user *props_ptr = (uint32_t __user *)(unsigned long)(arg->props_ptr); + uint64_t __user *prop_values_ptr = (uint64_t __user *)(unsigned long)(arg->prop_values_ptr); + unsigned int copied_objs, copied_props; + struct drm_atomic_state *state; + struct drm_modeset_acquire_ctx ctx; + struct drm_plane *plane; + unsigned plane_mask = 0; + int ret = 0; + unsigned int i, j; + + /* disallow for drivers not supporting atomic: */ + if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) + return -EINVAL; + + /* disallow for userspace that has not enabled atomic cap (even + * though this may be a bit overkill, since legacy userspace + * wouldn't know how to call this ioctl) + */ + if (!file_priv->atomic) + return -EINVAL; + + if (arg->flags & ~DRM_MODE_ATOMIC_FLAGS) + return -EINVAL; + + if (arg->reserved) + return -EINVAL; + + if ((arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) && + !dev->mode_config.async_page_flip) + return -EINVAL; + + /* can't test and expect an event at the same time. */ + if ((arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) && + (arg->flags & DRM_MODE_PAGE_FLIP_EVENT)) + return -EINVAL; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) + return -ENOMEM; + + state->acquire_ctx = &ctx; + state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET); + +retry: + copied_objs = 0; + copied_props = 0; + + for (i = 0; i < arg->count_objs; i++) { + uint32_t obj_id, count_props; + struct drm_mode_object *obj; + + if (get_user(obj_id, objs_ptr + copied_objs)) { + ret = -EFAULT; + goto fail; + } + + obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); + if (!obj || !obj->properties) { + ret = -ENOENT; + goto fail; + } + + if (obj->type == DRM_MODE_OBJECT_PLANE) { + plane = obj_to_plane(obj); + plane_mask |= (1 << drm_plane_index(plane)); + plane->old_fb = plane->fb; + } + + if (get_user(count_props, count_props_ptr + copied_objs)) { + ret = -EFAULT; + goto fail; + } + + copied_objs++; + + for (j = 0; j < count_props; j++) { + uint32_t prop_id; + uint64_t prop_value; + struct drm_property *prop; + + if (get_user(prop_id, props_ptr + copied_props)) { + ret = -EFAULT; + goto fail; + } + + prop = drm_property_find(dev, prop_id); + if (!prop) { + ret = -ENOENT; + goto fail; + } + + if (get_user(prop_value, prop_values_ptr + copied_props)) { + ret = -EFAULT; + goto fail; + } + + ret = atomic_set_prop(state, obj, prop, prop_value); + if (ret) + goto fail; + + copied_props++; + } + } + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { + int ncrtcs = dev->mode_config.num_crtc; + + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + struct drm_pending_vblank_event *e; + + if (!crtc_state) + continue; + + e = create_vblank_event(dev, file_priv, arg->user_data); + if (!e) { + ret = -ENOMEM; + goto fail; + } + + crtc_state->event = e; + } + } + + if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) { + ret = drm_atomic_check_only(state); + /* _check_only() does not free state, unlike _commit() */ + drm_atomic_state_free(state); + } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { + ret = drm_atomic_async_commit(state); + } else { + ret = drm_atomic_commit(state); + } + + /* if succeeded, fixup legacy plane crtc/fb ptrs before dropping + * locks (ie. while it is still safe to deref plane->state). We + * need to do this here because the driver entry points cannot + * distinguish between legacy and atomic ioctls. + */ + drm_for_each_plane_mask(plane, dev, plane_mask) { + if (ret == 0) { + struct drm_framebuffer *new_fb = plane->state->fb; + if (new_fb) + drm_framebuffer_reference(new_fb); + plane->fb = new_fb; + plane->crtc = plane->state->crtc; + } else { + plane->old_fb = NULL; + } + if (plane->old_fb) { + drm_framebuffer_unreference(plane->old_fb); + plane->old_fb = NULL; + } + } + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +fail: + if (ret == -EDEADLK) + goto backoff; + + if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) { + int ncrtcs = dev->mode_config.num_crtc; + + for (i = 0; i < ncrtcs; i++) { + struct drm_crtc_state *crtc_state = state->crtc_states[i]; + + if (!crtc_state) + continue; + + destroy_vblank_event(dev, file_priv, crtc_state->event); + crtc_state->event = NULL; + } + } + + drm_atomic_state_free(state); + + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); + + return ret; + +backoff: + drm_atomic_state_clear(state); + drm_modeset_backoff(&ctx); + + goto retry; +} diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 3cb1fa09ac9e..20596423d52d 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -4303,7 +4303,7 @@ EXPORT_SYMBOL(drm_mode_connector_update_edid_property); * object to which the property is attached has a chance to take it's own * reference). */ -static bool drm_property_change_valid_get(struct drm_property *property, +bool drm_property_change_valid_get(struct drm_property *property, uint64_t value, struct drm_mode_object **ref) { int i; @@ -4365,7 +4365,7 @@ static bool drm_property_change_valid_get(struct drm_property *property, return false; } -static void drm_property_change_valid_put(struct drm_property *property, +void drm_property_change_valid_put(struct drm_property *property, struct drm_mode_object *ref) { if (!ref) diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index adc822312f6c..a28c0abd1a38 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -630,6 +630,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index fc4767fa723b..1dcfb685d15f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -902,7 +902,7 @@ struct drm_bridge { /** * struct struct drm_atomic_state - the global state object for atomic updates * @dev: parent DRM device - * @flags: state flags like async update + * @allow_modeset: allow full modeset * @planes: pointer to array of plane pointers * @plane_states: pointer to array of plane states pointers * @crtcs: pointer to array of CRTC pointers @@ -914,7 +914,7 @@ struct drm_bridge { */ struct drm_atomic_state { struct drm_device *dev; - uint32_t flags; + bool allow_modeset : 1; struct drm_plane **planes; struct drm_plane_state **plane_states; struct drm_crtc **crtcs; @@ -1346,6 +1346,10 @@ extern int drm_mode_create_scaling_mode_property(struct drm_device *dev); extern int drm_mode_create_aspect_ratio_property(struct drm_device *dev); extern int drm_mode_create_dirty_info_property(struct drm_device *dev); extern int drm_mode_create_suggested_offset_properties(struct drm_device *dev); +extern bool drm_property_change_valid_get(struct drm_property *property, + uint64_t value, struct drm_mode_object **ref); +extern void drm_property_change_valid_put(struct drm_property *property, + struct drm_mode_object *ref); extern int drm_mode_connector_attach_encoder(struct drm_connector *connector, struct drm_encoder *encoder); @@ -1437,6 +1441,8 @@ extern int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, extern int drm_mode_plane_set_obj_prop(struct drm_plane *plane, struct drm_property *property, uint64_t value); +extern int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); extern void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index f7b2baf7ecb2..01b2d6d0e355 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -784,6 +784,7 @@ struct drm_prime_handle { #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) #define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) /** * Device specific ioctls should only be in their respective headers diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index b8f9c0f2e7fe..ca788e01dab2 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h @@ -526,4 +526,27 @@ struct drm_mode_destroy_dumb { uint32_t handle; }; +/* page-flip flags are valid, plus: */ +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 +#define DRM_MODE_ATOMIC_ALLOW_MODESET 0x0400 + +#define DRM_MODE_ATOMIC_FLAGS (\ + DRM_MODE_PAGE_FLIP_EVENT |\ + DRM_MODE_PAGE_FLIP_ASYNC |\ + DRM_MODE_ATOMIC_TEST_ONLY |\ + DRM_MODE_ATOMIC_NONBLOCK |\ + DRM_MODE_ATOMIC_ALLOW_MODESET) + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + #endif -- cgit v1.2.3 From a97df1ccd3c30f16385696964767adf854878021 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Thu, 18 Dec 2014 22:49:02 +0100 Subject: drm/atomic: Hide drm.ko internal interfaces This is just a bit fallout from patch polishing and moving the get_prop logic fully into the core: - Drop EXPORT_SYMBOL and make the helpers static. - Drop kerneldoc since not used by drivers. - Move the cross-file function declarations only used by drm.ko internally to an internal header. v2: keep the gist of the comments, requested by Rob. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_atomic.c | 54 +++++-------------------------------- drivers/gpu/drm/drm_crtc_internal.h | 6 +++++ drivers/gpu/drm/drm_ioctl.c | 1 + include/drm/drm_atomic.h | 12 --------- 4 files changed, 14 insertions(+), 59 deletions(-) (limited to 'drivers/gpu/drm/drm_ioctl.c') diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 67f64bd1058f..1e38dfc8e462 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -247,21 +247,11 @@ int drm_atomic_crtc_set_property(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_atomic_crtc_set_property); -/** - * drm_atomic_crtc_get_property - get property on CRTC - * @crtc: the drm CRTC to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling crtc->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, const struct drm_crtc_state *state, @@ -271,7 +261,6 @@ int drm_atomic_crtc_get_property(struct drm_crtc *crtc, return crtc->funcs->atomic_get_property(crtc, state, property, val); return -EINVAL; } -EXPORT_SYMBOL(drm_atomic_crtc_get_property); /** * drm_atomic_crtc_check - check crtc state @@ -409,23 +398,14 @@ int drm_atomic_plane_set_property(struct drm_plane *plane, } EXPORT_SYMBOL(drm_atomic_plane_set_property); -/** - * drm_atomic_plane_get_property - get property on plane - * @plane: the drm plane to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling plane->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ -int drm_atomic_plane_get_property(struct drm_plane *plane, +static int +drm_atomic_plane_get_property(struct drm_plane *plane, const struct drm_plane_state *state, struct drm_property *property, uint64_t *val) { @@ -460,7 +440,6 @@ int drm_atomic_plane_get_property(struct drm_plane *plane, return 0; } -EXPORT_SYMBOL(drm_atomic_plane_get_property); /** * drm_atomic_plane_check - check plane state @@ -650,23 +629,14 @@ int drm_atomic_connector_set_property(struct drm_connector *connector, } EXPORT_SYMBOL(drm_atomic_connector_set_property); -/** - * drm_atomic_connector_get_property - get property on connector - * @connector: the drm connector to get a property on - * @state: the state object with the property value to read - * @property: the property to get - * @val: the property value (returned by reference) - * - * Use this instead of calling connector->atomic_get_property directly. +/* * This function handles generic/core properties and calls out to * driver's ->atomic_get_property() for driver properties. To ensure * consistent behavior you must call this function rather than the * driver hook directly. - * - * RETURNS: - * Zero on success, error code on failure */ -int drm_atomic_connector_get_property(struct drm_connector *connector, +static int +drm_atomic_connector_get_property(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val) { @@ -686,17 +656,7 @@ int drm_atomic_connector_get_property(struct drm_connector *connector, return 0; } -EXPORT_SYMBOL(drm_atomic_connector_get_property); -/** - * drm_atomic_get_property - helper to read atomic property - * @obj: drm mode object whose property to read - * @property: the property to read - * @val: the read value, returned by reference - * - * RETURNS: - * Zero on success, error code on failure - */ int drm_atomic_get_property(struct drm_mode_object *obj, struct drm_property *property, uint64_t *val) { diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index a2945ee6d675..247dc8b62564 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -36,3 +36,9 @@ int drm_mode_object_get(struct drm_device *dev, void drm_mode_object_put(struct drm_device *dev, struct drm_mode_object *object); +/* drm_atomic.c */ +int drm_atomic_get_property(struct drm_mode_object *obj, + struct drm_property *property, uint64_t *val); +int drm_mode_atomic_ioctl(struct drm_device *dev, + void *data, struct drm_file *file_priv); + diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a28c0abd1a38..5cb405812245 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -32,6 +32,7 @@ #include #include "drm_legacy.h" #include "drm_internal.h" +#include "drm_crtc_internal.h" #include #include diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 231fb485abb3..51168a8b723a 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -41,30 +41,18 @@ drm_atomic_get_crtc_state(struct drm_atomic_state *state, int drm_atomic_crtc_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_crtc_get_property(struct drm_crtc *crtc, - const struct drm_crtc_state *state, - struct drm_property *property, uint64_t *val); struct drm_plane_state * __must_check drm_atomic_get_plane_state(struct drm_atomic_state *state, struct drm_plane *plane); int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_plane_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_plane_get_property(struct drm_plane *plane, - const struct drm_plane_state *state, - struct drm_property *property, uint64_t *val); struct drm_connector_state * __must_check drm_atomic_get_connector_state(struct drm_atomic_state *state, struct drm_connector *connector); int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val); -int drm_atomic_connector_get_property(struct drm_connector *connector, - const struct drm_connector_state *state, - struct drm_property *property, uint64_t *val); - -int drm_atomic_get_property(struct drm_mode_object *obj, - struct drm_property *property, uint64_t *val); int __must_check drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state, -- cgit v1.2.3 From 179f158ccf15fb9425f53d589d1b48eab90449a6 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Fri, 19 Dec 2014 10:33:52 +0100 Subject: drm: Ensure universal_planes is set for atomic Atomic doesn't really work without universal planes anyway. But make sure that evil userspace doesn't pull the kernel over the table because we didn't consider a cornercase that just doesn't make sense, just for safety. v2: Just force ->universal_planes to the same value to avoid imposing restrictions on userspace. Cc: Rob Clark Reviewed-by: Rob Clark Signed-off-by: Daniel Vetter --- drivers/gpu/drm/drm_ioctl.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/gpu/drm/drm_ioctl.c') diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 5cb405812245..3785d66721f2 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -355,6 +355,7 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) if (req->value > 1) return -EINVAL; file_priv->atomic = req->value; + file_priv->universal_planes = req->value; break; default: return -EINVAL; -- cgit v1.2.3