1 // SPDX-License-Identifier: GPL-2.0 or MIT 2 /* Copyright 2018 Marty E. Plummer <hanetzer@startmail.com> */ 3 /* Copyright 2019 Linaro, Ltd., Rob Herring <robh@kernel.org> */ 4 /* Copyright 2019 Collabora ltd. */ 5 6 #ifdef CONFIG_ARM_ARCH_TIMER 7 #include <asm/arch_timer.h> 8 #endif 9 10 #include <linux/list.h> 11 #include <linux/module.h> 12 #include <linux/of_platform.h> 13 #include <linux/pagemap.h> 14 #include <linux/platform_device.h> 15 #include <linux/pm_runtime.h> 16 #include <linux/sched/clock.h> 17 #include <linux/time64.h> 18 #include <linux/time_namespace.h> 19 20 #include <drm/drm_auth.h> 21 #include <drm/drm_debugfs.h> 22 #include <drm/drm_drv.h> 23 #include <drm/drm_exec.h> 24 #include <drm/drm_file.h> 25 #include <drm/drm_ioctl.h> 26 #include <drm/drm_print.h> 27 #include <drm/drm_syncobj.h> 28 #include <drm/drm_utils.h> 29 #include <drm/gpu_scheduler.h> 30 #include <drm/panthor_drm.h> 31 32 #include "panthor_devfreq.h" 33 #include "panthor_device.h" 34 #include "panthor_drv.h" 35 #include "panthor_fw.h" 36 #include "panthor_gem.h" 37 #include "panthor_gpu.h" 38 #include "panthor_heap.h" 39 #include "panthor_mmu.h" 40 #include "panthor_sched.h" 41 42 /** 43 * DOC: user <-> kernel object copy helpers. 44 */ 45 46 /** 47 * panthor_set_uobj() - Copy kernel object to user object. 48 * @usr_ptr: Users pointer. 49 * @usr_size: Size of the user object. 50 * @min_size: Minimum size for this object. 51 * @kern_size: Size of the kernel object. 52 * @in: Address of the kernel object to copy. 53 * 54 * Helper automating kernel -> user object copies. 55 * 56 * Don't use this function directly, use PANTHOR_UOBJ_SET() instead. 57 * 58 * Return: 0 on success, a negative error code otherwise. 59 */ 60 static int 61 panthor_set_uobj(u64 usr_ptr, u32 usr_size, u32 min_size, u32 kern_size, const void *in) 62 { 63 /* User size shouldn't be smaller than the minimal object size. */ 64 if (usr_size < min_size) 65 return -EINVAL; 66 67 if (copy_to_user(u64_to_user_ptr(usr_ptr), in, min_t(u32, usr_size, kern_size))) 68 return -EFAULT; 69 70 /* When the kernel object is smaller than the user object, we fill the gap with 71 * zeros. 72 */ 73 if (usr_size > kern_size && 74 clear_user(u64_to_user_ptr(usr_ptr + kern_size), usr_size - kern_size)) { 75 return -EFAULT; 76 } 77 78 return 0; 79 } 80 81 /** 82 * panthor_get_uobj_array() - Copy a user object array into a kernel accessible object array. 83 * @in: The object array to copy. 84 * @min_stride: Minimum array stride. 85 * @obj_size: Kernel object size. 86 * 87 * Helper automating user -> kernel object copies. 88 * 89 * Don't use this function directly, use PANTHOR_UOBJ_GET_ARRAY() instead. 90 * 91 * Return: newly allocated object array or an ERR_PTR on error. 92 */ 93 static void * 94 panthor_get_uobj_array(const struct drm_panthor_obj_array *in, u32 min_stride, 95 u32 obj_size) 96 { 97 int ret = 0; 98 void *out_alloc; 99 100 if (!in->count) 101 return NULL; 102 103 /* User stride must be at least the minimum object size, otherwise it might 104 * lack useful information. 105 */ 106 if (in->stride < min_stride) 107 return ERR_PTR(-EINVAL); 108 109 out_alloc = kvmalloc_array(in->count, obj_size, GFP_KERNEL); 110 if (!out_alloc) 111 return ERR_PTR(-ENOMEM); 112 113 if (obj_size == in->stride) { 114 /* Fast path when user/kernel have the same uAPI header version. */ 115 if (copy_from_user(out_alloc, u64_to_user_ptr(in->array), 116 (unsigned long)obj_size * in->count)) 117 ret = -EFAULT; 118 } else { 119 void __user *in_ptr = u64_to_user_ptr(in->array); 120 void *out_ptr = out_alloc; 121 122 /* If the sizes differ, we need to copy elements one by one. */ 123 for (u32 i = 0; i < in->count; i++) { 124 ret = copy_struct_from_user(out_ptr, obj_size, in_ptr, in->stride); 125 if (ret) 126 break; 127 128 out_ptr += obj_size; 129 in_ptr += in->stride; 130 } 131 } 132 133 if (ret) { 134 kvfree(out_alloc); 135 return ERR_PTR(ret); 136 } 137 138 return out_alloc; 139 } 140 141 /** 142 * PANTHOR_UOBJ_MIN_SIZE_INTERNAL() - Get the minimum user object size 143 * @_typename: Object type. 144 * @_last_mandatory_field: Last mandatory field. 145 * 146 * Get the minimum user object size based on the last mandatory field name, 147 * A.K.A, the name of the last field of the structure at the time this 148 * structure was added to the uAPI. 149 * 150 * Don't use directly, use PANTHOR_UOBJ_DECL() instead. 151 */ 152 #define PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) \ 153 (offsetof(_typename, _last_mandatory_field) + \ 154 sizeof(((_typename *)NULL)->_last_mandatory_field)) 155 156 /** 157 * PANTHOR_UOBJ_DECL() - Declare a new uAPI object whose subject to 158 * evolutions. 159 * @_typename: Object type. 160 * @_last_mandatory_field: Last mandatory field. 161 * 162 * Should be used to extend the PANTHOR_UOBJ_MIN_SIZE() list. 163 */ 164 #define PANTHOR_UOBJ_DECL(_typename, _last_mandatory_field) \ 165 _typename : PANTHOR_UOBJ_MIN_SIZE_INTERNAL(_typename, _last_mandatory_field) 166 167 /** 168 * PANTHOR_UOBJ_MIN_SIZE() - Get the minimum size of a given uAPI object 169 * @_obj_name: Object to get the minimum size of. 170 * 171 * Don't use this macro directly, it's automatically called by 172 * PANTHOR_UOBJ_{SET,GET_ARRAY}(). 173 */ 174 #define PANTHOR_UOBJ_MIN_SIZE(_obj_name) \ 175 _Generic(_obj_name, \ 176 PANTHOR_UOBJ_DECL(struct drm_panthor_gpu_info, tiler_present), \ 177 PANTHOR_UOBJ_DECL(struct drm_panthor_csif_info, pad), \ 178 PANTHOR_UOBJ_DECL(struct drm_panthor_mmu_info, page_size_bitmap), \ 179 PANTHOR_UOBJ_DECL(struct drm_panthor_timestamp_info, current_timestamp), \ 180 PANTHOR_UOBJ_DECL(struct drm_panthor_group_priorities_info, pad), \ 181 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \ 182 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \ 183 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \ 184 PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs), \ 185 PANTHOR_UOBJ_DECL(struct drm_panthor_bo_sync_op, size)) 186 187 /** 188 * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object. 189 * @_dest_usr_ptr: User pointer to copy to. 190 * @_usr_size: Size of the user object. 191 * @_src_obj: Kernel object to copy (not a pointer). 192 * 193 * Return: 0 on success, a negative error code otherwise. 194 */ 195 #define PANTHOR_UOBJ_SET(_dest_usr_ptr, _usr_size, _src_obj) \ 196 panthor_set_uobj(_dest_usr_ptr, _usr_size, \ 197 PANTHOR_UOBJ_MIN_SIZE(_src_obj), \ 198 sizeof(_src_obj), &(_src_obj)) 199 200 /** 201 * PANTHOR_UOBJ_GET_ARRAY() - Copy a user object array to a kernel accessible 202 * object array. 203 * @_dest_array: Local variable that will hold the newly allocated kernel 204 * object array. 205 * @_uobj_array: The drm_panthor_obj_array object describing the user object 206 * array. 207 * 208 * Return: 0 on success, a negative error code otherwise. 209 */ 210 #define PANTHOR_UOBJ_GET_ARRAY(_dest_array, _uobj_array) \ 211 ({ \ 212 typeof(_dest_array) _tmp; \ 213 _tmp = panthor_get_uobj_array(_uobj_array, \ 214 PANTHOR_UOBJ_MIN_SIZE((_dest_array)[0]), \ 215 sizeof((_dest_array)[0])); \ 216 if (!IS_ERR(_tmp)) \ 217 _dest_array = _tmp; \ 218 PTR_ERR_OR_ZERO(_tmp); \ 219 }) 220 221 /** 222 * struct panthor_sync_signal - Represent a synchronization object point to attach 223 * our job fence to. 224 * 225 * This structure is here to keep track of fences that are currently bound to 226 * a specific syncobj point. 227 * 228 * At the beginning of a job submission, the fence 229 * is retrieved from the syncobj itself, and can be NULL if no fence was attached 230 * to this point. 231 * 232 * At the end, it points to the fence of the last job that had a 233 * %DRM_PANTHOR_SYNC_OP_SIGNAL on this syncobj. 234 * 235 * With jobs being submitted in batches, the fence might change several times during 236 * the process, allowing one job to wait on a job that's part of the same submission 237 * but appears earlier in the drm_panthor_group_submit::queue_submits array. 238 */ 239 struct panthor_sync_signal { 240 /** @node: list_head to track signal ops within a submit operation */ 241 struct list_head node; 242 243 /** @handle: The syncobj handle. */ 244 u32 handle; 245 246 /** 247 * @point: The syncobj point. 248 * 249 * Zero for regular syncobjs, and non-zero for timeline syncobjs. 250 */ 251 u64 point; 252 253 /** 254 * @syncobj: The sync object pointed by @handle. 255 */ 256 struct drm_syncobj *syncobj; 257 258 /** 259 * @chain: Chain object used to link the new fence to an existing 260 * timeline syncobj. 261 * 262 * NULL for regular syncobj, non-NULL for timeline syncobjs. 263 */ 264 struct dma_fence_chain *chain; 265 266 /** 267 * @fence: The fence to assign to the syncobj or syncobj-point. 268 */ 269 struct dma_fence *fence; 270 }; 271 272 /** 273 * struct panthor_job_ctx - Job context 274 */ 275 struct panthor_job_ctx { 276 /** @job: The job that is about to be submitted to drm_sched. */ 277 struct drm_sched_job *job; 278 279 /** @syncops: Array of sync operations. */ 280 struct drm_panthor_sync_op *syncops; 281 282 /** @syncop_count: Number of sync operations. */ 283 u32 syncop_count; 284 }; 285 286 /** 287 * struct panthor_submit_ctx - Submission context 288 * 289 * Anything that's related to a submission (%DRM_IOCTL_PANTHOR_VM_BIND or 290 * %DRM_IOCTL_PANTHOR_GROUP_SUBMIT) is kept here, so we can automate the 291 * initialization and cleanup steps. 292 */ 293 struct panthor_submit_ctx { 294 /** @file: DRM file this submission happens on. */ 295 struct drm_file *file; 296 297 /** 298 * @signals: List of struct panthor_sync_signal. 299 * 300 * %DRM_PANTHOR_SYNC_OP_SIGNAL operations will be recorded here, 301 * and %DRM_PANTHOR_SYNC_OP_WAIT will first check if an entry 302 * matching the syncobj+point exists before calling 303 * drm_syncobj_find_fence(). This allows us to describe dependencies 304 * existing between jobs that are part of the same batch. 305 */ 306 struct list_head signals; 307 308 /** @jobs: Array of jobs. */ 309 struct panthor_job_ctx *jobs; 310 311 /** @job_count: Number of entries in the @jobs array. */ 312 u32 job_count; 313 314 /** @exec: drm_exec context used to acquire and prepare resv objects. */ 315 struct drm_exec exec; 316 }; 317 318 #define PANTHOR_SYNC_OP_FLAGS_MASK \ 319 (DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK | DRM_PANTHOR_SYNC_OP_SIGNAL) 320 321 static bool sync_op_is_signal(const struct drm_panthor_sync_op *sync_op) 322 { 323 return !!(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); 324 } 325 326 static bool sync_op_is_wait(const struct drm_panthor_sync_op *sync_op) 327 { 328 /* Note that DRM_PANTHOR_SYNC_OP_WAIT == 0 */ 329 return !(sync_op->flags & DRM_PANTHOR_SYNC_OP_SIGNAL); 330 } 331 332 /** 333 * panthor_check_sync_op() - Check drm_panthor_sync_op fields 334 * @sync_op: The sync operation to check. 335 * 336 * Return: 0 on success, -EINVAL otherwise. 337 */ 338 static int 339 panthor_check_sync_op(const struct drm_panthor_sync_op *sync_op) 340 { 341 u8 handle_type; 342 343 if (sync_op->flags & ~PANTHOR_SYNC_OP_FLAGS_MASK) 344 return -EINVAL; 345 346 handle_type = sync_op->flags & DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_MASK; 347 if (handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && 348 handle_type != DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_TIMELINE_SYNCOBJ) 349 return -EINVAL; 350 351 if (handle_type == DRM_PANTHOR_SYNC_OP_HANDLE_TYPE_SYNCOBJ && 352 sync_op->timeline_value != 0) 353 return -EINVAL; 354 355 return 0; 356 } 357 358 /** 359 * panthor_sync_signal_free() - Release resources and free a panthor_sync_signal object 360 * @sig_sync: Signal object to free. 361 */ 362 static void 363 panthor_sync_signal_free(struct panthor_sync_signal *sig_sync) 364 { 365 if (!sig_sync) 366 return; 367 368 drm_syncobj_put(sig_sync->syncobj); 369 dma_fence_chain_free(sig_sync->chain); 370 dma_fence_put(sig_sync->fence); 371 kfree(sig_sync); 372 } 373 374 /** 375 * panthor_submit_ctx_add_sync_signal() - Add a signal operation to a submit context 376 * @ctx: Context to add the signal operation to. 377 * @handle: Syncobj handle. 378 * @point: Syncobj point. 379 * 380 * Return: 0 on success, otherwise negative error value. 381 */ 382 static int 383 panthor_submit_ctx_add_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) 384 { 385 struct panthor_sync_signal *sig_sync; 386 struct dma_fence *cur_fence; 387 int ret; 388 389 sig_sync = kzalloc_obj(*sig_sync); 390 if (!sig_sync) 391 return -ENOMEM; 392 393 sig_sync->handle = handle; 394 sig_sync->point = point; 395 396 if (point > 0) { 397 sig_sync->chain = dma_fence_chain_alloc(); 398 if (!sig_sync->chain) { 399 ret = -ENOMEM; 400 goto err_free_sig_sync; 401 } 402 } 403 404 sig_sync->syncobj = drm_syncobj_find(ctx->file, handle); 405 if (!sig_sync->syncobj) { 406 ret = -EINVAL; 407 goto err_free_sig_sync; 408 } 409 410 /* Retrieve the current fence attached to that point. It's 411 * perfectly fine to get a NULL fence here, it just means there's 412 * no fence attached to that point yet. 413 */ 414 if (!drm_syncobj_find_fence(ctx->file, handle, point, 0, &cur_fence)) 415 sig_sync->fence = cur_fence; 416 417 list_add_tail(&sig_sync->node, &ctx->signals); 418 419 return 0; 420 421 err_free_sig_sync: 422 panthor_sync_signal_free(sig_sync); 423 return ret; 424 } 425 426 /** 427 * panthor_submit_ctx_search_sync_signal() - Search an existing signal operation in a 428 * submit context. 429 * @ctx: Context to search the signal operation in. 430 * @handle: Syncobj handle. 431 * @point: Syncobj point. 432 * 433 * Return: A valid panthor_sync_signal object if found, NULL otherwise. 434 */ 435 static struct panthor_sync_signal * 436 panthor_submit_ctx_search_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) 437 { 438 struct panthor_sync_signal *sig_sync; 439 440 list_for_each_entry(sig_sync, &ctx->signals, node) { 441 if (handle == sig_sync->handle && point == sig_sync->point) 442 return sig_sync; 443 } 444 445 return NULL; 446 } 447 448 /** 449 * panthor_submit_ctx_add_job() - Add a job to a submit context 450 * @ctx: Context to search the signal operation in. 451 * @idx: Index of the job in the context. 452 * @job: Job to add. 453 * @syncs: Sync operations provided by userspace. 454 * 455 * Return: 0 on success, a negative error code otherwise. 456 */ 457 static int 458 panthor_submit_ctx_add_job(struct panthor_submit_ctx *ctx, u32 idx, 459 struct drm_sched_job *job, 460 const struct drm_panthor_obj_array *syncs) 461 { 462 int ret; 463 464 ctx->jobs[idx].job = job; 465 466 ret = PANTHOR_UOBJ_GET_ARRAY(ctx->jobs[idx].syncops, syncs); 467 if (ret) 468 return ret; 469 470 ctx->jobs[idx].syncop_count = syncs->count; 471 return 0; 472 } 473 474 /** 475 * panthor_submit_ctx_get_sync_signal() - Search signal operation and add one if none was found. 476 * @ctx: Context to search the signal operation in. 477 * @handle: Syncobj handle. 478 * @point: Syncobj point. 479 * 480 * Return: 0 on success, a negative error code otherwise. 481 */ 482 static int 483 panthor_submit_ctx_get_sync_signal(struct panthor_submit_ctx *ctx, u32 handle, u64 point) 484 { 485 struct panthor_sync_signal *sig_sync; 486 487 sig_sync = panthor_submit_ctx_search_sync_signal(ctx, handle, point); 488 if (sig_sync) 489 return 0; 490 491 return panthor_submit_ctx_add_sync_signal(ctx, handle, point); 492 } 493 494 /** 495 * panthor_submit_ctx_update_job_sync_signal_fences() - Update fences 496 * on the signal operations specified by a job. 497 * @ctx: Context to search the signal operation in. 498 * @job_idx: Index of the job to operate on. 499 * 500 * Return: 0 on success, a negative error code otherwise. 501 */ 502 static int 503 panthor_submit_ctx_update_job_sync_signal_fences(struct panthor_submit_ctx *ctx, 504 u32 job_idx) 505 { 506 struct panthor_device *ptdev = container_of(ctx->file->minor->dev, 507 struct panthor_device, 508 base); 509 struct dma_fence *done_fence = &ctx->jobs[job_idx].job->s_fence->finished; 510 const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; 511 u32 sync_op_count = ctx->jobs[job_idx].syncop_count; 512 513 for (u32 i = 0; i < sync_op_count; i++) { 514 struct dma_fence *old_fence; 515 struct panthor_sync_signal *sig_sync; 516 517 if (!sync_op_is_signal(&sync_ops[i])) 518 continue; 519 520 sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, 521 sync_ops[i].timeline_value); 522 if (drm_WARN_ON(&ptdev->base, !sig_sync)) 523 return -EINVAL; 524 525 old_fence = sig_sync->fence; 526 sig_sync->fence = dma_fence_get(done_fence); 527 dma_fence_put(old_fence); 528 529 if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) 530 return -EINVAL; 531 } 532 533 return 0; 534 } 535 536 /** 537 * panthor_submit_ctx_collect_job_signal_ops() - Iterate over all job signal operations 538 * and add them to the context. 539 * @ctx: Context to search the signal operation in. 540 * @job_idx: Index of the job to operate on. 541 * 542 * Return: 0 on success, a negative error code otherwise. 543 */ 544 static int 545 panthor_submit_ctx_collect_job_signal_ops(struct panthor_submit_ctx *ctx, 546 u32 job_idx) 547 { 548 const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; 549 u32 sync_op_count = ctx->jobs[job_idx].syncop_count; 550 551 for (u32 i = 0; i < sync_op_count; i++) { 552 int ret; 553 554 if (!sync_op_is_signal(&sync_ops[i])) 555 continue; 556 557 ret = panthor_check_sync_op(&sync_ops[i]); 558 if (ret) 559 return ret; 560 561 ret = panthor_submit_ctx_get_sync_signal(ctx, 562 sync_ops[i].handle, 563 sync_ops[i].timeline_value); 564 if (ret) 565 return ret; 566 } 567 568 return 0; 569 } 570 571 /** 572 * panthor_submit_ctx_push_fences() - Iterate over the signal array, and for each entry, push 573 * the currently assigned fence to the associated syncobj. 574 * @ctx: Context to push fences on. 575 * 576 * This is the last step of a submission procedure, and is done once we know the submission 577 * is effective and job fences are guaranteed to be signaled in finite time. 578 */ 579 static void 580 panthor_submit_ctx_push_fences(struct panthor_submit_ctx *ctx) 581 { 582 struct panthor_sync_signal *sig_sync; 583 584 list_for_each_entry(sig_sync, &ctx->signals, node) { 585 if (sig_sync->chain) { 586 drm_syncobj_add_point(sig_sync->syncobj, sig_sync->chain, 587 sig_sync->fence, sig_sync->point); 588 sig_sync->chain = NULL; 589 } else { 590 drm_syncobj_replace_fence(sig_sync->syncobj, sig_sync->fence); 591 } 592 } 593 } 594 595 /** 596 * panthor_submit_ctx_add_sync_deps_to_job() - Add sync wait operations as 597 * job dependencies. 598 * @ctx: Submit context. 599 * @job_idx: Index of the job to operate on. 600 * 601 * Return: 0 on success, a negative error code otherwise. 602 */ 603 static int 604 panthor_submit_ctx_add_sync_deps_to_job(struct panthor_submit_ctx *ctx, 605 u32 job_idx) 606 { 607 struct panthor_device *ptdev = container_of(ctx->file->minor->dev, 608 struct panthor_device, 609 base); 610 const struct drm_panthor_sync_op *sync_ops = ctx->jobs[job_idx].syncops; 611 struct drm_sched_job *job = ctx->jobs[job_idx].job; 612 u32 sync_op_count = ctx->jobs[job_idx].syncop_count; 613 int ret = 0; 614 615 for (u32 i = 0; i < sync_op_count; i++) { 616 struct panthor_sync_signal *sig_sync; 617 struct dma_fence *fence; 618 619 if (!sync_op_is_wait(&sync_ops[i])) 620 continue; 621 622 ret = panthor_check_sync_op(&sync_ops[i]); 623 if (ret) 624 return ret; 625 626 sig_sync = panthor_submit_ctx_search_sync_signal(ctx, sync_ops[i].handle, 627 sync_ops[i].timeline_value); 628 if (sig_sync) { 629 if (drm_WARN_ON(&ptdev->base, !sig_sync->fence)) 630 return -EINVAL; 631 632 fence = dma_fence_get(sig_sync->fence); 633 } else { 634 ret = drm_syncobj_find_fence(ctx->file, sync_ops[i].handle, 635 sync_ops[i].timeline_value, 636 0, &fence); 637 if (ret) 638 return ret; 639 } 640 641 ret = drm_sched_job_add_dependency(job, fence); 642 if (ret) 643 return ret; 644 } 645 646 return 0; 647 } 648 649 /** 650 * panthor_submit_ctx_collect_jobs_signal_ops() - Collect all signal operations 651 * and add them to the submit context. 652 * @ctx: Submit context. 653 * 654 * Return: 0 on success, a negative error code otherwise. 655 */ 656 static int 657 panthor_submit_ctx_collect_jobs_signal_ops(struct panthor_submit_ctx *ctx) 658 { 659 for (u32 i = 0; i < ctx->job_count; i++) { 660 int ret; 661 662 ret = panthor_submit_ctx_collect_job_signal_ops(ctx, i); 663 if (ret) 664 return ret; 665 } 666 667 return 0; 668 } 669 670 /** 671 * panthor_submit_ctx_add_deps_and_arm_jobs() - Add jobs dependencies and arm jobs 672 * @ctx: Submit context. 673 * 674 * Must be called after the resv preparation has been taken care of. 675 * 676 * Return: 0 on success, a negative error code otherwise. 677 */ 678 static int 679 panthor_submit_ctx_add_deps_and_arm_jobs(struct panthor_submit_ctx *ctx) 680 { 681 for (u32 i = 0; i < ctx->job_count; i++) { 682 int ret; 683 684 ret = panthor_submit_ctx_add_sync_deps_to_job(ctx, i); 685 if (ret) 686 return ret; 687 688 drm_sched_job_arm(ctx->jobs[i].job); 689 690 ret = panthor_submit_ctx_update_job_sync_signal_fences(ctx, i); 691 if (ret) 692 return ret; 693 } 694 695 return 0; 696 } 697 698 /** 699 * panthor_submit_ctx_push_jobs() - Push jobs to their scheduling entities. 700 * @ctx: Submit context. 701 * @upd_resvs: Callback used to update reservation objects that were previously 702 * preapred. 703 */ 704 static void 705 panthor_submit_ctx_push_jobs(struct panthor_submit_ctx *ctx, 706 void (*upd_resvs)(struct drm_exec *, struct drm_sched_job *)) 707 { 708 for (u32 i = 0; i < ctx->job_count; i++) { 709 upd_resvs(&ctx->exec, ctx->jobs[i].job); 710 drm_sched_entity_push_job(ctx->jobs[i].job); 711 712 /* Job is owned by the scheduler now. */ 713 ctx->jobs[i].job = NULL; 714 } 715 716 panthor_submit_ctx_push_fences(ctx); 717 } 718 719 /** 720 * panthor_submit_ctx_init() - Initializes a submission context 721 * @ctx: Submit context to initialize. 722 * @file: drm_file this submission happens on. 723 * @job_count: Number of jobs that will be submitted. 724 * 725 * Return: 0 on success, a negative error code otherwise. 726 */ 727 static int panthor_submit_ctx_init(struct panthor_submit_ctx *ctx, 728 struct drm_file *file, u32 job_count) 729 { 730 ctx->jobs = kvmalloc_objs(*ctx->jobs, job_count, 731 GFP_KERNEL | __GFP_ZERO); 732 if (!ctx->jobs) 733 return -ENOMEM; 734 735 ctx->file = file; 736 ctx->job_count = job_count; 737 INIT_LIST_HEAD(&ctx->signals); 738 drm_exec_init(&ctx->exec, 739 DRM_EXEC_INTERRUPTIBLE_WAIT | DRM_EXEC_IGNORE_DUPLICATES, 740 0); 741 return 0; 742 } 743 744 /** 745 * panthor_submit_ctx_cleanup() - Cleanup a submission context 746 * @ctx: Submit context to cleanup. 747 * @job_put: Job put callback. 748 */ 749 static void panthor_submit_ctx_cleanup(struct panthor_submit_ctx *ctx, 750 void (*job_put)(struct drm_sched_job *)) 751 { 752 struct panthor_sync_signal *sig_sync, *tmp; 753 unsigned long i; 754 755 drm_exec_fini(&ctx->exec); 756 757 list_for_each_entry_safe(sig_sync, tmp, &ctx->signals, node) 758 panthor_sync_signal_free(sig_sync); 759 760 for (i = 0; i < ctx->job_count; i++) { 761 job_put(ctx->jobs[i].job); 762 kvfree(ctx->jobs[i].syncops); 763 } 764 765 kvfree(ctx->jobs); 766 } 767 768 #define VALID_TIMESTAMP_QUERY_FLAGS \ 769 (DRM_PANTHOR_TIMESTAMP_GPU | \ 770 DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK | \ 771 DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | \ 772 DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT | \ 773 DRM_PANTHOR_TIMESTAMP_FREQ | \ 774 DRM_PANTHOR_TIMESTAMP_DURATION) 775 776 static int panthor_query_timestamp_info(struct panthor_device *ptdev, 777 struct drm_panthor_timestamp_info *arg) 778 { 779 int ret; 780 u32 flags; 781 unsigned long irq_flags; 782 struct timespec64 cpu_ts; 783 u64 query_start_time; 784 bool minimize_interruption; 785 u32 timestamp_types = 0; 786 787 if (arg->flags != 0) { 788 flags = arg->flags; 789 } else { 790 /* 791 * If flags are 0, then ask for the same things that we asked 792 * for before flags were added. 793 */ 794 flags = DRM_PANTHOR_TIMESTAMP_GPU | 795 DRM_PANTHOR_TIMESTAMP_GPU_OFFSET | 796 DRM_PANTHOR_TIMESTAMP_FREQ; 797 } 798 799 switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 800 case DRM_PANTHOR_TIMESTAMP_CPU_NONE: 801 break; 802 case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: 803 case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: 804 timestamp_types++; 805 break; 806 default: 807 return -EINVAL; 808 } 809 810 if (flags & ~VALID_TIMESTAMP_QUERY_FLAGS) 811 return -EINVAL; 812 813 if (flags & DRM_PANTHOR_TIMESTAMP_GPU) 814 timestamp_types++; 815 if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT) 816 timestamp_types++; 817 818 /* If user asked to obtain timestamps from more than one source, 819 * then it very likely means they want them to be as close as possible. 820 * If they asked for duration, then that likely means that they 821 * want to know how long obtaining timestamp takes, without random 822 * events, like process scheduling or interrupts. 823 */ 824 minimize_interruption = 825 (flags & DRM_PANTHOR_TIMESTAMP_DURATION) || 826 (timestamp_types >= 2); 827 828 ret = panthor_device_resume_and_get(ptdev); 829 if (ret) 830 return ret; 831 832 if (flags & DRM_PANTHOR_TIMESTAMP_FREQ) { 833 #ifdef CONFIG_ARM_ARCH_TIMER 834 arg->timestamp_frequency = arch_timer_get_cntfrq(); 835 #else 836 arg->timestamp_frequency = 0; 837 #endif 838 } else { 839 arg->timestamp_frequency = 0; 840 } 841 842 if (flags & DRM_PANTHOR_TIMESTAMP_GPU_OFFSET) 843 arg->timestamp_offset = panthor_gpu_get_timestamp_offset(ptdev); 844 else 845 arg->timestamp_offset = 0; 846 847 if (minimize_interruption) { 848 preempt_disable(); 849 local_irq_save(irq_flags); 850 } 851 852 if (flags & DRM_PANTHOR_TIMESTAMP_DURATION) 853 query_start_time = local_clock(); 854 else 855 query_start_time = 0; 856 857 if (flags & DRM_PANTHOR_TIMESTAMP_GPU) 858 arg->current_timestamp = panthor_gpu_get_timestamp(ptdev); 859 else 860 arg->current_timestamp = 0; 861 862 switch (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 863 case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC: 864 ktime_get_ts64(&cpu_ts); 865 break; 866 case DRM_PANTHOR_TIMESTAMP_CPU_MONOTONIC_RAW: 867 ktime_get_raw_ts64(&cpu_ts); 868 break; 869 default: 870 break; 871 } 872 873 if (flags & DRM_PANTHOR_TIMESTAMP_GPU_CYCLE_COUNT) 874 arg->cycle_count = panthor_gpu_get_cycle_count(ptdev); 875 else 876 arg->cycle_count = 0; 877 878 if (flags & DRM_PANTHOR_TIMESTAMP_DURATION) 879 arg->duration_nsec = local_clock() - query_start_time; 880 else 881 arg->duration_nsec = 0; 882 883 if (minimize_interruption) { 884 local_irq_restore(irq_flags); 885 preempt_enable(); 886 } 887 888 if (flags & DRM_PANTHOR_TIMESTAMP_CPU_TYPE_MASK) { 889 timens_add_monotonic(&cpu_ts); 890 891 arg->cpu_timestamp_sec = cpu_ts.tv_sec; 892 arg->cpu_timestamp_nsec = cpu_ts.tv_nsec; 893 } else { 894 arg->cpu_timestamp_sec = 0; 895 arg->cpu_timestamp_nsec = 0; 896 } 897 898 pm_runtime_put(ptdev->base.dev); 899 return 0; 900 } 901 902 static int group_priority_permit(struct drm_file *file, 903 u8 priority) 904 { 905 /* Ensure that priority is valid */ 906 if (priority > PANTHOR_GROUP_PRIORITY_REALTIME) 907 return -EINVAL; 908 909 /* Medium priority and below are always allowed */ 910 if (priority <= PANTHOR_GROUP_PRIORITY_MEDIUM) 911 return 0; 912 913 /* Higher priorities require CAP_SYS_NICE or DRM_MASTER */ 914 if (capable(CAP_SYS_NICE) || drm_is_current_master(file)) 915 return 0; 916 917 return -EACCES; 918 } 919 920 static void panthor_query_group_priorities_info(struct drm_file *file, 921 struct drm_panthor_group_priorities_info *arg) 922 { 923 int prio; 924 925 memset(arg, 0, sizeof(*arg)); 926 for (prio = PANTHOR_GROUP_PRIORITY_REALTIME; prio >= 0; prio--) { 927 if (!group_priority_permit(file, prio)) 928 arg->allowed_mask |= BIT(prio); 929 } 930 } 931 932 static int panthor_ioctl_dev_query(struct drm_device *ddev, void *data, struct drm_file *file) 933 { 934 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); 935 struct drm_panthor_dev_query *args = data; 936 struct drm_panthor_timestamp_info timestamp_info; 937 struct drm_panthor_group_priorities_info priorities_info; 938 int ret; 939 940 if (!args->pointer) { 941 switch (args->type) { 942 case DRM_PANTHOR_DEV_QUERY_GPU_INFO: 943 args->size = sizeof(ptdev->gpu_info); 944 return 0; 945 946 case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: 947 args->size = sizeof(ptdev->csif_info); 948 return 0; 949 950 case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: 951 args->size = sizeof(timestamp_info); 952 return 0; 953 954 case DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO: 955 args->size = sizeof(priorities_info); 956 return 0; 957 958 case DRM_PANTHOR_DEV_QUERY_MMU_INFO: 959 args->size = sizeof(ptdev->mmu_info); 960 return 0; 961 962 default: 963 return -EINVAL; 964 } 965 } 966 967 switch (args->type) { 968 case DRM_PANTHOR_DEV_QUERY_GPU_INFO: 969 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->gpu_info); 970 971 case DRM_PANTHOR_DEV_QUERY_CSIF_INFO: 972 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->csif_info); 973 974 case DRM_PANTHOR_DEV_QUERY_TIMESTAMP_INFO: 975 ret = copy_struct_from_user(×tamp_info, 976 sizeof(timestamp_info), 977 u64_to_user_ptr(args->pointer), 978 args->size); 979 if (ret) 980 return ret; 981 982 ret = panthor_query_timestamp_info(ptdev, ×tamp_info); 983 if (ret) 984 return ret; 985 986 return PANTHOR_UOBJ_SET(args->pointer, args->size, timestamp_info); 987 988 case DRM_PANTHOR_DEV_QUERY_GROUP_PRIORITIES_INFO: 989 panthor_query_group_priorities_info(file, &priorities_info); 990 return PANTHOR_UOBJ_SET(args->pointer, args->size, priorities_info); 991 992 case DRM_PANTHOR_DEV_QUERY_MMU_INFO: 993 return PANTHOR_UOBJ_SET(args->pointer, args->size, ptdev->mmu_info); 994 995 default: 996 return -EINVAL; 997 } 998 } 999 1000 #define PANTHOR_VM_CREATE_FLAGS 0 1001 1002 static int panthor_ioctl_vm_create(struct drm_device *ddev, void *data, 1003 struct drm_file *file) 1004 { 1005 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); 1006 struct panthor_file *pfile = file->driver_priv; 1007 struct drm_panthor_vm_create *args = data; 1008 int cookie, ret; 1009 1010 if (!drm_dev_enter(ddev, &cookie)) 1011 return -ENODEV; 1012 1013 ret = panthor_vm_pool_create_vm(ptdev, pfile->vms, args); 1014 if (ret >= 0) { 1015 args->id = ret; 1016 ret = 0; 1017 } 1018 1019 drm_dev_exit(cookie); 1020 return ret; 1021 } 1022 1023 static int panthor_ioctl_vm_destroy(struct drm_device *ddev, void *data, 1024 struct drm_file *file) 1025 { 1026 struct panthor_file *pfile = file->driver_priv; 1027 struct drm_panthor_vm_destroy *args = data; 1028 1029 if (args->pad) 1030 return -EINVAL; 1031 1032 return panthor_vm_pool_destroy_vm(pfile->vms, args->id); 1033 } 1034 1035 #define PANTHOR_BO_FLAGS (DRM_PANTHOR_BO_NO_MMAP | \ 1036 DRM_PANTHOR_BO_WB_MMAP) 1037 1038 static int panthor_ioctl_bo_create(struct drm_device *ddev, void *data, 1039 struct drm_file *file) 1040 { 1041 struct panthor_file *pfile = file->driver_priv; 1042 struct drm_panthor_bo_create *args = data; 1043 struct panthor_vm *vm = NULL; 1044 int cookie, ret; 1045 1046 if (!drm_dev_enter(ddev, &cookie)) 1047 return -ENODEV; 1048 1049 if (!args->size || args->pad || 1050 (args->flags & ~PANTHOR_BO_FLAGS)) { 1051 ret = -EINVAL; 1052 goto out_dev_exit; 1053 } 1054 1055 if ((args->flags & DRM_PANTHOR_BO_NO_MMAP) && 1056 (args->flags & DRM_PANTHOR_BO_WB_MMAP)) { 1057 ret = -EINVAL; 1058 goto out_dev_exit; 1059 } 1060 1061 if (args->exclusive_vm_id) { 1062 vm = panthor_vm_pool_get_vm(pfile->vms, args->exclusive_vm_id); 1063 if (!vm) { 1064 ret = -EINVAL; 1065 goto out_dev_exit; 1066 } 1067 } 1068 1069 ret = panthor_gem_create_with_handle(file, ddev, vm, &args->size, 1070 args->flags, &args->handle); 1071 1072 panthor_vm_put(vm); 1073 1074 out_dev_exit: 1075 drm_dev_exit(cookie); 1076 return ret; 1077 } 1078 1079 static int panthor_ioctl_bo_mmap_offset(struct drm_device *ddev, void *data, 1080 struct drm_file *file) 1081 { 1082 struct drm_panthor_bo_mmap_offset *args = data; 1083 struct panthor_gem_object *bo; 1084 struct drm_gem_object *obj; 1085 int ret; 1086 1087 if (args->pad) 1088 return -EINVAL; 1089 1090 obj = drm_gem_object_lookup(file, args->handle); 1091 if (!obj) 1092 return -ENOENT; 1093 1094 bo = to_panthor_bo(obj); 1095 if (bo->flags & DRM_PANTHOR_BO_NO_MMAP) { 1096 ret = -EPERM; 1097 goto out; 1098 } 1099 1100 ret = drm_gem_create_mmap_offset(obj); 1101 if (ret) 1102 goto out; 1103 1104 args->offset = drm_vma_node_offset_addr(&obj->vma_node); 1105 1106 out: 1107 drm_gem_object_put(obj); 1108 return ret; 1109 } 1110 1111 static int panthor_ioctl_group_submit(struct drm_device *ddev, void *data, 1112 struct drm_file *file) 1113 { 1114 struct panthor_file *pfile = file->driver_priv; 1115 struct drm_panthor_group_submit *args = data; 1116 struct drm_panthor_queue_submit *jobs_args; 1117 struct panthor_submit_ctx ctx; 1118 int ret = 0, cookie; 1119 1120 if (args->pad) 1121 return -EINVAL; 1122 1123 if (!drm_dev_enter(ddev, &cookie)) 1124 return -ENODEV; 1125 1126 ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->queue_submits); 1127 if (ret) 1128 goto out_dev_exit; 1129 1130 ret = panthor_submit_ctx_init(&ctx, file, args->queue_submits.count); 1131 if (ret) 1132 goto out_free_jobs_args; 1133 1134 /* Create jobs and attach sync operations */ 1135 for (u32 i = 0; i < args->queue_submits.count; i++) { 1136 const struct drm_panthor_queue_submit *qsubmit = &jobs_args[i]; 1137 struct drm_sched_job *job; 1138 1139 job = panthor_job_create(pfile, args->group_handle, qsubmit, 1140 file->client_id); 1141 if (IS_ERR(job)) { 1142 ret = PTR_ERR(job); 1143 goto out_cleanup_submit_ctx; 1144 } 1145 1146 ret = panthor_submit_ctx_add_job(&ctx, i, job, &qsubmit->syncs); 1147 if (ret) 1148 goto out_cleanup_submit_ctx; 1149 } 1150 1151 /* 1152 * Collect signal operations on all jobs, such that each job can pick 1153 * from it for its dependencies and update the fence to signal when the 1154 * job is submitted. 1155 */ 1156 ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); 1157 if (ret) 1158 goto out_cleanup_submit_ctx; 1159 1160 /* 1161 * We acquire/prepare revs on all jobs before proceeding with the 1162 * dependency registration. 1163 * 1164 * This is solving two problems: 1165 * 1. drm_sched_job_arm() and drm_sched_entity_push_job() must be 1166 * protected by a lock to make sure no concurrent access to the same 1167 * entity get interleaved, which would mess up with the fence seqno 1168 * ordering. Luckily, one of the resv being acquired is the VM resv, 1169 * and a scheduling entity is only bound to a single VM. As soon as 1170 * we acquire the VM resv, we should be safe. 1171 * 2. Jobs might depend on fences that were issued by previous jobs in 1172 * the same batch, so we can't add dependencies on all jobs before 1173 * arming previous jobs and registering the fence to the signal 1174 * array, otherwise we might miss dependencies, or point to an 1175 * outdated fence. 1176 */ 1177 if (args->queue_submits.count > 0) { 1178 /* All jobs target the same group, so they also point to the same VM. */ 1179 struct panthor_vm *vm = panthor_job_vm(ctx.jobs[0].job); 1180 1181 drm_exec_until_all_locked(&ctx.exec) { 1182 ret = panthor_vm_prepare_mapped_bos_resvs(&ctx.exec, vm, 1183 args->queue_submits.count); 1184 } 1185 1186 if (ret) 1187 goto out_cleanup_submit_ctx; 1188 } 1189 1190 /* 1191 * Now that resvs are locked/prepared, we can iterate over each job to 1192 * add the dependencies, arm the job fence, register the job fence to 1193 * the signal array. 1194 */ 1195 ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); 1196 if (ret) 1197 goto out_cleanup_submit_ctx; 1198 1199 /* Nothing can fail after that point, so we can make our job fences 1200 * visible to the outside world. Push jobs and set the job fences to 1201 * the resv slots we reserved. This also pushes the fences to the 1202 * syncobjs that are part of the signal array. 1203 */ 1204 panthor_submit_ctx_push_jobs(&ctx, panthor_job_update_resvs); 1205 1206 out_cleanup_submit_ctx: 1207 panthor_submit_ctx_cleanup(&ctx, panthor_job_put); 1208 1209 out_free_jobs_args: 1210 kvfree(jobs_args); 1211 1212 out_dev_exit: 1213 drm_dev_exit(cookie); 1214 return ret; 1215 } 1216 1217 static int panthor_ioctl_group_destroy(struct drm_device *ddev, void *data, 1218 struct drm_file *file) 1219 { 1220 struct panthor_file *pfile = file->driver_priv; 1221 struct drm_panthor_group_destroy *args = data; 1222 1223 if (args->pad) 1224 return -EINVAL; 1225 1226 return panthor_group_destroy(pfile, args->group_handle); 1227 } 1228 1229 static int panthor_ioctl_group_create(struct drm_device *ddev, void *data, 1230 struct drm_file *file) 1231 { 1232 struct panthor_file *pfile = file->driver_priv; 1233 struct drm_panthor_group_create *args = data; 1234 struct drm_panthor_queue_create *queue_args; 1235 int ret; 1236 1237 if (!args->queues.count || args->queues.count > MAX_CS_PER_CSG) 1238 return -EINVAL; 1239 1240 ret = PANTHOR_UOBJ_GET_ARRAY(queue_args, &args->queues); 1241 if (ret) 1242 return ret; 1243 1244 ret = group_priority_permit(file, args->priority); 1245 if (ret) 1246 goto out; 1247 1248 ret = panthor_group_create(pfile, args, queue_args, file->client_id); 1249 if (ret < 0) 1250 goto out; 1251 args->group_handle = ret; 1252 ret = 0; 1253 1254 out: 1255 kvfree(queue_args); 1256 return ret; 1257 } 1258 1259 static int panthor_ioctl_group_get_state(struct drm_device *ddev, void *data, 1260 struct drm_file *file) 1261 { 1262 struct panthor_file *pfile = file->driver_priv; 1263 struct drm_panthor_group_get_state *args = data; 1264 1265 return panthor_group_get_state(pfile, args); 1266 } 1267 1268 static int panthor_ioctl_tiler_heap_create(struct drm_device *ddev, void *data, 1269 struct drm_file *file) 1270 { 1271 struct panthor_file *pfile = file->driver_priv; 1272 struct drm_panthor_tiler_heap_create *args = data; 1273 struct panthor_heap_pool *pool; 1274 struct panthor_vm *vm; 1275 int ret; 1276 1277 vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); 1278 if (!vm) 1279 return -EINVAL; 1280 1281 pool = panthor_vm_get_heap_pool(vm, true); 1282 if (IS_ERR(pool)) { 1283 ret = PTR_ERR(pool); 1284 goto out_put_vm; 1285 } 1286 1287 ret = panthor_heap_create(pool, 1288 args->initial_chunk_count, 1289 args->chunk_size, 1290 args->max_chunks, 1291 args->target_in_flight, 1292 &args->tiler_heap_ctx_gpu_va, 1293 &args->first_heap_chunk_gpu_va); 1294 if (ret < 0) 1295 goto out_put_heap_pool; 1296 1297 /* Heap pools are per-VM. We combine the VM and HEAP id to make 1298 * a unique heap handle. 1299 */ 1300 args->handle = (args->vm_id << 16) | ret; 1301 ret = 0; 1302 1303 out_put_heap_pool: 1304 panthor_heap_pool_put(pool); 1305 1306 out_put_vm: 1307 panthor_vm_put(vm); 1308 return ret; 1309 } 1310 1311 static int panthor_ioctl_tiler_heap_destroy(struct drm_device *ddev, void *data, 1312 struct drm_file *file) 1313 { 1314 struct panthor_file *pfile = file->driver_priv; 1315 struct drm_panthor_tiler_heap_destroy *args = data; 1316 struct panthor_heap_pool *pool; 1317 struct panthor_vm *vm; 1318 int ret; 1319 1320 if (args->pad) 1321 return -EINVAL; 1322 1323 vm = panthor_vm_pool_get_vm(pfile->vms, args->handle >> 16); 1324 if (!vm) 1325 return -EINVAL; 1326 1327 pool = panthor_vm_get_heap_pool(vm, false); 1328 if (IS_ERR(pool)) { 1329 ret = PTR_ERR(pool); 1330 goto out_put_vm; 1331 } 1332 1333 ret = panthor_heap_destroy(pool, args->handle & GENMASK(15, 0)); 1334 panthor_heap_pool_put(pool); 1335 1336 out_put_vm: 1337 panthor_vm_put(vm); 1338 return ret; 1339 } 1340 1341 static int panthor_ioctl_vm_bind_async(struct drm_device *ddev, 1342 struct drm_panthor_vm_bind *args, 1343 struct drm_file *file) 1344 { 1345 struct panthor_file *pfile = file->driver_priv; 1346 struct drm_panthor_vm_bind_op *jobs_args; 1347 struct panthor_submit_ctx ctx; 1348 struct panthor_vm *vm; 1349 int ret = 0; 1350 1351 vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); 1352 if (!vm) 1353 return -EINVAL; 1354 1355 ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); 1356 if (ret) 1357 goto out_put_vm; 1358 1359 ret = panthor_submit_ctx_init(&ctx, file, args->ops.count); 1360 if (ret) 1361 goto out_free_jobs_args; 1362 1363 for (u32 i = 0; i < args->ops.count; i++) { 1364 struct drm_panthor_vm_bind_op *op = &jobs_args[i]; 1365 struct drm_sched_job *job; 1366 1367 job = panthor_vm_bind_job_create(file, vm, op); 1368 if (IS_ERR(job)) { 1369 ret = PTR_ERR(job); 1370 goto out_cleanup_submit_ctx; 1371 } 1372 1373 ret = panthor_submit_ctx_add_job(&ctx, i, job, &op->syncs); 1374 if (ret) 1375 goto out_cleanup_submit_ctx; 1376 } 1377 1378 ret = panthor_submit_ctx_collect_jobs_signal_ops(&ctx); 1379 if (ret) 1380 goto out_cleanup_submit_ctx; 1381 1382 /* Prepare reservation objects for each VM_BIND job. */ 1383 drm_exec_until_all_locked(&ctx.exec) { 1384 for (u32 i = 0; i < ctx.job_count; i++) { 1385 ret = panthor_vm_bind_job_prepare_resvs(&ctx.exec, ctx.jobs[i].job); 1386 drm_exec_retry_on_contention(&ctx.exec); 1387 if (ret) 1388 goto out_cleanup_submit_ctx; 1389 } 1390 } 1391 1392 ret = panthor_submit_ctx_add_deps_and_arm_jobs(&ctx); 1393 if (ret) 1394 goto out_cleanup_submit_ctx; 1395 1396 /* Nothing can fail after that point. */ 1397 panthor_submit_ctx_push_jobs(&ctx, panthor_vm_bind_job_update_resvs); 1398 1399 out_cleanup_submit_ctx: 1400 panthor_submit_ctx_cleanup(&ctx, panthor_vm_bind_job_put); 1401 1402 out_free_jobs_args: 1403 kvfree(jobs_args); 1404 1405 out_put_vm: 1406 panthor_vm_put(vm); 1407 return ret; 1408 } 1409 1410 static int panthor_ioctl_vm_bind_sync(struct drm_device *ddev, 1411 struct drm_panthor_vm_bind *args, 1412 struct drm_file *file) 1413 { 1414 struct panthor_file *pfile = file->driver_priv; 1415 struct drm_panthor_vm_bind_op *jobs_args; 1416 struct panthor_vm *vm; 1417 int ret; 1418 1419 vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); 1420 if (!vm) 1421 return -EINVAL; 1422 1423 ret = PANTHOR_UOBJ_GET_ARRAY(jobs_args, &args->ops); 1424 if (ret) 1425 goto out_put_vm; 1426 1427 for (u32 i = 0; i < args->ops.count; i++) { 1428 ret = panthor_vm_bind_exec_sync_op(file, vm, &jobs_args[i]); 1429 if (ret) { 1430 /* Update ops.count so the user knows where things failed. */ 1431 args->ops.count = i; 1432 break; 1433 } 1434 } 1435 1436 kvfree(jobs_args); 1437 1438 out_put_vm: 1439 panthor_vm_put(vm); 1440 return ret; 1441 } 1442 1443 #define PANTHOR_VM_BIND_FLAGS DRM_PANTHOR_VM_BIND_ASYNC 1444 1445 static int panthor_ioctl_vm_bind(struct drm_device *ddev, void *data, 1446 struct drm_file *file) 1447 { 1448 struct drm_panthor_vm_bind *args = data; 1449 int cookie, ret; 1450 1451 if (!drm_dev_enter(ddev, &cookie)) 1452 return -ENODEV; 1453 1454 if (args->flags & DRM_PANTHOR_VM_BIND_ASYNC) 1455 ret = panthor_ioctl_vm_bind_async(ddev, args, file); 1456 else 1457 ret = panthor_ioctl_vm_bind_sync(ddev, args, file); 1458 1459 drm_dev_exit(cookie); 1460 return ret; 1461 } 1462 1463 static int panthor_ioctl_vm_get_state(struct drm_device *ddev, void *data, 1464 struct drm_file *file) 1465 { 1466 struct panthor_file *pfile = file->driver_priv; 1467 struct drm_panthor_vm_get_state *args = data; 1468 struct panthor_vm *vm; 1469 1470 vm = panthor_vm_pool_get_vm(pfile->vms, args->vm_id); 1471 if (!vm) 1472 return -EINVAL; 1473 1474 if (panthor_vm_is_unusable(vm)) 1475 args->state = DRM_PANTHOR_VM_STATE_UNUSABLE; 1476 else 1477 args->state = DRM_PANTHOR_VM_STATE_USABLE; 1478 1479 panthor_vm_put(vm); 1480 return 0; 1481 } 1482 1483 static int panthor_ioctl_bo_set_label(struct drm_device *ddev, void *data, 1484 struct drm_file *file) 1485 { 1486 struct drm_panthor_bo_set_label *args = data; 1487 struct drm_gem_object *obj; 1488 const char *label = NULL; 1489 int ret = 0; 1490 1491 if (args->pad) 1492 return -EINVAL; 1493 1494 obj = drm_gem_object_lookup(file, args->handle); 1495 if (!obj) 1496 return -ENOENT; 1497 1498 if (args->label) { 1499 label = strndup_user((const char __user *)(uintptr_t)args->label, 1500 PANTHOR_BO_LABEL_MAXLEN); 1501 if (IS_ERR(label)) { 1502 ret = PTR_ERR(label); 1503 if (ret == -EINVAL) 1504 ret = -E2BIG; 1505 goto err_put_obj; 1506 } 1507 } 1508 1509 /* 1510 * We treat passing a label of length 0 and passing a NULL label 1511 * differently, because even though they might seem conceptually 1512 * similar, future uses of the BO label might expect a different 1513 * behaviour in each case. 1514 */ 1515 panthor_gem_bo_set_label(obj, label); 1516 1517 err_put_obj: 1518 drm_gem_object_put(obj); 1519 1520 return ret; 1521 } 1522 1523 static int panthor_ioctl_set_user_mmio_offset(struct drm_device *ddev, 1524 void *data, struct drm_file *file) 1525 { 1526 struct drm_panthor_set_user_mmio_offset *args = data; 1527 struct panthor_file *pfile = file->driver_priv; 1528 1529 if (args->offset != DRM_PANTHOR_USER_MMIO_OFFSET_32BIT && 1530 args->offset != DRM_PANTHOR_USER_MMIO_OFFSET_64BIT) 1531 return -EINVAL; 1532 1533 WRITE_ONCE(pfile->user_mmio.offset, args->offset); 1534 return 0; 1535 } 1536 1537 static int panthor_ioctl_bo_sync(struct drm_device *ddev, void *data, 1538 struct drm_file *file) 1539 { 1540 struct drm_panthor_bo_sync *args = data; 1541 struct drm_panthor_bo_sync_op *ops; 1542 struct drm_gem_object *obj; 1543 int ret; 1544 1545 if (!args->ops.count) 1546 return 0; 1547 1548 ret = PANTHOR_UOBJ_GET_ARRAY(ops, &args->ops); 1549 if (ret) 1550 return ret; 1551 1552 for (u32 i = 0; i < args->ops.count; i++) { 1553 obj = drm_gem_object_lookup(file, ops[i].handle); 1554 if (!obj) { 1555 ret = -ENOENT; 1556 goto err_ops; 1557 } 1558 1559 ret = panthor_gem_sync(obj, ops[i].type, ops[i].offset, 1560 ops[i].size); 1561 1562 drm_gem_object_put(obj); 1563 1564 if (ret) 1565 goto err_ops; 1566 } 1567 1568 err_ops: 1569 kvfree(ops); 1570 1571 return ret; 1572 } 1573 1574 static int panthor_ioctl_bo_query_info(struct drm_device *ddev, void *data, 1575 struct drm_file *file) 1576 { 1577 struct drm_panthor_bo_query_info *args = data; 1578 struct panthor_gem_object *bo; 1579 struct drm_gem_object *obj; 1580 1581 obj = drm_gem_object_lookup(file, args->handle); 1582 if (!obj) 1583 return -ENOENT; 1584 1585 bo = to_panthor_bo(obj); 1586 args->pad = 0; 1587 args->create_flags = bo->flags; 1588 1589 args->extra_flags = 0; 1590 if (drm_gem_is_imported(&bo->base)) 1591 args->extra_flags |= DRM_PANTHOR_BO_IS_IMPORTED; 1592 1593 drm_gem_object_put(obj); 1594 return 0; 1595 } 1596 1597 static int 1598 panthor_open(struct drm_device *ddev, struct drm_file *file) 1599 { 1600 struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base); 1601 struct panthor_file *pfile; 1602 int ret; 1603 1604 pfile = kzalloc_obj(*pfile); 1605 if (!pfile) 1606 return -ENOMEM; 1607 1608 pfile->ptdev = ptdev; 1609 pfile->user_mmio.offset = DRM_PANTHOR_USER_MMIO_OFFSET; 1610 1611 #ifdef CONFIG_ARM64 1612 /* 1613 * With 32-bit systems being limited by the 32-bit representation of 1614 * mmap2's pgoffset field, we need to make the MMIO offset arch 1615 * specific. 1616 */ 1617 if (test_tsk_thread_flag(current, TIF_32BIT)) 1618 pfile->user_mmio.offset = DRM_PANTHOR_USER_MMIO_OFFSET_32BIT; 1619 #endif 1620 1621 1622 ret = panthor_vm_pool_create(pfile); 1623 if (ret) 1624 goto err_free_file; 1625 1626 ret = panthor_group_pool_create(pfile); 1627 if (ret) 1628 goto err_destroy_vm_pool; 1629 1630 file->driver_priv = pfile; 1631 return 0; 1632 1633 err_destroy_vm_pool: 1634 panthor_vm_pool_destroy(pfile); 1635 1636 err_free_file: 1637 kfree(pfile); 1638 return ret; 1639 } 1640 1641 static void 1642 panthor_postclose(struct drm_device *ddev, struct drm_file *file) 1643 { 1644 struct panthor_file *pfile = file->driver_priv; 1645 1646 panthor_group_pool_destroy(pfile); 1647 panthor_vm_pool_destroy(pfile); 1648 1649 kfree(pfile); 1650 } 1651 1652 static const struct drm_ioctl_desc panthor_drm_driver_ioctls[] = { 1653 #define PANTHOR_IOCTL(n, func, flags) \ 1654 DRM_IOCTL_DEF_DRV(PANTHOR_##n, panthor_ioctl_##func, flags) 1655 1656 PANTHOR_IOCTL(DEV_QUERY, dev_query, DRM_RENDER_ALLOW), 1657 PANTHOR_IOCTL(VM_CREATE, vm_create, DRM_RENDER_ALLOW), 1658 PANTHOR_IOCTL(VM_DESTROY, vm_destroy, DRM_RENDER_ALLOW), 1659 PANTHOR_IOCTL(VM_BIND, vm_bind, DRM_RENDER_ALLOW), 1660 PANTHOR_IOCTL(VM_GET_STATE, vm_get_state, DRM_RENDER_ALLOW), 1661 PANTHOR_IOCTL(BO_CREATE, bo_create, DRM_RENDER_ALLOW), 1662 PANTHOR_IOCTL(BO_MMAP_OFFSET, bo_mmap_offset, DRM_RENDER_ALLOW), 1663 PANTHOR_IOCTL(GROUP_CREATE, group_create, DRM_RENDER_ALLOW), 1664 PANTHOR_IOCTL(GROUP_DESTROY, group_destroy, DRM_RENDER_ALLOW), 1665 PANTHOR_IOCTL(GROUP_GET_STATE, group_get_state, DRM_RENDER_ALLOW), 1666 PANTHOR_IOCTL(TILER_HEAP_CREATE, tiler_heap_create, DRM_RENDER_ALLOW), 1667 PANTHOR_IOCTL(TILER_HEAP_DESTROY, tiler_heap_destroy, DRM_RENDER_ALLOW), 1668 PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW), 1669 PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW), 1670 PANTHOR_IOCTL(SET_USER_MMIO_OFFSET, set_user_mmio_offset, DRM_RENDER_ALLOW), 1671 PANTHOR_IOCTL(BO_SYNC, bo_sync, DRM_RENDER_ALLOW), 1672 PANTHOR_IOCTL(BO_QUERY_INFO, bo_query_info, DRM_RENDER_ALLOW), 1673 }; 1674 1675 static int panthor_mmap(struct file *filp, struct vm_area_struct *vma) 1676 { 1677 struct drm_file *file = filp->private_data; 1678 struct panthor_file *pfile = file->driver_priv; 1679 struct panthor_device *ptdev = pfile->ptdev; 1680 u64 offset = (u64)vma->vm_pgoff << PAGE_SHIFT; 1681 u64 user_mmio_offset; 1682 int ret, cookie; 1683 1684 if (!drm_dev_enter(file->minor->dev, &cookie)) 1685 return -ENODEV; 1686 1687 /* Adjust the user MMIO offset to match the offset used kernel side. 1688 * We use a local variable with a READ_ONCE() here to make sure 1689 * the user_mmio_offset we use for the is_user_mmio_mapping() check 1690 * hasn't changed when we do the offset adjustment. 1691 */ 1692 user_mmio_offset = READ_ONCE(pfile->user_mmio.offset); 1693 if (offset >= user_mmio_offset) { 1694 offset -= user_mmio_offset; 1695 offset += DRM_PANTHOR_USER_MMIO_OFFSET; 1696 vma->vm_pgoff = offset >> PAGE_SHIFT; 1697 ret = panthor_device_mmap_io(ptdev, vma); 1698 } else { 1699 ret = drm_gem_mmap(filp, vma); 1700 } 1701 1702 drm_dev_exit(cookie); 1703 return ret; 1704 } 1705 1706 static void panthor_gpu_show_fdinfo(struct panthor_device *ptdev, 1707 struct panthor_file *pfile, 1708 struct drm_printer *p) 1709 { 1710 if (ptdev->profile_mask & PANTHOR_DEVICE_PROFILING_ALL) 1711 panthor_fdinfo_gather_group_samples(pfile); 1712 1713 if (ptdev->profile_mask & PANTHOR_DEVICE_PROFILING_TIMESTAMP) { 1714 #ifdef CONFIG_ARM_ARCH_TIMER 1715 drm_printf(p, "drm-engine-panthor:\t%llu ns\n", 1716 DIV_ROUND_UP_ULL((pfile->stats.time * NSEC_PER_SEC), 1717 arch_timer_get_cntfrq())); 1718 #endif 1719 } 1720 if (ptdev->profile_mask & PANTHOR_DEVICE_PROFILING_CYCLES) 1721 drm_printf(p, "drm-cycles-panthor:\t%llu\n", pfile->stats.cycles); 1722 1723 drm_printf(p, "drm-maxfreq-panthor:\t%lu Hz\n", ptdev->fast_rate); 1724 drm_printf(p, "drm-curfreq-panthor:\t%lu Hz\n", 1725 panthor_devfreq_get_freq(ptdev)); 1726 } 1727 1728 static void panthor_show_internal_memory_stats(struct drm_printer *p, struct drm_file *file) 1729 { 1730 char *drv_name = file->minor->dev->driver->name; 1731 struct panthor_file *pfile = file->driver_priv; 1732 struct drm_memory_stats stats = {0}; 1733 1734 panthor_fdinfo_gather_group_mem_info(pfile, &stats); 1735 panthor_vm_heaps_sizes(pfile, &stats); 1736 1737 drm_fdinfo_print_size(p, drv_name, "resident", "memory", stats.resident); 1738 drm_fdinfo_print_size(p, drv_name, "active", "memory", stats.active); 1739 } 1740 1741 static void panthor_show_fdinfo(struct drm_printer *p, struct drm_file *file) 1742 { 1743 struct drm_device *dev = file->minor->dev; 1744 struct panthor_device *ptdev = container_of(dev, struct panthor_device, base); 1745 1746 panthor_gpu_show_fdinfo(ptdev, file->driver_priv, p); 1747 panthor_show_internal_memory_stats(p, file); 1748 1749 drm_show_memory_stats(p, file); 1750 } 1751 1752 static const struct file_operations panthor_drm_driver_fops = { 1753 .owner = THIS_MODULE, 1754 .open = drm_open, 1755 .release = drm_release, 1756 .unlocked_ioctl = drm_ioctl, 1757 .compat_ioctl = drm_compat_ioctl, 1758 .poll = drm_poll, 1759 .read = drm_read, 1760 .llseek = noop_llseek, 1761 .mmap = panthor_mmap, 1762 .get_unmapped_area = drm_gem_get_unmapped_area, 1763 .show_fdinfo = drm_show_fdinfo, 1764 .fop_flags = FOP_UNSIGNED_OFFSET, 1765 }; 1766 1767 #ifdef CONFIG_DEBUG_FS 1768 static void panthor_debugfs_init(struct drm_minor *minor) 1769 { 1770 panthor_mmu_debugfs_init(minor); 1771 panthor_gem_debugfs_init(minor); 1772 } 1773 #endif 1774 1775 /* 1776 * PanCSF driver version: 1777 * - 1.0 - initial interface 1778 * - 1.1 - adds DEV_QUERY_TIMESTAMP_INFO query 1779 * - 1.2 - adds DEV_QUERY_GROUP_PRIORITIES_INFO query 1780 * - adds PANTHOR_GROUP_PRIORITY_REALTIME priority 1781 * - 1.3 - adds DRM_PANTHOR_GROUP_STATE_INNOCENT flag 1782 * - 1.4 - adds DRM_IOCTL_PANTHOR_BO_SET_LABEL ioctl 1783 * - 1.5 - adds DRM_PANTHOR_SET_USER_MMIO_OFFSET ioctl 1784 * - 1.6 - enables GLB_COUNTER_EN 1785 * - 1.7 - adds DRM_PANTHOR_BO_WB_MMAP flag 1786 * - adds DRM_IOCTL_PANTHOR_BO_SYNC ioctl 1787 * - adds DRM_IOCTL_PANTHOR_BO_QUERY_INFO ioctl 1788 * - adds drm_panthor_gpu_info::selected_coherency 1789 * - 1.8 - extends DEV_QUERY_TIMESTAMP_INFO with flags 1790 * - 1.9 - adds DRM_PANTHOR_DEV_QUERY_MMU_INFO query 1791 * - adds DRM_PANTHOR_VM_BIND_OP_MAP_SPARSE flag 1792 */ 1793 static const struct drm_driver panthor_drm_driver = { 1794 .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ | 1795 DRIVER_SYNCOBJ_TIMELINE, 1796 .open = panthor_open, 1797 .postclose = panthor_postclose, 1798 .show_fdinfo = panthor_show_fdinfo, 1799 .ioctls = panthor_drm_driver_ioctls, 1800 .num_ioctls = ARRAY_SIZE(panthor_drm_driver_ioctls), 1801 .fops = &panthor_drm_driver_fops, 1802 .name = "panthor", 1803 .desc = "Panthor DRM driver", 1804 .major = 1, 1805 .minor = 9, 1806 1807 .gem_prime_import_sg_table = panthor_gem_prime_import_sg_table, 1808 .gem_prime_import = panthor_gem_prime_import, 1809 #ifdef CONFIG_DEBUG_FS 1810 .debugfs_init = panthor_debugfs_init, 1811 #endif 1812 }; 1813 1814 #ifdef CONFIG_TRANSPARENT_HUGEPAGE 1815 bool panthor_transparent_hugepage = true; 1816 module_param_named(transparent_hugepage, panthor_transparent_hugepage, bool, 0400); 1817 MODULE_PARM_DESC(transparent_hugepage, "Use a dedicated tmpfs mount point with Transparent Hugepage enabled (true = default)"); 1818 #endif 1819 1820 static int panthor_probe(struct platform_device *pdev) 1821 { 1822 struct panthor_device *ptdev; 1823 1824 ptdev = devm_drm_dev_alloc(&pdev->dev, &panthor_drm_driver, 1825 struct panthor_device, base); 1826 if (IS_ERR(ptdev)) 1827 return PTR_ERR(ptdev); 1828 1829 platform_set_drvdata(pdev, ptdev); 1830 1831 return panthor_device_init(ptdev); 1832 } 1833 1834 static void panthor_remove(struct platform_device *pdev) 1835 { 1836 struct panthor_device *ptdev = platform_get_drvdata(pdev); 1837 1838 panthor_device_unplug(ptdev); 1839 } 1840 1841 static ssize_t profiling_show(struct device *dev, 1842 struct device_attribute *attr, 1843 char *buf) 1844 { 1845 struct panthor_device *ptdev = dev_get_drvdata(dev); 1846 1847 return sysfs_emit(buf, "%d\n", ptdev->profile_mask); 1848 } 1849 1850 static ssize_t profiling_store(struct device *dev, 1851 struct device_attribute *attr, 1852 const char *buf, size_t len) 1853 { 1854 struct panthor_device *ptdev = dev_get_drvdata(dev); 1855 u32 value; 1856 int err; 1857 1858 err = kstrtou32(buf, 0, &value); 1859 if (err) 1860 return err; 1861 1862 if ((value & ~PANTHOR_DEVICE_PROFILING_ALL) != 0) 1863 return -EINVAL; 1864 1865 ptdev->profile_mask = value; 1866 1867 return len; 1868 } 1869 1870 static DEVICE_ATTR_RW(profiling); 1871 1872 static struct attribute *panthor_attrs[] = { 1873 &dev_attr_profiling.attr, 1874 NULL, 1875 }; 1876 1877 ATTRIBUTE_GROUPS(panthor); 1878 1879 static const struct panthor_soc_data soc_data_mediatek_mt8196 = { 1880 .asn_hash_enable = true, 1881 .asn_hash = { 0xb, 0xe, 0x0, }, 1882 }; 1883 1884 static const struct of_device_id dt_match[] = { 1885 { .compatible = "mediatek,mt8196-mali", .data = &soc_data_mediatek_mt8196, }, 1886 { .compatible = "rockchip,rk3588-mali" }, 1887 { .compatible = "arm,mali-valhall-csf" }, 1888 {} 1889 }; 1890 MODULE_DEVICE_TABLE(of, dt_match); 1891 1892 static DEFINE_RUNTIME_DEV_PM_OPS(panthor_pm_ops, 1893 panthor_device_suspend, 1894 panthor_device_resume, 1895 NULL); 1896 1897 static struct platform_driver panthor_driver = { 1898 .probe = panthor_probe, 1899 .remove = panthor_remove, 1900 .driver = { 1901 .name = "panthor", 1902 .pm = pm_ptr(&panthor_pm_ops), 1903 .of_match_table = dt_match, 1904 .dev_groups = panthor_groups, 1905 }, 1906 }; 1907 1908 /* 1909 * Workqueue used to cleanup stuff. 1910 * 1911 * We create a dedicated workqueue so we can drain on unplug and 1912 * make sure all resources are freed before the module is unloaded. 1913 */ 1914 struct workqueue_struct *panthor_cleanup_wq; 1915 1916 static int __init panthor_init(void) 1917 { 1918 int ret; 1919 1920 ret = panthor_mmu_pt_cache_init(); 1921 if (ret) 1922 return ret; 1923 1924 panthor_cleanup_wq = alloc_workqueue("panthor-cleanup", WQ_UNBOUND, 0); 1925 if (!panthor_cleanup_wq) { 1926 pr_err("panthor: Failed to allocate the workqueues"); 1927 ret = -ENOMEM; 1928 goto err_mmu_pt_cache_fini; 1929 } 1930 1931 ret = platform_driver_register(&panthor_driver); 1932 if (ret) 1933 goto err_destroy_cleanup_wq; 1934 1935 return 0; 1936 1937 err_destroy_cleanup_wq: 1938 destroy_workqueue(panthor_cleanup_wq); 1939 1940 err_mmu_pt_cache_fini: 1941 panthor_mmu_pt_cache_fini(); 1942 return ret; 1943 } 1944 module_init(panthor_init); 1945 1946 static void __exit panthor_exit(void) 1947 { 1948 platform_driver_unregister(&panthor_driver); 1949 destroy_workqueue(panthor_cleanup_wq); 1950 panthor_mmu_pt_cache_fini(); 1951 } 1952 module_exit(panthor_exit); 1953 1954 MODULE_AUTHOR("Panthor Project Developers"); 1955 MODULE_DESCRIPTION("Panthor DRM Driver"); 1956 MODULE_LICENSE("Dual MIT/GPL"); 1957 MODULE_IMPORT_NS("DMA_BUF"); 1958