1/* 2 * Copyright © 2015 Intel Corporation 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 (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include <sys/ioctl.h> 25#include <sys/types.h> 26#include <sys/mman.h> 27#include <string.h> 28#include <errno.h> 29#include <unistd.h> 30#include <fcntl.h> 31 32#include "anv_private.h" 33#include "common/intel_defines.h" 34#include "common/intel_gem.h" 35#include "drm-uapi/sync_file.h" 36 37/** 38 * Wrapper around DRM_IOCTL_I915_GEM_CREATE. 39 * 40 * Return gem handle, or 0 on failure. Gem handles are never 0. 41 */ 42uint32_t 43anv_gem_create(struct anv_device *device, uint64_t size) 44{ 45 struct drm_i915_gem_create gem_create = { 46 .size = size, 47 }; 48 49 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create); 50 if (ret != 0) { 51 /* FIXME: What do we do if this fails? */ 52 return 0; 53 } 54 55 return gem_create.handle; 56} 57 58void 59anv_gem_close(struct anv_device *device, uint32_t gem_handle) 60{ 61 struct drm_gem_close close = { 62 .handle = gem_handle, 63 }; 64 65 intel_ioctl(device->fd, DRM_IOCTL_GEM_CLOSE, &close); 66} 67 68uint32_t 69anv_gem_create_regions(struct anv_device *device, uint64_t anv_bo_size, 70 uint32_t num_regions, 71 struct drm_i915_gem_memory_class_instance *regions) 72{ 73 struct drm_i915_gem_create_ext_memory_regions ext_regions = { 74 .base = { .name = I915_GEM_CREATE_EXT_MEMORY_REGIONS }, 75 .num_regions = num_regions, 76 .regions = (uintptr_t)regions, 77 }; 78 79 struct drm_i915_gem_create_ext gem_create = { 80 .size = anv_bo_size, 81 .extensions = (uintptr_t) &ext_regions, 82 }; 83 84 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CREATE_EXT, 85 &gem_create); 86 if (ret != 0) { 87 return 0; 88 } 89 90 return gem_create.handle; 91} 92 93/** 94 * Wrapper around DRM_IOCTL_I915_GEM_MMAP. Returns MAP_FAILED on error. 95 */ 96static void* 97anv_gem_mmap_offset(struct anv_device *device, uint32_t gem_handle, 98 uint64_t offset, uint64_t size, uint32_t flags) 99{ 100 struct drm_i915_gem_mmap_offset gem_mmap = { 101 .handle = gem_handle, 102 .flags = device->info.has_local_mem ? I915_MMAP_OFFSET_FIXED : 103 (flags & I915_MMAP_WC) ? I915_MMAP_OFFSET_WC : I915_MMAP_OFFSET_WB, 104 }; 105 assert(offset == 0); 106 107 /* Get the fake offset back */ 108 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &gem_mmap); 109 if (ret != 0) 110 return MAP_FAILED; 111 112 /* And map it */ 113 void *map = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, 114 device->fd, gem_mmap.offset); 115 return map; 116} 117 118static void* 119anv_gem_mmap_legacy(struct anv_device *device, uint32_t gem_handle, 120 uint64_t offset, uint64_t size, uint32_t flags) 121{ 122 assert(!device->info.has_local_mem); 123 124 struct drm_i915_gem_mmap gem_mmap = { 125 .handle = gem_handle, 126 .offset = offset, 127 .size = size, 128 .flags = flags, 129 }; 130 131 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_mmap); 132 if (ret != 0) 133 return MAP_FAILED; 134 135 return (void *)(uintptr_t) gem_mmap.addr_ptr; 136} 137 138/** 139 * Wrapper around DRM_IOCTL_I915_GEM_MMAP. Returns MAP_FAILED on error. 140 */ 141void* 142anv_gem_mmap(struct anv_device *device, uint32_t gem_handle, 143 uint64_t offset, uint64_t size, uint32_t flags) 144{ 145 void *map; 146 if (device->physical->has_mmap_offset) 147 map = anv_gem_mmap_offset(device, gem_handle, offset, size, flags); 148 else 149 map = anv_gem_mmap_legacy(device, gem_handle, offset, size, flags); 150 151 if (map != MAP_FAILED) 152 VG(VALGRIND_MALLOCLIKE_BLOCK(map, size, 0, 1)); 153 154 return map; 155} 156 157/* This is just a wrapper around munmap, but it also notifies valgrind that 158 * this map is no longer valid. Pair this with anv_gem_mmap(). 159 */ 160void 161anv_gem_munmap(struct anv_device *device, void *p, uint64_t size) 162{ 163 VG(VALGRIND_FREELIKE_BLOCK(p, 0)); 164 munmap(p, size); 165} 166 167uint32_t 168anv_gem_userptr(struct anv_device *device, void *mem, size_t size) 169{ 170 struct drm_i915_gem_userptr userptr = { 171 .user_ptr = (__u64)((unsigned long) mem), 172 .user_size = size, 173 .flags = 0, 174 }; 175 176 if (device->physical->has_userptr_probe) 177 userptr.flags |= I915_USERPTR_PROBE; 178 179 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_USERPTR, &userptr); 180 if (ret == -1) 181 return 0; 182 183 return userptr.handle; 184} 185 186int 187anv_gem_set_caching(struct anv_device *device, 188 uint32_t gem_handle, uint32_t caching) 189{ 190 struct drm_i915_gem_caching gem_caching = { 191 .handle = gem_handle, 192 .caching = caching, 193 }; 194 195 return intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_CACHING, &gem_caching); 196} 197 198int 199anv_gem_set_domain(struct anv_device *device, uint32_t gem_handle, 200 uint32_t read_domains, uint32_t write_domain) 201{ 202 struct drm_i915_gem_set_domain gem_set_domain = { 203 .handle = gem_handle, 204 .read_domains = read_domains, 205 .write_domain = write_domain, 206 }; 207 208 return intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &gem_set_domain); 209} 210 211/** 212 * Returns 0, 1, or negative to indicate error 213 */ 214int 215anv_gem_busy(struct anv_device *device, uint32_t gem_handle) 216{ 217 struct drm_i915_gem_busy busy = { 218 .handle = gem_handle, 219 }; 220 221 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_BUSY, &busy); 222 if (ret < 0) 223 return ret; 224 225 return busy.busy != 0; 226} 227 228/** 229 * On error, \a timeout_ns holds the remaining time. 230 */ 231int 232anv_gem_wait(struct anv_device *device, uint32_t gem_handle, int64_t *timeout_ns) 233{ 234 struct drm_i915_gem_wait wait = { 235 .bo_handle = gem_handle, 236 .timeout_ns = *timeout_ns, 237 .flags = 0, 238 }; 239 240 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_WAIT, &wait); 241 *timeout_ns = wait.timeout_ns; 242 243 return ret; 244} 245 246int 247anv_gem_execbuffer(struct anv_device *device, 248 struct drm_i915_gem_execbuffer2 *execbuf) 249{ 250 if (execbuf->flags & I915_EXEC_FENCE_OUT) 251 return intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2_WR, execbuf); 252 else 253 return intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf); 254} 255 256/** Return -1 on error. */ 257int 258anv_gem_get_tiling(struct anv_device *device, uint32_t gem_handle) 259{ 260 struct drm_i915_gem_get_tiling get_tiling = { 261 .handle = gem_handle, 262 }; 263 264 /* FIXME: On discrete platforms we don't have DRM_IOCTL_I915_GEM_GET_TILING 265 * anymore, so we will need another way to get the tiling. Apparently this 266 * is only used in Android code, so we may need some other way to 267 * communicate the tiling mode. 268 */ 269 if (intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) { 270 assert(!"Failed to get BO tiling"); 271 return -1; 272 } 273 274 return get_tiling.tiling_mode; 275} 276 277int 278anv_gem_set_tiling(struct anv_device *device, 279 uint32_t gem_handle, uint32_t stride, uint32_t tiling) 280{ 281 int ret; 282 283 /* On discrete platforms we don't have DRM_IOCTL_I915_GEM_SET_TILING. So 284 * nothing needs to be done. 285 */ 286 if (!device->info.has_tiling_uapi) 287 return 0; 288 289 /* set_tiling overwrites the input on the error path, so we have to open 290 * code intel_ioctl. 291 */ 292 do { 293 struct drm_i915_gem_set_tiling set_tiling = { 294 .handle = gem_handle, 295 .tiling_mode = tiling, 296 .stride = stride, 297 }; 298 299 ret = ioctl(device->fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); 300 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 301 302 return ret; 303} 304 305int 306anv_gem_get_param(int fd, uint32_t param) 307{ 308 int tmp; 309 310 drm_i915_getparam_t gp = { 311 .param = param, 312 .value = &tmp, 313 }; 314 315 int ret = intel_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp); 316 if (ret == 0) 317 return tmp; 318 319 return 0; 320} 321 322uint64_t 323anv_gem_get_drm_cap(int fd, uint32_t capability) 324{ 325 struct drm_get_cap cap = { 326 .capability = capability, 327 }; 328 329 intel_ioctl(fd, DRM_IOCTL_GET_CAP, &cap); 330 return cap.value; 331} 332 333bool 334anv_gem_get_bit6_swizzle(int fd, uint32_t tiling) 335{ 336 struct drm_gem_close close; 337 int ret; 338 339 struct drm_i915_gem_create gem_create = { 340 .size = 4096, 341 }; 342 343 if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create)) { 344 assert(!"Failed to create GEM BO"); 345 return false; 346 } 347 348 bool swizzled = false; 349 350 /* set_tiling overwrites the input on the error path, so we have to open 351 * code intel_ioctl. 352 */ 353 do { 354 struct drm_i915_gem_set_tiling set_tiling = { 355 .handle = gem_create.handle, 356 .tiling_mode = tiling, 357 .stride = tiling == I915_TILING_X ? 512 : 128, 358 }; 359 360 ret = ioctl(fd, DRM_IOCTL_I915_GEM_SET_TILING, &set_tiling); 361 } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); 362 363 if (ret != 0) { 364 assert(!"Failed to set BO tiling"); 365 goto close_and_return; 366 } 367 368 struct drm_i915_gem_get_tiling get_tiling = { 369 .handle = gem_create.handle, 370 }; 371 372 if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_GET_TILING, &get_tiling)) { 373 assert(!"Failed to get BO tiling"); 374 goto close_and_return; 375 } 376 377 swizzled = get_tiling.swizzle_mode != I915_BIT_6_SWIZZLE_NONE; 378 379close_and_return: 380 381 memset(&close, 0, sizeof(close)); 382 close.handle = gem_create.handle; 383 intel_ioctl(fd, DRM_IOCTL_GEM_CLOSE, &close); 384 385 return swizzled; 386} 387 388bool 389anv_gem_has_context_priority(int fd) 390{ 391 return !anv_gem_set_context_param(fd, 0, I915_CONTEXT_PARAM_PRIORITY, 392 INTEL_CONTEXT_MEDIUM_PRIORITY); 393} 394 395int 396anv_gem_create_context(struct anv_device *device) 397{ 398 struct drm_i915_gem_context_create create = { 0 }; 399 400 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create); 401 if (ret == -1) 402 return -1; 403 404 return create.ctx_id; 405} 406 407int 408anv_gem_create_context_engines(struct anv_device *device, 409 const struct drm_i915_query_engine_info *info, 410 int num_engines, uint16_t *engine_classes) 411{ 412 const size_t engine_inst_sz = 2 * sizeof(__u16); /* 1 class, 1 instance */ 413 const size_t engines_param_size = 414 sizeof(__u64) /* extensions */ + num_engines * engine_inst_sz; 415 416 void *engines_param = malloc(engines_param_size); 417 assert(engines_param); 418 *(__u64*)engines_param = 0; 419 __u16 *class_inst_ptr = (__u16*)(((__u64*)engines_param) + 1); 420 421 /* For each type of drm_i915_gem_engine_class of interest, we keep track of 422 * the previous engine instance used. 423 */ 424 int last_engine_idx[] = { 425 [I915_ENGINE_CLASS_RENDER] = -1, 426 }; 427 428 int i915_engine_counts[] = { 429 [I915_ENGINE_CLASS_RENDER] = 430 anv_gem_count_engines(info, I915_ENGINE_CLASS_RENDER), 431 }; 432 433 /* For each queue, we look for the next instance that matches the class we 434 * need. 435 */ 436 for (int i = 0; i < num_engines; i++) { 437 uint16_t engine_class = engine_classes[i]; 438 if (i915_engine_counts[engine_class] <= 0) { 439 free(engines_param); 440 return -1; 441 } 442 443 /* Run through the engines reported by the kernel looking for the next 444 * matching instance. We loop in case we want to create multiple 445 * contexts on an engine instance. 446 */ 447 int engine_instance = -1; 448 for (int i = 0; i < info->num_engines; i++) { 449 int *idx = &last_engine_idx[engine_class]; 450 if (++(*idx) >= info->num_engines) 451 *idx = 0; 452 if (info->engines[*idx].engine.engine_class == engine_class) { 453 engine_instance = info->engines[*idx].engine.engine_instance; 454 break; 455 } 456 } 457 if (engine_instance < 0) { 458 free(engines_param); 459 return -1; 460 } 461 462 *class_inst_ptr++ = engine_class; 463 *class_inst_ptr++ = engine_instance; 464 } 465 466 assert((uintptr_t)engines_param + engines_param_size == 467 (uintptr_t)class_inst_ptr); 468 469 struct drm_i915_gem_context_create_ext_setparam set_engines = { 470 .base = { 471 .name = I915_CONTEXT_CREATE_EXT_SETPARAM, 472 }, 473 .param = { 474 .param = I915_CONTEXT_PARAM_ENGINES, 475 .value = (uintptr_t)engines_param, 476 .size = engines_param_size, 477 } 478 }; 479 struct drm_i915_gem_context_create_ext create = { 480 .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS, 481 .extensions = (uintptr_t)&set_engines, 482 }; 483 int ret = intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &create); 484 free(engines_param); 485 if (ret == -1) 486 return -1; 487 488 return create.ctx_id; 489} 490 491int 492anv_gem_destroy_context(struct anv_device *device, int context) 493{ 494 struct drm_i915_gem_context_destroy destroy = { 495 .ctx_id = context, 496 }; 497 498 return intel_ioctl(device->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy); 499} 500 501int 502anv_gem_set_context_param(int fd, int context, uint32_t param, uint64_t value) 503{ 504 struct drm_i915_gem_context_param p = { 505 .ctx_id = context, 506 .param = param, 507 .value = value, 508 }; 509 int err = 0; 510 511 if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &p)) 512 err = -errno; 513 return err; 514} 515 516int 517anv_gem_get_context_param(int fd, int context, uint32_t param, uint64_t *value) 518{ 519 struct drm_i915_gem_context_param gp = { 520 .ctx_id = context, 521 .param = param, 522 }; 523 524 int ret = intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &gp); 525 if (ret == -1) 526 return -1; 527 528 *value = gp.value; 529 return 0; 530} 531 532int 533anv_gem_context_get_reset_stats(int fd, int context, 534 uint32_t *active, uint32_t *pending) 535{ 536 struct drm_i915_reset_stats stats = { 537 .ctx_id = context, 538 }; 539 540 int ret = intel_ioctl(fd, DRM_IOCTL_I915_GET_RESET_STATS, &stats); 541 if (ret == 0) { 542 *active = stats.batch_active; 543 *pending = stats.batch_pending; 544 } 545 546 return ret; 547} 548 549int 550anv_gem_handle_to_fd(struct anv_device *device, uint32_t gem_handle) 551{ 552 struct drm_prime_handle args = { 553 .handle = gem_handle, 554 .flags = DRM_CLOEXEC | DRM_RDWR, 555 }; 556 557 int ret = intel_ioctl(device->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args); 558 if (ret == -1) 559 return -1; 560 561 return args.fd; 562} 563 564uint32_t 565anv_gem_fd_to_handle(struct anv_device *device, int fd) 566{ 567 struct drm_prime_handle args = { 568 .fd = fd, 569 }; 570 571 int ret = intel_ioctl(device->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args); 572 if (ret == -1) 573 return 0; 574 575 return args.handle; 576} 577 578int 579anv_gem_reg_read(int fd, uint32_t offset, uint64_t *result) 580{ 581 struct drm_i915_reg_read args = { 582 .offset = offset 583 }; 584 585 int ret = intel_ioctl(fd, DRM_IOCTL_I915_REG_READ, &args); 586 587 *result = args.val; 588 return ret; 589} 590 591int 592anv_gem_sync_file_merge(struct anv_device *device, int fd1, int fd2) 593{ 594 struct sync_merge_data args = { 595 .name = "anv merge fence", 596 .fd2 = fd2, 597 .fence = -1, 598 }; 599 600 int ret = intel_ioctl(fd1, SYNC_IOC_MERGE, &args); 601 if (ret == -1) 602 return -1; 603 604 return args.fence; 605} 606 607uint32_t 608anv_gem_syncobj_create(struct anv_device *device, uint32_t flags) 609{ 610 struct drm_syncobj_create args = { 611 .flags = flags, 612 }; 613 614 int ret = intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_CREATE, &args); 615 if (ret) 616 return 0; 617 618 return args.handle; 619} 620 621void 622anv_gem_syncobj_destroy(struct anv_device *device, uint32_t handle) 623{ 624 struct drm_syncobj_destroy args = { 625 .handle = handle, 626 }; 627 628 intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_DESTROY, &args); 629} 630 631int 632anv_gem_syncobj_handle_to_fd(struct anv_device *device, uint32_t handle) 633{ 634 struct drm_syncobj_handle args = { 635 .handle = handle, 636 }; 637 638 int ret = intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 639 if (ret) 640 return -1; 641 642 return args.fd; 643} 644 645uint32_t 646anv_gem_syncobj_fd_to_handle(struct anv_device *device, int fd) 647{ 648 struct drm_syncobj_handle args = { 649 .fd = fd, 650 }; 651 652 int ret = intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 653 if (ret) 654 return 0; 655 656 return args.handle; 657} 658 659int 660anv_gem_syncobj_export_sync_file(struct anv_device *device, uint32_t handle) 661{ 662 struct drm_syncobj_handle args = { 663 .handle = handle, 664 .flags = DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE, 665 }; 666 667 int ret = intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, &args); 668 if (ret) 669 return -1; 670 671 return args.fd; 672} 673 674int 675anv_gem_syncobj_import_sync_file(struct anv_device *device, 676 uint32_t handle, int fd) 677{ 678 struct drm_syncobj_handle args = { 679 .handle = handle, 680 .fd = fd, 681 .flags = DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE, 682 }; 683 684 return intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, &args); 685} 686 687void 688anv_gem_syncobj_reset(struct anv_device *device, uint32_t handle) 689{ 690 struct drm_syncobj_array args = { 691 .handles = (uint64_t)(uintptr_t)&handle, 692 .count_handles = 1, 693 }; 694 695 intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_RESET, &args); 696} 697 698bool 699anv_gem_supports_syncobj_wait(int fd) 700{ 701 return intel_gem_supports_syncobj_wait(fd); 702} 703 704int 705anv_gem_syncobj_wait(struct anv_device *device, 706 const uint32_t *handles, uint32_t num_handles, 707 int64_t abs_timeout_ns, bool wait_all) 708{ 709 struct drm_syncobj_wait args = { 710 .handles = (uint64_t)(uintptr_t)handles, 711 .count_handles = num_handles, 712 .timeout_nsec = abs_timeout_ns, 713 .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, 714 }; 715 716 if (wait_all) 717 args.flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL; 718 719 return intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_WAIT, &args); 720} 721 722int 723anv_gem_syncobj_timeline_wait(struct anv_device *device, 724 const uint32_t *handles, const uint64_t *points, 725 uint32_t num_items, int64_t abs_timeout_ns, 726 bool wait_all, bool wait_materialize) 727{ 728 assert(device->physical->has_syncobj_wait_available); 729 730 struct drm_syncobj_timeline_wait args = { 731 .handles = (uint64_t)(uintptr_t)handles, 732 .points = (uint64_t)(uintptr_t)points, 733 .count_handles = num_items, 734 .timeout_nsec = abs_timeout_ns, 735 .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT, 736 }; 737 738 if (wait_all) 739 args.flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL; 740 if (wait_materialize) 741 args.flags |= DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE; 742 743 return intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, &args); 744} 745 746int 747anv_gem_syncobj_timeline_signal(struct anv_device *device, 748 const uint32_t *handles, const uint64_t *points, 749 uint32_t num_items) 750{ 751 assert(device->physical->has_syncobj_wait_available); 752 753 struct drm_syncobj_timeline_array args = { 754 .handles = (uint64_t)(uintptr_t)handles, 755 .points = (uint64_t)(uintptr_t)points, 756 .count_handles = num_items, 757 }; 758 759 return intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, &args); 760} 761 762int 763anv_gem_syncobj_timeline_query(struct anv_device *device, 764 const uint32_t *handles, uint64_t *points, 765 uint32_t num_items) 766{ 767 assert(device->physical->has_syncobj_wait_available); 768 769 struct drm_syncobj_timeline_array args = { 770 .handles = (uint64_t)(uintptr_t)handles, 771 .points = (uint64_t)(uintptr_t)points, 772 .count_handles = num_items, 773 }; 774 775 return intel_ioctl(device->fd, DRM_IOCTL_SYNCOBJ_QUERY, &args); 776} 777 778struct drm_i915_query_engine_info * 779anv_gem_get_engine_info(int fd) 780{ 781 return intel_i915_query_alloc(fd, DRM_I915_QUERY_ENGINE_INFO); 782} 783 784int 785anv_gem_count_engines(const struct drm_i915_query_engine_info *info, 786 uint16_t engine_class) 787{ 788 int count = 0; 789 for (int i = 0; i < info->num_engines; i++) { 790 if (info->engines[i].engine.engine_class == engine_class) 791 count++; 792 } 793 return count; 794} 795