aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_gem.c31
-rw-r--r--drivers/gpu/drm/drm_info.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c2
-rw-r--r--include/drm/drmP.h19
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}
160EXPORT_SYMBOL(drm_gem_private_object_init); 160EXPORT_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
238void 234void
239drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj) 235drm_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);
1573int drm_gem_handle_delete(struct drm_file *filp, u32 handle); 1581int drm_gem_handle_delete(struct drm_file *filp, u32 handle);
1574 1582
1575static inline void
1576drm_gem_object_handle_reference(struct drm_gem_object *obj)
1577{
1578 drm_gem_object_reference(obj);
1579 atomic_inc(&obj->handle_count);
1580}
1581
1582void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj); 1583void drm_gem_object_handle_unreference_unlocked(struct drm_gem_object *obj);
1583 1584
1584void drm_gem_free_mmap_offset(struct drm_gem_object *obj); 1585void drm_gem_free_mmap_offset(struct drm_gem_object *obj);