Should drm's modetest work when an X server is running?

Daniel Kurtz djkurtz at chromium.org
Mon Mar 3 15:53:25 PST 2014


Dear dri developers,

Should libdrm's modetest work when an X server is running?
Should drmOpen(name, NULL) succeed when the drm device is already open?
Is "name" passed to drmOpen() the "drm" name returned by drmGetVersion()?
Or, is it the the kernel driver/module name?

tl;dr

Over the past couple of days I have been trying to get "modetest" from
the libdrm repository to run on my exynos based ARM chromebook.

With an X server running, "modetest" fails like this:
# modetest
trying to open device 'exynos'...failed.
no device found.

Without an X server, "modetest" succeeds:
# modetest
trying to open device 'exynos'...success.
Encoders:
id crtc type possible crtcs possible clones
15 5 TMDS 0x00000001 0x00000003
18 0 TMDS 0x00000002 0x00000003
...

So, why is modetest failing when the X server is running?

If we don't specify a module (-M) or device (-D) on the command line,
modetest searches through a hard coded list of "modules":
const char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx",
"omapdrm", "exynos", "tilcdc", "msm" };

For each module, it tries to open it with drmOpen:
  dev.fd = drmOpen(modules[i], device);

When checking for "exynos", this becomes...
drmOpen("exynos", NULL), which first calls
  -> drmAvailable()
    -> drmOpenMinor(0, 1, DRM_NODE_RENDER)
      -> drmOpenDevice(makedev(DRM_MAJOR, 0), 0, DRM_NODE_RENDER);
        -> this eventually calls open("/dev/dri/card0"), which returns
a valid fd.
drmOpen("exynos", NULL) then calls
  -> drmOpenByName("exynos")
     -> /* Redundant drmAvailable() check */
     -> for i=0:15:
       -> drmOpenMinor(i, 1, DRM_NODE_RENDER);
         -> if it returns a valid fd: version = drmGetVersion(fd)
           -> if version->name == "exynos": id = drmGetBusid(fd);
             -> if id != NULL && id != "":  Success! return the fd

In other words, drmOpen("exynos", NULL) succeeds if any of
"/dev/dri/card*" can be opened, it drmGetVersion() succeeds and
returns version->name == "exynos", and if drmGetBusid(fd) is NULL or
"".  In other words, it opens the first minor number that matches the
DRM "version" name and doesn't already have a busid assigned (ie, the
first matching minor that isn't in use).

So, this explains why modetest works when my X server is stopped.  The
drm name matches, and there is no busid, so drmOpen() happily returns
an fd.

But on a system with intel graphics (i915), modetest works even with
the X server running, why?
It turns out that there is another chunk of code in drmOpenByName(),
that is linux only, and implements "Backward-compatibility /proc
support".  In a loop it reads "/proc/dri/*/name" and matches the first
field against the "name" passed in to drmOpenByName().  If this
matches:
  * if there are 3 fields, the 3rd field is passed to drmOpenByBusid()
  * if there were only 2 fields, the 2nd field is parsed as a long and
passed as the dev parameter to drmOpenDevice().

"On my intel machine, the first field is "i915", the same name
returned as the version->name for drmGetVersion(), so we end up doing
something like drmOpenByBusid("pci:0000:00:02.0), which succeeds
because that matches what is returned by drmGetBusid().

$ cat /proc/dri/0/name
i915 0000:00:02.0 pci:0000:00:02.0

But, for exynos, the the driver name is actually "exynos-drm", so the
check fails, and drmOpen("exynos", NULL) fails.

# cat /proc/dri/0/name
exynos-drm exynos-drm platform:exynos-drm:00

I'm obviously using an older kernel.  From the kernel git log, I see
that danvet recently removed the entire proc interface.  So, does that
mean that on up to date kernels modetest (and the other libdrm tests)
will now also fail for intel if X is running (since the proc back door
is no longer available)?
Is this "working as intended"?

-Dan


More information about the dri-devel mailing list