1 /* $NetBSD: nouveau_gem.c,v 1.14 2022/05/31 00:17:10 riastradh Exp $ */ 2 3 /* 4 * Copyright (C) 2008 Ben Skeggs. 5 * All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the 16 * next paragraph) shall be included in all copies or substantial 17 * portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 23 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 25 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 * 27 */ 28 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: nouveau_gem.c,v 1.14 2022/05/31 00:17:10 riastradh Exp $"); 31 32 #include <asm/uaccess.h> 33 34 #include "nouveau_drv.h" 35 #include "nouveau_dma.h" 36 #include "nouveau_fence.h" 37 #include "nouveau_abi16.h" 38 39 #include "nouveau_ttm.h" 40 #include "nouveau_gem.h" 41 #include "nouveau_mem.h" 42 #include "nouveau_vmm.h" 43 44 #include <nvif/class.h> 45 46 #include <linux/nbsd-namespace.h> 47 48 void 49 nouveau_gem_object_del(struct drm_gem_object *gem) 50 { 51 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 52 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 53 struct device *dev = drm->dev->dev; 54 int ret; 55 56 ret = pm_runtime_get_sync(dev); 57 if (WARN_ON(ret < 0 && ret != -EACCES)) 58 return; 59 60 if (gem->import_attach) 61 drm_prime_gem_destroy(gem, nvbo->bo.sg); 62 63 ttm_bo_put(&nvbo->bo); 64 65 pm_runtime_mark_last_busy(dev); 66 pm_runtime_put_autosuspend(dev); 67 } 68 69 int 70 nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) 71 { 72 struct nouveau_cli *cli = nouveau_cli(file_priv); 73 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 74 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 75 struct device *dev = drm->dev->dev; 76 struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; 77 struct nouveau_vma *vma; 78 int ret; 79 80 if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) 81 return 0; 82 83 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); 84 if (ret) 85 return ret; 86 87 ret = pm_runtime_get_sync(dev); 88 if (ret < 0 && ret != -EACCES) 89 goto out; 90 91 ret = nouveau_vma_new(nvbo, vmm, &vma); 92 pm_runtime_mark_last_busy(dev); 93 pm_runtime_put_autosuspend(dev); 94 out: 95 ttm_bo_unreserve(&nvbo->bo); 96 return ret; 97 } 98 99 struct nouveau_gem_object_unmap { 100 struct nouveau_cli_work work; 101 struct nouveau_vma *vma; 102 }; 103 104 static void 105 nouveau_gem_object_delete(struct nouveau_vma *vma) 106 { 107 nouveau_fence_unref(&vma->fence); 108 nouveau_vma_del(&vma); 109 } 110 111 static void 112 nouveau_gem_object_delete_work(struct nouveau_cli_work *w) 113 { 114 struct nouveau_gem_object_unmap *work = 115 container_of(w, typeof(*work), work); 116 nouveau_gem_object_delete(work->vma); 117 kfree(work); 118 } 119 120 static void 121 nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma) 122 { 123 struct dma_fence *fence = vma->fence ? &vma->fence->base : NULL; 124 struct nouveau_gem_object_unmap *work; 125 126 list_del_init(&vma->head); 127 128 if (!fence) { 129 nouveau_gem_object_delete(vma); 130 return; 131 } 132 133 if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) { 134 WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0); 135 nouveau_gem_object_delete(vma); 136 return; 137 } 138 139 work->work.func = nouveau_gem_object_delete_work; 140 work->vma = vma; 141 nouveau_cli_work_queue(vma->vmm->cli, fence, &work->work); 142 } 143 144 void 145 nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) 146 { 147 struct nouveau_cli *cli = nouveau_cli(file_priv); 148 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 149 struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); 150 struct device *dev = drm->dev->dev; 151 struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : & cli->vmm; 152 struct nouveau_vma *vma; 153 int ret; 154 155 if (vmm->vmm.object.oclass < NVIF_CLASS_VMM_NV50) 156 return; 157 158 ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); 159 if (ret) 160 return; 161 162 vma = nouveau_vma_find(nvbo, vmm); 163 if (vma) { 164 if (--vma->refs == 0) { 165 ret = pm_runtime_get_sync(dev); 166 if (!WARN_ON(ret < 0 && ret != -EACCES)) { 167 nouveau_gem_object_unmap(nvbo, vma); 168 pm_runtime_mark_last_busy(dev); 169 pm_runtime_put_autosuspend(dev); 170 } 171 } 172 } 173 ttm_bo_unreserve(&nvbo->bo); 174 } 175 176 int 177 nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, 178 uint32_t tile_mode, uint32_t tile_flags, 179 struct nouveau_bo **pnvbo) 180 { 181 struct nouveau_drm *drm = cli->drm; 182 struct nouveau_bo *nvbo; 183 u32 flags = 0; 184 int ret; 185 186 if (domain & NOUVEAU_GEM_DOMAIN_VRAM) 187 flags |= TTM_PL_FLAG_VRAM; 188 if (domain & NOUVEAU_GEM_DOMAIN_GART) 189 flags |= TTM_PL_FLAG_TT; 190 if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU) 191 flags |= TTM_PL_FLAG_SYSTEM; 192 193 if (domain & NOUVEAU_GEM_DOMAIN_COHERENT) 194 flags |= TTM_PL_FLAG_UNCACHED; 195 196 nvbo = nouveau_bo_alloc(cli, &size, &align, flags, tile_mode, 197 tile_flags); 198 if (IS_ERR(nvbo)) 199 return PTR_ERR(nvbo); 200 201 /* Initialize the embedded gem-object. We return a single gem-reference 202 * to the caller, instead of a normal nouveau_bo ttm reference. */ 203 ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, size); 204 if (ret) { 205 kfree(nvbo); 206 return ret; 207 } 208 209 ret = nouveau_bo_init(nvbo, size, align, flags, NULL, NULL); 210 if (ret) { 211 /* XXX note: if this fails it kfrees nvbo */ 212 return ret; 213 } 214 215 /* we restrict allowed domains on nv50+ to only the types 216 * that were requested at creation time. not possibly on 217 * earlier chips without busting the ABI. 218 */ 219 nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | 220 NOUVEAU_GEM_DOMAIN_GART; 221 if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) 222 nvbo->valid_domains &= domain; 223 224 #ifndef __NetBSD__ /* XXX Let TTM swap; skip GEM like radeon. */ 225 nvbo->bo.persistent_swap_storage = nvbo->bo.base.filp; 226 #endif 227 *pnvbo = nvbo; 228 return 0; 229 } 230 231 static int 232 nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, 233 struct drm_nouveau_gem_info *rep) 234 { 235 struct nouveau_cli *cli = nouveau_cli(file_priv); 236 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 237 struct nouveau_vmm *vmm = cli->svm.cli ? &cli->svm : &cli->vmm; 238 struct nouveau_vma *vma; 239 240 if (is_power_of_2(nvbo->valid_domains)) 241 rep->domain = nvbo->valid_domains; 242 else if (nvbo->bo.mem.mem_type == TTM_PL_TT) 243 rep->domain = NOUVEAU_GEM_DOMAIN_GART; 244 else 245 rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; 246 rep->offset = nvbo->bo.offset; 247 if (vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 248 vma = nouveau_vma_find(nvbo, vmm); 249 if (!vma) 250 return -EINVAL; 251 252 rep->offset = vma->addr; 253 } 254 255 rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; 256 rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node); 257 rep->tile_mode = nvbo->mode; 258 rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG; 259 if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) 260 rep->tile_flags |= nvbo->kind << 8; 261 else 262 if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) 263 rep->tile_flags |= nvbo->kind << 8 | nvbo->comp << 16; 264 else 265 rep->tile_flags |= nvbo->zeta; 266 return 0; 267 } 268 269 int 270 nouveau_gem_ioctl_new(struct drm_device *dev, void *data, 271 struct drm_file *file_priv) 272 { 273 struct nouveau_cli *cli = nouveau_cli(file_priv); 274 struct drm_nouveau_gem_new *req = data; 275 struct nouveau_bo *nvbo = NULL; 276 int ret = 0; 277 278 ret = nouveau_gem_new(cli, req->info.size, req->align, 279 req->info.domain, req->info.tile_mode, 280 req->info.tile_flags, &nvbo); 281 if (ret) 282 return ret; 283 284 ret = drm_gem_handle_create(file_priv, &nvbo->bo.base, 285 &req->info.handle); 286 if (ret == 0) { 287 ret = nouveau_gem_info(file_priv, &nvbo->bo.base, &req->info); 288 if (ret) 289 drm_gem_handle_delete(file_priv, req->info.handle); 290 } 291 292 /* drop reference from allocate - handle holds it now */ 293 drm_gem_object_put_unlocked(&nvbo->bo.base); 294 return ret; 295 } 296 297 static int 298 nouveau_gem_set_domain(struct drm_gem_object *gem, uint32_t read_domains, 299 uint32_t write_domains, uint32_t valid_domains) 300 { 301 struct nouveau_bo *nvbo = nouveau_gem_object(gem); 302 struct ttm_buffer_object *bo = &nvbo->bo; 303 uint32_t domains = valid_domains & nvbo->valid_domains & 304 (write_domains ? write_domains : read_domains); 305 uint32_t pref_flags = 0, valid_flags = 0; 306 307 if (!domains) 308 return -EINVAL; 309 310 if (valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) 311 valid_flags |= TTM_PL_FLAG_VRAM; 312 313 if (valid_domains & NOUVEAU_GEM_DOMAIN_GART) 314 valid_flags |= TTM_PL_FLAG_TT; 315 316 if ((domains & NOUVEAU_GEM_DOMAIN_VRAM) && 317 bo->mem.mem_type == TTM_PL_VRAM) 318 pref_flags |= TTM_PL_FLAG_VRAM; 319 320 else if ((domains & NOUVEAU_GEM_DOMAIN_GART) && 321 bo->mem.mem_type == TTM_PL_TT) 322 pref_flags |= TTM_PL_FLAG_TT; 323 324 else if (domains & NOUVEAU_GEM_DOMAIN_VRAM) 325 pref_flags |= TTM_PL_FLAG_VRAM; 326 327 else 328 pref_flags |= TTM_PL_FLAG_TT; 329 330 nouveau_bo_placement_set(nvbo, pref_flags, valid_flags); 331 332 return 0; 333 } 334 335 struct validate_op { 336 struct list_head list; 337 struct ww_acquire_ctx ticket; 338 }; 339 340 static void 341 validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan, 342 struct nouveau_fence *fence, 343 struct drm_nouveau_gem_pushbuf_bo *pbbo) 344 { 345 struct nouveau_bo *nvbo; 346 struct drm_nouveau_gem_pushbuf_bo *b; 347 348 while (!list_empty(&op->list)) { 349 nvbo = list_entry(op->list.next, struct nouveau_bo, entry); 350 b = &pbbo[nvbo->pbbo_index]; 351 352 if (likely(fence)) { 353 nouveau_bo_fence(nvbo, fence, !!b->write_domains); 354 355 if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 356 struct nouveau_vma *vma = 357 (void *)(unsigned long)b->user_priv; 358 nouveau_fence_unref(&vma->fence); 359 dma_fence_get(&fence->base); 360 vma->fence = fence; 361 } 362 } 363 364 if (unlikely(nvbo->validate_mapped)) { 365 ttm_bo_kunmap(&nvbo->kmap); 366 nvbo->validate_mapped = false; 367 } 368 369 list_del(&nvbo->entry); 370 nvbo->reserved_by = NULL; 371 ttm_bo_unreserve(&nvbo->bo); 372 drm_gem_object_put_unlocked(&nvbo->bo.base); 373 } 374 } 375 376 static void 377 validate_fini(struct validate_op *op, struct nouveau_channel *chan, 378 struct nouveau_fence *fence, 379 struct drm_nouveau_gem_pushbuf_bo *pbbo) 380 { 381 validate_fini_no_ticket(op, chan, fence, pbbo); 382 ww_acquire_fini(&op->ticket); 383 } 384 385 static int 386 validate_init(struct nouveau_channel *chan, struct drm_file *file_priv, 387 struct drm_nouveau_gem_pushbuf_bo *pbbo, 388 int nr_buffers, struct validate_op *op) 389 { 390 struct nouveau_cli *cli = nouveau_cli(file_priv); 391 int trycnt = 0; 392 int ret = -EINVAL, i; 393 struct nouveau_bo *res_bo = NULL; 394 LIST_HEAD(gart_list); 395 LIST_HEAD(vram_list); 396 LIST_HEAD(both_list); 397 398 ww_acquire_init(&op->ticket, &reservation_ww_class); 399 retry: 400 if (++trycnt > 100000) { 401 NV_PRINTK(err, cli, "%s failed and gave up.\n", __func__); 402 return -EINVAL; 403 } 404 405 for (i = 0; i < nr_buffers; i++) { 406 struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[i]; 407 struct drm_gem_object *gem; 408 struct nouveau_bo *nvbo; 409 410 gem = drm_gem_object_lookup(file_priv, b->handle); 411 if (!gem) { 412 NV_PRINTK(err, cli, "Unknown handle 0x%08x\n", b->handle); 413 ret = -ENOENT; 414 break; 415 } 416 nvbo = nouveau_gem_object(gem); 417 if (nvbo == res_bo) { 418 res_bo = NULL; 419 drm_gem_object_put_unlocked(gem); 420 continue; 421 } 422 423 if (nvbo->reserved_by && nvbo->reserved_by == file_priv) { 424 NV_PRINTK(err, cli, "multiple instances of buffer %d on " 425 "validation list\n", b->handle); 426 drm_gem_object_put_unlocked(gem); 427 ret = -EINVAL; 428 break; 429 } 430 431 ret = ttm_bo_reserve(&nvbo->bo, true, false, &op->ticket); 432 if (ret) { 433 list_splice_tail_init(&vram_list, &op->list); 434 list_splice_tail_init(&gart_list, &op->list); 435 list_splice_tail_init(&both_list, &op->list); 436 validate_fini_no_ticket(op, chan, NULL, NULL); 437 if (unlikely(ret == -EDEADLK)) { 438 ret = ttm_bo_reserve_slowpath(&nvbo->bo, true, 439 &op->ticket); 440 if (!ret) 441 res_bo = nvbo; 442 } 443 if (unlikely(ret)) { 444 if (ret != -ERESTARTSYS) 445 NV_PRINTK(err, cli, "fail reserve\n"); 446 break; 447 } 448 } 449 450 if (chan->vmm->vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { 451 struct nouveau_vmm *vmm = chan->vmm; 452 struct nouveau_vma *vma = nouveau_vma_find(nvbo, vmm); 453 if (!vma) { 454 NV_PRINTK(err, cli, "vma not found!\n"); 455 ret = -EINVAL; 456 break; 457 } 458 459 b->user_priv = (uint64_t)(unsigned long)vma; 460 } else { 461 b->user_priv = (uint64_t)(unsigned long)nvbo; 462 } 463 464 nvbo->reserved_by = file_priv; 465 nvbo->pbbo_index = i; 466 if ((b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) && 467 (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART)) 468 list_add_tail(&nvbo->entry, &both_list); 469 else 470 if (b->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) 471 list_add_tail(&nvbo->entry, &vram_list); 472 else 473 if (b->valid_domains & NOUVEAU_GEM_DOMAIN_GART) 474 list_add_tail(&nvbo->entry, &gart_list); 475 else { 476 NV_PRINTK(err, cli, "invalid valid domains: 0x%08x\n", 477 b->valid_domains); 478 list_add_tail(&nvbo->entry, &both_list); 479 ret = -EINVAL; 480 break; 481 } 482 if (nvbo == res_bo) 483 goto retry; 484 } 485 486 ww_acquire_done(&op->ticket); 487 list_splice_tail(&vram_list, &op->list); 488 list_splice_tail(&gart_list, &op->list); 489 list_splice_tail(&both_list, &op->list); 490 if (ret) 491 validate_fini(op, chan, NULL, NULL); 492 return ret; 493 494 } 495 496 #ifdef __NetBSD__ /* XXX yargleblargh */ 497 # define __force 498 #endif 499 500 static int 501 validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, 502 struct list_head *list, struct drm_nouveau_gem_pushbuf_bo *pbbo) 503 { 504 struct nouveau_drm *drm = chan->drm; 505 struct nouveau_bo *nvbo; 506 int ret, relocs = 0; 507 508 list_for_each_entry(nvbo, list, entry) { 509 struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; 510 511 ret = nouveau_gem_set_domain(&nvbo->bo.base, b->read_domains, 512 b->write_domains, 513 b->valid_domains); 514 if (unlikely(ret)) { 515 NV_PRINTK(err, cli, "fail set_domain\n"); 516 return ret; 517 } 518 519 ret = nouveau_bo_validate(nvbo, true, false); 520 if (unlikely(ret)) { 521 if (ret != -ERESTARTSYS) 522 NV_PRINTK(err, cli, "fail ttm_validate\n"); 523 return ret; 524 } 525 526 ret = nouveau_fence_sync(nvbo, chan, !!b->write_domains, true); 527 if (unlikely(ret)) { 528 if (ret != -ERESTARTSYS) 529 NV_PRINTK(err, cli, "fail post-validate sync\n"); 530 return ret; 531 } 532 533 if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA) { 534 if (nvbo->bo.offset == b->presumed.offset && 535 ((nvbo->bo.mem.mem_type == TTM_PL_VRAM && 536 b->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM) || 537 (nvbo->bo.mem.mem_type == TTM_PL_TT && 538 b->presumed.domain & NOUVEAU_GEM_DOMAIN_GART))) 539 continue; 540 541 if (nvbo->bo.mem.mem_type == TTM_PL_TT) 542 b->presumed.domain = NOUVEAU_GEM_DOMAIN_GART; 543 else 544 b->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM; 545 b->presumed.offset = nvbo->bo.offset; 546 b->presumed.valid = 0; 547 relocs++; 548 } 549 } 550 551 return relocs; 552 } 553 554 static int 555 nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, 556 struct drm_file *file_priv, 557 struct drm_nouveau_gem_pushbuf_bo *pbbo, 558 int nr_buffers, 559 struct validate_op *op, bool *apply_relocs) 560 { 561 struct nouveau_cli *cli = nouveau_cli(file_priv); 562 int ret; 563 564 INIT_LIST_HEAD(&op->list); 565 566 if (nr_buffers == 0) 567 return 0; 568 569 ret = validate_init(chan, file_priv, pbbo, nr_buffers, op); 570 if (unlikely(ret)) { 571 if (ret != -ERESTARTSYS) 572 NV_PRINTK(err, cli, "validate_init\n"); 573 return ret; 574 } 575 576 ret = validate_list(chan, cli, &op->list, pbbo); 577 if (unlikely(ret < 0)) { 578 if (ret != -ERESTARTSYS) 579 NV_PRINTK(err, cli, "validating bo list\n"); 580 validate_fini(op, chan, NULL, NULL); 581 return ret; 582 } 583 *apply_relocs = ret; 584 return 0; 585 } 586 587 static inline void 588 u_free(void *addr) 589 { 590 kvfree(addr); 591 } 592 593 static inline void * 594 u_memcpya(uint64_t user, unsigned nmemb, unsigned size) 595 { 596 void *mem; 597 void __user *userptr = (void __force __user *)(uintptr_t)user; 598 599 size *= nmemb; 600 601 mem = kvmalloc(size, GFP_KERNEL); 602 if (!mem) 603 return ERR_PTR(-ENOMEM); 604 605 if (copy_from_user(mem, userptr, size)) { 606 u_free(mem); 607 return ERR_PTR(-EFAULT); 608 } 609 610 return mem; 611 } 612 613 static int 614 nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, 615 struct drm_nouveau_gem_pushbuf *req, 616 struct drm_nouveau_gem_pushbuf_reloc *reloc, 617 struct drm_nouveau_gem_pushbuf_bo *bo) 618 { 619 int ret = 0; 620 unsigned i; 621 622 for (i = 0; i < req->nr_relocs; i++) { 623 struct drm_nouveau_gem_pushbuf_reloc *r = &reloc[i]; 624 struct drm_nouveau_gem_pushbuf_bo *b; 625 struct nouveau_bo *nvbo; 626 uint32_t data; 627 628 if (unlikely(r->bo_index >= req->nr_buffers)) { 629 NV_PRINTK(err, cli, "reloc bo index invalid\n"); 630 ret = -EINVAL; 631 break; 632 } 633 634 b = &bo[r->bo_index]; 635 if (b->presumed.valid) 636 continue; 637 638 if (unlikely(r->reloc_bo_index >= req->nr_buffers)) { 639 NV_PRINTK(err, cli, "reloc container bo index invalid\n"); 640 ret = -EINVAL; 641 break; 642 } 643 nvbo = (void *)(unsigned long)bo[r->reloc_bo_index].user_priv; 644 645 if (unlikely(r->reloc_bo_offset + 4 > 646 nvbo->bo.mem.num_pages << PAGE_SHIFT)) { 647 NV_PRINTK(err, cli, "reloc outside of bo\n"); 648 ret = -EINVAL; 649 break; 650 } 651 652 if (!nvbo->kmap.virtual) { 653 ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.mem.num_pages, 654 &nvbo->kmap); 655 if (ret) { 656 NV_PRINTK(err, cli, "failed kmap for reloc\n"); 657 break; 658 } 659 nvbo->validate_mapped = true; 660 } 661 662 if (r->flags & NOUVEAU_GEM_RELOC_LOW) 663 data = b->presumed.offset + r->data; 664 else 665 if (r->flags & NOUVEAU_GEM_RELOC_HIGH) 666 data = (b->presumed.offset + r->data) >> 32; 667 else 668 data = r->data; 669 670 if (r->flags & NOUVEAU_GEM_RELOC_OR) { 671 if (b->presumed.domain == NOUVEAU_GEM_DOMAIN_GART) 672 data |= r->tor; 673 else 674 data |= r->vor; 675 } 676 677 ret = ttm_bo_wait(&nvbo->bo, false, false); 678 if (ret) { 679 NV_PRINTK(err, cli, "reloc wait_idle failed: %d\n", ret); 680 break; 681 } 682 683 nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); 684 } 685 686 u_free(reloc); 687 return ret; 688 } 689 690 int 691 nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, 692 struct drm_file *file_priv) 693 { 694 struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv); 695 struct nouveau_cli *cli = nouveau_cli(file_priv); 696 struct nouveau_abi16_chan *temp; 697 struct nouveau_drm *drm = nouveau_drm(dev); 698 struct drm_nouveau_gem_pushbuf *req = data; 699 struct drm_nouveau_gem_pushbuf_push *push; 700 struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; 701 struct drm_nouveau_gem_pushbuf_bo *bo; 702 struct nouveau_channel *chan = NULL; 703 struct validate_op op; 704 struct nouveau_fence *fence = NULL; 705 int i, j, ret = 0; 706 bool do_reloc = false, sync = false; 707 708 if (unlikely(!abi16)) 709 return -ENOMEM; 710 711 list_for_each_entry(temp, &abi16->channels, head) { 712 if (temp->chan->chid == req->channel) { 713 chan = temp->chan; 714 break; 715 } 716 } 717 718 if (!chan) 719 return nouveau_abi16_put(abi16, -ENOENT); 720 if (unlikely(atomic_read(&chan->killed))) 721 return nouveau_abi16_put(abi16, -ENODEV); 722 723 sync = req->vram_available & NOUVEAU_GEM_PUSHBUF_SYNC; 724 725 req->vram_available = drm->gem.vram_available; 726 req->gart_available = drm->gem.gart_available; 727 if (unlikely(req->nr_push == 0)) 728 goto out_next; 729 730 if (unlikely(req->nr_push > NOUVEAU_GEM_MAX_PUSH)) { 731 NV_PRINTK(err, cli, "pushbuf push count exceeds limit: %d max %d\n", 732 req->nr_push, NOUVEAU_GEM_MAX_PUSH); 733 return nouveau_abi16_put(abi16, -EINVAL); 734 } 735 736 if (unlikely(req->nr_buffers > NOUVEAU_GEM_MAX_BUFFERS)) { 737 NV_PRINTK(err, cli, "pushbuf bo count exceeds limit: %d max %d\n", 738 req->nr_buffers, NOUVEAU_GEM_MAX_BUFFERS); 739 return nouveau_abi16_put(abi16, -EINVAL); 740 } 741 742 if (unlikely(req->nr_relocs > NOUVEAU_GEM_MAX_RELOCS)) { 743 NV_PRINTK(err, cli, "pushbuf reloc count exceeds limit: %d max %d\n", 744 req->nr_relocs, NOUVEAU_GEM_MAX_RELOCS); 745 return nouveau_abi16_put(abi16, -EINVAL); 746 } 747 748 push = u_memcpya(req->push, req->nr_push, sizeof(*push)); 749 if (IS_ERR(push)) 750 return nouveau_abi16_put(abi16, PTR_ERR(push)); 751 752 bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); 753 if (IS_ERR(bo)) { 754 u_free(push); 755 return nouveau_abi16_put(abi16, PTR_ERR(bo)); 756 } 757 758 /* Ensure all push buffers are on validate list */ 759 for (i = 0; i < req->nr_push; i++) { 760 if (push[i].bo_index >= req->nr_buffers) { 761 NV_PRINTK(err, cli, "push %d buffer not in list\n", i); 762 ret = -EINVAL; 763 goto out_prevalid; 764 } 765 } 766 767 /* Validate buffer list */ 768 revalidate: 769 ret = nouveau_gem_pushbuf_validate(chan, file_priv, bo, 770 req->nr_buffers, &op, &do_reloc); 771 if (ret) { 772 if (ret != -ERESTARTSYS) 773 NV_PRINTK(err, cli, "validate: %d\n", ret); 774 goto out_prevalid; 775 } 776 777 /* Apply any relocations that are required */ 778 if (do_reloc) { 779 if (!reloc) { 780 validate_fini(&op, chan, NULL, bo); 781 reloc = u_memcpya(req->relocs, req->nr_relocs, sizeof(*reloc)); 782 if (IS_ERR(reloc)) { 783 ret = PTR_ERR(reloc); 784 goto out_prevalid; 785 } 786 787 goto revalidate; 788 } 789 790 ret = nouveau_gem_pushbuf_reloc_apply(cli, req, reloc, bo); 791 if (ret) { 792 NV_PRINTK(err, cli, "reloc apply: %d\n", ret); 793 goto out; 794 } 795 } 796 797 if (chan->dma.ib_max) { 798 ret = nouveau_dma_wait(chan, req->nr_push + 1, 16); 799 if (ret) { 800 NV_PRINTK(err, cli, "nv50cal_space: %d\n", ret); 801 goto out; 802 } 803 804 for (i = 0; i < req->nr_push; i++) { 805 struct nouveau_vma *vma = (void *)(unsigned long) 806 bo[push[i].bo_index].user_priv; 807 808 nv50_dma_push(chan, vma->addr + push[i].offset, 809 push[i].length); 810 } 811 } else 812 if (drm->client.device.info.chipset >= 0x25) { 813 ret = RING_SPACE(chan, req->nr_push * 2); 814 if (ret) { 815 NV_PRINTK(err, cli, "cal_space: %d\n", ret); 816 goto out; 817 } 818 819 for (i = 0; i < req->nr_push; i++) { 820 struct nouveau_bo *nvbo = (void *)(unsigned long) 821 bo[push[i].bo_index].user_priv; 822 823 OUT_RING(chan, (nvbo->bo.offset + push[i].offset) | 2); 824 OUT_RING(chan, 0); 825 } 826 } else { 827 ret = RING_SPACE(chan, req->nr_push * (2 + NOUVEAU_DMA_SKIPS)); 828 if (ret) { 829 NV_PRINTK(err, cli, "jmp_space: %d\n", ret); 830 goto out; 831 } 832 833 for (i = 0; i < req->nr_push; i++) { 834 struct nouveau_bo *nvbo = (void *)(unsigned long) 835 bo[push[i].bo_index].user_priv; 836 uint32_t cmd; 837 838 cmd = chan->push.addr + ((chan->dma.cur + 2) << 2); 839 cmd |= 0x20000000; 840 if (unlikely(cmd != req->suffix0)) { 841 if (!nvbo->kmap.virtual) { 842 ret = ttm_bo_kmap(&nvbo->bo, 0, 843 nvbo->bo.mem. 844 num_pages, 845 &nvbo->kmap); 846 if (ret) { 847 WIND_RING(chan); 848 goto out; 849 } 850 nvbo->validate_mapped = true; 851 } 852 853 nouveau_bo_wr32(nvbo, (push[i].offset + 854 push[i].length - 8) / 4, cmd); 855 } 856 857 OUT_RING(chan, 0x20000000 | 858 (nvbo->bo.offset + push[i].offset)); 859 OUT_RING(chan, 0); 860 for (j = 0; j < NOUVEAU_DMA_SKIPS; j++) 861 OUT_RING(chan, 0); 862 } 863 } 864 865 ret = nouveau_fence_new(chan, false, &fence); 866 if (ret) { 867 NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret); 868 WIND_RING(chan); 869 goto out; 870 } 871 872 if (sync) { 873 if (!(ret = nouveau_fence_wait(fence, false, false))) { 874 if ((ret = dma_fence_get_status(&fence->base)) == 1) 875 ret = 0; 876 } 877 } 878 879 out: 880 validate_fini(&op, chan, fence, bo); 881 nouveau_fence_unref(&fence); 882 883 if (do_reloc) { 884 struct drm_nouveau_gem_pushbuf_bo __user *upbbo = 885 u64_to_user_ptr(req->buffers); 886 887 for (i = 0; i < req->nr_buffers; i++) { 888 if (bo[i].presumed.valid) 889 continue; 890 891 if (copy_to_user(&upbbo[i].presumed, &bo[i].presumed, 892 sizeof(bo[i].presumed))) { 893 ret = -EFAULT; 894 break; 895 } 896 } 897 u_free(reloc); 898 } 899 out_prevalid: 900 u_free(bo); 901 u_free(push); 902 903 out_next: 904 if (chan->dma.ib_max) { 905 req->suffix0 = 0x00000000; 906 req->suffix1 = 0x00000000; 907 } else 908 if (drm->client.device.info.chipset >= 0x25) { 909 req->suffix0 = 0x00020000; 910 req->suffix1 = 0x00000000; 911 } else { 912 req->suffix0 = 0x20000000 | 913 (chan->push.addr + ((chan->dma.cur + 2) << 2)); 914 req->suffix1 = 0x00000000; 915 } 916 917 return nouveau_abi16_put(abi16, ret); 918 } 919 920 int 921 nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, 922 struct drm_file *file_priv) 923 { 924 struct drm_nouveau_gem_cpu_prep *req = data; 925 struct drm_gem_object *gem; 926 struct nouveau_bo *nvbo; 927 bool no_wait = !!(req->flags & NOUVEAU_GEM_CPU_PREP_NOWAIT); 928 bool write = !!(req->flags & NOUVEAU_GEM_CPU_PREP_WRITE); 929 long lret; 930 int ret; 931 932 gem = drm_gem_object_lookup(file_priv, req->handle); 933 if (!gem) 934 return -ENOENT; 935 nvbo = nouveau_gem_object(gem); 936 937 lret = dma_resv_wait_timeout_rcu(nvbo->bo.base.resv, write, true, 938 no_wait ? 0 : 30 * HZ); 939 if (!lret) 940 ret = -EBUSY; 941 else if (lret > 0) 942 ret = 0; 943 else 944 ret = lret; 945 946 nouveau_bo_sync_for_cpu(nvbo); 947 drm_gem_object_put_unlocked(gem); 948 949 return ret; 950 } 951 952 int 953 nouveau_gem_ioctl_cpu_fini(struct drm_device *dev, void *data, 954 struct drm_file *file_priv) 955 { 956 struct drm_nouveau_gem_cpu_fini *req = data; 957 struct drm_gem_object *gem; 958 struct nouveau_bo *nvbo; 959 960 gem = drm_gem_object_lookup(file_priv, req->handle); 961 if (!gem) 962 return -ENOENT; 963 nvbo = nouveau_gem_object(gem); 964 965 nouveau_bo_sync_for_device(nvbo); 966 drm_gem_object_put_unlocked(gem); 967 return 0; 968 } 969 970 int 971 nouveau_gem_ioctl_info(struct drm_device *dev, void *data, 972 struct drm_file *file_priv) 973 { 974 struct drm_nouveau_gem_info *req = data; 975 struct drm_gem_object *gem; 976 int ret; 977 978 gem = drm_gem_object_lookup(file_priv, req->handle); 979 if (!gem) 980 return -ENOENT; 981 982 ret = nouveau_gem_info(file_priv, gem, req); 983 drm_gem_object_put_unlocked(gem); 984 return ret; 985 } 986 987