01552a
From 10e686c2128bde0e70e7c137191dbe004d2f46fd Mon Sep 17 00:00:00 2001
01552a
From: Ray Strode <rstrode@redhat.com>
01552a
Date: Mon, 3 Mar 2014 13:27:30 -0500
01552a
Subject: [PATCH 1/2] device-manager: handle drm hotplug separately from
01552a
 /dev/fb
01552a
01552a
Right now, we piggyback off fb subsystem events to know whether or
01552a
not a drm device is hotplugged (since all drm devices have fb devices
01552a
for backward compat).
01552a
01552a
This commit makes drm and fb processing more independent, so we don't
01552a
rely on the compat device being available for drm hotplug to work..
01552a
---
01552a
 src/libply-splash-core/ply-device-manager.c | 182 ++++++++++++++--------------
01552a
 1 file changed, 89 insertions(+), 93 deletions(-)
01552a
01552a
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
01552a
index 36e814d..25f7d54 100644
01552a
--- a/src/libply-splash-core/ply-device-manager.c
01552a
+++ b/src/libply-splash-core/ply-device-manager.c
01552a
@@ -11,60 +11,63 @@
01552a
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
01552a
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
01552a
  * GNU General Public License for more details.
01552a
  *
01552a
  * You should have received a copy of the GNU General Public License
01552a
  * along with this program; if not, write to the Free Software
01552a
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
01552a
  * 02111-1307, USA.
01552a
  */
01552a
 #include "config.h"
01552a
 #include "ply-device-manager.h"
01552a
 
01552a
 #include <assert.h>
01552a
 #include <fcntl.h>
01552a
 #include <stdbool.h>
01552a
 #include <stdlib.h>
01552a
 #include <stdio.h>
01552a
 #include <string.h>
01552a
 #include <sys/inotify.h>
01552a
 #include <sys/stat.h>
01552a
 #include <sys/types.h>
01552a
 
01552a
 #include <libudev.h>
01552a
 
01552a
 #include "ply-logger.h"
01552a
 #include "ply-event-loop.h"
01552a
 #include "ply-hashtable.h"
01552a
 #include "ply-list.h"
01552a
 #include "ply-utils.h"
01552a
 
01552a
+#define SUBSYSTEM_DRM "drm"
01552a
+#define SUBSYSTEM_FRAME_BUFFER "graphics"
01552a
+
01552a
 static void create_seat_for_terminal_and_renderer_type (ply_device_manager_t *manager,
01552a
                                                         const char           *device_path,
01552a
                                                         ply_terminal_t       *terminal,
01552a
                                                         ply_renderer_type_t   renderer_type);
01552a
 struct _ply_device_manager
01552a
 {
01552a
   ply_device_manager_flags_t  flags;
01552a
   ply_event_loop_t           *loop;
01552a
   ply_hashtable_t            *terminals;
01552a
   ply_terminal_t             *local_console_terminal;
01552a
   ply_seat_t                 *local_console_seat;
01552a
   ply_list_t                 *seats;
01552a
   struct udev                *udev_context;
01552a
   struct udev_queue          *udev_queue;
01552a
   int                         udev_queue_fd;
01552a
   ply_fd_watch_t             *udev_queue_fd_watch;
01552a
   struct udev_monitor        *udev_monitor;
01552a
 
01552a
   ply_seat_added_handler_t    seat_added_handler;
01552a
   ply_seat_removed_handler_t  seat_removed_handler;
01552a
   void                       *seat_event_handler_data;
01552a
 };
01552a
 
01552a
 static void
01552a
 detach_from_event_loop (ply_device_manager_t *manager)
01552a
 {
01552a
   assert (manager != NULL);
01552a
 
01552a
   manager->loop = NULL;
01552a
 }
01552a
@@ -84,342 +87,334 @@ attach_to_event_loop (ply_device_manager_t *manager,
01552a
                                  manager);
01552a
 }
01552a
 
01552a
 static bool
01552a
 device_is_for_local_console (ply_device_manager_t *manager,
01552a
                              struct udev_device   *device)
