All V3D BOs are mapped write-combined, which makes CPU reads slow. Buffers frequently read by the CPU, or with access patterns that make non-cacheable mappings inefficient, can benefit from cached mappings.
Add DRM_V3D_BO_WB_MMAP to let userspace request a cached mapping. As V3D is not I/O coherent, userspace becomes responsible for CPU cache maintenance around the job execution. Note that this also includes CPU jobs, as the kernel accesses the BOs through write-combined mappings. Signed-off-by: Maíra Canal <[email protected]> --- drivers/gpu/drm/v3d/v3d_bo.c | 11 ++++++----- drivers/gpu/drm/v3d/v3d_drv.h | 3 +-- drivers/gpu/drm/v3d/v3d_irq.c | 2 +- include/uapi/drm/v3d_drm.h | 9 +++++++-- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_bo.c b/drivers/gpu/drm/v3d/v3d_bo.c index 803f3bbb7144..0a5a056d4b26 100644 --- a/drivers/gpu/drm/v3d/v3d_bo.c +++ b/drivers/gpu/drm/v3d/v3d_bo.c @@ -173,18 +173,19 @@ v3d_bo_create_finish(struct drm_gem_object *obj) return 0; } -struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv, - size_t unaligned_size) +struct v3d_bo *v3d_bo_create(struct drm_device *dev, size_t size, u32 flags) { struct drm_gem_shmem_object *shmem_obj; struct v3d_bo *bo; int ret; - shmem_obj = drm_gem_shmem_create(dev, unaligned_size); + shmem_obj = drm_gem_shmem_create(dev, size); if (IS_ERR(shmem_obj)) return ERR_CAST(shmem_obj); + bo = to_v3d_bo(&shmem_obj->base); bo->vaddr = NULL; + bo->base.map_wc = !(flags & DRM_V3D_BO_WB_MMAP); ret = v3d_bo_create_finish(&shmem_obj->base); if (ret) @@ -239,12 +240,12 @@ int v3d_create_bo_ioctl(struct drm_device *dev, void *data, struct v3d_bo *bo = NULL; int ret; - if (args->flags != 0) { + if (args->flags & ~DRM_V3D_BO_WB_MMAP) { drm_dbg(dev, "unknown create_bo flags: %d\n", args->flags); return -EINVAL; } - bo = v3d_bo_create(dev, file_priv, PAGE_ALIGN(args->size)); + bo = v3d_bo_create(dev, PAGE_ALIGN(args->size), args->flags); if (IS_ERR(bo)) return PTR_ERR(bo); diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index e0eed4cfef61..4f32fc3ab1de 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -591,8 +591,7 @@ struct v3d_submit_ext { /* v3d_bo.c */ struct drm_gem_object *v3d_create_object(struct drm_device *dev, size_t size); void v3d_free_object(struct drm_gem_object *gem_obj); -struct v3d_bo *v3d_bo_create(struct drm_device *dev, struct drm_file *file_priv, - size_t size); +struct v3d_bo *v3d_bo_create(struct drm_device *dev, size_t size, u32 flags); void v3d_get_bo_vaddr(struct v3d_bo *bo); void v3d_put_bo_vaddr(struct v3d_bo *bo); int v3d_create_bo_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index 963d711dc16b..19315acf567a 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -43,7 +43,7 @@ v3d_overflow_mem_work(struct work_struct *work) struct v3d_dev *v3d = container_of(work, struct v3d_dev, overflow_mem_work); struct drm_device *dev = &v3d->drm; - struct v3d_bo *bo = v3d_bo_create(dev, NULL /* XXX: GMP */, 256 * 1024); + struct v3d_bo *bo = v3d_bo_create(dev, SZ_256K, 0); struct v3d_queue_state *queue = &v3d->queue[V3D_BIN]; struct v3d_bin_job *bin_job; struct drm_gem_object *obj; diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h index 2750a6fbb6b8..4221c7544d08 100644 --- a/include/uapi/drm/v3d_drm.h +++ b/include/uapi/drm/v3d_drm.h @@ -237,11 +237,16 @@ struct drm_v3d_wait_bo { __u64 timeout_ns; }; +/* + * Map the BO CPU-cached instead of write-combined. Userspace is responsible + * for CPU cache maintenance. + */ +#define DRM_V3D_BO_WB_MMAP 0x01 + /** * struct drm_v3d_create_bo - ioctl argument for creating V3D BOs. * - * There are currently no values for the flags argument, but it may be - * used in a future extension. + * @flags is a mask of DRM_V3D_BO_* flags. */ struct drm_v3d_create_bo { __u32 size; -- 2.56.0
