1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2020-2024 Intel Corporation 4 */ 5 6 #include <drm/drm_file.h> 7 8 #include <linux/bitfield.h> 9 #include <linux/highmem.h> 10 #include <linux/pci.h> 11 #include <linux/module.h> 12 #include <uapi/drm/ivpu_accel.h> 13 14 #include "ivpu_drv.h" 15 #include "ivpu_fw.h" 16 #include "ivpu_hw.h" 17 #include "ivpu_ipc.h" 18 #include "ivpu_job.h" 19 #include "ivpu_jsm_msg.h" 20 #include "ivpu_pm.h" 21 #include "ivpu_trace.h" 22 #include "vpu_boot_api.h" 23 24 #define CMD_BUF_IDX 0 25 #define JOB_MAX_BUFFER_COUNT 65535 26 27 static void ivpu_cmdq_ring_db(struct ivpu_device *vdev, struct ivpu_cmdq *cmdq) 28 { 29 ivpu_hw_db_set(vdev, cmdq->db_id); 30 } 31 32 static int ivpu_preemption_buffers_create(struct ivpu_device *vdev, 33 struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) 34 { 35 u64 primary_size = ALIGN(vdev->fw->primary_preempt_buf_size, PAGE_SIZE); 36 u64 secondary_size = ALIGN(vdev->fw->secondary_preempt_buf_size, PAGE_SIZE); 37 38 if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) 39 return 0; 40 41 cmdq->primary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &vdev->hw->ranges.user, 42 primary_size, DRM_IVPU_BO_WC); 43 if (!cmdq->primary_preempt_buf) { 44 ivpu_err(vdev, "Failed to create primary preemption buffer\n"); 45 return -ENOMEM; 46 } 47 48 cmdq->secondary_preempt_buf = ivpu_bo_create(vdev, &file_priv->ctx, &vdev->hw->ranges.shave, 49 secondary_size, DRM_IVPU_BO_WC); 50 if (!cmdq->secondary_preempt_buf) { 51 ivpu_err(vdev, "Failed to create secondary preemption buffer\n"); 52 goto err_free_primary; 53 } 54 55 return 0; 56 57 err_free_primary: 58 ivpu_bo_free(cmdq->primary_preempt_buf); 59 cmdq->primary_preempt_buf = NULL; 60 return -ENOMEM; 61 } 62 63 static void ivpu_preemption_buffers_free(struct ivpu_device *vdev, 64 struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) 65 { 66 if (vdev->fw->sched_mode != VPU_SCHEDULING_MODE_HW) 67 return; 68 69 if (cmdq->primary_preempt_buf) 70 ivpu_bo_free(cmdq->primary_preempt_buf); 71 if (cmdq->secondary_preempt_buf) 72 ivpu_bo_free(cmdq->secondary_preempt_buf); 73 } 74 75 static int ivpu_id_alloc(struct xarray *xa, u32 *id, void *entry, struct xa_limit *limit, 76 const struct xa_limit default_limit) 77 { 78 int ret; 79 80 ret = __xa_alloc(xa, id, entry, *limit, GFP_KERNEL); 81 if (ret) { 82 limit->min = default_limit.min; 83 ret = __xa_alloc(xa, id, entry, *limit, GFP_KERNEL); 84 if (ret) 85 return ret; 86 } 87 88 limit->min = *id + 1; 89 if (limit->min > limit->max) 90 limit->min = default_limit.min; 91 92 return ret; 93 } 94 95 static struct ivpu_cmdq *ivpu_cmdq_alloc(struct ivpu_file_priv *file_priv) 96 { 97 struct ivpu_device *vdev = file_priv->vdev; 98 struct ivpu_cmdq *cmdq; 99 int ret; 100 101 cmdq = kzalloc(sizeof(*cmdq), GFP_KERNEL); 102 if (!cmdq) 103 return NULL; 104 105 xa_lock(&vdev->db_xa); /* lock here to protect db_limit */ 106 ret = ivpu_id_alloc(&vdev->db_xa, &cmdq->db_id, NULL, &vdev->db_limit, 107 vdev->default_db_limit); 108 xa_unlock(&vdev->db_xa); 109 if (ret) { 110 ivpu_err(vdev, "Failed to allocate doorbell id: %d\n", ret); 111 goto err_free_cmdq; 112 } 113 114 cmdq->mem = ivpu_bo_create_global(vdev, SZ_4K, DRM_IVPU_BO_WC | DRM_IVPU_BO_MAPPABLE); 115 if (!cmdq->mem) 116 goto err_erase_xa; 117 118 ret = ivpu_preemption_buffers_create(vdev, file_priv, cmdq); 119 if (ret) 120 ivpu_warn(vdev, "Failed to allocate preemption buffers, preemption limited\n"); 121 122 return cmdq; 123 124 err_erase_xa: 125 xa_erase(&vdev->db_xa, cmdq->db_id); 126 err_free_cmdq: 127 kfree(cmdq); 128 return NULL; 129 } 130 131 static void ivpu_cmdq_free(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) 132 { 133 if (!cmdq) 134 return; 135 136 ivpu_preemption_buffers_free(file_priv->vdev, file_priv, cmdq); 137 ivpu_bo_free(cmdq->mem); 138 xa_erase(&file_priv->vdev->db_xa, cmdq->db_id); 139 kfree(cmdq); 140 } 141 142 static int ivpu_hws_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, 143 u8 priority) 144 { 145 struct ivpu_device *vdev = file_priv->vdev; 146 int ret; 147 148 ret = ivpu_jsm_hws_create_cmdq(vdev, file_priv->ctx.id, file_priv->ctx.id, cmdq->db_id, 149 task_pid_nr(current), engine, 150 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 151 if (ret) 152 return ret; 153 154 ret = ivpu_jsm_hws_set_context_sched_properties(vdev, file_priv->ctx.id, cmdq->db_id, 155 priority); 156 if (ret) 157 return ret; 158 159 return 0; 160 } 161 162 static int ivpu_register_db(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) 163 { 164 struct ivpu_device *vdev = file_priv->vdev; 165 int ret; 166 167 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) 168 ret = ivpu_jsm_hws_register_db(vdev, file_priv->ctx.id, cmdq->db_id, cmdq->db_id, 169 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 170 else 171 ret = ivpu_jsm_register_db(vdev, file_priv->ctx.id, cmdq->db_id, 172 cmdq->mem->vpu_addr, ivpu_bo_size(cmdq->mem)); 173 174 if (!ret) 175 ivpu_dbg(vdev, JOB, "DB %d registered to ctx %d\n", cmdq->db_id, file_priv->ctx.id); 176 177 return ret; 178 } 179 180 static int 181 ivpu_cmdq_init(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq, u16 engine, u8 priority) 182 { 183 struct ivpu_device *vdev = file_priv->vdev; 184 struct vpu_job_queue_header *jobq_header; 185 int ret; 186 187 lockdep_assert_held(&file_priv->lock); 188 189 if (cmdq->db_registered) 190 return 0; 191 192 cmdq->entry_count = (u32)((ivpu_bo_size(cmdq->mem) - sizeof(struct vpu_job_queue_header)) / 193 sizeof(struct vpu_job_queue_entry)); 194 195 cmdq->jobq = (struct vpu_job_queue *)ivpu_bo_vaddr(cmdq->mem); 196 jobq_header = &cmdq->jobq->header; 197 jobq_header->engine_idx = engine; 198 jobq_header->head = 0; 199 jobq_header->tail = 0; 200 if (ivpu_test_mode & IVPU_TEST_MODE_TURBO) { 201 ivpu_dbg(vdev, JOB, "Turbo mode enabled"); 202 jobq_header->flags = VPU_JOB_QUEUE_FLAGS_TURBO_MODE; 203 } 204 205 wmb(); /* Flush WC buffer for jobq->header */ 206 207 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { 208 ret = ivpu_hws_cmdq_init(file_priv, cmdq, engine, priority); 209 if (ret) 210 return ret; 211 } 212 213 ret = ivpu_register_db(file_priv, cmdq); 214 if (ret) 215 return ret; 216 217 cmdq->db_registered = true; 218 219 return 0; 220 } 221 222 static int ivpu_cmdq_fini(struct ivpu_file_priv *file_priv, struct ivpu_cmdq *cmdq) 223 { 224 struct ivpu_device *vdev = file_priv->vdev; 225 int ret; 226 227 lockdep_assert_held(&file_priv->lock); 228 229 if (!cmdq->db_registered) 230 return 0; 231 232 cmdq->db_registered = false; 233 234 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW) { 235 ret = ivpu_jsm_hws_destroy_cmdq(vdev, file_priv->ctx.id, cmdq->db_id); 236 if (!ret) 237 ivpu_dbg(vdev, JOB, "Command queue %d destroyed\n", cmdq->db_id); 238 } 239 240 ret = ivpu_jsm_unregister_db(vdev, cmdq->db_id); 241 if (!ret) 242 ivpu_dbg(vdev, JOB, "DB %d unregistered\n", cmdq->db_id); 243 244 return 0; 245 } 246 247 static struct ivpu_cmdq *ivpu_cmdq_acquire(struct ivpu_file_priv *file_priv, u16 engine, 248 u8 priority) 249 { 250 int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); 251 struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; 252 int ret; 253 254 lockdep_assert_held(&file_priv->lock); 255 256 if (!cmdq) { 257 cmdq = ivpu_cmdq_alloc(file_priv); 258 if (!cmdq) 259 return NULL; 260 file_priv->cmdq[cmdq_idx] = cmdq; 261 } 262 263 ret = ivpu_cmdq_init(file_priv, cmdq, engine, priority); 264 if (ret) 265 return NULL; 266 267 return cmdq; 268 } 269 270 static void ivpu_cmdq_release_locked(struct ivpu_file_priv *file_priv, u16 engine, u8 priority) 271 { 272 int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); 273 struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; 274 275 lockdep_assert_held(&file_priv->lock); 276 277 if (cmdq) { 278 file_priv->cmdq[cmdq_idx] = NULL; 279 ivpu_cmdq_fini(file_priv, cmdq); 280 ivpu_cmdq_free(file_priv, cmdq); 281 } 282 } 283 284 void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv) 285 { 286 u16 engine; 287 u8 priority; 288 289 lockdep_assert_held(&file_priv->lock); 290 291 for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) 292 for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) 293 ivpu_cmdq_release_locked(file_priv, engine, priority); 294 } 295 296 /* 297 * Mark the doorbell as unregistered 298 * This function needs to be called when the VPU hardware is restarted 299 * and FW loses job queue state. The next time job queue is used it 300 * will be registered again. 301 */ 302 static void ivpu_cmdq_reset(struct ivpu_file_priv *file_priv) 303 { 304 u16 engine; 305 u8 priority; 306 307 mutex_lock(&file_priv->lock); 308 309 for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) { 310 for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { 311 int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); 312 struct ivpu_cmdq *cmdq = file_priv->cmdq[cmdq_idx]; 313 314 if (cmdq) 315 cmdq->db_registered = false; 316 } 317 } 318 319 mutex_unlock(&file_priv->lock); 320 } 321 322 void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev) 323 { 324 struct ivpu_file_priv *file_priv; 325 unsigned long ctx_id; 326 327 mutex_lock(&vdev->context_list_lock); 328 329 xa_for_each(&vdev->context_xa, ctx_id, file_priv) 330 ivpu_cmdq_reset(file_priv); 331 332 mutex_unlock(&vdev->context_list_lock); 333 } 334 335 static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv) 336 { 337 u16 engine; 338 u8 priority; 339 340 for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) { 341 for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) { 342 int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority); 343 344 if (file_priv->cmdq[cmdq_idx]) 345 ivpu_cmdq_fini(file_priv, file_priv->cmdq[cmdq_idx]); 346 } 347 } 348 } 349 350 void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv) 351 { 352 struct ivpu_device *vdev = file_priv->vdev; 353 354 lockdep_assert_held(&file_priv->lock); 355 356 ivpu_cmdq_fini_all(file_priv); 357 358 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_OS) 359 ivpu_jsm_context_release(vdev, file_priv->ctx.id); 360 } 361 362 static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job) 363 { 364 struct ivpu_device *vdev = job->vdev; 365 struct vpu_job_queue_header *header = &cmdq->jobq->header; 366 struct vpu_job_queue_entry *entry; 367 u32 tail = READ_ONCE(header->tail); 368 u32 next_entry = (tail + 1) % cmdq->entry_count; 369 370 /* Check if there is space left in job queue */ 371 if (next_entry == header->head) { 372 ivpu_dbg(vdev, JOB, "Job queue full: ctx %d engine %d db %d head %d tail %d\n", 373 job->file_priv->ctx.id, job->engine_idx, cmdq->db_id, header->head, tail); 374 return -EBUSY; 375 } 376 377 entry = &cmdq->jobq->slot[tail].job; 378 entry->batch_buf_addr = job->cmd_buf_vpu_addr; 379 entry->job_id = job->job_id; 380 entry->flags = 0; 381 if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_SUBMISSION)) 382 entry->flags = VPU_JOB_FLAGS_NULL_SUBMISSION_MASK; 383 384 if (vdev->fw->sched_mode == VPU_SCHEDULING_MODE_HW && 385 (unlikely(!(ivpu_test_mode & IVPU_TEST_MODE_PREEMPTION_DISABLE)))) { 386 if (cmdq->primary_preempt_buf) { 387 entry->primary_preempt_buf_addr = cmdq->primary_preempt_buf->vpu_addr; 388 entry->primary_preempt_buf_size = ivpu_bo_size(cmdq->primary_preempt_buf); 389 } 390 391 if (cmdq->secondary_preempt_buf) { 392 entry->secondary_preempt_buf_addr = cmdq->secondary_preempt_buf->vpu_addr; 393 entry->secondary_preempt_buf_size = 394 ivpu_bo_size(cmdq->secondary_preempt_buf); 395 } 396 } 397 398 wmb(); /* Ensure that tail is updated after filling entry */ 399 header->tail = next_entry; 400 wmb(); /* Flush WC buffer for jobq header */ 401 402 return 0; 403 } 404 405 struct ivpu_fence { 406 struct dma_fence base; 407 spinlock_t lock; /* protects base */ 408 struct ivpu_device *vdev; 409 }; 410 411 static inline struct ivpu_fence *to_vpu_fence(struct dma_fence *fence) 412 { 413 return container_of(fence, struct ivpu_fence, base); 414 } 415 416 static const char *ivpu_fence_get_driver_name(struct dma_fence *fence) 417 { 418 return DRIVER_NAME; 419 } 420 421 static const char *ivpu_fence_get_timeline_name(struct dma_fence *fence) 422 { 423 struct ivpu_fence *ivpu_fence = to_vpu_fence(fence); 424 425 return dev_name(ivpu_fence->vdev->drm.dev); 426 } 427 428 static const struct dma_fence_ops ivpu_fence_ops = { 429 .get_driver_name = ivpu_fence_get_driver_name, 430 .get_timeline_name = ivpu_fence_get_timeline_name, 431 }; 432 433 static struct dma_fence *ivpu_fence_create(struct ivpu_device *vdev) 434 { 435 struct ivpu_fence *fence; 436 437 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 438 if (!fence) 439 return NULL; 440 441 fence->vdev = vdev; 442 spin_lock_init(&fence->lock); 443 dma_fence_init(&fence->base, &ivpu_fence_ops, &fence->lock, dma_fence_context_alloc(1), 1); 444 445 return &fence->base; 446 } 447 448 static void ivpu_job_destroy(struct ivpu_job *job) 449 { 450 struct ivpu_device *vdev = job->vdev; 451 u32 i; 452 453 ivpu_dbg(vdev, JOB, "Job destroyed: id %3u ctx %2d engine %d", 454 job->job_id, job->file_priv->ctx.id, job->engine_idx); 455 456 for (i = 0; i < job->bo_count; i++) 457 if (job->bos[i]) 458 drm_gem_object_put(&job->bos[i]->base.base); 459 460 dma_fence_put(job->done_fence); 461 ivpu_file_priv_put(&job->file_priv); 462 kfree(job); 463 } 464 465 static struct ivpu_job * 466 ivpu_job_create(struct ivpu_file_priv *file_priv, u32 engine_idx, u32 bo_count) 467 { 468 struct ivpu_device *vdev = file_priv->vdev; 469 struct ivpu_job *job; 470 471 job = kzalloc(struct_size(job, bos, bo_count), GFP_KERNEL); 472 if (!job) 473 return NULL; 474 475 job->vdev = vdev; 476 job->engine_idx = engine_idx; 477 job->bo_count = bo_count; 478 job->done_fence = ivpu_fence_create(vdev); 479 if (!job->done_fence) { 480 ivpu_warn_ratelimited(vdev, "Failed to create a fence\n"); 481 goto err_free_job; 482 } 483 484 job->file_priv = ivpu_file_priv_get(file_priv); 485 486 trace_job("create", job); 487 ivpu_dbg(vdev, JOB, "Job created: ctx %2d engine %d", file_priv->ctx.id, job->engine_idx); 488 return job; 489 490 err_free_job: 491 kfree(job); 492 return NULL; 493 } 494 495 static struct ivpu_job *ivpu_job_remove_from_submitted_jobs(struct ivpu_device *vdev, u32 job_id) 496 { 497 struct ivpu_job *job; 498 499 xa_lock(&vdev->submitted_jobs_xa); 500 job = __xa_erase(&vdev->submitted_jobs_xa, job_id); 501 502 if (xa_empty(&vdev->submitted_jobs_xa) && job) { 503 vdev->busy_time = ktime_add(ktime_sub(ktime_get(), vdev->busy_start_ts), 504 vdev->busy_time); 505 } 506 507 xa_unlock(&vdev->submitted_jobs_xa); 508 509 return job; 510 } 511 512 static int ivpu_job_signal_and_destroy(struct ivpu_device *vdev, u32 job_id, u32 job_status) 513 { 514 struct ivpu_job *job; 515 516 job = ivpu_job_remove_from_submitted_jobs(vdev, job_id); 517 if (!job) 518 return -ENOENT; 519 520 if (job->file_priv->has_mmu_faults) 521 job_status = DRM_IVPU_JOB_STATUS_ABORTED; 522 523 job->bos[CMD_BUF_IDX]->job_status = job_status; 524 dma_fence_signal(job->done_fence); 525 526 trace_job("done", job); 527 ivpu_dbg(vdev, JOB, "Job complete: id %3u ctx %2d engine %d status 0x%x\n", 528 job->job_id, job->file_priv->ctx.id, job->engine_idx, job_status); 529 530 ivpu_job_destroy(job); 531 ivpu_stop_job_timeout_detection(vdev); 532 533 ivpu_rpm_put(vdev); 534 return 0; 535 } 536 537 void ivpu_jobs_abort_all(struct ivpu_device *vdev) 538 { 539 struct ivpu_job *job; 540 unsigned long id; 541 542 xa_for_each(&vdev->submitted_jobs_xa, id, job) 543 ivpu_job_signal_and_destroy(vdev, id, DRM_IVPU_JOB_STATUS_ABORTED); 544 } 545 546 static int ivpu_job_submit(struct ivpu_job *job, u8 priority) 547 { 548 struct ivpu_file_priv *file_priv = job->file_priv; 549 struct ivpu_device *vdev = job->vdev; 550 struct ivpu_cmdq *cmdq; 551 bool is_first_job; 552 int ret; 553 554 ret = ivpu_rpm_get(vdev); 555 if (ret < 0) 556 return ret; 557 558 mutex_lock(&file_priv->lock); 559 560 cmdq = ivpu_cmdq_acquire(file_priv, job->engine_idx, priority); 561 if (!cmdq) { 562 ivpu_warn_ratelimited(vdev, "Failed to get job queue, ctx %d engine %d prio %d\n", 563 file_priv->ctx.id, job->engine_idx, priority); 564 ret = -EINVAL; 565 goto err_unlock_file_priv; 566 } 567 568 xa_lock(&vdev->submitted_jobs_xa); 569 is_first_job = xa_empty(&vdev->submitted_jobs_xa); 570 ret = ivpu_id_alloc(&vdev->submitted_jobs_xa, &job->job_id, job, &file_priv->job_limit, 571 file_priv->default_job_limit); 572 if (ret) { 573 ivpu_dbg(vdev, JOB, "Too many active jobs in ctx %d\n", 574 file_priv->ctx.id); 575 ret = -EBUSY; 576 goto err_unlock_submitted_jobs_xa; 577 } 578 579 ret = ivpu_cmdq_push_job(cmdq, job); 580 if (ret) 581 goto err_erase_xa; 582 583 ivpu_start_job_timeout_detection(vdev); 584 585 if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) { 586 cmdq->jobq->header.head = cmdq->jobq->header.tail; 587 wmb(); /* Flush WC buffer for jobq header */ 588 } else { 589 ivpu_cmdq_ring_db(vdev, cmdq); 590 if (is_first_job) 591 vdev->busy_start_ts = ktime_get(); 592 } 593 594 trace_job("submit", job); 595 ivpu_dbg(vdev, JOB, "Job submitted: id %3u ctx %2d engine %d prio %d addr 0x%llx next %d\n", 596 job->job_id, file_priv->ctx.id, job->engine_idx, priority, 597 job->cmd_buf_vpu_addr, cmdq->jobq->header.tail); 598 599 xa_unlock(&vdev->submitted_jobs_xa); 600 601 mutex_unlock(&file_priv->lock); 602 603 if (unlikely(ivpu_test_mode & IVPU_TEST_MODE_NULL_HW)) 604 ivpu_job_signal_and_destroy(vdev, job->job_id, VPU_JSM_STATUS_SUCCESS); 605 606 return 0; 607 608 err_erase_xa: 609 __xa_erase(&vdev->submitted_jobs_xa, job->job_id); 610 err_unlock_submitted_jobs_xa: 611 xa_unlock(&vdev->submitted_jobs_xa); 612 err_unlock_file_priv: 613 mutex_unlock(&file_priv->lock); 614 ivpu_rpm_put(vdev); 615 return ret; 616 } 617 618 static int 619 ivpu_job_prepare_bos_for_submit(struct drm_file *file, struct ivpu_job *job, u32 *buf_handles, 620 u32 buf_count, u32 commands_offset) 621 { 622 struct ivpu_file_priv *file_priv = file->driver_priv; 623 struct ivpu_device *vdev = file_priv->vdev; 624 struct ww_acquire_ctx acquire_ctx; 625 enum dma_resv_usage usage; 626 struct ivpu_bo *bo; 627 int ret; 628 u32 i; 629 630 for (i = 0; i < buf_count; i++) { 631 struct drm_gem_object *obj = drm_gem_object_lookup(file, buf_handles[i]); 632 633 if (!obj) 634 return -ENOENT; 635 636 job->bos[i] = to_ivpu_bo(obj); 637 638 ret = ivpu_bo_pin(job->bos[i]); 639 if (ret) 640 return ret; 641 } 642 643 bo = job->bos[CMD_BUF_IDX]; 644 if (!dma_resv_test_signaled(bo->base.base.resv, DMA_RESV_USAGE_READ)) { 645 ivpu_warn(vdev, "Buffer is already in use\n"); 646 return -EBUSY; 647 } 648 649 if (commands_offset >= ivpu_bo_size(bo)) { 650 ivpu_warn(vdev, "Invalid command buffer offset %u\n", commands_offset); 651 return -EINVAL; 652 } 653 654 job->cmd_buf_vpu_addr = bo->vpu_addr + commands_offset; 655 656 ret = drm_gem_lock_reservations((struct drm_gem_object **)job->bos, buf_count, 657 &acquire_ctx); 658 if (ret) { 659 ivpu_warn(vdev, "Failed to lock reservations: %d\n", ret); 660 return ret; 661 } 662 663 for (i = 0; i < buf_count; i++) { 664 ret = dma_resv_reserve_fences(job->bos[i]->base.base.resv, 1); 665 if (ret) { 666 ivpu_warn(vdev, "Failed to reserve fences: %d\n", ret); 667 goto unlock_reservations; 668 } 669 } 670 671 for (i = 0; i < buf_count; i++) { 672 usage = (i == CMD_BUF_IDX) ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_BOOKKEEP; 673 dma_resv_add_fence(job->bos[i]->base.base.resv, job->done_fence, usage); 674 } 675 676 unlock_reservations: 677 drm_gem_unlock_reservations((struct drm_gem_object **)job->bos, buf_count, &acquire_ctx); 678 679 wmb(); /* Flush write combining buffers */ 680 681 return ret; 682 } 683 684 static inline u8 ivpu_job_to_hws_priority(struct ivpu_file_priv *file_priv, u8 priority) 685 { 686 if (priority == DRM_IVPU_JOB_PRIORITY_DEFAULT) 687 return DRM_IVPU_JOB_PRIORITY_NORMAL; 688 689 return priority - 1; 690 } 691 692 int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file) 693 { 694 struct ivpu_file_priv *file_priv = file->driver_priv; 695 struct ivpu_device *vdev = file_priv->vdev; 696 struct drm_ivpu_submit *params = data; 697 struct ivpu_job *job; 698 u32 *buf_handles; 699 int idx, ret; 700 u8 priority; 701 702 if (params->engine > DRM_IVPU_ENGINE_COPY) 703 return -EINVAL; 704 705 if (params->priority > DRM_IVPU_JOB_PRIORITY_REALTIME) 706 return -EINVAL; 707 708 if (params->buffer_count == 0 || params->buffer_count > JOB_MAX_BUFFER_COUNT) 709 return -EINVAL; 710 711 if (!IS_ALIGNED(params->commands_offset, 8)) 712 return -EINVAL; 713 714 if (!file_priv->ctx.id) 715 return -EINVAL; 716 717 if (file_priv->has_mmu_faults) 718 return -EBADFD; 719 720 buf_handles = kcalloc(params->buffer_count, sizeof(u32), GFP_KERNEL); 721 if (!buf_handles) 722 return -ENOMEM; 723 724 ret = copy_from_user(buf_handles, 725 (void __user *)params->buffers_ptr, 726 params->buffer_count * sizeof(u32)); 727 if (ret) { 728 ret = -EFAULT; 729 goto err_free_handles; 730 } 731 732 if (!drm_dev_enter(&vdev->drm, &idx)) { 733 ret = -ENODEV; 734 goto err_free_handles; 735 } 736 737 ivpu_dbg(vdev, JOB, "Submit ioctl: ctx %u buf_count %u\n", 738 file_priv->ctx.id, params->buffer_count); 739 740 job = ivpu_job_create(file_priv, params->engine, params->buffer_count); 741 if (!job) { 742 ivpu_err(vdev, "Failed to create job\n"); 743 ret = -ENOMEM; 744 goto err_exit_dev; 745 } 746 747 ret = ivpu_job_prepare_bos_for_submit(file, job, buf_handles, params->buffer_count, 748 params->commands_offset); 749 if (ret) { 750 ivpu_err(vdev, "Failed to prepare job: %d\n", ret); 751 goto err_destroy_job; 752 } 753 754 priority = ivpu_job_to_hws_priority(file_priv, params->priority); 755 756 down_read(&vdev->pm->reset_lock); 757 ret = ivpu_job_submit(job, priority); 758 up_read(&vdev->pm->reset_lock); 759 if (ret) 760 goto err_signal_fence; 761 762 drm_dev_exit(idx); 763 kfree(buf_handles); 764 return ret; 765 766 err_signal_fence: 767 dma_fence_signal(job->done_fence); 768 err_destroy_job: 769 ivpu_job_destroy(job); 770 err_exit_dev: 771 drm_dev_exit(idx); 772 err_free_handles: 773 kfree(buf_handles); 774 return ret; 775 } 776 777 static void 778 ivpu_job_done_callback(struct ivpu_device *vdev, struct ivpu_ipc_hdr *ipc_hdr, 779 struct vpu_jsm_msg *jsm_msg) 780 { 781 struct vpu_ipc_msg_payload_job_done *payload; 782 int ret; 783 784 if (!jsm_msg) { 785 ivpu_err(vdev, "IPC message has no JSM payload\n"); 786 return; 787 } 788 789 if (jsm_msg->result != VPU_JSM_STATUS_SUCCESS) { 790 ivpu_err(vdev, "Invalid JSM message result: %d\n", jsm_msg->result); 791 return; 792 } 793 794 payload = (struct vpu_ipc_msg_payload_job_done *)&jsm_msg->payload; 795 ret = ivpu_job_signal_and_destroy(vdev, payload->job_id, payload->job_status); 796 if (!ret && !xa_empty(&vdev->submitted_jobs_xa)) 797 ivpu_start_job_timeout_detection(vdev); 798 } 799 800 void ivpu_job_done_consumer_init(struct ivpu_device *vdev) 801 { 802 ivpu_ipc_consumer_add(vdev, &vdev->job_done_consumer, 803 VPU_IPC_CHAN_JOB_RET, ivpu_job_done_callback); 804 } 805 806 void ivpu_job_done_consumer_fini(struct ivpu_device *vdev) 807 { 808 ivpu_ipc_consumer_del(vdev, &vdev->job_done_consumer); 809 } 810