Skip to content

Commit fdb8d00

Browse files
committed
Merge tag 'char-misc-6.18-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc fixes from Greg KH: "Here are some small nvmem and fastrpc fixes that missed the cut-off to get into 6.17-final, due to me being slow in getting them out, my fault, not the maintainers of these subsystems :( Anyway, better late than never. Changes included in here are: - nvmem fix for automatic module loading - fastrpc driver fixes for reported issues All of these have been in linux-next for weeks (4?) with no reported issues" * tag 'char-misc-6.18-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: misc: fastrpc: Skip reference for DMA handles misc: fastrpc: fix possible map leak in fastrpc_put_args misc: fastrpc: Fix fastrpc_map_lookup operation misc: fastrpc: Save actual DMA size in fastrpc_map structure nvmem: layouts: fix automatic module loading
2 parents fbd2e22 + 10df039 commit fdb8d00

2 files changed

Lines changed: 71 additions & 31 deletions

File tree

drivers/misc/fastrpc.c

Lines changed: 58 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,11 @@ static void fastrpc_free_map(struct kref *ref)
320320

321321
perm.vmid = QCOM_SCM_VMID_HLOS;
322322
perm.perm = QCOM_SCM_PERM_RWX;
323-
err = qcom_scm_assign_mem(map->phys, map->size,
323+
err = qcom_scm_assign_mem(map->phys, map->len,
324324
&src_perms, &perm, 1);
325325
if (err) {
326326
dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
327-
map->phys, map->size, err);
327+
map->phys, map->len, err);
328328
return;
329329
}
330330
}
@@ -360,26 +360,21 @@ static int fastrpc_map_get(struct fastrpc_map *map)
360360

361361

362362
static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
363-
struct fastrpc_map **ppmap, bool take_ref)
363+
struct fastrpc_map **ppmap)
364364
{
365-
struct fastrpc_session_ctx *sess = fl->sctx;
366365
struct fastrpc_map *map = NULL;
366+
struct dma_buf *buf;
367367
int ret = -ENOENT;
368368

369+
buf = dma_buf_get(fd);
370+
if (IS_ERR(buf))
371+
return PTR_ERR(buf);
372+
369373
spin_lock(&fl->lock);
370374
list_for_each_entry(map, &fl->maps, node) {
371-
if (map->fd != fd)
375+
if (map->fd != fd || map->buf != buf)
372376
continue;
373377

374-
if (take_ref) {
375-
ret = fastrpc_map_get(map);
376-
if (ret) {
377-
dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
378-
__func__, fd, ret);
379-
break;
380-
}
381-
}
382-
383378
*ppmap = map;
384379
ret = 0;
385380
break;
@@ -749,16 +744,14 @@ static const struct dma_buf_ops fastrpc_dma_buf_ops = {
749744
.release = fastrpc_release,
750745
};
751746

752-
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
747+
static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
753748
u64 len, u32 attr, struct fastrpc_map **ppmap)
754749
{
755750
struct fastrpc_session_ctx *sess = fl->sctx;
756751
struct fastrpc_map *map = NULL;
757752
struct sg_table *table;
758-
int err = 0;
759-
760-
if (!fastrpc_map_lookup(fl, fd, ppmap, true))
761-
return 0;
753+
struct scatterlist *sgl = NULL;
754+
int err = 0, sgl_index = 0;
762755

763756
map = kzalloc(sizeof(*map), GFP_KERNEL);
764757
if (!map)
@@ -795,7 +788,15 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
795788
map->phys = sg_dma_address(map->table->sgl);
796789
map->phys += ((u64)fl->sctx->sid << 32);
797790
}
798-
map->size = len;
791+
for_each_sg(map->table->sgl, sgl, map->table->nents,
792+
sgl_index)
793+
map->size += sg_dma_len(sgl);
794+
if (len > map->size) {
795+
dev_dbg(sess->dev, "Bad size passed len 0x%llx map size 0x%llx\n",
796+
len, map->size);
797+
err = -EINVAL;
798+
goto map_err;
799+
}
799800
map->va = sg_virt(map->table->sgl);
800801
map->len = len;
801802

@@ -812,10 +813,10 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
812813
dst_perms[1].vmid = fl->cctx->vmperms[0].vmid;
813814
dst_perms[1].perm = QCOM_SCM_PERM_RWX;
814815
map->attr = attr;
815-
err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2);
816+
err = qcom_scm_assign_mem(map->phys, (u64)map->len, &src_perms, dst_perms, 2);
816817
if (err) {
817818
dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
818-
map->phys, map->size, err);
819+
map->phys, map->len, err);
819820
goto map_err;
820821
}
821822
}
@@ -836,6 +837,24 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
836837
return err;
837838
}
838839

