diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 30d4d04..a961a66 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -41,6 +41,10 @@
 #define INIT_FILE_NAMELEN_MAX (128)
 #define FASTRPC_DEVICE_NAME	"fastrpc"
 
+/* Maximum buffers cached in cached buffer list */
+#define FASTRPC_MAX_CACHED_BUFS (32)
+#define FASTRPC_MAX_CACHE_BUF_SIZE (8*1024*1024)
+
 /* Add memory to static PD pool, protection thru XPU */
 #define ADSP_MMAP_HEAP_ADDR  4
 /* MAP static DMA buffer on DSP User PD */
@@ -195,6 +199,7 @@ struct fastrpc_buf {
 	struct dma_buf *dmabuf;
 	struct device *dev;
 	void *virt;
+	u32 type;
 	u64 phys;
 	u64 size;
 	/* Lock for dma buf attachments */
@@ -293,6 +298,7 @@ struct fastrpc_user {
 	struct list_head maps;
 	struct list_head pending;
 	struct list_head mmaps;
+	struct list_head cached_bufs;
 
 	struct fastrpc_channel_ctx *cctx;
 	struct fastrpc_session_ctx *sctx;
@@ -300,6 +306,8 @@ struct fastrpc_user {
 
 	int tgid;
 	int pd;
+	/* total cached buffers */
+	u32 num_cached_buf;
 	bool is_secure_dev;
 	/* Lock for lists */
 	spinlock_t lock;
@@ -391,17 +399,95 @@ static int fastrpc_map_lookup(struct fastrpc_user *fl, int fd,
 	return ret;
 }
 
-static void fastrpc_buf_free(struct fastrpc_buf *buf)
+static void __fastrpc_buf_free(struct fastrpc_buf *buf)
 {
 	dma_free_coherent(buf->dev, buf->size, buf->virt,
 			  FASTRPC_PHYS(buf->phys));
 	kfree(buf);
 }
 
+static void fastrpc_cached_buf_list_add(struct fastrpc_buf *buf)
+{
+	struct fastrpc_user *fl = buf->fl;
+
+	if (buf->size < FASTRPC_MAX_CACHE_BUF_SIZE) {
+		spin_lock(&fl->lock);
+		if (fl->num_cached_buf > FASTRPC_MAX_CACHED_BUFS) {
+			spin_unlock(&fl->lock);
+			goto skip_buf_cache;
+		}
+
+		list_add_tail(&buf->node, &fl->cached_bufs);
+		fl->num_cached_buf++;
+		buf->type = -1;
+		spin_unlock(&fl->lock);
+	}
+	return;
+
+skip_buf_cache:
+	__fastrpc_buf_free(buf);
+}
+
+static void fastrpc_buf_free(struct fastrpc_buf *buf, bool cache)
+{
+	if (cache)
+		fastrpc_cached_buf_list_add(buf);
+	else
+		__fastrpc_buf_free(buf);
+}
+
+static inline bool fastrpc_get_cached_buf(struct fastrpc_user *fl,
+		size_t size, int buf_type, struct fastrpc_buf **obuf)
+{
+	bool found = false;
+	struct fastrpc_buf *buf, *n, *cbuf = NULL;
+
+	if (buf_type == USER_BUF)
+		return found;
+
+	/* find the smallest buffer that fits in the cache */
+	spin_lock(&fl->lock);
+	list_for_each_entry_safe(buf, n, &fl->cached_bufs, node) {
+		if (buf->size >= size && (!cbuf || cbuf->size > buf->size))
+			cbuf = buf;
+	}
+	if (cbuf) {
+		list_del_init(&cbuf->node);
+		fl->num_cached_buf--;
+	}
+	spin_unlock(&fl->lock);
+	if (cbuf) {
+		cbuf->type = buf_type;
+		*obuf = cbuf;
+		found = true;
+	}
+
+	return found;
+}
+
+static void fastrpc_cached_buf_list_free(struct fastrpc_user *fl)
+{
+	struct fastrpc_buf *buf, *n, *free;
+
+	do {
+		free = NULL;
+		spin_lock(&fl->lock);
+		list_for_each_entry_safe(buf, n, &fl->cached_bufs, node) {
+			list_del(&buf->node);
+			fl->num_cached_buf--;
+			free = buf;
+			break;
+		}
+		spin_unlock(&fl->lock);
+		if (free)
+			fastrpc_buf_free(free, false);
+	} while (free);
+}
+
 static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
 			     u64 size, struct fastrpc_buf **obuf)
 {
-	struct fastrpc_buf *buf;
+	struct fastrpc_buf *buf = NULL;
 
 	buf = kzalloc(sizeof(*buf), GFP_KERNEL);
 	if (!buf)
@@ -432,16 +518,23 @@ static int __fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
 }
 
 static int fastrpc_buf_alloc(struct fastrpc_user *fl, struct device *dev,
-			     u64 size, struct fastrpc_buf **obuf)
+			     u64 size, u32 buf_type, struct fastrpc_buf **obuf)
 {
 	int ret;
 	struct fastrpc_buf *buf;
 
+	if (fastrpc_get_cached_buf(fl, size, buf_type, obuf))
+		return 0;
 	ret = __fastrpc_buf_alloc(fl, dev, size, obuf);
-	if (ret)
-		return ret;
+	if (ret == -ENOMEM) {
+		fastrpc_cached_buf_list_free(fl);
+		ret = __fastrpc_buf_alloc(fl, dev, size, obuf);
+		if (ret)
+			return ret;
+	}
 
 	buf = *obuf;
+	buf->type = buf_type;
 
 	if (fl->sctx && fl->sctx->sid)
 		buf->phys += ((u64)fl->sctx->sid << 32);
@@ -490,7 +583,7 @@ static void fastrpc_context_free(struct kref *ref)
 		fastrpc_map_put(ctx->maps[i]);
 
 	if (ctx->buf)
-		fastrpc_buf_free(ctx->buf);
+		fastrpc_buf_free(ctx->buf, true);
 
 	spin_lock_irqsave(&cctx->lock, flags);
 	idr_remove(&cctx->ctx_idr, ctx->ctxid >> 4);
@@ -674,7 +767,7 @@ static void fastrpc_release(struct dma_buf *dmabuf)
 {
 	struct fastrpc_buf *buffer = dmabuf->priv;
 
-	fastrpc_buf_free(buffer);
+	fastrpc_buf_free(buffer, false);
 }
 
 static int fastrpc_dma_buf_attach(struct dma_buf *dmabuf,
@@ -951,7 +1044,7 @@ static int fastrpc_get_args(u32 kernel, struct fastrpc_invoke_ctx *ctx)
 
 	ctx->msg_sz = pkt_size;
 
-	err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, &ctx->buf);
+	err = fastrpc_buf_alloc(ctx->fl, dev, pkt_size, METADATA_BUF, &ctx->buf);
 	if (err)
 		return err;
 
@@ -1334,7 +1427,7 @@ static int fastrpc_init_create_static_process(struct fastrpc_user *fl,
 				fl->cctx->remote_heap->phys, fl->cctx->remote_heap->size, err);
 	}
 err_map:
-	fastrpc_buf_free(fl->cctx->remote_heap);
+	fastrpc_buf_free(fl->cctx->remote_heap, false);
 err_name:
 	kfree(name);
 err:
@@ -1403,7 +1496,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
 	memlen = ALIGN(max(INIT_FILELEN_MAX, (int)init.filelen * 4),
 		       1024 * 1024);
 	err = fastrpc_buf_alloc(fl, fl->sctx->dev, memlen,
-				&imem);
+				INITMEM_BUF, &imem);
 	if (err)
 		goto err_alloc;
 
