1 /***************************************************************************
2 
3  Copyright 2013 Intel Corporation.  All Rights Reserved.
4 
5  Permission is hereby granted, free of charge, to any person obtaining a
6  copy of this software and associated documentation files (the
7  "Software"), to deal in the Software without restriction, including
8  without limitation the rights to use, copy, modify, merge, publish,
9  distribute, sub license, and/or sell copies of the Software, and to
10  permit persons to whom the Software is furnished to do so, subject to
11  the following conditions:
12 
13  The above copyright notice and this permission notice (including the
14  next paragraph) shall be included in all copies or substantial portions
15  of the Software.
16 
17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  IN NO EVENT SHALL INTEL, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
21  DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22  OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
23  THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25  **************************************************************************/
26 
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30 
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <assert.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <stdlib.h>
38 #include <dirent.h>
39 #include <errno.h>
40 
41 #if MAJOR_IN_MKDEV
42 #include <sys/mkdev.h>
43 #elif MAJOR_IN_SYSMACROS
44 #include <sys/sysmacros.h>
45 #endif
46 
47 #include <pciaccess.h>
48 
49 #include <xorg-server.h>
50 #include <xf86.h>
51 #include <xf86drm.h>
52 #include <xf86drmMode.h>
53 #include <xf86_OSproc.h>
54 #include <i915_drm.h>
55 
56 #ifdef XSERVER_PLATFORM_BUS
57 #include <xf86platformBus.h>
58 #endif
59 
60 #ifdef HAVE_VALGRIND
61 #include <valgrind.h>
62 #include <memcheck.h>
63 #define VG(x) x
64 #else
65 #define VG(x)
66 #endif
67 
68 #define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
69 
70 #include "intel_driver.h"
71 #include "fd.h"
72 
73 struct intel_device {
74 	int idx;
75 	char *master_node;
76 	char *render_node;
77 	int fd;
78 	int device_id;
79 	int open_count;
80 	int master_count;
81 };
82 
83 static int intel_device_key = -1;
84 
dump_file(ScrnInfoPtr scrn,const char * path)85 static int dump_file(ScrnInfoPtr scrn, const char *path)
86 {
87 	FILE *file;
88 	size_t len = 0;
89 	char *line = NULL;
90 
91 	file = fopen(path, "r");
92 	if (file == NULL)
93 		return 0;
94 
95 	xf86DrvMsg(scrn->scrnIndex, X_INFO, "[drm] Contents of '%s':\n", path);
96 	while (getline(&line, &len, file) != -1)
97 		xf86DrvMsg(scrn->scrnIndex, X_INFO, "[drm] %s", line);
98 
99 	free(line);
100 	fclose(file);
101 	return 1;
102 }
103 
__find_debugfs(void)104 static int __find_debugfs(void)
105 {
106 	int i;
107 
108 	for (i = 0; i < DRM_MAX_MINOR; i++) {
109 		char path[80];
110 
111 		sprintf(path, "/sys/kernel/debug/dri/%d/i915_wedged", i);
112 		if (access(path, R_OK) == 0)
113 			return i;
114 
115 		sprintf(path, "/debug/dri/%d/i915_wedged", i);
116 		if (access(path, R_OK) == 0)
117 			return i;
118 	}
119 
120 	return -1;
121 }
122 
drm_get_minor(int fd)123 static int drm_get_minor(int fd)
124 {
125 	struct stat st;
126 
127 	if (fstat(fd, &st))
128 		return __find_debugfs();
129 
130 	if (!S_ISCHR(st.st_mode))
131 		return __find_debugfs();
132 
133 	return st.st_rdev & 0x63;
134 }
135 
136 #if __linux__
137 #include <sys/mount.h>
138 
dump_debugfs(ScrnInfoPtr scrn,int fd,const char * name)139 static void dump_debugfs(ScrnInfoPtr scrn, int fd, const char *name)
140 {
141 	char path[80];
142 	int minor;
143 
144 	minor = drm_get_minor(fd);
145 	if (minor < 0)
146 		return;
147 
148 	sprintf(path, "/sys/kernel/debug/dri/%d/%s", minor, name);
149 	if (dump_file(scrn, path))
150 		return;
151 
152 	sprintf(path, "/debug/dri/%d/%s", minor, name);
153 	if (dump_file(scrn, path))
154 		return;
155 
156 	if (mount("X-debug", "/sys/kernel/debug", "debugfs", 0, 0) == 0) {
157 		sprintf(path, "/sys/kernel/debug/dri/%d/%s", minor, name);
158 		dump_file(scrn, path);
159 		umount("X-debug");
160 		return;
161 	}
162 }
163 #else
dump_debugfs(ScrnInfoPtr scrn,int fd,const char * name)164 static void dump_debugfs(ScrnInfoPtr scrn, int fd, const char *name) { }
165 #endif
166 
dump_clients_info(ScrnInfoPtr scrn,int fd)167 static void dump_clients_info(ScrnInfoPtr scrn, int fd)
168 {
169 	dump_debugfs(scrn, fd, "clients");
170 }
171 
__intel_get_device_id(int fd)172 static int __intel_get_device_id(int fd)
173 {
174 	struct drm_i915_getparam gp;
175 	int devid = 0;
176 
177 	VG_CLEAR(gp);
178 	gp.param = I915_PARAM_CHIPSET_ID;
179 	gp.value = &devid;
180 
181 	if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
182 		return 0;
183 
184 	return devid;
185 }
186 
intel_entity_get_devid(int idx)187 int intel_entity_get_devid(int idx)
188 {
189 	struct intel_device *dev;
190 
191 	dev = xf86GetEntityPrivate(idx, intel_device_key)->ptr;
192 	if (dev == NULL)
193 		return 0;
194 
195 	return dev->device_id;
196 }
197 
intel_device(ScrnInfoPtr scrn)198 static inline struct intel_device *intel_device(ScrnInfoPtr scrn)
199 {
200 	if (scrn->entityList == NULL)
201 		return NULL;
202 
203 	return xf86GetEntityPrivate(scrn->entityList[0], intel_device_key)->ptr;
204 }
205 
206 static const char *kernel_module_names[] ={
207 	"i915kms",
208 	"i915",
209 	NULL,
210 };
211 
is_i915_device(int fd)212 static int is_i915_device(int fd)
213 {
214 	drm_version_t version;
215 	const char **kn;
216 	char name[5] = "";
217 
218 	memset(&version, 0, sizeof(version));
219 	version.name_len = 4;
220 	version.name = name;
221 
222 	if (drmIoctl(fd, DRM_IOCTL_VERSION, &version))
223 		return 0;
224 
225 	for (kn = kernel_module_names; *kn; kn++)
226 		if (strcmp(*kn, name) == 0)
227 			return 1;
228 
229 	return 0;
230 }
231 
load_i915_kernel_module(void)232 static int load_i915_kernel_module(void)
233 {
234 	const char **kn;
235 
236 	for (kn = kernel_module_names; *kn; kn++)
237 		if (xf86LoadKernelModule(*kn))
238 			return 0;
239 
240 	return -1;
241 }
242 
is_i915_gem(int fd)243 static int is_i915_gem(int fd)
244 {
245 	int ret = is_i915_device(fd);
246 
247 	if (ret) {
248 		struct drm_i915_getparam gp;
249 
250 		VG_CLEAR(gp);
251 		gp.param = I915_PARAM_HAS_GEM;
252 		gp.value = &ret;
253 
254 		if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp))
255 			ret = 0;
256 	}
257 
258 	return ret;
259 }
260 
__intel_check_device(int fd)261 static int __intel_check_device(int fd)
262 {
263 	int ret;
264 
265 	/* Confirm that this is a i915.ko device with GEM/KMS enabled */
266 	ret = is_i915_gem(fd);
267 	if (ret && !hosted()) {
268 		struct drm_mode_card_res res;
269 
270 		memset(&res, 0, sizeof(res));
271 		if (drmIoctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
272 			ret = 0;
273 	}
274 
275 	return ret;
276 }
277 
open_cloexec(const char * path)278 static int open_cloexec(const char *path)
279 {
280 	struct stat st;
281 	int loop = 1000;
282 	int fd;
283 
284 	/* No file? Assume the driver is loading slowly */
285 	while (stat(path, &st) == -1 && errno == ENOENT && --loop)
286 		usleep(50000);
287 
288 	if (loop != 1000)
289 		ErrorF("intel: waited %d ms for '%s' to appear\n",
290 		       (1000 - loop) * 50, path);
291 
292 	fd = -1;
293 #ifdef O_CLOEXEC
294 	fd = open(path, O_RDWR | O_NONBLOCK | O_CLOEXEC);
295 #endif
296 	if (fd == -1)
297 		fd = fd_set_cloexec(open(path, O_RDWR | O_NONBLOCK));
298 
299 	return fd;
300 }
301 
302 #ifdef __linux__
__intel_open_device__major_minor(int _major,int _minor)303 static int __intel_open_device__major_minor(int _major, int _minor)
304 {
305 	DIR *dir;
306 	struct dirent *de;
307 	char path[9+sizeof(de->d_name)];
308 	int base, fd = -1;
309 
310 	base = sprintf(path, "/dev/dri/");
311 
312 	dir = opendir(path);
313 	if (dir == NULL)
314 		return -1;
315 
316 	while ((de = readdir(dir)) != NULL) {
317 		struct stat st;
318 
319 		if (*de->d_name == '.')
320 			continue;
321 
322 		sprintf(path + base, "%s", de->d_name);
323 		if (stat(path, &st) == 0 &&
324 		    major(st.st_rdev) == _major &&
325 		    minor(st.st_rdev) == _minor) {
326 			fd = open_cloexec(path);
327 			break;
328 		}
329 	}
330 
331 	closedir(dir);
332 
333 	return fd;
334 }
335 
__intel_open_device__pci(const struct pci_device * pci)336 static int __intel_open_device__pci(const struct pci_device *pci)
337 {
338 	struct stat st;
339 	char path[256];
340 	DIR *dir;
341 	struct dirent *de;
342 	int base;
343 	int fd;
344 
345 	/* Look up the major:minor for the drm device through sysfs.
346 	 * First we need to check that sysfs is available, then
347 	 * check that we have loaded our driver. When we are happy
348 	 * that our KMS module is loaded, we can then search for our
349 	 * device node. We make the assumption that it uses the same
350 	 * name, but after that we read the major:minor assigned to us
351 	 * and search for a matching entry in /dev.
352 	 */
353 
354 	base = sprintf(path,
355 		       "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
356 		       pci->domain, pci->bus, pci->dev, pci->func);
357 	if (stat(path, &st))
358 		return -1;
359 
360 	sprintf(path + base, "drm");
361 	dir = opendir(path);
362 	if (dir == NULL) {
363 		int loop = 0;
364 
365 		sprintf(path + base, "driver");
366 		if (stat(path, &st)) {
367 			if (load_i915_kernel_module())
368 				return -1;
369 			(void)xf86LoadKernelModule("fbcon");
370 		}
371 
372 		sprintf(path + base, "drm");
373 		while ((dir = opendir(path)) == NULL && loop++ < 100)
374 			usleep(20000);
375 
376 		ErrorF("intel: waited %d ms for i915.ko driver to load\n", loop * 20000 / 1000);
377 
378 		if (dir == NULL)
379 			return -1;
380 	}
381 
382 	fd = -1;
383 	while ((de = readdir(dir)) != NULL) {
384 		if (*de->d_name == '.')
385 			continue;
386 
387 		if (strncmp(de->d_name, "card", 4) == 0) {
388 			sprintf(path + base + 4, "/dev/dri/%s", de->d_name);
389 			fd = open_cloexec(path + base + 4);
390 			if (fd != -1)
391 				break;
392 
393 			sprintf(path + base + 3, "/%s/dev", de->d_name);
394 			fd = open(path, O_RDONLY);
395 			if (fd == -1)
396 				break;
397 
398 			base = read(fd, path, sizeof(path) - 1);
399 			close(fd);
400 
401 			fd = -1;
402 			if (base > 0) {
403 				int major, minor;
404 				path[base] = '\0';
405 				if (sscanf(path, "%d:%d", &major, &minor) == 2)
406 					fd = __intel_open_device__major_minor(major, minor);
407 			}
408 			break;
409 		}
410 	}
411 	closedir(dir);
412 
413 	return fd;
414 }
415 #else
__intel_open_device__pci(const struct pci_device * pci)416 static int __intel_open_device__pci(const struct pci_device *pci) { return -1; }
417 #endif
418 
__intel_open_device__legacy(const struct pci_device * pci)419 static int __intel_open_device__legacy(const struct pci_device *pci)
420 {
421 	char id[20];
422 	int ret;
423 
424 	snprintf(id, sizeof(id),
425 		 "pci:%04x:%02x:%02x.%d",
426 		 pci->domain, pci->bus, pci->dev, pci->func);
427 
428 #if defined(__DragonFly__)
429 	/* assume modesetting for i915, allow multiple loads and no fbcon */
430 	load_i915_kernel_module();
431 #else
432 
433 	ret = drmCheckModesettingSupported(id);
434 	if (ret) {
435 		if (load_i915_kernel_module() == 0)
436 			ret = drmCheckModesettingSupported(id);
437 		if (ret)
438 			return -1;
439 		/* Be nice to the user and load fbcon too */
440 		(void)xf86LoadKernelModule("fbcon");
441 	}
442 #endif
443 	return fd_set_nonblock(drmOpen(NULL, id));
444 }
445 
__intel_open_device(const struct pci_device * pci,const char * path)446 static int __intel_open_device(const struct pci_device *pci, const char *path)
447 {
448 	int fd;
449 
450 	if (path == NULL) {
451 		if (pci == NULL)
452 			return -1;
453 
454 		fd = __intel_open_device__pci(pci);
455 		if (fd == -1)
456 			fd = __intel_open_device__legacy(pci);
457 	} else
458 		fd = open_cloexec(path);
459 
460 	return fd;
461 }
462 
find_master_node(int fd)463 static char *find_master_node(int fd)
464 {
465 	struct stat st, master;
466 	char buf[128];
467 
468 	if (fstat(fd, &st))
469 		return NULL;
470 
471 	if (!S_ISCHR(st.st_mode))
472 		return NULL;
473 
474 	sprintf(buf, "/dev/dri/card%d", (int)(st.st_rdev & 0x7f));
475 	if (stat(buf, &master) == 0 &&
476 	    S_ISCHR(master.st_mode) &&
477 	    (st.st_rdev & 0x7f) == master.st_rdev)
478 		return strdup(buf);
479 
480 	/* Fallback to iterating over the usual suspects */
481 	return drmGetDeviceNameFromFd(fd);
482 }
483 
is_render_node(int fd,struct stat * st)484 static int is_render_node(int fd, struct stat *st)
485 {
486 	if (fstat(fd, st))
487 		return -1;
488 
489 	if (!S_ISCHR(st->st_mode))
490 		return -1;
491 
492 	return st->st_rdev & 0x80;
493 }
494 
find_render_node(int fd)495 static char *find_render_node(int fd)
496 {
497 	struct stat master, render;
498 	char buf[128];
499 	int i;
500 
501 	/* Are we a render-node ourselves? */
502 	if (is_render_node(fd, &master))
503 		return NULL;
504 
505 	sprintf(buf, "/dev/dri/renderD%d", (int)((master.st_rdev | 0x80) & 0xbf));
506 	if (stat(buf, &render) == 0 &&
507 	    S_ISCHR(render.st_mode) &&
508 	    render.st_rdev == (master.st_rdev | 0x80))
509 		return strdup(buf);
510 
511 	/* Misaligned card <-> renderD, do a full search */
512 	for (i = 0; i < 16; i++) {
513 		sprintf(buf, "/dev/dri/renderD%d", i + 128);
514 		if (stat(buf, &render) == 0 &&
515 		    S_ISCHR(render.st_mode) &&
516 		    render.st_rdev == (master.st_rdev | 0x80))
517 			return strdup(buf);
518 	}
519 
520 	return NULL;
521 }
522 
523 #if defined(ODEV_ATTRIB_PATH)
get_path(struct xf86_platform_device * dev)524 static char *get_path(struct xf86_platform_device *dev)
525 {
526 	const char *path;
527 
528 	if (dev == NULL)
529 		return NULL;
530 
531 	path = xf86_get_platform_device_attrib(dev, ODEV_ATTRIB_PATH);
532 	if (path == NULL)
533 		return NULL;
534 
535 	return strdup(path);
536 }
537 
538 #else
539 
get_path(struct xf86_platform_device * dev)540 static char *get_path(struct xf86_platform_device *dev)
541 {
542 	return NULL;
543 }
544 #endif
545 
546 
547 #if defined(ODEV_ATTRIB_FD)
get_fd(struct xf86_platform_device * dev)548 static int get_fd(struct xf86_platform_device *dev)
549 {
550 	if (dev == NULL)
551 		return -1;
552 
553 	return xf86_get_platform_device_int_attrib(dev, ODEV_ATTRIB_FD, -1);
554 }
555 
556 #else
557 
get_fd(struct xf86_platform_device * dev)558 static int get_fd(struct xf86_platform_device *dev)
559 {
560 	return -1;
561 }
562 #endif
563 
is_master(int fd)564 static int is_master(int fd)
565 {
566 	drmSetVersion sv;
567 
568 	sv.drm_di_major = 1;
569 	sv.drm_di_minor = 1;
570 	sv.drm_dd_major = -1;
571 	sv.drm_dd_minor = -1;
572 
573 	return drmIoctl(fd, DRM_IOCTL_SET_VERSION, &sv) == 0;
574 }
575 
intel_open_device(int entity_num,const struct pci_device * pci,struct xf86_platform_device * platform)576 int intel_open_device(int entity_num,
577 		      const struct pci_device *pci,
578 		      struct xf86_platform_device *platform)
579 {
580 	struct intel_device *dev;
581 	char *path;
582 	int fd, master_count;
583 
584 	if (intel_device_key == -1)
585 		intel_device_key = xf86AllocateEntityPrivateIndex();
586 	if (intel_device_key == -1)
587 		return -1;
588 
589 	dev = xf86GetEntityPrivate(entity_num, intel_device_key)->ptr;
590 	if (dev)
591 		return dev->fd;
592 
593 	path = get_path(platform);
594 
595 	master_count = 1; /* DRM_MASTER is managed by Xserver */
596 	fd = get_fd(platform);
597 	if (fd == -1) {
598 		fd = __intel_open_device(pci, path);
599 		if (fd == -1)
600 			goto err_path;
601 
602 		master_count = 0;
603 	}
604 
605 	if (path == NULL) {
606 		path = find_master_node(fd);
607 		if (path == NULL)
608 			goto err_close;
609 	}
610 
611 	if (!__intel_check_device(fd))
612 		goto err_close;
613 
614 	dev = malloc(sizeof(*dev));
615 	if (dev == NULL)
616 		goto err_close;
617 
618 	/* If hosted under a system compositor, just pretend to be master */
619 	if (hosted())
620 		master_count++;
621 
622 	/* Non-root user holding MASTER, don't let go */
623 	if (geteuid() && is_master(fd))
624 		master_count++;
625 
626 	if (pci)
627 		dev->device_id = pci->device_id;
628 	else
629 		dev->device_id = __intel_get_device_id(fd);
630 
631 	dev->idx = entity_num;
632 	dev->fd = fd;
633 	dev->open_count = master_count;
634 	dev->master_count = master_count;
635 	dev->master_node = path;
636 	dev->render_node = find_render_node(fd);
637 	if (dev->render_node == NULL)
638 		dev->render_node = dev->master_node;
639 
640 	xf86GetEntityPrivate(entity_num, intel_device_key)->ptr = dev;
641 
642 	return fd;
643 
644 err_close:
645 	if (master_count == 0) /* Don't close server-fds */
646 		close(fd);
647 err_path:
648 	free(path);
649 	return -1;
650 }
651 
intel_close_device(int entity_num)652 void intel_close_device(int entity_num)
653 {
654 	struct intel_device *dev;
655 
656 	if (intel_device_key == -1)
657 		return;
658 
659 	dev = xf86GetEntityPrivate(entity_num, intel_device_key)->ptr;
660 	xf86GetEntityPrivate(entity_num, intel_device_key)->ptr = NULL;
661 	if (!dev)
662 		return;
663 
664 	if (dev->master_count == 0) /* Don't close server-fds */
665 		close(dev->fd);
666 
667 	if (dev->render_node != dev->master_node)
668 		free(dev->render_node);
669 	free(dev->master_node);
670 	free(dev);
671 }
672 
__intel_peek_fd(ScrnInfoPtr scrn)673 int __intel_peek_fd(ScrnInfoPtr scrn)
674 {
675 	struct intel_device *dev;
676 
677 	dev = intel_device(scrn);
678 	assert(dev && dev->fd != -1);
679 
680 	return dev->fd;
681 }
682 
intel_has_render_node(struct intel_device * dev)683 int intel_has_render_node(struct intel_device *dev)
684 {
685 	struct stat st;
686 
687 	assert(dev && dev->fd != -1);
688 	return is_render_node(dev->fd, &st);
689 }
690 
intel_get_device(ScrnInfoPtr scrn,int * fd)691 struct intel_device *intel_get_device(ScrnInfoPtr scrn, int *fd)
692 {
693 	struct intel_device *dev;
694 	int ret;
695 
696 	dev = intel_device(scrn);
697 	if (dev == NULL)
698 		return NULL;
699 
700 	assert(dev->fd != -1);
701 
702 	if (dev->open_count++ == 0) {
703 		drmSetVersion sv;
704 		int retry = 2000;
705 
706 		assert(!hosted());
707 
708 		/* Check that what we opened was a master or a
709 		 * master-capable FD, by setting the version of the
710 		 * interface we'll use to talk to it.
711 		 */
712 		do {
713 			sv.drm_di_major = 1;
714 			sv.drm_di_minor = 1;
715 			sv.drm_dd_major = -1;
716 			sv.drm_dd_minor = -1;
717 			ret = drmIoctl(dev->fd, DRM_IOCTL_SET_VERSION, &sv);
718 			if (ret == 0)
719 				break;
720 
721 			usleep(1000);
722 		} while (--retry);
723 		if (ret != 0) {
724 			xf86DrvMsg(scrn->scrnIndex, X_ERROR,
725 				   "[drm] failed to set drm interface version: %s [%d].\n",
726 				   strerror(errno), errno);
727 			dump_clients_info(scrn, dev->fd);
728 			dev->open_count--;
729 			return NULL;
730 		}
731 	}
732 
733 	*fd = dev->fd;
734 	return dev;
735 }
736 
intel_get_master_name(struct intel_device * dev)737 const char *intel_get_master_name(struct intel_device *dev)
738 {
739 	assert(dev && dev->master_node);
740 	return dev->master_node;
741 }
742 
intel_get_client_name(struct intel_device * dev)743 const char *intel_get_client_name(struct intel_device *dev)
744 {
745 	assert(dev && dev->render_node);
746 	return dev->render_node;
747 }
748 
authorise(struct intel_device * dev,int fd)749 static int authorise(struct intel_device *dev, int fd)
750 {
751 	struct stat st;
752 	drm_magic_t magic;
753 
754 	if (is_render_node(fd, &st)) /* restricted authority, do not elevate */
755 		return 1;
756 
757 	return drmGetMagic(fd, &magic) == 0 && drmAuthMagic(dev->fd, magic) == 0;
758 }
759 
intel_get_client_fd(struct intel_device * dev)760 int intel_get_client_fd(struct intel_device *dev)
761 {
762 	int fd = -1;
763 
764 	assert(dev && dev->fd != -1);
765 	assert(dev->render_node);
766 
767 #ifdef O_CLOEXEC
768 	fd = open(dev->render_node, O_RDWR | O_CLOEXEC);
769 #endif
770 	if (fd < 0)
771 		fd = fd_set_cloexec(open(dev->render_node, O_RDWR));
772 	if (fd < 0)
773 		return -BadAlloc;
774 
775 	if (!authorise(dev, fd)) {
776 		close(fd);
777 		return -BadMatch;
778 	}
779 
780 	assert(is_i915_gem(fd));
781 
782 	return fd;
783 }
784 
intel_get_device_id(struct intel_device * dev)785 int intel_get_device_id(struct intel_device *dev)
786 {
787 	assert(dev && dev->fd != -1);
788 	return dev->device_id;
789 }
790 
intel_get_master(struct intel_device * dev)791 int intel_get_master(struct intel_device *dev)
792 {
793 	int ret;
794 
795 	assert(dev && dev->fd != -1);
796 
797 	ret = 0;
798 	if (dev->master_count++ == 0) {
799 		int retry = 2000;
800 
801 		assert(!hosted());
802 		do {
803 			ret = drmSetMaster(dev->fd);
804 			if (ret == 0)
805 				break;
806 			usleep(1000);
807 		} while (--retry);
808 	}
809 
810 	return ret;
811 }
812 
intel_put_master(struct intel_device * dev)813 int intel_put_master(struct intel_device *dev)
814 {
815 	int ret;
816 
817 	assert(dev && dev->fd != -1);
818 
819 	ret = 0;
820 	assert(dev->master_count);
821 	if (--dev->master_count == 0) {
822 		assert(!hosted());
823 		assert(drmSetMaster(dev->fd) == 0);
824 		ret = drmDropMaster(dev->fd);
825 	}
826 
827 	return ret;
828 }
829 
intel_put_device(struct intel_device * dev)830 void intel_put_device(struct intel_device *dev)
831 {
832 	assert(dev && dev->fd != -1);
833 
834 	assert(dev->open_count);
835 	if (--dev->open_count)
836 		return;
837 
838 	assert(!hosted());
839 	xf86GetEntityPrivate(dev->idx, intel_device_key)->ptr = NULL;
840 
841 	drmClose(dev->fd);
842 	if (dev->render_node != dev->master_node)
843 		free(dev->render_node);
844 	free(dev->master_node);
845 	free(dev);
846 }
847