diff options
| author | Mark Brown <broonie@kernel.org> | 2026-05-29 23:00:40 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-05-29 23:00:40 +0100 |
| commit | 67d60349e1f7ddf021a7c70734347261a3047ffc (patch) | |
| tree | e507f49e542647d04fcc1b2f7a578c702415e7b9 /drivers | |
| parent | 1aef57bf376607540d77304cc65b44996746cbaf (diff) | |
| parent | 8d712bcdd1ef73bf790f01039508fb4e9c076bb1 (diff) | |
| download | linux-next-history-67d60349e1f7ddf021a7c70734347261a3047ffc.tar.gz | |
Merge branch 'for-next' of https://git.kernel.org/pub/scm/linux/kernel/git/srini/fastrpc.git
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/misc/fastrpc.c | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 1080f9acf70a3..5524354f3ccc8 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -310,6 +310,8 @@ struct fastrpc_user { spinlock_t lock; /* lock for allocations */ struct mutex mutex; + /* Reference count */ + struct kref refcount; }; /* Extract SMMU PA from consolidated IOVA */ @@ -497,15 +499,57 @@ static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx) kref_put(&cctx->refcount, fastrpc_channel_ctx_free); } +static void fastrpc_context_put(struct fastrpc_invoke_ctx *ctx); + +static void fastrpc_user_free(struct kref *ref) +{ + struct fastrpc_user *fl = container_of(ref, struct fastrpc_user, refcount); + struct fastrpc_invoke_ctx *ctx, *n; + struct fastrpc_map *map, *m; + struct fastrpc_buf *buf, *b; + + if (fl->init_mem) + fastrpc_buf_free(fl->init_mem); + + list_for_each_entry_safe(ctx, n, &fl->pending, node) { + list_del(&ctx->node); + fastrpc_context_put(ctx); + } + + list_for_each_entry_safe(map, m, &fl->maps, node) + fastrpc_map_put(map); + + list_for_each_entry_safe(buf, b, &fl->mmaps, node) { + list_del(&buf->node); + fastrpc_buf_free(buf); + } + + fastrpc_channel_ctx_put(fl->cctx); + mutex_destroy(&fl->mutex); + kfree(fl); +} + +static void fastrpc_user_get(struct fastrpc_user *fl) +{ + kref_get(&fl->refcount); +} + +static void fastrpc_user_put(struct fastrpc_user *fl) +{ + kref_put(&fl->refcount, fastrpc_user_free); +} + static void fastrpc_context_free(struct kref *ref) { struct fastrpc_invoke_ctx *ctx; struct fastrpc_channel_ctx *cctx; + struct fastrpc_user *fl; unsigned long flags; int i; ctx = container_of(ref, struct fastrpc_invoke_ctx, refcount); cctx = ctx->cctx; + fl = ctx->fl; for (i = 0; i < ctx->nbufs; i++) fastrpc_map_put(ctx->maps[i]); @@ -521,6 +565,8 @@ static void fastrpc_context_free(struct kref *ref) kfree(ctx->olaps); kfree(ctx); + /* Release the reference taken in fastrpc_context_alloc() */ + fastrpc_user_put(fl); fastrpc_channel_ctx_put(cctx); } @@ -628,6 +674,8 @@ static struct fastrpc_invoke_ctx *fastrpc_context_alloc( /* Released in fastrpc_context_put() */ fastrpc_channel_ctx_get(cctx); + /* Take a reference to user, released in fastrpc_context_free() */ + fastrpc_user_get(user); ctx->sc = sc; ctx->retval = -1; @@ -658,6 +706,7 @@ err_idr: spin_lock(&user->lock); list_del(&ctx->node); spin_unlock(&user->lock); + fastrpc_user_put(user); fastrpc_channel_ctx_put(cctx); kfree(ctx->maps); kfree(ctx->olaps); @@ -1041,7 +1090,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx) pages[i].addr = ctx->maps[i]->dma_addr; mmap_read_lock(current->mm); - vma = find_vma(current->mm, ctx->args[i].ptr); + vma = vma_lookup(current->mm, ctx->args[i].ptr); if (vma) pages[i].addr += (ctx->args[i].ptr & PAGE_MASK) - vma->vm_start; @@ -1579,9 +1628,6 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) { struct fastrpc_user *fl = (struct fastrpc_user *)file->private_data; struct fastrpc_channel_ctx *cctx = fl->cctx; - struct fastrpc_invoke_ctx *ctx, *n; - struct fastrpc_map *map, *m; - struct fastrpc_buf *buf, *b; unsigned long flags; fastrpc_release_current_dsp_process(fl); @@ -1590,28 +1636,10 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) list_del(&fl->user); spin_unlock_irqrestore(&cctx->lock, flags); - if (fl->init_mem) - fastrpc_buf_free(fl->init_mem); - - list_for_each_entry_safe(ctx, n, &fl->pending, node) { - list_del(&ctx->node); - fastrpc_context_put(ctx); - } - - list_for_each_entry_safe(map, m, &fl->maps, node) - fastrpc_map_put(map); - - list_for_each_entry_safe(buf, b, &fl->mmaps, node) { - list_del(&buf->node); - fastrpc_buf_free(buf); - } - fastrpc_session_free(cctx, fl->sctx); - fastrpc_channel_ctx_put(cctx); - - mutex_destroy(&fl->mutex); - kfree(fl); file->private_data = NULL; + /* Release the reference taken in fastrpc_device_open */ + fastrpc_user_put(fl); return 0; } @@ -1655,6 +1683,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) spin_lock_irqsave(&cctx->lock, flags); list_add_tail(&fl->user, &cctx->users); spin_unlock_irqrestore(&cctx->lock, flags); + kref_init(&fl->refcount); return 0; } @@ -2197,19 +2226,22 @@ static int fastrpc_cb_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; int i, sessions = 0; unsigned long flags; - int rc; u32 dma_bits; + u32 sid = 0; + int rc; cctx = dev_get_drvdata(dev->parent); if (!cctx) return -EINVAL; of_property_read_u32(dev->of_node, "qcom,nsessions", &sessions); + if (of_property_read_u32(dev->of_node, "reg", &sid)) + dev_info(dev, "FastRPC Session ID not specified in DT\n"); spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { - dev_err(&pdev->dev, "too many sessions\n"); spin_unlock_irqrestore(&cctx->lock, flags); + dev_err(&pdev->dev, "too many sessions\n"); return -ENOSPC; } dma_bits = cctx->soc_data->dma_addr_bits_default; @@ -2218,13 +2250,11 @@ static int fastrpc_cb_probe(struct platform_device *pdev) sess->valid = true; sess->dev = dev; dev_set_drvdata(dev, sess); + sess->sid = sid; if (cctx->domain_id == CDSP_DOMAIN_ID) dma_bits = cctx->soc_data->dma_addr_bits_cdsp; - if (of_property_read_u32(dev->of_node, "reg", &sess->sid)) - dev_info(dev, "FastRPC Session ID not specified in DT\n"); - if (sessions > 0) { struct fastrpc_session_ctx *dup_sess; @@ -2431,7 +2461,6 @@ 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); @@ -2440,6 +2469,7 @@ static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev) idr_init(&data->ctx_idr); data->domain_id = domain_id; data->rpdev = rpdev; + dev_set_drvdata(&rpdev->dev, data); err = of_platform_populate(rdev->of_node, NULL, NULL, rdev); if (err) @@ -2513,6 +2543,9 @@ static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data, if (len < sizeof(*rsp)) return -EINVAL; + if (!cctx) + return -ENODEV; + ctxid = ((rsp->ctx & FASTRPC_CTXID_MASK) >> 4); spin_lock_irqsave(&cctx->lock, flags); |
