Commit fdb8d00a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents fbd2e227 10df0398
Loading
Loading
Loading
Loading
+58 −31
Original line number Diff line number Diff line
@@ -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;

		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;
	}
+13 −0
Original line number Diff line number Diff line
@@ -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,