@@ -1450,7 +1543,7 @@ static int fastrpc_init_create_process(struct fastrpc_user *fl,
 
 err_invoke:
 	fl->init_mem = NULL;
-	fastrpc_buf_free(imem);
+	fastrpc_buf_free(imem, false);
 err_alloc:
 	fastrpc_map_put(map);
 err:
@@ -1521,7 +1614,7 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
 	spin_unlock_irqrestore(&cctx->lock, flags);
 
 	if (fl->init_mem)
-		fastrpc_buf_free(fl->init_mem);
+		fastrpc_buf_free(fl->init_mem, false);
 
 	list_for_each_entry_safe(ctx, n, &fl->pending, node) {
 		list_del(&ctx->node);
@@ -1533,9 +1626,10 @@ static int fastrpc_device_release(struct inode *inode, struct file *file)
 
 	list_for_each_entry_safe(buf, b, &fl->mmaps, node) {
 		list_del(&buf->node);
-		fastrpc_buf_free(buf);
+		fastrpc_buf_free(buf, false);
 	}
 
+	fastrpc_cached_buf_list_free(fl);
 	fastrpc_session_free(cctx, fl->sctx);
 	fastrpc_channel_ctx_put(cctx);
 
@@ -1570,6 +1664,7 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp)
 	INIT_LIST_HEAD(&fl->maps);
 	INIT_LIST_HEAD(&fl->mmaps);
 	INIT_LIST_HEAD(&fl->user);
+	INIT_LIST_HEAD(&fl->cached_bufs);
 	fl->tgid = current->tgid;
 	fl->cctx = cctx;
 	fl->is_secure_dev = fdevice->secure;
@@ -1600,7 +1695,7 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
 	if (copy_from_user(&bp, argp, sizeof(bp)))
 		return -EFAULT;
 
-	err = fastrpc_buf_alloc(fl, fl->sctx->dev, bp.size, &buf);
+	err = fastrpc_buf_alloc(fl, fl->sctx->dev, bp.size, USER_BUF, &buf);
 	if (err)
 		return err;
 	exp_info.ops = &fastrpc_dma_buf_ops;
@@ -1610,7 +1705,7 @@ static int fastrpc_dmabuf_alloc(struct fastrpc_user *fl, char __user *argp)
 	buf->dmabuf = dma_buf_export(&exp_info);
 	if (IS_ERR(buf->dmabuf)) {
 		err = PTR_ERR(buf->dmabuf);
-		fastrpc_buf_free(buf);
+		fastrpc_buf_free(buf, false);
 		return err;
 	}
 
@@ -1805,7 +1900,7 @@ static int fastrpc_req_munmap_impl(struct fastrpc_user *fl, struct fastrpc_buf *
 		spin_lock(&fl->lock);
 		list_del(&buf->node);
 		spin_unlock(&fl->lock);
-		fastrpc_buf_free(buf);
+		fastrpc_buf_free(buf, false);
 	} else {
 		dev_err(dev, "unmmap\tpt 0x%09lx ERROR\n", buf->raddr);
 	}
@@ -1866,7 +1961,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
 		return -EINVAL;
 	}
 
