drm/sysfs: Register "ddc" symlink later
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Tue, 29 Aug 2023 11:39:10 +0000 (14:39 +0300)
committerVille Syrjälä <ville.syrjala@linux.intel.com>
Fri, 15 Sep 2023 11:46:42 +0000 (14:46 +0300)
Currently drm_sysfs_connector_add() attempts to register
the "ddc" symlink (based one connector->ddc) before the
driver's .early_register() hook has been called. That is
too early for i915 which only fully registers the aux ch
and associated i2c bus from said hook (to prevent half
initialized stuff getting exposed to userspace). This
causes my attempt at using drm_connector_init_with_ddc()
to fail, and the entire connector disappears from sysfs
on account of sysfs_create_link() failing.

To fix that split the sysfs symlink stuff into separate
functions (drm_sysfs_connector_add_late() and
drm_sysfs_connector_remove_early()) which are called
on the opposite side of the .later_register() and
.early_unregister() hooks.

Cc: Andrzej Pietrasiewicz <andrzej.p@collabora.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Andrzej Hajda <a.hajda@samsung.com>
Cc: Emil Velikov <emil.velikov@collabora.com>
Cc: Sam Ravnborg <sam@ravnborg.org>
Cc: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230829113920.13713-3-ville.syrjala@linux.intel.com
Reviewed-by: Jani Nikula <jani.nikula@intel.com>
Acked-by: Thomas Zimmermann <tzimmermann@suse.de> #irc
drivers/gpu/drm/drm_connector.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_sysfs.c

index 20e94b4ce60e0c92c0da23b396e1658375239d3b..f239de0085c36aa341125f27dd3bcfc4a8151850 100644 (file)
@@ -631,6 +631,10 @@ int drm_connector_register(struct drm_connector *connector)
                        goto err_debugfs;
        }
 
+       ret = drm_sysfs_connector_add_late(connector);
+       if (ret)
+               goto err_late_register;
+
        drm_mode_object_register(connector->dev, &connector->base);
 
        connector->registration_state = DRM_CONNECTOR_REGISTERED;
@@ -647,6 +651,9 @@ int drm_connector_register(struct drm_connector *connector)
        mutex_unlock(&connector_list_lock);
        goto unlock;
 
+err_late_register:
+       if (connector->funcs->early_unregister)
+               connector->funcs->early_unregister(connector);
 err_debugfs:
        drm_debugfs_connector_remove(connector);
        drm_sysfs_connector_remove(connector);
@@ -681,6 +688,8 @@ void drm_connector_unregister(struct drm_connector *connector)
                                        connector->privacy_screen,
                                        &connector->privacy_screen_notifier);
 
+       drm_sysfs_connector_remove_early(connector);
+
        if (connector->funcs->early_unregister)
                connector->funcs->early_unregister(connector);
 
index ba12acd551390b8e96151139f786487d95e02a95..4053cf8105ce4c823baaa8fa5c4dc3663ae20abb 100644 (file)
@@ -153,6 +153,8 @@ int drm_sysfs_init(void);
 void drm_sysfs_destroy(void);
 struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
 int drm_sysfs_connector_add(struct drm_connector *connector);
+int drm_sysfs_connector_add_late(struct drm_connector *connector);
+void drm_sysfs_connector_remove_early(struct drm_connector *connector);
 void drm_sysfs_connector_remove(struct drm_connector *connector);
 
 void drm_sysfs_lease_event(struct drm_device *dev);
index b169b3e44a921b9c9e988c3cb6d34c1a378346cf..a953f69a34b6e98cb8cd2e94b124e78adf9f52ce 100644 (file)
@@ -400,10 +400,6 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
                        drm_err(dev, "failed to add component to create link to typec connector\n");
        }
 
-       if (connector->ddc)
-               return sysfs_create_link(&connector->kdev->kobj,
-                                &connector->ddc->dev.kobj, "ddc");
-
        return 0;
 
 err_free:
@@ -411,13 +407,25 @@ err_free:
        return r;
 }
 
-void drm_sysfs_connector_remove(struct drm_connector *connector)
+int drm_sysfs_connector_add_late(struct drm_connector *connector)
 {
-       if (!connector->kdev)
-               return;
+       if (connector->ddc)
+               return sysfs_create_link(&connector->kdev->kobj,
+                                        &connector->ddc->dev.kobj, "ddc");
+
+       return 0;
+}
 
+void drm_sysfs_connector_remove_early(struct drm_connector *connector)
+{
        if (connector->ddc)
                sysfs_remove_link(&connector->kdev->kobj, "ddc");
+}
+
+void drm_sysfs_connector_remove(struct drm_connector *connector)
+{
+       if (!connector->kdev)
+               return;
 
        if (dev_fwnode(connector->kdev))
                component_del(connector->kdev, &typec_connector_ops);