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

Reply via email to