diff options
author | Ross Zwisler <ross.zwisler@linux.intel.com> | 2015-08-18 15:55:39 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2015-08-20 14:07:23 -0400 |
commit | 5de490daec8b6354b90d5c9d3e2415b195f5adb6 (patch) | |
tree | 0f9091d0827916e8a810cff47315445bed81d726 /include/linux | |
parent | 4a370df5534ef727cba9a9d74bf22e0609f91d6e (diff) |
pmem: add copy_from_iter_pmem() and clear_pmem()
Add support for two new PMEM APIs, copy_from_iter_pmem() and
clear_pmem(). copy_from_iter_pmem() is used to copy data from an
iterator into a PMEM buffer. clear_pmem() zeros a PMEM memory range.
Both of these new APIs must be explicitly ordered using a wmb_pmem()
function call and are implemented in such a way that the wmb_pmem()
will make the stores to PMEM durable. Because both APIs are unordered
they can be called as needed without introducing any unwanted memory
barriers.
Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/pmem.h | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/include/linux/pmem.h b/include/linux/pmem.h index a0706ea04efd..a9d84bf335ee 100644 --- a/include/linux/pmem.h +++ b/include/linux/pmem.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define __PMEM_H__ | 14 | #define __PMEM_H__ |
15 | 15 | ||
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/uio.h> | ||
17 | 18 | ||
18 | #ifdef CONFIG_ARCH_HAS_PMEM_API | 19 | #ifdef CONFIG_ARCH_HAS_PMEM_API |
19 | #include <asm/pmem.h> | 20 | #include <asm/pmem.h> |
@@ -33,12 +34,24 @@ static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src, | |||
33 | { | 34 | { |
34 | BUG(); | 35 | BUG(); |
35 | } | 36 | } |
37 | |||
38 | static inline size_t arch_copy_from_iter_pmem(void __pmem *addr, size_t bytes, | ||
39 | struct iov_iter *i) | ||
40 | { | ||
41 | BUG(); | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static inline void arch_clear_pmem(void __pmem *addr, size_t size) | ||
46 | { | ||
47 | BUG(); | ||
48 | } | ||
36 | #endif | 49 | #endif |
37 | 50 | ||
38 | /* | 51 | /* |
39 | * Architectures that define ARCH_HAS_PMEM_API must provide | 52 | * Architectures that define ARCH_HAS_PMEM_API must provide |
40 | * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), and | 53 | * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), |
41 | * arch_has_wmb_pmem(). | 54 | * arch_copy_from_iter_pmem(), arch_clear_pmem() and arch_has_wmb_pmem(). |
42 | */ | 55 | */ |
43 | 56 | ||
44 | static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size) | 57 | static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size) |
@@ -78,6 +91,20 @@ static inline void default_memcpy_to_pmem(void __pmem *dst, const void *src, | |||
78 | memcpy((void __force *) dst, src, size); | 91 | memcpy((void __force *) dst, src, size); |
79 | } | 92 | } |
80 | 93 | ||
94 | static inline size_t default_copy_from_iter_pmem(void __pmem *addr, | ||
95 | size_t bytes, struct iov_iter *i) | ||
96 | { | ||
97 | return copy_from_iter_nocache((void __force *)addr, bytes, i); | ||
98 | } | ||
99 | |||
100 | static inline void default_clear_pmem(void __pmem *addr, size_t size) | ||
101 | { | ||
102 | if (size == PAGE_SIZE && ((unsigned long)addr & ~PAGE_MASK) == 0) | ||
103 | clear_page((void __force *)addr); | ||
104 | else | ||
105 | memset((void __force *)addr, 0, size); | ||
106 | } | ||
107 | |||
81 | /** | 108 | /** |
82 | * memremap_pmem - map physical persistent memory for pmem api | 109 | * memremap_pmem - map physical persistent memory for pmem api |
83 | * @offset: physical address of persistent memory | 110 | * @offset: physical address of persistent memory |
@@ -134,4 +161,37 @@ static inline void wmb_pmem(void) | |||
134 | if (arch_has_pmem_api()) | 161 | if (arch_has_pmem_api()) |
135 | arch_wmb_pmem(); | 162 | arch_wmb_pmem(); |
136 | } | 163 | } |
164 | |||
165 | /** | ||
166 | * copy_from_iter_pmem - copy data from an iterator to PMEM | ||
167 | * @addr: PMEM destination address | ||
168 | * @bytes: number of bytes to copy | ||
169 | * @i: iterator with source data | ||
170 | * | ||
171 | * Copy data from the iterator 'i' to the PMEM buffer starting at 'addr'. | ||
172 | * This function requires explicit ordering with a wmb_pmem() call. | ||
173 | */ | ||
174 | static inline size_t copy_from_iter_pmem(void __pmem *addr, size_t bytes, | ||
175 | struct iov_iter *i) | ||
176 | { | ||
177 | if (arch_has_pmem_api()) | ||
178 | return arch_copy_from_iter_pmem(addr, bytes, i); | ||
179 | return default_copy_from_iter_pmem(addr, bytes, i); | ||
180 | } | ||
181 | |||
182 | /** | ||
183 | * clear_pmem - zero a PMEM memory range | ||
184 | * @addr: virtual start address | ||
185 | * @size: number of bytes to zero | ||
186 | * | ||
187 | * Write zeros into the memory range starting at 'addr' for 'size' bytes. | ||
188 | * This function requires explicit ordering with a wmb_pmem() call. | ||
189 | */ | ||
190 | static inline void clear_pmem(void __pmem *addr, size_t size) | ||
191 | { | ||
192 | if (arch_has_pmem_api()) | ||
193 | arch_clear_pmem(addr, size); | ||
194 | else | ||
195 | default_clear_pmem(addr, size); | ||
196 | } | ||
137 | #endif /* __PMEM_H__ */ | 197 | #endif /* __PMEM_H__ */ |