Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/v3d: alloc and init job in one shot

Move job memory allocation to v3d_job_init function. This aim to facilitate
error handling in job initialization, since cleanup steps are similar for
all (struct v3d_job)-based types of job involved in a command submission.
To generalize v3d_job_init(), this change takes into account that all job
structs have the first element a struct v3d_job (bin, render, tfu, csd) or
it is a v3d_job itself (clean_job) for pointer casting.

v3:
- explicitly init job as NULL (Iago)
- fix pm failure handling on v3_job_init (Iago)

Suggested-by: Iago Toral Quiroga <itoral@igalia.com>
Signed-off-by: Melissa Wen <mwen@igalia.com>
Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Signed-off-by: Melissa Wen <melissa.srw@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/4d12e07bd334d2cddb51cabd359e99edde595619.1633016479.git.mwen@igalia.com

authored by

Melissa Wen and committed by
Melissa Wen
07c2a416 223583dd

+53 -82
+53 -82
drivers/gpu/drm/v3d/v3d_gem.c
··· 392 392 393 393 void v3d_job_cleanup(struct v3d_job *job) 394 394 { 395 + if (!job) 396 + return; 397 + 395 398 drm_sched_job_cleanup(&job->base); 396 399 v3d_job_put(job); 397 400 } ··· 453 450 454 451 static int 455 452 v3d_job_init(struct v3d_dev *v3d, struct drm_file *file_priv, 456 - struct v3d_job *job, void (*free)(struct kref *ref), 453 + void **container, size_t size, void (*free)(struct kref *ref), 457 454 u32 in_sync, enum v3d_queue queue) 458 455 { 459 456 struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 457 + struct v3d_job *job; 460 458 int ret; 461 459 460 + *container = kcalloc(1, size, GFP_KERNEL); 461 + if (!*container) { 462 + DRM_ERROR("Cannot allocate memory for v3d job."); 463 + return -ENOMEM; 464 + } 465 + 466 + job = *container; 462 467 job->v3d = v3d; 463 468 job->free = free; 464 469 465 470 ret = pm_runtime_get_sync(v3d->drm.dev); 466 471 if (ret < 0) 467 - return ret; 472 + goto fail; 468 473 469 474 ret = drm_sched_job_init(&job->base, &v3d_priv->sched_entity[queue], 470 475 v3d_priv); 471 476 if (ret) 472 - goto fail; 477 + goto fail_job; 473 478 474 479 ret = v3d_job_add_deps(file_priv, job, in_sync, 0); 475 480 if (ret) 476 - goto fail_job; 481 + goto fail_deps; 477 482 478 483 kref_init(&job->refcount); 479 484 480 485 return 0; 481 - fail_job: 486 + 487 + fail_deps: 482 488 drm_sched_job_cleanup(&job->base); 483 - fail: 489 + fail_job: 484 490 pm_runtime_put_autosuspend(v3d->drm.dev); 491 + fail: 492 + kfree(*container); 493 + *container = NULL; 494 + 485 495 return ret; 486 496 } 487 497 ··· 557 541 struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 558 542 struct drm_v3d_submit_cl *args = data; 559 543 struct v3d_bin_job *bin = NULL; 560 - struct v3d_render_job *render; 544 + struct v3d_render_job *render = NULL; 561 545 struct v3d_job *clean_job = NULL; 562 546 struct v3d_job *last_job; 563 547 struct ww_acquire_ctx acquire_ctx; ··· 574 558 return -EINVAL; 575 559 } 576 560 577 - render = kcalloc(1, sizeof(*render), GFP_KERNEL); 578 - if (!render) 579 - return -ENOMEM; 561 + ret = v3d_job_init(v3d, file_priv, (void *)&render, sizeof(*render), 562 + v3d_render_job_free, args->in_sync_rcl, V3D_RENDER); 563 + if (ret) 564 + goto fail; 580 565 581 566 render->start = args->rcl_start; 582 567 render->end = args->rcl_end; 583 568 INIT_LIST_HEAD(&render->unref_list); 584 569 585 - ret = v3d_job_init(v3d, file_priv, &render->base, 586 - v3d_render_job_free, args->in_sync_rcl, V3D_RENDER); 587 - if (ret) { 588 - kfree(render); 589 - return ret; 590 - } 591 - 592 570 if (args->bcl_start != args->bcl_end) { 593 - bin = kcalloc(1, sizeof(*bin), GFP_KERNEL); 594 - if (!bin) { 595 - v3d_job_cleanup(&render->base); 596 - return -ENOMEM; 597 - } 598 - 599 - ret = v3d_job_init(v3d, file_priv, &bin->base, 571 + ret = v3d_job_init(v3d, file_priv, (void *)&bin, sizeof(*bin), 600 572 v3d_job_free, args->in_sync_bcl, V3D_BIN); 601 - if (ret) { 602 - v3d_job_cleanup(&render->base); 603 - kfree(bin); 604 - return ret; 605 - } 573 + if (ret) 574 + goto fail; 606 575 607 576 bin->start = args->bcl_start; 608 577 bin->end = args->bcl_end; ··· 598 597 } 599 598 600 599 if (args->flags & DRM_V3D_SUBMIT_CL_FLUSH_CACHE) { 601 - clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL); 602 - if (!clean_job) { 603 - ret = -ENOMEM; 600 + ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job), 601 + v3d_job_free, 0, V3D_CACHE_CLEAN); 602 + if (ret) 604 603 goto fail; 605 - } 606 - 607 - ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0, V3D_CACHE_CLEAN); 608 - if (ret) { 609 - kfree(clean_job); 610 - clean_job = NULL; 611 - goto fail; 612 - } 613 604 614 605 last_job = clean_job; 615 606 } else { ··· 674 681 drm_gem_unlock_reservations(last_job->bo, 675 682 last_job->bo_count, &acquire_ctx); 676 683 fail: 677 - if (bin) 678 - v3d_job_cleanup(&bin->base); 679 - v3d_job_cleanup(&render->base); 680 - if (clean_job) 681 - v3d_job_cleanup(clean_job); 684 + v3d_job_cleanup((void *)bin); 685 + v3d_job_cleanup((void *)render); 686 + v3d_job_cleanup(clean_job); 682 687 683 688 return ret; 684 689 } ··· 696 705 { 697 706 struct v3d_dev *v3d = to_v3d_dev(dev); 698 707 struct drm_v3d_submit_tfu *args = data; 699 - struct v3d_tfu_job *job; 708 + struct v3d_tfu_job *job = NULL; 700 709 struct ww_acquire_ctx acquire_ctx; 701 710 int ret = 0; 702 711 703 712 trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia); 704 713 705 - job = kcalloc(1, sizeof(*job), GFP_KERNEL); 706 - if (!job) 707 - return -ENOMEM; 708 - 709 - ret = v3d_job_init(v3d, file_priv, &job->base, 714 + ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job), 710 715 v3d_job_free, args->in_sync, V3D_TFU); 711 - if (ret) { 712 - kfree(job); 713 - return ret; 714 - } 716 + if (ret) 717 + goto fail; 715 718 716 719 job->base.bo = kcalloc(ARRAY_SIZE(args->bo_handles), 717 720 sizeof(*job->base.bo), GFP_KERNEL); 718 721 if (!job->base.bo) { 719 - v3d_job_cleanup(&job->base); 720 - return -ENOMEM; 722 + ret = -ENOMEM; 723 + goto fail; 721 724 } 722 725 723 726 job->args = *args; ··· 758 773 return 0; 759 774 760 775 fail: 761 - v3d_job_cleanup(&job->base); 776 + v3d_job_cleanup((void *)job); 762 777 763 778 return ret; 764 779 } ··· 779 794 struct v3d_dev *v3d = to_v3d_dev(dev); 780 795 struct v3d_file_priv *v3d_priv = file_priv->driver_priv; 781 796 struct drm_v3d_submit_csd *args = data; 782 - struct v3d_csd_job *job; 783 - struct v3d_job *clean_job; 797 + struct v3d_csd_job *job = NULL; 798 + struct v3d_job *clean_job = NULL; 784 799 struct ww_acquire_ctx acquire_ctx; 785 800 int ret; 786 801 ··· 791 806 return -EINVAL; 792 807 } 793 808 794 - job = kcalloc(1, sizeof(*job), GFP_KERNEL); 795 - if (!job) 796 - return -ENOMEM; 797 - 798 - ret = v3d_job_init(v3d, file_priv, &job->base, 809 + ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job), 799 810 v3d_job_free, args->in_sync, V3D_CSD); 800 - if (ret) { 801 - kfree(job); 802 - return ret; 803 - } 811 + if (ret) 812 + goto fail; 804 813 805 - clean_job = kcalloc(1, sizeof(*clean_job), GFP_KERNEL); 806 - if (!clean_job) { 807 - v3d_job_cleanup(&job->base); 808 - return -ENOMEM; 809 - } 810 - 811 - ret = v3d_job_init(v3d, file_priv, clean_job, v3d_job_free, 0, V3D_CACHE_CLEAN); 812 - if (ret) { 813 - v3d_job_cleanup(&job->base); 814 - kfree(clean_job); 815 - return ret; 816 - } 814 + ret = v3d_job_init(v3d, file_priv, (void *)&clean_job, sizeof(*clean_job), 815 + v3d_job_free, 0, V3D_CACHE_CLEAN); 816 + if (ret) 817 + goto fail; 817 818 818 819 job->args = *args; 819 820 ··· 848 877 drm_gem_unlock_reservations(clean_job->bo, clean_job->bo_count, 849 878 &acquire_ctx); 850 879 fail: 851 - v3d_job_cleanup(&job->base); 880 + v3d_job_cleanup((void *)job); 852 881 v3d_job_cleanup(clean_job); 853 882 854 883 return ret;