Skip to content

Commit 12ea159

Browse files
committed
FROMLIST: misc: fastrpc: Move all remote heap allocations to a new list
Remote heap allocations are not organized in a maintainable manner, leading to potential issues with memory management. As the remote heap allocations are maintained in fl mmaps list, the allocations will go away if the audio daemon process is killed but there are chances that audio PD might still be using the memory. Move all remote heap allocations to a dedicated list where the entries are cleaned only for user requests and subsystem shutdown. Link: https://lore.kernel.org/all/20250513042825.2147985-3-ekansh.gupta@oss.qualcomm.com/ Fixes: 0871561 ("misc: fastrpc: Add support for audiopd") Cc: stable@kernel.org Signed-off-by: Ekansh Gupta <ekansh.gupta@oss.qualcomm.com>
1 parent 7479b77 commit 12ea159

1 file changed

Lines changed: 72 additions & 21 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 72 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -273,10 +273,12 @@ struct fastrpc_channel_ctx {
273273
struct kref refcount;
274274
/* Flag if dsp attributes are cached */
275275
bool valid_attributes;
276+
/* Flag if audio PD init mem was allocated */
277+
bool audio_init_mem;
276278
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
277279
struct fastrpc_device *secure_fdevice;
278280
struct fastrpc_device *fdevice;
279-
struct fastrpc_buf *remote_heap;
281+
struct list_head rhmaps;
280282
struct list_head invoke_interrupted_mmaps;
281283
bool secure;
282284
bool unsigned_support;
@@ -1237,12 +1239,47 @@ static bool is_session_rejected(struct fastrpc_user *fl, bool unsigned_pd_reques
12371239
return false;
12381240
}
12391241

1242+
static void fastrpc_cleanup_rhmaps(struct fastrpc_channel_ctx *cctx)
1243+
{
1244+
struct fastrpc_buf *buf, *b;
1245+
struct list_head temp_list;
1246+
int err;
1247+
unsigned long flags;
1248+
1249+
INIT_LIST_HEAD(&temp_list);
1250+
1251+
spin_lock_irqsave(&cctx->lock, flags);
1252+
list_splice_init(&cctx->rhmaps, &temp_list);
1253+
spin_unlock_irqrestore(&cctx->lock, flags);
1254+
1255+
list_for_each_entry_safe(buf, b, &temp_list, node) {
1256+
if (cctx->vmcount) {
1257+
u64 src_perms = 0;
1258+
struct qcom_scm_vmperm dst_perms;
1259+
u32 i;
1260+
1261+
for (i = 0; i < cctx->vmcount; i++)
1262+
src_perms |= BIT(cctx->vmperms[i].vmid);
1263+
1264+
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
1265+
dst_perms.perm = QCOM_SCM_PERM_RWX;
1266+
err = qcom_scm_assign_mem(buf->phys, (u64)buf->size,
1267+
&src_perms, &dst_perms, 1);
1268+
if (err)
1269+
continue;
1270+
}
1271+
fastrpc_buf_free(buf);
1272+
}
1273+
}
1274+
12401275
static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
12411276
char __user *argp)
12421277
{
12431278
struct fastrpc_init_create_static init;
12441279
struct fastrpc_invoke_args *args;
12451280
struct fastrpc_phy_page pages[1];
1281+
struct fastrpc_buf *buf = NULL;
1282+
u64 phys = 0, size = 0;
12461283
char *name;
12471284
int err;
12481285
bool scm_done = false;
@@ -1252,6 +1289,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
12521289
u32 pageslen;
12531290
} inbuf;
12541291
u32 sc;
1292+
unsigned long flags;
12551293

12561294
args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
12571295
if (!args)
@@ -1273,26 +1311,30 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
12731311
goto err;
12741312
}
12751313

1276-
if (!fl->cctx->remote_heap) {
1314+
if (!fl->cctx->audio_init_mem) {
12771315
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
1278-
&fl->cctx->remote_heap);
1316+
&buf);
12791317
if (err)
12801318
goto err_name;
12811319

