diff options
author | Max Filippov <jcmvbkbc@gmail.com> | 2016-04-25 15:08:52 -0400 |
---|---|---|
committer | Max Filippov <jcmvbkbc@gmail.com> | 2016-12-15 13:41:50 -0500 |
commit | 9d2ffe5c62554f2795859bb661eb138759eee980 (patch) | |
tree | 3093778665a69c88e9f0727d5ee2165078c530cb | |
parent | 3863c58cc742df9e5f9ef0bde7dc135fdc547c19 (diff) |
xtensa: enable HAVE_DMA_CONTIGUOUS
Enable HAVE_DMA_CONTIGUOUS, reserve contiguous memory at bootmem_init,
use dma_alloc_from_contiguous and dma_release_from_contiguous in
xtensa_dma_alloc/free.
This allows for big contiguous DMA buffer allocation from designated
area configured in the device tree.
Signed-off-by: Max Filippov <jcmvbkbc@gmail.com>
-rw-r--r-- | arch/xtensa/Kconfig | 1 | ||||
-rw-r--r-- | arch/xtensa/include/asm/Kbuild | 1 | ||||
-rw-r--r-- | arch/xtensa/kernel/pci-dma.c | 21 | ||||
-rw-r--r-- | arch/xtensa/mm/init.c | 2 |
4 files changed, 21 insertions, 4 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index f61058617ada..f4126cf997a4 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -15,6 +15,7 @@ config XTENSA | |||
15 | select GENERIC_SCHED_CLOCK | 15 | select GENERIC_SCHED_CLOCK |
16 | select HAVE_DEBUG_KMEMLEAK | 16 | select HAVE_DEBUG_KMEMLEAK |
17 | select HAVE_DMA_API_DEBUG | 17 | select HAVE_DMA_API_DEBUG |
18 | select HAVE_DMA_CONTIGUOUS | ||
18 | select HAVE_EXIT_THREAD | 19 | select HAVE_EXIT_THREAD |
19 | select HAVE_FUNCTION_TRACER | 20 | select HAVE_FUNCTION_TRACER |
20 | select HAVE_FUTEX_CMPXCHG if !MMU | 21 | select HAVE_FUTEX_CMPXCHG if !MMU |
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 28cf4c5d65ef..b7fbaa56b51a 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild | |||
@@ -3,6 +3,7 @@ generic-y += bug.h | |||
3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
4 | generic-y += cputime.h | 4 | generic-y += cputime.h |
5 | generic-y += div64.h | 5 | generic-y += div64.h |
6 | generic-y += dma-contiguous.h | ||
6 | generic-y += emergency-restart.h | 7 | generic-y += emergency-restart.h |
7 | generic-y += errno.h | 8 | generic-y += errno.h |
8 | generic-y += exec.h | 9 | generic-y += exec.h |
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index 1e68806d6695..10e5b8acf944 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> | 15 | * Joe Taylor <joe@tensilica.com, joetylr@yahoo.com> |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/dma-contiguous.h> | ||
18 | #include <linux/gfp.h> | 19 | #include <linux/gfp.h> |
19 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
20 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
@@ -146,6 +147,8 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size, | |||
146 | { | 147 | { |
147 | unsigned long ret; | 148 | unsigned long ret; |
148 | unsigned long uncached = 0; | 149 | unsigned long uncached = 0; |
150 | unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
151 | struct page *page = NULL; | ||
149 | 152 | ||
150 | /* ignore region speicifiers */ | 153 | /* ignore region speicifiers */ |
151 | 154 | ||
@@ -153,11 +156,18 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size, | |||
153 | 156 | ||
154 | if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) | 157 | if (dev == NULL || (dev->coherent_dma_mask < 0xffffffff)) |
155 | flag |= GFP_DMA; | 158 | flag |= GFP_DMA; |
156 | ret = (unsigned long)__get_free_pages(flag, get_order(size)); | ||
157 | 159 | ||
158 | if (ret == 0) | 160 | if (gfpflags_allow_blocking(flag)) |
161 | page = dma_alloc_from_contiguous(dev, count, get_order(size)); | ||
162 | |||
163 | if (!page) | ||
164 | page = alloc_pages(flag, get_order(size)); | ||
165 | |||
166 | if (!page) | ||
159 | return NULL; | 167 | return NULL; |
160 | 168 | ||
169 | ret = (unsigned long)page_address(page); | ||
170 | |||
161 | /* We currently don't support coherent memory outside KSEG */ | 171 | /* We currently don't support coherent memory outside KSEG */ |
162 | 172 | ||
163 | BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || | 173 | BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || |
@@ -170,16 +180,19 @@ static void *xtensa_dma_alloc(struct device *dev, size_t size, | |||
170 | return (void *)uncached; | 180 | return (void *)uncached; |
171 | } | 181 | } |
172 | 182 | ||
173 | static void xtensa_dma_free(struct device *hwdev, size_t size, void *vaddr, | 183 | static void xtensa_dma_free(struct device *dev, size_t size, void *vaddr, |
174 | dma_addr_t dma_handle, unsigned long attrs) | 184 | dma_addr_t dma_handle, unsigned long attrs) |
175 | { | 185 | { |
176 | unsigned long addr = (unsigned long)vaddr + | 186 | unsigned long addr = (unsigned long)vaddr + |
177 | XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; | 187 | XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; |
188 | struct page *page = virt_to_page(addr); | ||
189 | unsigned long count = PAGE_ALIGN(size) >> PAGE_SHIFT; | ||
178 | 190 | ||
179 | BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || | 191 | BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || |
180 | addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); | 192 | addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); |
181 | 193 | ||
182 | free_pages(addr, get_order(size)); | 194 | if (!dma_release_from_contiguous(dev, page, count)) |
195 | __free_pages(page, get_order(size)); | ||
183 | } | 196 | } |
184 | 197 | ||
185 | static dma_addr_t xtensa_map_page(struct device *dev, struct page *page, | 198 | static dma_addr_t xtensa_map_page(struct device *dev, struct page *page, |
diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index 80e4cfb2471a..720fe4e8b497 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/nodemask.h> | 26 | #include <linux/nodemask.h> |
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/of_fdt.h> | 28 | #include <linux/of_fdt.h> |
29 | #include <linux/dma-contiguous.h> | ||
29 | 30 | ||
30 | #include <asm/bootparam.h> | 31 | #include <asm/bootparam.h> |
31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
@@ -60,6 +61,7 @@ void __init bootmem_init(void) | |||
60 | max_low_pfn = min(max_pfn, MAX_LOW_PFN); | 61 | max_low_pfn = min(max_pfn, MAX_LOW_PFN); |
61 | 62 | ||
62 | memblock_set_current_limit(PFN_PHYS(max_low_pfn)); | 63 | memblock_set_current_limit(PFN_PHYS(max_low_pfn)); |
64 | dma_contiguous_reserve(PFN_PHYS(max_low_pfn)); | ||
63 | 65 | ||
64 | memblock_dump_all(); | 66 | memblock_dump_all(); |
65 | } | 67 | } |