diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 2ee90822d826..c4019db14ac4 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -294,8 +294,6 @@ struct fastrpc_channel_ctx { struct kref refcount; /* Flag if dsp attributes are cached */ bool valid_attributes; - /* Flag if audio PD init mem was allocated */ - bool audio_init_mem; u32 dsp_attributes[FASTRPC_MAX_DSP_ATTRIBUTES]; struct fastrpc_device *secure_fdevice; struct fastrpc_device *fdevice; @@ -416,9 +414,6 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd, static void fastrpc_buf_free(struct fastrpc_buf *buf) { - if (!buf) - return; - dma_free_coherent(buf->dev, buf->size, buf->virt, FASTRPC_PHYS(buf->phys)); kfree(buf); @@ -536,7 +531,8 @@ static void fastrpc_context_free(struct kref *ref) for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); - fastrpc_buf_free(ctx->buf); + if (ctx->buf) + fastrpc_buf_free(ctx->buf); spin_lock_irqsave(&cctx->lock, flags); idr_remove(&cctx->ctx_idr, ctx->ctxid >> 8); @@ -1398,16 +1394,15 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, struct fastrpc_init_create_static init; struct fastrpc_invoke_args *args; struct fastrpc_phy_page pages[1]; - struct fastrpc_channel_ctx *cctx = fl->cctx; char *name; int err; + bool scm_done = false; struct { int client_id; u32 namelen; u32 pageslen; } inbuf; u32 sc; - unsigned long flags; args = kcalloc(FASTRPC_CREATE_STATIC_PROCESS_NARGS, sizeof(*args), GFP_KERNEL); if (!args) @@ -1428,10 +1423,33 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, err = PTR_ERR(name); goto err; } + + 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) { + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); + + err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, + (u64)fl->cctx->remote_heap->size, + &src_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\n", + fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err); + goto err_map; + } + scm_done = true; + } + } + inbuf.client_id = fl->client_id; inbuf.namelen = init.namelen; inbuf.pageslen = 0; - fl->pd = USER_PD; args[0].ptr = (u64)(uintptr_t)&inbuf; @@ -1442,25 +1460,8 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, args[1].length = inbuf.namelen; args[1].fd = -1; - spin_lock_irqsave(&cctx->lock, flags); - if (!fl->cctx->audio_init_mem) { - if (!fl->cctx->remote_heap || - !fl->cctx->remote_heap->phys || - !fl->cctx->remote_heap->size) { - spin_unlock_irqrestore(&cctx->lock, flags); - err = -ENOMEM; - goto err; - } - - pages[0].addr = fl->cctx->remote_heap->phys; - pages[0].size = fl->cctx->remote_heap->size; - fl->cctx->audio_init_mem = true; - inbuf.pageslen = 1; - } else { - pages[0].addr = 0; - pages[0].size = 0; - } - spin_unlock_irqrestore(&cctx->lock, flags); + 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); @@ -1478,7 +1479,26 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl, return 0; err_invoke: - fl->cctx->audio_init_mem = false; + if (fl->cctx->vmcount && scm_done) { + u64 src_perms = 0; + struct qcom_scm_vmperm dst_perms; + u32 i; + + for (i = 0; i < fl->cctx->vmcount; i++) + src_perms |= BIT(fl->cctx->vmperms[i].vmid); + + dst_perms.vmid = QCOM_SCM_VMID_HLOS; + dst_perms.perm = QCOM_SCM_PERM_RWX; + err = qcom_scm_assign_mem(fl->cctx->remote_heap->phys, + (u64)fl->cctx->remote_heap->size, + &src_perms, &dst_perms, 1); + if (err) + dev_err(fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d\n", + 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); @@ -1666,7 +1686,8 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) list_del(&fl->user); spin_unlock_irqrestore(&cctx->lock, flags); - fastrpc_buf_free(fl->init_mem); + if (fl->init_mem) + fastrpc_buf_free(fl->init_mem); list_for_each_entry_safe(ctx, n, &fl->pending, node) { list_del(&ctx->node); @@ -1937,6 +1958,9 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf * &args[0]); if (!err) { dev_dbg(dev, "unmmap\tpt 0x%09lx OK\n", buf->raddr); + spin_lock(&fl->lock); + list_del(&buf->node); + spin_unlock(&fl->lock); fastrpc_buf_free(buf); } else { dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr); @@ -1950,7 +1974,6 @@ 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; - int err; if (copy_from_user(&req, argp, sizeof(req))) return -EFAULT; @@ -1958,7 +1981,6 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) spin_lock(&fl->lock); list_for_each_entry_safe(iter, b, &fl->mmaps, node) { if ((iter->raddr == req.vaddrout) && (iter->size == req.size)) { - list_del(&iter->node); buf = iter; break; } @@ -1971,14 +1993,7 @@ static int fastrpc_req_munmap(struct fastrpc_user *fl, char __user *argp) return -EINVAL; } - err = fastrpc_req_munmap_impl(fl, buf); - if (err) { - spin_lock(&fl->lock); - list_add_tail(&buf->node, &fl->mmaps); - spin_unlock(&fl->lock); - } - - return err; + return fastrpc_req_munmap_impl(fl, buf); } static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) @@ -2068,17 +2083,14 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) if (copy_to_user((void __user *)argp, &req, sizeof(req))) { err = -EFAULT; - goto err_copy; + goto err_assign; } dev_dbg(dev, "mmap\t\tpt 0x%09lx OK [len 0x%08llx]\n", buf->raddr, buf->size); return 0; -err_copy: - spin_lock(&fl->lock); - list_del(&buf->node); - spin_unlock(&fl->lock); + err_assign: fastrpc_req_munmap_impl(fl, buf); @@ -2444,7 +2456,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) } } - if (domain_id == SDSP_DOMAIN_ID || domain_id == ADSP_DOMAIN_ID) { + if (domain_id == SDSP_DOMAIN_ID) { struct resource res; u64 src_perms; @@ -2455,15 +2467,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) qcom_scm_assign_mem(res.start, resource_size(&res), &src_perms, data->vmperms, data->vmcount); } - if (domain_id == ADSP_DOMAIN_ID) { - data->remote_heap = - kzalloc(sizeof(*data->remote_heap), GFP_KERNEL); - if (!data->remote_heap) - return -ENOMEM; - - data->remote_heap->phys = res.start; - data->remote_heap->size = resource_size(&res); - } + } secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain")); @@ -2543,7 +2547,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_buf *buf, *b; struct fastrpc_user *user; unsigned long flags; - int err; /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); @@ -2561,22 +2564,8 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) list_for_each_entry_safe(buf, b, &cctx->invoke_interrupted_mmaps, node) list_del(&buf->node); - if (cctx->remote_heap && cctx->vmcount) { - u64 src_perms = 0; - struct qcom_scm_vmperm dst_perms; - - for (u32 i = 0; i < cctx->vmcount; i++) - src_perms |= BIT(cctx->vmperms[i].vmid); - - dst_perms.vmid = QCOM_SCM_VMID_HLOS; - dst_perms.perm = QCOM_SCM_PERM_RWX; - - err = qcom_scm_assign_mem(cctx->remote_heap->phys, - cctx->remote_heap->size, &src_perms, - &dst_perms, 1); - if (!err) - fastrpc_buf_free(cctx->remote_heap); - } + if (cctx->remote_heap) + fastrpc_buf_free(cctx->remote_heap); of_platform_depopulate(&rpdev->dev);