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
to_paddr(struct delta_ipc_ctx * ctx,void * vaddr)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
is_valid_data(struct delta_ipc_ctx * ctx,void * data,u32 size)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
build_msg_header(struct delta_ipc_ctx * ctx,enum delta_ipc_fw_command command,struct delta_ipc_header_msg * header)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
delta_ipc_open(struct delta_ctx * pctx,const char * name,struct delta_ipc_param * param,u32 ipc_buf_size,struct delta_buf ** ipc_buf,void ** hdl)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 strscpy(msg.name, name, sizeof(msg.name));
179
180 msg.param_size = param->size;
181 memcpy(ctx->ipc_buf->vaddr, param->data, msg.param_size);
182 msg.param_paddr = ctx->ipc_buf->paddr;
183
184 /* send it */
185 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
186 if (ret) {
187 dev_err(delta->dev,
188 "%s ipc: failed to open, rpmsg_send failed (%d) for DELTA_IPC_OPEN (name=%s, size=%d, data=%p)\n",
189 pctx->name,
190 ret, name, param->size, param->data);
191 goto err;
192 }
193
194 /* wait for acknowledge */
195 if (!wait_for_completion_timeout
196 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
197 dev_err(delta->dev,
198 "%s ipc: failed to open, timeout waiting for DELTA_IPC_OPEN callback (name=%s, size=%d, data=%p)\n",
199 pctx->name,
200 name, param->size, param->data);
201 ret = -ETIMEDOUT;
202 goto err;
203 }
204
205 /* command completed, check error */
206 if (ctx->cb_err) {
207 dev_err(delta->dev,
208 "%s ipc: failed to open, DELTA_IPC_OPEN completed but with error (%d) (name=%s, size=%d, data=%p)\n",
209 pctx->name,
210 ctx->cb_err, name, param->size, param->data);
211 ret = -EIO;
212 goto err;
213 }
214
215 *ipc_buf = ctx->ipc_buf;
216 *hdl = (void *)ctx;
217
218 return 0;
219
220 err:
221 pctx->sys_errors++;
222 hw_free(pctx, ctx->ipc_buf);
223 ctx->ipc_buf = NULL;
224
225 return ret;
226 };
227
delta_ipc_set_stream(void * hdl,struct delta_ipc_param * param)228 int delta_ipc_set_stream(void *hdl, struct delta_ipc_param *param)
229 {
230 struct delta_ipc_ctx *ctx = to_ctx(hdl);
231 struct delta_ctx *pctx = to_pctx(ctx);
232 struct delta_dev *delta = pctx->dev;
233 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
234 struct delta_ipc_set_stream_msg msg;
235 int ret;
236
237 if (!hdl) {
238 dev_err(delta->dev,
239 "%s ipc: failed to set stream, invalid ipc handle\n",
240 pctx->name);
241 return -EINVAL;
242 }
243
244 if (!rpmsg_device) {
245 dev_err(delta->dev,
246 "%s ipc: failed to set stream, rpmsg is not initialized\n",
247 pctx->name);
248 return -EINVAL;
249 }
250
251 if (!param || !param->data || !param->size) {
252 dev_err(delta->dev,
253 "%s ipc: failed to set stream, empty parameter\n",
254 pctx->name);
255 return -EINVAL;
256 }
257
258 if (param->size > ctx->ipc_buf->size) {
259 dev_err(delta->dev,
260 "%s ipc: failed to set stream, too large ipc parameter(%d bytes while max %d expected)\n",
261 pctx->name,
262 param->size, ctx->ipc_buf->size);
263 return -EINVAL;
264 }
265
266 if (!is_valid_data(ctx, param->data, param->size)) {
267 dev_err(delta->dev,
268 "%s ipc: failed to set stream, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
269 pctx->name,
270 param->size,
271 param->data,
272 ctx->ipc_buf->vaddr,
273 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
274 return -EINVAL;
275 }
276
277 /* build rpmsg message */
278 build_msg_header(ctx, DELTA_IPC_SET_STREAM, &msg.header);
279
280 msg.param_size = param->size;
281 msg.param_paddr = to_paddr(ctx, param->data);
282
283 /* send it */
284 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
285 if (ret) {
286 dev_err(delta->dev,
287 "%s ipc: failed to set stream, rpmsg_send failed (%d) for DELTA_IPC_SET_STREAM (size=%d, data=%p)\n",
288 pctx->name,
289 ret, param->size, param->data);
290 pctx->sys_errors++;
291 return ret;
292 }
293
294 /* wait for acknowledge */
295 if (!wait_for_completion_timeout
296 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
297 dev_err(delta->dev,
298 "%s ipc: failed to set stream, timeout waiting for DELTA_IPC_SET_STREAM callback (size=%d, data=%p)\n",
299 pctx->name,
300 param->size, param->data);
301 pctx->sys_errors++;
302 return -ETIMEDOUT;
303 }
304
305 /* command completed, check status */
306 if (ctx->cb_err) {
307 dev_err(delta->dev,
308 "%s ipc: failed to set stream, DELTA_IPC_SET_STREAM completed but with error (%d) (size=%d, data=%p)\n",
309 pctx->name,
310 ctx->cb_err, param->size, param->data);
311 pctx->sys_errors++;
312 return -EIO;
313 }
314
315 return 0;
316 }
317
delta_ipc_decode(void * hdl,struct delta_ipc_param * param,struct delta_ipc_param * status)318 int delta_ipc_decode(void *hdl, struct delta_ipc_param *param,
319 struct delta_ipc_param *status)
320 {
321 struct delta_ipc_ctx *ctx = to_ctx(hdl);
322 struct delta_ctx *pctx = to_pctx(ctx);
323 struct delta_dev *delta = pctx->dev;
324 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
325 struct delta_ipc_decode_msg msg;
326 int ret;
327
328 if (!hdl) {
329 dev_err(delta->dev,
330 "%s ipc: failed to decode, invalid ipc handle\n",
331 pctx->name);
332 return -EINVAL;
333 }
334
335 if (!rpmsg_device) {
336 dev_err(delta->dev,
337 "%s ipc: failed to decode, rpmsg is not initialized\n",
338 pctx->name);
339 return -EINVAL;
340 }
341
342 if (!param || !param->data || !param->size) {
343 dev_err(delta->dev,
344 "%s ipc: failed to decode, empty parameter\n",
345 pctx->name);
346 return -EINVAL;
347 }
348
349 if (!status || !status->data || !status->size) {
350 dev_err(delta->dev,
351 "%s ipc: failed to decode, empty status\n",
352 pctx->name);
353 return -EINVAL;
354 }
355
356 if (param->size + status->size > ctx->ipc_buf->size) {
357 dev_err(delta->dev,
358 "%s ipc: failed to decode, too large ipc parameter (%d bytes (param) + %d bytes (status) while max %d expected)\n",
359 pctx->name,
360 param->size,
361 status->size,
362 ctx->ipc_buf->size);
363 return -EINVAL;
364 }
365
366 if (!is_valid_data(ctx, param->data, param->size)) {
367 dev_err(delta->dev,
368 "%s ipc: failed to decode, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
369 pctx->name,
370 param->size,
371 param->data,
372 ctx->ipc_buf->vaddr,
373 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
374 return -EINVAL;
375 }
376
377 if (!is_valid_data(ctx, status->data, status->size)) {
378 dev_err(delta->dev,
379 "%s ipc: failed to decode, status is not in expected address range (size=%d, data=%p not in %p..%p)\n",
380 pctx->name,
381 status->size,
382 status->data,
383 ctx->ipc_buf->vaddr,
384 ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1);
385 return -EINVAL;
386 }
387
388 /* build rpmsg message */
389 build_msg_header(ctx, DELTA_IPC_DECODE, &msg.header);
390
391 msg.param_size = param->size;
392 msg.param_paddr = to_paddr(ctx, param->data);
393
394 msg.status_size = status->size;
395 msg.status_paddr = to_paddr(ctx, status->data);
396
397 /* send it */
398 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
399 if (ret) {
400 dev_err(delta->dev,
401 "%s ipc: failed to decode, rpmsg_send failed (%d) for DELTA_IPC_DECODE (size=%d, data=%p)\n",
402 pctx->name,
403 ret, param->size, param->data);
404 pctx->sys_errors++;
405 return ret;
406 }
407
408 /* wait for acknowledge */
409 if (!wait_for_completion_timeout
410 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
411 dev_err(delta->dev,
412 "%s ipc: failed to decode, timeout waiting for DELTA_IPC_DECODE callback (size=%d, data=%p)\n",
413 pctx->name,
414 param->size, param->data);
415 pctx->sys_errors++;
416 return -ETIMEDOUT;
417 }
418
419 /* command completed, check status */
420 if (ctx->cb_err) {
421 dev_err(delta->dev,
422 "%s ipc: failed to decode, DELTA_IPC_DECODE completed but with error (%d) (size=%d, data=%p)\n",
423 pctx->name,
424 ctx->cb_err, param->size, param->data);
425 pctx->sys_errors++;
426 return -EIO;
427 }
428
429 return 0;
430 };
431
delta_ipc_close(void * hdl)432 void delta_ipc_close(void *hdl)
433 {
434 struct delta_ipc_ctx *ctx = to_ctx(hdl);
435 struct delta_ctx *pctx = to_pctx(ctx);
436 struct delta_dev *delta = pctx->dev;
437 struct rpmsg_device *rpmsg_device = delta->rpmsg_device;
438 struct delta_ipc_close_msg msg;
439 int ret;
440
441 if (!hdl) {
442 dev_err(delta->dev,
443 "%s ipc: failed to close, invalid ipc handle\n",
444 pctx->name);
445 return;
446 }
447
448 if (ctx->ipc_buf) {
449 hw_free(pctx, ctx->ipc_buf);
450 ctx->ipc_buf = NULL;
451 }
452
453 if (!rpmsg_device) {
454 dev_err(delta->dev,
455 "%s ipc: failed to close, rpmsg is not initialized\n",
456 pctx->name);
457 return;
458 }
459
460 /* build rpmsg message */
461 build_msg_header(ctx, DELTA_IPC_CLOSE, &msg.header);
462
463 /* send it */
464 ret = rpmsg_send(rpmsg_device->ept, &msg, sizeof(msg));
465 if (ret) {
466 dev_err(delta->dev,
467 "%s ipc: failed to close, rpmsg_send failed (%d) for DELTA_IPC_CLOSE\n",
468 pctx->name, ret);
469 pctx->sys_errors++;
470 return;
471 }
472
473 /* wait for acknowledge */
474 if (!wait_for_completion_timeout
475 (&ctx->done, msecs_to_jiffies(IPC_TIMEOUT))) {
476 dev_err(delta->dev,
477 "%s ipc: failed to close, timeout waiting for DELTA_IPC_CLOSE callback\n",
478 pctx->name);
479 pctx->sys_errors++;
480 return;
481 }
482
483 /* command completed, check status */
484 if (ctx->cb_err) {
485 dev_err(delta->dev,
486 "%s ipc: failed to close, DELTA_IPC_CLOSE completed but with error (%d)\n",
487 pctx->name, ctx->cb_err);
488 pctx->sys_errors++;
489 }
490 };
491
delta_ipc_cb(struct rpmsg_device * rpdev,void * data,int len,void * priv,u32 src)492 static int delta_ipc_cb(struct rpmsg_device *rpdev, void *data,
493 int len, void *priv, u32 src)
494 {
495 struct delta_ipc_ctx *ctx;
496 struct delta_ipc_cb_msg *msg;
497
498 /* sanity check */
499 if (!rpdev) {
500 dev_err(NULL, "rpdev is NULL\n");
501 return -EINVAL;
502 }
503
504 if (!data || !len) {
505 dev_err(&rpdev->dev,
506 "unexpected empty message received from src=%d\n", src);
507 return -EINVAL;
508 }
509
510 if (len != sizeof(*msg)) {
511 dev_err(&rpdev->dev,
512 "unexpected message length received from src=%d (received %d bytes while %zu bytes expected)\n",
513 len, src, sizeof(*msg));
514 return -EINVAL;
515 }
516
517 msg = (struct delta_ipc_cb_msg *)data;
518 if (msg->header.tag != IPC_SANITY_TAG) {
519 dev_err(&rpdev->dev,
520 "unexpected message tag received from src=%d (received %x tag while %x expected)\n",
521 src, msg->header.tag, IPC_SANITY_TAG);
522 return -EINVAL;
523 }
524
525 ctx = msg_to_ctx(msg);
526 if (!ctx) {
527 dev_err(&rpdev->dev,
528 "unexpected message with NULL host_hdl received from src=%d\n",
529 src);
530 return -EINVAL;
531 }
532
533 /*
534 * if not already known, save copro instance context
535 * to ensure re-entrance on copro side
536 */
537 if (!ctx->copro_hdl)
538 ctx->copro_hdl = msg_to_copro_hdl(msg);
539
540 /*
541 * all is fine,
542 * update status & complete command
543 */
544 ctx->cb_err = msg->err;
545 complete(&ctx->done);
546
547 return 0;
548 }
549
delta_ipc_probe(struct rpmsg_device * rpmsg_device)550 static int delta_ipc_probe(struct rpmsg_device *rpmsg_device)
551 {
552 struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
553 struct delta_dev *delta = to_delta(rpdrv);
554
555 delta->rpmsg_device = rpmsg_device;
556
557 return 0;
558 }
559
delta_ipc_remove(struct rpmsg_device * rpmsg_device)560 static void delta_ipc_remove(struct rpmsg_device *rpmsg_device)
561 {
562 struct rpmsg_driver *rpdrv = to_rpmsg_driver(rpmsg_device->dev.driver);
563 struct delta_dev *delta = to_delta(rpdrv);
564
565 delta->rpmsg_device = NULL;
566 }
567
568 static struct rpmsg_device_id delta_ipc_device_id_table[] = {
569 {.name = "rpmsg-delta"},
570 {},
571 };
572
573 static struct rpmsg_driver delta_rpmsg_driver = {
574 .drv = {.name = KBUILD_MODNAME},
575 .id_table = delta_ipc_device_id_table,
576 .probe = delta_ipc_probe,
577 .callback = delta_ipc_cb,
578 .remove = delta_ipc_remove,
579 };
580
delta_ipc_init(struct delta_dev * delta)581 int delta_ipc_init(struct delta_dev *delta)
582 {
583 delta->rpmsg_driver = delta_rpmsg_driver;
584
585 return register_rpmsg_driver(&delta->rpmsg_driver);
586 }
587
delta_ipc_exit(struct delta_dev * delta)588 void delta_ipc_exit(struct delta_dev *delta)
589 {
590 unregister_rpmsg_driver(&delta->rpmsg_driver);
591 }
592