Patch "drm: prevent double-(un)registration for connectors" has been added to the 4.9-stable tree
Subsystems (3)
This is a note to let you know that I've just added the patch titled
drm: prevent double-(un)registration for connectors
to the 4.9-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
drm-prevent-double-un-registration-for-connectors.patch
and it can be found in the queue-4.9 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From foo@baz Thu Jun 15 13:06:48 CEST 2017
From: Daniel Vetter <[email protected]>
Date: Sun, 18 Dec 2016 14:35:45 +0100
Subject: drm: prevent double-(un)registration for connectors
From: Daniel Vetter <[email protected]>
[ Upstream commit e73ab00e9a0f1731f34d0620a9c55f5c30c4ad4e ]
If we're unlucky then the registration from a hotplugged connector might race with the final registration step on driver load. And since MST topology discover is asynchronous that's even somewhat likely.
v2: Also update the kerneldoc for @registered!
v3: Review from Chris:
- Improve kerneldoc for late_register/early_unregister callbacks.
- Use mutex_destroy.
--- drivers/gpu/drm/drm_connector.c | 20 +++++++++++++++----- include/drm/drm_connector.h | 16 +++++++++++++++- 2 files changed, 30 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_connector.c +15 -5
@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_deviceINIT_LIST_HEAD (&connector->probed_modes);INIT_LIST_HEAD (&connector->modes); +mutex_init (&connector->mutex); connector->edid_blob_ptr =NULL ; connector->status = connector_status_unknown;
@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_co connector->funcs->atomic_destroy_state (connector, connector->state); +mutex_destroy (&connector->mutex); +memset (connector,0 ,sizeof (*connector)); }EXPORT_SYMBOL (drm_connector_cleanup);
@@ -374,14 +377,15 @@ EXPORT_SYMBOL(drm_connector_cleanup);*/ int drm_connector_register (struct drm_connector *connector) { -int ret; +int ret =0 ; +mutex_lock (&connector->mutex);if (connector->registered) -return 0 ; + goto unlock; ret =drm_sysfs_connector_add (connector);if (ret) -return ret; + goto unlock; ret =drm_debugfs_connector_add (connector);if (ret) {
@@ -397,12 +401,14 @@ int drm_connector_register(struct drm_codrm_mode_object_register (connector->dev, &connector->base); connector->registered = true; -return 0 ; + goto unlock; err_debugfs:drm_debugfs_connector_remove (connector); err_sysfs:drm_sysfs_connector_remove (connector); +unlock: +mutex_unlock (&connector->mutex);return ret; }EXPORT_SYMBOL (drm_connector_register);
@@ -415,8 +421,11 @@ EXPORT_SYMBOL(drm_connector_register);*/ void drm_connector_unregister (struct drm_connector *connector) { -if (!connector->registered) +mutex_lock (&connector->mutex); +if (!connector->registered) { +mutex_unlock (&connector->mutex);return ; + }if (connector->funcs->early_unregister) connector->funcs->early_unregister (connector);
@@ -425,6 +434,7 @@ void drm_connector_unregister(struct drmdrm_debugfs_connector_remove (connector); connector->registered = false; +mutex_unlock (&connector->mutex); }EXPORT_SYMBOL (drm_connector_unregister);
include/drm/drm_connector.h +15 -1
@@ -345,6 +345,8 @@ struct drm_connector_funcs {* core drm connector interfaces. Everything added from this callback * should be unregistered in the early_unregister callback. * +* This is called while holding drm_connector->mutex. +* * Returns: * * 0 on success, or a negative error code on failure.
@@ -359,6 +361,8 @@ struct drm_connector_funcs {* late_register(). It is called from drm_connector_unregister(), * early in the driver unload sequence to disable userspace access * before data structures are torndown. +* +* This is called while holding drm_connector->mutex. */ void (*early_unregister)(struct drm_connector *connector);
@@ -511,7 +515,6 @@ struct drm_cmdline_mode {* @interlace_allowed: can this connector handle interlaced modes? * @doublescan_allowed: can this connector handle doublescan? * @stereo_allowed: can this connector handle stereo modes? -* @registered: is this connector exposed (registered) with userspace? * @modes: modes available on this connector (from fill_modes() + user) * @status: one of the drm_connector_status enums (connected, not, or unknown) * @probed_modes: list of modes derived directly from the display
@@ -560,6 +563,13 @@ struct drm_connector {char *name;/** +* @mutex: Lock for general connector state, but currently only protects +* @registered. Most of the connector state is still protected by the +* mutex in &drm_mode_config. +*/ +struct mutex mutex; + +/** * @index: Compacted connector index, which matches the position inside * the mode_config.list for drivers not supporting hot-add/removing. Can * be used as an array index. It is invariant over the lifetime of the
@@ -572,6 +582,10 @@ struct drm_connector {bool interlace_allowed;bool doublescan_allowed;bool stereo_allowed; +/** +* @registered: Is this connector exposed (registered) with userspace? +* Protected by @mutex. +*/ bool registered;struct list_head modes;/* list of modes on this connector */
Patches currently in stable-queue which might be from [email protected] are
queue-4.9/drm-prevent-double-un-registration-for-connectors.patch