From: Will Deacon <will.deacon-5wv7dgnIgG8@public.gmane.org>
To: Robin Murphy <Robin.Murphy-5wv7dgnIgG8@public.gmane.org>
Cc: "linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org"
<linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org>,
"arnd-r2nGTMty4D4@public.gmane.org"
<arnd-r2nGTMty4D4@public.gmane.org>,
"stefano.stabellini-mvvWK6WmYclDPfheJLI6IQ@public.gmane.org"
<stefano.stabellini-mvvWK6WmYclDPfheJLI6IQ@public.gmane.org>,
Catalin Marinas <Catalin.Marinas-5wv7dgnIgG8@public.gmane.org>,
"iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org"
<iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org>,
"thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org"
<thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org>,
"dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org"
<dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org>,
"linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org"
<linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>
Subject: Re: [RFC PATCH 4/5] arm64: add IOMMU dma_ops
Date: Fri, 23 Jan 2015 15:26:05 +0000 [thread overview]
Message-ID: <20150123152605.GA31460@arm.com> (raw)
In-Reply-To: <aa7de3b1dd189c31eb8b14d0c0eea699183f8a2c.1421086706.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>
On Mon, Jan 12, 2015 at 08:48:56PM +0000, Robin Murphy wrote:
> Taking some inspiration from the arch/arm code, implement the
> arch-specific side of the DMA mapping ops using the new IOMMU-DMA layer.
>
> Signed-off-by: Robin Murphy <robin.murphy-5wv7dgnIgG8@public.gmane.org>
> ---
> arch/arm64/include/asm/device.h | 3 +
> arch/arm64/include/asm/dma-mapping.h | 12 ++
> arch/arm64/mm/dma-mapping.c | 297 +++++++++++++++++++++++++++++++++++
> 3 files changed, 312 insertions(+)
>
> diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
> index 243ef25..c17f100 100644
> --- a/arch/arm64/include/asm/device.h
> +++ b/arch/arm64/include/asm/device.h
> @@ -20,6 +20,9 @@ struct dev_archdata {
> struct dma_map_ops *dma_ops;
> #ifdef CONFIG_IOMMU_API
> void *iommu; /* private IOMMU data */
> +#ifdef CONFIG_IOMMU_DMA
> + struct iommu_dma_mapping *mapping;
> +#endif
> #endif
> bool dma_coherent;
> };
> diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
> index 6932bb5..82082c4 100644
> --- a/arch/arm64/include/asm/dma-mapping.h
> +++ b/arch/arm64/include/asm/dma-mapping.h
> @@ -64,11 +64,23 @@ static inline bool is_device_dma_coherent(struct device *dev)
>
> static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> {
> +#ifdef CONFIG_IOMMU_DMA
> + /* We don't have an easy way of dealing with this... */
> + BUG_ON(dev->archdata.mapping);
> +#endif
> return (dma_addr_t)paddr;
> }
>
> +#ifdef CONFIG_IOMMU_DMA
> +phys_addr_t iova_to_phys(struct device *dev, dma_addr_t dev_addr);
I think this name is a bit too generic, especially as we already have an
iommu_iova_to_phys function in drivers/iommu/iommu.c
In fact, can't you just make CONFIG_IOMMU_DMA depend on IOMMU_API and then
use iommu_iova_to_phys instead?
> +#endif
> +
> static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
> {
> +#ifdef CONFIG_IOMMU_DMA
> + if (dev->archdata.mapping)
> + return iova_to_phys(dev, dev_addr);
> +#endif
> return (phys_addr_t)dev_addr;
> }
It would be cleaner just to define these functions twice; with and without
the CONFIG_IOMMU_DMA case.
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 0a24b9b..8e449a7 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -23,6 +23,7 @@
> #include <linux/genalloc.h>
> #include <linux/dma-mapping.h>
> #include <linux/dma-contiguous.h>
> +#include <linux/dma-iommu.h>
> #include <linux/vmalloc.h>
> #include <linux/swiotlb.h>
>
> @@ -426,6 +427,9 @@ static int __init arm64_dma_init(void)
>
> ret |= swiotlb_late_init();
> ret |= atomic_pool_init();
> +#ifdef CONFIG_IOMMU_DMA
> + ret |= iommu_dma_init();
> +#endif
Same here, just make an empty iommu_dma_init if !CONFIG_IOMMU_DMA.
> return ret;
> }
> @@ -439,3 +443,296 @@ static int __init dma_debug_do_init(void)
> return 0;
> }
> fs_initcall(dma_debug_do_init);
> +
> +
> +#ifdef CONFIG_IOMMU_DMA
> +
> +static struct page **__atomic_get_pages(void *addr)
> +{
> + struct page *page;
> + phys_addr_t phys;
> +
> + phys = gen_pool_virt_to_phys(atomic_pool, (unsigned long)addr);
> + page = phys_to_page(phys);
> +
> + return (struct page **)page;
> +}
> +
> +static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
> +{
> + struct vm_struct *area;
> +
> + if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
> + return __atomic_get_pages(cpu_addr);
> +
> + area = find_vm_area(cpu_addr);
> + if (!area)
> + return NULL;
> +
> + return area->pages;
> +}
> +
> +static void *__iommu_alloc_atomic(struct device *dev, size_t size,
> + dma_addr_t *handle, bool coherent)
> +{
> + struct page *page;
> + void *addr;
> +
> + addr = __alloc_from_pool(size, &page);
> + if (!addr)
> + return NULL;
> +
> + *handle = iommu_dma_create_iova_mapping(dev, &page, size, coherent);
> + if (*handle == DMA_ERROR_CODE) {
> + __free_from_pool(addr, size);
> + return NULL;
> + }
> + return addr;
> +}
> +
> +static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
> + dma_addr_t handle, size_t size)
> +{
> + iommu_dma_release_iova_mapping(dev, handle, size);
> + __free_from_pool(cpu_addr, size);
> +}
> +
> +static void __dma_clear_buffer(struct page *page, size_t size)
> +{
> + void *ptr = page_address(page);
> +
> + memset(ptr, 0, size);
> + __dma_flush_range(ptr, ptr + size);
> +}
> +
> +static void *__iommu_alloc_attrs(struct device *dev, size_t size,
> + dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> +{
> + bool coherent = is_device_dma_coherent(dev);
> + pgprot_t prot = coherent ? __pgprot(PROT_NORMAL) :
> + __pgprot(PROT_NORMAL_NC);
> + struct page **pages;
> + void *addr = NULL;
> +
> + *handle = DMA_ERROR_CODE;
> + size = PAGE_ALIGN(size);
> +
> + if (!(gfp & __GFP_WAIT))
> + return __iommu_alloc_atomic(dev, size, handle, coherent);
> + /*
> + * Following is a work-around (a.k.a. hack) to prevent pages
> + * with __GFP_COMP being passed to split_page() which cannot
> + * handle them. The real problem is that this flag probably
> + * should be 0 on ARM as it is not supported on this
> + * platform; see CONFIG_HUGETLBFS.
> + */
> + gfp &= ~(__GFP_COMP);
This comment seems to have been copied from avr32 to arm to arm64 and has
the assumption that the architecture in question doesn't support hugepages.
That's not a valid assumption on LPAE ARM or arm64, so I'd like to get to
the bottom of this.
Will
WARNING: multiple messages have this Message-ID (diff)
From: will.deacon@arm.com (Will Deacon)
To: linux-arm-kernel@lists.infradead.org
Subject: [RFC PATCH 4/5] arm64: add IOMMU dma_ops
Date: Fri, 23 Jan 2015 15:26:05 +0000 [thread overview]
Message-ID: <20150123152605.GA31460@arm.com> (raw)
In-Reply-To: <aa7de3b1dd189c31eb8b14d0c0eea699183f8a2c.1421086706.git.robin.murphy@arm.com>
On Mon, Jan 12, 2015 at 08:48:56PM +0000, Robin Murphy wrote:
> Taking some inspiration from the arch/arm code, implement the
> arch-specific side of the DMA mapping ops using the new IOMMU-DMA layer.
>
> Signed-off-by: Robin Murphy <robin.murphy@arm.com>
> ---
> arch/arm64/include/asm/device.h | 3 +
> arch/arm64/include/asm/dma-mapping.h | 12 ++
> arch/arm64/mm/dma-mapping.c | 297 +++++++++++++++++++++++++++++++++++
> 3 files changed, 312 insertions(+)
>
> diff --git a/arch/arm64/include/asm/device.h b/arch/arm64/include/asm/device.h
> index 243ef25..c17f100 100644
> --- a/arch/arm64/include/asm/device.h
> +++ b/arch/arm64/include/asm/device.h
> @@ -20,6 +20,9 @@ struct dev_archdata {
> struct dma_map_ops *dma_ops;
> #ifdef CONFIG_IOMMU_API
> void *iommu; /* private IOMMU data */
> +#ifdef CONFIG_IOMMU_DMA
> + struct iommu_dma_mapping *mapping;
> +#endif
> #endif
> bool dma_coherent;
> };
> diff --git a/arch/arm64/include/asm/dma-mapping.h b/arch/arm64/include/asm/dma-mapping.h
> index 6932bb5..82082c4 100644
> --- a/arch/arm64/include/asm/dma-mapping.h
> +++ b/arch/arm64/include/asm/dma-mapping.h
> @@ -64,11 +64,23 @@ static inline bool is_device_dma_coherent(struct device *dev)
>
> static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
> {
> +#ifdef CONFIG_IOMMU_DMA
> + /* We don't have an easy way of dealing with this... */
> + BUG_ON(dev->archdata.mapping);
> +#endif
> return (dma_addr_t)paddr;
> }
>
> +#ifdef CONFIG_IOMMU_DMA
> +phys_addr_t iova_to_phys(struct device *dev, dma_addr_t dev_addr);
I think this name is a bit too generic, especially as we already have an
iommu_iova_to_phys function in drivers/iommu/iommu.c
In fact, can't you just make CONFIG_IOMMU_DMA depend on IOMMU_API and then
use iommu_iova_to_phys instead?
> +#endif
> +
> static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t dev_addr)
> {
> +#ifdef CONFIG_IOMMU_DMA
> + if (dev->archdata.mapping)
> + return iova_to_phys(dev, dev_addr);
> +#endif
> return (phys_addr_t)dev_addr;
> }
It would be cleaner just to define these functions twice; with and without
the CONFIG_IOMMU_DMA case.
> diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
> index 0a24b9b..8e449a7 100644
> --- a/arch/arm64/mm/dma-mapping.c
> +++ b/arch/arm64/mm/dma-mapping.c
> @@ -23,6 +23,7 @@
> #include <linux/genalloc.h>
> #include <linux/dma-mapping.h>
> #include <linux/dma-contiguous.h>
> +#include <linux/dma-iommu.h>
> #include <linux/vmalloc.h>
> #include <linux/swiotlb.h>
>
> @@ -426,6 +427,9 @@ static int __init arm64_dma_init(void)
>
> ret |= swiotlb_late_init();
> ret |= atomic_pool_init();
> +#ifdef CONFIG_IOMMU_DMA
> + ret |= iommu_dma_init();
> +#endif
Same here, just make an empty iommu_dma_init if !CONFIG_IOMMU_DMA.
> return ret;
> }
> @@ -439,3 +443,296 @@ static int __init dma_debug_do_init(void)
> return 0;
> }
> fs_initcall(dma_debug_do_init);
> +
> +
> +#ifdef CONFIG_IOMMU_DMA
> +
> +static struct page **__atomic_get_pages(void *addr)
> +{
> + struct page *page;
> + phys_addr_t phys;
> +
> + phys = gen_pool_virt_to_phys(atomic_pool, (unsigned long)addr);
> + page = phys_to_page(phys);
> +
> + return (struct page **)page;
> +}
> +
> +static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
> +{
> + struct vm_struct *area;
> +
> + if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
> + return __atomic_get_pages(cpu_addr);
> +
> + area = find_vm_area(cpu_addr);
> + if (!area)
> + return NULL;
> +
> + return area->pages;
> +}
> +
> +static void *__iommu_alloc_atomic(struct device *dev, size_t size,
> + dma_addr_t *handle, bool coherent)
> +{
> + struct page *page;
> + void *addr;
> +
> + addr = __alloc_from_pool(size, &page);
> + if (!addr)
> + return NULL;
> +
> + *handle = iommu_dma_create_iova_mapping(dev, &page, size, coherent);
> + if (*handle == DMA_ERROR_CODE) {
> + __free_from_pool(addr, size);
> + return NULL;
> + }
> + return addr;
> +}
> +
> +static void __iommu_free_atomic(struct device *dev, void *cpu_addr,
> + dma_addr_t handle, size_t size)
> +{
> + iommu_dma_release_iova_mapping(dev, handle, size);
> + __free_from_pool(cpu_addr, size);
> +}
> +
> +static void __dma_clear_buffer(struct page *page, size_t size)
> +{
> + void *ptr = page_address(page);
> +
> + memset(ptr, 0, size);
> + __dma_flush_range(ptr, ptr + size);
> +}
> +
> +static void *__iommu_alloc_attrs(struct device *dev, size_t size,
> + dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
> +{
> + bool coherent = is_device_dma_coherent(dev);
> + pgprot_t prot = coherent ? __pgprot(PROT_NORMAL) :
> + __pgprot(PROT_NORMAL_NC);
> + struct page **pages;
> + void *addr = NULL;
> +
> + *handle = DMA_ERROR_CODE;
> + size = PAGE_ALIGN(size);
> +
> + if (!(gfp & __GFP_WAIT))
> + return __iommu_alloc_atomic(dev, size, handle, coherent);
> + /*
> + * Following is a work-around (a.k.a. hack) to prevent pages
> + * with __GFP_COMP being passed to split_page() which cannot
> + * handle them. The real problem is that this flag probably
> + * should be 0 on ARM as it is not supported on this
> + * platform; see CONFIG_HUGETLBFS.
> + */
> + gfp &= ~(__GFP_COMP);
This comment seems to have been copied from avr32 to arm to arm64 and has
the assumption that the architecture in question doesn't support hugepages.
That's not a valid assumption on LPAE ARM or arm64, so I'd like to get to
the bottom of this.
Will
next prev parent reply other threads:[~2015-01-23 15:26 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-12 20:48 [RFC PATCH 0/5] arm64: IOMMU-backed DMA mapping Robin Murphy
2015-01-12 20:48 ` Robin Murphy
2015-01-13 8:02 ` Yingjoe Chen
2015-01-13 8:02 ` Yingjoe Chen
2015-01-13 12:07 ` Robin Murphy
2015-01-13 12:07 ` Robin Murphy
2015-01-15 18:35 ` Robin Murphy
2015-01-15 18:35 ` Robin Murphy
2015-01-16 7:21 ` Yong Wu
2015-01-16 7:21 ` Yong Wu
2015-01-16 20:12 ` Robin Murphy
2015-01-16 20:12 ` Robin Murphy
[not found] ` <cover.1421086706.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>
2015-01-12 20:48 ` [RFC PATCH 1/5] arm64: Combine coherent and non-coherent swiotlb dma_ops Robin Murphy
2015-01-12 20:48 ` Robin Murphy
2015-01-12 20:48 ` [RFC PATCH 2/5] arm64: implement generic IOMMU configuration Robin Murphy
2015-01-12 20:48 ` Robin Murphy
2015-01-12 20:48 ` [RFC PATCH 3/5] iommu: implement common IOMMU ops for DMA mapping Robin Murphy
2015-01-12 20:48 ` Robin Murphy
[not found] ` <09e5515a9afcb3235f4c425520cd18a6032d31b4.1421086706.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>
2015-01-23 17:42 ` Laura Abbott
2015-01-23 17:42 ` Laura Abbott
[not found] ` <54C287F7.3060603-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-01-23 18:14 ` Robin Murphy
2015-01-23 18:14 ` Robin Murphy
2015-01-27 0:21 ` Joerg Roedel
2015-01-27 0:21 ` Joerg Roedel
[not found] ` <20150127002116.GI30345-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-01-27 12:27 ` Robin Murphy
2015-01-27 12:27 ` Robin Murphy
[not found] ` <54C7843B.3000605-5wv7dgnIgG8@public.gmane.org>
2015-01-27 12:38 ` Joerg Roedel
2015-01-27 12:38 ` Joerg Roedel
[not found] ` <20150127123809.GJ30345-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2015-01-28 13:53 ` Will Deacon
2015-01-28 13:53 ` Will Deacon
2015-01-12 20:48 ` [RFC PATCH 4/5] arm64: add IOMMU dma_ops Robin Murphy
2015-01-12 20:48 ` Robin Murphy
[not found] ` <aa7de3b1dd189c31eb8b14d0c0eea699183f8a2c.1421086706.git.robin.murphy-5wv7dgnIgG8@public.gmane.org>
2015-01-23 15:26 ` Will Deacon [this message]
2015-01-23 15:26 ` Will Deacon
[not found] ` <20150123152605.GA31460-5wv7dgnIgG8@public.gmane.org>
2015-01-23 17:33 ` Robin Murphy
2015-01-23 17:33 ` Robin Murphy
2015-01-26 3:25 ` Joseph Lo
2015-01-26 3:25 ` Joseph Lo
[not found] ` <54C5B3B9.1040300-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org>
2015-01-27 17:30 ` Robin Murphy
2015-01-27 17:30 ` Robin Murphy
2015-01-26 9:10 ` Joseph Lo
2015-01-26 9:10 ` Joseph Lo
2015-01-28 2:22 ` Joseph Lo
2015-01-28 2:22 ` Joseph Lo
2015-03-05 14:31 ` Marek Szyprowski
2015-03-05 14:31 ` Marek Szyprowski
2015-01-12 20:48 ` [RFC PATCH 5/5] arm64: hook up " Robin Murphy
2015-01-12 20:48 ` Robin Murphy
2015-01-13 11:08 ` [RFC PATCH 0/5] arm64: IOMMU-backed DMA mapping Stefano Stabellini
2015-01-13 11:08 ` Stefano Stabellini
[not found] ` <alpine.DEB.2.02.1501131102540.3058-7Z66fg9igcxYtxbxJUhB2Dgeux46jI+i@public.gmane.org>
2015-01-13 11:45 ` Robin Murphy
2015-01-13 11:45 ` Robin Murphy
2015-01-23 16:47 ` Catalin Marinas
2015-01-23 16:47 ` Catalin Marinas
[not found] ` <20150123164759.GF9557-M2fw3Uu6cmfZROr8t4l/smS4ubULX0JqMm0uRHvK7Nw@public.gmane.org>
2015-01-23 17:41 ` Robin Murphy
2015-01-23 17:41 ` Robin Murphy
2015-03-05 14:31 ` Marek Szyprowski
2015-03-05 14:31 ` Marek Szyprowski
[not found] ` <54F868A8.7070103-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org>
2015-03-05 16:42 ` Robin Murphy
2015-03-05 16:42 ` Robin Murphy
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150123152605.GA31460@arm.com \
--to=will.deacon-5wv7dgnigg8@public.gmane.org \
--cc=Catalin.Marinas-5wv7dgnIgG8@public.gmane.org \
--cc=Robin.Murphy-5wv7dgnIgG8@public.gmane.org \
--cc=arnd-r2nGTMty4D4@public.gmane.org \
--cc=dwmw2-wEGCiKHe2LqWVfeAwA7xHQ@public.gmane.org \
--cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-lFZ/pmaqli7XmaaqVzeoHQ@public.gmane.org \
--cc=stefano.stabellini-mvvWK6WmYclDPfheJLI6IQ@public.gmane.org \
--cc=thunder.leizhen-hv44wF8Li93QT0dZR+AlfA@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.