840+
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
841+
u64 len, u32 attr, struct fastrpc_map **ppmap)
842+
{
843+
struct fastrpc_session_ctx *sess = fl->sctx;
844+
int err = 0;
845+
846+
if (!fastrpc_map_lookup(fl, fd, ppmap)) {
847+
if (!fastrpc_map_get(*ppmap))
848+
return 0;
849+
dev_dbg(sess->dev, "%s: Failed to get map fd=%d\n",
850+
__func__, fd);
851+
}
852+
853+
err = fastrpc_map_attach(fl, fd, len, attr, ppmap);
854+
855+
return err;
856+
}
857+
839858
/*
840859
* Fastrpc payload buffer with metadata looks like:
841860
*
@@ -908,8 +927,12 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
908927
ctx->args[i].length == 0)
909928
continue;
910929

911-
err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
912-
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
930+
if (i < ctx->nbufs)
931+
err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
932+
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
933+
else
934+
err = fastrpc_map_attach(ctx->fl, ctx->args[i].fd,
935+
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
913936
if (err) {
914937
dev_err(dev, "Error Creating map %d\n", err);
915938
return -EINVAL;
@@ -1068,6 +1091,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
10681091
struct fastrpc_phy_page *pages;
10691092
u64 *fdlist;
10701093
int i, inbufs, outbufs, handles;
1094+
int ret = 0;
10711095

10721096
inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
10731097
outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);
@@ -1083,23 +1107,26 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
10831107
u64 len = rpra[i].buf.len;
10841108

10851109
if (!kernel) {
1086-
if (copy_to_user((void __user *)dst, src, len))
1087-
return -EFAULT;
1110+
if (copy_to_user((void __user *)dst, src, len)) {
1111+
ret = -EFAULT;
1112+
goto cleanup_fdlist;
1113+
}
10881114
} else {
10891115
memcpy(dst, src, len);
10901116
}
10911117
}
10921118
}
10931119

1120+
cleanup_fdlist:
10941121
/* Clean up fdlist which is updated by DSP */
10951122
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
10961123
if (!fdlist[i])
10971124
break;
1098-
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
1125+
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
10991126
fastrpc_map_put(mmap);
11001127
}
11011128

1102-
return 0;
1129+
return ret;
11031130
}
11041131

11051132
static int fastrpc_invoke_send(struct fastrpc_session_ctx *sctx,
@@ -2031,7 +2058,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
20312058
args[0].length = sizeof(req_msg);
20322059

20332060
pages.addr = map->phys;
2034-
pages.size = map->size;
2061+
pages.size = map->len;
20352062

20362063
args[1].ptr = (u64) (uintptr_t) &pages;
20372064
args[1].length = sizeof(pages);
@@ -2046,7 +2073,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
20462073
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]);
20472074
if (err) {
20482075
dev_err(dev, "mem mmap error, fd %d, vaddr %llx, size %lld\n",
2049-
req.fd, req.vaddrin, map->size);
2076+
req.fd, req.vaddrin, map->len);
20502077
goto err_invoke;
20512078
}
20522079

@@ -2059,7 +2086,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
20592086
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
20602087
/* unmap the memory and release the buffer */
20612088
req_unmap.vaddr = (uintptr_t) rsp_msg.vaddr;
2062-
req_unmap.length = map->size;
2089+
req_unmap.length = map->len;
20632090
fastrpc_req_mem_unmap_impl(fl, &req_unmap);
20642091
return -EFAULT;
20652092
}

drivers/nvmem/layouts.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,24 @@ static void nvmem_layout_bus_remove(struct device *dev)
4545
return drv->remove(layout);
4646
}
4747

48+
static int nvmem_layout_bus_uevent(const struct device *dev,
49+
struct kobj_uevent_env *env)
50+
{
51+
int ret;
52+
53+
ret = of_device_uevent_modalias(dev, env);
54+
if (ret != ENODEV)
55+
return ret;
56+
57+
return 0;
58+
}
59+
4860
static const struct bus_type nvmem_layout_bus_type = {
4961
.name = "nvmem-layout",
5062
.match = nvmem_layout_bus_match,
5163
.probe = nvmem_layout_bus_probe,
5264
.remove = nvmem_layout_bus_remove,
65+
.uevent = nvmem_layout_bus_uevent,
5366
};
5467

5568
int __nvmem_layout_driver_register(struct nvmem_layout_driver *drv,

0 commit comments

Comments
 (0)