linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stephen Boyd <stephen.boyd@linaro.org>
To: linux-kernel@vger.kernel.org
Cc: linux-arm@lists.infradead.org,
	Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Mimi Zohar <zohar@linux.vnet.ibm.com>,
	Andrew Morton <akpm@linux-foundation.org>,
	Mark Brown <broonie@kernel.org>,
	Laura Abbott <labbott@redhat.com>,
	Robin Murphy <robin.murphy@arm.com>,
	Laura Abbott <lauraa@codeaurora.org>,
	Arnd Bergmann <arnd@arndb.de>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Catalin Marinas <catalin.marinas@arm.com>,
	Will Deacon <will.deacon@arm.com>
Subject: [PATCH 1/4] ARM64: dma: Add support for NO_KERNEL_MAPPING attribute
Date: Tue,  8 Mar 2016 16:22:16 +0700	[thread overview]
Message-ID: <1457428939-26659-2-git-send-email-stephen.boyd@linaro.org> (raw)
In-Reply-To: <1457428939-26659-1-git-send-email-stephen.boyd@linaro.org>

Both the IOMMU and non-IOMMU allocations don't respect the
NO_KERNEL_MAPPING attribute, therefore drivers can't save virtual
address space and time spent mapping large buffers that are
intended only for userspace. Plumb this attribute into the code
for both types of DMA ops.

Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Laura Abbott <lauraa@codeaurora.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
---
 arch/arm64/mm/dma-mapping.c | 39 ++++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 331c4ca6205c..06a593653f23 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -169,6 +169,9 @@ static void *__dma_alloc(struct device *dev, size_t size,
 
 	/* create a coherent mapping */
 	page = virt_to_page(ptr);
+	if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+		return page;
+
 	coherent_ptr = dma_common_contiguous_remap(page, size, VM_USERMAP,
 						   prot, NULL);
 	if (!coherent_ptr)
@@ -194,7 +197,8 @@ static void __dma_free(struct device *dev, size_t size,
 	if (!is_device_dma_coherent(dev)) {
 		if (__free_from_pool(vaddr, size))
 			return;
-		vunmap(vaddr);
+		if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+			vunmap(vaddr);
 	}
 	__dma_free_coherent(dev, size, swiotlb_addr, dma_handle, attrs);
 }
@@ -567,6 +571,9 @@ static void *__iommu_alloc_attrs(struct device *dev, size_t size,
 		if (!pages)
 			return NULL;
 
+		if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+			return pages;
+
 		addr = dma_common_pages_remap(pages, size, VM_USERMAP, prot,
 					      __builtin_return_address(0));
 		if (!addr)
@@ -624,18 +631,32 @@ static void __iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
 		if (WARN_ON(!area || !area->pages))
 			return;
 		iommu_dma_free(dev, area->pages, iosize, &handle);
-		dma_common_free_remap(cpu_addr, size, VM_USERMAP);
+		if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+			dma_common_free_remap(cpu_addr, size, VM_USERMAP);
 	} else {
 		iommu_dma_unmap_page(dev, handle, iosize, 0, NULL);
 		__free_pages(virt_to_page(cpu_addr), get_order(size));
 	}
 }
 
+static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
+{
+	struct vm_struct *area;
+
+	if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
+		return cpu_addr;
+
+	area = find_vm_area(cpu_addr);
+	if (area)
+		return area->pages;
+	return NULL;
+}
+
 static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 			      void *cpu_addr, dma_addr_t dma_addr, size_t size,
 			      struct dma_attrs *attrs)
 {
-	struct vm_struct *area;
+	struct page **pages;
 	int ret;
 
 	vma->vm_page_prot = __get_dma_pgprot(attrs, vma->vm_page_prot,
@@ -644,11 +665,11 @@ static int __iommu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
 	if (dma_mmap_from_coherent(dev, vma, cpu_addr, size, &ret))
 		return ret;
 
-	area = find_vm_area(cpu_addr);
-	if (WARN_ON(!area || !area->pages))
+	pages = __iommu_get_pages(cpu_addr, attrs);
+	if (WARN_ON(!pages))
 		return -ENXIO;
 
-	return iommu_dma_mmap(area->pages, size, vma);
+	return iommu_dma_mmap(pages, size, vma);
 }
 
 static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
@@ -656,12 +677,12 @@ static int __iommu_get_sgtable(struct device *dev, struct sg_table *sgt,
 			       size_t size, struct dma_attrs *attrs)
 {
 	unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
-	struct vm_struct *area = find_vm_area(cpu_addr);
+	struct page **pages = __iommu_get_pages(cpu_addr, attrs);
 
-	if (WARN_ON(!area || !area->pages))
+	if (WARN_ON(!pages))
 		return -ENXIO;
 
-	return sg_alloc_table_from_pages(sgt, area->pages, count, 0, size,
+	return sg_alloc_table_from_pages(sgt, pages, count, 0, size,
 					 GFP_KERNEL);
 }
 
-- 
2.7.0.25.gfc10eb5

  reply	other threads:[~2016-03-08  9:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-03-08  9:22 [RFC/PATCH 0/4] request_firmware() on memory constrained devices Stephen Boyd
2016-03-08  9:22 ` Stephen Boyd [this message]
2016-03-08 13:58   ` [PATCH 1/4] ARM64: dma: Add support for NO_KERNEL_MAPPING attribute Robin Murphy
2016-03-08  9:22 ` [RFC/PATCH 2/4] dma-mapping: Add dma_remap() APIs Stephen Boyd
2016-03-08  9:22 ` [RFC/PATCH 3/4] firmware_class: Provide infrastructure to make fw caching optional Stephen Boyd
2016-03-08  9:22 ` [RFC/PATCH 4/4] firmware: Support requesting firmware directly into DMA memory Stephen Boyd
2016-03-08 11:58   ` Mimi Zohar
     [not found]     ` <20160412172708.28213.21206@sboyd-linaro>
2016-04-12 23:04       ` Mimi Zohar
2016-03-08 13:42   ` Ming Lei
2016-03-09  2:29     ` Mark Brown
2016-03-08  9:32 ` [RFC/PATCH 0/4] request_firmware() on memory constrained devices Alexander Stein
2016-03-08 10:07   ` Stephen Boyd

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=1457428939-26659-2-git-send-email-stephen.boyd@linaro.org \
    --to=stephen.boyd@linaro.org \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=broonie@kernel.org \
    --cc=catalin.marinas@arm.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=labbott@redhat.com \
    --cc=lauraa@codeaurora.org \
    --cc=linux-arm@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    --cc=robin.murphy@arm.com \
    --cc=will.deacon@arm.com \
    --cc=zohar@linux.vnet.ibm.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).