Commit | Line | Data |
---|---|---|
7217e0ca ML |
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 @@ | |
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 @@ | |
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 @@ | |
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 @@ | |
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 @@ | |
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: |