struct idr ctx_idr;
        struct list_head users;
        struct miscdevice miscdev;
+       struct kref refcount;
 };
 
 struct fastrpc_user {
        return 0;
 }
 
+static void fastrpc_channel_ctx_free(struct kref *ref)
+{
+       struct fastrpc_channel_ctx *cctx;
+
+       cctx = container_of(ref, struct fastrpc_channel_ctx, refcount);
+
+       kfree(cctx);
+}
+
+static void fastrpc_channel_ctx_get(struct fastrpc_channel_ctx *cctx)
+{
+       kref_get(&cctx->refcount);
+}
+
+static void fastrpc_channel_ctx_put(struct fastrpc_channel_ctx *cctx)
+{
+       kref_put(&cctx->refcount, fastrpc_channel_ctx_free);
+}
+
 static void fastrpc_context_free(struct kref *ref)
 {
        struct fastrpc_invoke_ctx *ctx;
        kfree(ctx->maps);
        kfree(ctx->olaps);
        kfree(ctx);
+
+       fastrpc_channel_ctx_put(cctx);
 }
 
 static void fastrpc_context_get(struct fastrpc_invoke_ctx *ctx)
                fastrpc_get_buff_overlaps(ctx);
        }
 
+       /* Released in fastrpc_context_put() */
+       fastrpc_channel_ctx_get(cctx);
+
        ctx->sc = sc;
        ctx->retval = -1;
        ctx->pid = current->pid;
        spin_lock(&user->lock);
        list_del(&ctx->node);
        spin_unlock(&user->lock);
+       fastrpc_channel_ctx_put(cctx);
        kfree(ctx->maps);
        kfree(ctx->olaps);
        kfree(ctx);
        }
 
        fastrpc_session_free(cctx, fl->sctx);
+       fastrpc_channel_ctx_put(cctx);
 
        mutex_destroy(&fl->mutex);
        kfree(fl);
        if (!fl)
                return -ENOMEM;
 
+       /* Released in fastrpc_device_release() */
+       fastrpc_channel_ctx_get(cctx);
+
        filp->private_data = fl;
        spin_lock_init(&fl->lock);
        mutex_init(&fl->mutex);
        int i, err, domain_id = -1;
        const char *domain;
 
-       data = devm_kzalloc(rdev, sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
        err = of_property_read_string(rdev->of_node, "label", &domain);
        if (err) {
                dev_info(rdev, "FastRPC Domain not specified in DT\n");
                return -EINVAL;
        }
 
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
        data->miscdev.minor = MISC_DYNAMIC_MINOR;
        data->miscdev.name = kasprintf(GFP_KERNEL, "fastrpc-%s",
                                domains[domain_id]);
        if (err)
                return err;
 
+       kref_init(&data->refcount);
+
        dev_set_drvdata(&rpdev->dev, data);
        dma_set_mask_and_coherent(rdev, DMA_BIT_MASK(32));
        INIT_LIST_HEAD(&data->users);
 
        misc_deregister(&cctx->miscdev);
        of_platform_depopulate(&rpdev->dev);
-       kfree(cctx);
+
+       fastrpc_channel_ctx_put(cctx);
 }
 
 static int fastrpc_rpmsg_callback(struct rpmsg_device *rpdev, void *data,