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

drm/v3d: add generic ioctl extension

Add support to attach generic extensions on job submission. This patch
is third prep work to enable multiple syncobjs on job submission. With
this work, when the job submission interface needs to be extended to
accommodate a new feature, we will use a generic extension struct where
an id determines the data type to be pointed. The first application is
to enable multiples in/out syncobj (next patch), but the base is
already done for future features. Therefore, to attach a new feature,
a specific extension struct should subclass drm_v3d_extension and
update the list of extensions in a job submission.

v2:
- remove redundant elements to subclass struct (Daniel)

v3:
- add comment for v3d_get_extensions

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/ed53b1cd7e3125b76f18fe3fb995a04393639bc6.1633016479.git.mwen@igalia.com

authored by

Melissa Wen and committed by
Melissa Wen
bb3425ef 07c2a416

+103 -6
+1 -3
drivers/gpu/drm/v3d/v3d_drv.c
··· 83 83 return 0; 84 84 } 85 85 86 - 87 86 switch (args->param) { 88 87 case DRM_V3D_PARAM_SUPPORTS_TFU: 89 88 args->value = 1; ··· 146 147 DEFINE_DRM_GEM_FOPS(v3d_drm_fops); 147 148 148 149 /* DRM_AUTH is required on SUBMIT_CL for now, while we don't have GMP 149 - * protection between clients. Note that render nodes would be be 150 + * protection between clients. Note that render nodes would be 150 151 * able to submit CLs that could access BOs from clients authenticated 151 152 * with the master node. The TFU doesn't use the GMP, so it would 152 153 * need to stay DRM_AUTH until we do buffer size/offset validation. ··· 217 218 int ret; 218 219 u32 mmu_debug; 219 220 u32 ident1; 220 - 221 221 222 222 v3d = devm_drm_dev_alloc(dev, &v3d_drm_driver, struct v3d_dev, drm); 223 223 if (IS_ERR(v3d))
+71 -3
drivers/gpu/drm/v3d/v3d_gem.c
··· 537 537 } 538 538 } 539 539 540 + /* Whenever userspace sets ioctl extensions, v3d_get_extensions parses data 541 + * according to the extension id (name). 542 + */ 543 + static int 544 + v3d_get_extensions(struct drm_file *file_priv, u64 ext_handles) 545 + { 546 + struct drm_v3d_extension __user *user_ext; 547 + 548 + user_ext = u64_to_user_ptr(ext_handles); 549 + while (user_ext) { 550 + struct drm_v3d_extension ext; 551 + 552 + if (copy_from_user(&ext, user_ext, sizeof(ext))) { 553 + DRM_DEBUG("Failed to copy submit extension\n"); 554 + return -EFAULT; 555 + } 556 + 557 + switch (ext.id) { 558 + case 0: 559 + default: 560 + DRM_DEBUG_DRIVER("Unknown extension id: %d\n", ext.id); 561 + return -EINVAL; 562 + } 563 + 564 + user_ext = u64_to_user_ptr(ext.next); 565 + } 566 + 567 + return 0; 568 + } 569 + 540 570 /** 541 571 * v3d_submit_cl_ioctl() - Submits a job (frame) to the V3D. 542 572 * @dev: DRM device ··· 595 565 596 566 trace_v3d_submit_cl_ioctl(&v3d->drm, args->rcl_start, args->rcl_end); 597 567 598 - if (args->pad != 0) 568 + if (args->pad) 599 569 return -EINVAL; 600 570 601 - if (args->flags != 0 && 602 - args->flags != DRM_V3D_SUBMIT_CL_FLUSH_CACHE) { 571 + if (args->flags && 572 + args->flags & ~(DRM_V3D_SUBMIT_CL_FLUSH_CACHE | 573 + DRM_V3D_SUBMIT_EXTENSION)) { 603 574 DRM_INFO("invalid flags: %d\n", args->flags); 604 575 return -EINVAL; 576 + } 577 + 578 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 579 + ret = v3d_get_extensions(file_priv, args->extensions); 580 + if (ret) { 581 + DRM_DEBUG("Failed to get extensions.\n"); 582 + return ret; 583 + } 605 584 } 606 585 607 586 ret = v3d_job_init(v3d, file_priv, (void *)&render, sizeof(*render), ··· 741 702 742 703 trace_v3d_submit_tfu_ioctl(&v3d->drm, args->iia); 743 704 705 + if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 706 + DRM_DEBUG("invalid flags: %d\n", args->flags); 707 + return -EINVAL; 708 + } 709 + 710 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 711 + ret = v3d_get_extensions(file_priv, args->extensions); 712 + if (ret) { 713 + DRM_DEBUG("Failed to get extensions.\n"); 714 + return ret; 715 + } 716 + } 717 + 744 718 ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job), 745 719 v3d_job_free, args->in_sync, V3D_TFU); 746 720 if (ret) ··· 838 786 839 787 trace_v3d_submit_csd_ioctl(&v3d->drm, args->cfg[5], args->cfg[6]); 840 788 789 + if (args->pad) 790 + return -EINVAL; 791 + 841 792 if (!v3d_has_csd(v3d)) { 842 793 DRM_DEBUG("Attempting CSD submit on non-CSD hardware\n"); 843 794 return -EINVAL; 795 + } 796 + 797 + if (args->flags && !(args->flags & DRM_V3D_SUBMIT_EXTENSION)) { 798 + DRM_INFO("invalid flags: %d\n", args->flags); 799 + return -EINVAL; 800 + } 801 + 802 + if (args->flags & DRM_V3D_SUBMIT_EXTENSION) { 803 + ret = v3d_get_extensions(file_priv, args->extensions); 804 + if (ret) { 805 + DRM_DEBUG("Failed to get extensions.\n"); 806 + return ret; 807 + } 844 808 } 845 809 846 810 ret = v3d_job_init(v3d, file_priv, (void *)&job, sizeof(*job),
+31
include/uapi/drm/v3d_drm.h
··· 58 58 struct drm_v3d_perfmon_get_values) 59 59 60 60 #define DRM_V3D_SUBMIT_CL_FLUSH_CACHE 0x01 61 + #define DRM_V3D_SUBMIT_EXTENSION 0x02 62 + 63 + /* struct drm_v3d_extension - ioctl extensions 64 + * 65 + * Linked-list of generic extensions where the id identify which struct is 66 + * pointed by ext_data. Therefore, DRM_V3D_EXT_ID_* is used on id to identify 67 + * the extension type. 68 + */ 69 + struct drm_v3d_extension { 70 + __u64 next; 71 + __u32 id; 72 + #define DRM_V3D_EXT_ID_MULTI_SYNC 0x01 73 + __u32 flags; /* mbz */ 74 + }; 61 75 62 76 /** 63 77 * struct drm_v3d_submit_cl - ioctl argument for submitting commands to the 3D ··· 149 135 /* Number of BO handles passed in (size is that times 4). */ 150 136 __u32 bo_handle_count; 151 137 138 + /* DRM_V3D_SUBMIT_* properties */ 152 139 __u32 flags; 153 140 154 141 /* ID of the perfmon to attach to this job. 0 means no perfmon. */ 155 142 __u32 perfmon_id; 156 143 157 144 __u32 pad; 145 + 146 + /* Pointer to an array of ioctl extensions*/ 147 + __u64 extensions; 158 148 }; 159 149 160 150 /** ··· 266 248 __u32 in_sync; 267 249 /* Sync object to signal when the TFU job is done. */ 268 250 __u32 out_sync; 251 + 252 + __u32 flags; 253 + 254 + /* Pointer to an array of ioctl extensions*/ 255 + __u64 extensions; 256 + 269 257 }; 270 258 271 259 /* Submits a compute shader for dispatch. This job will block on any ··· 300 276 301 277 /* ID of the perfmon to attach to this job. 0 means no perfmon. */ 302 278 __u32 perfmon_id; 279 + 280 + /* Pointer to an array of ioctl extensions*/ 281 + __u64 extensions; 282 + 283 + __u32 flags; 284 + 285 + __u32 pad; 303 286 }; 304 287 305 288 enum {