brcm2708: rename target to bcm27xx
[openwrt/staging/wigyori.git] / target / linux / bcm27xx / patches-4.19 / 950-0551-staging-vcsm-cma-Add-cache-control-ioctls.patch
1 From b17f6dc1d79ae057294ac2d8d824aa2258ab09a8 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.org>
3 Date: Wed, 20 Mar 2019 10:40:00 +0000
4 Subject: [PATCH] staging: vcsm-cma: Add cache control ioctls
5
6 The old driver allowed for direct cache manipulation and that
7 was used by various clients. Replicate here.
8
9 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.org>
10 ---
11 .../staging/vc04_services/vc-sm-cma/vc_sm.c | 141 +++++++++++++++++-
12 include/linux/broadcom/vc_sm_cma_ioctl.h | 27 ++++
13 2 files changed, 165 insertions(+), 3 deletions(-)
14
15 --- a/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
16 +++ b/drivers/staging/vc04_services/vc-sm-cma/vc_sm.c
17 @@ -46,6 +46,7 @@
18 #include <linux/seq_file.h>
19 #include <linux/syscalls.h>
20 #include <linux/types.h>
21 +#include <asm/cacheflush.h>
22
23 #include "vchiq_connected.h"
24 #include "vc_sm_cma_vchi.h"
25 @@ -1258,6 +1259,99 @@ error:
26 return ret;
27 }
28
29 +/* Converts VCSM_CACHE_OP_* to an operating function. */
30 +static void (*cache_op_to_func(const unsigned int cache_op))
31 + (const void*, const void*)
32 +{
33 + switch (cache_op) {
34 + case VC_SM_CACHE_OP_NOP:
35 + return NULL;
36 +
37 + case VC_SM_CACHE_OP_INV:
38 + return dmac_inv_range;
39 +
40 + case VC_SM_CACHE_OP_CLEAN:
41 + return dmac_clean_range;
42 +
43 + case VC_SM_CACHE_OP_FLUSH:
44 + return dmac_flush_range;
45 +
46 + default:
47 + pr_err("[%s]: Invalid cache_op: 0x%08x\n", __func__, cache_op);
48 + return NULL;
49 + }
50 +}
51 +
52 +/*
53 + * Clean/invalid/flush cache of which buffer is already pinned (i.e. accessed).
54 + */
55 +static int clean_invalid_contig_2d(const void __user *addr,
56 + const size_t block_count,
57 + const size_t block_size,
58 + const size_t stride,
59 + const unsigned int cache_op)
60 +{
61 + size_t i;
62 + void (*op_fn)(const void *start, const void *end);
63 +
64 + if (!block_size) {
65 + pr_err("[%s]: size cannot be 0\n", __func__);
66 + return -EINVAL;
67 + }
68 +
69 + op_fn = cache_op_to_func(cache_op);
70 + if (!op_fn)
71 + return -EINVAL;
72 +
73 + for (i = 0; i < block_count; i ++, addr += stride)
74 + op_fn(addr, addr + block_size);
75 +
76 + return 0;
77 +}
78 +
79 +static int vc_sm_cma_clean_invalid2(unsigned int cmdnr, unsigned long arg)
80 +{
81 + struct vc_sm_cma_ioctl_clean_invalid2 ioparam;
82 + struct vc_sm_cma_ioctl_clean_invalid_block *block = NULL;
83 + int i, ret = 0;
84 +
85 + /* Get parameter data. */
86 + if (copy_from_user(&ioparam, (void *)arg, sizeof(ioparam))) {
87 + pr_err("[%s]: failed to copy-from-user header for cmd %x\n",
88 + __func__, cmdnr);
89 + return -EFAULT;
90 + }
91 + block = kmalloc(ioparam.op_count * sizeof(*block), GFP_KERNEL);
92 + if (!block)
93 + return -EFAULT;
94 +
95 + if (copy_from_user(block, (void *)(arg + sizeof(ioparam)),
96 + ioparam.op_count * sizeof(*block)) != 0) {
97 + pr_err("[%s]: failed to copy-from-user payload for cmd %x\n",
98 + __func__, cmdnr);
99 + ret = -EFAULT;
100 + goto out;
101 + }
102 +
103 + for (i = 0; i < ioparam.op_count; i++) {
104 + const struct vc_sm_cma_ioctl_clean_invalid_block * const op = block + i;
105 +
106 + if (op->invalidate_mode == VC_SM_CACHE_OP_NOP)
107 + continue;
108 +
109 + ret = clean_invalid_contig_2d((void __user *)op->start_address,
110 + op->block_count, op->block_size,
111 + op->inter_block_stride,
112 + op->invalidate_mode);
113 + if (ret)
114 + break;
115 + }
116 +out:
117 + kfree(block);
118 +
119 + return ret;
120 +}
121 +
122 static long vc_sm_cma_ioctl(struct file *file, unsigned int cmd,
123 unsigned long arg)
124 {
125 @@ -1272,9 +1366,6 @@ static long vc_sm_cma_ioctl(struct file
126 return -EPERM;
127 }
128
129 - pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
130 - current->tgid, file_data->pid);
131 -
132 /* Action is a re-post of a previously interrupted action? */
133 if (file_data->restart_sys == -EINTR) {
134 struct vc_sm_action_clean_t action_clean;
135 @@ -1357,7 +1448,18 @@ static long vc_sm_cma_ioctl(struct file
136 break;
137 }
138
139 + /*
140 + * Flush/Invalidate the cache for a given mapping.
141 + * Blocks must be pinned (i.e. accessed) before this call.
142 + */
143 + case VC_SM_CMA_CMD_CLEAN_INVALID2:
144 + ret = vc_sm_cma_clean_invalid2(cmdnr, arg);
145 + break;
146 +
147 default:
148 + pr_debug("[%s]: cmd %x tgid %u, owner %u\n", __func__, cmdnr,
149 + current->tgid, file_data->pid);
150 +
151 ret = -EINVAL;
152 break;
153 }
154 @@ -1365,10 +1467,43 @@ static long vc_sm_cma_ioctl(struct file
155 return ret;
156 }
157
158 +#ifdef CONFIG_COMPAT
159 +struct vc_sm_cma_ioctl_clean_invalid2_32 {
160 + u32 op_count;
161 + struct vc_sm_cma_ioctl_clean_invalid_block {
162 + u16 invalidate_mode;
163 + u16 block_count;
164 + compat_uptr_t start_address;
165 + u32 block_size;
166 + u32 inter_block_stride;
167 + } s[0];
168 +};
169 +
170 +#define VC_SM_CMA_CMD_CLEAN_INVALID2_32\
171 + _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
172 + struct vc_sm_cma_ioctl_clean_invalid2)
173 +
174 +static long vc_sm_cma_compat_ioctl(struct file *file, unsigned int cmd,
175 + unsigned long arg)
176 +{
177 + switch (cmd) {
178 + case VC_SM_CMA_CMD_CLEAN_INVALID2_32:
179 + /* FIXME */
180 + break;
181 +
182 + default:
183 + return vc_sm_cma_compat_ioctl(file, cmd, arg);
184 + }
185 +}
186 +#endif
187 +
188 /* Device operations that we managed in this driver. */
189 static const struct file_operations vc_sm_ops = {
190 .owner = THIS_MODULE,
191 .unlocked_ioctl = vc_sm_cma_ioctl,
192 +#ifdef CONFIG_COMPAT
193 + .compat_ioctl = vc_sm_cma_compat_ioctl,
194 +#endif
195 .open = vc_sm_cma_open,
196 .release = vc_sm_cma_release,
197 };
198 --- a/include/linux/broadcom/vc_sm_cma_ioctl.h
199 +++ b/include/linux/broadcom/vc_sm_cma_ioctl.h
200 @@ -33,6 +33,8 @@ enum vc_sm_cma_cmd_e {
201
202 VC_SM_CMA_CMD_IMPORT_DMABUF,
203
204 + VC_SM_CMA_CMD_CLEAN_INVALID2,
205 +
206 VC_SM_CMA_CMD_LAST /* Do not delete */
207 };
208
209 @@ -75,6 +77,27 @@ struct vc_sm_cma_ioctl_import_dmabuf {
210 __u64 dma_addr;
211 };
212
213 +/*
214 + * Cache functions to be set to struct vc_sm_cma_ioctl_clean_invalid2
215 + * invalidate_mode.
216 + */
217 +#define VC_SM_CACHE_OP_NOP 0x00
218 +#define VC_SM_CACHE_OP_INV 0x01
219 +#define VC_SM_CACHE_OP_CLEAN 0x02
220 +#define VC_SM_CACHE_OP_FLUSH 0x03
221 +
222 +struct vc_sm_cma_ioctl_clean_invalid2 {
223 + __u32 op_count;
224 + __u32 pad;
225 + struct vc_sm_cma_ioctl_clean_invalid_block {
226 + __u32 invalidate_mode;
227 + __u32 block_count;
228 + void * __user start_address;
229 + __u32 block_size;
230 + __u32 inter_block_stride;
231 + } s[0];
232 +};
233 +
234 /* IOCTL numbers */
235 #define VC_SM_CMA_IOCTL_MEM_ALLOC\
236 _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_ALLOC,\
237 @@ -84,4 +107,8 @@ struct vc_sm_cma_ioctl_import_dmabuf {
238 _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_IMPORT_DMABUF,\
239 struct vc_sm_cma_ioctl_import_dmabuf)
240
241 +#define VC_SM_CMA_IOCTL_MEM_CLEAN_INVALID2\
242 + _IOR(VC_SM_CMA_MAGIC_TYPE, VC_SM_CMA_CMD_CLEAN_INVALID2,\
243 + struct vc_sm_cma_ioctl_clean_invalid2)
244 +
245 #endif /* __VC_SM_CMA_IOCTL_H */