Preliminary udev support

Kevin Murphy kemurphy.cmu at gmail.com
Sun Mar 10 06:47:22 PDT 2013


Hey,

So I was rereading my patch and remembered that I watch "graphics" for
framebuffer devices, and then when udev finds them, I check to see if it's
associated with a "drm" device:

+              /* We want to see if the framebuffer is associated with a
DRM-capable
+               * graphics card */
+              udev = udev_device_get_udev (dev);
+              cards = udev_enumerate_new (udev);
+              udev_enumerate_add_match_parent (cards,
udev_device_get_parent(dev));
+              udev_enumerate_add_match_subsystem (cards, "drm");
+
+              /* Udev assigns the "seat" tag to framebuffer and graphics
card
+               * devices; without matching this tag, we also end up with
the
+               * connected displays and the control interface to the card,
which
+               * we don't care about at the moment. */
+              udev_enumerate_add_match_tag (cards, "seat");
+              udev_enumerate_scan_devices (cards);
+
+              card_entry = udev_enumerate_get_list_entry (cards);
+
+              if (card_entry != NULL)
+                {
+                  struct udev_device *card;
+                  const char *card_path;
+
+
+                  card_path = udev_list_entry_get_name (card_entry);
+                  card = udev_device_new_from_syspath (udev, card_path);
+                  card_node = udev_device_get_devnode(card);
+
+                  if (card_node != NULL)
+                    {
+                      ply_trace ("Found DRM card %s for framebuffer %s",
card_node, fb_node);
+                      card_node = strdup (card_node);
+                    }
+                  else
+                    {
+                      ply_trace ("This is strange, DRM card found with no
device node...");
+                      ply_trace ("Continuing as if no card found");
+                    }
[snip]
+              ply_renderer_t *renderer = NULL;
+
+              if (card_node != NULL)
+                {
+                  renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH
"renderers/drm.so",
+                                               card_node,
+
state->local_console_terminal);
+
+                  if (renderer == NULL || !ply_renderer_open (renderer))
+                    {
+                      ply_trace ("Could not open renderer for %s, falling
back to framebuffer", card_node);
+                      ply_renderer_free (renderer);
+                      renderer = NULL;
+                    }
+                }
+
+              if (renderer == NULL)
+                {
+                  renderer = ply_renderer_new (PLYMOUTH_PLUGIN_PATH
"renderers/frame-buffer.so",
+                                               fb_node,
+
state->local_console_terminal);
+
+                  if (renderer == NULL || !ply_renderer_open (renderer))
+                    {
+                      ply_trace ("Could not open renderer for %s,
aborting", fb_node);
+                      ply_renderer_free (renderer);
+
+                      if (card_node != NULL)
+                        {
+                          free (card_node);
+                        }
+
+                      return;
+                    }
+                }

This way we get automatic fallback to the framebuffer if the user's system
doesn't have a drm-capable card.  Do you think this is the right way to go
about it?

Thanks,
Kevin

On Fri, Mar 1, 2013 at 11:16 AM, Ray Strode <halfline at gmail.com> wrote:

> Hi,
>
> > +  udev_enum = udev_enumerate_new (state->udev);
> > +  udev_enumerate_add_match_subsystem (udev_enum, "graphics");
> > +  udev_enumerate_add_match_tag(udev_enum, "seat");
> > +  udev_enumerate_add_match_is_initialized(udev_enum);
> > +  udev_enumerate_scan_devices (udev_enum);
> > +
> > +  entries = udev_enumerate_get_list_entry (udev_enum);
> >
> > Unless I'm mistaken about how to drive the udev API, that should just
> simply
> > gather a list of all graphics devices with the "seat" tag that have been
> > fully initialized out of the list of all the devices that udev has
> detected
> > at that point; the ordering with framebuffer devices shouldn't come into
> > play.
> I believe the "graphics" subsystem corresponds to /sys/class/graphics
> which is the legacy fb device subsystem.
>
> > As far as I remember, udev events don't fire until the device is fully
> initialized.
>
> I remember looking into this a while back briefly.  let me see if i
> can find the log... Ok it was actually from way back in october.
> Pasted below:
>
> <poettering>    airlied: around?
> <poettering>    ajax: or you?
> <poettering>    got a question regarding fb and drm device nodes
> <poettering>    do we get any guarantee about the order in which they
> show up in userspace?
> <poettering>    the reason i am asking is this:
> <poettering>    logind currently watches for fb device nodes to show up
> <poettering>    it uses that as the main indicator for a seat being around
> <poettering>    now, if the drm device node can show up after the fb node
> <poettering>    then we'll inform gdm about the seat a bit too early
> <poettering>    where it will start x at a time where drm is not yet
> available
> <poettering>    now, what i am wondering about:
> <poettering>    a) is there a guarantee that fb shows up after drm?
> <poettering>    b) if not, can we get one?
> <poettering>    c) if we can't get one, should i just forget about fb and
> always only watch drm?
> <poettering>    d) and if c), are there any devices we stop supporting
> that way?
> <poettering>    any other thoughts?
> <mjg59> poettering: Pretty sure that the drm device needs to exist for
> the KMS fb nodes to exist
> <mjg59> But that's not quite the same as the drm device *nodes* existing
> <mjg59> Let me look at that a bit more
> <poettering>    to me only the order for the udev events matters really...
> <mjg59> poettering: This is the card node rather than any connectors,
> right?
> <mjg59> poettering: Looks like the card%d sysfs node will be created
> in drm_get_pci_dev()
> <mjg59> poettering: And I can't see any way the framebuffers could be
> created before that
> <halfline>      well the real question is, at what point can we safely open
> /dev/dri/card0 and have it 1) exist and 2) not give any errors because
> we're trying to use it before things are fully initialized
> <ajax>  mclasen: working on it, but afaik things should build in f18.
> <mclasen>       ajax: ok, I'll try again
> <mclasen>       ajax: also, did you see poetterings question ?
> <ajax>  i did, i'm afraid i don't know that answer
> <ajax>  my personal preference would be to not have fbdev emulation at
> all anymore really
> <ajax>  but that probably doesn't help in the case of handing off the
> device from efifb to drm
> <mclasen>       there seems to be a question about the readiness of
> /dev/dri/card0 too, though
> <ajax>  that seems like a bad question though
> <mclasen>       bad in the sense of ill-posed, or in the sense of 'you
> won't
> like the answer' ?
> <ajax>  i guess i'm not sure why we'd get into a scenario where it
> could exist but be "not ready"
> <ajax>  and if we could, why we wouldn't just consider that a drm bug.
> <mjg59> sysfs node is created before driver->load() is called
> <halfline>      poettering,mjg59: looking at the code..drm_pci.c
> drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY) creates the card0
> device and then  dev->driver->load(dev, ent->driver_data) is called
> after taht
> <halfline>      mjg59: jinx
> <ajax>  uh, okay, let's just move A below B then.
> <ajax>  nothing in ->load should be looking at the chardev info i don't
> think
> <mjg59> Yeah that does seem like a generally bad idea
> <mjg59> But does anything open card0 before there are any connectors?
> <halfline>      well anyway ret = intel_fbdev_init(dev); is called after
> the whole lot
> <halfline>      so what poettering is doing should be fine
> <halfline>      assuming the other drivers are okay
> <ajax>  mjg59: if we emit udev plug events when the connectors appear,
> then who cares?
> <ajax>  just uevents i guess
> <halfline>      well it's the difference between things occasionally
> failing and things not occasionally failing...
> <ajax>  no, it's the difference between the opener being correct and
> not being correct.
> <halfline>      heh
> <ajax>  connectors can already come and go
> <ajax>  so you ought already to be looking for that
> <halfline>      ought but not
> <halfline>      (for plymouth anyway)
> <ajax>  yeah, i didn't say we _are_ correct, just that the way forward
> is, er, straightforward
> <ajax>  but in the static connector list case i think those all exist
> by the time ->load is done
> <mclasen>       makes sense; if there are events for connectors appearing,
> we should deal with them
> <ajax>  so simply not exposing the chardev before initialization seems
> like it'll paper over that ordering issue
> <mjg59> ajax: As long as ->load() doesn't create any connector objects
> <mjg59> Because that depends on the sysfs parent already existing
> <ajax>  clearly i'm missing something here
> <halfline>      well poettering is just waiting for the /dev/fb device to
> show up which should be fine paper
> <mjg59> ajax: drm_get_minor() is currently called before the driver
> ->load() method. This guarantees that there's a sysfs object for the
> card, and any connectors will use that as their parent. You suggested
> moving it to after ->load(). That's fine as long as nothing tries to
> create connectors in the load() method.
> <ajax>  remind me which cog in this hell machine is responsible for
> making the /dev node exist
> <mjg59> ajax: udev will create the device node some amount of time
> after the sysfs object is created
> <mjg59> ajax: But depending on it to not do that until after load() is racy
> <mjg59> It could happen at any time after the card sysfs object is created
> <ajax>  this seems like a class of races that others have to have faced
> <mjg59> I blame drm's awful abstractions
> <mjg59> Anyway, the device will normally be created during boot, so
> the only thing that could really be racing with it is plymouth
> <mjg59> Lennart's stuff is waiting for framebuffer creation, which
> works as a useful extra sequencing point
> <halfline>      cosimoc's machine boots so fast that plymouth isn't in the
> picture and he gets software rendering for gnome-shell
> <halfline>      well once in a while
> <halfline>      because pam_systemd runs before the /dev/dri/card0 exists
> <halfline>      and so it doesn't given gdm access rights to it
> <halfline>      so we're going to make GDM not start an X server until
> systemd gives the go ahead
> <halfline>      and systemd gives the go ahead when /dev/fb0 shows up
> <halfline>      so we should be good
> <poettering>    mjg59: so you say fb is a good sync point?
> <poettering>    if that's the case then i am happy
> <poettering>    and if fb is dropped one day we can reinvestigate the
> whole issue
> <poettering>    all i am aksing for basically is that by the time fb was
> handled by userspace all initialization that X might need of the
> drivers is complete
> <halfline>      poettering: so i checked intel, radeon, and nouveau
> earlier, and they all did fbdev initialization at the end
> <halfline>      so i think you're safe
> <mjg59> poettering: "Good" may be overstating
> <mjg59> But I suspect it'd work
> <notting>       does gnome-tweak-tool tweak non-dconf settings?
> <kay>   mjg59: udev does not create any device node since quite some
> time, it's all in the kernel, /dev is at the same time as /sys
> <mjg59> kay: Yeah ok I need to pay more attention
> <kay>   mjg59: udev today does only symlinks and permissions at event
> time. devtmpfs does all the nodes stuff. udev does not even have the
> code anymore to call mknod() in the hotplug handler ...
> <airlied>       please don'
> <airlied>       please don'y rely on /dev/fb nodes
> <airlied>       its not good
> <airlied>       all the other stuff is protected by drm_global_muetx
> <airlied>       so if you open before we area ready it'll block
> <airlied>       since drm_stub_open also takes the drm_global_mutex
> <airlied>       we don't want to require drm to provide fb emulation for
> ever
> <airlied>       poettering, halfline, ajax, mjg59 ^
> <halfline>      airlied: hmm, pretty sure we've had bugs plymouth bugs in
> the past where if we open /dev/dri/card0 too early it's there but
> fails
> <halfline>      anyway the problem this time around was it not being there
> at all
> <halfline>      so pam_systemd couldn't trigger ACL changes to it
> <airlied>       halfline: yeah there was problems years ago
> <airlied>       its almsot like we fixed them :-)
> <airlied>       though I'm trying to remember when we did
> <airlied>       b64c115eb22516ecd187c74ad6de3f1693f1dc7b 2 years ago
> <airlied>       I've had alternate patches to move stuff around but I never
> trusted them enough
> <airlied>       and I didn't think open was too contended
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/plymouth/attachments/20130310/38f6d5bb/attachment-0001.html>


More information about the plymouth mailing list