aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_connector.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2016-12-18 08:35:45 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-01-30 04:17:17 -0500
commit4e5b54f127426c82dc2816340c26d951a5bb3429 (patch)
treecc3a8f7e335cf12880bc8d1a1e2066f6cfe0a68e /drivers/gpu/drm/drm_connector.c
parent566cf877a1fcb6d6dc0126b076aad062054c2637 (diff)
drm: prevent double-(un)registration for connectors
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. Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: Chris Wilson <chris@chris-wilson.co.uk> Reviewed-by: Sean Paul <seanpaul@chromium.org> Reported-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20161218133545.2106-1-daniel.vetter@ffwll.ch (cherry picked from commit e73ab00e9a0f1731f34d0620a9c55f5c30c4ad4e)
Diffstat (limited to 'drivers/gpu/drm/drm_connector.c')
-rw-r--r--drivers/gpu/drm/drm_connector.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 5a4526289392..8be60a4576b3 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -225,6 +225,7 @@ int drm_connector_init(struct drm_device *dev,
225 225
226 INIT_LIST_HEAD(&connector->probed_modes); 226 INIT_LIST_HEAD(&connector->probed_modes);
227 INIT_LIST_HEAD(&connector->modes); 227 INIT_LIST_HEAD(&connector->modes);
228 mutex_init(&connector->mutex);
228 connector->edid_blob_ptr = NULL; 229 connector->edid_blob_ptr = NULL;
229 connector->status = connector_status_unknown; 230 connector->status = connector_status_unknown;
230 231
@@ -359,6 +360,8 @@ void drm_connector_cleanup(struct drm_connector *connector)
359 connector->funcs->atomic_destroy_state(connector, 360 connector->funcs->atomic_destroy_state(connector,
360 connector->state); 361 connector->state);
361 362
363 mutex_destroy(&connector->mutex);
364
362 memset(connector, 0, sizeof(*connector)); 365 memset(connector, 0, sizeof(*connector));
363} 366}
364EXPORT_SYMBOL(drm_connector_cleanup); 367EXPORT_SYMBOL(drm_connector_cleanup);
@@ -374,14 +377,15 @@ EXPORT_SYMBOL(drm_connector_cleanup);
374 */ 377 */
375int drm_connector_register(struct drm_connector *connector) 378int drm_connector_register(struct drm_connector *connector)
376{ 379{
377 int ret; 380 int ret = 0;
378 381
382 mutex_lock(&connector->mutex);
379 if (connector->registered) 383 if (connector->registered)
380 return 0; 384 goto unlock;
381 385
382 ret = drm_sysfs_connector_add(connector); 386 ret = drm_sysfs_connector_add(connector);
383 if (ret) 387 if (ret)
384 return ret; 388 goto unlock;
385 389
386 ret = drm_debugfs_connector_add(connector); 390 ret = drm_debugfs_connector_add(connector);
387 if (ret) { 391 if (ret) {
@@ -397,12 +401,14 @@ int drm_connector_register(struct drm_connector *connector)
397 drm_mode_object_register(connector->dev, &connector->base); 401 drm_mode_object_register(connector->dev, &connector->base);
398 402
399 connector->registered = true; 403 connector->registered = true;
400 return 0; 404 goto unlock;
401 405
402err_debugfs: 406err_debugfs:
403 drm_debugfs_connector_remove(connector); 407 drm_debugfs_connector_remove(connector);
404err_sysfs: 408err_sysfs:
405 drm_sysfs_connector_remove(connector); 409 drm_sysfs_connector_remove(connector);
410unlock:
411 mutex_unlock(&connector->mutex);
406 return ret; 412 return ret;
407} 413}
408EXPORT_SYMBOL(drm_connector_register); 414EXPORT_SYMBOL(drm_connector_register);
@@ -415,8 +421,11 @@ EXPORT_SYMBOL(drm_connector_register);
415 */ 421 */
416void drm_connector_unregister(struct drm_connector *connector) 422void drm_connector_unregister(struct drm_connector *connector)
417{ 423{
418 if (!connector->registered) 424 mutex_lock(&connector->mutex);
425 if (!connector->registered) {
426 mutex_unlock(&connector->mutex);
419 return; 427 return;
428 }
420 429
421 if (connector->funcs->early_unregister) 430 if (connector->funcs->early_unregister)
422 connector->funcs->early_unregister(connector); 431 connector->funcs->early_unregister(connector);
@@ -425,6 +434,7 @@ void drm_connector_unregister(struct drm_connector *connector)
425 drm_debugfs_connector_remove(connector); 434 drm_debugfs_connector_remove(connector);
426 435
427 connector->registered = false; 436 connector->registered = false;
437 mutex_unlock(&connector->mutex);
428} 438}
429EXPORT_SYMBOL(drm_connector_unregister); 439EXPORT_SYMBOL(drm_connector_unregister);
430 440