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