01552a
 {
01552a
   const char *device_path;
01552a
   struct udev_device *bus_device;
01552a
   char *bus_device_path;
01552a
   const char *boot_vga;
01552a
   bool for_local_console;
01552a
 
01552a
   /* Look at the associated bus device to see if this card is the
01552a
    * card the kernel is using for its console. */
01552a
   device_path = udev_device_get_syspath (device);
01552a
   asprintf (&bus_device_path, "%s/device", device_path);
01552a
   bus_device = udev_device_new_from_syspath (manager->udev_context, bus_device_path);
01552a
 
01552a
   boot_vga = udev_device_get_sysattr_value (bus_device, "boot_vga");
01552a
   free (bus_device_path);
01552a
 
01552a
   if (boot_vga != NULL && strcmp (boot_vga, "1") == 0)
01552a
     for_local_console = true;
01552a
   else
01552a
     for_local_console = false;
01552a
 
01552a
   return for_local_console;
01552a
 }
01552a
 
01552a
-static char *
01552a
-get_drm_device_node_path_from_fb_device (ply_device_manager_t *manager,
01552a
-                                         struct udev_device   *fb_device)
01552a
+static bool
01552a
+fb_device_has_drm_device (ply_device_manager_t *manager,
01552a
+                          struct udev_device   *fb_device)
01552a
 {
01552a
   struct udev_enumerate *card_matches;
01552a
   struct udev_list_entry *card_entry;
01552a
   const char *id_path;
01552a
-  char *device_node_path = NULL;
01552a
+  bool has_drm_device = false;
01552a
 
01552a
   /* We want to see if the framebuffer is associated with a DRM-capable
01552a
    * graphics card, if it is, we'll use the DRM device */
01552a
   card_matches = udev_enumerate_new (manager->udev_context);
01552a
   udev_enumerate_add_match_is_initialized(card_matches);
01552a
   udev_enumerate_add_match_parent (card_matches, udev_device_get_parent (fb_device));
01552a
   udev_enumerate_add_match_subsystem (card_matches, "drm");
01552a
   id_path = udev_device_get_property_value (fb_device, "ID_PATH");
01552a
   udev_enumerate_add_match_property (card_matches, "ID_PATH", id_path);
01552a
 
01552a
   ply_trace ("trying to find associated drm node for fb device (path: %s)", id_path);
01552a
 
01552a
   udev_enumerate_scan_devices (card_matches);
01552a
 
01552a
   /* there should only ever be at most one match so we don't iterate through
01552a
    * the list, but just look at the first entry */
01552a
   card_entry = udev_enumerate_get_list_entry (card_matches);
01552a
 
01552a
   if (card_entry != NULL)
01552a
     {
01552a
       struct udev_device *card_device = NULL;
01552a
       const char *card_node;
01552a
       const char *card_path;
01552a
 
01552a
       card_path = udev_list_entry_get_name (card_entry);
01552a
       card_device = udev_device_new_from_syspath (manager->udev_context, card_path);
01552a
       card_node = udev_device_get_devnode (card_device);
01552a
       if (card_node != NULL)
01552a
-        device_node_path = strdup (card_node);
01552a
+        has_drm_device = true;
01552a
       else
01552a
         ply_trace ("no card node!");
01552a
 
01552a
       udev_device_unref (card_device);
01552a
     }
01552a
   else
01552a
     {
01552a
       ply_trace ("no card entry!");
01552a
     }
01552a
 
01552a
   udev_enumerate_unref (card_matches);
01552a
-  return device_node_path;
01552a
+  return has_drm_device;
01552a
 }
01552a
 
01552a
 static void
01552a
 create_seat_for_udev_device (ply_device_manager_t *manager,
01552a
                              struct udev_device   *device)
