1 From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
2 Subject: [PATCH] do not use drmGetBusid to grab the pci-id name
4 The kernel returns EACCES or EAGAIN on drm open when the drm device is
5 currently unavailable, such as if it is in use by another process
6 (e.g. plymouth), or hasn't finished initializing (e.g. on a really fast
7 SSD). Because the probing is done before a vt switch is completed,
8 we have no way to ensure that we can own DRM master. This results
11 Also attrib->unowned is not initialized, always initialize it to fix
12 a valgrind warning, and to prevent adding the same device a second time
15 Fixes: https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/982889
17 Signed-off-by: Bryce Harrington <bryce@canonical.com>
19 hw/xfree86/os-support/linux/lnx_platform.c | 29 +++++++++++++++++++++++++---
20 1 file changed, 26 insertions(+), 3 deletions(-)
24 @@ -98,7 +98,7 @@ device_added(struct udev_device *udev_de
25 if (strncmp(sysname, "card", 4) != 0)
28 - LogMessage(X_INFO, "config/udev: Adding drm device (%s)\n", path);
29 + LogMessage(X_INFO, "config/udev: Adding drm device (%s) %s %s\n", path, sysname, syspath);
31 config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
33 @@ -430,11 +430,23 @@ config_udev_fini(void)
34 #ifdef CONFIG_UDEV_KMS
37 +get_pci_busid(const char *in, char *pci_str)
39 + int ret, domain, bus, dev, func;
40 + ret = sscanf(in, "/%04x:%02x:%02x.%d/drm/card%*d", &domain, &bus, &dev, &func);
43 + sprintf(pci_str, "pci:%04x:%02x:%02x.%d", domain, bus, dev, func);
48 config_udev_odev_setup_attribs(const char *path, const char *syspath,
49 config_odev_probe_proc_ptr probe_callback)
51 struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
53 + const char *platform;
57 @@ -447,6 +459,33 @@ config_udev_odev_setup_attribs(const cha
61 + if (strstr(syspath, "/devices/pci")) {
63 + const char *end = strstr(syspath, "/drm/card");
64 + if (strstr(syspath, "/usb"))
65 + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_BUSID, "");
66 + else if (get_pci_busid(end - 13, pci_str))
67 + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_BUSID, pci_str);
68 + } else if ((platform = strstr(syspath, "/devices/platform/"))) {
69 + /* OMAP relies on this, modesetting doesn't use it */
72 + end = strchr(platform, '.');
75 + ret = asprintf(&busid, "platform:%.*s:%02li",
76 + (int)(end - platform), platform, strtol(end + 1, NULL, 10));
78 + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_BUSID, busid);
88 /* ownership of attribs is passed to probe layer */
89 probe_callback(attribs);
91 --- a/hw/xfree86/os-support/linux/lnx_platform.c
92 +++ b/hw/xfree86/os-support/linux/lnx_platform.c
98 -get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
105 - fd = open(path, O_RDWR, O_CLOEXEC);
109 - sv.drm_di_major = 1;
110 - sv.drm_di_minor = 4;
111 - sv.drm_dd_major = -1; /* Don't care */
112 - sv.drm_dd_minor = -1; /* Don't care */
114 - err = drmSetInterfaceVersion(fd, &sv);
116 - ErrorF("setversion 1.4 failed: %s\n", strerror(-err));
120 - /* for a delayed probe we've already added the device */
121 - if (delayed_index == -1) {
122 - xf86_add_platform_device(attribs);
123 - delayed_index = xf86_num_platform_devices - 1;
126 - buf = drmGetBusid(fd);
127 - xf86_add_platform_device_attrib(delayed_index,
128 - ODEV_ATTRIB_BUSID, buf);
136 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
138 @@ -105,11 +67,6 @@ xf86PlatformReprobeDevice(int index, str
140 dpath = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
142 - ret = get_drm_info(attribs, dpath, index);
143 - if (ret == FALSE) {
144 - xf86_remove_platform_device(index);
147 ret = xf86platformAddDevice(index);
149 xf86_remove_platform_device(index);
150 @@ -145,18 +102,10 @@ xf86PlatformDeviceProbe(struct OdevAttri
152 LogMessage(X_INFO, "xfree86: Adding drm device (%s)\n", path);
154 - if (!xf86VTOwner()) {
155 - /* if we don't currently own the VT then don't probe the device,
156 - just mark it as unowned for later use */
157 - attribs->unowned = TRUE;
158 - xf86_add_platform_device(attribs);
162 - ret = get_drm_info(attribs, path, -1);
166 + /* if we don't currently own the VT then don't probe the device,
167 + just mark it as unowned for later use */
168 + attribs->unowned = !xf86VTOwner();
169 + xf86_add_platform_device(attribs);