aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-25 12:18:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-25 12:18:59 -0400
commitd484864dd96e1830e7689510597707c1df8cd681 (patch)
tree51551708ba3f26d05575fa91daaf0c0d970a77c3 /include
parentbe87cfb47c5c740f7b17929bcd7c480b228513e0 (diff)
parent0f51596bd39a5c928307ffcffc9ba07f90f42a8b (diff)
Merge branch 'for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping
Pull CMA and ARM DMA-mapping updates from Marek Szyprowski: "These patches contain two major updates for DMA mapping subsystem (mainly for ARM architecture). First one is Contiguous Memory Allocator (CMA) which makes it possible for device drivers to allocate big contiguous chunks of memory after the system has booted. The main difference from the similar frameworks is the fact that CMA allows to transparently reuse the memory region reserved for the big chunk allocation as a system memory, so no memory is wasted when no big chunk is allocated. Once the alloc request is issued, the framework migrates system pages to create space for the required big chunk of physically contiguous memory. For more information one can refer to nice LWN articles: - 'A reworked contiguous memory allocator': http://lwn.net/Articles/447405/ - 'CMA and ARM': http://lwn.net/Articles/450286/ - 'A deep dive into CMA': http://lwn.net/Articles/486301/ - and the following thread with the patches and links to all previous versions: https://lkml.org/lkml/2012/4/3/204 The main client for this new framework is ARM DMA-mapping subsystem. The second part provides a complete redesign in ARM DMA-mapping subsystem. The core implementation has been changed to use common struct dma_map_ops based infrastructure with the recent updates for new dma attributes merged in v3.4-rc2. This allows to use more than one implementation of dma-mapping calls and change/select them on the struct device basis. The first client of this new infractructure is dmabounce implementation which has been completely cut out of the core, common code. The last patch of this redesign update introduces a new, experimental implementation of dma-mapping calls on top of generic IOMMU framework. This lets ARM sub-platform to transparently use IOMMU for DMA-mapping calls if one provides required IOMMU hardware. For more information please refer to the following thread: http://www.spinics.net/lists/arm-kernel/msg175729.html The last patch merges changes from both updates and provides a resolution for the conflicts which cannot be avoided when patches have been applied on the same files (mainly arch/arm/mm/dma-mapping.c)." Acked by Andrew Morton <akpm@linux-foundation.org>: "Yup, this one please. It's had much work, plenty of review and I think even Russell is happy with it." * 'for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping: (28 commits) ARM: dma-mapping: use PMD size for section unmap cma: fix migration mode ARM: integrate CMA with DMA-mapping subsystem X86: integrate CMA with DMA-mapping subsystem drivers: add Contiguous Memory Allocator mm: trigger page reclaim in alloc_contig_range() to stabilise watermarks mm: extract reclaim code from __alloc_pages_direct_reclaim() mm: Serialize access to min_free_kbytes mm: page_isolation: MIGRATE_CMA isolation functions added mm: mmzone: MIGRATE_CMA migration type added mm: page_alloc: change fallbacks array handling mm: page_alloc: introduce alloc_contig_range() mm: compaction: export some of the functions mm: compaction: introduce isolate_freepages_range() mm: compaction: introduce map_pages() mm: compaction: introduce isolate_migratepages_range() mm: page_alloc: remove trailing whitespace ARM: dma-mapping: add support for IOMMU mapper ARM: dma-mapping: use alloc, mmap, free from dma_ops ARM: dma-mapping: remove redundant code and do the cleanup ... Conflicts: arch/x86/include/asm/dma-mapping.h
Diffstat (limited to 'include')
-rw-r--r--include/asm-generic/dma-coherent.h4
-rw-r--r--include/asm-generic/dma-contiguous.h28
-rw-r--r--include/linux/device.h4
-rw-r--r--include/linux/dma-contiguous.h110
-rw-r--r--include/linux/gfp.h12
-rw-r--r--include/linux/mmzone.h47
-rw-r--r--include/linux/page-isolation.h18
7 files changed, 206 insertions, 17 deletions
diff --git a/include/asm-generic/dma-coherent.h b/include/asm-generic/dma-coherent.h
index 85a3ffaa0242..abfb2682de7f 100644
--- a/include/asm-generic/dma-coherent.h
+++ b/include/asm-generic/dma-coherent.h
@@ -3,13 +3,15 @@
3 3
4#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT 4#ifdef CONFIG_HAVE_GENERIC_DMA_COHERENT
5/* 5/*
6 * These two functions are only for dma allocator. 6 * These three functions are only for dma allocator.
7 * Don't use them in device drivers. 7 * Don't use them in device drivers.
8 */ 8 */
9int dma_alloc_from_coherent(struct device *dev, ssize_t size, 9int dma_alloc_from_coherent(struct device *dev, ssize_t size,
10 dma_addr_t *dma_handle, void **ret); 10 dma_addr_t *dma_handle, void **ret);
11int dma_release_from_coherent(struct device *dev, int order, void *vaddr); 11int dma_release_from_coherent(struct device *dev, int order, void *vaddr);
12 12
13int dma_mmap_from_coherent(struct device *dev, struct vm_area_struct *vma,
14 void *cpu_addr, size_t size, int *ret);
13/* 15/*
14 * Standard interface 16 * Standard interface
15 */ 17 */
diff --git a/include/asm-generic/dma-contiguous.h b/include/asm-generic/dma-contiguous.h
new file mode 100644
index 000000000000..c544356b374b
--- /dev/null
+++ b/include/asm-generic/dma-contiguous.h
@@ -0,0 +1,28 @@
1#ifndef ASM_DMA_CONTIGUOUS_H
2#define ASM_DMA_CONTIGUOUS_H
3
4#ifdef __KERNEL__
5#ifdef CONFIG_CMA
6
7#include <linux/device.h>
8#include <linux/dma-contiguous.h>
9
10static inline struct cma *dev_get_cma_area(struct device *dev)
11{
12 if (dev && dev->cma_area)
13 return dev->cma_area;
14 return dma_contiguous_default_area;
15}
16
17static inline void dev_set_cma_area(struct device *dev, struct cma *cma)
18{
19 if (dev)
20 dev->cma_area = cma;
21 if (!dev || !dma_contiguous_default_area)
22 dma_contiguous_default_area = cma;
23}
24
25#endif
26#endif
27
28#endif
diff --git a/include/linux/device.h b/include/linux/device.h
index e04f5776f6d0..161d96241b1b 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -667,6 +667,10 @@ struct device {
667 667
668 struct dma_coherent_mem *dma_mem; /* internal for coherent mem 668 struct dma_coherent_mem *dma_mem; /* internal for coherent mem
669 override */ 669 override */
670#ifdef CONFIG_CMA
671 struct cma *cma_area; /* contiguous memory area for dma
672 allocations */
673#endif
670 /* arch specific additions */ 674 /* arch specific additions */
671 struct dev_archdata archdata; 675 struct dev_archdata archdata;
672 676
diff --git a/include/linux/dma-contiguous.h b/include/linux/dma-contiguous.h
new file mode 100644
index 000000000000..2f303e4b7ed3
--- /dev/null
+++ b/include/linux/dma-contiguous.h
@@ -0,0 +1,110 @@
1#ifndef __LINUX_CMA_H
2#define __LINUX_CMA_H
3
4/*
5 * Contiguous Memory Allocator for DMA mapping framework
6 * Copyright (c) 2010-2011 by Samsung Electronics.
7 * Written by:
8 * Marek Szyprowski <m.szyprowski@samsung.com>
9 * Michal Nazarewicz <mina86@mina86.com>
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License or (at your optional) any later version of the license.
15 */
16
17/*
18 * Contiguous Memory Allocator
19 *
20 * The Contiguous Memory Allocator (CMA) makes it possible to
21 * allocate big contiguous chunks of memory after the system has
22 * booted.
23 *
24 * Why is it needed?
25 *
26 * Various devices on embedded systems have no scatter-getter and/or
27 * IO map support and require contiguous blocks of memory to
28 * operate. They include devices such as cameras, hardware video
29 * coders, etc.
30 *
31 * Such devices often require big memory buffers (a full HD frame
32 * is, for instance, more then 2 mega pixels large, i.e. more than 6
33 * MB of memory), which makes mechanisms such as kmalloc() or
34 * alloc_page() ineffective.
35 *
36 * At the same time, a solution where a big memory region is
37 * reserved for a device is suboptimal since often more memory is
38 * reserved then strictly required and, moreover, the memory is
39 * inaccessible to page system even if device drivers don't use it.
40 *
41 * CMA tries to solve this issue by operating on memory regions
42 * where only movable pages can be allocated from. This way, kernel
43 * can use the memory for pagecache and when device driver requests
44 * it, allocated pages can be migrated.
45 *
46 * Driver usage
47 *
48 * CMA should not be used by the device drivers directly. It is
49 * only a helper framework for dma-mapping subsystem.
50 *
51 * For more information, see kernel-docs in drivers/base/dma-contiguous.c
52 */
53
54#ifdef __KERNEL__
55
56struct cma;
57struct page;
58struct device;
59
60#ifdef CONFIG_CMA
61
62/*
63 * There is always at least global CMA area and a few optional device
64 * private areas configured in kernel .config.
65 */
66#define MAX_CMA_AREAS (1 + CONFIG_CMA_AREAS)
67
68extern struct cma *dma_contiguous_default_area;
69
70void dma_contiguous_reserve(phys_addr_t addr_limit);
71int dma_declare_contiguous(struct device *dev, unsigned long size,
72 phys_addr_t base, phys_addr_t limit);
73
74struct page *dma_alloc_from_contiguous(struct device *dev, int count,
75 unsigned int order);
76bool dma_release_from_contiguous(struct device *dev, struct page *pages,
77 int count);
78
79#else
80
81#define MAX_CMA_AREAS (0)
82
83static inline void dma_contiguous_reserve(phys_addr_t limit) { }
84
85static inline
86int dma_declare_contiguous(struct device *dev, unsigned long size,
87 phys_addr_t base, phys_addr_t limit)
88{
89 return -ENOSYS;
90}
91
92static inline
93struct page *dma_alloc_from_contiguous(struct device *dev, int count,
94 unsigned int order)
95{
96 return NULL;
97}
98
99static inline
100bool dma_release_from_contiguous(struct device *dev, struct page *pages,
101 int count)
102{
103 return false;
104}
105
106#endif
107
108#endif
109
110#endif
diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index 581e74b7df95..1e49be49d324 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -391,4 +391,16 @@ static inline bool pm_suspended_storage(void)
391} 391}
392#endif /* CONFIG_PM_SLEEP */ 392#endif /* CONFIG_PM_SLEEP */
393 393
394#ifdef CONFIG_CMA
395
396/* The below functions must be run on a range from a single zone. */
397extern int alloc_contig_range(unsigned long start, unsigned long end,
398 unsigned migratetype);
399extern void free_contig_range(unsigned long pfn, unsigned nr_pages);
400
401/* CMA stuff */
402extern void init_cma_reserved_pageblock(struct page *page);
403
404#endif
405
394#endif /* __LINUX_GFP_H */ 406#endif /* __LINUX_GFP_H */
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 41aa49b74821..4871e31ae277 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -35,13 +35,39 @@
35 */ 35 */
36#define PAGE_ALLOC_COSTLY_ORDER 3 36#define PAGE_ALLOC_COSTLY_ORDER 3
37 37
38#define MIGRATE_UNMOVABLE 0 38enum {
39#define MIGRATE_RECLAIMABLE 1 39 MIGRATE_UNMOVABLE,
40#define MIGRATE_MOVABLE 2 40 MIGRATE_RECLAIMABLE,
41#define MIGRATE_PCPTYPES 3 /* the number of types on the pcp lists */ 41 MIGRATE_MOVABLE,
42#define MIGRATE_RESERVE 3 42 MIGRATE_PCPTYPES, /* the number of types on the pcp lists */
43#define MIGRATE_ISOLATE 4 /* can't allocate from here */ 43 MIGRATE_RESERVE = MIGRATE_PCPTYPES,
44#define MIGRATE_TYPES 5 44#ifdef CONFIG_CMA
45 /*
46 * MIGRATE_CMA migration type is designed to mimic the way
47 * ZONE_MOVABLE works. Only movable pages can be allocated
48 * from MIGRATE_CMA pageblocks and page allocator never
49 * implicitly change migration type of MIGRATE_CMA pageblock.
50 *
51 * The way to use it is to change migratetype of a range of
52 * pageblocks to MIGRATE_CMA which can be done by
53 * __free_pageblock_cma() function. What is important though
54 * is that a range of pageblocks must be aligned to
55 * MAX_ORDER_NR_PAGES should biggest page be bigger then
56 * a single pageblock.
57 */
58 MIGRATE_CMA,
59#endif
60 MIGRATE_ISOLATE, /* can't allocate from here */
61 MIGRATE_TYPES
62};
63
64#ifdef CONFIG_CMA
65# define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
66# define cma_wmark_pages(zone) zone->min_cma_pages
67#else
68# define is_migrate_cma(migratetype) false
69# define cma_wmark_pages(zone) 0
70#endif
45 71
46#define for_each_migratetype_order(order, type) \ 72#define for_each_migratetype_order(order, type) \
47 for (order = 0; order < MAX_ORDER; order++) \ 73 for (order = 0; order < MAX_ORDER; order++) \
@@ -347,6 +373,13 @@ struct zone {
347 /* see spanned/present_pages for more description */ 373 /* see spanned/present_pages for more description */
348 seqlock_t span_seqlock; 374 seqlock_t span_seqlock;
349#endif 375#endif
376#ifdef CONFIG_CMA
377 /*
378 * CMA needs to increase watermark levels during the allocation
379 * process to make sure that the system is not starved.
380 */
381 unsigned long min_cma_pages;
382#endif
350 struct free_area free_area[MAX_ORDER]; 383 struct free_area free_area[MAX_ORDER];
351 384
352#ifndef CONFIG_SPARSEMEM 385#ifndef CONFIG_SPARSEMEM
diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h
index 051c1b1ede4e..3bdcab30ca41 100644
--- a/include/linux/page-isolation.h
+++ b/include/linux/page-isolation.h
@@ -3,7 +3,7 @@
3 3
4/* 4/*
5 * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE. 5 * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE.
6 * If specified range includes migrate types other than MOVABLE, 6 * If specified range includes migrate types other than MOVABLE or CMA,
7 * this will fail with -EBUSY. 7 * this will fail with -EBUSY.
8 * 8 *
9 * For isolating all pages in the range finally, the caller have to 9 * For isolating all pages in the range finally, the caller have to
@@ -11,27 +11,27 @@
11 * test it. 11 * test it.
12 */ 12 */
13extern int 13extern int
14start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); 14start_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
15 unsigned migratetype);
15 16
16/* 17/*
17 * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE. 18 * Changes MIGRATE_ISOLATE to MIGRATE_MOVABLE.
18 * target range is [start_pfn, end_pfn) 19 * target range is [start_pfn, end_pfn)
19 */ 20 */
20extern int 21extern int
21undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn); 22undo_isolate_page_range(unsigned long start_pfn, unsigned long end_pfn,
23 unsigned migratetype);
22 24
23/* 25/*
24 * test all pages in [start_pfn, end_pfn)are isolated or not. 26 * Test all pages in [start_pfn, end_pfn) are isolated or not.
25 */ 27 */
26extern int 28int test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
27test_pages_isolated(unsigned long start_pfn, unsigned long end_pfn);
28 29
29/* 30/*
30 * Internal funcs.Changes pageblock's migrate type. 31 * Internal functions. Changes pageblock's migrate type.
31 * Please use make_pagetype_isolated()/make_pagetype_movable().
32 */ 32 */
33extern int set_migratetype_isolate(struct page *page); 33extern int set_migratetype_isolate(struct page *page);
34extern void unset_migratetype_isolate(struct page *page); 34extern void unset_migratetype_isolate(struct page *page, unsigned migratetype);
35 35
36 36
37#endif 37#endif