1 /* 2 * Copyright 2012 Red Hat Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: Ben Skeggs 23 */ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <stdint.h> 28 #include <string.h> 29 #include <strings.h> 30 #include <stdbool.h> 31 #include <assert.h> 32 #include <errno.h> 33 #include <fcntl.h> 34 35 #include <xf86drm.h> 36 #include <xf86atomic.h> 37 #include "libdrm_macros.h" 38 #include "libdrm_lists.h" 39 #include "nouveau_drm.h" 40 41 #include "nouveau.h" 42 #include "private.h" 43 44 #include "nvif/class.h" 45 #include "nvif/cl0080.h" 46 #include "nvif/ioctl.h" 47 #include "nvif/unpack.h" 48 49 #ifdef DEBUG 50 drm_private uint32_t nouveau_debug = 0; 51 52 static void 53 debug_init(char *args) 54 { 55 if (args) { 56 int n = strtol(args, NULL, 0); 57 if (n >= 0) 58 nouveau_debug = n; 59 } 60 } 61 #endif 62 63 static int 64 nouveau_object_ioctl(struct nouveau_object *obj, void *data, uint32_t size) 65 { 66 struct nouveau_drm *drm = nouveau_drm(obj); 67 union { 68 struct nvif_ioctl_v0 v0; 69 } *args = data; 70 uint32_t argc = size; 71 int ret = -ENOSYS; 72 73 if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { 74 if (!obj->length) { 75 if (obj != &drm->client) 76 args->v0.object = (unsigned long)(void *)obj; 77 else 78 args->v0.object = 0; 79 args->v0.owner = NVIF_IOCTL_V0_OWNER_ANY; 80 args->v0.route = 0x00; 81 } else { 82 args->v0.route = 0xff; 83 args->v0.token = obj->handle; 84 } 85 } else 86 return ret; 87 88 return drmCommandWriteRead(drm->fd, DRM_NOUVEAU_NVIF, args, argc); 89 } 90 91 int 92 nouveau_object_mthd(struct nouveau_object *obj, 93 uint32_t mthd, void *data, uint32_t size) 94 { 95 struct nouveau_drm *drm = nouveau_drm(obj); 96 struct { 97 struct nvif_ioctl_v0 ioctl; 98 struct nvif_ioctl_mthd_v0 mthd; 99 } *args; 100 uint32_t argc = sizeof(*args) + size; 101 uint8_t stack[128]; 102 int ret; 103 104 if (!drm->nvif) 105 return -ENOSYS; 106 107 if (argc > sizeof(stack)) { 108 if (!(args = malloc(argc))) 109 return -ENOMEM; 110 } else { 111 args = (void *)stack; 112 } 113 args->ioctl.version = 0; 114 args->ioctl.type = NVIF_IOCTL_V0_MTHD; 115 args->mthd.version = 0; 116 args->mthd.method = mthd; 117 118 memcpy(args->mthd.data, data, size); 119 ret = nouveau_object_ioctl(obj, args, argc); 120 memcpy(data, args->mthd.data, size); 121 if (args != (void *)stack) 122 free(args); 123 return ret; 124 } 125 126 void 127 nouveau_object_sclass_put(struct nouveau_sclass **psclass) 128 { 129 free(*psclass); 130 *psclass = NULL; 131 } 132 133 int 134 nouveau_object_sclass_get(struct nouveau_object *obj, 135 struct nouveau_sclass **psclass) 136 { 137 struct nouveau_drm *drm = nouveau_drm(obj); 138 struct { 139 struct nvif_ioctl_v0 ioctl; 140 struct nvif_ioctl_sclass_v0 sclass; 141 } *args = NULL; 142 struct nouveau_sclass *sclass; 143 int ret, cnt = 0, i; 144 uint32_t size; 145 146 if (!drm->nvif) 147 return abi16_sclass(obj, psclass); 148 149 while (1) { 150 size = sizeof(*args) + cnt * sizeof(args->sclass.oclass[0]); 151 if (!(args = malloc(size))) 152 return -ENOMEM; 153 args->ioctl.version = 0; 154 args->ioctl.type = NVIF_IOCTL_V0_SCLASS; 155 args->sclass.version = 0; 156 args->sclass.count = cnt; 157 158 ret = nouveau_object_ioctl(obj, args, size); 159 if (ret == 0 && args->sclass.count <= cnt) 160 break; 161 cnt = args->sclass.count; 162 free(args); 163 if (ret != 0) 164 return ret; 165 } 166 167 if ((sclass = calloc(args->sclass.count, sizeof(*sclass)))) { 168 for (i = 0; i < args->sclass.count; i++) { 169 sclass[i].oclass = args->sclass.oclass[i].oclass; 170 sclass[i].minver = args->sclass.oclass[i].minver; 171 sclass[i].maxver = args->sclass.oclass[i].maxver; 172 } 173 *psclass = sclass; 174 ret = args->sclass.count; 175 } else { 176 ret = -ENOMEM; 177 } 178 179 free(args); 180 return ret; 181 } 182 183 int 184 nouveau_object_mclass(struct nouveau_object *obj, 185 const struct nouveau_mclass *mclass) 186 { 187 struct nouveau_sclass *sclass; 188 int ret = -ENODEV; 189 int cnt, i, j; 190 191 cnt = nouveau_object_sclass_get(obj, &sclass); 192 if (cnt < 0) 193 return cnt; 194 195 for (i = 0; ret < 0 && mclass[i].oclass; i++) { 196 for (j = 0; j < cnt; j++) { 197 if (mclass[i].oclass == sclass[j].oclass && 198 mclass[i].version >= sclass[j].minver && 199 mclass[i].version <= sclass[j].maxver) { 200 ret = i; 201 break; 202 } 203 } 204 } 205 206 nouveau_object_sclass_put(&sclass); 207 return ret; 208 } 209 210 static void 211 nouveau_object_fini(struct nouveau_object *obj) 212 { 213 struct { 214 struct nvif_ioctl_v0 ioctl; 215 struct nvif_ioctl_del del; 216 } args = { 217 .ioctl.type = NVIF_IOCTL_V0_DEL, 218 }; 219 220 if (obj->data) { 221 abi16_delete(obj); 222 free(obj->data); 223 obj->data = NULL; 224 return; 225 } 226 227 nouveau_object_ioctl(obj, &args, sizeof(args)); 228 } 229 230 static int 231 nouveau_object_init(struct nouveau_object *parent, uint32_t handle, 232 int32_t oclass, void *data, uint32_t size, 233 struct nouveau_object *obj) 234 { 235 struct nouveau_drm *drm = nouveau_drm(parent); 236 struct { 237 struct nvif_ioctl_v0 ioctl; 238 struct nvif_ioctl_new_v0 new; 239 } *args; 240 uint32_t argc = sizeof(*args) + size; 241 int (*func)(struct nouveau_object *); 242 int ret = -ENOSYS; 243 244 obj->parent = parent; 245 obj->handle = handle; 246 obj->oclass = oclass; 247 obj->length = 0; 248 obj->data = NULL; 249 250 if (!abi16_object(obj, &func) && drm->nvif) { 251 if (!(args = malloc(argc))) 252 return -ENOMEM; 253 args->ioctl.version = 0; 254 args->ioctl.type = NVIF_IOCTL_V0_NEW; 255 args->new.version = 0; 256 args->new.route = NVIF_IOCTL_V0_ROUTE_NVIF; 257 args->new.token = (unsigned long)(void *)obj; 258 args->new.object = (unsigned long)(void *)obj; 259 args->new.handle = handle; 260 args->new.oclass = oclass; 261 memcpy(args->new.data, data, size); 262 ret = nouveau_object_ioctl(parent, args, argc); 263 memcpy(data, args->new.data, size); 264 free(args); 265 } else 266 if (func) { 267 obj->length = size ? size : sizeof(struct nouveau_object *); 268 if (!(obj->data = malloc(obj->length))) 269 return -ENOMEM; 270 if (data) 271 memcpy(obj->data, data, obj->length); 272 *(struct nouveau_object **)obj->data = obj; 273 274 ret = func(obj); 275 } 276 277 if (ret) { 278 nouveau_object_fini(obj); 279 return ret; 280 } 281 282 return 0; 283 } 284 285 int 286 nouveau_object_new(struct nouveau_object *parent, uint64_t handle, 287 uint32_t oclass, void *data, uint32_t length, 288 struct nouveau_object **pobj) 289 { 290 struct nouveau_object *obj; 291 int ret; 292 293 if (!(obj = malloc(sizeof(*obj)))) 294 return -ENOMEM; 295 296 ret = nouveau_object_init(parent, handle, oclass, data, length, obj); 297 if (ret) { 298 free(obj); 299 return ret; 300 } 301 302 *pobj = obj; 303 return 0; 304 } 305 306 void 307 nouveau_object_del(struct nouveau_object **pobj) 308 { 309 struct nouveau_object *obj = *pobj; 310 if (obj) { 311 nouveau_object_fini(obj); 312 free(obj); 313 *pobj = NULL; 314 } 315 } 316 317 void 318 nouveau_drm_del(struct nouveau_drm **pdrm) 319 { 320 free(*pdrm); 321 *pdrm = NULL; 322 } 323 324 int 325 nouveau_drm_new(int fd, struct nouveau_drm **pdrm) 326 { 327 struct nouveau_drm *drm; 328 drmVersionPtr ver; 329 330 #ifdef DEBUG 331 debug_init(getenv("NOUVEAU_LIBDRM_DEBUG")); 332 #endif 333 334 if (!(drm = calloc(1, sizeof(*drm)))) 335 return -ENOMEM; 336 drm->fd = fd; 337 338 if (!(ver = drmGetVersion(fd))) { 339 nouveau_drm_del(&drm); 340 return -EINVAL; 341 } 342 *pdrm = drm; 343 344 drm->version = (ver->version_major << 24) | 345 (ver->version_minor << 8) | 346 ver->version_patchlevel; 347 drm->nvif = (drm->version >= 0x01000301); 348 drmFreeVersion(ver); 349 return 0; 350 } 351 352 /* this is the old libdrm's version of nouveau_device_wrap(), the symbol 353 * is kept here to prevent AIGLX from crashing if the DDX is linked against 354 * the new libdrm, but the DRI driver against the old 355 */ 356 int 357 nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd, 358 drm_context_t ctx) 359 { 360 return -EACCES; 361 } 362 363 int 364 nouveau_device_new(struct nouveau_object *parent, int32_t oclass, 365 void *data, uint32_t size, struct nouveau_device **pdev) 366 { 367 struct nv_device_info_v0 info = {}; 368 union { 369 struct nv_device_v0 v0; 370 } *args = data; 371 uint32_t argc = size; 372 struct nouveau_drm *drm = nouveau_drm(parent); 373 struct nouveau_device_priv *nvdev; 374 struct nouveau_device *dev; 375 uint64_t v; 376 char *tmp; 377 int ret = -ENOSYS; 378 379 if (oclass != NV_DEVICE || 380 nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)) 381 return ret; 382 383 if (!(nvdev = calloc(1, sizeof(*nvdev)))) 384 return -ENOMEM; 385 dev = *pdev = &nvdev->base; 386 dev->fd = -1; 387 388 if (drm->nvif) { 389 ret = nouveau_object_init(parent, 0, oclass, args, argc, 390 &dev->object); 391 if (ret) 392 goto done; 393 394 info.version = 0; 395 396 ret = nouveau_object_mthd(&dev->object, NV_DEVICE_V0_INFO, 397 &info, sizeof(info)); 398 if (ret) 399 goto done; 400 401 nvdev->base.chipset = info.chipset; 402 nvdev->have_bo_usage = true; 403 } else 404 if (args->v0.device == ~0ULL) { 405 nvdev->base.object.parent = &drm->client; 406 nvdev->base.object.handle = ~0ULL; 407 nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS; 408 nvdev->base.object.length = ~0; 409 410 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &v); 411 if (ret) 412 goto done; 413 nvdev->base.chipset = v; 414 415 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &v); 416 if (ret == 0) 417 nvdev->have_bo_usage = (v != 0); 418 } else 419 return -ENOSYS; 420 421 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &v); 422 if (ret) 423 goto done; 424 nvdev->base.vram_size = v; 425 426 ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &v); 427 if (ret) 428 goto done; 429 nvdev->base.gart_size = v; 430 431 tmp = getenv("NOUVEAU_LIBDRM_VRAM_LIMIT_PERCENT"); 432 if (tmp) 433 nvdev->vram_limit_percent = atoi(tmp); 434 else 435 nvdev->vram_limit_percent = 80; 436 437 nvdev->base.vram_limit = 438 (nvdev->base.vram_size * nvdev->vram_limit_percent) / 100; 439 440 tmp = getenv("NOUVEAU_LIBDRM_GART_LIMIT_PERCENT"); 441 if (tmp) 442 nvdev->gart_limit_percent = atoi(tmp); 443 else 444 nvdev->gart_limit_percent = 80; 445 446 nvdev->base.gart_limit = 447 (nvdev->base.gart_size * nvdev->gart_limit_percent) / 100; 448 449 ret = pthread_mutex_init(&nvdev->lock, NULL); 450 DRMINITLISTHEAD(&nvdev->bo_list); 451 done: 452 if (ret) 453 nouveau_device_del(pdev); 454 return ret; 455 } 456 457 int 458 nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev) 459 { 460 struct nouveau_drm *drm; 461 struct nouveau_device_priv *nvdev; 462 int ret; 463 464 ret = nouveau_drm_new(fd, &drm); 465 if (ret) 466 return ret; 467 drm->nvif = false; 468 469 ret = nouveau_device_new(&drm->client, NV_DEVICE, 470 &(struct nv_device_v0) { 471 .device = ~0ULL, 472 }, sizeof(struct nv_device_v0), pdev); 473 if (ret) { 474 nouveau_drm_del(&drm); 475 return ret; 476 } 477 478 nvdev = nouveau_device(*pdev); 479 nvdev->base.fd = drm->fd; 480 nvdev->base.drm_version = drm->version; 481 nvdev->close = close; 482 return 0; 483 } 484 485 int 486 nouveau_device_open(const char *busid, struct nouveau_device **pdev) 487 { 488 int ret = -ENODEV, fd = drmOpen("nouveau", busid); 489 if (fd >= 0) { 490 ret = nouveau_device_wrap(fd, 1, pdev); 491 if (ret) 492 drmClose(fd); 493 } 494 return ret; 495 } 496 497 void 498 nouveau_device_del(struct nouveau_device **pdev) 499 { 500 struct nouveau_device_priv *nvdev = nouveau_device(*pdev); 501 if (nvdev) { 502 free(nvdev->client); 503 pthread_mutex_destroy(&nvdev->lock); 504 if (nvdev->base.fd >= 0) { 505 struct nouveau_drm *drm = 506 nouveau_drm(&nvdev->base.object); 507 nouveau_drm_del(&drm); 508 if (nvdev->close) 509 drmClose(nvdev->base.fd); 510 } 511 free(nvdev); 512 *pdev = NULL; 513 } 514 } 515 516 int 517 nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value) 518 { 519 struct nouveau_drm *drm = nouveau_drm(&dev->object); 520 struct drm_nouveau_getparam r = { .param = param }; 521 int fd = drm->fd, ret = 522 drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r)); 523 *value = r.value; 524 return ret; 525 } 526 527 int 528 nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value) 529 { 530 struct nouveau_drm *drm = nouveau_drm(&dev->object); 531 struct drm_nouveau_setparam r = { .param = param, .value = value }; 532 return drmCommandWrite(drm->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r)); 533 } 534 535 int 536 nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient) 537 { 538 struct nouveau_device_priv *nvdev = nouveau_device(dev); 539 struct nouveau_client_priv *pcli; 540 int id = 0, i, ret = -ENOMEM; 541 uint32_t *clients; 542 543 pthread_mutex_lock(&nvdev->lock); 544 545 for (i = 0; i < nvdev->nr_client; i++) { 546 id = ffs(nvdev->client[i]) - 1; 547 if (id >= 0) 548 goto out; 549 } 550 551 clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1)); 552 if (!clients) 553 goto unlock; 554 nvdev->client = clients; 555 nvdev->client[i] = 0; 556 nvdev->nr_client++; 557 558 out: 559 pcli = calloc(1, sizeof(*pcli)); 560 if (pcli) { 561 nvdev->client[i] |= (1 << id); 562 pcli->base.device = dev; 563 pcli->base.id = (i * 32) + id; 564 ret = 0; 565 } 566 567 *pclient = &pcli->base; 568 569 unlock: 570 pthread_mutex_unlock(&nvdev->lock); 571 return ret; 572 } 573 574 void 575 nouveau_client_del(struct nouveau_client **pclient) 576 { 577 struct nouveau_client_priv *pcli = nouveau_client(*pclient); 578 struct nouveau_device_priv *nvdev; 579 if (pcli) { 580 int id = pcli->base.id; 581 nvdev = nouveau_device(pcli->base.device); 582 pthread_mutex_lock(&nvdev->lock); 583 nvdev->client[id / 32] &= ~(1 << (id % 32)); 584 pthread_mutex_unlock(&nvdev->lock); 585 free(pcli->kref); 586 free(pcli); 587 } 588 } 589 590 static void 591 nouveau_bo_del(struct nouveau_bo *bo) 592 { 593 struct nouveau_drm *drm = nouveau_drm(&bo->device->object); 594 struct nouveau_device_priv *nvdev = nouveau_device(bo->device); 595 struct nouveau_bo_priv *nvbo = nouveau_bo(bo); 596 struct drm_gem_close req = { .handle = bo->handle }; 597 598 if (nvbo->head.next) { 599 pthread_mutex_lock(&nvdev->lock); 600 if (atomic_read(&nvbo->refcnt) == 0) { 601 DRMLISTDEL(&nvbo->head); 602 /* 603 * This bo has to be closed with the lock held because 604 * gem handles are not refcounted. If a shared bo is 605 * closed and re-opened in another thread a race 606 * against DRM_IOCTL_GEM_OPEN or drmPrimeFDToHandle 607 * might cause the bo to be closed accidentally while 608 * re-importing. 609 */ 610 drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &req); 611 } 612 pthread_mutex_unlock(&nvdev->lock); 613 } else { 614 drmIoctl(drm->fd, DRM_IOCTL_GEM_CLOSE, &req); 615 } 616 if (bo->map) 617 drm_munmap(bo->map, bo->size); 618 free(nvbo); 619 } 620 621 int 622 nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align, 623 uint64_t size, union nouveau_bo_config *config, 624 struct nouveau_bo **pbo) 625 { 626 struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo)); 627 struct nouveau_bo *bo = &nvbo->base; 628 int ret; 629 630 if (!nvbo) 631 return -ENOMEM; 632 atomic_set(&nvbo->refcnt, 1); 633 bo->device = dev; 634 bo->flags = flags; 635 bo->size = size; 636 637 ret = abi16_bo_init(bo, align, config); 638 if (ret) { 639 free(nvbo); 640 return ret; 641 } 642 643 *pbo = bo; 644 return 0; 645 } 646 647 static int 648 nouveau_bo_wrap_locked(struct nouveau_device *dev, uint32_t handle, 649 struct nouveau_bo **pbo, int name) 650 { 651 struct nouveau_drm *drm = nouveau_drm(&dev->object); 652 struct nouveau_device_priv *nvdev = nouveau_device(dev); 653 struct drm_nouveau_gem_info req = { .handle = handle }; 654 struct nouveau_bo_priv *nvbo; 655 int ret; 656 657 DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) { 658 if (nvbo->base.handle == handle) { 659 if (atomic_inc_return(&nvbo->refcnt) == 1) { 660 /* 661 * Uh oh, this bo is dead and someone else 662 * will free it, but because refcnt is 663 * now non-zero fortunately they won't 664 * call the ioctl to close the bo. 665 * 666 * Remove this bo from the list so other 667 * calls to nouveau_bo_wrap_locked will 668 * see our replacement nvbo. 669 */ 670 DRMLISTDEL(&nvbo->head); 671 if (!name) 672 name = nvbo->name; 673 break; 674 } 675 676 *pbo = &nvbo->base; 677 return 0; 678 } 679 } 680 681 ret = drmCommandWriteRead(drm->fd, DRM_NOUVEAU_GEM_INFO, 682 &req, sizeof(req)); 683 if (ret) 684 return ret; 685 686 nvbo = calloc(1, sizeof(*nvbo)); 687 if (nvbo) { 688 atomic_set(&nvbo->refcnt, 1); 689 nvbo->base.device = dev; 690 abi16_bo_info(&nvbo->base, &req); 691 nvbo->name = name; 692 DRMLISTADD(&nvbo->head, &nvdev->bo_list); 693 *pbo = &nvbo->base; 694 return 0; 695 } 696 697 return -ENOMEM; 698 } 699 700 static void 701 nouveau_bo_make_global(struct nouveau_bo_priv *nvbo) 702 { 703 if (!nvbo->head.next) { 704 struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device); 705 pthread_mutex_lock(&nvdev->lock); 706 if (!nvbo->head.next) 707 DRMLISTADD(&nvbo->head, &nvdev->bo_list); 708 pthread_mutex_unlock(&nvdev->lock); 709 } 710 } 711 712 int 713 nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle, 714 struct nouveau_bo **pbo) 715 { 716 struct nouveau_device_priv *nvdev = nouveau_device(dev); 717 int ret; 718 pthread_mutex_lock(&nvdev->lock); 719 ret = nouveau_bo_wrap_locked(dev, handle, pbo, 0); 720 pthread_mutex_unlock(&nvdev->lock); 721 return ret; 722 } 723 724 int 725 nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name, 726 struct nouveau_bo **pbo) 727 { 728 struct nouveau_drm *drm = nouveau_drm(&dev->object); 729 struct nouveau_device_priv *nvdev = nouveau_device(dev); 730 struct nouveau_bo_priv *nvbo; 731 struct drm_gem_open req = { .name = name }; 732 int ret; 733 734 pthread_mutex_lock(&nvdev->lock); 735 DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) { 736 if (nvbo->name == name) { 737 ret = nouveau_bo_wrap_locked(dev, nvbo->base.handle, 738 pbo, name); 739 pthread_mutex_unlock(&nvdev->lock); 740 return ret; 741 } 742 } 743 744 ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_OPEN, &req); 745 if (ret == 0) { 746 ret = nouveau_bo_wrap_locked(dev, req.handle, pbo, name); 747 } 748 749 pthread_mutex_unlock(&nvdev->lock); 750 return ret; 751 } 752 753 int 754 nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name) 755 { 756 struct drm_gem_flink req = { .handle = bo->handle }; 757 struct nouveau_drm *drm = nouveau_drm(&bo->device->object); 758 struct nouveau_bo_priv *nvbo = nouveau_bo(bo); 759 760 *name = nvbo->name; 761 if (!*name) { 762 int ret = drmIoctl(drm->fd, DRM_IOCTL_GEM_FLINK, &req); 763 764 if (ret) { 765 *name = 0; 766 return ret; 767 } 768 nvbo->name = *name = req.name; 769 770 nouveau_bo_make_global(nvbo); 771 } 772 return 0; 773 } 774 775 void 776 nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref) 777 { 778 struct nouveau_bo *ref = *pref; 779 if (bo) { 780 atomic_inc(&nouveau_bo(bo)->refcnt); 781 } 782 if (ref) { 783 if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt)) 784 nouveau_bo_del(ref); 785 } 786 *pref = bo; 787 } 788 789 int 790 nouveau_bo_prime_handle_ref(struct nouveau_device *dev, int prime_fd, 791 struct nouveau_bo **bo) 792 { 793 struct nouveau_drm *drm = nouveau_drm(&dev->object); 794 struct nouveau_device_priv *nvdev = nouveau_device(dev); 795 int ret; 796 unsigned int handle; 797 798 nouveau_bo_ref(NULL, bo); 799 800 pthread_mutex_lock(&nvdev->lock); 801 ret = drmPrimeFDToHandle(drm->fd, prime_fd, &handle); 802 if (ret == 0) { 803 ret = nouveau_bo_wrap_locked(dev, handle, bo, 0); 804 } 805 pthread_mutex_unlock(&nvdev->lock); 806 return ret; 807 } 808 809 int 810 nouveau_bo_set_prime(struct nouveau_bo *bo, int *prime_fd) 811 { 812 struct nouveau_drm *drm = nouveau_drm(&bo->device->object); 813 struct nouveau_bo_priv *nvbo = nouveau_bo(bo); 814 int ret; 815 816 ret = drmPrimeHandleToFD(drm->fd, nvbo->base.handle, DRM_CLOEXEC, prime_fd); 817 if (ret) 818 return ret; 819 820 nouveau_bo_make_global(nvbo); 821 return 0; 822 } 823 824 int 825 nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access, 826 struct nouveau_client *client) 827 { 828 struct nouveau_drm *drm = nouveau_drm(&bo->device->object); 829 struct nouveau_bo_priv *nvbo = nouveau_bo(bo); 830 struct drm_nouveau_gem_cpu_prep req; 831 struct nouveau_pushbuf *push; 832 int ret = 0; 833 834 if (!(access & NOUVEAU_BO_RDWR)) 835 return 0; 836 837 push = cli_push_get(client, bo); 838 if (push && push->channel) 839 nouveau_pushbuf_kick(push, push->channel); 840 841 if (!nvbo->head.next && !(nvbo->access & NOUVEAU_BO_WR) && 842 !(access & NOUVEAU_BO_WR)) 843 return 0; 844 845 req.handle = bo->handle; 846 req.flags = 0; 847 if (access & NOUVEAU_BO_WR) 848 req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE; 849 if (access & NOUVEAU_BO_NOBLOCK) 850 req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT; 851 852 ret = drmCommandWrite(drm->fd, DRM_NOUVEAU_GEM_CPU_PREP, 853 &req, sizeof(req)); 854 if (ret == 0) 855 nvbo->access = 0; 856 return ret; 857 } 858 859 int 860 nouveau_bo_map(struct nouveau_bo *bo, uint32_t access, 861 struct nouveau_client *client) 862 { 863 struct nouveau_drm *drm = nouveau_drm(&bo->device->object); 864 struct nouveau_bo_priv *nvbo = nouveau_bo(bo); 865 if (bo->map == NULL) { 866 bo->map = drm_mmap(0, bo->size, PROT_READ | PROT_WRITE, 867 MAP_SHARED, drm->fd, nvbo->map_handle); 868 if (bo->map == MAP_FAILED) { 869 bo->map = NULL; 870 return -errno; 871 } 872 } 873 return nouveau_bo_wait(bo, access, client); 874 } 875