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 	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 
delta_ipc_set_stream(void * hdl,struct delta_ipc_param * param)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 
delta_ipc_decode(void * hdl,struct delta_ipc_param * param,struct delta_ipc_param * status)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 
delta_ipc_close(void * hdl)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 
delta_ipc_cb(struct rpmsg_device * rpdev,void * data,int len,void * priv,u32 src)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 
delta_ipc_probe(struct rpmsg_device * rpmsg_device)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 
delta_ipc_remove(struct rpmsg_device * rpmsg_device)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 
delta_ipc_init(struct delta_dev * delta)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 
delta_ipc_exit(struct delta_dev * delta)591 void delta_ipc_exit(struct delta_dev *delta)
592 {
593 	unregister_rpmsg_driver(&delta->rpmsg_driver);
594 }
595