diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 4fb22001b2ca..d5953a30a5a8 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -155,8 +155,22 @@ static long dma_heap_ioctl_allocate(struct file *file, void *data) return 0; } +static int dma_heap_ioctl_get_phys(struct file *file, void *data) +{ +#if IS_ENABLED(CONFIG_NO_GKI) + struct dma_heap *heap = file->private_data; + struct dma_heap_phys_data *phys = data; + + if (heap->ops->get_phys) + return heap->ops->get_phys(heap, phys); +#endif + + return -EINVAL; +} + static unsigned int dma_heap_ioctl_cmds[] = { DMA_HEAP_IOCTL_ALLOC, + DMA_HEAP_IOCTL_GET_PHYS, }; static long dma_heap_ioctl(struct file *file, unsigned int ucmd, @@ -205,6 +219,9 @@ static long dma_heap_ioctl(struct file *file, unsigned int ucmd, case DMA_HEAP_IOCTL_ALLOC: ret = dma_heap_ioctl_allocate(file, kdata); break; + case DMA_HEAP_IOCTL_GET_PHYS: + ret = dma_heap_ioctl_get_phys(file, kdata); + break; default: ret = -ENOTTY; goto err; diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c index 2c0ba561957c..ab6f937eb60d 100644 --- a/drivers/dma-buf/heaps/cma_heap.c +++ b/drivers/dma-buf/heaps/cma_heap.c @@ -21,6 +21,7 @@ #include #include #include +#include struct cma_heap { @@ -440,8 +441,42 @@ static struct dma_buf *cma_heap_allocate(struct dma_heap *heap, return cma_heap_do_allocate(heap, len, fd_flags, heap_flags, false); } +static int cma_heap_get_phys(struct dma_heap *heap, + struct dma_heap_phys_data *phys) +{ + struct cma_heap *cma_heap = dma_heap_get_drvdata(heap); + struct cma_heap_buffer *buffer; + struct dma_buf *dmabuf; + + phys->paddr = (__u64)-1; + + if (IS_ERR_OR_NULL(phys)) + return -EINVAL; + + dmabuf = dma_buf_get(phys->fd); + if (IS_ERR_OR_NULL(dmabuf)) + return -EBADFD; + + buffer = dmabuf->priv; + if (IS_ERR_OR_NULL(buffer)) + goto err; + + if (buffer->heap != cma_heap) + goto err; + + phys->paddr = page_to_phys(buffer->cma_pages); + +err: + dma_buf_put(dmabuf); + + return (phys->paddr == (__u64)-1) ? -EINVAL : 0; +} + static const struct dma_heap_ops cma_heap_ops = { .allocate = cma_heap_allocate, +#if IS_ENABLED(CONFIG_NO_GKI) + .get_phys = cma_heap_get_phys, +#endif }; static struct dma_buf *cma_uncached_heap_allocate(struct dma_heap *heap, diff --git a/include/linux/dma-heap.h b/include/linux/dma-heap.h index e8f0e92c27dd..04a9667adbb0 100644 --- a/include/linux/dma-heap.h +++ b/include/linux/dma-heap.h @@ -11,6 +11,7 @@ #include #include +#include struct dma_heap; @@ -27,6 +28,9 @@ struct dma_heap_ops { unsigned long fd_flags, unsigned long heap_flags); long (*get_pool_size)(struct dma_heap *heap); +#if IS_ENABLED(CONFIG_NO_GKI) + int (*get_phys)(struct dma_heap *heap, struct dma_heap_phys_data *phys); +#endif }; /** diff --git a/include/uapi/linux/dma-heap.h b/include/uapi/linux/dma-heap.h index 6f84fa08e074..a69bdf05d801 100644 --- a/include/uapi/linux/dma-heap.h +++ b/include/uapi/linux/dma-heap.h @@ -39,6 +39,11 @@ struct dma_heap_allocation_data { __u64 heap_flags; }; +struct dma_heap_phys_data { + __u64 paddr; + __u32 fd; +}; + #define DMA_HEAP_IOC_MAGIC 'H' /** @@ -50,4 +55,7 @@ struct dma_heap_allocation_data { #define DMA_HEAP_IOCTL_ALLOC _IOWR(DMA_HEAP_IOC_MAGIC, 0x0,\ struct dma_heap_allocation_data) +#define DMA_HEAP_IOCTL_GET_PHYS _IOWR(DMA_HEAP_IOC_MAGIC, 0x1, \ + struct dma_heap_phys_data) + #endif /* _UAPI_LINUX_DMABUF_POOL_H */