From: Christoph Hellwig <hch@lst.de>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Joerg Roedel <joro@8bytes.org>, Will Deacon <will.deacon@arm.com>,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
Christoph Hellwig <hch@lst.de>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers
Date: Fri, 19 Apr 2019 10:23:48 +0200 [thread overview]
Message-ID: <20190419082348.GA22299@lst.de> (raw)
In-Reply-To: <228ee57a-d7b2-48e0-a34e-81d5fba0a090@arm.com>
On Thu, Apr 18, 2019 at 07:15:00PM +0100, Robin Murphy wrote:
> Still, I've worked in the vm_map_pages() stuff pending in MM and given them
> the same treatment to finish the picture. Both x86_64_defconfig and
> i386_defconfig do indeed compile and link fine as I expected, so I really
> would like to understand the concern around #ifdefs better.
This looks generally fine to me. One thing I'd like to do is to
generally make use of the fact that __iommu_dma_get_pages returns NULL
for the force contigous case as that cleans up a few things. Also
for the !DMA_REMAP case we need to try the page allocator when
dma_alloc_from_contiguous does not return a page. What do you thing
of the following incremental diff? If that is fine with you I can
fold that in and add back in the remaining patches from my series
not obsoleted by your patches and resend.
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1bc8d1de1a1d..50b44e220de3 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -894,7 +894,7 @@ static void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
{
- struct page *page, **pages;
+ struct page *page = NULL;
int count = size >> PAGE_SHIFT;
/* Non-coherent atomic allocation? Easy */
@@ -902,24 +902,26 @@ static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
dma_free_from_pool(cpu_addr, size))
return;
- /* Lowmem means a coherent atomic or CMA allocation */
- if (!IS_ENABLED(CONFIG_DMA_REMAP) || !is_vmalloc_addr(cpu_addr)) {
- page = virt_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
- return;
- }
- /*
- * If it's remapped, then it's either non-coherent or highmem CMA, or
- * an iommu_dma_alloc_remap() construction.
- */
- page = vmalloc_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count)) {
- pages = __iommu_dma_get_pages(cpu_addr);
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ /*
+ * If it the address is remapped, then it's either non-coherent
+ * or highmem CMA, or an iommu_dma_alloc_remap() construction.
+ */
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
if (pages)
__iommu_dma_free_pages(pages, count);
+ else
+ page = vmalloc_to_page(cpu_addr);
+
+ dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+ } else {
+ /* Lowmem means a coherent atomic or CMA allocation */
+ page = virt_to_page(cpu_addr);
}
- dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+
+ if (page && !dma_release_from_contiguous(dev, page, count))
+ __free_pages(page, get_order(size));
}
static void *iommu_dma_alloc(struct device *dev, size_t size,
@@ -935,25 +937,26 @@ static void *iommu_dma_alloc(struct device *dev, size_t size,
gfp |= __GFP_ZERO;
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && gfpflags_allow_blocking(gfp) &&
+ !(attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
+
if (!gfpflags_allow_blocking(gfp)) {
- if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent)
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent) {
cpu_addr = dma_alloc_from_pool(alloc_size, &page, gfp);
- else
- page = alloc_pages(gfp, page_order);
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (!cpu_addr)
+ return NULL;
+ goto do_iommu_map;
+ }
+ } else {
page = dma_alloc_from_contiguous(dev, count, page_order,
gfp & __GFP_NOWARN);
- } else {
- return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
}
-
+ if (!page)
+ page = alloc_pages(gfp, page_order);
if (!page)
return NULL;
- if (cpu_addr)
- goto do_iommu_map;
-
if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
@@ -1007,16 +1010,14 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
if (off >= nr_pages || vma_pages(vma) > nr_pages - off)
return -ENXIO;
- if (!is_vmalloc_addr(cpu_addr)) {
- pfn = page_to_pfn(virt_to_page(cpu_addr));
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return vm_map_pages(vma, pages, nr_pages);
pfn = vmalloc_to_pfn(cpu_addr);
} else {
- struct page **pages = __iommu_dma_get_pages(cpu_addr);
- if (!pages)
- return -ENXIO;
- return vm_map_pages(vma, pages, nr_pages);
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
}
return remap_pfn_range(vma, vma->vm_start, pfn + off,
@@ -1028,26 +1029,25 @@ static int iommu_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
- struct page *page = NULL, **pages = NULL;
- int ret = -ENXIO;
+ struct page *page;
+ int ret;
- if (!is_vmalloc_addr(cpu_addr))
- page = virt_to_page(cpu_addr);
- else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return sg_alloc_table_from_pages(sgt,
+ __iommu_dma_get_pages(cpu_addr),
+ PAGE_ALIGN(size) >> PAGE_SHIFT, 0, size,
+ GFP_KERNEL);
page = vmalloc_to_page(cpu_addr);
- else
- pages = __iommu_dma_get_pages(cpu_addr);
-
- if (page) {
- ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
- if (!ret)
- sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
- } else if (pages) {
- ret = sg_alloc_table_from_pages(sgt, pages,
- PAGE_ALIGN(size) >> PAGE_SHIFT,
- 0, size, GFP_KERNEL);
+ } else {
+ page = virt_to_page(cpu_addr);
}
+
+ ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+ if (!ret)
+ sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
return ret;
}
WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will.deacon@arm.com>,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
Christoph Hellwig <hch@lst.de>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers
Date: Fri, 19 Apr 2019 10:23:48 +0200 [thread overview]
Message-ID: <20190419082348.GA22299@lst.de> (raw)
Message-ID: <20190419082348.0MpeoeTNzI9TWowhYhBxpiWsiNNCVPRuC-3rzsz1cEA@z> (raw)
In-Reply-To: <228ee57a-d7b2-48e0-a34e-81d5fba0a090@arm.com>
On Thu, Apr 18, 2019 at 07:15:00PM +0100, Robin Murphy wrote:
> Still, I've worked in the vm_map_pages() stuff pending in MM and given them
> the same treatment to finish the picture. Both x86_64_defconfig and
> i386_defconfig do indeed compile and link fine as I expected, so I really
> would like to understand the concern around #ifdefs better.
This looks generally fine to me. One thing I'd like to do is to
generally make use of the fact that __iommu_dma_get_pages returns NULL
for the force contigous case as that cleans up a few things. Also
for the !DMA_REMAP case we need to try the page allocator when
dma_alloc_from_contiguous does not return a page. What do you thing
of the following incremental diff? If that is fine with you I can
fold that in and add back in the remaining patches from my series
not obsoleted by your patches and resend.
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1bc8d1de1a1d..50b44e220de3 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -894,7 +894,7 @@ static void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
{
- struct page *page, **pages;
+ struct page *page = NULL;
int count = size >> PAGE_SHIFT;
/* Non-coherent atomic allocation? Easy */
@@ -902,24 +902,26 @@ static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
dma_free_from_pool(cpu_addr, size))
return;
- /* Lowmem means a coherent atomic or CMA allocation */
- if (!IS_ENABLED(CONFIG_DMA_REMAP) || !is_vmalloc_addr(cpu_addr)) {
- page = virt_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
- return;
- }
- /*
- * If it's remapped, then it's either non-coherent or highmem CMA, or
- * an iommu_dma_alloc_remap() construction.
- */
- page = vmalloc_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count)) {
- pages = __iommu_dma_get_pages(cpu_addr);
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ /*
+ * If it the address is remapped, then it's either non-coherent
+ * or highmem CMA, or an iommu_dma_alloc_remap() construction.
+ */
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
if (pages)
__iommu_dma_free_pages(pages, count);
+ else
+ page = vmalloc_to_page(cpu_addr);
+
+ dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+ } else {
+ /* Lowmem means a coherent atomic or CMA allocation */
+ page = virt_to_page(cpu_addr);
}
- dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+
+ if (page && !dma_release_from_contiguous(dev, page, count))
+ __free_pages(page, get_order(size));
}
static void *iommu_dma_alloc(struct device *dev, size_t size,
@@ -935,25 +937,26 @@ static void *iommu_dma_alloc(struct device *dev, size_t size,
gfp |= __GFP_ZERO;
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && gfpflags_allow_blocking(gfp) &&
+ !(attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
+
if (!gfpflags_allow_blocking(gfp)) {
- if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent)
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent) {
cpu_addr = dma_alloc_from_pool(alloc_size, &page, gfp);
- else
- page = alloc_pages(gfp, page_order);
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (!cpu_addr)
+ return NULL;
+ goto do_iommu_map;
+ }
+ } else {
page = dma_alloc_from_contiguous(dev, count, page_order,
gfp & __GFP_NOWARN);
- } else {
- return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
}
-
+ if (!page)
+ page = alloc_pages(gfp, page_order);
if (!page)
return NULL;
- if (cpu_addr)
- goto do_iommu_map;
-
if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
@@ -1007,16 +1010,14 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
if (off >= nr_pages || vma_pages(vma) > nr_pages - off)
return -ENXIO;
- if (!is_vmalloc_addr(cpu_addr)) {
- pfn = page_to_pfn(virt_to_page(cpu_addr));
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return vm_map_pages(vma, pages, nr_pages);
pfn = vmalloc_to_pfn(cpu_addr);
} else {
- struct page **pages = __iommu_dma_get_pages(cpu_addr);
- if (!pages)
- return -ENXIO;
- return vm_map_pages(vma, pages, nr_pages);
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
}
return remap_pfn_range(vma, vma->vm_start, pfn + off,
@@ -1028,26 +1029,25 @@ static int iommu_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
- struct page *page = NULL, **pages = NULL;
- int ret = -ENXIO;
+ struct page *page;
+ int ret;
- if (!is_vmalloc_addr(cpu_addr))
- page = virt_to_page(cpu_addr);
- else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return sg_alloc_table_from_pages(sgt,
+ __iommu_dma_get_pages(cpu_addr),
+ PAGE_ALIGN(size) >> PAGE_SHIFT, 0, size,
+ GFP_KERNEL);
page = vmalloc_to_page(cpu_addr);
- else
- pages = __iommu_dma_get_pages(cpu_addr);
-
- if (page) {
- ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
- if (!ret)
- sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
- } else if (pages) {
- ret = sg_alloc_table_from_pages(sgt, pages,
- PAGE_ALIGN(size) >> PAGE_SHIFT,
- 0, size, GFP_KERNEL);
+ } else {
+ page = virt_to_page(cpu_addr);
}
+
+ ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+ if (!ret)
+ sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
return ret;
}
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>,
Catalin Marinas <catalin.marinas@arm.com>,
Joerg Roedel <joro@8bytes.org>, Will Deacon <will.deacon@arm.com>,
linux-kernel@vger.kernel.org, iommu@lists.linux-foundation.org,
Christoph Hellwig <hch@lst.de>,
linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers
Date: Fri, 19 Apr 2019 10:23:48 +0200 [thread overview]
Message-ID: <20190419082348.GA22299@lst.de> (raw)
In-Reply-To: <228ee57a-d7b2-48e0-a34e-81d5fba0a090@arm.com>
On Thu, Apr 18, 2019 at 07:15:00PM +0100, Robin Murphy wrote:
> Still, I've worked in the vm_map_pages() stuff pending in MM and given them
> the same treatment to finish the picture. Both x86_64_defconfig and
> i386_defconfig do indeed compile and link fine as I expected, so I really
> would like to understand the concern around #ifdefs better.
This looks generally fine to me. One thing I'd like to do is to
generally make use of the fact that __iommu_dma_get_pages returns NULL
for the force contigous case as that cleans up a few things. Also
for the !DMA_REMAP case we need to try the page allocator when
dma_alloc_from_contiguous does not return a page. What do you thing
of the following incremental diff? If that is fine with you I can
fold that in and add back in the remaining patches from my series
not obsoleted by your patches and resend.
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1bc8d1de1a1d..50b44e220de3 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -894,7 +894,7 @@ static void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
{
- struct page *page, **pages;
+ struct page *page = NULL;
int count = size >> PAGE_SHIFT;
/* Non-coherent atomic allocation? Easy */
@@ -902,24 +902,26 @@ static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
dma_free_from_pool(cpu_addr, size))
return;
- /* Lowmem means a coherent atomic or CMA allocation */
- if (!IS_ENABLED(CONFIG_DMA_REMAP) || !is_vmalloc_addr(cpu_addr)) {
- page = virt_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
- return;
- }
- /*
- * If it's remapped, then it's either non-coherent or highmem CMA, or
- * an iommu_dma_alloc_remap() construction.
- */
- page = vmalloc_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count)) {
- pages = __iommu_dma_get_pages(cpu_addr);
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ /*
+ * If it the address is remapped, then it's either non-coherent
+ * or highmem CMA, or an iommu_dma_alloc_remap() construction.
+ */
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
if (pages)
__iommu_dma_free_pages(pages, count);
+ else
+ page = vmalloc_to_page(cpu_addr);
+
+ dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+ } else {
+ /* Lowmem means a coherent atomic or CMA allocation */
+ page = virt_to_page(cpu_addr);
}
- dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+
+ if (page && !dma_release_from_contiguous(dev, page, count))
+ __free_pages(page, get_order(size));
}
static void *iommu_dma_alloc(struct device *dev, size_t size,
@@ -935,25 +937,26 @@ static void *iommu_dma_alloc(struct device *dev, size_t size,
gfp |= __GFP_ZERO;
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && gfpflags_allow_blocking(gfp) &&
+ !(attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
+
if (!gfpflags_allow_blocking(gfp)) {
- if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent)
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent) {
cpu_addr = dma_alloc_from_pool(alloc_size, &page, gfp);
- else
- page = alloc_pages(gfp, page_order);
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (!cpu_addr)
+ return NULL;
+ goto do_iommu_map;
+ }
+ } else {
page = dma_alloc_from_contiguous(dev, count, page_order,
gfp & __GFP_NOWARN);
- } else {
- return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
}
-
+ if (!page)
+ page = alloc_pages(gfp, page_order);
if (!page)
return NULL;
- if (cpu_addr)
- goto do_iommu_map;
-
if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
@@ -1007,16 +1010,14 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
if (off >= nr_pages || vma_pages(vma) > nr_pages - off)
return -ENXIO;
- if (!is_vmalloc_addr(cpu_addr)) {
- pfn = page_to_pfn(virt_to_page(cpu_addr));
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return vm_map_pages(vma, pages, nr_pages);
pfn = vmalloc_to_pfn(cpu_addr);
} else {
- struct page **pages = __iommu_dma_get_pages(cpu_addr);
- if (!pages)
- return -ENXIO;
- return vm_map_pages(vma, pages, nr_pages);
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
}
return remap_pfn_range(vma, vma->vm_start, pfn + off,
@@ -1028,26 +1029,25 @@ static int iommu_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
- struct page *page = NULL, **pages = NULL;
- int ret = -ENXIO;
+ struct page *page;
+ int ret;
- if (!is_vmalloc_addr(cpu_addr))
- page = virt_to_page(cpu_addr);
- else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return sg_alloc_table_from_pages(sgt,
+ __iommu_dma_get_pages(cpu_addr),
+ PAGE_ALIGN(size) >> PAGE_SHIFT, 0, size,
+ GFP_KERNEL);
page = vmalloc_to_page(cpu_addr);
- else
- pages = __iommu_dma_get_pages(cpu_addr);
-
- if (page) {
- ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
- if (!ret)
- sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
- } else if (pages) {
- ret = sg_alloc_table_from_pages(sgt, pages,
- PAGE_ALIGN(size) >> PAGE_SHIFT,
- 0, size, GFP_KERNEL);
+ } else {
+ page = virt_to_page(cpu_addr);
}
+
+ ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+ if (!ret)
+ sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
return ret;
}
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
WARNING: multiple messages have this Message-ID (diff)
From: Christoph Hellwig <hch@lst.de>
To: Robin Murphy <robin.murphy@arm.com>
Cc: Christoph Hellwig <hch@lst.de>, Joerg Roedel <joro@8bytes.org>,
Catalin Marinas <catalin.marinas@arm.com>,
Will Deacon <will.deacon@arm.com>,
Tom Lendacky <thomas.lendacky@amd.com>,
iommu@lists.linux-foundation.org,
linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers
Date: Fri, 19 Apr 2019 10:23:48 +0200 [thread overview]
Message-ID: <20190419082348.GA22299@lst.de> (raw)
In-Reply-To: <228ee57a-d7b2-48e0-a34e-81d5fba0a090@arm.com>
On Thu, Apr 18, 2019 at 07:15:00PM +0100, Robin Murphy wrote:
> Still, I've worked in the vm_map_pages() stuff pending in MM and given them
> the same treatment to finish the picture. Both x86_64_defconfig and
> i386_defconfig do indeed compile and link fine as I expected, so I really
> would like to understand the concern around #ifdefs better.
This looks generally fine to me. One thing I'd like to do is to
generally make use of the fact that __iommu_dma_get_pages returns NULL
for the force contigous case as that cleans up a few things. Also
for the !DMA_REMAP case we need to try the page allocator when
dma_alloc_from_contiguous does not return a page. What do you thing
of the following incremental diff? If that is fine with you I can
fold that in and add back in the remaining patches from my series
not obsoleted by your patches and resend.
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1bc8d1de1a1d..50b44e220de3 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -894,7 +894,7 @@ static void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
{
- struct page *page, **pages;
+ struct page *page = NULL;
int count = size >> PAGE_SHIFT;
/* Non-coherent atomic allocation? Easy */
@@ -902,24 +902,26 @@ static void __iommu_dma_free(struct device *dev, void *cpu_addr, size_t size)
dma_free_from_pool(cpu_addr, size))
return;
- /* Lowmem means a coherent atomic or CMA allocation */
- if (!IS_ENABLED(CONFIG_DMA_REMAP) || !is_vmalloc_addr(cpu_addr)) {
- page = virt_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count))
- __free_pages(page, get_order(size));
- return;
- }
- /*
- * If it's remapped, then it's either non-coherent or highmem CMA, or
- * an iommu_dma_alloc_remap() construction.
- */
- page = vmalloc_to_page(cpu_addr);
- if (!dma_release_from_contiguous(dev, page, count)) {
- pages = __iommu_dma_get_pages(cpu_addr);
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ /*
+ * If it the address is remapped, then it's either non-coherent
+ * or highmem CMA, or an iommu_dma_alloc_remap() construction.
+ */
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
if (pages)
__iommu_dma_free_pages(pages, count);
+ else
+ page = vmalloc_to_page(cpu_addr);
+
+ dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+ } else {
+ /* Lowmem means a coherent atomic or CMA allocation */
+ page = virt_to_page(cpu_addr);
}
- dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+
+ if (page && !dma_release_from_contiguous(dev, page, count))
+ __free_pages(page, get_order(size));
}
static void *iommu_dma_alloc(struct device *dev, size_t size,
@@ -935,25 +937,26 @@ static void *iommu_dma_alloc(struct device *dev, size_t size,
gfp |= __GFP_ZERO;
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && gfpflags_allow_blocking(gfp) &&
+ !(attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
+
if (!gfpflags_allow_blocking(gfp)) {
- if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent)
+ if (IS_ENABLED(CONFIG_DMA_DIRECT_REMAP) && !coherent) {
cpu_addr = dma_alloc_from_pool(alloc_size, &page, gfp);
- else
- page = alloc_pages(gfp, page_order);
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (!cpu_addr)
+ return NULL;
+ goto do_iommu_map;
+ }
+ } else {
page = dma_alloc_from_contiguous(dev, count, page_order,
gfp & __GFP_NOWARN);
- } else {
- return iommu_dma_alloc_remap(dev, size, handle, gfp, attrs);
}
-
+ if (!page)
+ page = alloc_pages(gfp, page_order);
if (!page)
return NULL;
- if (cpu_addr)
- goto do_iommu_map;
-
if (IS_ENABLED(CONFIG_DMA_REMAP) && (!coherent || PageHighMem(page))) {
pgprot_t prot = arch_dma_mmap_pgprot(dev, PAGE_KERNEL, attrs);
@@ -1007,16 +1010,14 @@ static int iommu_dma_mmap(struct device *dev, struct vm_area_struct *vma,
if (off >= nr_pages || vma_pages(vma) > nr_pages - off)
return -ENXIO;
- if (!is_vmalloc_addr(cpu_addr)) {
- pfn = page_to_pfn(virt_to_page(cpu_addr));
- } else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS)) {
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return vm_map_pages(vma, pages, nr_pages);
pfn = vmalloc_to_pfn(cpu_addr);
} else {
- struct page **pages = __iommu_dma_get_pages(cpu_addr);
- if (!pages)
- return -ENXIO;
- return vm_map_pages(vma, pages, nr_pages);
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
}
return remap_pfn_range(vma, vma->vm_start, pfn + off,
@@ -1028,26 +1029,25 @@ static int iommu_dma_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size,
unsigned long attrs)
{
- struct page *page = NULL, **pages = NULL;
- int ret = -ENXIO;
+ struct page *page;
+ int ret;
- if (!is_vmalloc_addr(cpu_addr))
- page = virt_to_page(cpu_addr);
- else if (!IS_ENABLED(CONFIG_DMA_REMAP) ||
- (attrs & DMA_ATTR_FORCE_CONTIGUOUS))
+ if (IS_ENABLED(CONFIG_DMA_REMAP) && is_vmalloc_addr(cpu_addr)) {
+ struct page **pages = __iommu_dma_get_pages(cpu_addr);
+
+ if (pages)
+ return sg_alloc_table_from_pages(sgt,
+ __iommu_dma_get_pages(cpu_addr),
+ PAGE_ALIGN(size) >> PAGE_SHIFT, 0, size,
+ GFP_KERNEL);
page = vmalloc_to_page(cpu_addr);
- else
- pages = __iommu_dma_get_pages(cpu_addr);
-
- if (page) {
- ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
- if (!ret)
- sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
- } else if (pages) {
- ret = sg_alloc_table_from_pages(sgt, pages,
- PAGE_ALIGN(size) >> PAGE_SHIFT,
- 0, size, GFP_KERNEL);
+ } else {
+ page = virt_to_page(cpu_addr);
}
+
+ ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
+ if (!ret)
+ sg_set_page(sgt->sgl, page, PAGE_ALIGN(size), 0);
return ret;
}
next prev parent reply other threads:[~2019-04-19 8:23 UTC|newest]
Thread overview: 168+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-03-27 8:04 implement generic dma_map_ops for IOMMUs v2 [rebase + resend] Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 01/21] arm64/iommu: handle non-remapped addresses in ->mmap and ->get_sgtable Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 17:16 ` Robin Murphy
2019-04-05 17:16 ` Robin Murphy
2019-04-05 17:16 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 02/21] arm64/iommu: improve mmap bounds checking Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 17:30 ` Robin Murphy
2019-04-05 17:30 ` Robin Murphy
2019-04-05 17:30 ` Robin Murphy
2019-04-07 6:59 ` Christoph Hellwig
2019-04-07 6:59 ` Christoph Hellwig
2019-04-07 6:59 ` Christoph Hellwig
2019-04-09 15:12 ` Robin Murphy
2019-04-09 15:12 ` Robin Murphy
2019-04-09 15:12 ` Robin Murphy
2019-04-09 17:09 ` Christoph Hellwig
2019-04-09 17:09 ` Christoph Hellwig
2019-04-09 17:09 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 04/21] dma-iommu: cleanup dma-iommu.h Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 17:42 ` Robin Murphy
2019-04-05 17:42 ` Robin Murphy
2019-04-05 17:42 ` Robin Murphy
2019-04-09 17:10 ` Christoph Hellwig
2019-04-09 17:10 ` Christoph Hellwig
2019-04-09 17:10 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 05/21] dma-iommu: remove the flush_page callback Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 17:46 ` Robin Murphy
2019-04-05 17:46 ` Robin Murphy
2019-04-05 17:46 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 06/21] dma-iommu: use for_each_sg in iommu_dma_alloc Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 18:08 ` Robin Murphy
2019-04-05 18:08 ` Robin Murphy
2019-04-05 18:08 ` Robin Murphy
[not found] ` <20190327080448.5500-1-hch-jcswGhMUV9g@public.gmane.org>
2019-03-27 8:04 ` [PATCH 03/21] dma-mapping: add a Kconfig symbol to indicated arch_dma_prep_coherent presence Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-05 17:41 ` Robin Murphy
2019-04-05 17:41 ` Robin Murphy
2019-04-05 17:41 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 07/21] dma-iommu: move the arm64 wrappers to common code Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 15:07 ` Robin Murphy
2019-04-09 15:07 ` Robin Murphy
2019-04-09 15:07 ` Robin Murphy
2019-04-09 17:15 ` Christoph Hellwig
2019-04-09 17:15 ` Christoph Hellwig
2019-04-09 17:15 ` Christoph Hellwig
[not found] ` <67573dd3-72c7-692d-bc1a-7edb49ff9551-5wv7dgnIgG8@public.gmane.org>
2019-04-09 17:23 ` Christoph Hellwig
2019-04-09 17:23 ` Christoph Hellwig
2019-04-09 17:23 ` Christoph Hellwig
2019-04-09 17:23 ` Christoph Hellwig
2019-04-09 17:33 ` Robin Murphy
2019-04-09 17:33 ` Robin Murphy
2019-04-09 17:33 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 08/21] dma-iommu: refactor iommu_dma_mmap Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 15:29 ` Robin Murphy
2019-04-09 15:29 ` Robin Murphy
2019-04-09 15:29 ` Robin Murphy
[not found] ` <adf139e2-a595-fa08-e287-f358c06d7e91-5wv7dgnIgG8@public.gmane.org>
2019-04-09 17:25 ` Christoph Hellwig
2019-04-09 17:25 ` Christoph Hellwig
2019-04-09 17:25 ` Christoph Hellwig
2019-04-09 17:25 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 09/21] dma-iommu: refactor iommu_dma_get_sgtable Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 15:49 ` Robin Murphy
2019-04-09 15:49 ` Robin Murphy
2019-04-09 15:49 ` Robin Murphy
2019-04-09 17:26 ` Christoph Hellwig
2019-04-09 17:26 ` Christoph Hellwig
2019-04-09 17:26 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 10/21] dma-iommu: move __iommu_dma_map Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 15:54 ` Robin Murphy
2019-04-09 15:54 ` Robin Murphy
2019-04-09 15:54 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 11/21] dma-iommu: refactor page array remap helpers Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 16:38 ` Robin Murphy
2019-04-09 16:38 ` Robin Murphy
2019-04-09 16:38 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-09 17:59 ` Robin Murphy
2019-04-09 17:59 ` Robin Murphy
2019-04-09 17:59 ` Robin Murphy
2019-04-10 6:11 ` Christoph Hellwig
2019-04-10 6:11 ` Christoph Hellwig
2019-04-10 6:11 ` Christoph Hellwig
2019-04-17 6:33 ` Christoph Hellwig
2019-04-17 6:33 ` Christoph Hellwig
2019-04-17 6:33 ` Christoph Hellwig
2019-04-17 11:54 ` Robin Murphy
2019-04-17 11:54 ` Robin Murphy
2019-04-17 11:54 ` Robin Murphy
2019-04-18 15:06 ` Robin Murphy
2019-04-18 15:06 ` Robin Murphy
2019-04-18 15:06 ` Robin Murphy
2019-04-18 16:35 ` Christoph Hellwig
2019-04-18 16:35 ` Christoph Hellwig
2019-04-18 16:35 ` Christoph Hellwig
2019-04-18 16:35 ` Christoph Hellwig
2019-04-18 16:41 ` Robin Murphy
2019-04-18 16:41 ` Robin Murphy
2019-04-18 16:41 ` Robin Murphy
2019-04-19 9:07 ` Christoph Hellwig
2019-04-19 9:07 ` Christoph Hellwig
2019-04-19 9:07 ` Christoph Hellwig
2019-04-19 9:07 ` Christoph Hellwig
2019-04-23 9:48 ` Robin Murphy
2019-04-23 9:48 ` Robin Murphy
2019-04-23 9:48 ` Robin Murphy
2019-04-18 18:15 ` Robin Murphy
2019-04-18 18:15 ` Robin Murphy
2019-04-18 18:15 ` Robin Murphy
2019-04-19 8:23 ` Christoph Hellwig [this message]
2019-04-19 8:23 ` Christoph Hellwig
2019-04-19 8:23 ` Christoph Hellwig
2019-04-19 8:23 ` Christoph Hellwig
[not found] ` <20190419082348.GA22299-jcswGhMUV9g@public.gmane.org>
2019-04-23 10:01 ` Robin Murphy
2019-04-23 10:01 ` Robin Murphy
2019-04-23 10:01 ` Robin Murphy
2019-04-23 10:01 ` Robin Murphy
2019-04-23 14:52 ` Christoph Hellwig
2019-04-23 14:52 ` Christoph Hellwig
2019-04-23 14:52 ` Christoph Hellwig
2019-04-29 11:49 ` Christoph Hellwig
2019-04-29 11:49 ` Christoph Hellwig
2019-04-29 11:49 ` Christoph Hellwig
2019-04-29 12:02 ` Robin Murphy
2019-04-29 12:02 ` Robin Murphy
2019-04-29 12:02 ` Robin Murphy
2019-04-29 12:02 ` Robin Murphy
2019-04-22 18:03 ` Christoph Hellwig
2019-04-22 18:03 ` Christoph Hellwig
2019-04-22 18:03 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 13/21] dma-iommu: factor contiguous " Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 14/21] dma-iommu: refactor iommu_dma_free Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 15/21] dma-iommu: don't remap contiguous allocations for coherent devices Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 16/21] dma-iommu: factor contiguous remapped allocations into helpers Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 17/21] dma-iommu: refactor iommu_dma_alloc Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 18/21] dma-iommu: don't depend on CONFIG_DMA_DIRECT_REMAP Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 19/21] dma-iommu: switch copyright boilerplace to SPDX Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-03-27 8:04 ` [PATCH 20/21] arm64: switch copyright boilerplace to SPDX in dma-mapping.c Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
2019-04-01 6:28 ` Mukesh Ojha
2019-04-01 6:28 ` Mukesh Ojha
2019-04-01 9:39 ` Robin Murphy
2019-04-01 9:39 ` Robin Murphy
2019-03-27 8:04 ` [PATCH 21/21] arm64: trim includes " Christoph Hellwig
2019-03-27 8:04 ` Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2019-02-13 18:28 implement generic dma_map_ops for IOMMUs v2 Christoph Hellwig
2019-02-13 18:29 ` [PATCH 12/21] dma-iommu: factor atomic pool allocations into helpers Christoph Hellwig
2019-02-13 18:29 ` Christoph Hellwig
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=20190419082348.GA22299@lst.de \
--to=hch@lst.de \
--cc=catalin.marinas@arm.com \
--cc=iommu@lists.linux-foundation.org \
--cc=joro@8bytes.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=robin.murphy@arm.com \
--cc=thomas.lendacky@amd.com \
--cc=will.deacon@arm.com \
/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.