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 */
