1/* 2 * Copyright 2014 Advanced Micro Devices, 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 */ 23 24#include <stdlib.h> 25#include <stdio.h> 26#include <string.h> 27#include <errno.h> 28#include <pthread.h> 29#include <sched.h> 30#include <sys/ioctl.h> 31#if HAVE_ALLOCA_H 32# include <alloca.h> 33#endif 34 35#include "xf86drm.h" 36#include "amdgpu_drm.h" 37#include "amdgpu_internal.h" 38 39static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem); 40static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem); 41 42/** 43 * Create command submission context 44 * 45 * \param dev - \c [in] Device handle. See #amdgpu_device_initialize() 46 * \param priority - \c [in] Context creation flags. See AMDGPU_CTX_PRIORITY_* 47 * \param context - \c [out] GPU Context handle 48 * 49 * \return 0 on success otherwise POSIX Error code 50*/ 51drm_public int amdgpu_cs_ctx_create2(amdgpu_device_handle dev, 52 uint32_t priority, 53 amdgpu_context_handle *context) 54{ 55 struct amdgpu_context *gpu_context; 56 union drm_amdgpu_ctx args; 57 int i, j, k; 58 int r; 59 60 if (!dev || !context) 61 return -EINVAL; 62 63 gpu_context = calloc(1, sizeof(struct amdgpu_context)); 64 if (!gpu_context) 65 return -ENOMEM; 66 67 gpu_context->dev = dev; 68 69 r = pthread_mutex_init(&gpu_context->sequence_mutex, NULL); 70 if (r) 71 goto error; 72 73 /* Create the context */ 74 memset(&args, 0, sizeof(args)); 75 args.in.op = AMDGPU_CTX_OP_ALLOC_CTX; 76 args.in.priority = priority; 77 78 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CTX, &args, sizeof(args)); 79 if (r) 80 goto error; 81 82 gpu_context->id = args.out.alloc.ctx_id; 83 for (i = 0; i < AMDGPU_HW_IP_NUM; i++) 84 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) 85 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) 86 list_inithead(&gpu_context->sem_list[i][j][k]); 87 *context = (amdgpu_context_handle)gpu_context; 88 89 return 0; 90 91error: 92 pthread_mutex_destroy(&gpu_context->sequence_mutex); 93 free(gpu_context); 94 return r; 95} 96 97drm_public int amdgpu_cs_ctx_create(amdgpu_device_handle dev, 98 amdgpu_context_handle *context) 99{ 100 return amdgpu_cs_ctx_create2(dev, AMDGPU_CTX_PRIORITY_NORMAL, context); 101} 102 103/** 104 * Release command submission context 105 * 106 * \param dev - \c [in] amdgpu device handle 107 * \param context - \c [in] amdgpu context handle 108 * 109 * \return 0 on success otherwise POSIX Error code 110*/ 111drm_public int amdgpu_cs_ctx_free(amdgpu_context_handle context) 112{ 113 union drm_amdgpu_ctx args; 114 int i, j, k; 115 int r; 116 117 if (!context) 118 return -EINVAL; 119 120 pthread_mutex_destroy(&context->sequence_mutex); 121 122 /* now deal with kernel side */ 123 memset(&args, 0, sizeof(args)); 124 args.in.op = AMDGPU_CTX_OP_FREE_CTX; 125 args.in.ctx_id = context->id; 126 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 127 &args, sizeof(args)); 128 for (i = 0; i < AMDGPU_HW_IP_NUM; i++) { 129 for (j = 0; j < AMDGPU_HW_IP_INSTANCE_MAX_COUNT; j++) { 130 for (k = 0; k < AMDGPU_CS_MAX_RINGS; k++) { 131 amdgpu_semaphore_handle sem; 132 LIST_FOR_EACH_ENTRY(sem, &context->sem_list[i][j][k], list) { 133 list_del(&sem->list); 134 amdgpu_cs_reset_sem(sem); 135 amdgpu_cs_unreference_sem(sem); 136 } 137 } 138 } 139 } 140 free(context); 141 142 return r; 143} 144 145drm_public int amdgpu_cs_ctx_override_priority(amdgpu_device_handle dev, 146 amdgpu_context_handle context, 147 int master_fd, 148 unsigned priority) 149{ 150 union drm_amdgpu_sched args; 151 int r; 152 153 if (!dev || !context || master_fd < 0) 154 return -EINVAL; 155 156 memset(&args, 0, sizeof(args)); 157 158 args.in.op = AMDGPU_SCHED_OP_CONTEXT_PRIORITY_OVERRIDE; 159 args.in.fd = dev->fd; 160 args.in.priority = priority; 161 args.in.ctx_id = context->id; 162 163 r = drmCommandWrite(master_fd, DRM_AMDGPU_SCHED, &args, sizeof(args)); 164 if (r) 165 return r; 166 167 return 0; 168} 169 170drm_public int amdgpu_cs_ctx_stable_pstate(amdgpu_context_handle context, 171 uint32_t op, 172 uint32_t flags, 173 uint32_t *out_flags) 174{ 175 union drm_amdgpu_ctx args; 176 int r; 177 178 if (!context) 179 return -EINVAL; 180 181 memset(&args, 0, sizeof(args)); 182 args.in.op = op; 183 args.in.ctx_id = context->id; 184 args.in.flags = flags; 185 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 186 &args, sizeof(args)); 187 if (!r && out_flags) 188 *out_flags = args.out.pstate.flags; 189 return r; 190} 191 192drm_public int amdgpu_cs_query_reset_state(amdgpu_context_handle context, 193 uint32_t *state, uint32_t *hangs) 194{ 195 union drm_amdgpu_ctx args; 196 int r; 197 198 if (!context) 199 return -EINVAL; 200 201 memset(&args, 0, sizeof(args)); 202 args.in.op = AMDGPU_CTX_OP_QUERY_STATE; 203 args.in.ctx_id = context->id; 204 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 205 &args, sizeof(args)); 206 if (!r) { 207 *state = args.out.state.reset_status; 208 *hangs = args.out.state.hangs; 209 } 210 return r; 211} 212 213drm_public int amdgpu_cs_query_reset_state2(amdgpu_context_handle context, 214 uint64_t *flags) 215{ 216 union drm_amdgpu_ctx args; 217 int r; 218 219 if (!context) 220 return -EINVAL; 221 222 memset(&args, 0, sizeof(args)); 223 args.in.op = AMDGPU_CTX_OP_QUERY_STATE2; 224 args.in.ctx_id = context->id; 225 r = drmCommandWriteRead(context->dev->fd, DRM_AMDGPU_CTX, 226 &args, sizeof(args)); 227 if (!r) 228 *flags = args.out.state.flags; 229 return r; 230} 231 232/** 233 * Submit command to kernel DRM 234 * \param dev - \c [in] Device handle 235 * \param context - \c [in] GPU Context 236 * \param ibs_request - \c [in] Pointer to submission requests 237 * \param fence - \c [out] return fence for this submission 238 * 239 * \return 0 on success otherwise POSIX Error code 240 * \sa amdgpu_cs_submit() 241*/ 242static int amdgpu_cs_submit_one(amdgpu_context_handle context, 243 struct amdgpu_cs_request *ibs_request) 244{ 245 struct drm_amdgpu_cs_chunk *chunks; 246 struct drm_amdgpu_cs_chunk_data *chunk_data; 247 struct drm_amdgpu_cs_chunk_dep *dependencies = NULL; 248 struct drm_amdgpu_cs_chunk_dep *sem_dependencies = NULL; 249 amdgpu_device_handle dev = context->dev; 250 struct list_head *sem_list; 251 amdgpu_semaphore_handle sem, tmp; 252 uint32_t i, size, num_chunks, bo_list_handle = 0, sem_count = 0; 253 uint64_t seq_no; 254 bool user_fence; 255 int r = 0; 256 257 if (ibs_request->ip_type >= AMDGPU_HW_IP_NUM) 258 return -EINVAL; 259 if (ibs_request->ring >= AMDGPU_CS_MAX_RINGS) 260 return -EINVAL; 261 if (ibs_request->number_of_ibs == 0) { 262 ibs_request->seq_no = AMDGPU_NULL_SUBMIT_SEQ; 263 return 0; 264 } 265 user_fence = (ibs_request->fence_info.handle != NULL); 266 267 size = ibs_request->number_of_ibs + (user_fence ? 2 : 1) + 1; 268 269 chunks = alloca(sizeof(struct drm_amdgpu_cs_chunk) * size); 270 271 size = ibs_request->number_of_ibs + (user_fence ? 1 : 0); 272 273 chunk_data = alloca(sizeof(struct drm_amdgpu_cs_chunk_data) * size); 274 275 if (ibs_request->resources) 276 bo_list_handle = ibs_request->resources->handle; 277 num_chunks = ibs_request->number_of_ibs; 278 /* IB chunks */ 279 for (i = 0; i < ibs_request->number_of_ibs; i++) { 280 struct amdgpu_cs_ib_info *ib; 281 chunks[i].chunk_id = AMDGPU_CHUNK_ID_IB; 282 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_ib) / 4; 283 chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i]; 284 285 ib = &ibs_request->ibs[i]; 286 287 chunk_data[i].ib_data._pad = 0; 288 chunk_data[i].ib_data.va_start = ib->ib_mc_address; 289 chunk_data[i].ib_data.ib_bytes = ib->size * 4; 290 chunk_data[i].ib_data.ip_type = ibs_request->ip_type; 291 chunk_data[i].ib_data.ip_instance = ibs_request->ip_instance; 292 chunk_data[i].ib_data.ring = ibs_request->ring; 293 chunk_data[i].ib_data.flags = ib->flags; 294 } 295 296 pthread_mutex_lock(&context->sequence_mutex); 297 298 if (user_fence) { 299 i = num_chunks++; 300 301 /* fence chunk */ 302 chunks[i].chunk_id = AMDGPU_CHUNK_ID_FENCE; 303 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_fence) / 4; 304 chunks[i].chunk_data = (uint64_t)(uintptr_t)&chunk_data[i]; 305 306 /* fence bo handle */ 307 chunk_data[i].fence_data.handle = ibs_request->fence_info.handle->handle; 308 /* offset */ 309 chunk_data[i].fence_data.offset = 310 ibs_request->fence_info.offset * sizeof(uint64_t); 311 } 312 313 if (ibs_request->number_of_dependencies) { 314 dependencies = alloca(sizeof(struct drm_amdgpu_cs_chunk_dep) * 315 ibs_request->number_of_dependencies); 316 if (!dependencies) { 317 r = -ENOMEM; 318 goto error_unlock; 319 } 320 321 for (i = 0; i < ibs_request->number_of_dependencies; ++i) { 322 struct amdgpu_cs_fence *info = &ibs_request->dependencies[i]; 323 struct drm_amdgpu_cs_chunk_dep *dep = &dependencies[i]; 324 dep->ip_type = info->ip_type; 325 dep->ip_instance = info->ip_instance; 326 dep->ring = info->ring; 327 dep->ctx_id = info->context->id; 328 dep->handle = info->fence; 329 } 330 331 i = num_chunks++; 332 333 /* dependencies chunk */ 334 chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES; 335 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 336 * ibs_request->number_of_dependencies; 337 chunks[i].chunk_data = (uint64_t)(uintptr_t)dependencies; 338 } 339 340 sem_list = &context->sem_list[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring]; 341 LIST_FOR_EACH_ENTRY(sem, sem_list, list) 342 sem_count++; 343 if (sem_count) { 344 sem_dependencies = alloca(sizeof(struct drm_amdgpu_cs_chunk_dep) * sem_count); 345 if (!sem_dependencies) { 346 r = -ENOMEM; 347 goto error_unlock; 348 } 349 sem_count = 0; 350 LIST_FOR_EACH_ENTRY_SAFE(sem, tmp, sem_list, list) { 351 struct amdgpu_cs_fence *info = &sem->signal_fence; 352 struct drm_amdgpu_cs_chunk_dep *dep = &sem_dependencies[sem_count++]; 353 dep->ip_type = info->ip_type; 354 dep->ip_instance = info->ip_instance; 355 dep->ring = info->ring; 356 dep->ctx_id = info->context->id; 357 dep->handle = info->fence; 358 359 list_del(&sem->list); 360 amdgpu_cs_reset_sem(sem); 361 amdgpu_cs_unreference_sem(sem); 362 } 363 i = num_chunks++; 364 365 /* dependencies chunk */ 366 chunks[i].chunk_id = AMDGPU_CHUNK_ID_DEPENDENCIES; 367 chunks[i].length_dw = sizeof(struct drm_amdgpu_cs_chunk_dep) / 4 * sem_count; 368 chunks[i].chunk_data = (uint64_t)(uintptr_t)sem_dependencies; 369 } 370 371 r = amdgpu_cs_submit_raw2(dev, context, bo_list_handle, num_chunks, 372 chunks, &seq_no); 373 if (r) 374 goto error_unlock; 375 376 ibs_request->seq_no = seq_no; 377 context->last_seq[ibs_request->ip_type][ibs_request->ip_instance][ibs_request->ring] = ibs_request->seq_no; 378error_unlock: 379 pthread_mutex_unlock(&context->sequence_mutex); 380 return r; 381} 382 383drm_public int amdgpu_cs_submit(amdgpu_context_handle context, 384 uint64_t flags, 385 struct amdgpu_cs_request *ibs_request, 386 uint32_t number_of_requests) 387{ 388 uint32_t i; 389 int r; 390 391 if (!context || !ibs_request) 392 return -EINVAL; 393 394 r = 0; 395 for (i = 0; i < number_of_requests; i++) { 396 r = amdgpu_cs_submit_one(context, ibs_request); 397 if (r) 398 break; 399 ibs_request++; 400 } 401 402 return r; 403} 404 405/** 406 * Calculate absolute timeout. 407 * 408 * \param timeout - \c [in] timeout in nanoseconds. 409 * 410 * \return absolute timeout in nanoseconds 411*/ 412drm_private uint64_t amdgpu_cs_calculate_timeout(uint64_t timeout) 413{ 414 int r; 415 416 if (timeout != AMDGPU_TIMEOUT_INFINITE) { 417 struct timespec current; 418 uint64_t current_ns; 419 r = clock_gettime(CLOCK_MONOTONIC, ¤t); 420 if (r) { 421 fprintf(stderr, "clock_gettime() returned error (%d)!", errno); 422 return AMDGPU_TIMEOUT_INFINITE; 423 } 424 425 current_ns = ((uint64_t)current.tv_sec) * 1000000000ull; 426 current_ns += current.tv_nsec; 427 timeout += current_ns; 428 if (timeout < current_ns) 429 timeout = AMDGPU_TIMEOUT_INFINITE; 430 } 431 return timeout; 432} 433 434static int amdgpu_ioctl_wait_cs(amdgpu_context_handle context, 435 unsigned ip, 436 unsigned ip_instance, 437 uint32_t ring, 438 uint64_t handle, 439 uint64_t timeout_ns, 440 uint64_t flags, 441 bool *busy) 442{ 443 amdgpu_device_handle dev = context->dev; 444 union drm_amdgpu_wait_cs args; 445 int r; 446 447 memset(&args, 0, sizeof(args)); 448 args.in.handle = handle; 449 args.in.ip_type = ip; 450 args.in.ip_instance = ip_instance; 451 args.in.ring = ring; 452 args.in.ctx_id = context->id; 453 454 if (flags & AMDGPU_QUERY_FENCE_TIMEOUT_IS_ABSOLUTE) 455 args.in.timeout = timeout_ns; 456 else 457 args.in.timeout = amdgpu_cs_calculate_timeout(timeout_ns); 458 459 r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_CS, &args); 460 if (r) 461 return -errno; 462 463 *busy = args.out.status; 464 return 0; 465} 466 467drm_public int amdgpu_cs_query_fence_status(struct amdgpu_cs_fence *fence, 468 uint64_t timeout_ns, 469 uint64_t flags, 470 uint32_t *expired) 471{ 472 bool busy = true; 473 int r; 474 475 if (!fence || !expired || !fence->context) 476 return -EINVAL; 477 if (fence->ip_type >= AMDGPU_HW_IP_NUM) 478 return -EINVAL; 479 if (fence->ring >= AMDGPU_CS_MAX_RINGS) 480 return -EINVAL; 481 if (fence->fence == AMDGPU_NULL_SUBMIT_SEQ) { 482 *expired = true; 483 return 0; 484 } 485 486 *expired = false; 487 488 r = amdgpu_ioctl_wait_cs(fence->context, fence->ip_type, 489 fence->ip_instance, fence->ring, 490 fence->fence, timeout_ns, flags, &busy); 491 492 if (!r && !busy) 493 *expired = true; 494 495 return r; 496} 497 498static int amdgpu_ioctl_wait_fences(struct amdgpu_cs_fence *fences, 499 uint32_t fence_count, 500 bool wait_all, 501 uint64_t timeout_ns, 502 uint32_t *status, 503 uint32_t *first) 504{ 505 struct drm_amdgpu_fence *drm_fences; 506 amdgpu_device_handle dev = fences[0].context->dev; 507 union drm_amdgpu_wait_fences args; 508 int r; 509 uint32_t i; 510 511 drm_fences = alloca(sizeof(struct drm_amdgpu_fence) * fence_count); 512 for (i = 0; i < fence_count; i++) { 513 drm_fences[i].ctx_id = fences[i].context->id; 514 drm_fences[i].ip_type = fences[i].ip_type; 515 drm_fences[i].ip_instance = fences[i].ip_instance; 516 drm_fences[i].ring = fences[i].ring; 517 drm_fences[i].seq_no = fences[i].fence; 518 } 519 520 memset(&args, 0, sizeof(args)); 521 args.in.fences = (uint64_t)(uintptr_t)drm_fences; 522 args.in.fence_count = fence_count; 523 args.in.wait_all = wait_all; 524 args.in.timeout_ns = amdgpu_cs_calculate_timeout(timeout_ns); 525 526 r = drmIoctl(dev->fd, DRM_IOCTL_AMDGPU_WAIT_FENCES, &args); 527 if (r) 528 return -errno; 529 530 *status = args.out.status; 531 532 if (first) 533 *first = args.out.first_signaled; 534 535 return 0; 536} 537 538drm_public int amdgpu_cs_wait_fences(struct amdgpu_cs_fence *fences, 539 uint32_t fence_count, 540 bool wait_all, 541 uint64_t timeout_ns, 542 uint32_t *status, 543 uint32_t *first) 544{ 545 uint32_t i; 546 547 /* Sanity check */ 548 if (!fences || !status || !fence_count) 549 return -EINVAL; 550 551 for (i = 0; i < fence_count; i++) { 552 if (NULL == fences[i].context) 553 return -EINVAL; 554 if (fences[i].ip_type >= AMDGPU_HW_IP_NUM) 555 return -EINVAL; 556 if (fences[i].ring >= AMDGPU_CS_MAX_RINGS) 557 return -EINVAL; 558 } 559 560 *status = 0; 561 562 return amdgpu_ioctl_wait_fences(fences, fence_count, wait_all, 563 timeout_ns, status, first); 564} 565 566drm_public int amdgpu_cs_create_semaphore(amdgpu_semaphore_handle *sem) 567{ 568 struct amdgpu_semaphore *gpu_semaphore; 569 570 if (!sem) 571 return -EINVAL; 572 573 gpu_semaphore = calloc(1, sizeof(struct amdgpu_semaphore)); 574 if (!gpu_semaphore) 575 return -ENOMEM; 576 577 atomic_set(&gpu_semaphore->refcount, 1); 578 *sem = gpu_semaphore; 579 580 return 0; 581} 582 583drm_public int amdgpu_cs_signal_semaphore(amdgpu_context_handle ctx, 584 uint32_t ip_type, 585 uint32_t ip_instance, 586 uint32_t ring, 587 amdgpu_semaphore_handle sem) 588{ 589 if (!ctx || !sem) 590 return -EINVAL; 591 if (ip_type >= AMDGPU_HW_IP_NUM) 592 return -EINVAL; 593 if (ring >= AMDGPU_CS_MAX_RINGS) 594 return -EINVAL; 595 /* sem has been signaled */ 596 if (sem->signal_fence.context) 597 return -EINVAL; 598 pthread_mutex_lock(&ctx->sequence_mutex); 599 sem->signal_fence.context = ctx; 600 sem->signal_fence.ip_type = ip_type; 601 sem->signal_fence.ip_instance = ip_instance; 602 sem->signal_fence.ring = ring; 603 sem->signal_fence.fence = ctx->last_seq[ip_type][ip_instance][ring]; 604 update_references(NULL, &sem->refcount); 605 pthread_mutex_unlock(&ctx->sequence_mutex); 606 return 0; 607} 608 609drm_public int amdgpu_cs_wait_semaphore(amdgpu_context_handle ctx, 610 uint32_t ip_type, 611 uint32_t ip_instance, 612 uint32_t ring, 613 amdgpu_semaphore_handle sem) 614{ 615 if (!ctx || !sem) 616 return -EINVAL; 617 if (ip_type >= AMDGPU_HW_IP_NUM) 618 return -EINVAL; 619 if (ring >= AMDGPU_CS_MAX_RINGS) 620 return -EINVAL; 621 /* must signal first */ 622 if (!sem->signal_fence.context) 623 return -EINVAL; 624 625 pthread_mutex_lock(&ctx->sequence_mutex); 626 list_add(&sem->list, &ctx->sem_list[ip_type][ip_instance][ring]); 627 pthread_mutex_unlock(&ctx->sequence_mutex); 628 return 0; 629} 630 631static int amdgpu_cs_reset_sem(amdgpu_semaphore_handle sem) 632{ 633 if (!sem || !sem->signal_fence.context) 634 return -EINVAL; 635 636 sem->signal_fence.context = NULL; 637 sem->signal_fence.ip_type = 0; 638 sem->signal_fence.ip_instance = 0; 639 sem->signal_fence.ring = 0; 640 sem->signal_fence.fence = 0; 641 642 return 0; 643} 644 645static int amdgpu_cs_unreference_sem(amdgpu_semaphore_handle sem) 646{ 647 if (!sem) 648 return -EINVAL; 649 650 if (update_references(&sem->refcount, NULL)) 651 free(sem); 652 return 0; 653} 654 655drm_public int amdgpu_cs_destroy_semaphore(amdgpu_semaphore_handle sem) 656{ 657 return amdgpu_cs_unreference_sem(sem); 658} 659 660drm_public int amdgpu_cs_create_syncobj2(amdgpu_device_handle dev, 661 uint32_t flags, 662 uint32_t *handle) 663{ 664 if (NULL == dev) 665 return -EINVAL; 666 667 return drmSyncobjCreate(dev->fd, flags, handle); 668} 669 670drm_public int amdgpu_cs_create_syncobj(amdgpu_device_handle dev, 671 uint32_t *handle) 672{ 673 if (NULL == dev) 674 return -EINVAL; 675 676 return drmSyncobjCreate(dev->fd, 0, handle); 677} 678 679drm_public int amdgpu_cs_destroy_syncobj(amdgpu_device_handle dev, 680 uint32_t handle) 681{ 682 if (NULL == dev) 683 return -EINVAL; 684 685 return drmSyncobjDestroy(dev->fd, handle); 686} 687 688drm_public int amdgpu_cs_syncobj_reset(amdgpu_device_handle dev, 689 const uint32_t *syncobjs, 690 uint32_t syncobj_count) 691{ 692 if (NULL == dev) 693 return -EINVAL; 694 695 return drmSyncobjReset(dev->fd, syncobjs, syncobj_count); 696} 697 698drm_public int amdgpu_cs_syncobj_signal(amdgpu_device_handle dev, 699 const uint32_t *syncobjs, 700 uint32_t syncobj_count) 701{ 702 if (NULL == dev) 703 return -EINVAL; 704 705 return drmSyncobjSignal(dev->fd, syncobjs, syncobj_count); 706} 707 708drm_public int amdgpu_cs_syncobj_timeline_signal(amdgpu_device_handle dev, 709 const uint32_t *syncobjs, 710 uint64_t *points, 711 uint32_t syncobj_count) 712{ 713 if (NULL == dev) 714 return -EINVAL; 715 716 return drmSyncobjTimelineSignal(dev->fd, syncobjs, 717 points, syncobj_count); 718} 719 720drm_public int amdgpu_cs_syncobj_wait(amdgpu_device_handle dev, 721 uint32_t *handles, unsigned num_handles, 722 int64_t timeout_nsec, unsigned flags, 723 uint32_t *first_signaled) 724{ 725 if (NULL == dev) 726 return -EINVAL; 727 728 return drmSyncobjWait(dev->fd, handles, num_handles, timeout_nsec, 729 flags, first_signaled); 730} 731 732drm_public int amdgpu_cs_syncobj_timeline_wait(amdgpu_device_handle dev, 733 uint32_t *handles, uint64_t *points, 734 unsigned num_handles, 735 int64_t timeout_nsec, unsigned flags, 736 uint32_t *first_signaled) 737{ 738 if (NULL == dev) 739 return -EINVAL; 740 741 return drmSyncobjTimelineWait(dev->fd, handles, points, num_handles, 742 timeout_nsec, flags, first_signaled); 743} 744 745drm_public int amdgpu_cs_syncobj_query(amdgpu_device_handle dev, 746 uint32_t *handles, uint64_t *points, 747 unsigned num_handles) 748{ 749 if (NULL == dev) 750 return -EINVAL; 751 752 return drmSyncobjQuery(dev->fd, handles, points, num_handles); 753} 754 755drm_public int amdgpu_cs_syncobj_query2(amdgpu_device_handle dev, 756 uint32_t *handles, uint64_t *points, 757 unsigned num_handles, uint32_t flags) 758{ 759 if (!dev) 760 return -EINVAL; 761 762 return drmSyncobjQuery2(dev->fd, handles, points, num_handles, flags); 763} 764 765drm_public int amdgpu_cs_export_syncobj(amdgpu_device_handle dev, 766 uint32_t handle, 767 int *shared_fd) 768{ 769 if (NULL == dev) 770 return -EINVAL; 771 772 return drmSyncobjHandleToFD(dev->fd, handle, shared_fd); 773} 774 775drm_public int amdgpu_cs_import_syncobj(amdgpu_device_handle dev, 776 int shared_fd, 777 uint32_t *handle) 778{ 779 if (NULL == dev) 780 return -EINVAL; 781 782 return drmSyncobjFDToHandle(dev->fd, shared_fd, handle); 783} 784 785drm_public int amdgpu_cs_syncobj_export_sync_file(amdgpu_device_handle dev, 786 uint32_t syncobj, 787 int *sync_file_fd) 788{ 789 if (NULL == dev) 790 return -EINVAL; 791 792 return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd); 793} 794 795drm_public int amdgpu_cs_syncobj_import_sync_file(amdgpu_device_handle dev, 796 uint32_t syncobj, 797 int sync_file_fd) 798{ 799 if (NULL == dev) 800 return -EINVAL; 801 802 return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd); 803} 804 805drm_public int amdgpu_cs_syncobj_export_sync_file2(amdgpu_device_handle dev, 806 uint32_t syncobj, 807 uint64_t point, 808 uint32_t flags, 809 int *sync_file_fd) 810{ 811 uint32_t binary_handle; 812 int ret; 813 814 if (NULL == dev) 815 return -EINVAL; 816 817 if (!point) 818 return drmSyncobjExportSyncFile(dev->fd, syncobj, sync_file_fd); 819 820 ret = drmSyncobjCreate(dev->fd, 0, &binary_handle); 821 if (ret) 822 return ret; 823 824 ret = drmSyncobjTransfer(dev->fd, binary_handle, 0, 825 syncobj, point, flags); 826 if (ret) 827 goto out; 828 ret = drmSyncobjExportSyncFile(dev->fd, binary_handle, sync_file_fd); 829out: 830 drmSyncobjDestroy(dev->fd, binary_handle); 831 return ret; 832} 833 834drm_public int amdgpu_cs_syncobj_import_sync_file2(amdgpu_device_handle dev, 835 uint32_t syncobj, 836 uint64_t point, 837 int sync_file_fd) 838{ 839 uint32_t binary_handle; 840 int ret; 841 842 if (NULL == dev) 843 return -EINVAL; 844 845 if (!point) 846 return drmSyncobjImportSyncFile(dev->fd, syncobj, sync_file_fd); 847 848 ret = drmSyncobjCreate(dev->fd, 0, &binary_handle); 849 if (ret) 850 return ret; 851 ret = drmSyncobjImportSyncFile(dev->fd, binary_handle, sync_file_fd); 852 if (ret) 853 goto out; 854 ret = drmSyncobjTransfer(dev->fd, syncobj, point, 855 binary_handle, 0, 0); 856out: 857 drmSyncobjDestroy(dev->fd, binary_handle); 858 return ret; 859} 860 861drm_public int amdgpu_cs_syncobj_transfer(amdgpu_device_handle dev, 862 uint32_t dst_handle, 863 uint64_t dst_point, 864 uint32_t src_handle, 865 uint64_t src_point, 866 uint32_t flags) 867{ 868 if (NULL == dev) 869 return -EINVAL; 870 871 return drmSyncobjTransfer(dev->fd, 872 dst_handle, dst_point, 873 src_handle, src_point, 874 flags); 875} 876 877drm_public int amdgpu_cs_submit_raw(amdgpu_device_handle dev, 878 amdgpu_context_handle context, 879 amdgpu_bo_list_handle bo_list_handle, 880 int num_chunks, 881 struct drm_amdgpu_cs_chunk *chunks, 882 uint64_t *seq_no) 883{ 884 union drm_amdgpu_cs cs; 885 uint64_t *chunk_array; 886 int i, r; 887 if (num_chunks == 0) 888 return -EINVAL; 889 890 memset(&cs, 0, sizeof(cs)); 891 chunk_array = alloca(sizeof(uint64_t) * num_chunks); 892 for (i = 0; i < num_chunks; i++) 893 chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; 894 cs.in.chunks = (uint64_t)(uintptr_t)chunk_array; 895 cs.in.ctx_id = context->id; 896 cs.in.bo_list_handle = bo_list_handle ? bo_list_handle->handle : 0; 897 cs.in.num_chunks = num_chunks; 898 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS, 899 &cs, sizeof(cs)); 900 if (r) 901 return r; 902 903 if (seq_no) 904 *seq_no = cs.out.handle; 905 return 0; 906} 907 908drm_public int amdgpu_cs_submit_raw2(amdgpu_device_handle dev, 909 amdgpu_context_handle context, 910 uint32_t bo_list_handle, 911 int num_chunks, 912 struct drm_amdgpu_cs_chunk *chunks, 913 uint64_t *seq_no) 914{ 915 union drm_amdgpu_cs cs; 916 uint64_t *chunk_array; 917 int i, r; 918 919 memset(&cs, 0, sizeof(cs)); 920 chunk_array = alloca(sizeof(uint64_t) * num_chunks); 921 for (i = 0; i < num_chunks; i++) 922 chunk_array[i] = (uint64_t)(uintptr_t)&chunks[i]; 923 cs.in.chunks = (uint64_t)(uintptr_t)chunk_array; 924 cs.in.ctx_id = context->id; 925 cs.in.bo_list_handle = bo_list_handle; 926 cs.in.num_chunks = num_chunks; 927 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_CS, 928 &cs, sizeof(cs)); 929 if (!r && seq_no) 930 *seq_no = cs.out.handle; 931 return r; 932} 933 934drm_public void amdgpu_cs_chunk_fence_info_to_data(struct amdgpu_cs_fence_info *fence_info, 935 struct drm_amdgpu_cs_chunk_data *data) 936{ 937 data->fence_data.handle = fence_info->handle->handle; 938 data->fence_data.offset = fence_info->offset * sizeof(uint64_t); 939} 940 941drm_public void amdgpu_cs_chunk_fence_to_dep(struct amdgpu_cs_fence *fence, 942 struct drm_amdgpu_cs_chunk_dep *dep) 943{ 944 dep->ip_type = fence->ip_type; 945 dep->ip_instance = fence->ip_instance; 946 dep->ring = fence->ring; 947 dep->ctx_id = fence->context->id; 948 dep->handle = fence->fence; 949} 950 951drm_public int amdgpu_cs_fence_to_handle(amdgpu_device_handle dev, 952 struct amdgpu_cs_fence *fence, 953 uint32_t what, 954 uint32_t *out_handle) 955{ 956 union drm_amdgpu_fence_to_handle fth; 957 int r; 958 959 memset(&fth, 0, sizeof(fth)); 960 fth.in.fence.ctx_id = fence->context->id; 961 fth.in.fence.ip_type = fence->ip_type; 962 fth.in.fence.ip_instance = fence->ip_instance; 963 fth.in.fence.ring = fence->ring; 964 fth.in.fence.seq_no = fence->fence; 965 fth.in.what = what; 966 967 r = drmCommandWriteRead(dev->fd, DRM_AMDGPU_FENCE_TO_HANDLE, 968 &fth, sizeof(fth)); 969 if (r == 0) 970 *out_handle = fth.out.handle; 971 return r; 972} 973