Skip to content

Commit 2956f08

Browse files
authored
misc: fastrpc: Add missing bug fixes (#433)
misc: fastrpc: Add missing bug fixes
2 parents 31f8843 + d1a141e commit 2956f08

1 file changed

Lines changed: 72 additions & 61 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 72 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,8 @@ struct fastrpc_channel_ctx {
294294
struct kref refcount;
295295
/* Flag if dsp attributes are cached */
296296
bool valid_attributes;
297+
/* Flag if audio PD init mem was allocated */
298+
bool audio_init_mem;
297299
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
298300
struct fastrpc_device *secure_fdevice;
299301
struct fastrpc_device *fdevice;
@@ -414,6 +416,9 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
414416

415417
static void fastrpc_buf_free(struct fastrpc_buf *buf)
416418
{
419+
if (!buf)
420+
return;
421+
417422
dma_free_coherent(buf->dev, buf->size, buf->virt,
418423
FASTRPC_PHYS(buf->phys));
419424
kfree(buf);
@@ -531,8 +536,7 @@ static void fastrpc_context_free(struct kref *ref)
531536
for (i = 0; i < ctx->nbufs; i++)
532537
fastrpc_map_put(ctx->maps[i]);
533538

534-
if (ctx->buf)
535-
fastrpc_buf_free(ctx->buf);
539+
fastrpc_buf_free(ctx->buf);
536540

537541
spin_lock_irqsave(&cctx->lock, flags);
538542
idr_remove(&cctx->ctx_idr, ctx->ctxid >> 8);
@@ -1394,15 +1398,16 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
13941398
struct fastrpc_init_create_static init;
13951399
struct fastrpc_invoke_args *args;
13961400
struct fastrpc_phy_page pages[1];
1401+
struct fastrpc_channel_ctx *cctx = fl->cctx;
13971402
char *name;
13981403
int err;
1399-
bool scm_done = false;
14001404
struct {
14011405
int client_id;
14021406
u32 namelen;
14031407
u32 pageslen;
14041408
} inbuf;
14051409
u32 sc;
1410+
unsigned long flags;
14061411

14071412
args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
14081413
if (!args)
@@ -1423,33 +1428,10 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14231428
err = PTR_ERR(name);
14241429
goto err;
14251430
}
1426-
1427-
if (!fl->cctx->remote_heap) {
1428-
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
1429-
&fl->cctx->remote_heap);
1430-
if (err)
1431-
goto err_name;
1432-
1433-
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
1434-
if (fl->cctx->vmcount) {
1435-
u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
1436-
1437-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1438-
(u64)fl->cctx->remote_heap->size,
1439-
&src_perms,
1440-
fl->cctx->vmperms, fl->cctx->vmcount);
1441-
if (err) {
1442-
dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
1443-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1444-
goto err_map;
1445-
}
1446-
scm_done = true;
1447-
}
1448-
}
1449-
14501431
inbuf.client_id = fl->client_id;
14511432
inbuf.namelen = init.namelen;
14521433
inbuf.pageslen = 0;
1434+
14531435
fl->pd = USER_PD;
14541436

14551437
args[0].ptr = (u64)(uintptr_t)&inbuf;
@@ -1460,8 +1442,25 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14601442
args[1].length = inbuf.namelen;
14611443
args[1].fd = -1;
14621444

1463-
pages[0].addr = fl->cctx->remote_heap->phys;
1464-
pages[0].size = fl->cctx->remote_heap->size;
1445+
spin_lock_irqsave(&cctx->lock, flags);
1446+
if (!fl->cctx->audio_init_mem) {
1447+
if (!fl->cctx->remote_heap ||
1448+
!fl->cctx->remote_heap->phys ||
1449+
!fl->cctx->remote_heap->size) {
1450+
spin_unlock_irqrestore(&cctx->lock, flags);
1451+
err = -ENOMEM;
1452+
goto err;
1453+
}
1454+
1455+
pages[0].addr = fl->cctx->remote_heap->phys;
1456+
pages[0].size = fl->cctx->remote_heap->size;
1457+
fl->cctx->audio_init_mem = true;
1458+
inbuf.pageslen = 1;
1459+
} else {
1460+
pages[0].addr = 0;
1461+
pages[0].size = 0;
1462+
}
1463+
spin_unlock_irqrestore(&cctx->lock, flags);
14651464

14661465
args[2].ptr = (u64)(uintptr_t) pages;
14671466
args[2].length = sizeof(*pages);
@@ -1479,26 +1478,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
14791478

14801479
return 0;
14811480
err_invoke:
1482-
if (fl->cctx->vmcount && scm_done) {
1483-
u64 src_perms = 0;
1484-
struct qcom_scm_vmperm dst_perms;
1485-
u32 i;
1486-
1487-
for (i = 0; i < fl->cctx->vmcount; i++)
1488-
src_perms |= BIT(fl->cctx->vmperms[i].vmid);
1489-
1490-
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
1491-
dst_perms.perm = QCOM_SCM_PERM_RWX;
1492-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1493-
(u64)fl->cctx->remote_heap->size,
1494-
&src_perms, &dst_perms, 1);
1495-
if (err)
1496-
dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
1497-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1498-
}
1499-
err_map:
1500-
fastrpc_buf_free(fl->cctx->remote_heap);
1501-
err_name:
1481+
fl->cctx->audio_init_mem = false;
15021482
kfree(name);
15031483
err:
15041484
kfree(args);
@@ -1686,8 +1666,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
16861666
list_del(&fl->user);
16871667
spin_unlock_irqrestore(&cctx->lock, flags);
16881668

