Commit 8e7389c7 authored by Thierry Escande's avatar Thierry Escande Committed by Greg Kroah-Hartman

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: c68cfb71 ("misc: fastrpc: Add support for context Invoke method")
Signed-off-by: default avatarThierry Escande <thierry.escande@linaro.org>
Signed-off-by: default avatarSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 34bf9ce9
...@@ -149,6 +149,7 @@ struct fastrpc_invoke_ctx { ...@@ -149,6 +149,7 @@ struct fastrpc_invoke_ctx {
struct kref refcount; struct kref refcount;
struct list_head node; /* list of ctxs */ struct list_head node; /* list of ctxs */
struct completion work; struct completion work;
struct work_struct put_work;
struct fastrpc_msg msg; struct fastrpc_msg msg;
struct fastrpc_user *fl; struct fastrpc_user *fl;
struct fastrpc_remote_arg *rpra; struct fastrpc_remote_arg *rpra;
...@@ -311,6 +312,14 @@ static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx) ...@@ -311,6 +312,14 @@ static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx)
kref_put(&ctx->refcount, fastrpc_context_free); 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( static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
struct fastrpc_user *user, u32 kernel, u32 sc, struct fastrpc_user *user, u32 kernel, u32 sc,
struct fastrpc_invoke_args *args) struct fastrpc_invoke_args *args)
...@@ -345,6 +354,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( ...@@ -345,6 +354,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
ctx->tgid = user->tgid; ctx->tgid = user->tgid;
ctx->cctx = cctx; ctx->cctx = cctx;
init_completion(&ctx->work); init_completion(&ctx->work);
INIT_WORK(&ctx->put_work, fastrpc_context_put_wq);
spin_lock(&user->lock); spin_lock(&user->lock);
list_add_tail(&ctx->node, &user->pending); list_add_tail(&ctx->node, &user->pending);
...@@ -1349,7 +1359,13 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, ...@@ -1349,7 +1359,13 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
ctx->retval = rsp->retval; ctx->retval = rsp->retval;
complete(&ctx->work); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment