brcm2708: organize kernel patches
[openwrt/staging/chunkeey.git] / target / linux / brcm2708 / patches-4.19 / 950-0579-staging-vcsm-cma-Add-cache-control-ioctls.patch
diff --git a/target/linux/brcm2708/patches-4.19/950-0579-staging-vcsm-cma-Add-cache-control-ioctls.patch b/target/linux/brcm2708/patches-4.19/950-0579-staging-vcsm-cma-Add-cache-control-ioctls.patch
new file mode 100644 (file)
index 0000000..500ec5f
--- /dev/null
@@ -0,0 +1,245 @@
+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] 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 */