@@ -223,23 +223,34 @@ static void drm_gem_object_handle_get(struct drm_gem_object *obj)
223223}
224224
225225/**
226- * drm_gem_object_handle_get_unlocked - acquire reference on user-space handles
226+ * drm_gem_object_handle_get_if_exists_unlocked - acquire reference on user-space handle, if any
227227 * @obj: GEM object
228228 *
229- * Acquires a reference on the GEM buffer object's handle. Required
230- * to keep the GEM object alive. Call drm_gem_object_handle_put_unlocked()
231- * to release the reference.
229+ * Acquires a reference on the GEM buffer object's handle. Required to keep
230+ * the GEM object alive. Call drm_gem_object_handle_put_if_exists_unlocked()
231+ * to release the reference. Does nothing if the buffer object has no handle.
232+ *
233+ * Returns:
234+ * True if a handle exists, or false otherwise
232235 */
233- void drm_gem_object_handle_get_unlocked (struct drm_gem_object * obj )
236+ bool drm_gem_object_handle_get_if_exists_unlocked (struct drm_gem_object * obj )
234237{
235238 struct drm_device * dev = obj -> dev ;
236239
237240 guard (mutex )(& dev -> object_name_lock );
238241
239- drm_WARN_ON (dev , !obj -> handle_count ); /* first ref taken in create-tail helper */
242+ /*
243+ * First ref taken during GEM object creation, if any. Some
244+ * drivers set up internal framebuffers with GEM objects that
245+ * do not have a GEM handle. Hence, this counter can be zero.
246+ */
247+ if (!obj -> handle_count )
248+ return false;
249+
240250 drm_gem_object_handle_get (obj );
251+
252+ return true;
241253}
242- EXPORT_SYMBOL (drm_gem_object_handle_get_unlocked );
243254
244255/**
245256 * drm_gem_object_handle_free - release resources bound to userspace handles
@@ -272,7 +283,7 @@ static void drm_gem_object_exported_dma_buf_free(struct drm_gem_object *obj)
272283}
273284
274285/**
275- * drm_gem_object_handle_put_unlocked - releases reference on user-space handles
286+ * drm_gem_object_handle_put_unlocked - releases reference on user-space handle
276287 * @obj: GEM object
277288 *
278289 * Releases a reference on the GEM buffer object's handle. Possibly releases
@@ -283,14 +294,14 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
283294 struct drm_device * dev = obj -> dev ;
284295 bool final = false;
285296
286- if (WARN_ON ( READ_ONCE (obj -> handle_count ) == 0 ))
297+ if (drm_WARN_ON ( dev , READ_ONCE (obj -> handle_count ) == 0 ))
287298 return ;
288299
289300 /*
290- * Must bump handle count first as this may be the last
291- * ref, in which case the object would disappear before we
292- * checked for a name
293- */
301+ * Must bump handle count first as this may be the last
302+ * ref, in which case the object would disappear before
303+ * we checked for a name.
304+ */
294305
295306 mutex_lock (& dev -> object_name_lock );
296307 if (-- obj -> handle_count == 0 ) {
@@ -303,7 +314,6 @@ void drm_gem_object_handle_put_unlocked(struct drm_gem_object *obj)
303314 if (final )
304315 drm_gem_object_put (obj );
305316}
306- EXPORT_SYMBOL (drm_gem_object_handle_put_unlocked );
307317
308318/*
309319 * Called at device or object close to release the file's
@@ -315,6 +325,9 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
315325 struct drm_file * file_priv = data ;
316326 struct drm_gem_object * obj = ptr ;
317327
328+ if (drm_WARN_ON (obj -> dev , !data ))
329+ return 0 ;
330+
318331 if (obj -> funcs -> close )
319332 obj -> funcs -> close (obj , file_priv );
320333
@@ -435,7 +448,7 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
435448 idr_preload (GFP_KERNEL );
436449 spin_lock (& file_priv -> table_lock );
437450
438- ret = idr_alloc (& file_priv -> object_idr , obj , 1 , 0 , GFP_NOWAIT );
451+ ret = idr_alloc (& file_priv -> object_idr , NULL , 1 , 0 , GFP_NOWAIT );
439452
440453 spin_unlock (& file_priv -> table_lock );
441454 idr_preload_end ();
@@ -456,6 +469,11 @@ drm_gem_handle_create_tail(struct drm_file *file_priv,
456469 goto err_revoke ;
457470 }
458471
472+ /* mirrors drm_gem_handle_delete to avoid races */
473+ spin_lock (& file_priv -> table_lock );
474+ obj = idr_replace (& file_priv -> object_idr , obj , handle );
475+ WARN_ON (obj != NULL );
476+ spin_unlock (& file_priv -> table_lock );
459477 * handlep = handle ;
460478 return 0 ;
461479
0 commit comments