Skip to content

Commit 977e6c8

Browse files
Srinivas-Kandagatlagregkh
authored andcommitted
misc: fastrpc: use correct spinlock variant
context spin lock can be interrupted from callback path so use correct spinlock so that we do not hit spinlock recursion. Fixes: c68cfb7 ("misc: fastrpc: Add support for context Invoke method") Signed-off-by: Srinivas Kandagatla <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 415a072 commit 977e6c8

File tree

1 file changed

+29
-19
lines changed

1 file changed

+29
-19
lines changed

drivers/misc/fastrpc.c

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ static void fastrpc_context_free(struct kref *ref)
283283
{
284284
struct fastrpc_invoke_ctx *ctx;
285285
struct fastrpc_channel_ctx *cctx;
286+
unsigned long flags;
286287
int i;
287288

288289
ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount);
@@ -294,9 +295,9 @@ static void fastrpc_context_free(struct kref *ref)
294295
if (ctx->buf)
295296
fastrpc_buf_free(ctx->buf);
296297

297-
spin_lock(&cctx->lock);
298+
spin_lock_irqsave(&cctx->lock, flags);
298299
idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4);
299-
spin_unlock(&cctx->lock);
300+
spin_unlock_irqrestore(&cctx->lock, flags);
300301

301302
kfree(ctx->maps);
302303
kfree(ctx);
@@ -326,6 +327,7 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
326327
{
327328
struct fastrpc_channel_ctx *cctx = user->cctx;
328329
struct fastrpc_invoke_ctx *ctx = NULL;
330+
unsigned long flags;
329331
int ret;
330332

331333
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -360,15 +362,15 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc(
360362
list_add_tail(&ctx->node, &user->pending);
361363
spin_unlock(&user->lock);
362364

363-
spin_lock(&cctx->lock);
365+
spin_lock_irqsave(&cctx->lock, flags);
364366
ret = idr_alloc_cyclic(&cctx->ctx_idr, ctx, 1,
365367
FASTRPC_CTX_MAX, GFP_ATOMIC);
366368
if (ret < 0) {
367-
spin_unlock(&cctx->lock);
369+
spin_unlock_irqrestore(&cctx->lock, flags);
368370
goto err_idr;
369371
}
370372
ctx->ctxid = ret << 4;
371-
spin_unlock(&cctx->lock);
373+
spin_unlock_irqrestore(&cctx->lock, flags);
372374

373375
kref_init(&ctx->refcount);
374376

@@ -948,27 +950,30 @@ static struct fastrpc_session_ctx *fastrpc_session_alloc(
948950
struct fastrpc_channel_ctx *cctx)
949951
{
950952
struct fastrpc_session_ctx *session = NULL;
953+
unsigned long flags;
951954
int i;
952955

953-
spin_lock(&cctx->lock);
956+
spin_lock_irqsave(&cctx->lock, flags);
954957
for (i = 0; i < cctx->sesscount; i++) {
955958
if (!cctx->session[i].used && cctx->session[i].valid) {
956959
cctx->session[i].used = true;
957960
session = &cctx->session[i];
958961
break;
959962
}
960963
}
961-
spin_unlock(&cctx->lock);
964+
spin_unlock_irqrestore(&cctx->lock, flags);
962965

963966
return session;
964967
}
965968

966969
static void fastrpc_session_free(struct fastrpc_channel_ctx *cctx,
967970
struct fastrpc_session_ctx *session)
968971
{
969-
spin_lock(&cctx->lock);
972+
unsigned long flags;
973+
974+
spin_lock_irqsave(&cctx->lock, flags);
970975
session->used = false;
971-
spin_unlock(&cctx->lock);
976+
spin_unlock_irqrestore(&cctx->lock, flags);
972977
}
973978

974979
static int fastrpc_release_current_dsp_process(struct fastrpc_user *fl)
@@ -994,12 +999,13 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
994999
struct fastrpc_channel_ctx *cctx = fl->cctx;
9951000
struct fastrpc_invoke_ctx *ctx, *n;
9961001
struct fastrpc_map *map, *m;
1002+
unsigned long flags;
9971003

9981004
fastrpc_release_current_dsp_process(fl);
9991005

1000-
spin_lock(&cctx->lock);
1006+
spin_lock_irqsave(&cctx->lock, flags);
10011007
list_del(&fl->user);
1002-
spin_unlock(&cctx->lock);
1008+
spin_unlock_irqrestore(&cctx->lock, flags);
10031009

10041010
if (fl->init_mem)
10051011
fastrpc_buf_free(fl->init_mem);
@@ -1027,6 +1033,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
10271033
{
10281034
struct fastrpc_channel_ctx *cctx = miscdev_to_cctx(filp->private_data);
10291035
struct fastrpc_user *fl = NULL;
1036+
unsigned long flags;
10301037

10311038
fl = kzalloc(sizeof(*fl), GFP_KERNEL);
10321039
if (!fl)
@@ -1050,9 +1057,9 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
10501057
return -EBUSY;
10511058
}
10521059

1053-
spin_lock(&cctx->lock);
1060+
spin_lock_irqsave(&cctx->lock, flags);
10541061
list_add_tail(&fl->user, &cctx->users);
1055-
spin_unlock(&cctx->lock);
1062+
spin_unlock_irqrestore(&cctx->lock, flags);
10561063

10571064
return 0;
10581065
}
@@ -1208,14 +1215,15 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
12081215
struct fastrpc_session_ctx *sess;
12091216
struct device *dev = &pdev->dev;
12101217
int i, sessions = 0;
1218+
unsigned long flags;
12111219

12121220
cctx = dev_get_drvdata(dev->parent);
12131221
if (!cctx)
12141222
return -EINVAL;
12151223

12161224
of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions);
12171225

