diff options
Diffstat (limited to 'drivers/gpu/drm/drm_client.c')
| -rw-r--r-- | drivers/gpu/drm/drm_client.c | 33 | 
1 files changed, 20 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index fd67efe37c63..056ab9d5f313 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -233,21 +233,17 @@ void drm_client_dev_restore(struct drm_device *dev)  static void drm_client_buffer_delete(struct drm_client_buffer *buffer)  { -	struct drm_device *dev = buffer->client->dev; -  	if (buffer->gem) {  		drm_gem_vunmap_unlocked(buffer->gem, &buffer->map);  		drm_gem_object_put(buffer->gem);  	} -	if (buffer->handle) -		drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file); -  	kfree(buffer);  }  static struct drm_client_buffer * -drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format) +drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, +			 u32 format, u32 *handle)  {  	const struct drm_format_info *info = drm_format_info(format);  	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  	if (ret)  		goto err_delete; -	buffer->handle = dumb_args.handle; -	buffer->pitch = dumb_args.pitch; -  	obj = drm_gem_object_lookup(client->file, dumb_args.handle);  	if (!obj)  {  		ret = -ENOENT;  		goto err_delete;  	} +	buffer->pitch = dumb_args.pitch;  	buffer->gem = obj; +	*handle = dumb_args.handle;  	return buffer; @@ -365,7 +360,8 @@ static void drm_client_buffer_rmfb(struct drm_client_buffer *buffer)  }  static int drm_client_buffer_addfb(struct drm_client_buffer *buffer, -				   u32 width, u32 height, u32 format) +				   u32 width, u32 height, u32 format, +				   u32 handle)  {  	struct drm_client_dev *client = buffer->client;  	struct drm_mode_fb_cmd fb_req = { }; @@ -377,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,  	fb_req.depth = info->depth;  	fb_req.width = width;  	fb_req.height = height; -	fb_req.handle = buffer->handle; +	fb_req.handle = handle;  	fb_req.pitch = buffer->pitch;  	ret = drm_mode_addfb(client->dev, &fb_req, client->file); @@ -414,13 +410,24 @@ struct drm_client_buffer *  drm_client_framebuffer_create(struct drm_client_dev *client, u32 width, u32 height, u32 format)  {  	struct drm_client_buffer *buffer; +	u32 handle;  	int ret; -	buffer = drm_client_buffer_create(client, width, height, format); +	buffer = drm_client_buffer_create(client, width, height, format, +					  &handle);  	if (IS_ERR(buffer))  		return buffer; -	ret = drm_client_buffer_addfb(buffer, width, height, format); +	ret = drm_client_buffer_addfb(buffer, width, height, format, handle); + +	/* +	 * The handle is only needed for creating the framebuffer, destroy it +	 * again to solve a circular dependency should anybody export the GEM +	 * object as DMA-buf. The framebuffer and our buffer structure are still +	 * holding references to the GEM object to prevent its destruction. +	 */ +	drm_mode_destroy_dumb(client->dev, handle, client->file); +  	if (ret) {  		drm_client_buffer_delete(buffer);  		return ERR_PTR(ret);  |