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