Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions drivers/misc/fastrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ struct fastrpc_session_ctx {
int sid;
bool used;
bool valid;
bool coherent;
};

struct fastrpc_channel_ctx {
Expand Down Expand Up @@ -1056,6 +1057,64 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
return 0;
}

static void fastrpc_flush_args(struct fastrpc_invoke_ctx *ctx)
{
union fastrpc_remote_arg *rpra = ctx->rpra;
int i, inbufs, outbufs;

inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);

for (i = 0; i < inbufs + outbufs; ++i) {
int raix = ctx->olaps[i].raix;
struct fastrpc_map *map = ctx->maps[raix];

if (raix + 1 > inbufs)
continue;
if (!map || !map->buf)
continue;

if (rpra[raix].buf.len && ctx->olaps[i].mstart) {
dma_buf_begin_cpu_access(map->buf, DMA_TO_DEVICE);
dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE);
}
}
}

static void fastrpc_inv_args(struct fastrpc_invoke_ctx *ctx)
{
union fastrpc_remote_arg *rpra = ctx->rpra;
int i, inbufs, outbufs;

inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);

for (i = 0; i < inbufs + outbufs; ++i) {
int raix = ctx->olaps[i].raix;
struct fastrpc_map *map = ctx->maps[raix];

if (raix + 1 <= inbufs)
continue;
if (!rpra[raix].buf.len)
continue;
if (!map || !map->buf)
continue;

/*
* Skip invalidation if the argument overlaps with the
* RPC control header page.
*/
if (((uintptr_t)rpra & PAGE_MASK) ==
((uintptr_t)rpra[raix].buf.pv & PAGE_MASK))
continue;

if (ctx->olaps[i].mstart) {
dma_buf_begin_cpu_access(map->buf, DMA_FROM_DEVICE);
dma_buf_end_cpu_access(map->buf, DMA_TO_DEVICE);
}
}
}

static struct fastrpc_invoke_buf *fastrpc_invoke_buf_start(union fastrpc_remote_arg *pra, int len)
{
return (struct fastrpc_invoke_buf *)(&pra[len]);
Expand Down Expand Up @@ -1179,6 +1238,9 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
}
}

if (!ctx->fl->sctx->coherent)
fastrpc_flush_args(ctx);

for (i = ctx->nbufs; i < ctx->nscalars; ++i) {
list[i].num = ctx->args[i].length ? 1 : 0;
list[i].pgidx = i;
Expand Down Expand Up @@ -1404,6 +1466,9 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
}
/* make sure that all memory writes by DSP are seen by CPU */
dma_rmb();
if (!fl->sctx->coherent)
fastrpc_inv_args(ctx);

/* populate all the output buffers with results */
err = fastrpc_put_args(ctx, kernel);
if (err)
Expand Down Expand Up @@ -2334,6 +2399,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
sess->used = false;
sess->valid = true;
sess->dev = dev;
sess->coherent = of_property_read_bool(dev->of_node, "dma-coherent");
dev_set_drvdata(dev, sess);

if (of_property_read_u32(dev->of_node, "reg", &sess->sid))
Expand Down