at v4.2 4.4 kB view raw
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/cacheflush.h> 20#else 21static inline void arch_wmb_pmem(void) 22{ 23 BUG(); 24} 25 26static inline bool __arch_has_wmb_pmem(void) 27{ 28 return false; 29} 30 31static inline void __pmem *arch_memremap_pmem(resource_size_t offset, 32 unsigned long size) 33{ 34 return NULL; 35} 36 37static inline void arch_memcpy_to_pmem(void __pmem *dst, const void *src, 38 size_t n) 39{ 40 BUG(); 41} 42#endif 43 44/* 45 * Architectures that define ARCH_HAS_PMEM_API must provide 46 * implementations for arch_memremap_pmem(), arch_memcpy_to_pmem(), 47 * arch_wmb_pmem(), and __arch_has_wmb_pmem(). 48 */ 49 50static inline void memcpy_from_pmem(void *dst, void __pmem const *src, size_t size) 51{ 52 memcpy(dst, (void __force const *) src, size); 53} 54 55static inline void memunmap_pmem(void __pmem *addr) 56{ 57 iounmap((void __force __iomem *) addr); 58} 59 60/** 61 * arch_has_wmb_pmem - true if wmb_pmem() ensures durability 62 * 63 * For a given cpu implementation within an architecture it is possible 64 * that wmb_pmem() resolves to a nop. In the case this returns 65 * false, pmem api users are unable to ensure durability and may want to 66 * fall back to a different data consistency model, or otherwise notify 67 * the user. 68 */ 69static inline bool arch_has_wmb_pmem(void) 70{ 71 if (IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) 72 return __arch_has_wmb_pmem(); 73 return false; 74} 75 76static inline bool arch_has_pmem_api(void) 77{ 78 return IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API) && arch_has_wmb_pmem(); 79} 80 81/* 82 * These defaults seek to offer decent performance and minimize the 83 * window between i/o completion and writes being durable on media. 84 * However, it is undefined / architecture specific whether 85 * default_memremap_pmem + default_memcpy_to_pmem is sufficient for 86 * making data durable relative to i/o completion. 87 */ 88static void default_memcpy_to_pmem(void __pmem *dst, const void *src, 89 size_t size) 90{ 91 memcpy((void __force *) dst, src, size); 92} 93 94static void __pmem *default_memremap_pmem(resource_size_t offset, 95 unsigned long size) 96{ 97 return (void __pmem __force *)ioremap_wt(offset, size); 98} 99 100/** 101 * memremap_pmem - map physical persistent memory for pmem api 102 * @offset: physical address of persistent memory 103 * @size: size of the mapping 104 * 105 * Establish a mapping of the architecture specific memory type expected 106 * by memcpy_to_pmem() and wmb_pmem(). For example, it may be 107 * the case that an uncacheable or writethrough mapping is sufficient, 108 * or a writeback mapping provided memcpy_to_pmem() and 109 * wmb_pmem() arrange for the data to be written through the 110 * cache to persistent media. 111 */ 112static inline void __pmem *memremap_pmem(resource_size_t offset, 113 unsigned long size) 114{ 115 if (arch_has_pmem_api()) 116 return arch_memremap_pmem(offset, size); 117 return default_memremap_pmem(offset, size); 118} 119 120/** 121 * memcpy_to_pmem - copy data to persistent memory 122 * @dst: destination buffer for the copy 123 * @src: source buffer for the copy 124 * @n: length of the copy in bytes 125 * 126 * Perform a memory copy that results in the destination of the copy 127 * being effectively evicted from, or never written to, the processor 128 * cache hierarchy after the copy completes. After memcpy_to_pmem() 129 * data may still reside in cpu or platform buffers, so this operation 130 * must be followed by a wmb_pmem(). 131 */ 132static inline void memcpy_to_pmem(void __pmem *dst, const void *src, size_t n) 133{ 134 if (arch_has_pmem_api()) 135 arch_memcpy_to_pmem(dst, src, n); 136 else 137 default_memcpy_to_pmem(dst, src, n); 138} 139 140/** 141 * wmb_pmem - synchronize writes to persistent memory 142 * 143 * After a series of memcpy_to_pmem() operations this drains data from 144 * cpu write buffers and any platform (memory controller) buffers to 145 * ensure that written data is durable on persistent memory media. 146 */ 147static inline void wmb_pmem(void) 148{ 149 if (arch_has_pmem_api()) 150 arch_wmb_pmem(); 151} 152#endif /* __PMEM_H__ */