aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch')
-rw-r--r--target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch675
1 files changed, 675 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch b/target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch
new file mode 100644
index 0000000000..53a936e993
--- /dev/null
+++ b/target/linux/bcm27xx/patches-4.19/950-0550-staging-vc-sm-cma-Add-in-userspace-allocation-API.patch
@@ -0,0 +1,675 @@
+From 549c0266e570da686f19e4435d76411cd7137954 Mon Sep 17 00:00:00 2001
+From: Dave Stevenson <dave.stevenson@raspberrypi.org>
+Date: Mon, 11 Mar 2019 16:35:23 +0000
+Subject: [PATCH] staging: vc-sm-cma: Add in userspace allocation API
+
+Replacing the functionality from the older vc-sm driver,
+add in a userspace API that allows allocation of buffers,
+and importing of dma-bufs.
+The driver hands out dma-buf fds, therefore much of the
+handling around lifespan and odd mmaps from the old driver
+goes away.
+
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
+---
+ .../staging/vc04_services/vc-sm-cma/vc_sm.c | 371 ++++++++++++++++--
+ .../vc04_services/vc-sm-cma/vc_sm_cma.c | 3 +-
+ .../vc04_services/vc-sm-cma/vc_sm_cma.h | 2 +-
+ include/linux/broadcom/vc_sm_cma_ioctl.h | 87 ++++
+ 4 files changed, 435 insertions(+), 28 deletions(-)
+ create mode 100644 include/linux/broadcom/vc_sm_cma_ioctl.h
+
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+@@ -36,6 +36,7 @@
+ #include <linux/fs.h>
+ #include <linux/kernel.h>
+ #include <linux/list.h>
++#include <linux/miscdevice.h>
+ #include <linux/module.h>
+ #include <linux/mm.h>
+ #include <linux/of_device.h>
+@@ -52,6 +53,7 @@
+ #include "vc_sm.h"
+ #include "vc_sm_cma.h"
+ #include "vc_sm_knl.h"
++#include <linux/broadcom/vc_sm_cma_ioctl.h>
+
+ /* ---- Private Constants and Types --------------------------------------- */
+
+@@ -83,6 +85,8 @@ struct sm_pde_t {
+ struct sm_state_t {
+ struct platform_device *pdev;
+
++ struct miscdevice misc_dev;
++
+ struct sm_instance *sm_handle; /* Handle for videocore service. */
+ struct cma *cma_heap;
+
+@@ -346,7 +350,6 @@ static void vc_sm_release_resource(struc
+
+ defer:
+ mutex_unlock(&buffer->lock);
+- return;
+ }
+
+ /* Create support for private data tracking. */
+@@ -381,7 +384,7 @@ static struct sg_table *dup_sg_table(str
+ ret = sg_alloc_table(new_table, table->nents, GFP_KERNEL);
+ if (ret) {
+ kfree(new_table);
+- return ERR_PTR(-ENOMEM);
++ return ERR_PTR(ret);
+ }
+
+ new_sg = new_table->sgl;
+@@ -417,7 +420,7 @@ static int vc_sm_dma_buf_attach(struct d
+ table = dup_sg_table(buf->sg_table);
+ if (IS_ERR(table)) {
+ kfree(a);
+- return -ENOMEM;
++ return PTR_ERR(table);
+ }
+
+ a->table = table;
+@@ -433,8 +436,8 @@ static int vc_sm_dma_buf_attach(struct d
+ return 0;
+ }
+
+-static void vc_sm_dma_buf_detatch(struct dma_buf *dmabuf,
+- struct dma_buf_attachment *attachment)
++static void vc_sm_dma_buf_detach(struct dma_buf *dmabuf,
++ struct dma_buf_attachment *attachment)
+ {
+ struct vc_sm_dma_buf_attachment *a = attachment->priv;
+ struct vc_sm_buffer *buf = dmabuf->priv;
+@@ -544,6 +547,9 @@ static void vc_sm_dma_buf_release(struct
+ vc_sm_clean_up_dmabuf(buffer);
+ pr_debug("%s clean_up dmabuf done\n", __func__);
+
++ /* buffer->lock will be destroyed by vc_sm_release_resource if finished
++ * with, otherwise unlocked. Do NOT unlock here.
++ */
+ vc_sm_release_resource(buffer);
+ pr_debug("%s done\n", __func__);
+ }
+@@ -613,7 +619,7 @@ static const struct dma_buf_ops dma_buf_
+ .mmap = vc_sm_dmabuf_mmap,
+ .release = vc_sm_dma_buf_release,
+ .attach = vc_sm_dma_buf_attach,
+- .detach = vc_sm_dma_buf_detatch,
++ .detach = vc_sm_dma_buf_detach,
+ .begin_cpu_access = vc_sm_dma_buf_begin_cpu_access,
+ .end_cpu_access = vc_sm_dma_buf_end_cpu_access,
+ .map = vc_sm_dma_buf_kmap,
+@@ -762,6 +768,7 @@ static const struct dma_buf_ops dma_buf_
+ int
+ vc_sm_cma_import_dmabuf_internal(struct vc_sm_privdata_t *private,
+ struct dma_buf *dma_buf,
++ int fd,
+ struct dma_buf **imported_buf)
+ {
+ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+@@ -775,10 +782,15 @@ vc_sm_cma_import_dmabuf_internal(struct
+ int status;
+
+ /* Setup our allocation parameters */
+- pr_debug("%s: importing dma_buf %p\n", __func__, dma_buf);
++ pr_debug("%s: importing dma_buf %p/fd %d\n", __func__, dma_buf, fd);
+
+- get_dma_buf(dma_buf);
+- dma_buf = dma_buf;
++ if (fd < 0)
++ get_dma_buf(dma_buf);
++ else
++ dma_buf = dma_buf_get(fd);
++
++ if (!dma_buf)
++ return -EINVAL;
+
+ attach = dma_buf_attach(dma_buf, &sm_state->pdev->dev);
+ if (IS_ERR(attach)) {
+@@ -921,6 +933,10 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+ return -ENOMEM;
+
+ mutex_init(&buffer->lock);
++ /* Acquire the mutex as vc_sm_release_resource will release it in the
++ * error path.
++ */
++ mutex_lock(&buffer->lock);
+
+ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
+ aligned_size)) {
+@@ -976,6 +992,8 @@ static int vc_sm_cma_vpu_alloc(u32 size,
+
+ vc_sm_add_resource(sm_state->vpu_allocs, buffer);
+
++ mutex_unlock(&buffer->lock);
++
+ *ret_buffer = buffer;
+ return 0;
+ error:
+@@ -1065,6 +1083,297 @@ vc_sm_vpu_event(struct sm_instance *inst
+ }
+ }
+
++/* Userspace handling */
++/*
++ * Open the device. Creates a private state to help track all allocation
++ * associated with this device.
++ */
++static int vc_sm_cma_open(struct inode *inode, struct file *file)
++{
++ /* Make sure the device was started properly. */
++ if (!sm_state) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return -EPERM;
++ }
++
++ file->private_data = vc_sm_cma_create_priv_data(current->tgid);
++ if (!file->private_data) {
++ pr_err("[%s]: failed to create data tracker\n", __func__);
++
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++/*
++ * Close the vcsm-cma device.
++ * All allocations are file descriptors to the dmabuf objects, so we will get
++ * the clean up request on those as those are cleaned up.
++ */
++static int vc_sm_cma_release(struct inode *inode, struct file *file)
++{
++ struct vc_sm_privdata_t *file_data =
++ (struct vc_sm_privdata_t *)file->private_data;
++ int ret = 0;
++
++ /* Make sure the device was started properly. */
++ if (!sm_state || !file_data) {
++ pr_err("[%s]: invalid device\n", __func__);
++ ret = -EPERM;
++ goto out;
++ }
++
++ pr_debug("[%s]: using private data %p\n", __func__, file_data);
++
++ /* Terminate the private data. */
++ kfree(file_data);
++
++out:
++ return ret;
++}
++
++/*
++ * Allocate a shared memory handle and block.
++ * Allocation is from CMA, and then imported into the VPU mappings.
++ */
++int vc_sm_cma_ioctl_alloc(struct vc_sm_privdata_t *private,
++ struct vc_sm_cma_ioctl_alloc *ioparam)
++{
++ DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
++ struct vc_sm_buffer *buffer = NULL;
++ struct vc_sm_import import = { 0 };
++ struct vc_sm_import_result result = { 0 };
++ struct dma_buf *dmabuf = NULL;
++ int aligned_size;
++ int ret = 0;
++ int status;
++ int fd = -1;
++
++ aligned_size = PAGE_ALIGN(ioparam->size);
++
++ if (!aligned_size)
++ return -EINVAL;
++
++ /* Allocate local buffer to track this allocation. */
++ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
++ if (!buffer) {
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ if (vc_sm_cma_buffer_allocate(sm_state->cma_heap, &buffer->alloc,
++ aligned_size)) {
++ pr_err("[%s]: cma alloc of %d bytes failed\n",
++ __func__, aligned_size);
++ kfree(buffer);
++ return -ENOMEM;
++ }
++ buffer->sg_table = buffer->alloc.sg_table;
++
++ if (dma_map_sg(&sm_state->pdev->dev, buffer->sg_table->sgl,
++ buffer->sg_table->nents, DMA_BIDIRECTIONAL) <= 0) {
++ pr_err("[%s]: dma_map_sg failed\n", __func__);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ import.type = VC_SM_ALLOC_NON_CACHED;
++ import.allocator = current->tgid;
++
++ if (*ioparam->name)
++ memcpy(import.name, ioparam->name, sizeof(import.name) - 1);
++ else
++ memcpy(import.name, VC_SM_RESOURCE_NAME_DEFAULT,
++ sizeof(VC_SM_RESOURCE_NAME_DEFAULT));
++
++ mutex_init(&buffer->lock);
++ INIT_LIST_HEAD(&buffer->attachments);
++ memcpy(buffer->name, import.name,
++ min(sizeof(buffer->name), sizeof(import.name) - 1));
++
++ exp_info.ops = &dma_buf_ops;
++ exp_info.size = aligned_size;
++ exp_info.flags = O_RDWR;
++ exp_info.priv = buffer;
++
++ dmabuf = dma_buf_export(&exp_info);
++ if (IS_ERR(dmabuf)) {
++ ret = PTR_ERR(dmabuf);
++ goto error;
++ }
++ buffer->dma_buf = dmabuf;
++
++ import.addr = (uint32_t)sg_dma_address(buffer->sg_table->sgl);
++ import.size = aligned_size;
++ import.kernel_id = (uint32_t)buffer;
++
++ /* Wrap it into a videocore buffer. */
++ status = vc_sm_cma_vchi_import(sm_state->sm_handle, &import, &result,
++ &sm_state->int_trans_id);
++ if (status == -EINTR) {
++ pr_debug("[%s]: requesting import memory action restart (trans_id: %u)\n",
++ __func__, sm_state->int_trans_id);
++ ret = -ERESTARTSYS;
++ private->restart_sys = -EINTR;
++ private->int_action = VC_SM_MSG_TYPE_IMPORT;
++ goto error;
++ } else if (status || !result.res_handle) {
++ pr_err("[%s]: failed to import memory on videocore (status: %u, trans_id: %u)\n",
++ __func__, status, sm_state->int_trans_id);
++ ret = -ENOMEM;
++ goto error;
++ }
++
++ /* Keep track of the buffer we created. */
++ buffer->private = private;
++ buffer->vc_handle = result.res_handle;
++ buffer->size = import.size;
++ buffer->dma_addr = import.addr;
++ buffer->vpu_state = VPU_MAPPED;
++ //buffer->res_cached = ioparam->cached;
++
++ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
++ if (fd < 0)
++ goto error;
++
++ vc_sm_add_resource(private, buffer);
++
++ pr_debug("[%s]: Added resource as fd %d, buffer %p, private %p, dma_addr %pad\n",
++ __func__, fd, buffer, private, &buffer->dma_addr);
++
++ /* We're done */
++ ioparam->handle = fd;
++ ioparam->vc_handle = buffer->vc_handle;
++ ioparam->dma_addr = buffer->dma_addr;
++ return 0;
++
++error:
++ if (buffer) {
++ pr_err("[%s]: something failed - cleanup. ret %d\n", __func__,
++ ret);
++
++ dma_buf_put(dmabuf);
++ }
++ return ret;
++}
++
++static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ int ret = 0;
++ unsigned int cmdnr = _IOC_NR(cmd);
++ struct vc_sm_privdata_t *file_data =
++ (struct vc_sm_privdata_t *)file->private_data;
++
++ /* Validate we can work with this device. */
++ if (!sm_state || !file_data) {
++ pr_err("[%s]: invalid device\n", __func__);
++ return -EPERM;
++ }
++
++ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
++ current->tgid, file_data->pid);
++
++ /* Action is a re-post of a previously interrupted action? */
++ if (file_data->restart_sys == -EINTR) {
++ struct vc_sm_action_clean_t action_clean;
++
++ pr_debug("[%s]: clean up of action %u (trans_id: %u) following EINTR\n",
++ __func__, file_data->int_action,
++ file_data->int_trans_id);
++
++ action_clean.res_action = file_data->int_action;
++ action_clean.action_trans_id = file_data->int_trans_id;
++
++ file_data->restart_sys = 0;
++ }
++
++ /* Now process the command. */
++ switch (cmdnr) {
++ /* New memory allocation.
++ */
++ case VC_SM_CMA_CMD_ALLOC:
++ {
++ struct vc_sm_cma_ioctl_alloc ioparam;
++
++ /* Get the parameter data. */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ break;
++ }
++
++ ret = vc_sm_cma_ioctl_alloc(file_data, &ioparam);
++ if (!ret &&
++ (copy_to_user((void *)arg, &ioparam,
++ sizeof(ioparam)) != 0)) {
++ /* FIXME: Release allocation */
++ pr_err("[%s]: failed to copy-to-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ }
++ break;
++ }
++
++ case VC_SM_CMA_CMD_IMPORT_DMABUF:
++ {
++ struct vc_sm_cma_ioctl_import_dmabuf ioparam;
++ struct dma_buf *new_dmabuf;
++
++ /* Get the parameter data. */
++ if (copy_from_user
++ (&ioparam, (void *)arg, sizeof(ioparam)) != 0) {
++ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
++ __func__, cmdnr);
++ ret = -EFAULT;
++ break;
++ }
++
++ ret = vc_sm_cma_import_dmabuf_internal(file_data,
++ NULL,
++ ioparam.dmabuf_fd,
++ &new_dmabuf);
++
++ if (!ret) {
++ struct vc_sm_buffer *buf = new_dmabuf->priv;
++
++ ioparam.size = buf->size;
++ ioparam.handle = dma_buf_fd(new_dmabuf,
++ O_CLOEXEC);
++ ioparam.vc_handle = buf->vc_handle;
++ ioparam.dma_addr = buf->dma_addr;
++
++ if (ioparam.handle < 0 ||
++ (copy_to_user((void *)arg, &ioparam,
++ sizeof(ioparam)) != 0)) {
++ dma_buf_put(new_dmabuf);
++ /* FIXME: Release allocation */
++ ret = -EFAULT;
++ }
++ }
++ break;
++ }
++
++ default:
++ ret = -EINVAL;
++ break;
++ }
++
++ return ret;
++}
++
++/* Device operations that we managed in this driver. */
++static const struct file_operations vc_sm_ops = {
++ .owner = THIS_MODULE,
++ .unlocked_ioctl = vc_sm_cma_ioctl,
++ .open = vc_sm_cma_open,
++ .release = vc_sm_cma_release,
++};
++
++/* Driver load/unload functions */
+ /* Videocore connected. */
+ static void vc_sm_connected_init(void)
+ {
+@@ -1075,12 +1384,11 @@ static void vc_sm_connected_init(void)
+
+ pr_info("[%s]: start\n", __func__);
+
+- if (vc_sm_cma_add_heaps(&sm_state->cma_heap) ||
+- !sm_state->cma_heap) {
+- pr_err("[%s]: failed to initialise CMA heaps\n",
++ vc_sm_cma_add_heaps(&sm_state->cma_heap);
++ if (!sm_state->cma_heap) {
++ pr_err("[%s]: failed to initialise CMA heap\n",
+ __func__);
+- ret = -EIO;
+- goto err_free_mem;
++ return;
+ }
+
+ /*
+@@ -1092,8 +1400,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to initialise VCHI instance (ret=%d)\n",
+ __func__, ret);
+
+- ret = -EIO;
+- goto err_failed;
++ return;
+ }
+
+ ret = vchi_connect(NULL, 0, vchi_instance);
+@@ -1101,8 +1408,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to connect VCHI instance (ret=%d)\n",
+ __func__, ret);
+
+- ret = -EIO;
+- goto err_failed;
++ return;
+ }
+
+ /* Initialize an instance of the shared memory service. */
+@@ -1112,8 +1418,7 @@ static void vc_sm_connected_init(void)
+ pr_err("[%s]: failed to initialize shared memory service\n",
+ __func__);
+
+- ret = -EPERM;
+- goto err_failed;
++ return;
+ }
+
+ /* Create a debug fs directory entry (root). */
+@@ -1127,11 +1432,22 @@ static void vc_sm_connected_init(void)
+
+ INIT_LIST_HEAD(&sm_state->buffer_list);
+
++ /* Create a shared memory device. */
++ sm_state->misc_dev.minor = MISC_DYNAMIC_MINOR;
++ sm_state->misc_dev.name = DEVICE_NAME;
++ sm_state->misc_dev.fops = &vc_sm_ops;
++ sm_state->misc_dev.parent = NULL;
++ ret = misc_register(&sm_state->misc_dev);
++ if (ret) {
++ pr_err("vcsm-cma: failed to register misc device.\n");
++ goto err_remove_debugfs;
++ }
++
+ sm_state->data_knl = vc_sm_cma_create_priv_data(0);
+ if (!sm_state->data_knl) {
+ pr_err("[%s]: failed to create kernel private data tracker\n",
+ __func__);
+- goto err_remove_shared_memory;
++ goto err_remove_misc_dev;
+ }
+
+ version.version = 2;
+@@ -1148,11 +1464,13 @@ static void vc_sm_connected_init(void)
+ pr_info("[%s]: installed successfully\n", __func__);
+ return;
+
+-err_remove_shared_memory:
++err_remove_misc_dev:
++ misc_deregister(&sm_state->misc_dev);
++err_remove_debugfs:
+ debugfs_remove_recursive(sm_state->dir_root);
+ vc_sm_cma_vchi_stop(&sm_state->sm_handle);
+-err_failed:
+- pr_info("[%s]: failed, ret %d\n", __func__, ret);
++
++ return;
+ }
+
+ /* Driver loading. */
+@@ -1184,6 +1502,8 @@ static int bcm2835_vc_sm_cma_remove(stru
+ {
+ pr_debug("[%s]: start\n", __func__);
+ if (sm_inited) {
++ misc_deregister(&sm_state->misc_dev);
++
+ /* Remove all proc entries. */
+ debugfs_remove_recursive(sm_state->dir_root);
+
+@@ -1202,6 +1522,7 @@ static int bcm2835_vc_sm_cma_remove(stru
+ return 0;
+ }
+
++/* Kernel API calls */
+ /* Get an internal resource handle mapped from the external one. */
+ int vc_sm_cma_int_handle(void *handle)
+ {
+@@ -1252,7 +1573,7 @@ int vc_sm_cma_import_dmabuf(struct dma_b
+ }
+
+ ret = vc_sm_cma_import_dmabuf_internal(sm_state->data_knl, src_dmabuf,
+- &new_dma_buf);
++ -1, &new_dma_buf);
+
+ if (!ret) {
+ pr_debug("%s: imported to ptr %p\n", __func__, new_dma_buf);
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.c
+@@ -92,8 +92,7 @@ int __vc_sm_cma_add_heaps(struct cma *cm
+ return 0;
+ }
+
+-int vc_sm_cma_add_heaps(struct cma **cma_heap)
++void vc_sm_cma_add_heaps(struct cma **cma_heap)
+ {
+ cma_for_each_area(__vc_sm_cma_add_heaps, cma_heap);
+- return 0;
+ }
+--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
++++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm_cma.h
+@@ -34,6 +34,6 @@ int vc_sm_cma_buffer_allocate(struct cma
+ unsigned long len);
+ void vc_sm_cma_buffer_free(struct vc_sm_cma_alloc_data *buffer);
+
+-int vc_sm_cma_add_heaps(struct cma **cma_heap);
++void vc_sm_cma_add_heaps(struct cma **cma_heap);
+
+ #endif
+--- /dev/null
++++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
+@@ -0,0 +1,87 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/*
++ * Copyright 2019 Raspberry Pi (Trading) Ltd. All rights reserved.
++ *
++ * Based on vmcs_sm_ioctl.h Copyright Broadcom Corporation.
++ */
++
++#ifndef __VC_SM_CMA_IOCTL_H
++#define __VC_SM_CMA_IOCTL_H
++
++/* ---- Include Files ---------------------------------------------------- */
++
++#if defined(__KERNEL__)
++#include <linux/types.h> /* Needed for standard types */
++#else
++#include <stdint.h>
++#endif
++
++#include <linux/ioctl.h>
++
++/* ---- Constants and Types ---------------------------------------------- */
++
++#define VC_SM_CMA_RESOURCE_NAME 32
++#define VC_SM_CMA_RESOURCE_NAME_DEFAULT "sm-host-resource"
++
++/* Type define used to create unique IOCTL number */
++#define VC_SM_CMA_MAGIC_TYPE 'J'
++
++/* IOCTL commands on /dev/vc-sm-cma */
++enum vc_sm_cma_cmd_e {
++ VC_SM_CMA_CMD_ALLOC = 0x5A, /* Start at 0x5A arbitrarily */
++
++ VC_SM_CMA_CMD_IMPORT_DMABUF,
++
++ VC_SM_CMA_CMD_LAST /* Do not delete */
++};
++
++/* Cache type supported, conveniently matches the user space definition in
++ * user-vcsm.h.
++ */
++enum vc_sm_cma_cache_e {
++ VC_SM_CMA_CACHE_NONE,
++ VC_SM_CMA_CACHE_HOST,
++ VC_SM_CMA_CACHE_VC,
++ VC_SM_CMA_CACHE_BOTH,
++};
++
++/* IOCTL Data structures */
++struct vc_sm_cma_ioctl_alloc {
++ /* user -> kernel */
++ __u32 size;
++ __u32 num;
++ __u32 cached; /* enum vc_sm_cma_cache_e */
++ __u32 pad;
++ __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++ /* kernel -> user */
++ __s32 handle;
++ __u32 vc_handle;
++ __u64 dma_addr;
++};
++
++struct vc_sm_cma_ioctl_import_dmabuf {
++ /* user -> kernel */
++ __s32 dmabuf_fd;
++ __u32 cached; /* enum vc_sm_cma_cache_e */
++ __u8 name[VC_SM_CMA_RESOURCE_NAME];
++
++ /* kernel -> user */
++ __s32 handle;
++ __u32 vc_handle;
++ __u32 size;
++ __u32 pad;
++ __u64 dma_addr;
++};
++
++/* IOCTL numbers */
++#define VC_SM_CMA_IOCTL_MEM_ALLOC\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
++ struct vc_sm_cma_ioctl_alloc)
++
++#define VC_SM_CMA_IOCTL_MEM_IMPORT_DMABUF\
++ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
++ struct vc_sm_cma_ioctl_import_dmabuf)
++
++#endif /* __VC_SM_CMA_IOCTL_H */