01552a
 {
01552a
   bool for_local_console;
01552a
-  char *card_path;
01552a
+  const char *device_path;
01552a
   ply_terminal_t *terminal = NULL;
01552a
 
01552a
   for_local_console = device_is_for_local_console (manager, device);
01552a
 
01552a
   ply_trace ("device is for local console: %s", for_local_console? "yes" : "no");
01552a
 
01552a
   if (for_local_console)
01552a
     terminal = manager->local_console_terminal;
01552a
 
01552a
-  card_path = get_drm_device_node_path_from_fb_device (manager, device);
01552a
+  device_path = udev_device_get_devnode (device);
01552a
 
01552a
-  if (card_path != NULL)
01552a
-    {
01552a
-      create_seat_for_terminal_and_renderer_type (manager,
01552a
-                                                  card_path,
01552a
-                                                  terminal,
01552a
-                                                  PLY_RENDERER_TYPE_DRM);
01552a
-      free (card_path);
01552a
-    }
01552a
-  else
01552a
+  if (device_path != NULL)
01552a
     {
01552a
-      const char *fb_device_node_path;
01552a
+      const char *subsystem;
01552a
+      ply_renderer_type_t renderer_type = PLY_RENDERER_TYPE_NONE;
01552a
+
01552a
+      subsystem = udev_device_get_subsystem (device);
01552a
+
01552a
+      if (strcmp (subsystem, SUBSYSTEM_DRM) == 0)
01552a
+        {
01552a
+          ply_trace ("found DRM device %s", device_path);
01552a
+          renderer_type = PLY_RENDERER_TYPE_DRM;
01552a
+        }
01552a
+      else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0)
01552a
+        {
01552a
+          ply_trace ("found frame buffer device %s", device_path);
01552a
+          if (!fb_device_has_drm_device (manager, device))
01552a
+            {
01552a
+              renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER;
01552a
+            }
01552a
+          else
01552a
+            {
01552a
+              ply_trace ("ignoring, since there's a DRM device associated with it");
01552a
+            }
01552a
+        }
01552a
 
01552a
-      fb_device_node_path = udev_device_get_devnode (device);
01552a
-      if (fb_device_node_path != NULL)
01552a
+      if (renderer_type != PLY_RENDERER_TYPE_NONE)
01552a
         create_seat_for_terminal_and_renderer_type (manager,
01552a
-                                                    fb_device_node_path,
01552a
+                                                    device_path,
01552a
                                                     terminal,
01552a
-                                                    PLY_RENDERER_TYPE_FRAME_BUFFER);
01552a
+                                                    renderer_type);
01552a
     }
01552a
 }
01552a
 
01552a
 static void
01552a
 free_seat_from_device_path (ply_device_manager_t *manager,
01552a
                             const char           *device_path)
01552a
 {
01552a
   ply_list_node_t *node;
01552a
 
01552a
   node = ply_list_get_first_node (manager->seats);
01552a
   while (node != NULL)
01552a
     {
01552a
       ply_seat_t *seat;
01552a
       ply_renderer_t *renderer;
01552a
       ply_list_node_t *next_node;
01552a
       const char *renderer_device_path;
01552a
 
01552a
       seat = ply_list_node_get_data (node);
01552a
       next_node = ply_list_get_next_node (manager->seats, node);
01552a
       renderer = ply_seat_get_renderer (seat);
01552a
 
01552a
       if (renderer != NULL)
01552a
         {
01552a
           renderer_device_path = ply_renderer_get_device_name (renderer);
01552a
 
01552a
           if (renderer_device_path != NULL)
01552a
             {
01552a
               if (strcmp (device_path, renderer_device_path) == 0)
01552a
                 {
01552a
                   ply_trace ("removing seat associated with %s", device_path);
01552a
 
01552a
                   if (manager->seat_removed_handler != NULL)
01552a
                     manager->seat_removed_handler (manager->seat_event_handler_data, seat);
01552a
 
01552a
                   ply_seat_free (seat);
01552a
                   ply_list_remove_node (manager->seats, node);
01552a
                   break;
01552a
                 }
01552a
             }
01552a
         }
01552a
 
01552a
       node = next_node;
01552a
     }
01552a
 }
01552a
 
01552a
 static void
01552a
 free_seat_for_udev_device (ply_device_manager_t *manager,
01552a
                            struct udev_device   *device)
