kernel: bump 5.4 to 5.4.110
[openwrt/openwrt.git] / target / linux / layerscape / patches-5.4 / 701-net-0131-bus-fsl-mc-add-fsl-mc-userspace-support.patch
1 From 5b5567547d0088ec96160634c4e342bb06e52f19 Mon Sep 17 00:00:00 2001
2 From: Ioana Ciornei <ioana.ciornei@nxp.com>
3 Date: Wed, 14 Mar 2018 19:25:27 +0200
4 Subject: [PATCH] bus: fsl-mc: add fsl-mc userspace support
5
6 Adding userspace support for the MC (Management Complex) means exporting
7 an ioctl capable device file representing the root resource container.
8
9 This new functionality in the fsl-mc bus driver intends to provide
10 userspace applications an interface to interact with the MC firmware.
11
12 Commands that are composed in userspace are sent to the MC firmware
13 through the FSL_MC_SEND_MC_COMMAND ioctl. By default the implicit MC
14 I/O portal is used for this operation, but if the implicit one is busy,
15 a dynamic portal is allocated and then freed upon execution.
16
17 Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
18 ---
19 Documentation/ioctl/ioctl-number.rst | 1 +
20 drivers/bus/fsl-mc/Kconfig | 7 ++
21 drivers/bus/fsl-mc/Makefile | 3 +
22 drivers/bus/fsl-mc/dprc-driver.c | 14 ++-
23 drivers/bus/fsl-mc/fsl-mc-private.h | 39 ++++++++
24 drivers/bus/fsl-mc/fsl-mc-uapi.c | 168 +++++++++++++++++++++++++++++++++++
25 include/uapi/linux/fsl_mc.h | 9 ++
26 7 files changed, 240 insertions(+), 1 deletion(-)
27 create mode 100644 drivers/bus/fsl-mc/fsl-mc-uapi.c
28
29 --- a/Documentation/ioctl/ioctl-number.rst
30 +++ b/Documentation/ioctl/ioctl-number.rst
31 @@ -180,6 +180,7 @@ Code Seq# Include File
32 'R' 00-1F linux/random.h conflict!
33 'R' 01 linux/rfkill.h conflict!
34 'R' C0-DF net/bluetooth/rfcomm.h
35 +'R' E0 uapi/linux/fsl_mc.h
36 'S' all linux/cdrom.h conflict!
37 'S' 80-81 scsi/scsi_ioctl.h conflict!
38 'S' 82-FF scsi/scsi.h conflict!
39 --- a/drivers/bus/fsl-mc/Kconfig
40 +++ b/drivers/bus/fsl-mc/Kconfig
41 @@ -14,3 +14,10 @@ config FSL_MC_BUS
42 architecture. The fsl-mc bus driver handles discovery of
43 DPAA2 objects (which are represented as Linux devices) and
44 binding objects to drivers.
45 +
46 +config FSL_MC_UAPI_SUPPORT
47 + bool "Management Complex (MC) userspace support"
48 + depends on FSL_MC_BUS
49 + help
50 + Provides userspace support for creating/destroying/configuring
51 + DPAA2 objects in the Management Complex.
52 --- a/drivers/bus/fsl-mc/Makefile
53 +++ b/drivers/bus/fsl-mc/Makefile
54 @@ -16,3 +16,6 @@ mc-bus-driver-objs := fsl-mc-bus.o \
55 fsl-mc-allocator.o \
56 fsl-mc-msi.o \
57 dpmcp.o
58 +
59 +# MC userspace support
60 +obj-$(CONFIG_FSL_MC_UAPI_SUPPORT) += fsl-mc-uapi.o
61 --- a/drivers/bus/fsl-mc/dprc-driver.c
62 +++ b/drivers/bus/fsl-mc/dprc-driver.c
63 @@ -647,6 +647,12 @@ static int dprc_probe(struct fsl_mc_devi
64 } else {
65 dev_set_msi_domain(&mc_dev->dev, mc_msi_domain);
66 msi_domain_set = true;
67 +
68 + error = fsl_mc_uapi_create_device_file(mc_bus);
69 + if (error < 0) {
70 + error = -EPROBE_DEFER;
71 + goto error_cleanup_msi_domain;
72 + }
73 }
74 }
75
76 @@ -654,7 +660,7 @@ static int dprc_probe(struct fsl_mc_devi
77 &mc_dev->mc_handle);
78 if (error < 0) {
79 dev_err(&mc_dev->dev, "dprc_open() failed: %d\n", error);
80 - goto error_cleanup_msi_domain;
81 + goto error_cleanup_uapi;
82 }
83
84 error = dprc_get_attributes(mc_dev->mc_io, 0, mc_dev->mc_handle,
85 @@ -706,6 +712,10 @@ static int dprc_probe(struct fsl_mc_devi
86 error_cleanup_open:
87 (void)dprc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
88
89 +error_cleanup_uapi:
90 + if (fsl_mc_is_root_dprc(&mc_dev->dev))
91 + fsl_mc_uapi_remove_device_file(mc_bus);
92 +
93 error_cleanup_msi_domain:
94 if (msi_domain_set)
95 dev_set_msi_domain(&mc_dev->dev, NULL);
96 @@ -774,6 +784,8 @@ static int dprc_remove(struct fsl_mc_dev
97 if (!fsl_mc_is_root_dprc(&mc_dev->dev)) {
98 fsl_destroy_mc_io(mc_dev->mc_io);
99 mc_dev->mc_io = NULL;
100 + } else {
101 + fsl_mc_uapi_remove_device_file(mc_bus);
102 }
103
104 dev_info(&mc_dev->dev, "DPRC device unbound from driver");
105 --- a/drivers/bus/fsl-mc/fsl-mc-private.h
106 +++ b/drivers/bus/fsl-mc/fsl-mc-private.h
107 @@ -10,6 +10,8 @@
108
109 #include <linux/fsl/mc.h>
110 #include <linux/mutex.h>
111 +#include <linux/ioctl.h>
112 +#include <linux/miscdevice.h>
113
114 /*
115 * Data Path Management Complex (DPMNG) General API
116 @@ -505,6 +507,22 @@ struct fsl_mc_resource_pool {
117 };
118
119 /**
120 + * struct fsl_mc_uapi - information associated with a device file
121 + * @misc: struct miscdevice linked to the root dprc
122 + * @device: newly created device in /dev
123 + * @mutex: mutex lock to serialize the open/release operations
124 + * @local_instance_in_use: local MC I/O instance in use or not
125 + * @static_mc_io: pointer to the static MC I/O object
126 + */
127 +struct fsl_mc_uapi {
128 + struct miscdevice misc;
129 + struct device *device;
130 + struct mutex mutex; /* serialize open/release operations */
131 + u32 local_instance_in_use;
132 + struct fsl_mc_io *static_mc_io;
133 +};
134 +
135 +/**
136 * struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
137 * @mc_dev: fsl-mc device for the bus device itself.
138 * @resource_pools: array of resource pools (one pool per resource type)
139 @@ -513,6 +531,7 @@ struct fsl_mc_resource_pool {
140 * @irq_resources: Pointer to array of IRQ objects for the IRQ pool
141 * @scan_mutex: Serializes bus scanning
142 * @dprc_attr: DPRC attributes
143 + * @uapi_misc: struct that abstracts the interaction with userspace
144 */
145 struct fsl_mc_bus {
146 struct fsl_mc_device mc_dev;
147 @@ -520,6 +539,7 @@ struct fsl_mc_bus {
148 struct fsl_mc_device_irq *irq_resources;
149 struct mutex scan_mutex; /* serializes bus scanning */
150 struct dprc_attributes dprc_attr;
151 + struct fsl_mc_uapi uapi_misc;
152 };
153
154 #define to_fsl_mc_bus(_mc_dev) \
155 @@ -574,4 +594,23 @@ void fsl_destroy_mc_io(struct fsl_mc_io
156
157 bool fsl_mc_is_root_dprc(struct device *dev);
158
159 +#ifdef CONFIG_FSL_MC_UAPI_SUPPORT
160 +
161 +int fsl_mc_uapi_create_device_file(struct fsl_mc_bus *mc_bus);
162 +
163 +void fsl_mc_uapi_remove_device_file(struct fsl_mc_bus *mc_bus);
164 +
165 +#else
166 +
167 +static inline int fsl_mc_uapi_create_device_file(struct fsl_mc_bus *mc_bus)
168 +{
169 + return 0;
170 +}
171 +
172 +static inline void fsl_mc_uapi_remove_device_file(struct fsl_mc_bus *mc_bus)
173 +{
174 +}
175 +
176 +#endif
177 +
178 #endif /* _FSL_MC_PRIVATE_H_ */
179 --- /dev/null
180 +++ b/drivers/bus/fsl-mc/fsl-mc-uapi.c
181 @@ -0,0 +1,168 @@
182 +// SPDX-License-Identifier: GPL-2.0
183 +/*
184 + * Management Complex (MC) userspace support
185 + *
186 + * Copyright 2018 NXP
187 + *
188 + */
189 +
190 +#include <linux/slab.h>
191 +#include <linux/fs.h>
192 +#include <linux/uaccess.h>
193 +#include <linux/miscdevice.h>
194 +
195 +#include "fsl-mc-private.h"
196 +
197 +struct uapi_priv_data {
198 + struct fsl_mc_uapi *uapi;
199 + struct fsl_mc_io *mc_io;
200 +};
201 +
202 +static int fsl_mc_uapi_send_command(unsigned long arg,
203 + struct fsl_mc_io *mc_io)
204 +{
205 + struct fsl_mc_command mc_cmd;
206 + int error;
207 +
208 + error = copy_from_user(&mc_cmd, (void __user *)arg, sizeof(mc_cmd));
209 + if (error)
210 + return -EFAULT;
211 +
212 + error = mc_send_command(mc_io, &mc_cmd);
213 + if (error)
214 + return error;
215 +
216 + error = copy_to_user((void __user *)arg, &mc_cmd, sizeof(mc_cmd));
217 + if (error)
218 + return -EFAULT;
219 +
220 + return 0;
221 +}
222 +
223 +static int fsl_mc_uapi_dev_open(struct inode *inode, struct file *filep)
224 +{
225 + struct fsl_mc_device *root_mc_device;
226 + struct uapi_priv_data *priv_data;
227 + struct fsl_mc_io *dynamic_mc_io;
228 + struct fsl_mc_uapi *mc_uapi;
229 + struct fsl_mc_bus *mc_bus;
230 + int error;
231 +
232 + priv_data = kzalloc(sizeof(*priv_data), GFP_KERNEL);
233 + if (!priv_data)
234 + return -ENOMEM;
235 +
236 + mc_uapi = container_of(filep->private_data, struct fsl_mc_uapi, misc);
237 + mc_bus = container_of(mc_uapi, struct fsl_mc_bus, uapi_misc);
238 + root_mc_device = &mc_bus->mc_dev;
239 +
240 + mutex_lock(&mc_uapi->mutex);
241 +
242 + if (!mc_uapi->local_instance_in_use) {
243 + priv_data->mc_io = mc_uapi->static_mc_io;
244 + mc_uapi->local_instance_in_use = 1;
245 + } else {
246 + error = fsl_mc_portal_allocate(root_mc_device, 0,
247 + &dynamic_mc_io);
248 + if (error) {
249 + dev_dbg(&root_mc_device->dev,
250 + "Could not allocate MC portal\n");
251 + goto error_portal_allocate;
252 + }
253 +
254 + priv_data->mc_io = dynamic_mc_io;
255 + }
256 + priv_data->uapi = mc_uapi;
257 + filep->private_data = priv_data;
258 +
259 + mutex_unlock(&mc_uapi->mutex);
260 +
261 + return 0;
262 +
263 +error_portal_allocate:
264 + mutex_unlock(&mc_uapi->mutex);
265 +
266 + return error;
267 +}
268 +
269 +static int fsl_mc_uapi_dev_release(struct inode *inode, struct file *filep)
270 +{
271 + struct uapi_priv_data *priv_data;
272 + struct fsl_mc_uapi *mc_uapi;
273 + struct fsl_mc_io *mc_io;
274 +
275 + priv_data = filep->private_data;
276 + mc_uapi = priv_data->uapi;
277 + mc_io = priv_data->mc_io;
278 +
279 + mutex_lock(&mc_uapi->mutex);
280 +
281 + if (mc_io == mc_uapi->static_mc_io)
282 + mc_uapi->local_instance_in_use = 0;
283 + else
284 + fsl_mc_portal_free(mc_io);
285 +
286 + kfree(filep->private_data);
287 + filep->private_data = NULL;
288 +
289 + mutex_unlock(&mc_uapi->mutex);
290 +
291 + return 0;
292 +}
293 +
294 +static long fsl_mc_uapi_dev_ioctl(struct file *file,
295 + unsigned int cmd,
296 + unsigned long arg)
297 +{
298 + struct uapi_priv_data *priv_data = file->private_data;
299 + struct fsl_mc_device *root_mc_device;
300 + struct fsl_mc_bus *mc_bus;
301 + int error;
302 +
303 + mc_bus = container_of(priv_data->uapi, struct fsl_mc_bus, uapi_misc);
304 + root_mc_device = &mc_bus->mc_dev;
305 +
306 + switch (cmd) {
307 + case FSL_MC_SEND_MC_COMMAND:
308 + error = fsl_mc_uapi_send_command(arg, priv_data->mc_io);
309 + break;
310 + default:
311 + dev_dbg(&root_mc_device->dev, "unexpected ioctl call number\n");
312 + error = -EINVAL;
313 + }
314 +
315 + return error;
316 +}
317 +
318 +static const struct file_operations fsl_mc_uapi_dev_fops = {
319 + .owner = THIS_MODULE,
320 + .open = fsl_mc_uapi_dev_open,
321 + .release = fsl_mc_uapi_dev_release,
322 + .unlocked_ioctl = fsl_mc_uapi_dev_ioctl,
323 +};
324 +
325 +int fsl_mc_uapi_create_device_file(struct fsl_mc_bus *mc_bus)
326 +{
327 + struct fsl_mc_device *mc_dev = &mc_bus->mc_dev;
328 + struct fsl_mc_uapi *mc_uapi = &mc_bus->uapi_misc;
329 + int error;
330 +
331 + mc_uapi->misc.minor = MISC_DYNAMIC_MINOR;
332 + mc_uapi->misc.name = dev_name(&mc_dev->dev);
333 + mc_uapi->misc.fops = &fsl_mc_uapi_dev_fops;
334 +
335 + error = misc_register(&mc_uapi->misc);
336 + if (error)
337 + return error;
338 +
339 + mc_uapi->static_mc_io = mc_bus->mc_dev.mc_io;
340 +
341 + mutex_init(&mc_uapi->mutex);
342 +
343 + return 0;
344 +}
345 +
346 +void fsl_mc_uapi_remove_device_file(struct fsl_mc_bus *mc_bus)
347 +{
348 + misc_deregister(&mc_bus->uapi_misc.misc);
349 +}
350 --- a/include/uapi/linux/fsl_mc.h
351 +++ b/include/uapi/linux/fsl_mc.h
352 @@ -16,10 +16,19 @@
353 * struct fsl_mc_command - Management Complex (MC) command structure
354 * @header: MC command header
355 * @params: MC command parameters
356 + *
357 + * Used by FSL_MC_SEND_MC_COMMAND
358 */
359 struct fsl_mc_command {
360 __le64 header;
361 __le64 params[MC_CMD_NUM_OF_PARAMS];
362 };
363
364 +#define FSL_MC_SEND_CMD_IOCTL_TYPE 'R'
365 +#define FSL_MC_SEND_CMD_IOCTL_SEQ 0xE0
366 +
367 +#define FSL_MC_SEND_MC_COMMAND \
368 + _IOWR(FSL_MC_SEND_CMD_IOCTL_TYPE, FSL_MC_SEND_CMD_IOCTL_SEQ, \
369 + struct fsl_mc_command)
370 +
371 #endif /* _UAPI_FSL_MC_H_ */