mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 23:24:22 -04:00
msm: adsprpc: Fix concurrency in early wake of fastrpc
Currently is_work_done flag is checked to free the context. There could be concurrency where is_work_done flag is set and context is added to async queue just before checking the flag. Propagate is_work_done status instead of checking flag directly to avoid race condition. Change-Id: I50d4b1d94499f07fa40608b5cf5c62ef3aeaa64b Signed-off-by: Himateja Reddy <hmreddy@codeaurora.org>
This commit is contained in:
parent
c322899f4a
commit
c29be08d5c
1 changed files with 23 additions and 8 deletions
|
|
@ -2616,7 +2616,8 @@ static inline int fastrpc_wait_for_response(struct smq_invoke_ctx *ctx,
|
|||
}
|
||||
|
||||
static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
|
||||
int *ptr_interrupted, uint32_t kernel, uint32_t async)
|
||||
int *ptr_interrupted, uint32_t kernel, uint32_t async,
|
||||
bool *ptr_isworkdone)
|
||||
{
|
||||
int interrupted = 0, err = 0;
|
||||
int jj;
|
||||
|
|
@ -2628,6 +2629,7 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
|
|||
if (!ctx) {
|
||||
/* This failure is not expected */
|
||||
err = *ptr_interrupted = EFAULT;
|
||||
*ptr_isworkdone = false;
|
||||
ADSPRPC_ERR("ctx is NULL, cannot wait for response err %d\n",
|
||||
err);
|
||||
return;
|
||||
|
|
@ -2652,8 +2654,11 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
|
|||
preempt_enable();
|
||||
if (async) {
|
||||
spin_lock_irqsave(&ctx->fl->aqlock, flags);
|
||||
if (!ctx->is_work_done)
|
||||
if (!ctx->is_work_done) {
|
||||
ctx->is_early_wakeup = false;
|
||||
*ptr_isworkdone = false;
|
||||
} else
|
||||
*ptr_isworkdone = true;
|
||||
spin_unlock_irqrestore(&ctx->fl->aqlock, flags);
|
||||
goto bail;
|
||||
} else if (!wait_resp) {
|
||||
|
|
@ -2673,14 +2678,18 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
|
|||
/* Wait for completion if poll on memory timoeut */
|
||||
if (!err) {
|
||||
ctx->is_work_done = true;
|
||||
*ptr_isworkdone = true;
|
||||
goto bail;
|
||||
}
|
||||
ADSPRPC_INFO("poll timeout for handle 0x%x, sc 0x%x\n",
|
||||
ctx->handle, ctx->sc);
|
||||
if (async) {
|
||||
spin_lock_irqsave(&ctx->fl->aqlock, flags);
|
||||
if (!ctx->is_work_done)
|
||||
if (!ctx->is_work_done) {
|
||||
ctx->is_early_wakeup = false;
|
||||
*ptr_isworkdone = false;
|
||||
} else
|
||||
*ptr_isworkdone = true;
|
||||
spin_unlock_irqrestore(&ctx->fl->aqlock, flags);
|
||||
goto bail;
|
||||
} else if (!ctx->is_work_done) {
|
||||
|
|
@ -2702,14 +2711,18 @@ static void fastrpc_wait_for_completion(struct smq_invoke_ctx *ctx,
|
|||
goto bail;
|
||||
} else {
|
||||
spin_lock_irqsave(&ctx->fl->aqlock, flags);
|
||||
if (!ctx->is_work_done)
|
||||
if (!ctx->is_work_done) {
|
||||
ctx->is_early_wakeup = false;
|
||||
*ptr_isworkdone = false;
|
||||
} else
|
||||
*ptr_isworkdone = true;
|
||||
spin_unlock_irqrestore(&ctx->fl->aqlock, flags);
|
||||
goto bail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
*ptr_interrupted = EBADR;
|
||||
*ptr_isworkdone = false;
|
||||
ADSPRPC_ERR(
|
||||
"unsupported response flags 0x%x for handle 0x%x, sc 0x%x\n",
|
||||
ctx->rsp_flags, ctx->handle, ctx->sc);
|
||||
|
|
@ -2747,7 +2760,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
|
|||
int err = 0, interrupted = 0, cid = -1;
|
||||
struct timespec64 invoket = {0};
|
||||
int64_t *perf_counter = NULL;
|
||||
bool isasyncinvoke = false;
|
||||
bool isasyncinvoke = false, isworkdone = false;
|
||||
|
||||
cid = fl->cid;
|
||||
VERIFY(err, cid >= ADSP_DOMAIN_ID && cid < NUM_CHANNELS &&
|
||||
|
|
@ -2821,7 +2834,7 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
|
|||
if (isasyncinvoke)
|
||||
goto invoke_end;
|
||||
wait:
|
||||
fastrpc_wait_for_completion(ctx, &interrupted, kernel, 0);
|
||||
fastrpc_wait_for_completion(ctx, &interrupted, kernel, 0, &isworkdone);
|
||||
VERIFY(err, 0 == (err = interrupted));
|
||||
if (err)
|
||||
goto bail;
|
||||
|
|
@ -2873,6 +2886,7 @@ static int fastrpc_wait_on_async_queue(
|
|||
struct smq_invoke_ctx *ctx = NULL, *ictx = NULL, *n = NULL;
|
||||
unsigned long flags;
|
||||
int64_t *perf_counter = NULL;
|
||||
bool isworkdone = false;
|
||||
|
||||
read_async_job:
|
||||
interrupted = wait_event_interruptible(fl->async_wait_queue,
|
||||
|
|
@ -2894,8 +2908,9 @@ read_async_job:
|
|||
}
|
||||
spin_unlock_irqrestore(&fl->aqlock, flags);
|
||||
if (ctx) {
|
||||
fastrpc_wait_for_completion(ctx, &interrupted, 0, 1);
|
||||
if (!ctx->is_work_done) {//In valid workdone state
|
||||
fastrpc_wait_for_completion(ctx, &interrupted, 0, 1,
|
||||
&isworkdone);
|
||||
if (!isworkdone) {//In valid workdone state
|
||||
ADSPRPC_DEBUG(
|
||||
"Async early wake response did not reach on time for thread %d handle 0x%x, sc 0x%x\n",
|
||||
ctx->pid, ctx->handle, ctx->sc);
|
||||
|
|
|
|||
Loading…
Reference in a new issue