GNU Linux-libre 4.19.286-gnu1
[releases.git] / drivers / media / platform / sti / delta / delta-ipc.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) STMicroelectronics SA 2015
4  * Author: Hugues Fruchet <hugues.fruchet@st.com> for STMicroelectronics.
5  */
6
7 #include <linux/rpmsg.h>
8
9 #include "delta.h"
10 #include "delta-ipc.h"
11 #include "delta-mem.h"
12
13 #define IPC_TIMEOUT 100
14 #define IPC_SANITY_TAG 0xDEADBEEF
15
16 enum delta_ipc_fw_command {
17         DELTA_IPC_OPEN,
18         DELTA_IPC_SET_STREAM,
19         DELTA_IPC_DECODE,
20         DELTA_IPC_CLOSE
21 };
22
23 #define to_rpmsg_driver(__drv) container_of(__drv, struct rpmsg_driver, drv)
24 #define to_delta(__d) container_of(__d, struct delta_dev, rpmsg_driver)
25
26 #define to_ctx(hdl) ((struct delta_ipc_ctx *)hdl)
27 #define to_pctx(ctx) container_of(ctx, struct delta_ctx, ipc_ctx)
28
29 struct delta_ipc_header_msg {
30         u32 tag;
31         void *host_hdl;
32         u32 copro_hdl;
33         u32 command;
34 };
35
36 #define to_host_hdl(ctx) ((void *)ctx)
37
38 #define msg_to_ctx(msg) ((struct delta_ipc_ctx *)(msg)->header.host_hdl)
39 #define msg_to_copro_hdl(msg) ((msg)->header.copro_hdl)
40
41 static inline dma_addr_t to_paddr(struct delta_ipc_ctx *ctx, void *vaddr)
42 {
43         return (ctx->ipc_buf->paddr + (vaddr - ctx->ipc_buf->vaddr));
44 }
45
46 static inline bool is_valid_data(struct delta_ipc_ctx *ctx,
47                                  void *data, u32 size)
48 {
49         return ((data >= ctx->ipc_buf->vaddr) &&
50                 ((data + size) <= (ctx->ipc_buf->vaddr + ctx->ipc_buf->size)));
51 }
52
53 /*
54  * IPC shared memory (@ipc_buf_size, @ipc_buf_paddr) is sent to copro
55  * at each instance opening. This memory is allocated by IPC client
56  * and given through delta_ipc_open(). All messages parameters
57  * (open, set_stream, decode) will have their phy address within
58  * this IPC shared memory, avoiding de-facto recopies inside delta-ipc.
59  * All the below messages structures are used on both host and firmware
60  * side and are packed (use only of 32 bits size fields in messages
61  * structures to ensure packing):
62  * - struct delta_ipc_open_msg
63  * - struct delta_ipc_set_stream_msg
64  * - struct delta_ipc_decode_msg
65  * - struct delta_ipc_close_msg
66  * - struct delta_ipc_cb_msg
67  */
68 struct delta_ipc_open_msg {
69         struct delta_ipc_header_msg header;
70         u32 ipc_buf_size;
71         dma_addr_t ipc_buf_paddr;
72         char name[32];
73         u32 param_size;
74         dma_addr_t param_paddr;
75 };
76
77 struct delta_ipc_set_stream_msg {
78         struct delta_ipc_header_msg header;
79         u32 param_size;
80         dma_addr_t param_paddr;
81 };
82
83 struct delta_ipc_decode_msg {
84         struct delta_ipc_header_msg header;
85         u32 param_size;
86         dma_addr_t param_paddr;
87         u32 status_size;
88         dma_addr_t status_paddr;
89 };
90
91 struct delta_ipc_close_msg {
92         struct delta_ipc_header_msg header;
93 };
94
95 struct delta_ipc_cb_msg {
96         struct delta_ipc_header_msg header;
97         int err;
98 };
99
100 static void build_msg_header(struct delta_ipc_ctx *ctx,
101                              enum delta_ipc_fw_command command,
102                              struct delta_ipc_header_msg *header)
103 {
104         header->tag = IPC_SANITY_TAG;
105         header->host_hdl = to_host_hdl(ctx);
106         header->copro_hdl = ctx->copro_hdl;
107         header->command = command;
108 }
109
110 int delta_ipc_open(struct delta_ctx *pctx, const char *name,
111                    struct delta_ipc_param *param, u32 ipc_buf_size,
112                    struct delta_buf **ipc_buf, void **hdl)
113 {
114         struct delta_dev *delta = pctx->dev;
115         struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
116         struct delta_ipc_ctx *ctx = &pctx->ipc_ctx;
117         struct delta_ipc_open_msg msg;
118         struct delta_buf *buf = &ctx->ipc_buf_struct;
119         int ret;
120
121         if (!rpmsg_device) {
122                 dev_err(delta->dev,
123                         "%s   ipc: failed to open, rpmsg is not initialized\n",
124                         pctx->name);
125                 pctx->sys_errors++;
126                 return -EINVAL;
127         }
128
129         if (!name) {
130                 dev_err(delta->dev,
131                         "%s   ipc: failed to open, no name given\n",
132                         pctx->name);
133                 return -EINVAL;
134         }
135
136         if (!param || !param->data || !param->size) {
137                 dev_err(delta->dev,
138                         "%s  ipc: failed to open, empty parameter\n",
139                         pctx->name);
140                 return -EINVAL;
141         }
142
143         if (!ipc_buf_size) {
144                 dev_err(delta->dev,
145                         "%s   ipc: failed to open, no size given for ipc buffer\n",
146                         pctx->name);
147                 return -EINVAL;
148         }
149
150         if (param->size > ipc_buf_size) {
151                 dev_err(delta->dev,
152                         "%s   ipc: failed to open, too large ipc parameter (%d bytes while max %d expected)\n",
153                         pctx->name,
154                         param->size, ctx->ipc_buf->size);
155                 return -EINVAL;
156         }
157
158         /* init */
159         init_completion(&ctx->done);
160
161         /*
162          * allocation of contiguous buffer for
163          * data of commands exchanged between
164          * host and firmware coprocessor
165          */
166         ret = hw_alloc(pctx, ipc_buf_size,
167                        "ipc data buffer", buf);
168         if (ret)
169                 return ret;
170         ctx->ipc_buf = buf;
171
172         /* build rpmsg message */
173         build_msg_header(ctx, DELTA_IPC_OPEN, &msg.header);
174
175         msg.ipc_buf_size = ipc_buf_size;
176         msg.ipc_buf_paddr = ctx->ipc_buf->paddr;
177
178         memcpy(msg.name, name, sizeof(msg.name));
179         msg.name[sizeof(msg.name) - 1] = 0;
180
181         msg.param_size = param->size;
182         memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
183         msg.param_paddr = ctx->ipc_buf->paddr;
184
185         /* send it */
186         ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
187         if (ret) {
188                 dev_err(delta->dev,
189                         "%s   ipc: failed to open, rpmsg_send failed (%d) for DELTA_IPC_OPEN (name=%s, size=%d, data=%p)\n",
190                         pctx->name,
191                         ret, name, param->size, param->data);
192                 goto err;
193         }
194
195         /* wait for acknowledge */
196         if (!wait_for_completion_timeout
197             (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
198                 dev_err(delta->dev,
199                         "%s   ipc: failed to open, timeout waiting for DELTA_IPC_OPEN callback (name=%s, size=%d, data=%p)\n",
200                         pctx->name,
201                         name, param->size, param->data);
202                 ret = -ETIMEDOUT;
203                 goto err;
204         }
205
206         /* command completed, check error */
207         if (ctx->cb_err) {
208                 dev_err(delta->dev,
209                         "%s   ipc: failed to open, DELTA_IPC_OPEN completed but with error (%d) (name=%s, size=%d, data=%p)\n",
210                         pctx->name,
211                         ctx->cb_err, name, param->size, param->data);
212                 ret = -EIO;
213                 goto err;
214         }
215
216         *ipc_buf = ctx->ipc_buf;
217         *hdl = (void *)ctx;
218
219         return 0;
220
221 err:
222         pctx->sys_errors++;
223         if (ctx->ipc_buf) {
224                 hw_free(pctx, ctx->ipc_buf);
225                 ctx->ipc_buf = NULL;
226         }
227
228         return ret;
229 };
230
231 int delta_ipc_set_stream(void *hdl, struct delta_ipc_param *param)
232 {
233         struct delta_ipc_ctx *ctx = to_ctx(hdl);
234         struct delta_ctx *pctx = to_pctx(ctx);
235         struct delta_dev *delta = pctx->dev;
236         struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
237         struct delta_ipc_set_stream_msg msg;
238         int ret;
239
240         if (!hdl) {
241                 dev_err(delta->dev,
242                         "%s   ipc: failed to set stream, invalid ipc handle\n",
243                         pctx->name);
244                 return -EINVAL;
245         }
246
247         if (!rpmsg_device) {
248                 dev_err(delta->dev,
249                         "%s   ipc: failed to set stream, rpmsg is not initialized\n",
250                         pctx->name);
251                 return -EINVAL;
252         }
253
254         if (!param || !param->data || !param->size) {
255                 dev_err(delta->dev,
256                         "%s  ipc: failed to set stream, empty parameter\n",
257                         pctx->name);
258                 return -EINVAL;
259         }
260
261         if (param->size > ctx->ipc_buf->size) {
262                 dev_err(delta->dev,
263                         "%s   ipc: failed to set stream, too large ipc parameter(%d bytes while max %d expected)\n",
264                         pctx->name,
265                         param->size, ctx->ipc_buf->size);
266                 return -EINVAL;
267         }
268
269         if (!is_valid_data(ctx, param->data, param->size)) {
270                 dev_err(delta->dev,
271                         "%s   ipc: failed to set stream, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
272                         pctx->name,
273                         param->size,
274                         param->data,
275                         ctx->ipc_buf->vaddr,
276                         ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
277                 return -EINVAL;
278         }
279
280         /* build rpmsg message */
281         build_msg_header(ctx, DELTA_IPC_SET_STREAM, &msg.header);
282
283         msg.param_size = param->size;
284         msg.param_paddr = to_paddr(ctx, param->data);
285
286         /* send it */
287         ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
288         if (ret) {
289                 dev_err(delta->dev,
290                         "%s   ipc: failed to set stream, rpmsg_send failed (%d) for DELTA_IPC_SET_STREAM (size=%d, data=%p)\n",
291                         pctx->name,
292                         ret, param->size, param->data);
293                 pctx->sys_errors++;
294                 return ret;
295         }
296
297         /* wait for acknowledge */
298         if (!wait_for_completion_timeout
299             (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
300                 dev_err(delta->dev,
301                         "%s   ipc: failed to set stream, timeout waiting for DELTA_IPC_SET_STREAM callback (size=%d, data=%p)\n",
302                         pctx->name,
303                         param->size, param->data);
304                 pctx->sys_errors++;
305                 return -ETIMEDOUT;
306         }
307
308         /* command completed, check status */
309         if (ctx->cb_err) {
310                 dev_err(delta->dev,
311                         "%s   ipc: failed to set stream, DELTA_IPC_SET_STREAM completed but with error (%d) (size=%d, data=%p)\n",
312                         pctx->name,
313                         ctx->cb_err, param->size, param->data);
314                 pctx->sys_errors++;
315                 return -EIO;
316         }
317
318         return 0;
319 }
320
321 int delta_ipc_decode(void *hdl, struct delta_ipc_param *param,
322                      struct delta_ipc_param *status)
323 {
324         struct delta_ipc_ctx *ctx = to_ctx(hdl);
325         struct delta_ctx *pctx = to_pctx(ctx);
326         struct delta_dev *delta = pctx->dev;
327         struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
328         struct delta_ipc_decode_msg msg;
329         int ret;
330
331         if (!hdl) {
332                 dev_err(delta->dev,
333                         "%s   ipc: failed to decode, invalid ipc handle\n",
334                         pctx->name);
335                 return -EINVAL;
336         }
337
338         if (!rpmsg_device) {
339                 dev_err(delta->dev,
340                         "%s   ipc: failed to decode, rpmsg is not initialized\n",
341                         pctx->name);
342                 return -EINVAL;
343         }
344
345         if (!param || !param->data || !param->size) {
346                 dev_err(delta->dev,
347                         "%s  ipc: failed to decode, empty parameter\n",
348                         pctx->name);
349                 return -EINVAL;
350         }
351
352         if (!status || !status->data || !status->size) {
353                 dev_err(delta->dev,
354                         "%s  ipc: failed to decode, empty status\n",
355                         pctx->name);
356                 return -EINVAL;
357         }
358
359         if (param->size + status->size > ctx->ipc_buf->size) {
360                 dev_err(delta->dev,
361                         "%s   ipc: failed to decode, too large ipc parameter (%d bytes (param) + %d bytes (status) while max %d expected)\n",
362                         pctx->name,
363                         param->size,
364                         status->size,
365                         ctx->ipc_buf->size);
366                 return -EINVAL;
367         }
368
369         if (!is_valid_data(ctx, param->data, param->size)) {
370                 dev_err(delta->dev,
371                         "%s   ipc: failed to decode, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
372                         pctx->name,
373                         param->size,
374                         param->data,
375                         ctx->ipc_buf->vaddr,
376                         ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
377                 return -EINVAL;
378         }
379
380         if (!is_valid_data(ctx, status->data, status->size)) {
381                 dev_err(delta->dev,
382                         "%s   ipc: failed to decode, status is not in expected address range (size=%d, data=%p not in %p..%p)\n",
383                         pctx->name,
384                         status->size,
385                         status->data,
386                         ctx->ipc_buf->vaddr,
387                         ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
388                 return -EINVAL;
389         }
390
391         /* build rpmsg message */
392         build_msg_header(ctx, DELTA_IPC_DECODE, &msg.header);
393
394         msg.param_size = param->size;
395         msg.param_paddr = to_paddr(ctx, param->data);
396
397         msg.status_size = status->size;
398         msg.status_paddr = to_paddr(ctx, status->data);
399
400         /* send it */
401         ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
402         if (ret) {
403                 dev_err(delta->dev,
404                         "%s   ipc: failed to decode, rpmsg_send failed (%d) for DELTA_IPC_DECODE (size=%d, data=%p)\n",
405                         pctx->name,
406                         ret, param->size, param->data);
407                 pctx->sys_errors++;
408                 return ret;
409         }
410
411         /* wait for acknowledge */
412         if (!wait_for_completion_timeout
413             (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
414                 dev_err(delta->dev,
415                         "%s   ipc: failed to decode, timeout waiting for DELTA_IPC_DECODE callback (size=%d, data=%p)\n",
416                         pctx->name,
417                         param->size, param->data);
418                 pctx->sys_errors++;
419                 return -ETIMEDOUT;
420         }
421
422         /* command completed, check status */
423         if (ctx->cb_err) {
424                 dev_err(delta->dev,
425                         "%s   ipc: failed to decode, DELTA_IPC_DECODE completed but with error (%d) (size=%d, data=%p)\n",
426                         pctx->name,
427                         ctx->cb_err, param->size, param->data);
428                 pctx->sys_errors++;
429                 return -EIO;
430         }
431
432         return 0;
433 };
434
435 void delta_ipc_close(void *hdl)
436 {
437         struct delta_ipc_ctx *ctx = to_ctx(hdl);
438         struct delta_ctx *pctx = to_pctx(ctx);
439         struct delta_dev *delta = pctx->dev;
440         struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
441         struct delta_ipc_close_msg msg;
442         int ret;
443
444         if (!hdl) {
445                 dev_err(delta->dev,
446                         "%s   ipc: failed to close, invalid ipc handle\n",
447                         pctx->name);
448                 return;
449         }
450
451         if (ctx->ipc_buf) {
452                 hw_free(pctx, ctx->ipc_buf);
453                 ctx->ipc_buf = NULL;
454         }
455
456         if (!rpmsg_device) {
457                 dev_err(delta->dev,
458                         "%s   ipc: failed to close, rpmsg is not initialized\n",
459                         pctx->name);
460                 return;
461         }
462
463         /* build rpmsg message */
464         build_msg_header(ctx, DELTA_IPC_CLOSE, &msg.header);
465
466         /* send it */
467         ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
468         if (ret) {
469                 dev_err(delta->dev,
470                         "%s   ipc: failed to close, rpmsg_send failed (%d) for DELTA_IPC_CLOSE\n",
471                         pctx->name, ret);
472                 pctx->sys_errors++;
473                 return;
474         }
475
476         /* wait for acknowledge */
477         if (!wait_for_completion_timeout
478             (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
479                 dev_err(delta->dev,
480                         "%s   ipc: failed to close, timeout waiting for DELTA_IPC_CLOSE callback\n",
481                         pctx->name);
482                 pctx->sys_errors++;
483                 return;
484         }
485
486         /* command completed, check status */
487         if (ctx->cb_err) {
488                 dev_err(delta->dev,
489                         "%s   ipc: failed to close, DELTA_IPC_CLOSE completed but with error (%d)\n",
490                         pctx->name, ctx->cb_err);
491                 pctx->sys_errors++;
492         }
493 };
494
495 static int delta_ipc_cb(struct rpmsg_device *rpdev, void *data,
496                         int len, void *priv, u32 src)
497 {
498         struct delta_ipc_ctx *ctx;
499         struct delta_ipc_cb_msg *msg;
500
501         /* sanity check */
502         if (!rpdev) {
503                 dev_err(NULL, "rpdev is NULL\n");
504                 return -EINVAL;
505         }
506
507         if (!data || !len) {
508                 dev_err(&rpdev->dev,
509                         "unexpected empty message received from src=%d\n", src);
510                 return -EINVAL;
511         }
512
513         if (len != sizeof(*msg)) {
514                 dev_err(&rpdev->dev,
515                         "unexpected message length received from src=%d (received %d bytes while %zu bytes expected)\n",
516                         len, src, sizeof(*msg));
517                 return -EINVAL;
518         }
519
520         msg = (struct delta_ipc_cb_msg *)data;
521         if (msg->header.tag != IPC_SANITY_TAG) {
522                 dev_err(&rpdev->dev,
523                         "unexpected message tag received from src=%d (received %x tag while %x expected)\n",
524                         src, msg->header.tag, IPC_SANITY_TAG);
525                 return -EINVAL;
526         }
527
528         ctx = msg_to_ctx(msg);
529         if (!ctx) {
530                 dev_err(&rpdev->dev,
531                         "unexpected message with NULL host_hdl received from src=%d\n",
532                         src);
533                 return -EINVAL;
534         }
535
536         /*
537          * if not already known, save copro instance context
538          * to ensure re-entrance on copro side
539          */
540         if (!ctx->copro_hdl)
541                 ctx->copro_hdl = msg_to_copro_hdl(msg);
542
543         /*
544          * all is fine,
545          * update status & complete command
546          */
547         ctx->cb_err = msg->err;
548         complete(&ctx->done);
549
550         return 0;
551 }
552
553 static int delta_ipc_probe(struct rpmsg_device *rpmsg_device)
554 {
555         struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
556         struct delta_dev *delta = to_delta(rpdrv);
557
558         delta->rpmsg_device = rpmsg_device;
559
560         return 0;
561 }
562
563 static void delta_ipc_remove(struct rpmsg_device *rpmsg_device)
564 {
565         struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
566         struct delta_dev *delta = to_delta(rpdrv);
567
568         delta->rpmsg_device = NULL;
569 }
570
571 static struct rpmsg_device_id delta_ipc_device_id_table[] = {
572         {.name = "rpmsg-delta"},
573         {},
574 };
575
576 static struct rpmsg_driver delta_rpmsg_driver = {
577         .drv = {.name = KBUILD_MODNAME},
578         .id_table = delta_ipc_device_id_table,
579         .probe = delta_ipc_probe,
580         .callback = delta_ipc_cb,
581         .remove = delta_ipc_remove,
582 };
583
584 int delta_ipc_init(struct delta_dev *delta)
585 {
586         delta->rpmsg_driver = delta_rpmsg_driver;
587
588         return register_rpmsg_driver(&delta->rpmsg_driver);
589 }
590
591 void delta_ipc_exit(struct delta_dev *delta)
592 {
593         unregister_rpmsg_driver(&delta->rpmsg_driver);
594 }