From 40daac6136948dc83c1dec14fe4a2444915b22df Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 15 Jun 2016 13:17:48 +0100 Subject: [PATCH] drm: Make drm_connector_register() safe against multiple calls Protect against drivers that may try to register the connector more than once, or who try to unregister it multiple times. Signed-off-by: Chris Wilson Cc: Dave Airlie Cc: dri-devel@lists.freedesktop.org Reviewed-by: Daniel Vetter Signed-off-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/1465993109-19523-4-git-send-email-chris@chris-wilson.co.uk --- drivers/gpu/drm/drm_crtc.c | 9 +++++++++ include/drm/drm_crtc.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 23dfec41decb..ea5ec641eacc 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -984,6 +984,9 @@ int drm_connector_register(struct drm_connector *connector) { int ret; + if (connector->registered) + return 0; + ret = drm_sysfs_connector_add(connector); if (ret) return ret; @@ -1001,6 +1004,7 @@ int drm_connector_register(struct drm_connector *connector) drm_mode_object_register(connector->dev, &connector->base); + connector->registered = true; return 0; err_debugfs: @@ -1019,11 +1023,16 @@ EXPORT_SYMBOL(drm_connector_register); */ void drm_connector_unregister(struct drm_connector *connector) { + if (!connector->registered) + return; + if (connector->funcs->early_unregister) connector->funcs->early_unregister(connector); drm_sysfs_connector_remove(connector); drm_debugfs_connector_remove(connector); + + connector->registered = false; } EXPORT_SYMBOL(drm_connector_unregister); diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 4cc170cfc8fd..c2734979f164 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -1193,6 +1193,7 @@ struct drm_encoder { * @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 @@ -1249,6 +1250,7 @@ struct drm_connector { bool interlace_allowed; bool doublescan_allowed; bool stereo_allowed; + bool registered; struct list_head modes; /* list of modes on this connector */ enum drm_connector_status status; -- 2.30.2