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

Configure Feed

Select the types of activity you want to include in your feed.

drm/panthor: Add a PANTHOR_BO_SYNC ioctl

This will be used by the UMD to synchronize CPU-cached mappings when
the UMD can't do it directly (no usermode cache maintenance instruction
on Arm32).

v2:
- Change the flags so they better match the drm_gem_shmem_sync()
semantics

v3:
- Add Steve's R-b

v4:
- No changes

v5:
- Drop Steve's R-b (the semantics changes call for a new review)

v6:
- Drop ret initialization in panthor_ioctl_bo_sync()
- Bail out early in panthor_ioctl_bo_sync() if ops.count is zero
- Drop unused PANTHOR_BO_SYNC_OP_FLAGS definition

v7:
- Hand-roll the sync logic (was previously provided by gem_shmem)

v8:
- Collect R-b

Signed-off-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Reviewed-by: Steven Price <steven.price@arm.com>
Link: https://patch.msgid.link/20251208100841.730527-5-boris.brezillon@collabora.com
Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>

+179 -1
+40 -1
drivers/gpu/drm/panthor/panthor_drv.c
··· 177 177 PANTHOR_UOBJ_DECL(struct drm_panthor_sync_op, timeline_value), \ 178 178 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_submit, syncs), \ 179 179 PANTHOR_UOBJ_DECL(struct drm_panthor_queue_create, ringbuf_size), \ 180 - PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs)) 180 + PANTHOR_UOBJ_DECL(struct drm_panthor_vm_bind_op, syncs), \ 181 + PANTHOR_UOBJ_DECL(struct drm_panthor_bo_sync_op, size)) 181 182 182 183 /** 183 184 * PANTHOR_UOBJ_SET() - Copy a kernel object to a user object. ··· 1397 1396 return 0; 1398 1397 } 1399 1398 1399 + static int panthor_ioctl_bo_sync(struct drm_device *ddev, void *data, 1400 + struct drm_file *file) 1401 + { 1402 + struct drm_panthor_bo_sync *args = data; 1403 + struct drm_panthor_bo_sync_op *ops; 1404 + struct drm_gem_object *obj; 1405 + int ret; 1406 + 1407 + if (!args->ops.count) 1408 + return 0; 1409 + 1410 + ret = PANTHOR_UOBJ_GET_ARRAY(ops, &args->ops); 1411 + if (ret) 1412 + return ret; 1413 + 1414 + for (u32 i = 0; i < args->ops.count; i++) { 1415 + obj = drm_gem_object_lookup(file, ops[i].handle); 1416 + if (!obj) { 1417 + ret = -ENOENT; 1418 + goto err_ops; 1419 + } 1420 + 1421 + ret = panthor_gem_sync(obj, ops[i].type, ops[i].offset, 1422 + ops[i].size); 1423 + 1424 + drm_gem_object_put(obj); 1425 + 1426 + if (ret) 1427 + goto err_ops; 1428 + } 1429 + 1430 + err_ops: 1431 + kvfree(ops); 1432 + 1433 + return ret; 1434 + } 1435 + 1400 1436 static int 1401 1437 panthor_open(struct drm_device *ddev, struct drm_file *file) 1402 1438 { ··· 1508 1470 PANTHOR_IOCTL(GROUP_SUBMIT, group_submit, DRM_RENDER_ALLOW), 1509 1471 PANTHOR_IOCTL(BO_SET_LABEL, bo_set_label, DRM_RENDER_ALLOW), 1510 1472 PANTHOR_IOCTL(SET_USER_MMIO_OFFSET, set_user_mmio_offset, DRM_RENDER_ALLOW), 1473 + PANTHOR_IOCTL(BO_SYNC, bo_sync, DRM_RENDER_ALLOW), 1511 1474 }; 1512 1475 1513 1476 static int panthor_mmap(struct file *filp, struct vm_area_struct *vma)
+85
drivers/gpu/drm/panthor/panthor_gem.c
··· 465 465 panthor_gem_bo_set_label(bo->obj, str); 466 466 } 467 467 468 + int 469 + panthor_gem_sync(struct drm_gem_object *obj, u32 type, 470 + u64 offset, u64 size) 471 + { 472 + struct panthor_gem_object *bo = to_panthor_bo(obj); 473 + struct drm_gem_shmem_object *shmem = &bo->base; 474 + const struct drm_device *dev = shmem->base.dev; 475 + struct sg_table *sgt; 476 + struct scatterlist *sgl; 477 + unsigned int count; 478 + 479 + /* Make sure the range is in bounds. */ 480 + if (offset + size < offset || offset + size > shmem->base.size) 481 + return -EINVAL; 482 + 483 + /* Disallow CPU-cache maintenance on imported buffers. */ 484 + if (drm_gem_is_imported(&shmem->base)) 485 + return -EINVAL; 486 + 487 + switch (type) { 488 + case DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH: 489 + case DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE: 490 + break; 491 + 492 + default: 493 + return -EINVAL; 494 + } 495 + 496 + /* Don't bother if it's WC-mapped */ 497 + if (shmem->map_wc) 498 + return 0; 499 + 500 + /* Nothing to do if the size is zero. */ 501 + if (size == 0) 502 + return 0; 503 + 504 + sgt = drm_gem_shmem_get_pages_sgt(shmem); 505 + if (IS_ERR(sgt)) 506 + return PTR_ERR(sgt); 507 + 508 + for_each_sgtable_dma_sg(sgt, sgl, count) { 509 + if (size == 0) 510 + break; 511 + 512 + dma_addr_t paddr = sg_dma_address(sgl); 513 + size_t len = sg_dma_len(sgl); 514 + 515 + if (len <= offset) { 516 + offset -= len; 517 + continue; 518 + } 519 + 520 + paddr += offset; 521 + len -= offset; 522 + len = min_t(size_t, len, size); 523 + size -= len; 524 + offset = 0; 525 + 526 + /* It's unclear whether dma_sync_xxx() is the right API to do CPU 527 + * cache maintenance given an IOMMU can register their own 528 + * implementation doing more than just CPU cache flushes/invalidation, 529 + * and what we really care about here is CPU caches only, but that's 530 + * the best we have that is both arch-agnostic and does at least the 531 + * CPU cache maintenance on a <page,offset,size> tuple. 532 + * 533 + * Also, I wish we could do a single 534 + * 535 + * dma_sync_single_for_device(BIDIR) 536 + * 537 + * and get a flush+invalidate, but that's not how it's implemented 538 + * in practice (at least on arm64), so we have to make it 539 + * 540 + * dma_sync_single_for_device(TO_DEVICE) 541 + * dma_sync_single_for_cpu(FROM_DEVICE) 542 + * 543 + * for the flush+invalidate case. 544 + */ 545 + dma_sync_single_for_device(dev->dev, paddr, len, DMA_TO_DEVICE); 546 + if (type == DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE) 547 + dma_sync_single_for_cpu(dev->dev, paddr, len, DMA_FROM_DEVICE); 548 + } 549 + 550 + return 0; 551 + } 552 + 468 553 #ifdef CONFIG_DEBUG_FS 469 554 struct gem_size_totals { 470 555 size_t size;
+2
drivers/gpu/drm/panthor/panthor_gem.h
··· 148 148 149 149 void panthor_gem_bo_set_label(struct drm_gem_object *obj, const char *label); 150 150 void panthor_gem_kernel_bo_set_label(struct panthor_kernel_bo *bo, const char *label); 151 + int panthor_gem_sync(struct drm_gem_object *obj, 152 + u32 type, u64 offset, u64 size); 151 153 152 154 struct drm_gem_object * 153 155 panthor_gem_prime_import(struct drm_device *dev,
+52
include/uapi/drm/panthor_drm.h
··· 144 144 * pgoff_t size. 145 145 */ 146 146 DRM_PANTHOR_SET_USER_MMIO_OFFSET, 147 + 148 + /** @DRM_PANTHOR_BO_SYNC: Sync BO data to/from the device */ 149 + DRM_PANTHOR_BO_SYNC, 147 150 }; 148 151 149 152 /** ··· 1077 1074 }; 1078 1075 1079 1076 /** 1077 + * enum drm_panthor_bo_sync_op_type - BO sync type 1078 + */ 1079 + enum drm_panthor_bo_sync_op_type { 1080 + /** @DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH: Flush CPU caches. */ 1081 + DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH = 0, 1082 + 1083 + /** @DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE: Flush and invalidate CPU caches. */ 1084 + DRM_PANTHOR_BO_SYNC_CPU_CACHE_FLUSH_AND_INVALIDATE = 1, 1085 + }; 1086 + 1087 + /** 1088 + * struct drm_panthor_bo_sync_op - BO map sync op 1089 + */ 1090 + struct drm_panthor_bo_sync_op { 1091 + /** @handle: Handle of the buffer object to sync. */ 1092 + __u32 handle; 1093 + 1094 + /** @type: Type of operation. */ 1095 + __u32 type; 1096 + 1097 + /** 1098 + * @offset: Offset into the BO at which the sync range starts. 1099 + * 1100 + * This will be rounded down to the nearest cache line as needed. 1101 + */ 1102 + __u64 offset; 1103 + 1104 + /** 1105 + * @size: Size of the range to sync 1106 + * 1107 + * @size + @offset will be rounded up to the nearest cache line as 1108 + * needed. 1109 + */ 1110 + __u64 size; 1111 + }; 1112 + 1113 + /** 1114 + * struct drm_panthor_bo_sync - BO map sync request 1115 + */ 1116 + struct drm_panthor_bo_sync { 1117 + /** 1118 + * @ops: Array of struct drm_panthor_bo_sync_op sync operations. 1119 + */ 1120 + struct drm_panthor_obj_array ops; 1121 + }; 1122 + 1123 + /** 1080 1124 * DRM_IOCTL_PANTHOR() - Build a Panthor IOCTL number 1081 1125 * @__access: Access type. Must be R, W or RW. 1082 1126 * @__id: One of the DRM_PANTHOR_xxx id. ··· 1169 1119 DRM_IOCTL_PANTHOR(WR, BO_SET_LABEL, bo_set_label), 1170 1120 DRM_IOCTL_PANTHOR_SET_USER_MMIO_OFFSET = 1171 1121 DRM_IOCTL_PANTHOR(WR, SET_USER_MMIO_OFFSET, set_user_mmio_offset), 1122 + DRM_IOCTL_PANTHOR_BO_SYNC = 1123 + DRM_IOCTL_PANTHOR(WR, BO_SYNC, bo_sync), 1172 1124 }; 1173 1125 1174 1126 #if defined(__cplusplus)