Char/Misc fixes for 6.18-rc1

Here are some small nvmem and fastrpc fixes for 6.18-rc1.  They 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.
 
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 -----BEGIN PGP SIGNATURE-----
 
 iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCaOUMwg8cZ3JlZ0Brcm9h
 aC5jb20ACgkQMUfUDdst+yletACgvGqfpfSAd3c08ex6F9eDNsQ1aAcAn2p+h0nL
 Xu/ja1YO8z+PBS6ji2Cz
 =ILvk
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Linus Torvalds 2025-10-07 12:13:26 -07:00
commit fdb8d00af9
2 changed files with 71 additions and 31 deletions

View File

@ -320,11 +320,11 @@ static void fastrpc_free_map(struct kref *ref)
perm.vmid = QCOM_SCM_VMID_HLOS;
perm.perm = QCOM_SCM_PERM_RWX;
err = qcom_scm_assign_mem(map->phys, map->size,
err = qcom_scm_assign_mem(map->phys, map->len,
&src_perms, &perm, 1);
if (err) {
dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n",
map->phys, map->size, err);
map->phys, map->len, err);
return;
}
}
@ -360,26 +360,21 @@ static int fastrpc_map_get(struct fastrpc_map *map)
static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
struct fastrpc_map **ppmap, bool take_ref)
struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
struct dma_buf *buf;
int ret = -ENOENT;
buf = dma_buf_get(fd);
if (IS_ERR(buf))
return PTR_ERR(buf);
spin_lock(&fl->lock);
list_for_each_entry(map, &fl->maps, node) {
if (map->fd != fd)
if (map->fd != fd || map->buf != buf)
continue;
if (take_ref) {
ret = fastrpc_map_get(map);
if (ret) {
dev_dbg(sess->dev, "%s: Failed to get map fd=%d ret=%d\n",
__func__, fd, ret);
break;
}
}
*ppmap = map;
ret = 0;
break;
@ -749,16 +744,14 @@ static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.release = fastrpc_release,
};
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
struct fastrpc_map *map = NULL;
struct sg_table *table;
int err = 0;
if (!fastrpc_map_lookup(fl, fd, ppmap, true))
return 0;
struct scatterlist *sgl = NULL;
int err = 0, sgl_index = 0;
map = kzalloc(sizeof(*map), GFP_KERNEL);
if (!map)
@ -795,7 +788,15 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
map->phys = sg_dma_address(map->table->sgl);
map->phys += ((u64)fl->sctx->sid << 32);
}
map->size = len;
for_each_sg(map->table->sgl, sgl, map->table->nents,
sgl_index)
map->size += sg_dma_len(sgl);
if (len > map->size) {
dev_dbg(sess->dev, "Bad size passed len 0x%llx map size 0x%llx\n",
len, map->size);
err = -EINVAL;
goto map_err;
}
map->va = sg_virt(map->table->sgl);
map->len = len;
@ -812,10 +813,10 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
dst_perms[1].vmid = fl->cctx->vmperms[0].vmid;
dst_perms[1].perm = QCOM_SCM_PERM_RWX;
map->attr = attr;
err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2);
err = qcom_scm_assign_mem(map->phys, (u64)map->len, &src_perms, dst_perms, 2);
if (err) {
dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d\n",
map->phys, map->size, err);
map->phys, map->len, err);
goto map_err;
}
}
@ -836,6 +837,24 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
return err;
}
static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
struct fastrpc_session_ctx *sess = fl->sctx;
int err = 0;
if (!fastrpc_map_lookup(fl, fd, ppmap)) {
if (!fastrpc_map_get(*ppmap))
return 0;
dev_dbg(sess->dev, "%s: Failed to get map fd=%d\n",
__func__, fd);
}
err = fastrpc_map_attach(fl, fd, len, attr, ppmap);
return err;
}
/*
* Fastrpc payload buffer with metadata looks like:
*
@ -908,8 +927,12 @@ static int fastrpc_create_maps(struct fastrpc_invoke_ctx *ctx)
ctx->args[i].length == 0)
continue;
err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
if (i < ctx->nbufs)
err = fastrpc_map_create(ctx->fl, ctx->args[i].fd,
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
else
err = fastrpc_map_attach(ctx->fl, ctx->args[i].fd,
ctx->args[i].length, ctx->args[i].attr, &ctx->maps[i]);
if (err) {
dev_err(dev, "Error Creating map %d\n", err);
return -EINVAL;
@ -1068,6 +1091,7 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
struct fastrpc_phy_page *pages;
u64 *fdlist;
int i, inbufs, outbufs, handles;
int ret = 0;
inbufs = REMOTE_SCALARS_INBUFS(ctx->sc);
outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc);
@ -1083,23 +1107,26 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx,
u64 len = rpra[i].buf.len;
if (!kernel) {
if (copy_to_user((void __user *)dst, src, len))
return -EFAULT;
if (copy_to_user((void __user *)dst, src, len)) {
ret = -EFAULT;
goto cleanup_fdlist;
}
} else {
memcpy(dst, src, len);
}
}
}
cleanup_fdlist:
/* Clean up fdlist which is updated by DSP */
for (i = 0; i < FASTRPC_MAX_FDLIST; i++) {
if (!fdlist[i])
break;
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap, false))
if (!fastrpc_map_lookup(fl, (int)fdlist[i], &mmap))
fastrpc_map_put(mmap);
}
return 0;
return ret;
}
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)
args[0].length = sizeof(req_msg);
pages.addr = map->phys;
pages.size = map->size;
pages.size = map->len;
args[1].ptr = (u64) (uintptr_t) &pages;
args[1].length = sizeof(pages);
@ -2046,7 +2073,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE, sc, &args[0]);
if (err) {
dev_err(dev, "mem mmap error, fd %d, vaddr %llx, size %lld\n",
req.fd, req.vaddrin, map->size);
req.fd, req.vaddrin, map->len);
goto err_invoke;
}
@ -2059,7 +2086,7 @@ static int fastrpc_req_mem_map(struct fastrpc_user *fl, char __user *argp)
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
/* unmap the memory and release the buffer */
req_unmap.vaddr = (uintptr_t) rsp_msg.vaddr;
req_unmap.length = map->size;
req_unmap.length = map->len;
fastrpc_req_mem_unmap_impl(fl, &req_unmap);
return -EFAULT;
}

View File

@ -45,11 +45,24 @@ static void nvmem_layout_bus_remove(struct device *dev)
return drv->remove(layout);
}
static int nvmem_layout_bus_uevent(const struct device *dev,
struct kobj_uevent_env *env)
{
int ret;
ret = of_device_uevent_modalias(dev, env);
if (ret != ENODEV)
return ret;
return 0;
}
static const struct bus_type nvmem_layout_bus_type = {
.name = "nvmem-layout",
.match = nvmem_layout_bus_match,
.probe = nvmem_layout_bus_probe,
.remove = nvmem_layout_bus_remove,
.uevent = nvmem_layout_bus_uevent,
};
int __nvmem_layout_driver_register(struct nvmem_layout_driver *drv,