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

Reply via email to