]> git.ipfire.org Git - thirdparty/plymouth.git/commitdiff
ply-device-manager: Handle change events for monitor hotplugging
authorHans de Goede <hdegoede@redhat.com>
Mon, 14 Jan 2019 10:47:21 +0000 (11:47 +0100)
committerHans de Goede <hdegoede@redhat.com>
Mon, 21 Jan 2019 14:45:00 +0000 (15:45 +0100)
Not only handle add but also change events for drm-subsys devices,
change events are generated when the hardware detect a new monitor
has been plugged in.

This is esp. important with modern DisplayPort MST docking stations where
discovery / enumeration can take so long that the connected displays
are not enumerated by the kernel yet when the drm plugin first calls
drmModeGetResources(). Causing the monitors on these docks to sometimes
not show plymouth during boot (based on various timing parameters).

Note that if during the add event drm-renderer could not be bound, this
commit tries to re-bind the DRM renderer on change events in case a
monitor got plugged into a GPU which did not have anything connected before.
This often happens with the second GPU in a laptop with a hybrid GPU setup.

BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1652279
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
src/libply-splash-core/ply-device-manager.c

index 028bf4add6f30b473f0f68ae9df165bb58641ca5..e2a9eaee8d0ae5ba2151609014317a0c91572d75 100644 (file)
@@ -51,6 +51,9 @@ static bool create_devices_for_terminal_and_renderer_type (ply_device_manager_t
                                                            const char           *device_path,
                                                            ply_terminal_t       *terminal,
                                                            ply_renderer_type_t   renderer_type);
+static void create_pixel_displays_for_renderer (ply_device_manager_t *manager,
+                                                ply_renderer_t       *renderer);
+
 struct _ply_device_manager
 {
         ply_device_manager_flags_t flags;
@@ -371,6 +374,39 @@ create_devices_for_subsystem (ply_device_manager_t *manager,
         return found_device;
 }
 
+static void
+on_drm_udev_add_or_change (ply_device_manager_t *manager,
+                           const char           *action,
+                           struct udev_device   *device)
+{
+        const char *device_path = udev_device_get_devnode (device);
+        ply_renderer_t *renderer;
+        bool changed;
+
+        if (device_path == NULL)
+                return;
+
+        renderer = ply_hashtable_lookup (manager->renderers, (void *) device_path);
+        if (renderer == NULL) {
+                /* We also try to create the renderer again on change events,
+                 * renderer creation fails when no outputs are connected and
+                 * this may have changed.
+                 */
+                create_devices_for_udev_device (manager, device);
+                return;
+        }
+
+        /* Renderer exists, bail if this is not a change event */
+        if (strcmp (action, "change"))
+                return;
+
+        changed = ply_renderer_handle_change_event (renderer);
+        if (changed) {
+                free_displays_for_renderer (manager, renderer);
+                create_pixel_displays_for_renderer (manager, renderer);
+        }
+}
+
 static bool
 on_udev_event (ply_device_manager_t *manager)
 {
@@ -388,7 +424,7 @@ on_udev_event (ply_device_manager_t *manager)
         if (action == NULL)
                 return false;
 
-        if (strcmp (action, "add") == 0) {
+        if (strcmp (action, "add") == 0 || strcmp (action, "change") == 0) {
                 const char *subsystem;
 
                 subsystem = udev_device_get_subsystem (device);
@@ -397,7 +433,7 @@ on_udev_event (ply_device_manager_t *manager)
                         if (manager->local_console_managed && manager->local_console_is_text)
                                 ply_trace ("ignoring since we're already using text splash for local console");
                         else
-                                create_devices_for_udev_device (manager, device);
+                                on_drm_udev_add_or_change (manager, action, device);
                 } else {
                         ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem);
                 }