-	err = fastrpc_buf_alloc(fl, fl->sctx->dev, req.size, &buf);
+	err = fastrpc_buf_alloc(fl, fl->sctx->dev, req.size, USER_BUF, &buf);
 	if (err) {
 		dev_err(dev, "failed to allocate buffer\n");
 		return err;
@@ -1935,7 +2030,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp)
 err_assign:
 	fastrpc_req_munmap_impl(fl, buf);
 err_invoke:
-	fastrpc_buf_free(buf);
+	fastrpc_buf_free(buf, false);
 
 	return err;
 }
@@ -2380,7 +2475,7 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev)
 		list_del(&buf->node);
 
 	if (cctx->remote_heap)
-		fastrpc_buf_free(cctx->remote_heap);
+		fastrpc_buf_free(cctx->remote_heap, false);
 
 	of_platform_depopulate(&rpdev->dev);
 
diff --git a/include/uapi/misc/fastrpc.h b/include/uapi/misc/fastrpc.h
index f33d914..91c7c4f 100644
--- a/include/uapi/misc/fastrpc.h
+++ b/include/uapi/misc/fastrpc.h
@@ -64,6 +64,14 @@ enum fastrpc_proc_attr {
 	FASTRPC_MODE_PRIVILEGED		= (1 << 6),
 };
 
+ /* Types of fastrpc DMA bufs sent to DSP */
+ enum fastrpc_buf_type {
+	METADATA_BUF,
+	COPYDATA_BUF,
+	INITMEM_BUF,
+	USER_BUF,
+};
+
 /* Fastrpc attribute for memory protection of buffers */
 #define FASTRPC_ATTR_SECUREMAP	(1)
 
