ply-device-manager: Handle change events for monitor hotplugging

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>
This commit is contained in:
Hans de Goede 2019-01-14 11:47:21 +01:00
parent f9e376797a
commit e54f6a4731

View 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);
}