diff options
author | Liu Gang <gang.liu@freescale.com> | 2014-04-17 10:19:16 (GMT) |
---|---|---|
committer | Jose Rivera <German.Rivera@freescale.com> | 2014-04-18 04:01:01 (GMT) |
commit | 153f2d27a28a543f722fdef20553dd65e8decac1 (patch) | |
tree | ce4da2534869a2295a11d56c9fb64b61af7b8d6d /drivers/uio | |
parent | 0dfc5833cea4f87c5a640aff8a8ecb079af4dde2 (diff) | |
download | linux-fsl-qoriq-153f2d27a28a543f722fdef20553dd65e8decac1.tar.xz |
UIO/DMA: Add dma uio private mmap function
UIO mmap cannot map an unaligned page address, and
the PowerPC DMA register space has an unaligned
page base address. So the mmap for DMA register
address should be supported via a private function.
Signed-off-by: Liu Gang <gang.liu@freescale.com>
Signed-off-by: Minghuan Lian <Minghuan.Lian@freescale.com>
Change-Id: Ic5672dd4f86031fab34830d47e231fb1c46b2070
Reviewed-on: http://git.am.freescale.net:8181/11081
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Mingkai Hu <Mingkai.Hu@freescale.com>
Reviewed-by: Jose Rivera <German.Rivera@freescale.com>
Diffstat (limited to 'drivers/uio')
-rw-r--r-- | drivers/uio/fsl_dma_uio.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/drivers/uio/fsl_dma_uio.c b/drivers/uio/fsl_dma_uio.c index f16a009..899523f 100644 --- a/drivers/uio/fsl_dma_uio.c +++ b/drivers/uio/fsl_dma_uio.c @@ -25,6 +25,7 @@ #include <linux/uio_driver.h> #include <linux/list.h> #include <linux/io.h> +#include <linux/mm.h> static const char dma_uio_version[] = "DMA UIO driver v1.0"; @@ -82,6 +83,32 @@ static irqreturn_t dma_uio_irq_handler(int irq, struct uio_info *dev_info) return IRQ_HANDLED; } +static int dma_uio_mmap(struct uio_info *info, struct vm_area_struct *vma) +{ + int mi; + struct uio_mem *mem; + + if (vma->vm_pgoff < MAX_UIO_MAPS) { + if (info->mem[vma->vm_pgoff].size == 0) + return -EINVAL; + mi = (int)vma->vm_pgoff; + } else + return -EINVAL; + + mem = info->mem + mi; + + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; + + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + + return remap_pfn_range(vma, + vma->vm_start, + mem->addr >> PAGE_SHIFT, + vma->vm_end - vma->vm_start, + vma->vm_page_prot); +} + static int dma_chan_uio_setup(struct dma_chan *dma_ch) { int ret; @@ -112,6 +139,7 @@ static int dma_chan_uio_setup(struct dma_chan *dma_ch) info->uio.handler = dma_uio_irq_handler; info->uio.open = dma_uio_open; info->uio.release = dma_uio_release; + info->uio.mmap = dma_uio_mmap; info->uio.priv = dma_ch; ret = uio_register_device(dma_ch->dev, &info->uio); if (ret) { |