1689-
if (fl->init_mem)
1690-
fastrpc_buf_free(fl->init_mem);
1669+
fastrpc_buf_free(fl->init_mem);
16911670

16921671
list_for_each_entry_safe(ctx, n, &fl->pending, node) {
16931672
list_del(&ctx->node);
@@ -1958,9 +1937,6 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *
19581937
&args[0]);
19591938
if (!err) {
19601939
dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr);
1961-
spin_lock(&fl->lock);
1962-
list_del(&buf->node);
1963-
spin_unlock(&fl->lock);
19641940
fastrpc_buf_free(buf);
19651941
} else {
19661942
dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr);
@@ -1974,13 +1950,15 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
19741950
struct fastrpc_buf *buf = NULL, *iter, *b;
19751951
struct fastrpc_req_munmap req;
19761952
struct device *dev = fl->sctx->dev;
1953+
int err;
19771954

19781955
if (copy_from_user(&req, argp, sizeof(req)))
19791956
return -EFAULT;
19801957

19811958
spin_lock(&fl->lock);
19821959
list_for_each_entry_safe(iter, b, &fl->mmaps, node) {
19831960
if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) {
1961+
list_del(&iter->node);
19841962
buf = iter;
19851963
break;
19861964
}
@@ -1993,7 +1971,14 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
19931971
return -EINVAL;
19941972
}
19951973

1996-
return fastrpc_req_munmap_impl(fl, buf);
1974+
err = fastrpc_req_munmap_impl(fl, buf);
1975+
if (err) {
1976+
spin_lock(&fl->lock);
1977+
list_add_tail(&buf->node, &fl->mmaps);
1978+
spin_unlock(&fl->lock);
1979+
}
1980+
1981+
return err;
19971982
}
19981983

19991984
static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
@@ -2083,14 +2068,17 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
20832068

20842069
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
20852070
err = -EFAULT;
2086-
goto err_assign;
2071+
goto err_copy;
20872072
}
20882073

20892074
dev_dbg(dev, "mmap\t\tpt 0x%09lx OK [len 0x%08llx]\n",
20902075
buf->raddr, buf->size);
20912076

20922077
return 0;
2093-
2078+
err_copy:
2079+
spin_lock(&fl->lock);
2080+
list_del(&buf->node);
2081+
spin_unlock(&fl->lock);
20942082
err_assign:
20952083
fastrpc_req_munmap_impl(fl, buf);
20962084

@@ -2456,7 +2444,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24562444
}
24572445
}
24582446

2459-
if (domain_id == SDSP_DOMAIN_ID) {
2447+
if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) {
24602448
struct resource res;
24612449
u64 src_perms;
24622450

@@ -2467,7 +2455,15 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
24672455
qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms,
24682456
data->vmperms, data->vmcount);
24692457
}
2470-
2458+
if (domain_id == ADSP_DOMAIN_ID) {
2459+
data->remote_heap =
2460+
kzalloc(sizeof(*data->remote_heap), GFP_KERNEL);
2461+
if (!data->remote_heap)
2462+
return -ENOMEM;
2463+
2464+
data->remote_heap->phys = res.start;
2465+
data->remote_heap->size = resource_size(&res);
2466+
}
24712467
}
24722468

24732469
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
@@ -2547,6 +2543,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25472543
struct fastrpc_buf *buf, *b;
25482544
struct fastrpc_user *user;
25492545
unsigned long flags;
2546+
int err;
25502547

25512548
/* No invocations past this point */
25522549
spin_lock_irqsave(&cctx->lock, flags);
@@ -2564,8 +2561,22 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
25642561
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
25652562
list_del(&buf->node);
25662563

2567-
if (cctx->remote_heap)
2568-
fastrpc_buf_free(cctx->remote_heap);
2564+
if (cctx->remote_heap && cctx->vmcount) {
2565+
u64 src_perms = 0;
2566+
struct qcom_scm_vmperm dst_perms;
2567+
2568+
for (u32 i = 0; i < cctx->vmcount; i++)
2569+
src_perms |= BIT(cctx->vmperms[i].vmid);
2570+
2571+
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
2572+
dst_perms.perm = QCOM_SCM_PERM_RWX;
2573+
2574+
err = qcom_scm_assign_mem(cctx->remote_heap->phys,
2575+
cctx->remote_heap->size, &src_perms,
2576+
&dst_perms, 1);
2577+
if (!err)
2578+
fastrpc_buf_free(cctx->remote_heap);
2579+
}
25692580

25702581
of_platform_depopulate(&rpdev->dev);
25712582

0 commit comments

Comments
 (0)