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