staging: vc04_services: Use vc-sm-cma to support zero copy

With the vc-sm-cma driver we can support zero copy of buffers between
the kernel and VPU. Add this support to vchiq-mmal.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
This commit is contained in:
Dave Stevenson
2018-09-25 16:07:55 +01:00
committed by popcornmix
parent e8078c692e
commit f631650f84
4 changed files with 70 additions and 2 deletions

View File

@@ -2,6 +2,7 @@ config BCM2835_VCHIQ_MMAL
tristate "BCM2835 MMAL VCHIQ service" tristate "BCM2835 MMAL VCHIQ service"
depends on (ARCH_BCM2835 || COMPILE_TEST) depends on (ARCH_BCM2835 || COMPILE_TEST)
select BCM2835_VCHIQ select BCM2835_VCHIQ
select BCM_VC_SM_CMA
help help
Enables the MMAL API over VCHIQ as used for the Enables the MMAL API over VCHIQ as used for the
majority of the multimedia services on VideoCore. majority of the multimedia services on VideoCore.

View File

@@ -51,6 +51,10 @@ struct mmal_buffer {
struct mmal_msg_context *msg_context; struct mmal_msg_context *msg_context;
struct dma_buf *dma_buf;/* Exported dmabuf fd from videobuf2 */
int vcsm_handle; /* VCSM handle having imported the dmabuf */
u32 vc_handle; /* VC handle to that dmabuf */
u32 cmd; /* MMAL command. 0=data. */ u32 cmd; /* MMAL command. 0=data. */
unsigned long length; unsigned long length;
u32 mmal_flags; u32 mmal_flags;

View File

@@ -26,9 +26,12 @@
#include <media/videobuf2-vmalloc.h> #include <media/videobuf2-vmalloc.h>
#include "mmal-common.h" #include "mmal-common.h"
#include "mmal-parameters.h"
#include "mmal-vchiq.h" #include "mmal-vchiq.h"
#include "mmal-msg.h" #include "mmal-msg.h"
#include "vc-sm-cma/vc_sm_knl.h"
#define USE_VCHIQ_ARM #define USE_VCHIQ_ARM
#include "interface/vchi/vchi.h" #include "interface/vchi/vchi.h"
@@ -424,8 +427,13 @@ buffer_from_host(struct vchiq_mmal_instance *instance,
/* buffer header */ /* buffer header */
m.u.buffer_from_host.buffer_header.cmd = 0; m.u.buffer_from_host.buffer_header.cmd = 0;
m.u.buffer_from_host.buffer_header.data = if (port->zero_copy) {
(u32)(unsigned long)buf->buffer; 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; m.u.buffer_from_host.buffer_header.alloc_size = buf->buffer_size;
if (port->type == MMAL_PORT_TYPE_OUTPUT) { if (port->type == MMAL_PORT_TYPE_OUTPUT) {
m.u.buffer_from_host.buffer_header.length = 0; m.u.buffer_from_host.buffer_header.length = 0;
@@ -590,6 +598,22 @@ static void buffer_to_host_cb(struct vchiq_mmal_instance *instance,
msg_context->u.bulk.status = msg->h.status; 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) { } else if (msg->u.buffer_from_host.buffer_header.length == 0) {
/* empty buffer */ /* empty buffer */
if (msg->u.buffer_from_host.buffer_header.flags & if (msg->u.buffer_from_host.buffer_header.flags &
@@ -1537,6 +1561,9 @@ int vchiq_mmal_port_parameter_set(struct vchiq_mmal_instance *instance,
mutex_unlock(&instance->vchiq_mutex); mutex_unlock(&instance->vchiq_mutex);
if (parameter == MMAL_PARAMETER_ZERO_COPY && !ret)
port->zero_copy = !!(*(bool *)value);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set); EXPORT_SYMBOL_GPL(vchiq_mmal_port_parameter_set);
@@ -1705,6 +1732,31 @@ int vchiq_mmal_submit_buffer(struct vchiq_mmal_instance *instance,
unsigned long flags = 0; unsigned long flags = 0;
int ret; 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); ret = buffer_from_host(instance, port, buffer);
if (ret == -EINVAL) { if (ret == -EINVAL) {
/* Port is disabled. Queue for when it is enabled. */ /* Port is disabled. Queue for when it is enabled. */
@@ -1738,6 +1790,16 @@ int mmal_vchi_buffer_cleanup(struct mmal_buffer *buf)
release_msg_context(msg_context); release_msg_context(msg_context);
buf->msg_context = NULL; buf->msg_context = NULL;
if (buf->vcsm_handle) {
int ret;
pr_debug("%s: vc_sm_cma_free on handle %08X\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; return 0;
} }
EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup); EXPORT_SYMBOL_GPL(mmal_vchi_buffer_cleanup);

View File

@@ -49,6 +49,7 @@ typedef void (*vchiq_mmal_buffer_cb)(
struct vchiq_mmal_port { struct vchiq_mmal_port {
u32 enabled:1; u32 enabled:1;
u32 zero_copy:1;
u32 handle; u32 handle;
u32 type; /* port type, cached to use on port info set */ u32 type; /* port type, cached to use on port info set */
u32 index; /* port index, cached to use on port info set */ u32 index; /* port index, cached to use on port info set */