1218-
spin_lock(&cctx->lock);
1226+
spin_lock_irqsave(&cctx->lock, flags);
12191227
sess = &cctx->session[cctx->sesscount];
12201228
sess->used = false;
12211229
sess->valid = true;
@@ -1236,7 +1244,7 @@ static int fastrpc_cb_probe(struct platform_device *pdev)
12361244
}
12371245
}
12381246
cctx->sesscount++;
1239-
spin_unlock(&cctx->lock);
1247+
spin_unlock_irqrestore(&cctx->lock, flags);
12401248
dma_set_mask(dev, DMA_BIT_MASK(32));
12411249

12421250
return 0;
@@ -1246,16 +1254,17 @@ static int fastrpc_cb_remove(struct platform_device *pdev)
12461254
{
12471255
struct fastrpc_channel_ctx *cctx = dev_get_drvdata(pdev->dev.parent);
12481256
struct fastrpc_session_ctx *sess = dev_get_drvdata(&pdev->dev);
1257+
unsigned long flags;
12491258
int i;
12501259

1251-
spin_lock(&cctx->lock);
1260+
spin_lock_irqsave(&cctx->lock, flags);
12521261
for (i = 1; i < FASTRPC_MAX_SESSIONS; i++) {
12531262
if (cctx->session[i].sid == sess->sid) {
12541263
cctx->session[i].valid = false;
12551264
cctx->sesscount--;
12561265
}
12571266
}
1258-
spin_unlock(&cctx->lock);
1267+
spin_unlock_irqrestore(&cctx->lock, flags);
12591268

12601269
return 0;
12611270
}
@@ -1337,11 +1346,12 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
13371346
{
13381347
struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev);
13391348
struct fastrpc_user *user;
1349+
unsigned long flags;
13401350

1341-
spin_lock(&cctx->lock);
1351+
spin_lock_irqsave(&cctx->lock, flags);
13421352
list_for_each_entry(user, &cctx->users, user)
13431353
fastrpc_notify_users(user);
1344-
spin_unlock(&cctx->lock);
1354+
spin_unlock_irqrestore(&cctx->lock, flags);
13451355

13461356
misc_deregister(&cctx->miscdev);
13471357
of_platform_depopulate(&rpdev->dev);

0 commit comments

Comments
 (0)