01552a
 {
01552a
-  char *card_path;
01552a
-
01552a
- card_path = get_drm_device_node_path_from_fb_device (manager, device);
01552a
-
01552a
-  if (card_path != NULL)
01552a
-    {
01552a
-      free_seat_from_device_path (manager, card_path);
01552a
-      free (card_path);
01552a
-    }
01552a
-  else
01552a
-    {
01552a
-      const char *fb_device_node_path;
01552a
+  const char *device_path;
01552a
 
01552a
-      fb_device_node_path = udev_device_get_devnode (device);
01552a
+  device_path = udev_device_get_devnode (device);
01552a
 
01552a
-      if (fb_device_node_path != NULL)
01552a
-        free_seat_from_device_path (manager, fb_device_node_path);
01552a
-    }
01552a
+  if (device_path != NULL)
01552a
+    free_seat_from_device_path (manager, device_path);
01552a
 }
01552a
 
01552a
 static bool
01552a
-scan_graphics_devices (ply_device_manager_t *manager)
01552a
+create_seats_for_subsystem (ply_device_manager_t *manager,
01552a
+                            const char           *subsystem)
01552a
 {
01552a
-  struct udev_enumerate *fb_matches;
01552a
-  struct udev_list_entry *fb_entry;
01552a
+  struct udev_enumerate *matches;
01552a
+  struct udev_list_entry *entry;
01552a
   bool found_device = false;
01552a
 
01552a
-  ply_trace ("scanning for graphics devices");
01552a
-  /* graphics subsystem is for /dev/fb devices.  kms drivers provide /dev/fb for backward
01552a
-   * compatibility, and do so at the end of their initialization, so we can be confident
01552a
-   * that when this subsystem is available the drm device is fully initialized */
01552a
-  fb_matches = udev_enumerate_new (manager->udev_context);
01552a
-  udev_enumerate_add_match_subsystem (fb_matches, "graphics");
01552a
-  udev_enumerate_scan_devices (fb_matches);
01552a
+  ply_trace ("creating seats for %s devices",
01552a
+             strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0?
01552a
+             "frame buffer":
01552a
+             subsystem);
01552a
 
01552a
-  udev_list_entry_foreach (fb_entry, udev_enumerate_get_list_entry (fb_matches))
01552a
+  matches = udev_enumerate_new (manager->udev_context);
01552a
+  udev_enumerate_add_match_subsystem (matches, subsystem);
01552a
+  udev_enumerate_scan_devices (matches);
01552a
+
01552a
+  udev_list_entry_foreach (entry, udev_enumerate_get_list_entry (matches))
01552a
     {
01552a
-      struct udev_device *fb_device = NULL;
01552a
-      const char *fb_path;
01552a
+      struct udev_device *device = NULL;
01552a
+      const char *path;
01552a
 
01552a
-      fb_path = udev_list_entry_get_name (fb_entry);
01552a
+      path = udev_list_entry_get_name (entry);
01552a
 
01552a
-      if (fb_path == NULL)
01552a
+      if (path == NULL)
01552a
         {
01552a
-          ply_trace ("fb path was null!");
01552a
+          ply_trace ("path was null!");
01552a
           continue;
01552a
         }
01552a
 
01552a
-      ply_trace ("found device %s", fb_path);
01552a
+      ply_trace ("found device %s", path);
01552a
 
01552a
-      /* skip virtual fbcon device
01552a
-       */
01552a
-      if (strcmp (fb_path, "/sys/devices/virtual/graphics/fbcon") == 0)
01552a
-        {
01552a
-          ply_trace ("ignoring since it's fbcon");
01552a
-          continue;
01552a
-        }
01552a
-
01552a
-      fb_device = udev_device_new_from_syspath (manager->udev_context, fb_path);
01552a
+      device = udev_device_new_from_syspath (manager->udev_context, path);
01552a
 
01552a
       /* if device isn't fully initialized, we'll get an add event later
01552a
        */
01552a
-      if (udev_device_get_is_initialized (fb_device))
01552a
+      if (udev_device_get_is_initialized (device))
01552a
         {
01552a
           ply_trace ("device is initialized");
01552a
+
01552a
           /* We only care about devices assigned to a (any) seat. Floating
01552a
-           * devices should be ignored.  As a side-effect, this conveniently
01552a
-           * filters out the fbcon device which we don't care about.
01552a
+           * devices should be ignored.
01552a
            */
01552a
-          if (udev_device_has_tag (fb_device, "seat"))
01552a
+          if (udev_device_has_tag (device, "seat"))
01552a
             {
01552a
-              const char *fb_node;
01552a
-              fb_node = udev_device_get_devnode (fb_device);
01552a
-              if (fb_node != NULL)
01552a
+              const char *node;
01552a
+              node = udev_device_get_devnode (device);
01552a
+              if (node != NULL)
01552a
                 {
01552a
-                  ply_trace ("found node %s", fb_node);
01552a
+                  ply_trace ("found node %s", node);
01552a
                   found_device = true;
01552a
-                  create_seat_for_udev_device (manager, fb_device);
01552a
+                  create_seat_for_udev_device (manager, device);
01552a
                 }
01552a
             }
01552a
           else
01552a
             {
01552a
               ply_trace ("device doesn't have a seat tag");
01552a
             }
01552a
         }
01552a
       else
01552a
         {
01552a
           ply_trace ("it's not initialized");
01552a
         }
01552a
 
01552a
-      udev_device_unref (fb_device);
01552a
+      udev_device_unref (device);
01552a
     }
01552a
 
01552a
-  udev_enumerate_unref (fb_matches);
01552a
+  udev_enumerate_unref (matches);
01552a
 
01552a
   return found_device;
01552a
 }
