The number of attributes/objects you can pass to the
DRM_IOCTL_VC4_SUBMIT_CL ioctl is limited by the drm_vc4_submit_cl struct
size.

Add a mechanism to easily pass extra attributes when submitting a CL to
the V3D engine.

Signed-off-by: Boris Brezillon <boris.brezil...@free-electrons.com>
---
 drivers/gpu/drm/vc4/vc4_drv.c |  1 +
 drivers/gpu/drm/vc4/vc4_drv.h |  2 ++
 drivers/gpu/drm/vc4/vc4_gem.c | 60 +++++++++++++++++++++++++++++++-
 include/uapi/drm/vc4_drm.h    | 81 +++++++++++++++++++++++++++++++++++++------
 4 files changed, 133 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index e3c29729da2e..5c62013f8ca3 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -101,6 +101,7 @@ static int vc4_get_param_ioctl(struct drm_device *dev, void 
*data,
        case DRM_VC4_PARAM_SUPPORTS_THREADED_FS:
        case DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER:
        case DRM_VC4_PARAM_SUPPORTS_MADVISE:
+       case DRM_VC4_PARAM_SUPPORTS_EXTENDED_CL:
                args->value = true;
                break;
        default:
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 9c0d380c96f2..3c54cc386443 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -318,6 +318,8 @@ struct vc4_exec_info {
 
        /* Kernel-space copy of the ioctl arguments */
        struct drm_vc4_submit_cl *args;
+       uint32_t nchunks;
+       union drm_vc4_submit_cl_chunk *chunks;
 
        /* This is the array of BOs that were looked up at the start of exec.
         * Command validation will use indices into this array.
diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c
index 6c32c89a83a9..06976c61422a 100644
--- a/drivers/gpu/drm/vc4/vc4_gem.c
+++ b/drivers/gpu/drm/vc4/vc4_gem.c
@@ -920,6 +920,7 @@ vc4_complete_exec(struct drm_device *dev, struct 
vc4_exec_info *exec)
        }
        mutex_unlock(&vc4->power_lock);
 
+       kfree(exec->chunks);
        kfree(exec);
 }
 
@@ -1048,6 +1049,27 @@ vc4_wait_bo_ioctl(struct drm_device *dev, void *data,
        return ret;
 }
 
+static int
+vc4_parse_cl_chunk(struct vc4_dev *vc4, struct vc4_exec_info *exec,
+                  const union drm_vc4_submit_cl_chunk *chunk)
+{
+       switch(chunk->dummy.type) {
+       case VC4_BIN_CL_CHUNK:
+               /* Update bin_cl related fields so that we don't have to patch
+                * existing vc4_get_bcl() logic to support the BIN_CL
+                * chunk.
+                */
+               exec->args->bin_cl = chunk->bin.ptr;
+               exec->args->bin_cl_size = chunk->bin.size;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 /**
  * vc4_submit_cl_ioctl() - Submits a job (frame) to the VC4.
  * @dev: DRM device
@@ -1073,11 +1095,18 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
        if ((args->flags & ~(VC4_SUBMIT_CL_USE_CLEAR_COLOR |
                             VC4_SUBMIT_CL_FIXED_RCL_ORDER |
                             VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X |
-                            VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y)) != 0) {
+                            VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y |
+                            VC4_SUBMIT_CL_EXTENDED)) != 0) {
                DRM_DEBUG("Unknown flags: 0x%02x\n", args->flags);
                return -EINVAL;
        }
 
+       if ((args->flags & VC4_SUBMIT_CL_EXTENDED) &&
+           !args->num_cl_chunks) {
+               DRM_DEBUG("CL_EXTENDED flag set but no chunks provided\n");
+               return -EINVAL;
+       }
+
        exec = kcalloc(1, sizeof(*exec), GFP_KERNEL);
        if (!exec) {
                DRM_ERROR("malloc failure on exec struct\n");
@@ -1103,6 +1132,35 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
        if (ret)
                goto fail;
 
+       if (args->flags & VC4_SUBMIT_CL_EXTENDED) {
+               uint32_t i;
+
+               ret = -ENOMEM;
+               exec->nchunks = args->num_cl_chunks;
+               exec->chunks = kcalloc(exec->nchunks, sizeof(*exec->chunks),
+                                      GFP_KERNEL);
+               if (!exec->chunks)
+                       goto fail;
+
+               if (copy_from_user(exec->chunks,
+                                  u64_to_user_ptr(args->cl_chunks),
+                                  exec->nchunks *
+                                  sizeof(*exec->chunks)))
+                       goto fail;
+
+               /* Reset ->bin_cl fields so that if no BIN_CL chunk is
+                * passed, vc4_get_bcl() is skipped.
+                */
+               exec->args->bin_cl = 0;
+               exec->args->bin_cl_size = 0;
+               for (i = 0; i < exec->nchunks; i++) {
+                       ret = vc4_parse_cl_chunk(vc4, exec,
+                                                &exec->chunks[i]);
+                       if (ret)
+                               goto fail;
+               }
+       }
+
        if (exec->args->bin_cl_size != 0) {
                ret = vc4_get_bcl(dev, exec);
                if (ret)
diff --git a/include/uapi/drm/vc4_drm.h b/include/uapi/drm/vc4_drm.h
index 52263b575bdc..ddcaa72da82a 100644
--- a/include/uapi/drm/vc4_drm.h
+++ b/include/uapi/drm/vc4_drm.h
@@ -70,6 +70,50 @@ struct drm_vc4_submit_rcl_surface {
 };
 
 /**
+ * @VC4_BIN_CL_CHUNK: binner CL chunk
+ */
+enum {
+       VC4_BIN_CL_CHUNK,
+};
+
+/**
+ * struct drm_vc4_submit_cl_chunk - dummy chunk
+ * @type: extension type
+ * @pad: unused, should be set to zero
+ *
+ * Meant to be used for chunks that do not require extra parameters.
+ */
+struct drm_vc4_submit_cl_dummy_chunk {
+       __u32 type;
+       __u32 pad[3];
+};
+
+/**
+ * struct drm_vc4_submit_cl_bin_chunk - binner CL chunk
+ *
+ * @type: extention type, should be set to %VC4_BIN_CL_CHUNK
+ * @size: size in bytes of the binner CL
+ * @ptr: userspace pointer to the binner CL
+ */
+struct drm_vc4_submit_cl_bin_chunk {
+       __u32 type;
+       __u32 size;
+       __u64 ptr;
+};
+
+/**
+ * union drm_vc4_submit_cl_chunk - CL chunk
+ *
+ * CL chunks allow us to easily extend the set of arguments one can pass
+ * to the submit CL ioctl without having to add new ioctls/struct everytime
+ * we run out of free fields in the drm_vc4_submit_cl struct.
+ */
+union drm_vc4_submit_cl_chunk {
+       struct drm_vc4_submit_cl_dummy_chunk dummy;
+       struct drm_vc4_submit_cl_bin_chunk bin;
+};
+
+/**
  * struct drm_vc4_submit_cl - ioctl argument for submitting commands to the 3D
  * engine.
  *
@@ -83,14 +127,23 @@ struct drm_vc4_submit_rcl_surface {
  * BO.
  */
 struct drm_vc4_submit_cl {
-       /* Pointer to the binner command list.
-        *
-        * This is the first set of commands executed, which runs the
-        * coordinate shader to determine where primitives land on the screen,
-        * then writes out the state updates and draw calls necessary per tile
-        * to the tile allocation BO.
-        */
-       __u64 bin_cl;
+       union {
+               /* Pointer to the binner command list.
+                *
+                * This is the first set of commands executed, which runs the
+                * coordinate shader to determine where primitives land on
+                * the screen, then writes out the state updates and draw calls
+                * necessary per tile to the tile allocation BO.
+                */
+               __u64 bin_cl;
+
+               /* Pointer to an array of CL chunks.
+                *
+                * This is now the preferred way of passing optional attributes
+                * when submitting a job.
+                */
+               __u64 cl_chunks;
+       };
 
        /* Pointer to the shader records.
         *
@@ -120,8 +173,14 @@ struct drm_vc4_submit_cl {
        __u64 uniforms;
        __u64 bo_handles;
 
-       /* Size in bytes of the binner command list. */
-       __u32 bin_cl_size;
+       union {
+               /* Size in bytes of the binner command list. */
+               __u32 bin_cl_size;
+
+               /* Number of entries in the CL extension array. */
+               __u32 num_cl_chunks;
+       };
+
        /* Size in bytes of the set of shader records. */
        __u32 shader_rec_size;
        /* Number of shader records.
@@ -167,6 +226,7 @@ struct drm_vc4_submit_cl {
 #define VC4_SUBMIT_CL_FIXED_RCL_ORDER                  (1 << 1)
 #define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_X           (1 << 2)
 #define VC4_SUBMIT_CL_RCL_ORDER_INCREASING_Y           (1 << 3)
+#define VC4_SUBMIT_CL_EXTENDED                         (1 << 4)
        __u32 flags;
 
        /* Returned value of the seqno of this render job (for the
@@ -308,6 +368,7 @@ struct drm_vc4_get_hang_state {
 #define DRM_VC4_PARAM_SUPPORTS_THREADED_FS     5
 #define DRM_VC4_PARAM_SUPPORTS_FIXED_RCL_ORDER 6
 #define DRM_VC4_PARAM_SUPPORTS_MADVISE         7
+#define DRM_VC4_PARAM_SUPPORTS_EXTENDED_CL     8
 
 struct drm_vc4_get_param {
        __u32 param;
-- 
2.11.0

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to