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