|
@@ -14,6 +14,7 @@
|
|
|
#define __PMEM_H__
|
|
|
|
|
|
#include <linux/io.h>
|
|
|
+#include <linux/uio.h>
|
|
|
|
|
|
#ifdef CONFIG_ARCH_HAS_PMEM_API
|
|
|
#include <asm/pmem.h>
|
|
@@ -33,12 +34,24 @@ static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src,
|
|
|
{
|
|
|
BUG();
|
|
|
}
|
|
|
+
|
|
|
+static inline size_t arch_copy_from_iter_pmem(void __pmem *addr, size_t bytes,
|
|
|
+ struct iov_iter *i)
|
|
|
+{
|
|
|
+ BUG();
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void arch_clear_pmem(void __pmem *addr, size_t size)
|
|
|
+{
|
|
|
+ BUG();
|
|
|
+}
|
|
|
#endif
|
|
|
|
|
|
/*
|
|
|
* Architectures that define ARCH_HAS_PMEM_API must provide
|
|
|
- * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), and
|
|
|
- * arch_has_wmb_pmem().
|
|
|
+ * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(),
|
|
|
+ * arch_copy_from_iter_pmem(), arch_clear_pmem() and arch_has_wmb_pmem().
|
|
|
*/
|
|
|
|
|
|
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,
|
|
|
memcpy((void __force *) dst, src, size);
|
|
|
}
|
|
|
|
|
|
+static inline size_t default_copy_from_iter_pmem(void __pmem *addr,
|
|
|
+ size_t bytes, struct iov_iter *i)
|
|
|
+{
|
|
|
+ return copy_from_iter_nocache((void __force *)addr, bytes, i);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void default_clear_pmem(void __pmem *addr, size_t size)
|
|
|
+{
|
|
|
+ if (size == PAGE_SIZE && ((unsigned long)addr & ~PAGE_MASK) == 0)
|
|
|
+ clear_page((void __force *)addr);
|
|
|
+ else
|
|
|
+ memset((void __force *)addr, 0, size);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* memremap_pmem - map physical persistent memory for pmem api
|
|
|
* @offset: physical address of persistent memory
|
|
@@ -134,4 +161,37 @@ static inline void wmb_pmem(void)
|
|
|
if (arch_has_pmem_api())
|
|
|
arch_wmb_pmem();
|
|
|
}
|
|
|
+
|
|
|
+/**
|
|
|
+ * copy_from_iter_pmem - copy data from an iterator to PMEM
|
|
|
+ * @addr: PMEM destination address
|
|
|
+ * @bytes: number of bytes to copy
|
|
|
+ * @i: iterator with source data
|
|
|
+ *
|
|
|
+ * Copy data from the iterator 'i' to the PMEM buffer starting at 'addr'.
|
|
|
+ * This function requires explicit ordering with a wmb_pmem() call.
|
|
|
+ */
|
|
|
+static inline size_t copy_from_iter_pmem(void __pmem *addr, size_t bytes,
|
|
|
+ struct iov_iter *i)
|
|
|
+{
|
|
|
+ if (arch_has_pmem_api())
|
|
|
+ return arch_copy_from_iter_pmem(addr, bytes, i);
|
|
|
+ return default_copy_from_iter_pmem(addr, bytes, i);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * clear_pmem - zero a PMEM memory range
|
|
|
+ * @addr: virtual start address
|
|
|
+ * @size: number of bytes to zero
|
|
|
+ *
|
|
|
+ * Write zeros into the memory range starting at 'addr' for 'size' bytes.
|
|
|
+ * This function requires explicit ordering with a wmb_pmem() call.
|
|
|
+ */
|
|
|
+static inline void clear_pmem(void __pmem *addr, size_t size)
|
|
|
+{
|
|
|
+ if (arch_has_pmem_api())
|
|
|
+ arch_clear_pmem(addr, size);
|
|
|
+ else
|
|
|
+ default_clear_pmem(addr, size);
|
|
|
+}
|
|
|
#endif /* __PMEM_H__ */
|