a0706ea04efdffcadb27615b4123f3e562311854
[linux-drm-fsl-dcu.git] / include / linux / pmem.h
1 /*
2  * Copyright(c) 2015 Intel Corporation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of version 2 of the GNU General Public License as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  */
13 #ifndef __PMEM_H__
14 #define __PMEM_H__
15
16 #include <linux/io.h>
17
18 #ifdef CONFIG_ARCH_HAS_PMEM_API
19 #include <asm/pmem.h>
20 #else
21 static inline void arch_wmb_pmem(void)
22 {
23         BUG();
24 }
25
26 static inline bool arch_has_wmb_pmem(void)
27 {
28         return false;
29 }
30
31 static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src,
32                 size_t n)
33 {
34         BUG();
35 }
36 #endif
37
38 /*
39  * Architectures that define ARCH_HAS_PMEM_API must provide
40  * implementations for arch_memcpy_to_pmem(), arch_wmb_pmem(), and
41  * arch_has_wmb_pmem().
42  */
43
44 static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size)
45 {
46         memcpy(dst, (void __force const *) src, size);
47 }
48
49 static inline void memunmap_pmem(struct device *dev, void __pmem *addr)
50 {
51         devm_memunmap(dev, (void __force *) addr);
52 }
53
54 /**
55  * arch_has_pmem_api - true if wmb_pmem() ensures durability
56  *
57  * For a given cpu implementation within an architecture it is possible
58  * that wmb_pmem() resolves to a nop.  In the case this returns
59  * false, pmem api users are unable to ensure durability and may want to
60  * fall back to a different data consistency model, or otherwise notify
61  * the user.
62  */
63 static inline bool arch_has_pmem_api(void)
64 {
65         return IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && arch_has_wmb_pmem();
66 }
67
68 /*
69  * These defaults seek to offer decent performance and minimize the
70  * window between i/o completion and writes being durable on media.
71  * However, it is undefined / architecture specific whether
72  * default_memremap_pmem + default_memcpy_to_pmem is sufficient for
73  * making data durable relative to i/o completion.
74  */
75 static inline void default_memcpy_to_pmem(void __pmem *dst, const void *src,
76                 size_t size)
77 {
78         memcpy((void __force *) dst, src, size);
79 }
80
81 /**
82  * memremap_pmem - map physical persistent memory for pmem api
83  * @offset: physical address of persistent memory
84  * @size: size of the mapping
85  *
86  * Establish a mapping of the architecture specific memory type expected
87  * by memcpy_to_pmem() and wmb_pmem().  For example, it may be
88  * the case that an uncacheable or writethrough mapping is sufficient,
89  * or a writeback mapping provided memcpy_to_pmem() and
90  * wmb_pmem() arrange for the data to be written through the
91  * cache to persistent media.
92  */
93 static inline void __pmem *memremap_pmem(struct device *dev,
94                 resource_size_t offset, unsigned long size)
95 {
96 #ifdef ARCH_MEMREMAP_PMEM
97         return (void __pmem *) devm_memremap(dev, offset, size,
98                         ARCH_MEMREMAP_PMEM);
99 #else
100         return (void __pmem *) devm_memremap(dev, offset, size,
101                         MEMREMAP_WT);
102 #endif
103 }
104
105 /**
106  * memcpy_to_pmem - copy data to persistent memory
107  * @dst: destination buffer for the copy
108  * @src: source buffer for the copy
109  * @n: length of the copy in bytes
110  *
111  * Perform a memory copy that results in the destination of the copy
112  * being effectively evicted from, or never written to, the processor
113  * cache hierarchy after the copy completes.  After memcpy_to_pmem()
114  * data may still reside in cpu or platform buffers, so this operation
115  * must be followed by a wmb_pmem().
116  */
117 static inline void memcpy_to_pmem(void __pmem *dst, const void *src, size_t n)
118 {
119         if (arch_has_pmem_api())
120                 arch_memcpy_to_pmem(dst, src, n);
121         else
122                 default_memcpy_to_pmem(dst, src, n);
123 }
124
125 /**
126  * wmb_pmem - synchronize writes to persistent memory
127  *
128  * After a series of memcpy_to_pmem() operations this drains data from
129  * cpu write buffers and any platform (memory controller) buffers to
130  * ensure that written data is durable on persistent memory media.
131  */
132 static inline void wmb_pmem(void)
133 {
134         if (arch_has_pmem_api())
135                 arch_wmb_pmem();
136 }
137 #endif /* __PMEM_H__ */