diff options
-rw-r--r-- | arch/x86/Kconfig | 4 | ||||
-rw-r--r-- | include/linux/io-mapping.h | 43 |
2 files changed, 29 insertions, 18 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 6f20718d3156..e60c59b81bdd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -1894,6 +1894,10 @@ config SYSVIPC_COMPAT | |||
1894 | endmenu | 1894 | endmenu |
1895 | 1895 | ||
1896 | 1896 | ||
1897 | config HAVE_ATOMIC_IOMAP | ||
1898 | def_bool y | ||
1899 | depends on X86_32 | ||
1900 | |||
1897 | source "net/Kconfig" | 1901 | source "net/Kconfig" |
1898 | 1902 | ||
1899 | source "drivers/Kconfig" | 1903 | source "drivers/Kconfig" |
diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index 1b566993db6e..82df31726a54 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h | |||
@@ -33,86 +33,93 @@ | |||
33 | /* this struct isn't actually defined anywhere */ | 33 | /* this struct isn't actually defined anywhere */ |
34 | struct io_mapping; | 34 | struct io_mapping; |
35 | 35 | ||
36 | #ifdef CONFIG_X86_64 | 36 | #ifdef CONFIG_HAVE_ATOMIC_IOMAP |
37 | |||
38 | /* | ||
39 | * For small address space machines, mapping large objects | ||
40 | * into the kernel virtual space isn't practical. Where | ||
41 | * available, use fixmap support to dynamically map pages | ||
42 | * of the object at run time. | ||
43 | */ | ||
37 | 44 | ||
38 | /* Create the io_mapping object*/ | ||
39 | static inline struct io_mapping * | 45 | static inline struct io_mapping * |
40 | io_mapping_create_wc(unsigned long base, unsigned long size) | 46 | io_mapping_create_wc(unsigned long base, unsigned long size) |
41 | { | 47 | { |
42 | return (struct io_mapping *) ioremap_wc(base, size); | 48 | return (struct io_mapping *) base; |
43 | } | 49 | } |
44 | 50 | ||
45 | static inline void | 51 | static inline void |
46 | io_mapping_free(struct io_mapping *mapping) | 52 | io_mapping_free(struct io_mapping *mapping) |
47 | { | 53 | { |
48 | iounmap(mapping); | ||
49 | } | 54 | } |
50 | 55 | ||
51 | /* Atomic map/unmap */ | 56 | /* Atomic map/unmap */ |
52 | static inline void * | 57 | static inline void * |
53 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) | 58 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) |
54 | { | 59 | { |
55 | return ((char *) mapping) + offset; | 60 | offset += (unsigned long) mapping; |
61 | return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0, | ||
62 | __pgprot(__PAGE_KERNEL_WC)); | ||
56 | } | 63 | } |
57 | 64 | ||
58 | static inline void | 65 | static inline void |
59 | io_mapping_unmap_atomic(void *vaddr) | 66 | io_mapping_unmap_atomic(void *vaddr) |
60 | { | 67 | { |
68 | iounmap_atomic(vaddr, KM_USER0); | ||
61 | } | 69 | } |
62 | 70 | ||
63 | /* Non-atomic map/unmap */ | ||
64 | static inline void * | 71 | static inline void * |
65 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) | 72 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) |
66 | { | 73 | { |
67 | return ((char *) mapping) + offset; | 74 | offset += (unsigned long) mapping; |
75 | return ioremap_wc(offset, PAGE_SIZE); | ||
68 | } | 76 | } |
69 | 77 | ||
70 | static inline void | 78 | static inline void |
71 | io_mapping_unmap(void *vaddr) | 79 | io_mapping_unmap(void *vaddr) |
72 | { | 80 | { |
81 | iounmap(vaddr); | ||
73 | } | 82 | } |
74 | 83 | ||
75 | #endif /* CONFIG_X86_64 */ | 84 | #else |
76 | 85 | ||
77 | #ifdef CONFIG_X86_32 | 86 | /* Create the io_mapping object*/ |
78 | static inline struct io_mapping * | 87 | static inline struct io_mapping * |
79 | io_mapping_create_wc(unsigned long base, unsigned long size) | 88 | io_mapping_create_wc(unsigned long base, unsigned long size) |
80 | { | 89 | { |
81 | return (struct io_mapping *) base; | 90 | return (struct io_mapping *) ioremap_wc(base, size); |
82 | } | 91 | } |
83 | 92 | ||
84 | static inline void | 93 | static inline void |
85 | io_mapping_free(struct io_mapping *mapping) | 94 | io_mapping_free(struct io_mapping *mapping) |
86 | { | 95 | { |
96 | iounmap(mapping); | ||
87 | } | 97 | } |
88 | 98 | ||
89 | /* Atomic map/unmap */ | 99 | /* Atomic map/unmap */ |
90 | static inline void * | 100 | static inline void * |
91 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) | 101 | io_mapping_map_atomic_wc(struct io_mapping *mapping, unsigned long offset) |
92 | { | 102 | { |
93 | offset += (unsigned long) mapping; | 103 | return ((char *) mapping) + offset; |
94 | return iomap_atomic_prot_pfn(offset >> PAGE_SHIFT, KM_USER0, | ||
95 | __pgprot(__PAGE_KERNEL_WC)); | ||
96 | } | 104 | } |
97 | 105 | ||
98 | static inline void | 106 | static inline void |
99 | io_mapping_unmap_atomic(void *vaddr) | 107 | io_mapping_unmap_atomic(void *vaddr) |
100 | { | 108 | { |
101 | iounmap_atomic(vaddr, KM_USER0); | ||
102 | } | 109 | } |
103 | 110 | ||
111 | /* Non-atomic map/unmap */ | ||
104 | static inline void * | 112 | static inline void * |
105 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) | 113 | io_mapping_map_wc(struct io_mapping *mapping, unsigned long offset) |
106 | { | 114 | { |
107 | offset += (unsigned long) mapping; | 115 | return ((char *) mapping) + offset; |
108 | return ioremap_wc(offset, PAGE_SIZE); | ||
109 | } | 116 | } |
110 | 117 | ||
111 | static inline void | 118 | static inline void |
112 | io_mapping_unmap(void *vaddr) | 119 | io_mapping_unmap(void *vaddr) |
113 | { | 120 | { |
114 | iounmap(vaddr); | ||
115 | } | 121 | } |
116 | #endif /* CONFIG_X86_32 */ | 122 | |
123 | #endif /* HAVE_ATOMIC_IOMAP */ | ||
117 | 124 | ||
118 | #endif /* _LINUX_IO_MAPPING_H */ | 125 | #endif /* _LINUX_IO_MAPPING_H */ |