You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openwrt/target/linux/brcm2708/patches-4.19/950-0626-staging-vcsm-cma-A...

246 lines
6.4 KiB
Diff

From b17f6dc1d79ae057294ac2d8d824aa2258ab09a8 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.org>
Date: Wed, 20 Mar 2019 10:40:00 +0000
Subject: [PATCH 626/806] staging: vcsm-cma: Add cache control ioctls
The old driver allowed for direct cache manipulation and that
was used by various clients. Replicate here.
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
---
.../staging/vc04_services/vc-sm-cma/vc_sm.c | 141 +++++++++++++++++-
include/linux/broadcom/vc_sm_cma_ioctl.h | 27 ++++
2 files changed, 165 insertions(+), 3 deletions(-)
--- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
+++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
@@ -46,6 +46,7 @@
#include <linux/seq_file.h>
#include <linux/syscalls.h>
#include <linux/types.h>
+#include <asm/cacheflush.h>
#include "vchiq_connected.h"
#include "vc_sm_cma_vchi.h"
@@ -1258,6 +1259,99 @@ error:
return ret;
}
+/* Converts VCSM_CACHE_OP_* to an operating function. */
+static void (*cache_op_to_func(const unsigned int cache_op))
+ (const void*, const void*)
+{
+ switch (cache_op) {
+ case VC_SM_CACHE_OP_NOP:
+ return NULL;
+
+ case VC_SM_CACHE_OP_INV:
+ return dmac_inv_range;
+
+ case VC_SM_CACHE_OP_CLEAN:
+ return dmac_clean_range;
+
+ case VC_SM_CACHE_OP_FLUSH:
+ return dmac_flush_range;
+
+ default:
+ pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
+ return NULL;
+ }
+}
+
+/*
+ * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
+ */
+static int clean_invalid_contig_2d(const void __user *addr,
+ const size_t block_count,
+ const size_t block_size,
+ const size_t stride,
+ const unsigned int cache_op)
+{
+ size_t i;
+ void (*op_fn)(const void *start, const void *end);
+
+ if (!block_size) {
+ pr_err("[%s]: size cannot be 0\n", __func__);
+ return -EINVAL;
+ }
+
+ op_fn = cache_op_to_func(cache_op);
+ if (!op_fn)
+ return -EINVAL;
+
+ for (i = 0; i < block_count; i ++, addr += stride)
+ op_fn(addr, addr + block_size);
+
+ return 0;
+}
+
+static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
+{
+ struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
+ struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
+ int i, ret = 0;
+
+ /* Get parameter data. */
+ if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
+ pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
+ __func__, cmdnr);
+ return -EFAULT;
+ }
+ block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
+ if (!block)
+ return -EFAULT;
+
+ if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
+ ioparam.op_count * sizeof(*block)) != 0) {
+ pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
+ __func__, cmdnr);
+ ret = -EFAULT;
+ goto out;
+ }
+
+ for (i = 0; i < ioparam.op_count; i++) {
+ const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
+
+ if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
+ continue;
+
+ ret = clean_invalid_contig_2d((void __user *)op->start_address,
+ op->block_count, op->block_size,
+ op->inter_block_stride,
+ op->invalidate_mode);
+ if (ret)
+ break;
+ }
+out:
+ kfree(block);
+
+ return ret;
+}
+
static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
@@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
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;
@@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
break;
}
+ /*
+ * Flush/Invalidate the cache for a given mapping.
+ * Blocks must be pinned (i.e. accessed) before this call.
+ */
+ case VC_SM_CMA_CMD_CLEAN_INVALID2:
+ ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
+ break;
+
default:
+ pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
+ current->tgid, file_data->pid);
+
ret = -EINVAL;
break;
}
@@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
return ret;
}
+#ifdef CONFIG_COMPAT
+struct vc_sm_cma_ioctl_clean_invalid2_32 {
+ u32 op_count;
+ struct vc_sm_cma_ioctl_clean_invalid_block {
+ u16 invalidate_mode;
+ u16 block_count;
+ compat_uptr_t start_address;
+ u32 block_size;
+ u32 inter_block_stride;
+ } s[0];
+};
+
+#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
+ struct vc_sm_cma_ioctl_clean_invalid2)
+
+static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ switch (cmd) {
+ case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
+ /* FIXME */
+ break;
+
+ default:
+ return vc_sm_cma_compat_ioctl(file, cmd, arg);
+ }
+}
+#endif
+
/* 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,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = vc_sm_cma_compat_ioctl,
+#endif
.open = vc_sm_cma_open,
.release = vc_sm_cma_release,
};
--- a/include/linux/broadcom/vc_sm_cma_ioctl.h
+++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
@@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
VC_SM_CMA_CMD_IMPORT_DMABUF,
+ VC_SM_CMA_CMD_CLEAN_INVALID2,
+
VC_SM_CMA_CMD_LAST /* Do not delete */
};
@@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
__u64 dma_addr;
};
+/*
+ * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
+ * invalidate_mode.
+ */
+#define VC_SM_CACHE_OP_NOP 0x00
+#define VC_SM_CACHE_OP_INV 0x01
+#define VC_SM_CACHE_OP_CLEAN 0x02
+#define VC_SM_CACHE_OP_FLUSH 0x03
+
+struct vc_sm_cma_ioctl_clean_invalid2 {
+ __u32 op_count;
+ __u32 pad;
+ struct vc_sm_cma_ioctl_clean_invalid_block {
+ __u32 invalidate_mode;
+ __u32 block_count;
+ void * __user start_address;
+ __u32 block_size;
+ __u32 inter_block_stride;
+ } s[0];
+};
+
/* IOCTL numbers */
#define VC_SM_CMA_IOCTL_MEM_ALLOC\
_IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
@@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
_IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
struct vc_sm_cma_ioctl_import_dmabuf)
+#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
+ _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
+ struct vc_sm_cma_ioctl_clean_invalid2)
+
#endif /* __VC_SM_CMA_IOCTL_H */