diff options
author | Thierry Escande <thierry.escande@linaro.org> | 2019-03-07 11:12:22 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-03-27 18:09:57 +0100 |
commit | 8e7389c79b40ed44c855193bfb46b496ac25676f (patch) | |
tree | 05a2af592e1636b77e39a6785c6f9bddcddbc627 /drivers/misc/fastrpc.c | |
parent | misc: rtsx: clean up some indenting (diff) | |
download | linux-8e7389c79b40ed44c855193bfb46b496ac25676f.tar.xz linux-8e7389c79b40ed44c855193bfb46b496ac25676f.zip |
misc: fastrpc: Avoid free of DMA buffer in interrupt context
When the remote DSP invocation is interrupted by the user, the
associated DMA buffer can be freed in interrupt context causing a kernel
BUG.
This patch adds a worker thread associated to the fastrpc context. It
is scheduled in the rpmsg callback to decrease its refcount out of the
interrupt context.
Fixes: c68cfb718c8f ("misc: fastrpc: Add support for context Invoke method")
Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/fastrpc.c')
-rw-r--r-- | drivers/misc/fastrpc.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 39f832d27288..6483b881f7e4 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -149,6 +149,7 @@ struct fastrpc_invoke_ctx { struct kref refcount; struct list_head node; /* list of ctxs */ struct completion work; + struct work_struct put_work; struct fastrpc_msg msg; struct fastrpc_user *fl; struct fastrpc_remote_arg *rpra; @@ -311,6 +312,14 @@ static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx) kref_put(&ctx->refcount, fastrpc_context_free); } +static void fastrpc_context_put_wq(struct work_struct *work) +{ + struct fastrpc_invoke_ctx *ctx = + container_of(work, struct fastrpc_invoke_ctx, put_work); + + fastrpc_context_put(ctx); +} + static struct fastrpc_invoke_ctx *fastrpc_context_alloc( struct fastrpc_user *user, u32 kernel, u32 sc, struct fastrpc_invoke_args *args) @@ -345,6 +354,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( ctx->tgid = user->tgid; ctx->cctx = cctx; init_completion(&ctx->work); + INIT_WORK(&ctx->put_work, fastrpc_context_put_wq); spin_lock(&user->lock); list_add_tail(&ctx->node, &user->pending); @@ -1349,7 +1359,13 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, ctx->retval = rsp->retval; complete(&ctx->work); - fastrpc_context_put(ctx); + + /* + * The DMA buffer associated with the context cannot be freed in + * interrupt context so schedule it through a worker thread to + * avoid a kernel BUG. + */ + schedule_work(&ctx->put_work); return 0; } |