/* * IPC shared memory (@ipc_buf_size, @ipc_buf_paddr) is sent to copro * at each instance opening. This memory is allocated by IPC client * and given through delta_ipc_open(). All messages parameters * (open, set_stream, decode) will have their phy address within * this IPC shared memory, avoiding de-facto recopies inside delta-ipc. * All the below messages structures are used on both host and firmware * side and are packed (use only of 32 bits size fields in messages * structures to ensure packing): * - struct delta_ipc_open_msg * - struct delta_ipc_set_stream_msg * - struct delta_ipc_decode_msg * - struct delta_ipc_close_msg * - struct delta_ipc_cb_msg
*/ struct delta_ipc_open_msg { struct delta_ipc_header_msg header;
u32 ipc_buf_size;
dma_addr_t ipc_buf_paddr; char name[32];
u32 param_size;
dma_addr_t param_paddr;
};
if (!rpmsg_device) {
dev_err(delta->dev, "%s ipc: failed to open, rpmsg is not initialized\n",
pctx->name);
pctx->sys_errors++; return -EINVAL;
}
if (!name) {
dev_err(delta->dev, "%s ipc: failed to open, no name given\n",
pctx->name); return -EINVAL;
}
if (!param || !param->data || !param->size) {
dev_err(delta->dev, "%s ipc: failed to open, empty parameter\n",
pctx->name); return -EINVAL;
}
if (!ipc_buf_size) {
dev_err(delta->dev, "%s ipc: failed to open, no size given for ipc buffer\n",
pctx->name); return -EINVAL;
}
if (param->size > ipc_buf_size) {
dev_err(delta->dev, "%s ipc: failed to open, too large ipc parameter (%d bytes while max %d expected)\n",
pctx->name,
param->size, ctx->ipc_buf->size); return -EINVAL;
}
/* init */
init_completion(&ctx->done);
/* * allocation of contiguous buffer for * data of commands exchanged between * host and firmware coprocessor
*/
ret = hw_alloc(pctx, ipc_buf_size, "ipc data buffer", buf); if (ret) return ret;
ctx->ipc_buf = buf;
if (!hdl) {
dev_err(delta->dev, "%s ipc: failed to set stream, invalid ipc handle\n",
pctx->name); return -EINVAL;
}
if (!rpmsg_device) {
dev_err(delta->dev, "%s ipc: failed to set stream, rpmsg is not initialized\n",
pctx->name); return -EINVAL;
}
if (!param || !param->data || !param->size) {
dev_err(delta->dev, "%s ipc: failed to set stream, empty parameter\n",
pctx->name); return -EINVAL;
}
if (param->size > ctx->ipc_buf->size) {
dev_err(delta->dev, "%s ipc: failed to set stream, too large ipc parameter(%d bytes while max %d expected)\n",
pctx->name,
param->size, ctx->ipc_buf->size); return -EINVAL;
}
if (!is_valid_data(ctx, param->data, param->size)) {
dev_err(delta->dev, "%s ipc: failed to set stream, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
pctx->name,
param->size,
param->data,
ctx->ipc_buf->vaddr,
ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1); return -EINVAL;
}
if (!hdl) {
dev_err(delta->dev, "%s ipc: failed to decode, invalid ipc handle\n",
pctx->name); return -EINVAL;
}
if (!rpmsg_device) {
dev_err(delta->dev, "%s ipc: failed to decode, rpmsg is not initialized\n",
pctx->name); return -EINVAL;
}
if (!param || !param->data || !param->size) {
dev_err(delta->dev, "%s ipc: failed to decode, empty parameter\n",
pctx->name); return -EINVAL;
}
if (!status || !status->data || !status->size) {
dev_err(delta->dev, "%s ipc: failed to decode, empty status\n",
pctx->name); return -EINVAL;
}
if (param->size + status->size > ctx->ipc_buf->size) {
dev_err(delta->dev, "%s ipc: failed to decode, too large ipc parameter (%d bytes (param) + %d bytes (status) while max %d expected)\n",
pctx->name,
param->size,
status->size,
ctx->ipc_buf->size); return -EINVAL;
}
if (!is_valid_data(ctx, param->data, param->size)) {
dev_err(delta->dev, "%s ipc: failed to decode, parameter is not in expected address range (size=%d, data=%p not in %p..%p)\n",
pctx->name,
param->size,
param->data,
ctx->ipc_buf->vaddr,
ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1); return -EINVAL;
}
if (!is_valid_data(ctx, status->data, status->size)) {
dev_err(delta->dev, "%s ipc: failed to decode, status is not in expected address range (size=%d, data=%p not in %p..%p)\n",
pctx->name,
status->size,
status->data,
ctx->ipc_buf->vaddr,
ctx->ipc_buf->vaddr + ctx->ipc_buf->size - 1); return -EINVAL;
}
/* sanity check */ if (!rpdev) {
dev_err(NULL, "rpdev is NULL\n"); return -EINVAL;
}
if (!data || !len) {
dev_err(&rpdev->dev, "unexpected empty message received from src=%d\n", src); return -EINVAL;
}
if (len != sizeof(*msg)) {
dev_err(&rpdev->dev, "unexpected message length received from src=%d (received %d bytes while %zu bytes expected)\n",
len, src, sizeof(*msg)); return -EINVAL;
}
msg = (struct delta_ipc_cb_msg *)data; if (msg->header.tag != IPC_SANITY_TAG) {
dev_err(&rpdev->dev, "unexpected message tag received from src=%d (received %x tag while %x expected)\n",
src, msg->header.tag, IPC_SANITY_TAG); return -EINVAL;
}
ctx = msg_to_ctx(msg); if (!ctx) {
dev_err(&rpdev->dev, "unexpected message with NULL host_hdl received from src=%d\n",
src); return -EINVAL;
}
/* * if not already known, save copro instance context * to ensure re-entrance on copro side
*/ if (!ctx->copro_hdl)
ctx->copro_hdl = msg_to_copro_hdl(msg);
/* * all is fine, * update status & complete command
*/
ctx->cb_err = msg->err;
complete(&ctx->done);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.