diff options
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 61 | ||||
-rw-r--r-- | include/drm/drm_crtc.h | 5 | ||||
-rw-r--r-- | include/uapi/drm/drm_mode.h | 1 |
3 files changed, 60 insertions, 7 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 73f543af4924..f990d9f180f0 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -370,6 +370,21 @@ void drm_mode_object_put(struct drm_device *dev, | |||
370 | mutex_unlock(&dev->mode_config.idr_mutex); | 370 | mutex_unlock(&dev->mode_config.idr_mutex); |
371 | } | 371 | } |
372 | 372 | ||
373 | static struct drm_mode_object *_object_find(struct drm_device *dev, | ||
374 | uint32_t id, uint32_t type) | ||
375 | { | ||
376 | struct drm_mode_object *obj = NULL; | ||
377 | |||
378 | mutex_lock(&dev->mode_config.idr_mutex); | ||
379 | obj = idr_find(&dev->mode_config.crtc_idr, id); | ||
380 | if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) || | ||
381 | (obj->id != id)) | ||
382 | obj = NULL; | ||
383 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
384 | |||
385 | return obj; | ||
386 | } | ||
387 | |||
373 | /** | 388 | /** |
374 | * drm_mode_object_find - look up a drm object with static lifetime | 389 | * drm_mode_object_find - look up a drm object with static lifetime |
375 | * @dev: drm device | 390 | * @dev: drm device |
@@ -377,7 +392,9 @@ void drm_mode_object_put(struct drm_device *dev, | |||
377 | * @type: type of the mode object | 392 | * @type: type of the mode object |
378 | * | 393 | * |
379 | * Note that framebuffers cannot be looked up with this functions - since those | 394 | * Note that framebuffers cannot be looked up with this functions - since those |
380 | * are reference counted, they need special treatment. | 395 | * are reference counted, they need special treatment. Even with |
396 | * DRM_MODE_OBJECT_ANY (although that will simply return NULL | ||
397 | * rather than WARN_ON()). | ||
381 | */ | 398 | */ |
382 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | 399 | struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, |
383 | uint32_t id, uint32_t type) | 400 | uint32_t id, uint32_t type) |
@@ -387,13 +404,10 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | |||
387 | /* Framebuffers are reference counted and need their own lookup | 404 | /* Framebuffers are reference counted and need their own lookup |
388 | * function.*/ | 405 | * function.*/ |
389 | WARN_ON(type == DRM_MODE_OBJECT_FB); | 406 | WARN_ON(type == DRM_MODE_OBJECT_FB); |
390 | 407 | obj = _object_find(dev, id, type); | |
391 | mutex_lock(&dev->mode_config.idr_mutex); | 408 | /* don't leak out unref'd fb's */ |
392 | obj = idr_find(&dev->mode_config.crtc_idr, id); | 409 | if (obj && (obj->type == DRM_MODE_OBJECT_FB)) |
393 | if (!obj || (obj->type != type) || (obj->id != id)) | ||
394 | obj = NULL; | 410 | obj = NULL; |
395 | mutex_unlock(&dev->mode_config.idr_mutex); | ||
396 | |||
397 | return obj; | 411 | return obj; |
398 | } | 412 | } |
399 | EXPORT_SYMBOL(drm_mode_object_find); | 413 | EXPORT_SYMBOL(drm_mode_object_find); |
@@ -3074,6 +3088,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags, | |||
3074 | if (!property) | 3088 | if (!property) |
3075 | return NULL; | 3089 | return NULL; |
3076 | 3090 | ||
3091 | property->dev = dev; | ||
3092 | |||
3077 | if (num_values) { | 3093 | if (num_values) { |
3078 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); | 3094 | property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL); |
3079 | if (!property->values) | 3095 | if (!property->values) |
@@ -3234,6 +3250,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags | |||
3234 | } | 3250 | } |
3235 | EXPORT_SYMBOL(drm_property_create_range); | 3251 | EXPORT_SYMBOL(drm_property_create_range); |
3236 | 3252 | ||
3253 | struct drm_property *drm_property_create_object(struct drm_device *dev, | ||
3254 | int flags, const char *name, uint32_t type) | ||
3255 | { | ||
3256 | struct drm_property *property; | ||
3257 | |||
3258 | flags |= DRM_MODE_PROP_OBJECT; | ||
3259 | |||
3260 | property = drm_property_create(dev, flags, name, 1); | ||
3261 | if (!property) | ||
3262 | return NULL; | ||
3263 | |||
3264 | property->values[0] = type; | ||
3265 | |||
3266 | return property; | ||
3267 | } | ||
3268 | EXPORT_SYMBOL(drm_property_create_object); | ||
3269 | |||
3237 | /** | 3270 | /** |
3238 | * drm_property_add_enum - add a possible value to an enumeration property | 3271 | * drm_property_add_enum - add a possible value to an enumeration property |
3239 | * @property: enumeration property to change | 3272 | * @property: enumeration property to change |
@@ -3661,6 +3694,20 @@ static bool drm_property_change_is_valid(struct drm_property *property, | |||
3661 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { | 3694 | } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) { |
3662 | /* Only the driver knows */ | 3695 | /* Only the driver knows */ |
3663 | return true; | 3696 | return true; |
3697 | } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) { | ||
3698 | struct drm_mode_object *obj; | ||
3699 | /* a zero value for an object property translates to null: */ | ||
3700 | if (value == 0) | ||
3701 | return true; | ||
3702 | /* | ||
3703 | * NOTE: use _object_find() directly to bypass restriction on | ||
3704 | * looking up refcnt'd objects (ie. fb's). For a refcnt'd | ||
3705 | * object this could race against object finalization, so it | ||
3706 | * simply tells us that the object *was* valid. Which is good | ||
3707 | * enough. | ||
3708 | */ | ||
3709 | obj = _object_find(property->dev, value, property->values[0]); | ||
3710 | return obj != NULL; | ||
3664 | } else { | 3711 | } else { |
3665 | int i; | 3712 | int i; |
3666 | for (i = 0; i < property->num_values; i++) | 3713 | for (i = 0; i < property->num_values; i++) |
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 92f6ec2de86a..cb2e599f769f 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h | |||
@@ -50,6 +50,7 @@ struct drm_clip_rect; | |||
50 | #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb | 50 | #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb |
51 | #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee | 51 | #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee |
52 | #define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd | 52 | #define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd |
53 | #define DRM_MODE_OBJECT_ANY 0 | ||
53 | 54 | ||
54 | struct drm_mode_object { | 55 | struct drm_mode_object { |
55 | uint32_t id; | 56 | uint32_t id; |
@@ -190,6 +191,7 @@ struct drm_property { | |||
190 | char name[DRM_PROP_NAME_LEN]; | 191 | char name[DRM_PROP_NAME_LEN]; |
191 | uint32_t num_values; | 192 | uint32_t num_values; |
192 | uint64_t *values; | 193 | uint64_t *values; |
194 | struct drm_device *dev; | ||
193 | 195 | ||
194 | struct list_head enum_blob_list; | 196 | struct list_head enum_blob_list; |
195 | }; | 197 | }; |
@@ -980,6 +982,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev, | |||
980 | struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, | 982 | struct drm_property *drm_property_create_range(struct drm_device *dev, int flags, |
981 | const char *name, | 983 | const char *name, |
982 | uint64_t min, uint64_t max); | 984 | uint64_t min, uint64_t max); |
985 | struct drm_property *drm_property_create_object(struct drm_device *dev, | ||
986 | int flags, const char *name, uint32_t type); | ||
983 | extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); | 987 | extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property); |
984 | extern int drm_property_add_enum(struct drm_property *property, int index, | 988 | extern int drm_property_add_enum(struct drm_property *property, int index, |
985 | uint64_t value, const char *name); | 989 | uint64_t value, const char *name); |
@@ -995,6 +999,7 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc, | |||
995 | int gamma_size); | 999 | int gamma_size); |
996 | extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, | 1000 | extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, |
997 | uint32_t id, uint32_t type); | 1001 | uint32_t id, uint32_t type); |
1002 | |||
998 | /* IOCTLs */ | 1003 | /* IOCTLs */ |
999 | extern int drm_mode_getresources(struct drm_device *dev, | 1004 | extern int drm_mode_getresources(struct drm_device *dev, |
1000 | void *data, struct drm_file *file_priv); | 1005 | void *data, struct drm_file *file_priv); |
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h index caeaa6f7ebde..57f46348befe 100644 --- a/include/uapi/drm/drm_mode.h +++ b/include/uapi/drm/drm_mode.h | |||
@@ -264,6 +264,7 @@ struct drm_mode_get_connector { | |||
264 | */ | 264 | */ |
265 | #define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 | 265 | #define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0 |
266 | #define DRM_MODE_PROP_TYPE(n) ((n) << 6) | 266 | #define DRM_MODE_PROP_TYPE(n) ((n) << 6) |
267 | #define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1) | ||
267 | 268 | ||
268 | struct drm_mode_property_enum { | 269 | struct drm_mode_property_enum { |
269 | __u64 value; | 270 | __u64 value; |