34051a1fe57902c192349eaaa948be810fd7d5d3
[deb_xorg-server.git] / debian / patches / drm_device_keep_trying.patch
1 From: Maarten Lankhorst <maarten.lankhorst@canonical.com>
2 Subject: [PATCH] do not use drmGetBusid to grab the pci-id name
3
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
9 in failing to boot.
10
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
13 after a vt switch.
14
15 Fixes: https://bugs.launchpad.net/ubuntu/+source/xorg-server/+bug/982889
16
17 Signed-off-by: Bryce Harrington <bryce@canonical.com>
18 ---
19 hw/xfree86/os-support/linux/lnx_platform.c | 29 +++++++++++++++++++++++++---
20 1 file changed, 26 insertions(+), 3 deletions(-)
21
22 --- a/config/udev.c
23 +++ b/config/udev.c
24 @@ -98,7 +98,7 @@ device_added(struct udev_device *udev_de
25 if (strncmp(sysname, "card", 4) != 0)
26 return;
27
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);
30
31 config_udev_odev_setup_attribs(path, syspath, NewGPUDeviceRequest);
32 return;
33 @@ -430,11 +430,23 @@ config_udev_fini(void)
34 #ifdef CONFIG_UDEV_KMS
35
36 static Bool
37 +get_pci_busid(const char *in, char *pci_str)
38 +{
39 + int ret, domain, bus, dev, func;
40 + ret = sscanf(in, "/%04x:%02x:%02x.%d/drm/card%*d", &domain, &bus, &dev, &func);
41 + if (ret != 4)
42 + return FALSE;
43 + sprintf(pci_str, "pci:%04x:%02x:%02x.%d", domain, bus, dev, func);
44 + return TRUE;
45 +}
46 +
47 +static Bool
48 config_udev_odev_setup_attribs(const char *path, const char *syspath,
49 config_odev_probe_proc_ptr probe_callback)
50 {
51 struct OdevAttributes *attribs = config_odev_allocate_attribute_list();
52 int ret;
53 + const char *platform;
54
55 if (!attribs)
56 return FALSE;
57 @@ -447,6 +459,33 @@ config_udev_odev_setup_attribs(const cha
58 if (ret == FALSE)
59 goto fail;
60
61 + if (strstr(syspath, "/devices/pci")) {
62 + char pci_str[17];
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 */
70 + const char *end;
71 + platform += 18;
72 + end = strchr(platform, '.');
73 + if (end) {
74 + char *busid;
75 + ret = asprintf(&busid, "platform:%.*s:%02li",
76 + (int)(end - platform), platform, strtol(end + 1, NULL, 10));
77 + if (ret >= 0) {
78 + ret = config_odev_add_attribute(attribs, ODEV_ATTRIB_BUSID, busid);
79 + free(busid);
80 + }
81 + else
82 + ret = TRUE;
83 + }
84 + }
85 + if (ret == FALSE)
86 + goto fail;
87 +
88 /* ownership of attribs is passed to probe layer */
89 probe_callback(attribs);
90 return TRUE;
91 --- a/hw/xfree86/os-support/linux/lnx_platform.c
92 +++ b/hw/xfree86/os-support/linux/lnx_platform.c
93 @@ -19,44 +19,6 @@
94
95 #include "hotplug.h"
96
97 -static Bool
98 -get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index)
99 -{
100 - drmSetVersion sv;
101 - char *buf;
102 - int fd;
103 - int err = 0;
104 -
105 - fd = open(path, O_RDWR, O_CLOEXEC);
106 - if (fd == -1)
107 - return FALSE;
108 -
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 */
113 -
114 - err = drmSetInterfaceVersion(fd, &sv);
115 - if (err) {
116 - ErrorF("setversion 1.4 failed: %s\n", strerror(-err));
117 - goto out;
118 - }
119 -
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;
124 - }
125 -
126 - buf = drmGetBusid(fd);
127 - xf86_add_platform_device_attrib(delayed_index,
128 - ODEV_ATTRIB_BUSID, buf);
129 - drmFreeBusid(buf);
130 -out:
131 - close(fd);
132 - return (err == 0);
133 -}
134 -
135 Bool
136 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid)
137 {
138 @@ -105,11 +67,6 @@ xf86PlatformReprobeDevice(int index, str
139 char *dpath;
140 dpath = xf86_get_platform_attrib(index, ODEV_ATTRIB_PATH);
141
142 - ret = get_drm_info(attribs, dpath, index);
143 - if (ret == FALSE) {
144 - xf86_remove_platform_device(index);
145 - return;
146 - }
147 ret = xf86platformAddDevice(index);
148 if (ret == -1)
149 xf86_remove_platform_device(index);
150 @@ -145,18 +102,10 @@ xf86PlatformDeviceProbe(struct OdevAttri
151
152 LogMessage(X_INFO, "xfree86: Adding drm device (%s)\n", path);
153
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);
159 - return;
160 - }
161 -
162 - ret = get_drm_info(attribs, path, -1);
163 - if (ret == FALSE)
164 - goto out_free;
165 -
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);
170 return;
171
172 out_free: