From 16828bb6b697a1c5a83a7134f31832c134db1b8a Mon Sep 17 00:00:00 2001
From: "ivan.liu" <xiaowen.liu@nxp.com>
Date: Mon, 7 May 2018 11:24:26 +0800
Subject: [PATCH] MA-11994 Add get phys address ioctl to dma-buf.

Add structure dma_buf_phys to store physical address.
Add DMA_BUF_IOCTL_PHYS to export physical address.

TODO: checkpatch warnings

Change-Id: Ib2f24b33462d603f2cbeef975689aaf82447d088
Signed-off-by: ivan.liu <xiaowen.liu@nxp.com>
Signed-off-by: Vipul Kumar <vipul_kumar@mentor.com>
Signed-off-by: Srikanth Krishnakar <Srikanth_Krishnakar@mentor.com>
---
 drivers/dma-buf/dma-buf.c    | 31 +++++++++++++++++++++++++++++++
 include/uapi/linux/dma-buf.h |  5 +++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 13884474d1588f..9058d61b2bb0c6 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -34,6 +34,7 @@
 #include <linux/poll.h>
 #include <linux/reservation.h>
 #include <linux/mm.h>
+#include <linux/device.h>
 
 #include <uapi/linux/dma-buf.h>
 
@@ -287,6 +288,36 @@ static long dma_buf_ioctl(struct file *file,
 	dmabuf = file->private_data;
 
 	switch (cmd) {
+	case DMA_BUF_IOCTL_PHYS: {
+		struct dma_buf_attachment *attachment = NULL;
+		struct sg_table *sgt = NULL;
+		unsigned long phys = 0;
+		struct device dev;
+
+		if (!dmabuf || IS_ERR(dmabuf)) {
+			return -EFAULT;
+		}
+		memset(&dev, 0, sizeof(dev));
+		device_initialize(&dev);
+		dev.coherent_dma_mask = DMA_BIT_MASK(64);
+		dev.dma_mask = &dev.coherent_dma_mask;
+		arch_setup_dma_ops(&dev, 0, 0, NULL, false);
+		attachment = dma_buf_attach(dmabuf, &dev);
+		if (!attachment || IS_ERR(attachment)) {
+			return -EFAULT;
+		}
+
+		sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
+		if (sgt && !IS_ERR(sgt)) {
+			phys = sg_dma_address(sgt->sgl);
+			dma_buf_unmap_attachment(attachment, sgt,
+					DMA_BIDIRECTIONAL);
+		}
+		dma_buf_detach(dmabuf, attachment);
+		if (copy_to_user((void __user *) arg, &phys, sizeof(phys)))
+			return -EFAULT;
+		return 0;
+	}
 	case DMA_BUF_IOCTL_SYNC:
 		if (copy_from_user(&sync, (void __user *) arg, sizeof(sync)))
 			return -EFAULT;
diff --git a/include/uapi/linux/dma-buf.h b/include/uapi/linux/dma-buf.h
index d75df5210a4a59..514beecd2d1364 100644
--- a/include/uapi/linux/dma-buf.h
+++ b/include/uapi/linux/dma-buf.h
@@ -27,6 +27,10 @@ struct dma_buf_sync {
 	__u64 flags;
 };
 
+struct dma_buf_phys {
+	unsigned long phys;
+};
+
 #define DMA_BUF_SYNC_READ      (1 << 0)
 #define DMA_BUF_SYNC_WRITE     (2 << 0)
 #define DMA_BUF_SYNC_RW        (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE)
@@ -37,5 +41,6 @@ struct dma_buf_sync {
 
 #define DMA_BUF_BASE		'b'
 #define DMA_BUF_IOCTL_SYNC	_IOW(DMA_BUF_BASE, 0, struct dma_buf_sync)
+#define DMA_BUF_IOCTL_PHYS	_IOW(DMA_BUF_BASE, 1, struct dma_buf_phys)
 
 #endif
-- 
GitLab