[PATCH 5/6] misc: fastrpc: Add extended context bank support
From: Vinayak Katoch
Date: Wed Aug 26 2026 - 10:03:04 EST
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 <vinayak.katoch@xxxxxxxxxxxxxxxx>
---
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