staging: mmal-vchiq: Use vc-sm-cma to support zero copy
authorDave Stevenson <dave.stevenson@raspberrypi.org>
Tue, 25 Sep 2018 15:07:55 +0000 (16:07 +0100)
committerDom Cobley <popcornmix@gmail.com>
Mon, 21 Mar 2022 16:04:07 +0000 (16:04 +0000)
With the vc-sm-cma driver we can support zero copy of buffers between
the kernel and VPU. Add this support to mmal-vchiq.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
drivers/staging/vc04_services/vchiq-mmal/Kconfig
drivers/staging/vc04_services/vchiq-mmal/mmal-common.h
drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.h

index c99525a..a7c1a7b 100644 (file)
@@ -1,6 +1,7 @@
 config BCM2835_VCHIQ_MMAL
        tristate "BCM2835 MMAL VCHIQ service"
        depends on BCM2835_VCHIQ
+       select BCM_VC_SM_CMA
        help
          Enables the MMAL API over VCHIQ interface as used for the
          majority of the multimedia services on VideoCore.
index 58763d6..72e5a03 100644 (file)
@@ -50,6 +50,10 @@ struct mmal_buffer {
 
        struct mmal_msg_context *msg_context;
 
+       struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
+       void *vcsm_handle;      /* VCSM handle having imported the dmabuf */
+       u32 vc_handle;          /* VC handle to that dmabuf */
+
        u32 cmd;                /* MMAL command. 0=data. */
        unsigned long length;
        u32 mmal_flags;
index 38303b0..c88393f 100644 (file)
 #include <media/videobuf2-vmalloc.h>
 
 #include "mmal-common.h"
+#include "mmal-parameters.h"
 #include "mmal-vchiq.h"
 #include "mmal-msg.h"
 
+#include "vc-sm-cma/vc_sm_knl.h"
 /*
  * maximum number of components supported.
  * This matches the maximum permitted by default on the VPU
@@ -419,8 +421,13 @@ buffer_from_host(struct vchiq_mmal_instance *instance,
 
        /* buffer header */
        m.u.buffer_from_host.buffer_header.cmd = 0;
-       m.u.buffer_from_host.buffer_header.data =
-               (u32)(unsigned long)buf->buffer;
+       if (port->zero_copy) {
+               m.u.buffer_from_host.buffer_header.data = buf->vc_handle;
+       } else {
+               m.u.buffer_from_host.buffer_header.data =
+                       (u32)(unsigned long)buf->buffer;
+       }
+
        m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
        if (port->type == MMAL_PORT_TYPE_OUTPUT) {
                m.u.buffer_from_host.buffer_header.length = 0;
@@ -586,6 +593,22 @@ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
 
                msg_context->u.bulk.status = msg->h.status;
 
+       } else if (msg->u.buffer_from_host.is_zero_copy) {
+               /*
+                * Zero copy buffer, so nothing to do.
+                * Copy buffer info and make callback.
+                */
+               msg_context->u.bulk.buffer_used =
+                               msg->u.buffer_from_host.buffer_header.length;
+               msg_context->u.bulk.mmal_flags =
+                               msg->u.buffer_from_host.buffer_header.flags;
+               msg_context->u.bulk.dts =
+                               msg->u.buffer_from_host.buffer_header.dts;
+               msg_context->u.bulk.pts =
+                               msg->u.buffer_from_host.buffer_header.pts;
+               msg_context->u.bulk.cmd =
+                               msg->u.buffer_from_host.buffer_header.cmd;
+
        } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
                /* empty buffer */
                if (msg->u.buffer_from_host.buffer_header.flags &
@@ -1530,6 +1553,9 @@ int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
 
        mutex_unlock(&instance->vchiq_mutex);
 
+       if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
+               port->zero_copy = !!(*(bool *)value);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
@@ -1698,6 +1724,31 @@ int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
        unsigned long flags = 0;
        int ret;
 
+       /*
+        * We really want to do this in mmal_vchi_buffer_init but can't as
+        * videobuf2 won't let us have the dmabuf there.
+        */
+       if (port->zero_copy && buffer->dma_buf && !buffer->vcsm_handle) {
+               pr_debug("%s: import dmabuf %p\n", __func__, buffer->dma_buf);
+               ret = vc_sm_cma_import_dmabuf(buffer->dma_buf,
+                                             &buffer->vcsm_handle);
+               if (ret) {
+                       pr_err("%s: vc_sm_import_dmabuf_fd failed, ret %d\n",
+                              __func__, ret);
+                       return ret;
+               }
+
+               buffer->vc_handle = vc_sm_cma_int_handle(buffer->vcsm_handle);
+               if (!buffer->vc_handle) {
+                       pr_err("%s: vc_sm_int_handle failed %d\n",
+                              __func__, ret);
+                       vc_sm_cma_free(buffer->vcsm_handle);
+                       return ret;
+               }
+               pr_debug("%s: import dmabuf %p - got vc handle %08X\n",
+                        __func__, buffer->dma_buf, buffer->vc_handle);
+       }
+
        ret = buffer_from_host(instance, port, buffer);
        if (ret == -EINVAL) {
                /* Port is disabled. Queue for when it is enabled. */
@@ -1731,6 +1782,16 @@ int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
                release_msg_context(msg_context);
        buf->msg_context = NULL;
 
+       if (buf->vcsm_handle) {
+               int ret;
+
+               pr_debug("%s: vc_sm_cma_free on handle %p\n", __func__,
+                        buf->vcsm_handle);
+               ret = vc_sm_cma_free(buf->vcsm_handle);
+               if (ret)
+                       pr_err("%s: vcsm_free failed, ret %d\n", __func__, ret);
+               buf->vcsm_handle = 0;
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);
index e87f88f..247521f 100644 (file)
@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
 
 struct vchiq_mmal_port {
        u32 enabled:1;
+       u32 zero_copy:1;
        u32 handle;
        u32 type; /* port type, cached to use on port info set */
        u32 index; /* port index, cached to use on port info set */