@@ -233,21 +233,17 @@ void drm_client_dev_restore(struct drm_device *dev)
233233
234234static void drm_client_buffer_delete (struct drm_client_buffer * buffer )
235235{
236- struct drm_device * dev = buffer -> client -> dev ;
237-
238236 if (buffer -> gem ) {
239237 drm_gem_vunmap_unlocked (buffer -> gem , & buffer -> map );
240238 drm_gem_object_put (buffer -> gem );
241239 }
242240
243- if (buffer -> handle )
244- drm_mode_destroy_dumb (dev , buffer -> handle , buffer -> client -> file );
245-
246241 kfree (buffer );
247242}
248243
249244static struct drm_client_buffer *
250- drm_client_buffer_create (struct drm_client_dev * client , u32 width , u32 height , u32 format )
245+ drm_client_buffer_create (struct drm_client_dev * client , u32 width , u32 height ,
246+ u32 format , u32 * handle )
251247{
252248 const struct drm_format_info * info = drm_format_info (format );
253249 struct drm_mode_create_dumb dumb_args = { };
@@ -269,16 +265,15 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
269265 if (ret )
270266 goto err_delete ;
271267
272- buffer -> handle = dumb_args .handle ;
273- buffer -> pitch = dumb_args .pitch ;
274-
275268 obj = drm_gem_object_lookup (client -> file , dumb_args .handle );
276269 if (!obj ) {
277270 ret = - ENOENT ;
278271 goto err_delete ;
279272 }
280273
274+ buffer -> pitch = dumb_args .pitch ;
281275 buffer -> gem = obj ;
276+ * handle = dumb_args .handle ;
282277
283278 return buffer ;
284279
@@ -365,7 +360,8 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)
365360}
366361
367362static int drm_client_buffer_addfb (struct drm_client_buffer * buffer ,
368- u32 width , u32 height , u32 format )
363+ u32 width , u32 height , u32 format ,
364+ u32 handle )
369365{
370366 struct drm_client_dev * client = buffer -> client ;
371367 struct drm_mode_fb_cmd fb_req = { };
@@ -377,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
377373 fb_req .depth = info -> depth ;
378374 fb_req .width = width ;
379375 fb_req .height = height ;
380- fb_req .handle = buffer -> handle ;
376+ fb_req .handle = handle ;
381377 fb_req .pitch = buffer -> pitch ;
382378
383379 ret = drm_mode_addfb (client -> dev , & fb_req , client -> file );
@@ -414,13 +410,24 @@ struct drm_client_buffer *
414410drm_client_framebuffer_create (struct drm_client_dev * client , u32 width , u32 height , u32 format )
415411{
416412 struct drm_client_buffer * buffer ;
413+ u32 handle ;
417414 int ret ;
418415
419- buffer = drm_client_buffer_create (client , width , height , format );
416+ buffer = drm_client_buffer_create (client , width , height , format ,
417+ & handle );
420418 if (IS_ERR (buffer ))
421419 return buffer ;
422420
423- ret = drm_client_buffer_addfb (buffer , width , height , format );
421+ ret = drm_client_buffer_addfb (buffer , width , height , format , handle );
422+
423+ /*
424+ * The handle is only needed for creating the framebuffer, destroy it
425+ * again to solve a circular dependency should anybody export the GEM
426+ * object as DMA-buf. The framebuffer and our buffer structure are still
427+ * holding references to the GEM object to prevent its destruction.
428+ */
429+ drm_mode_destroy_dumb (client -> dev , handle , client -> file );
430+
424431 if (ret ) {
425432 drm_client_buffer_delete (buffer );
426433 return ERR_PTR (ret );
0 commit comments