01552a
 
01552a
 static void
01552a
-on_udev_graphics_event (ply_device_manager_t *manager)
01552a
+on_udev_event (ply_device_manager_t *manager)
01552a
 {
01552a
   struct udev_device *device;
01552a
   const char *action;
01552a
 
01552a
   device = udev_monitor_receive_device (manager->udev_monitor);
01552a
   if (device == NULL)
01552a
     return;
01552a
 
01552a
   action = udev_device_get_action (device);
01552a
 
01552a
   ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device));
01552a
 
01552a
   if (action == NULL)
01552a
     return;
01552a
 
01552a
   if (strcmp (action, "add") == 0)
01552a
     create_seat_for_udev_device (manager, device);
01552a
   else if (strcmp (action, "remove") == 0)
01552a
     free_seat_for_udev_device (manager, device);
01552a
 
01552a
   udev_device_unref (device);
01552a
 }
01552a
 
01552a
 static void
01552a
 watch_for_udev_events (ply_device_manager_t *manager)
01552a
 {
01552a
   int fd;
01552a
   assert (manager != NULL);
01552a
   assert (manager->udev_monitor == NULL);
01552a
 
01552a
   ply_trace ("watching for udev graphics device add and remove events");
01552a
 
01552a
   manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
01552a
 
01552a
-  /* The filter matching here mimics the matching done in scan_graphics_devices.
01552a
-   * See the comments in that function, for an explanation of what we're doing.
01552a
-   */
01552a
-  udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, "graphics", NULL);
01552a
+  udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
01552a
+  udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
01552a
   udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
01552a
   udev_monitor_enable_receiving (manager->udev_monitor);
01552a
 
01552a
   fd = udev_monitor_get_fd (manager->udev_monitor);
01552a
   ply_event_loop_watch_fd (manager->loop,
01552a
                            fd,
01552a
                            PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
01552a
                            (ply_event_handler_t)
01552a
-                           on_udev_graphics_event,
01552a
+                           on_udev_event,
01552a
                            NULL,
01552a
                            manager);
01552a
 }
01552a
 
01552a
 static void
01552a
 free_seats (ply_device_manager_t *manager)
