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