Merge tag 'char-misc-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver updates from Greg KH: "Here is the large set of char/misc and other driver subsystem changes for 6.2-rc1. Nothing earth-shattering in here at all, just a lot of new driver development and minor fixes. Highlights include: - fastrpc driver updates - iio new drivers and updates - habanalabs driver updates for new hardware and features - slimbus driver updates - speakup module parameters added to aid in boot time configuration - i2c probe_new conversions for lots of different drivers - other small driver fixes and additions One semi-interesting change in here is the increase of the number of misc dynamic minors available to 1048448 to handle new huge-cpu systems. All of these have been in linux-next for a while with no reported problems" * tag 'char-misc-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (521 commits) extcon: usbc-tusb320: Convert to i2c's .probe_new() extcon: rt8973: Convert to i2c's .probe_new() extcon: fsa9480: Convert to i2c's .probe_new() extcon: max77843: Replace irqchip mask_invert with unmask_base chardev: fix error handling in cdev_device_add() mcb: mcb-parse: fix error handing in chameleon_parse_gdd() drivers: mcb: fix resource leak in mcb_probe() coresight: etm4x: fix repeated words in comments coresight: cti: Fix null pointer error on CTI init before ETM coresight: trbe: remove cpuhp instance node before remove cpuhp state counter: stm32-lptimer-cnt: fix the check on arr and cmp registers update misc: fastrpc: Add dma_mask to fastrpc_channel_ctx misc: fastrpc: Add mmap request assigning for static PD pool misc: fastrpc: Safekeep mmaps on interrupted invoke misc: fastrpc: Add support for audiopd misc: fastrpc: Rework fastrpc_req_munmap misc: fastrpc: Use fastrpc_map_put in fastrpc_map_create on fail misc: fastrpc: Add fastrpc_remote_heap_alloc misc: fastrpc: Add reserved mem support misc: fastrpc: Rename audio protection domain to root ...
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/qcom_scm.h>
|
||||
#include <uapi/misc/fastrpc.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
|
||||
#define ADSP_DOMAIN_ID (0)
|
||||
#define MDSP_DOMAIN_ID (1)
|
||||
@@ -37,8 +38,20 @@
|
||||
#define FASTRPC_DSP_UTILITIES_HANDLE 2
|
||||
#define FASTRPC_CTXID_MASK (0xFF0)
|
||||
#define INIT_FILELEN_MAX (2 * 1024 * 1024)
|
||||
#define INIT_FILE_NAMELEN_MAX (128)
|
||||
#define FASTRPC_DEVICE_NAME "fastrpc"
|
||||
|
||||
/* Add memory to static PD pool, protection thru XPU */
|
||||
#define ADSP_MMAP_HEAP_ADDR 4
|
||||
/* MAP static DMA buffer on DSP User PD */
|
||||
#define ADSP_MMAP_DMA_BUFFER 6
|
||||
/* Add memory to static PD pool protection thru hypervisor */
|
||||
#define ADSP_MMAP_REMOTE_HEAP_ADDR 8
|
||||
/* Add memory to userPD pool, for user heap */
|
||||
#define ADSP_MMAP_ADD_PAGES 0x1000
|
||||
/* Add memory to userPD pool, for LLC heap */
|
||||
#define ADSP_MMAP_ADD_PAGES_LLC 0x3000,
|
||||
|
||||
#define DSP_UNSUPPORTED_API (0x80000414)
|
||||
/* MAX NUMBER of DSP ATTRIBUTES SUPPORTED */
|
||||
#define FASTRPC_MAX_DSP_ATTRIBUTES (256)
|
||||
@@ -72,6 +85,7 @@
|
||||
FASTRPC_BUILD_SCALARS(0, method, in, out, 0, 0)
|
||||
|
||||
#define FASTRPC_CREATE_PROCESS_NARGS 6
|
||||
#define FASTRPC_CREATE_STATIC_PROCESS_NARGS 3
|
||||
/* Remote Method id table */
|
||||
#define FASTRPC_RMID_INIT_ATTACH 0
|
||||
#define FASTRPC_RMID_INIT_RELEASE 1
|
||||
@@ -84,7 +98,7 @@
|
||||
#define FASTRPC_RMID_INIT_MEM_UNMAP 11
|
||||
|
||||
/* Protection Domain(PD) ids */
|
||||
#define AUDIO_PD (0) /* also GUEST_OS PD? */
|
||||
#define ROOT_PD (0)
|
||||
#define USER_PD (1)
|
||||
#define SENSORS_PD (2)
|
||||
|
||||
@@ -261,8 +275,11 @@ struct fastrpc_channel_ctx {
|
||||
u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES];
|
||||
struct fastrpc_device *secure_fdevice;
|
||||
struct fastrpc_device *fdevice;
|
||||
struct fastrpc_buf *remote_heap;
|
||||
struct list_head invoke_interrupted_mmaps;
|
||||
bool secure;
|
||||
bool unsigned_support;
|
||||
u64 dma_mask;
|
||||
};
|
||||
|
||||
struct fastrpc_device {
|
||||
@@ -369,7 +386,7 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf)
|
||||
kfree(buf);
|
||||
}
|
||||
|
||||
static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
|
||||
static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
|
||||
u64 size, struct fastrpc_buf **obuf)
|
||||
{
|
||||
struct fastrpc_buf *buf;
|
||||
@@ -397,14 +414,37 @@ static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (fl->sctx && fl->sctx->sid)
|
||||
buf->phys += ((u64)fl->sctx->sid << 32);
|
||||
|
||||
*obuf = buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
|
||||
u64 size, struct fastrpc_buf **obuf)
|
||||
{
|
||||
int ret;
|
||||
struct fastrpc_buf *buf;
|
||||
|
||||
ret = __fastrpc_buf_alloc(fl, dev, size, obuf);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf = *obuf;
|
||||
|
||||
if (fl->sctx && fl->sctx->sid)
|
||||
buf->phys += ((u64)fl->sctx->sid << 32);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fastrpc_remote_heap_alloc(struct fastrpc_user *fl, struct device *dev,
|
||||
u64 size, struct fastrpc_buf **obuf)
|
||||
{
|
||||
struct device *rdev = &fl->cctx->rpdev->dev;
|
||||
|
||||
return __fastrpc_buf_alloc(fl, rdev, size, obuf);
|
||||
}
|
||||
|
||||
static void fastrpc_channel_ctx_free(struct kref *ref)
|
||||
{
|
||||
struct fastrpc_channel_ctx *cctx;
|
||||
@@ -714,6 +754,8 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
|
||||
return -ENOMEM;
|
||||
|
||||
INIT_LIST_HEAD(&map->node);
|
||||
kref_init(&map->refcount);
|
||||
|
||||
map->fl = fl;
|
||||
map->fd = fd;
|
||||
map->buf = dma_buf_get(fd);
|
||||
@@ -740,7 +782,6 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd,
|
||||
map->size = len;
|
||||
map->va = sg_virt(map->table->sgl);
|
||||
map->len = len;
|
||||
kref_init(&map->refcount);
|
||||
|
||||
if (attr & FASTRPC_ATTR_SECUREMAP) {
|
||||
/*
|
||||
@@ -770,7 +811,7 @@ map_err:
|
||||
attach_err:
|
||||
dma_buf_put(map->buf);
|
||||
get_err:
|
||||
kfree(map);
|
||||
fastrpc_map_put(map);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -1073,6 +1114,8 @@ static int fastrpc_internal_invoke(struct fastrpc_user *fl, u32 kernel,
|
||||
struct fastrpc_invoke_args *args)
|
||||
{
|
||||
struct fastrpc_invoke_ctx *ctx = NULL;
|
||||
struct fastrpc_buf *buf, *b;
|
||||
|
||||
int err = 0;
|
||||
|
||||
if (!fl->sctx)
|
||||
@@ -1135,6 +1178,14 @@ bail:
|
||||
spin_unlock(&fl->lock);
|
||||
fastrpc_context_put(ctx);
|
||||
}
|
||||
|
||||
if (err == -ERESTARTSYS) {
|
||||
list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
|
||||
list_del(&buf->node);
|
||||
list_add_tail(&buf->node, &fl->cctx->invoke_interrupted_mmaps);
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
dev_dbg(fl->sctx->dev, "Error: Invoke Failed %d\n", err);
|
||||
|
||||
@@ -1159,6 +1210,120 @@ static bool is_session_rejected(struct fastrpc_user *fl, bool unsigned_pd_reques
|
||||
return false;
|
||||
}
|
||||
|
||||
static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
|
||||
char __user *argp)
|
||||
{
|
||||
struct fastrpc_init_create_static init;
|
||||
struct fastrpc_invoke_args *args;
|
||||
struct fastrpc_phy_page pages[1];
|
||||
char *name;
|
||||
int err;
|
||||
struct {
|
||||
int pgid;
|
||||
u32 namelen;
|
||||
u32 pageslen;
|
||||
} inbuf;
|
||||
u32 sc;
|
||||
|
||||
args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL);
|
||||
if (!args)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(&init, argp, sizeof(init))) {
|
||||
err = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (init.namelen > INIT_FILE_NAMELEN_MAX) {
|
||||
err = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
name = kzalloc(init.namelen, GFP_KERNEL);
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (copy_from_user(name, (void __user *)(uintptr_t)init.name, init.namelen)) {
|
||||
err = -EFAULT;
|
||||
goto err_name;
|
||||
}
|
||||
|
||||
if (!fl->cctx->remote_heap) {
|
||||
err = fastrpc_remote_heap_alloc(fl, fl->sctx->dev, init.memlen,
|
||||
&fl->cctx->remote_heap);
|
||||
if (err)
|
||||
goto err_name;
|
||||
|
||||
/* Map if we have any heap VMIDs associated with this ADSP Static Process. */
|
||||
if (fl->cctx->vmcount) {
|
||||
unsigned int perms = BIT(QCOM_SCM_VMID_HLOS);
|
||||
|
||||
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
|
||||
(u64)fl->cctx->remote_heap->size, &perms,
|
||||
fl->cctx->vmperms, fl->cctx->vmcount);
|
||||
if (err) {
|
||||
dev_err(fl->sctx->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d",
|
||||
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
|
||||
goto err_map;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inbuf.pgid = fl->tgid;
|
||||
inbuf.namelen = init.namelen;
|
||||
inbuf.pageslen = 0;
|
||||
fl->pd = USER_PD;
|
||||
|
||||
args[0].ptr = (u64)(uintptr_t)&inbuf;
|
||||
args[0].length = sizeof(inbuf);
|
||||
args[0].fd = -1;
|
||||
|
||||
args[1].ptr = (u64)(uintptr_t)name;
|
||||
args[1].length = inbuf.namelen;
|
||||
args[1].fd = -1;
|
||||
|
||||
pages[0].addr = fl->cctx->remote_heap->phys;
|
||||
pages[0].size = fl->cctx->remote_heap->size;
|
||||
|
||||
args[2].ptr = (u64)(uintptr_t) pages;
|
||||
args[2].length = sizeof(*pages);
|
||||
args[2].fd = -1;
|
||||
|
||||
sc = FASTRPC_SCALARS(FASTRPC_RMID_INIT_CREATE_STATIC, 3, 0);
|
||||
|
||||
err = fastrpc_internal_invoke(fl, true, FASTRPC_INIT_HANDLE,
|
||||
sc, args);
|
||||
if (err)
|
||||
goto err_invoke;
|
||||
|
||||
kfree(args);
|
||||
|
||||
return 0;
|
||||
err_invoke:
|
||||
if (fl->cctx->vmcount) {
|
||||
struct qcom_scm_vmperm perm;
|
||||
|
||||
perm.vmid = QCOM_SCM_VMID_HLOS;
|
||||
perm.perm = QCOM_SCM_PERM_RWX;
|
||||
err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys,
|
||||
(u64)fl->cctx->remote_heap->size,
|
||||
&(fl->cctx->vmperms[0].vmid), &perm, 1);
|
||||
if (err)
|
||||
dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
|
||||
fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
|
||||
}
|
||||
err_map:
|
||||
fastrpc_buf_free(fl->cctx->remote_heap);
|
||||
err_name:
|
||||
kfree(name);
|
||||
err:
|
||||
kfree(args);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int fastrpc_init_create_process(struct fastrpc_user *fl,
|
||||
char __user *argp)
|
||||
{
|
||||
@@ -1605,30 +1770,14 @@ static int fastrpc_get_dsp_info(struct fastrpc_user *fl, char __user *argp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fastrpc_req_munmap_impl(struct fastrpc_user *fl,
|
||||
struct fastrpc_req_munmap *req)
|
||||
static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *buf)
|
||||
{
|
||||
struct fastrpc_invoke_args args[1] = { [0] = { 0 } };
|
||||
struct fastrpc_buf *buf = NULL, *iter, *b;
|
||||
struct fastrpc_munmap_req_msg req_msg;
|
||||
struct device *dev = fl->sctx->dev;
|
||||
int err;
|
||||
u32 sc;
|
||||
|
||||
spin_lock(&fl->lock);
|
||||
list_for_each_entry_safe(iter, b, &fl->mmaps, node) {
|
||||
if ((iter->raddr == req->vaddrout) && (iter->size == req->size)) {
|
||||
buf = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&fl->lock);
|
||||
|
||||
if (!buf) {
|
||||
dev_err(dev, "mmap not in list\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req_msg.pgid = fl->tgid;
|
||||
req_msg.size = buf->size;
|
||||
req_msg.vaddr = buf->raddr;
|
||||
@@ -1654,12 +1803,29 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl,
|
||||
|
||||
static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp)
|
||||
{
|
||||
struct fastrpc_buf *buf = NULL, *iter, *b;
|
||||
struct fastrpc_req_munmap req;
|
||||
struct device *dev = fl->sctx->dev;
|
||||
|
||||
if (copy_from_user(&req, argp, sizeof(req)))
|
||||
return -EFAULT;
|
||||
|
||||
return fastrpc_req_munmap_impl(fl, &req);
|
||||
spin_lock(&fl->lock);
|
||||
list_for_each_entry_safe(iter, b, &fl->mmaps, node) {
|
||||
if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) {
|
||||
buf = iter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&fl->lock);
|
||||
|
||||
if (!buf) {
|
||||
dev_err(dev, "mmap\t\tpt 0x%09llx [len 0x%08llx] not in list\n",
|
||||
req.vaddrout, req.size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return fastrpc_req_munmap_impl(fl, buf);
|
||||
}
|
||||
|
||||
static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
@@ -1668,7 +1834,6 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
struct fastrpc_buf *buf = NULL;
|
||||
struct fastrpc_mmap_req_msg req_msg;
|
||||
struct fastrpc_mmap_rsp_msg rsp_msg;
|
||||
struct fastrpc_req_munmap req_unmap;
|
||||
struct fastrpc_phy_page pages;
|
||||
struct fastrpc_req_mmap req;
|
||||
struct device *dev = fl->sctx->dev;
|
||||
@@ -1678,8 +1843,9 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
if (copy_from_user(&req, argp, sizeof(req)))
|
||||
return -EFAULT;
|
||||
|
||||
if (req.flags != ADSP_MMAP_ADD_PAGES) {
|
||||
if (req.flags != ADSP_MMAP_ADD_PAGES && req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR) {
|
||||
dev_err(dev, "flag not supported 0x%x\n", req.flags);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1725,16 +1891,29 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
/* let the client know the address to use */
|
||||
req.vaddrout = rsp_msg.vaddr;
|
||||
|
||||
/* Add memory to static PD pool, protection thru hypervisor */
|
||||
if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) {
|
||||
struct qcom_scm_vmperm perm;
|
||||
int err = 0;
|
||||
|
||||
perm.vmid = QCOM_SCM_VMID_HLOS;
|
||||
perm.perm = QCOM_SCM_PERM_RWX;
|
||||
err = qcom_scm_assign_mem(buf->phys, buf->size,
|
||||
&(fl->cctx->vmperms[0].vmid), &perm, 1);
|
||||
if (err) {
|
||||
dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d",
|
||||
buf->phys, buf->size, err);
|
||||
goto err_assign;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&fl->lock);
|
||||
list_add_tail(&buf->node, &fl->mmaps);
|
||||
spin_unlock(&fl->lock);
|
||||
|
||||
if (copy_to_user((void __user *)argp, &req, sizeof(req))) {
|
||||
/* unmap the memory and release the buffer */
|
||||
req_unmap.vaddrout = buf->raddr;
|
||||
req_unmap.size = buf->size;
|
||||
fastrpc_req_munmap_impl(fl, &req_unmap);
|
||||
return -EFAULT;
|
||||
err = -EFAULT;
|
||||
goto err_assign;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "mmap\t\tpt 0x%09lx OK [len 0x%08llx]\n",
|
||||
@@ -1742,6 +1921,8 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
|
||||
|
||||
return 0;
|
||||
|
||||
err_assign:
|
||||
fastrpc_req_munmap_impl(fl, buf);
|
||||
err_invoke:
|
||||
fastrpc_buf_free(buf);
|
||||
|
||||
@@ -1889,11 +2070,14 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
|
||||
err = fastrpc_invoke(fl, argp);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_ATTACH:
|
||||
err = fastrpc_init_attach(fl, AUDIO_PD);
|
||||
err = fastrpc_init_attach(fl, ROOT_PD);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_ATTACH_SNS:
|
||||
err = fastrpc_init_attach(fl, SENSORS_PD);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_CREATE_STATIC:
|
||||
err = fastrpc_init_create_static_process(fl, argp);
|
||||
break;
|
||||
case FASTRPC_IOCTL_INIT_CREATE:
|
||||
err = fastrpc_init_create_process(fl, argp);
|
||||
break;
|
||||
@@ -2068,6 +2252,9 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (of_reserved_mem_device_init_by_idx(rdev, rdev->of_node, 0))
|
||||
dev_info(rdev, "no reserved DMA memory for FASTRPC\n");
|
||||
|
||||
vmcount = of_property_read_variable_u32_array(rdev->of_node,
|
||||
"qcom,vmids", &vmids[0], 0, FASTRPC_MAX_VMIDS);
|
||||
if (vmcount < 0)
|
||||
@@ -2120,8 +2307,10 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
kref_init(&data->refcount);
|
||||
|
||||
dev_set_drvdata(&rpdev->dev, data);
|
||||
rdev->dma_mask = &data->dma_mask;
|
||||
dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
|
||||
INIT_LIST_HEAD(&data->users);
|
||||
INIT_LIST_HEAD(&data->invoke_interrupted_mmaps);
|
||||
spin_lock_init(&data->lock);
|
||||
idr_init(&data->ctx_idr);
|
||||
data->domain_id = domain_id;
|
||||
@@ -2146,6 +2335,7 @@ static void fastrpc_notify_users(struct fastrpc_user *user)
|
||||
static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||
{
|
||||
struct fastrpc_channel_ctx *cctx = dev_get_drvdata(&rpdev->dev);
|
||||
struct fastrpc_buf *buf, *b;
|
||||
struct fastrpc_user *user;
|
||||
unsigned long flags;
|
||||
|
||||
@@ -2160,6 +2350,12 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||
if (cctx->secure_fdevice)
|
||||
misc_deregister(&cctx->secure_fdevice->miscdev);
|
||||
|
||||
list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node)
|
||||
list_del(&buf->node);
|
||||
|
||||
if (cctx->remote_heap)
|
||||
fastrpc_buf_free(cctx->remote_heap);
|
||||
|
||||
of_platform_depopulate(&rpdev->dev);
|
||||
|
||||
cctx->rpdev = NULL;
|
||||
|
||||
Reference in New Issue
Block a user