lnx_platform.c (5326B)
1 #ifdef HAVE_XORG_CONFIG_H 2 #include <xorg-config.h> 3 #endif 4 5 #ifdef XSERVER_PLATFORM_BUS 6 7 #include <xf86drm.h> 8 #include <fcntl.h> 9 #include <unistd.h> 10 #include <errno.h> 11 #include <string.h> 12 13 /* Linux platform device support */ 14 #include "xf86_OSproc.h" 15 16 #include "xf86.h" 17 #include "xf86platformBus.h" 18 #include "xf86Bus.h" 19 20 #include "hotplug.h" 21 #include "systemd-logind.h" 22 23 static Bool 24 get_drm_info(struct OdevAttributes *attribs, char *path, int delayed_index) 25 { 26 drmVersionPtr v; 27 int fd; 28 int err = 0; 29 Bool paused, server_fd = FALSE; 30 31 LogMessage(X_INFO, "Platform probe for %s\n", attribs->syspath); 32 33 fd = systemd_logind_take_fd(attribs->major, attribs->minor, path, &paused); 34 if (fd != -1) { 35 if (paused) { 36 LogMessage(X_ERROR, 37 "Error systemd-logind returned paused fd for drm node\n"); 38 systemd_logind_release_fd(attribs->major, attribs->minor, -1); 39 return FALSE; 40 } 41 attribs->fd = fd; 42 server_fd = TRUE; 43 } 44 45 if (fd == -1) 46 fd = open(path, O_RDWR | O_CLOEXEC, 0); 47 48 if (fd == -1) 49 return FALSE; 50 51 /* for a delayed probe we've already added the device */ 52 if (delayed_index == -1) { 53 xf86_add_platform_device(attribs, FALSE); 54 delayed_index = xf86_num_platform_devices - 1; 55 } 56 57 if (server_fd) 58 xf86_platform_devices[delayed_index].flags |= XF86_PDEV_SERVER_FD; 59 60 v = drmGetVersion(fd); 61 if (!v) { 62 xf86Msg(X_ERROR, "%s: failed to query DRM version\n", path); 63 goto out; 64 } 65 66 xf86_platform_odev_attributes(delayed_index)->driver = XNFstrdup(v->name); 67 drmFreeVersion(v); 68 69 out: 70 if (!server_fd) 71 close(fd); 72 return (err == 0); 73 } 74 75 Bool 76 xf86PlatformDeviceCheckBusID(struct xf86_platform_device *device, const char *busid) 77 { 78 const char *syspath = device->attribs->syspath; 79 BusType bustype; 80 const char *id; 81 82 if (!syspath) 83 return FALSE; 84 85 bustype = StringToBusType(busid, &id); 86 if (bustype == BUS_PCI) { 87 struct pci_device *pPci = device->pdev; 88 if (!pPci) 89 return FALSE; 90 91 if (xf86ComparePciBusString(busid, 92 ((pPci->domain << 8) 93 | pPci->bus), 94 pPci->dev, pPci->func)) { 95 return TRUE; 96 } 97 } 98 else if (bustype == BUS_PLATFORM) { 99 /* match on the minimum string */ 100 int len = strlen(id); 101 102 if (strlen(syspath) < strlen(id)) 103 len = strlen(syspath); 104 105 if (strncmp(id, syspath, len)) 106 return FALSE; 107 return TRUE; 108 } 109 else if (bustype == BUS_USB) { 110 if (strcasecmp(busid, device->attribs->busid)) 111 return FALSE; 112 return TRUE; 113 } 114 return FALSE; 115 } 116 117 void 118 xf86PlatformReprobeDevice(int index, struct OdevAttributes *attribs) 119 { 120 Bool ret; 121 char *dpath = attribs->path; 122 123 ret = get_drm_info(attribs, dpath, index); 124 if (ret == FALSE) { 125 xf86_remove_platform_device(index); 126 return; 127 } 128 ret = xf86platformAddDevice(index); 129 if (ret == -1) 130 xf86_remove_platform_device(index); 131 } 132 133 void 134 xf86PlatformDeviceProbe(struct OdevAttributes *attribs) 135 { 136 int i; 137 char *path = attribs->path; 138 Bool ret; 139 140 if (!path) 141 goto out_free; 142 143 for (i = 0; i < xf86_num_platform_devices; i++) { 144 char *dpath = xf86_platform_odev_attributes(i)->path; 145 146 if (dpath && !strcmp(path, dpath)) 147 break; 148 } 149 150 if (i != xf86_num_platform_devices) 151 goto out_free; 152 153 LogMessage(X_INFO, "xfree86: Adding drm device (%s)\n", path); 154 155 if (!xf86VTOwner()) { 156 /* if we don't currently own the VT then don't probe the device, 157 just mark it as unowned for later use */ 158 xf86_add_platform_device(attribs, TRUE); 159 return; 160 } 161 162 ret = get_drm_info(attribs, path, -1); 163 if (ret == FALSE) 164 goto out_free; 165 166 return; 167 168 out_free: 169 config_odev_free_attributes(attribs); 170 } 171 172 void NewGPUDeviceRequest(struct OdevAttributes *attribs) 173 { 174 int old_num = xf86_num_platform_devices; 175 int ret; 176 xf86PlatformDeviceProbe(attribs); 177 178 if (old_num == xf86_num_platform_devices) 179 return; 180 181 if (xf86_get_platform_device_unowned(xf86_num_platform_devices - 1) == TRUE) 182 return; 183 184 ret = xf86platformAddDevice(xf86_num_platform_devices-1); 185 if (ret == -1) 186 xf86_remove_platform_device(xf86_num_platform_devices-1); 187 188 ErrorF("xf86: found device %d\n", xf86_num_platform_devices); 189 return; 190 } 191 192 void DeleteGPUDeviceRequest(struct OdevAttributes *attribs) 193 { 194 int index; 195 char *syspath = attribs->syspath; 196 197 if (!syspath) 198 goto out; 199 200 for (index = 0; index < xf86_num_platform_devices; index++) { 201 char *dspath = xf86_platform_odev_attributes(index)->syspath; 202 if (dspath && !strcmp(syspath, dspath)) 203 break; 204 } 205 206 if (index == xf86_num_platform_devices) 207 goto out; 208 209 ErrorF("xf86: remove device %d %s\n", index, syspath); 210 211 if (xf86_get_platform_device_unowned(index) == TRUE) 212 xf86_remove_platform_device(index); 213 else 214 xf86platformRemoveDevice(index); 215 out: 216 config_odev_free_attributes(attribs); 217 } 218 219 #endif