01552a
 {
01552a
   ply_list_node_t *node;
01552a
 
01552a
   ply_trace ("removing seats");
01552a
   node = ply_list_get_first_node (manager->seats);
01552a
   while (node != NULL)
01552a
     {
01552a
       ply_seat_t *seat;
01552a
       ply_list_node_t *next_node;
01552a
 
01552a
       seat = ply_list_node_get_data (node);
01552a
       next_node = ply_list_get_next_node (manager->seats, node);
01552a
 
01552a
       if (manager->seat_removed_handler != NULL)
01552a
         manager->seat_removed_handler (manager->seat_event_handler_data, seat);
01552a
 
01552a
       ply_seat_free (seat);
01552a
       ply_list_remove_node (manager->seats, node);
01552a
 
01552a
       node = next_node;
01552a
     }
01552a
 }
01552a
 
01552a
 static void
01552a
@@ -657,77 +652,78 @@ create_seats_from_terminals (ply_device_manager_t *manager)
01552a
   int num_consoles;
01552a
 
01552a
   ply_trace ("checking for consoles");
01552a
 
01552a
   if (manager->flags & PLY_DEVICE_MANAGER_FLAGS_IGNORE_SERIAL_CONSOLES)
01552a
     {
01552a
       num_consoles = 0;
01552a
       ply_trace ("ignoring all consoles but default console because explicitly told to.");
01552a
     }
01552a
   else
01552a
     {
01552a
       num_consoles = add_consoles_from_file (manager, "/sys/class/tty/console/active");
01552a
 
01552a
       if (num_consoles == 0)
01552a
         ply_trace ("ignoring all consoles but default console because /sys/class/tty/console/active could not be read");
01552a
     }
01552a
 
01552a
   if (num_consoles > 1)
01552a
     {
01552a
       ply_trace ("serial consoles detected, managing them with details forced");
01552a
       ply_hashtable_foreach (manager->terminals,
01552a
                              (ply_hashtable_foreach_func_t *)
01552a
                              create_seat_for_terminal,
01552a
                              manager);
01552a
       return true;
01552a
     }
01552a
 
01552a
   return false;
01552a
 }
01552a
 
01552a
-static bool
01552a
+static void
01552a
 create_seats_from_udev (ply_device_manager_t *manager)
01552a
 {
01552a
-  bool found_device;
01552a
+  bool found_drm_device, found_fb_device;
01552a
 
01552a
   ply_trace ("Looking for devices from udev");
01552a
-  found_device = scan_graphics_devices (manager);
01552a
-  if (!found_device)
01552a
-    {
01552a
-      ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware");
01552a
-      create_seat_for_terminal_and_renderer_type (manager,
01552a
-                                                  ply_terminal_get_name (manager->local_console_terminal),
01552a
-                                                  manager->local_console_terminal,
01552a
-                                                  PLY_RENDERER_TYPE_NONE);
01552a
-    }
01552a
 
01552a
-  return true;
01552a
+  found_drm_device = create_seats_for_subsystem (manager, SUBSYSTEM_DRM);
01552a
+  found_fb_device = create_seats_for_subsystem (manager, SUBSYSTEM_FRAME_BUFFER);
01552a
+
01552a
+  if (found_drm_device || found_fb_device)
01552a
+    return;
01552a
+
01552a
+  ply_trace ("Creating non-graphical seat, since there's no suitable graphics hardware");
01552a
+  create_seat_for_terminal_and_renderer_type (manager,
01552a
+                                              ply_terminal_get_name (manager->local_console_terminal),
01552a
+                                              manager->local_console_terminal,
01552a
+                                              PLY_RENDERER_TYPE_NONE);
01552a
 }
01552a
 
01552a
 static void
01552a
 create_fallback_seat (ply_device_manager_t *manager)
01552a
 {
01552a
   create_seat_for_terminal_and_renderer_type (manager,
01552a
                                               ply_terminal_get_name (manager->local_console_terminal),
01552a
                                               manager->local_console_terminal,
01552a
                                               PLY_RENDERER_TYPE_AUTO);
01552a
 }
01552a
 
01552a
 static void
01552a
 on_udev_queue_changed (ply_device_manager_t *manager)
