Detect extended context banks by the presence of iommu-ranges on the
context bank node. Register them in a separate ext_cb array so the
mapping layer can direct large allocations into the wider IOVA window.

Signed-off-by: Vinayak Katoch <[email protected]>
---
 drivers/misc/fastrpc.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 5c7bb56cf46d..d40cdcd5dec3 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -307,6 +307,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;
@@ -538,9 +540,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);
 }
@@ -2343,6 +2349,7 @@ static int fastrpc_cb_init(struct platform_device *pdev)
        u32 dma_bits;
        u32 sid = 0;
        int rc;
+       bool is_extended_cb = false;
 
        cctx = dev_get_drvdata(dev->parent);
        if (!cctx)
@@ -2352,6 +2359,43 @@ 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");
 
+       if (of_property_present(dev->of_node, "iommu-ranges"))
+               is_extended_cb = true;
+
+       if (is_extended_cb) {
+               struct fastrpc_session_ctx **new_ext;
+
+               sess = kzalloc_obj(*sess);
+               if (!sess)
+                       return -ENOMEM;
+
+               rc = dma_set_mask(dev, DMA_BIT_MASK(40));
+               if (rc) {
+                       dev_err(dev, "40-bit DMA enable failed\n");
+                       kfree(sess);
+                       return rc;
+               }
+
+               new_ext = krealloc(cctx->ext_cb,
+                                  (cctx->ext_cb_count + 1) * 
sizeof(*cctx->ext_cb),
+                                  GFP_KERNEL);
+               if (!new_ext) {
+                       kfree(sess);
+                       return -ENOMEM;
+               }
+
+               spin_lock_irqsave(&cctx->lock, flags);
+               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);
+
+               return 0;
+       }
+
        spin_lock_irqsave(&cctx->lock, flags);
        if (cctx->sesscount >= FASTRPC_MAX_SESSIONS) {
                spin_unlock_irqrestore(&cctx->lock, flags);
@@ -2391,6 +2435,8 @@ static void fastrpc_cb_devices_destroy(struct 
rpmsg_device *rpdev)
        spin_lock_irqsave(&cctx->lock, flags);
        for (i = 0; i < cctx->sesscount; i++)
                cctx->session[i].valid = false;
+       for (i = 0; i < cctx->ext_cb_count; i++)
+               cctx->ext_cb[i]->valid = false;
        spin_unlock_irqrestore(&cctx->lock, flags);
 
        for_each_available_child_of_node(rdev->of_node, np) {

-- 
2.34.1

Reply via email to