diff options
author | Hans de Goede <jwrdegoede@fedoraproject.org> | 2021-03-09 11:25:31 +0000 |
---|---|---|
committer | Hans de Goede <jwrdegoede@fedoraproject.org> | 2021-03-09 11:25:31 +0000 |
commit | 9773f3e5130812e289d09f35514876af12650155 (patch) | |
tree | fbaac0a7158cfa2585cbb0b76c97f006399b829e | |
parent | 8c249a46f2376a8b93aade0fc78803efa5094002 (diff) | |
parent | 42ee6809b0cb669c23cac8cb289b0d101a19fa47 (diff) |
Merge branch 'drm_probe_speedup' into 'master'
Speed up DRM-connector probing
See merge request plymouth/plymouth!133
-rw-r--r-- | src/libply-splash-core/ply-device-manager.c | 138 | ||||
-rw-r--r-- | src/plugins/splash/two-step/plugin.c | 2 |
2 files changed, 101 insertions, 39 deletions
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c index f65d7317..13c2b1b2 100644 --- a/src/libply-splash-core/ply-device-manager.c +++ b/src/libply-splash-core/ply-device-manager.c @@ -308,18 +308,6 @@ create_devices_for_udev_device (ply_device_manager_t *manager, return created; } -static void -free_devices_for_udev_device (ply_device_manager_t *manager, - struct udev_device *device) -{ - const char *device_path; - - device_path = udev_device_get_devnode (device); - - if (device_path != NULL) - free_devices_from_device_path (manager, device_path, true); -} - static bool create_devices_for_subsystem (ply_device_manager_t *manager, const char *subsystem) @@ -385,15 +373,12 @@ create_devices_for_subsystem (ply_device_manager_t *manager, static void on_drm_udev_add_or_change (ply_device_manager_t *manager, const char *action, + const char *device_path, 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, @@ -415,41 +400,120 @@ on_drm_udev_add_or_change (ply_device_manager_t *manager, } } +static bool +verify_add_or_change (ply_device_manager_t *manager, + const char *action, + const char *device_path, + struct udev_device *device) +{ + const char *subsystem = udev_device_get_subsystem (device); + + if (strcmp (action, "add") && strcmp (action, "change")) + return false; + + subsystem = udev_device_get_subsystem (device); + + if (strcmp (subsystem, SUBSYSTEM_DRM) == 0) { + if (manager->local_console_managed && manager->local_console_is_text) { + ply_trace ("ignoring since we're already using text splash for local console"); + return false; + } + } else { + ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem); + return false; + } + + return true; +} + +static bool +duplicate_device_path (ply_list_t *events, const char *device_path) +{ + struct udev_device *device; + ply_list_node_t *node; + + for (node = ply_list_get_first_node (events); + node; node = ply_list_get_next_node (events, node)) { + device = ply_list_node_get_data (node); + + if (strcmp (udev_device_get_devnode (device), device_path) == 0) + return true; + } + + return false; +} + +static void +process_udev_add_or_change_events (ply_device_manager_t *manager, ply_list_t *events) +{ + const char *action, *device_path; + struct udev_device *device; + ply_list_node_t *node; + + while ((node = ply_list_get_first_node (events))) { + device = ply_list_node_get_data (node); + action = udev_device_get_action (device); + device_path = udev_device_get_devnode (device); + + on_drm_udev_add_or_change (manager, action, device_path, device); + + ply_list_remove_node (events, node); + udev_device_unref (device); + } +} + static void on_udev_event (ply_device_manager_t *manager) { + const char *action, *device_path; struct udev_device *device; - const char *action; + ply_list_t *pending_events; - device = udev_monitor_receive_device (manager->udev_monitor); - if (device == NULL) - return; + pending_events = ply_list_new (); - action = udev_device_get_action (device); + /* + * During the initial monitor/connector enumeration on boot the kernel + * fires a large number of change events. If we process these 1 by 1, + * we spend a lot of time probing the drm-connectors. So instead we + * collect them all and then coalescence them so that if there are multiple + * change events pending for a single card, we only re-probe the card once. + */ + while ((device = udev_monitor_receive_device (manager->udev_monitor))) { + action = udev_device_get_action (device); + device_path = udev_device_get_devnode (device); - ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device)); + if (action == NULL || device_path == NULL) + goto unref; - if (action == NULL) - return; + ply_trace ("got %s event for device %s", action, device_path); - if (strcmp (action, "add") == 0 || strcmp (action, "change") == 0) { - const char *subsystem; + /* + * Add/change events before and after a remove may not be + * coalesced together. So flush the queue and then process + * the remove event immediately. + */ + if (strcmp (action, "remove") == 0) { + process_udev_add_or_change_events (manager, pending_events); + free_devices_from_device_path (manager, device_path, true); + goto unref; + } - subsystem = udev_device_get_subsystem (device); + if (!verify_add_or_change (manager, action, device_path, device)) + goto unref; - if (strcmp (subsystem, SUBSYSTEM_DRM) == 0) { - if (manager->local_console_managed && manager->local_console_is_text) - ply_trace ("ignoring since we're already using text splash for local console"); - else - on_drm_udev_add_or_change (manager, action, device); - } else { - ply_trace ("ignoring since we only handle subsystem %s devices after timeout", subsystem); + if (duplicate_device_path (pending_events, device_path)) { + ply_trace ("ignoring duplicate %s event for device %s", action, device_path); + goto unref; } - } else if (strcmp (action, "remove") == 0) { - free_devices_for_udev_device (manager, device); + + ply_list_append_data (pending_events, udev_device_ref(device)); +unref: + udev_device_unref (device); } - udev_device_unref (device); + process_udev_add_or_change_events (manager, pending_events); + + ply_list_free (pending_events); } static void diff --git a/src/plugins/splash/two-step/plugin.c b/src/plugins/splash/two-step/plugin.c index ed83d8bc..9c8bc439 100644 --- a/src/plugins/splash/two-step/plugin.c +++ b/src/plugins/splash/two-step/plugin.c @@ -1642,8 +1642,6 @@ show_splash_screen (ply_boot_splash_plugin_t *plugin, ply_buffer_t *boot_buffer, ply_boot_splash_mode_t mode) { - int i; - assert (plugin != NULL); plugin->loop = loop; |