01552a
 {
01552a
 
01552a
   if (!udev_queue_get_queue_is_empty (manager->udev_queue))
01552a
     return;
01552a
 
01552a
   ply_trace ("udev coldplug complete");
01552a
   ply_event_loop_stop_watching_fd (manager->loop, manager->udev_queue_fd_watch);
01552a
   manager->udev_queue_fd_watch = NULL;
01552a
   udev_queue_unref (manager->udev_queue);
01552a
 
01552a
   close (manager->udev_queue_fd);
01552a
   manager->udev_queue_fd = -1;
01552a
 
01552a
   manager->udev_queue = NULL;
01552a
 
01552a
   create_seats_from_udev (manager);
01552a
 }
01552a
-- 
01552a
1.8.3.1
01552a
01552a
01552a
From 20603c552e7e31f65f6265ed7230ba4bcaf12bf5 Mon Sep 17 00:00:00 2001
01552a
From: Ray Strode <rstrode@redhat.com>
01552a
Date: Mon, 3 Mar 2014 17:25:44 -0500
01552a
Subject: [PATCH 2/2] device-manager: defer /dev/fb compat processing until
01552a
 after coldplug
01552a
01552a
We never want to use a /dev/fb device if a DRM device will work instead
01552a
(since it supports multi-monitor, isn't a legacy interface, etc)
01552a
01552a
Unfortunately, right now plymouthd notices efifb at early start up,
01552a
see's there is no DRM device associated with it and chooses it for
01552a
the main display, which causes all sort of problems.
01552a
01552a
This commit defers using /dev/fb devices until after udev settles.
01552a
---
01552a
 src/libply-splash-core/ply-device-manager.c | 24 +++++++++++++++++++++---
01552a
 1 file changed, 21 insertions(+), 3 deletions(-)
01552a
01552a
diff --git a/src/libply-splash-core/ply-device-manager.c b/src/libply-splash-core/ply-device-manager.c
01552a
index 25f7d54..d06e1b5 100644
01552a
--- a/src/libply-splash-core/ply-device-manager.c
01552a
+++ b/src/libply-splash-core/ply-device-manager.c
01552a
@@ -161,62 +161,63 @@ fb_device_has_drm_device (ply_device_manager_t *manager,
01552a
       ply_trace ("no card entry!");
01552a
     }
01552a
 
01552a
   udev_enumerate_unref (card_matches);
01552a
   return has_drm_device;
01552a
 }
01552a
 
01552a
 static void
01552a
 create_seat_for_udev_device (ply_device_manager_t *manager,
01552a
                              struct udev_device   *device)
01552a
 {
01552a
   bool for_local_console;
01552a
   const char *device_path;
01552a
   ply_terminal_t *terminal = NULL;
01552a
 
01552a
   for_local_console = device_is_for_local_console (manager, device);
01552a
 
01552a
   ply_trace ("device is for local console: %s", for_local_console? "yes" : "no");
01552a
 
01552a
   if (for_local_console)
01552a
     terminal = manager->local_console_terminal;
01552a
 
01552a
   device_path = udev_device_get_devnode (device);
01552a
 
01552a
   if (device_path != NULL)
01552a
     {
01552a
       const char *subsystem;
01552a
       ply_renderer_type_t renderer_type = PLY_RENDERER_TYPE_NONE;
01552a
 
01552a
       subsystem = udev_device_get_subsystem (device);
01552a
+      ply_trace ("device subsystem is %s", subsystem);
01552a
 
01552a
-      if (strcmp (subsystem, SUBSYSTEM_DRM) == 0)
01552a
+      if (subsystem != NULL && strcmp (subsystem, SUBSYSTEM_DRM) == 0)
01552a
         {
01552a
           ply_trace ("found DRM device %s", device_path);
01552a
           renderer_type = PLY_RENDERER_TYPE_DRM;
01552a
         }
01552a
       else if (strcmp (subsystem, SUBSYSTEM_FRAME_BUFFER) == 0)
01552a
         {
01552a
           ply_trace ("found frame buffer device %s", device_path);
01552a
           if (!fb_device_has_drm_device (manager, device))
01552a
             {
01552a
               renderer_type = PLY_RENDERER_TYPE_FRAME_BUFFER;
01552a
             }
01552a
           else
01552a
             {
01552a
               ply_trace ("ignoring, since there's a DRM device associated with it");
01552a
             }
01552a
         }
01552a
 
01552a
       if (renderer_type != PLY_RENDERER_TYPE_NONE)
01552a
         create_seat_for_terminal_and_renderer_type (manager,
01552a
                                                     device_path,
01552a
                                                     terminal,
01552a
                                                     renderer_type);
01552a
     }
01552a
 }
