aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/io-mapping.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/io-mapping.h')
-rw-r--r--include/linux/io-mapping.h48
1 files changed, 37 insertions, 11 deletions
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h
index 82df31726a54..f1ed66c43787 100644
--- a/include/linux/io-mapping.h
+++ b/include/linux/io-mapping.h
@@ -30,11 +30,14 @@
30 * See Documentation/io_mapping.txt 30 * See Documentation/io_mapping.txt
31 */ 31 */
32 32
33/* this struct isn't actually defined anywhere */
34struct io_mapping;
35
36#ifdef CONFIG_HAVE_ATOMIC_IOMAP 33#ifdef CONFIG_HAVE_ATOMIC_IOMAP
37 34
35struct io_mapping {
36 resource_size_t base;
37 unsigned long size;
38 pgprot_t prot;
39};
40
38/* 41/*
39 * For small address space machines, mapping large objects 42 * For small address space machines, mapping large objects
40 * into the kernel virtual space isn't practical. Where 43 * into the kernel virtual space isn't practical. Where
@@ -43,23 +46,42 @@ struct io_mapping;
43 */ 46 */
44 47
45static inline struct io_mapping * 48static inline struct io_mapping *
46io_mapping_create_wc(unsigned long base, unsigned long size) 49io_mapping_create_wc(resource_size_t base, unsigned long size)
47{ 50{
48 return (struct io_mapping *) base; 51 struct io_mapping *iomap;
52 pgprot_t prot;
53
54 if (!reserve_io_memtype_wc(base, size, &prot))
55 return NULL;
56
57 iomap = kmalloc(sizeof(*iomap), GFP_KERNEL);
58 if (!iomap)
59 return NULL;
60
61 iomap->base = base;
62 iomap->size = size;
63 iomap->prot = prot;
64 return iomap;
49} 65}
50 66
51static inline void 67static inline void
52io_mapping_free(struct io_mapping *mapping) 68io_mapping_free(struct io_mapping *mapping)
53{ 69{
70 free_io_memtype(mapping->base, mapping->size);
71 kfree(mapping);
54} 72}
55 73
56/* Atomic map/unmap */ 74/* Atomic map/unmap */
57static inline void * 75static inline void *
58io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) 76io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset)
59{ 77{
60 offset += (unsigned long) mapping; 78 resource_size_t phys_addr;
61 return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0, 79 unsigned long pfn;
62 __pgprot(__PAGE_KERNEL_WC)); 80
81 BUG_ON(offset >= mapping->size);
82 phys_addr = mapping->base + offset;
83 pfn = (unsigned long) (phys_addr >> PAGE_SHIFT);
84 return iomap_atomic_prot_pfn(pfn, KM_USER0, mapping->prot);
63} 85}
64 86
65static inline void 87static inline void
@@ -71,8 +93,9 @@ io_mapping_unmap_atomic(void *vaddr)
71static inline void * 93static inline void *
72io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) 94io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset)
73{ 95{
74 offset += (unsigned long) mapping; 96 BUG_ON(offset >= mapping->size);
75 return ioremap_wc(offset, PAGE_SIZE); 97 resource_size_t phys_addr = mapping->base + offset;
98 return ioremap_wc(phys_addr, PAGE_SIZE);
76} 99}
77 100
78static inline void 101static inline void
@@ -83,9 +106,12 @@ io_mapping_unmap(void *vaddr)
83 106
84#else 107#else
85 108
109/* this struct isn't actually defined anywhere */
110struct io_mapping;
111
86/* Create the io_mapping object*/ 112/* Create the io_mapping object*/
87static inline struct io_mapping * 113static inline struct io_mapping *
88io_mapping_create_wc(unsigned long base, unsigned long size) 114io_mapping_create_wc(resource_size_t base, unsigned long size)
89{ 115{
90 return (struct io_mapping *) ioremap_wc(base, size); 116 return (struct io_mapping *) ioremap_wc(base, size);
91} 117}