1320+
phys = buf->phys;
1321+
size = buf->size;
12821322
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
12831323
if (fl->cctx->vmcount) {
12841324
u64 src_perms = BIT(QCOM_SCM_VMID_HLOS);
12851325

1286-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1287-
(u64)fl->cctx->remote_heap->size,
1288-
&src_perms,
1289-
fl->cctx->vmperms, fl->cctx->vmcount);
1326+
err = qcom_scm_assign_mem(phys, size, &src_perms,
1327+
fl->cctx->vmperms, fl->cctx->vmcount);
12901328
if (err) {
12911329
dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
1292-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1330+
phys, size, err);
12931331
goto err_map;
12941332
}
12951333
scm_done = true;
1334+
spin_lock_irqsave(&fl->cctx->lock, flags);
1335+
list_add_tail(&buf->node, &fl->cctx->rhmaps);
1336+
spin_unlock_irqrestore(&fl->cctx->lock, flags);
1337+
fl->cctx->audio_init_mem = true;
12961338
}
12971339
}
12981340

@@ -1309,8 +1351,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
13091351
args[1].length = inbuf.namelen;
13101352
args[1].fd = -1;
13111353

1312-
pages[0].addr = fl->cctx->remote_heap->phys;
1313-
pages[0].size = fl->cctx->remote_heap->size;
1354+
pages[0].addr = phys;
1355+
pages[0].size = size;
13141356

13151357
args[2].ptr = (u64)(uintptr_t) pages;
13161358
args[2].length = sizeof(*pages);
@@ -1328,6 +1370,11 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
13281370

13291371
return 0;
13301372
err_invoke:
1373+
if (buf) {
1374+
spin_lock_irqsave(&fl->cctx->lock, flags);
1375+
list_del(&buf->node);
1376+
spin_unlock_irqrestore(&fl->cctx->lock, flags);
1377+
}
13311378
if (fl->cctx->vmcount && scm_done) {
13321379
u64 src_perms = 0;
13331380
struct qcom_scm_vmperm dst_perms;
@@ -1338,15 +1385,15 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
13381385

13391386
dst_perms.vmid = QCOM_SCM_VMID_HLOS;
13401387
dst_perms.perm = QCOM_SCM_PERM_RWX;
1341-
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
1342-
(u64)fl->cctx->remote_heap->size,
1343-
&src_perms, &dst_perms, 1);
1388+
err = qcom_scm_assign_mem(phys, size, &src_perms,
1389+
&dst_perms, 1);
13441390
if (err)
13451391
dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
1346-
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
1392+
phys, size, err);
13471393
}
13481394
err_map:
1349-
fastrpc_buf_free(fl->cctx->remote_heap);
1395+
fl->cctx->audio_init_mem = false;
1396+
fastrpc_buf_free(buf);
13501397
err_name:
13511398
kfree(name);
13521399
err:
@@ -1869,6 +1916,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
18691916
struct device *dev = fl->sctx->dev;
18701917
int err;
18711918
u32 sc;
1919+
unsigned long flags;
18721920

18731921
if (copy_from_user(&req, argp, sizeof(req)))
18741922
return -EFAULT;
@@ -1937,12 +1985,15 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
19371985
buf->phys, buf->size, err);
19381986
goto err_assign;
19391987
}
1988+
spin_lock_irqsave(&fl->cctx->lock, flags);
1989+
list_add_tail(&buf->node, &fl->cctx->rhmaps);
1990+
spin_unlock_irqrestore(&fl->cctx->lock, flags);
1991+
} else {
1992+
spin_lock(&fl->lock);
1993+
list_add_tail(&buf->node, &fl->mmaps);
1994+
spin_unlock(&fl->lock);
19401995
}
19411996

1942-
spin_lock(&fl->lock);
1943-
list_add_tail(&buf->node, &fl->mmaps);
1944-
spin_unlock(&fl->lock);
1945-
19461997
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
19471998
err = -EFAULT;
19481999
goto err_assign;
@@ -2362,6 +2413,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
23622413
rdev->dma_mask = &data->dma_mask;
23632414
dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
23642415
INIT_LIST_HEAD(&data->users);
2416+
INIT_LIST_HEAD(&data->rhmaps);
23652417
INIT_LIST_HEAD(&data->invoke_interrupted_mmaps);
23662418
spin_lock_init(&data->lock);
23672419
idr_init(&data->ctx_idr);
@@ -2420,8 +2472,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
24202472
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
24212473
list_del(&buf->node);
24222474

2423-
if (cctx->remote_heap)
2424-
fastrpc_buf_free(cctx->remote_heap);
2475+
fastrpc_cleanup_rhmaps(cctx);
24252476

24262477
of_platform_depopulate(&rpdev->dev);
24272478

0 commit comments

Comments
 (0)