01552a
 
01552a
 static void
01552a
 free_seat_from_device_path (ply_device_manager_t *manager,
01552a
                             const char           *device_path)
01552a
 {
01552a
   ply_list_node_t *node;
01552a
@@ -332,63 +333,80 @@ create_seats_for_subsystem (ply_device_manager_t *manager,
01552a
         {
01552a
           ply_trace ("it's not initialized");
01552a
         }
01552a
 
01552a
       udev_device_unref (device);
01552a
     }
01552a
 
01552a
   udev_enumerate_unref (matches);
01552a
 
01552a
   return found_device;
01552a
 }
01552a
 
01552a
 static void
01552a
 on_udev_event (ply_device_manager_t *manager)
01552a
 {
01552a
   struct udev_device *device;
01552a
   const char *action;
01552a
 
01552a
   device = udev_monitor_receive_device (manager->udev_monitor);
01552a
   if (device == NULL)
01552a
     return;
01552a
 
01552a
   action = udev_device_get_action (device);
01552a
 
01552a
   ply_trace ("got %s event for device %s", action, udev_device_get_sysname (device));
01552a
 
01552a
   if (action == NULL)
01552a
     return;
01552a
 
01552a
   if (strcmp (action, "add") == 0)
01552a
-    create_seat_for_udev_device (manager, device);
01552a
+    {
01552a
+      const char *subsystem;
01552a
+      bool coldplug_complete = manager->udev_queue_fd_watch == NULL;
01552a
+
01552a
+      subsystem = udev_device_get_subsystem (device);
01552a
+
01552a
+      if (strcmp (subsystem, SUBSYSTEM_DRM) == 0 ||
01552a
+          coldplug_complete)
01552a
+        {
01552a
+          create_seat_for_udev_device (manager, device);
01552a
+        }
01552a
+      else
01552a
+        {
01552a
+          ply_trace ("ignoring since we only handle subsystem %s devices after coldplug completes", subsystem);
01552a
+        }
01552a
+    }
01552a
   else if (strcmp (action, "remove") == 0)
01552a
-    free_seat_for_udev_device (manager, device);
01552a
+    {
01552a
+      free_seat_for_udev_device (manager, device);
01552a
+    }
01552a
 
01552a
   udev_device_unref (device);
01552a
 }
01552a
 
01552a
 static void
01552a
 watch_for_udev_events (ply_device_manager_t *manager)
01552a
 {
01552a
   int fd;
01552a
   assert (manager != NULL);
01552a
   assert (manager->udev_monitor == NULL);
01552a
 
01552a
   ply_trace ("watching for udev graphics device add and remove events");
01552a
 
01552a
   manager->udev_monitor = udev_monitor_new_from_netlink (manager->udev_context, "udev");
01552a
 
01552a
   udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_DRM, NULL);
01552a
   udev_monitor_filter_add_match_subsystem_devtype (manager->udev_monitor, SUBSYSTEM_FRAME_BUFFER, NULL);
01552a
   udev_monitor_filter_add_match_tag (manager->udev_monitor, "seat");
01552a
   udev_monitor_enable_receiving (manager->udev_monitor);
01552a
 
01552a
   fd = udev_monitor_get_fd (manager->udev_monitor);
01552a
   ply_event_loop_watch_fd (manager->loop,
01552a
                            fd,
01552a
                            PLY_EVENT_LOOP_FD_STATUS_HAS_DATA,
01552a
                            (ply_event_handler_t)
01552a
                            on_udev_event,
01552a
                            NULL,
01552a
                            manager);
01552a
 }
01552a
 
01552a
-- 
01552a
1.8.3.1
01552a