diff options
Diffstat (limited to 'drivers/gpu/drm/drm_client.c')
| -rw-r--r-- | drivers/gpu/drm/drm_client.c | 54 | 
1 files changed, 35 insertions, 19 deletions
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index fd67efe37c63..f6292ba0e6fc 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -198,13 +198,23 @@ void drm_client_dev_hotplug(struct drm_device *dev)  	if (!drm_core_check_feature(dev, DRIVER_MODESET))  		return; +	if (!dev->mode_config.num_connector) { +		drm_dbg_kms(dev, "No connectors found, will not send hotplug events!\n"); +		return; +	} +  	mutex_lock(&dev->clientlist_mutex);  	list_for_each_entry(client, &dev->clientlist, list) {  		if (!client->funcs || !client->funcs->hotplug)  			continue; +		if (client->hotplug_failed) +			continue; +  		ret = client->funcs->hotplug(client);  		drm_dbg_kms(dev, "%s: ret=%d\n", client->name, ret); +		if (ret) +			client->hotplug_failed = true;  	}  	mutex_unlock(&dev->clientlist_mutex);  } @@ -233,21 +243,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 +275,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 +370,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 +383,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 +420,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); @@ -480,8 +497,8 @@ EXPORT_SYMBOL(drm_client_framebuffer_flush);  #ifdef CONFIG_DEBUG_FS  static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)  { -	struct drm_info_node *node = m->private; -	struct drm_device *dev = node->minor->dev; +	struct drm_debugfs_entry *entry = m->private; +	struct drm_device *dev = entry->dev;  	struct drm_printer p = drm_seq_file_printer(m);  	struct drm_client_dev *client; @@ -493,14 +510,13 @@ static int drm_client_debugfs_internal_clients(struct seq_file *m, void *data)  	return 0;  } -static const struct drm_info_list drm_client_debugfs_list[] = { +static const struct drm_debugfs_info drm_client_debugfs_list[] = {  	{ "internal_clients", drm_client_debugfs_internal_clients, 0 },  };  void drm_client_debugfs_init(struct drm_minor *minor)  { -	drm_debugfs_create_files(drm_client_debugfs_list, -				 ARRAY_SIZE(drm_client_debugfs_list), -				 minor->debugfs_root, minor); +	drm_debugfs_add_files(minor->dev, drm_client_debugfs_list, +			      ARRAY_SIZE(drm_client_debugfs_list));  }  #endif  |