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 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 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 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 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 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 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 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 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 588 void delta_ipc_exit(struct delta_dev *delta) 589 { 590 unregister_rpmsg_driver(&delta->rpmsg_driver); 591 } 592