diff options
-rw-r--r-- | drivers/gpu/drm/drm_gem.c | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/drm_info.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/exynos/exynos_drm_gem.c | 2 | ||||
-rw-r--r-- | include/drm/drmP.h | 19 |
4 files changed, 32 insertions, 22 deletions
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index dcbd2f559e39..b8a8132becef 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c | |||
@@ -154,7 +154,7 @@ void drm_gem_private_object_init(struct drm_device *dev, | |||
154 | obj->filp = NULL; | 154 | obj->filp = NULL; |
155 | 155 | ||
156 | kref_init(&obj->refcount); | 156 | kref_init(&obj->refcount); |
157 | atomic_set(&obj->handle_count, 0); | 157 | obj->handle_count = 0; |
158 | obj->size = size; | 158 | obj->size = size; |
159 | } | 159 | } |
160 | EXPORT_SYMBOL(drm_gem_private_object_init); | 160 | EXPORT_SYMBOL(drm_gem_private_object_init); |
@@ -218,11 +218,9 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj) | |||
218 | struct drm_device *dev = obj->dev; | 218 | struct drm_device *dev = obj->dev; |
219 | 219 | ||
220 | /* Remove any name for this object */ | 220 | /* Remove any name for this object */ |
221 | spin_lock(&dev->object_name_lock); | ||
222 | if (obj->name) { | 221 | if (obj->name) { |
223 | idr_remove(&dev->object_name_idr, obj->name); | 222 | idr_remove(&dev->object_name_idr, obj->name); |
224 | obj->name = 0; | 223 | obj->name = 0; |
225 | spin_unlock(&dev->object_name_lock); | ||
226 | /* | 224 | /* |
227 | * The object name held a reference to this object, drop | 225 | * The object name held a reference to this object, drop |
228 | * that now. | 226 | * that now. |
@@ -230,15 +228,13 @@ static void drm_gem_object_handle_free(struct drm_gem_object *obj) | |||
230 | * This cannot be the last reference, since the handle holds one too. | 228 | * This cannot be the last reference, since the handle holds one too. |
231 | */ | 229 | */ |
232 | kref_put(&obj->refcount, drm_gem_object_ref_bug); | 230 | kref_put(&obj->refcount, drm_gem_object_ref_bug); |
233 | } else | 231 | } |
234 | spin_unlock(&dev->object_name_lock); | ||
235 | |||
236 | } | 232 | } |
237 | 233 | ||
238 | void | 234 | void |
239 | drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | 235 | drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) |
240 | { | 236 | { |
241 | if (WARN_ON(atomic_read(&obj->handle_count) == 0)) | 237 | if (WARN_ON(obj->handle_count == 0)) |
242 | return; | 238 | return; |
243 | 239 | ||
244 | /* | 240 | /* |
@@ -247,8 +243,11 @@ drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) | |||
247 | * checked for a name | 243 | * checked for a name |
248 | */ | 244 | */ |
249 | 245 | ||
250 | if (atomic_dec_and_test(&obj->handle_count)) | 246 | spin_lock(&obj->dev->object_name_lock); |
247 | if (--obj->handle_count == 0) | ||
251 | drm_gem_object_handle_free(obj); | 248 | drm_gem_object_handle_free(obj); |
249 | spin_unlock(&obj->dev->object_name_lock); | ||
250 | |||
252 | drm_gem_object_unreference_unlocked(obj); | 251 | drm_gem_object_unreference_unlocked(obj); |
253 | } | 252 | } |
254 | 253 | ||
@@ -326,17 +325,21 @@ drm_gem_handle_create(struct drm_file *file_priv, | |||
326 | * allocation under our spinlock. | 325 | * allocation under our spinlock. |
327 | */ | 326 | */ |
328 | idr_preload(GFP_KERNEL); | 327 | idr_preload(GFP_KERNEL); |
328 | spin_lock(&dev->object_name_lock); | ||
329 | spin_lock(&file_priv->table_lock); | 329 | spin_lock(&file_priv->table_lock); |
330 | 330 | ||
331 | ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); | 331 | ret = idr_alloc(&file_priv->object_idr, obj, 1, 0, GFP_NOWAIT); |
332 | 332 | drm_gem_object_reference(obj); | |
333 | obj->handle_count++; | ||
333 | spin_unlock(&file_priv->table_lock); | 334 | spin_unlock(&file_priv->table_lock); |
335 | spin_unlock(&dev->object_name_lock); | ||
334 | idr_preload_end(); | 336 | idr_preload_end(); |
335 | if (ret < 0) | 337 | if (ret < 0) { |
338 | drm_gem_object_handle_unreference_unlocked(obj); | ||
336 | return ret; | 339 | return ret; |
340 | } | ||
337 | *handlep = ret; | 341 | *handlep = ret; |
338 | 342 | ||
339 | drm_gem_object_handle_reference(obj); | ||
340 | 343 | ||
341 | if (dev->driver->gem_open_object) { | 344 | if (dev->driver->gem_open_object) { |
342 | ret = dev->driver->gem_open_object(obj, file_priv); | 345 | ret = dev->driver->gem_open_object(obj, file_priv); |
@@ -577,6 +580,12 @@ drm_gem_flink_ioctl(struct drm_device *dev, void *data, | |||
577 | 580 | ||
578 | idr_preload(GFP_KERNEL); | 581 | idr_preload(GFP_KERNEL); |
579 | spin_lock(&dev->object_name_lock); | 582 | spin_lock(&dev->object_name_lock); |
583 | /* prevent races with concurrent gem_close. */ | ||
584 | if (obj->handle_count == 0) { | ||
585 | ret = -ENOENT; | ||
586 | goto err; | ||
587 | } | ||
588 | |||
580 | if (!obj->name) { | 589 | if (!obj->name) { |
581 | ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT); | 590 | ret = idr_alloc(&dev->object_name_idr, obj, 1, 0, GFP_NOWAIT); |
582 | if (ret < 0) | 591 | if (ret < 0) |
diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c index 9f8fc4c328c9..5351e811c421 100644 --- a/drivers/gpu/drm/drm_info.c +++ b/drivers/gpu/drm/drm_info.c | |||
@@ -207,7 +207,7 @@ static int drm_gem_one_name_info(int id, void *ptr, void *data) | |||
207 | 207 | ||
208 | seq_printf(m, "%6d %8zd %7d %8d\n", | 208 | seq_printf(m, "%6d %8zd %7d %8d\n", |
209 | obj->name, obj->size, | 209 | obj->name, obj->size, |
210 | atomic_read(&obj->handle_count), | 210 | obj->handle_count, |
211 | atomic_read(&obj->refcount.refcount)); | 211 | atomic_read(&obj->refcount.refcount)); |
212 | return 0; | 212 | return 0; |
213 | } | 213 | } |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index b904633863e8..f3c6f40666e1 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -136,7 +136,7 @@ void exynos_drm_gem_destroy(struct exynos_drm_gem_obj *exynos_gem_obj) | |||
136 | obj = &exynos_gem_obj->base; | 136 | obj = &exynos_gem_obj->base; |
137 | buf = exynos_gem_obj->buffer; | 137 | buf = exynos_gem_obj->buffer; |
138 | 138 | ||
139 | DRM_DEBUG_KMS("handle count = %d\n", atomic_read(&obj->handle_count)); | 139 | DRM_DEBUG_KMS("handle count = %d\n", obj->handle_count); |
140 | 140 | ||
141 | /* | 141 | /* |
142 | * do not release memory region from exporter. | 142 | * do not release memory region from exporter. |
diff --git a/include/drm/drmP.h b/include/drm/drmP.h index 1a7a78fdb4b7..57dce6081d73 100644 --- a/include/drm/drmP.h +++ b/include/drm/drmP.h | |||
@@ -615,8 +615,16 @@ struct drm_gem_object { | |||
615 | /** Reference count of this object */ | 615 | /** Reference count of this object */ |
616 | struct kref refcount; | 616 | struct kref refcount; |
617 | 617 | ||
618 | /** Handle count of this object. Each handle also holds a reference */ | 618 | /** |
619 | atomic_t handle_count; /* number of handles on this object */ | 619 | * handle_count - gem file_priv handle count of this object |
620 | * | ||
621 | * Each handle also holds a reference. Note that when the handle_count | ||
622 | * drops to 0 any global names (e.g. the id in the flink namespace) will | ||
623 | * be cleared. | ||
624 | * | ||
625 | * Protected by dev->object_name_lock. | ||
626 | * */ | ||
627 | unsigned handle_count; | ||
620 | 628 | ||
621 | /** Related drm device */ | 629 | /** Related drm device */ |
622 | struct drm_device *dev; | 630 | struct drm_device *dev; |
@@ -1572,13 +1580,6 @@ int drm_gem_handle_create(struct drm_file *file_priv, | |||
1572 | u32 *handlep); | 1580 | u32 *handlep); |
1573 | int drm_gem_handle_delete(struct drm_file *filp, u32 handle); | 1581 | int drm_gem_handle_delete(struct drm_file *filp, u32 handle); |
1574 | 1582 | ||
1575 | static inline void | ||
1576 | drm_gem_object_handle_reference(struct drm_gem_object *obj) | ||
1577 | { | ||
1578 | drm_gem_object_reference(obj); | ||
1579 | atomic_inc(&obj->handle_count); | ||
1580 | } | ||
1581 | |||
1582 | void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj); | 1583 | void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj); |
1583 | 1584 | ||
1584 | void drm_gem_free_mmap_offset(struct drm_gem_object *obj); | 1585 | void drm_gem_free_mmap_offset(struct drm_gem_object *obj); |