Extended context banks carry a 40-bit DMA mask and are shared across all open sessions rather than exclusively owned by one. They are a fundamentally different resource from normal CBs and do not belong in the session[] pool.
Maintain a separate dynamically allocated cctx->ext_cb[] array instead. Extended CBs are detected at probe time by the presence of a memory-region phandle and routed there, leaving session[] and the normal allocation path unchanged. Signed-off-by: Vinayak Katoch <[email protected]> --- drivers/misc/fastrpc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 07a0f2b229b4..28d89fd9cbbc 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -309,6 +309,8 @@ struct fastrpc_channel_ctx { struct qcom_scm_vmperm vmperms[FASTRPC_MAX_VMIDS]; struct rpmsg_device *rpdev; struct fastrpc_session_ctx session[FASTRPC_MAX_SESSIONS]; + struct fastrpc_session_ctx **ext_cb; + int ext_cb_count; spinlock_t lock; struct idr ctx_idr; struct list_head users; @@ -536,9 +538,13 @@ static int fastrpc_remote_heap_alloc(struct fastrpc_user *fl, struct device *dev static void fastrpc_channel_ctx_free(struct kref *ref) { struct fastrpc_channel_ctx *cctx; + int i; cctx = container_of(ref, struct fastrpc_channel_ctx, refcount); + for (i = 0; i < cctx->ext_cb_count; i++) + kfree(cctx->ext_cb[i]); + kfree(cctx->ext_cb); idr_destroy(&cctx->ctx_idr); kfree(cctx); } @@ -2373,6 +2379,8 @@ static int fastrpc_cb_init(struct platform_device *pdev) u32 dma_bits; u32 sid = 0; int rc; + bool is_extended_cb = false; + struct device_node *mem_np; cctx = dev_get_drvdata(dev->parent); if (!cctx) @@ -2382,6 +2390,45 @@ static int fastrpc_cb_init(struct platform_device *pdev) of_n_addr_cells(dev->of_node) - 1, &sid)) dev_info(dev, "FastRPC Session ID not specified in DT\n"); + mem_np = of_parse_phandle(dev->of_node, "memory-region", 0); + if (mem_np) { + is_extended_cb = true; + of_node_put(mem_np); + } + + if (is_extended_cb) { + struct fastrpc_session_ctx **new_ext; + + sess = kzalloc_obj(*sess); + if (!sess) + return -ENOMEM; + + spin_lock_irqsave(&cctx->lock, flags); + new_ext = krealloc(cctx->ext_cb, + (cctx->ext_cb_count + 1) * sizeof(*cctx->ext_cb), + GFP_KERNEL); + if (!new_ext) { + spin_unlock_irqrestore(&cctx->lock, flags); + kfree(sess); + return -ENOMEM; + } + cctx->ext_cb = new_ext; + sess->valid = true; + sess->dev = dev; + sess->sid = sid; + dev_set_drvdata(dev, sess); + cctx->ext_cb[cctx->ext_cb_count++] = sess; + spin_unlock_irqrestore(&cctx->lock, flags); + + rc = dma_set_mask(dev, DMA_BIT_MASK(40)); + if (rc) { + dev_err(dev, "40-bit DMA enable failed\n"); + return rc; + } + + return 0; + } + spin_lock_irqsave(&cctx->lock, flags); if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) { spin_unlock_irqrestore(&cctx->lock, flags); -- 2.34.1
