xref: /openbmc/linux/include/linux/libnvdimm.h (revision f57aec44)
15b497af4SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
2b94d5230SDan Williams /*
3b94d5230SDan Williams  * libnvdimm - Non-volatile-memory Devices Subsystem
4b94d5230SDan Williams  *
5b94d5230SDan Williams  * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
6b94d5230SDan Williams  */
7b94d5230SDan Williams #ifndef __LIBNVDIMM_H__
8b94d5230SDan Williams #define __LIBNVDIMM_H__
9047fc8a1SRoss Zwisler #include <linux/kernel.h>
1062232e45SDan Williams #include <linux/sizes.h>
1162232e45SDan Williams #include <linux/types.h>
12faec6f8aSDan Williams #include <linux/uuid.h>
13aa9ad44aSDave Jiang #include <linux/spinlock.h>
14c5d4355dSPankaj Gupta #include <linux/bio.h>
15aa9ad44aSDave Jiang 
16aa9ad44aSDave Jiang struct badrange_entry {
17aa9ad44aSDave Jiang 	u64 start;
18aa9ad44aSDave Jiang 	u64 length;
19aa9ad44aSDave Jiang 	struct list_head list;
20aa9ad44aSDave Jiang };
21aa9ad44aSDave Jiang 
22aa9ad44aSDave Jiang struct badrange {
23aa9ad44aSDave Jiang 	struct list_head list;
24aa9ad44aSDave Jiang 	spinlock_t lock;
25aa9ad44aSDave Jiang };
26e6dfb2deSDan Williams 
27e6dfb2deSDan Williams enum {
2858138820SDan Williams 	/* unarmed memory devices may not persist writes */
298f078b38SDan Williams 	NDD_UNARMED = 1,
308f078b38SDan Williams 	/* locked memory devices should not be accessed */
318f078b38SDan Williams 	NDD_LOCKED = 2,
327d988097SDave Jiang 	/* memory under security wipes should not be accessed */
337d988097SDave Jiang 	NDD_SECURITY_OVERWRITE = 3,
347d988097SDave Jiang 	/*  tracking whether or not there is a pending device reference */
357d988097SDave Jiang 	NDD_WORK_PENDING = 4,
36a0e37452SDan Williams 	/* dimm supports namespace labels */
37a0e37452SDan Williams 	NDD_LABELING = 6,
38dc370b28SDan Williams 	/*
39dc370b28SDan Williams 	 * dimm contents have changed requiring invalidation of CPU caches prior
40dc370b28SDan Williams 	 * to activation of a region that includes this device
41dc370b28SDan Williams 	 */
42dc370b28SDan Williams 	NDD_INCOHERENT = 7,
4362232e45SDan Williams 
44*f57aec44SDan Williams 	/* dimm provider wants synchronous registration by __nvdimm_create() */
45*f57aec44SDan Williams 	NDD_REGISTER_SYNC = 8,
46*f57aec44SDan Williams 
4762232e45SDan Williams 	/* need to set a limit somewhere, but yes, this is likely overkill */
4862232e45SDan Williams 	ND_IOCTL_MAX_BUFLEN = SZ_4M,
494577b066SDan Williams 	ND_CMD_MAX_ELEM = 5,
5040abf9beSJerry Hoemann 	ND_CMD_MAX_ENVELOPE = 256,
511f7df6f8SDan Williams 	ND_MAX_MAPPINGS = 32,
521b40e09aSDan Williams 
53004f1afbSDan Williams 	/* region flag indicating to direct-map persistent memory by default */
54004f1afbSDan Williams 	ND_REGION_PAGEMAP = 0,
5506e8ccdaSDave Jiang 	/*
5606e8ccdaSDave Jiang 	 * Platform ensures entire CPU store data path is flushed to pmem on
5706e8ccdaSDave Jiang 	 * system power loss.
5806e8ccdaSDave Jiang 	 */
5906e8ccdaSDave Jiang 	ND_REGION_PERSIST_CACHE = 1,
6030e6d7bfSDave Jiang 	/*
6130e6d7bfSDave Jiang 	 * Platform provides mechanisms to automatically flush outstanding
6230e6d7bfSDave Jiang 	 * write data from memory controler to pmem on system power loss.
6330e6d7bfSDave Jiang 	 * (ADR)
6430e6d7bfSDave Jiang 	 */
6530e6d7bfSDave Jiang 	ND_REGION_PERSIST_MEMCTRL = 2,
66004f1afbSDan Williams 
67c5d4355dSPankaj Gupta 	/* Platform provides asynchronous flush mechanism */
68c5d4355dSPankaj Gupta 	ND_REGION_ASYNC = 3,
69c5d4355dSPankaj Gupta 
7004ad63f0SDan Williams 	/* Region was created by CXL subsystem */
7104ad63f0SDan Williams 	ND_REGION_CXL = 4,
7204ad63f0SDan Williams 
731b40e09aSDan Williams 	/* mark newly adjusted resources as requiring a label update */
741b40e09aSDan Williams 	DPA_RESOURCE_ADJUSTED = 1 << 0,
75e6dfb2deSDan Williams };
76e6dfb2deSDan Williams 
77b94d5230SDan Williams struct nvdimm;
78b94d5230SDan Williams struct nvdimm_bus_descriptor;
79b94d5230SDan Williams typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,
80b94d5230SDan Williams 		struct nvdimm *nvdimm, unsigned int cmd, void *buf,
81aef25338SDan Williams 		unsigned int buf_len, int *cmd_rc);
82b94d5230SDan Williams 
831ff19f48SOliver O'Halloran struct device_node;
84b94d5230SDan Williams struct nvdimm_bus_descriptor {
8545def22cSDan Williams 	const struct attribute_group **attr_groups;
86e3654ecaSDan Williams 	unsigned long cmd_mask;
8792fe2aa8SDan Williams 	unsigned long dimm_family_mask;
8892fe2aa8SDan Williams 	unsigned long bus_family_mask;
89bc9775d8SDan Williams 	struct module *module;
90b94d5230SDan Williams 	char *provider_name;
911ff19f48SOliver O'Halloran 	struct device_node *of_node;
92b94d5230SDan Williams 	ndctl_fn ndctl;
937ae0fa43SDan Williams 	int (*flush_probe)(struct nvdimm_bus_descriptor *nd_desc);
9487bf572eSDan Williams 	int (*clear_to_send)(struct nvdimm_bus_descriptor *nd_desc,
95b3ed2ce0SDave Jiang 			struct nvdimm *nvdimm, unsigned int cmd, void *data);
9648001ea5SDan Williams 	const struct nvdimm_bus_fw_ops *fw_ops;
97b94d5230SDan Williams };
98b94d5230SDan Williams 
9962232e45SDan Williams struct nd_cmd_desc {
10062232e45SDan Williams 	int in_num;
10162232e45SDan Williams 	int out_num;
10262232e45SDan Williams 	u32 in_sizes[ND_CMD_MAX_ELEM];
10362232e45SDan Williams 	int out_sizes[ND_CMD_MAX_ELEM];
10462232e45SDan Williams };
10562232e45SDan Williams 
106eaf96153SDan Williams struct nd_interleave_set {
107c12c48ceSDan Williams 	/* v1.1 definition of the interleave-set-cookie algorithm */
108c12c48ceSDan Williams 	u64 cookie1;
109c12c48ceSDan Williams 	/* v1.2 definition of the interleave-set-cookie algorithm */
110c12c48ceSDan Williams 	u64 cookie2;
11186ef58a4SDan Williams 	/* compatibility with initial buggy Linux implementation */
11286ef58a4SDan Williams 	u64 altcookie;
113faec6f8aSDan Williams 
114faec6f8aSDan Williams 	guid_t type_guid;
115eaf96153SDan Williams };
116eaf96153SDan Williams 
11744c462ebSDan Williams struct nd_mapping_desc {
11844c462ebSDan Williams 	struct nvdimm *nvdimm;
11944c462ebSDan Williams 	u64 start;
12044c462ebSDan Williams 	u64 size;
121401c0a19SDan Williams 	int position;
12244c462ebSDan Williams };
12344c462ebSDan Williams 
124c5d4355dSPankaj Gupta struct nd_region;
1251f7df6f8SDan Williams struct nd_region_desc {
1261f7df6f8SDan Williams 	struct resource *res;
12744c462ebSDan Williams 	struct nd_mapping_desc *mapping;
1281f7df6f8SDan Williams 	u16 num_mappings;
1291f7df6f8SDan Williams 	const struct attribute_group **attr_groups;
130eaf96153SDan Williams 	struct nd_interleave_set *nd_set;
1311f7df6f8SDan Williams 	void *provider_data;
1325212e11fSVishal Verma 	int num_lanes;
13341d7a6d6SToshi Kani 	int numa_node;
1348fc5c735SDan Williams 	int target_node;
135004f1afbSDan Williams 	unsigned long flags;
13604ad63f0SDan Williams 	int memregion;
1371ff19f48SOliver O'Halloran 	struct device_node *of_node;
138c5d4355dSPankaj Gupta 	int (*flush)(struct nd_region *nd_region, struct bio *bio);
1391f7df6f8SDan Williams };
1401f7df6f8SDan Williams 
14129b9aa0aSDan Williams struct device;
14229b9aa0aSDan Williams void *devm_nvdimm_memremap(struct device *dev, resource_size_t offset,
14329b9aa0aSDan Williams 		size_t size, unsigned long flags);
devm_nvdimm_ioremap(struct device * dev,resource_size_t offset,size_t size)14429b9aa0aSDan Williams static inline void __iomem *devm_nvdimm_ioremap(struct device *dev,
14529b9aa0aSDan Williams 		resource_size_t offset, size_t size)
14629b9aa0aSDan Williams {
14729b9aa0aSDan Williams 	return (void __iomem *) devm_nvdimm_memremap(dev, offset, size, 0);
14829b9aa0aSDan Williams }
14929b9aa0aSDan Williams 
15062232e45SDan Williams struct nvdimm_bus;
151047fc8a1SRoss Zwisler 
152d78c620aSDan Williams /*
153d78c620aSDan Williams  * Note that separate bits for locked + unlocked are defined so that
154d78c620aSDan Williams  * 'flags == 0' corresponds to an error / not-supported state.
155d78c620aSDan Williams  */
156d78c620aSDan Williams enum nvdimm_security_bits {
157f2989396SDave Jiang 	NVDIMM_SECURITY_DISABLED,
158f2989396SDave Jiang 	NVDIMM_SECURITY_UNLOCKED,
159f2989396SDave Jiang 	NVDIMM_SECURITY_LOCKED,
160f2989396SDave Jiang 	NVDIMM_SECURITY_FROZEN,
161f2989396SDave Jiang 	NVDIMM_SECURITY_OVERWRITE,
162f2989396SDave Jiang };
163f2989396SDave Jiang 
1644c6926a2SDave Jiang #define NVDIMM_PASSPHRASE_LEN		32
1654c6926a2SDave Jiang #define NVDIMM_KEY_DESC_LEN		22
1664c6926a2SDave Jiang 
1674c6926a2SDave Jiang struct nvdimm_key_data {
1684c6926a2SDave Jiang 	u8 data[NVDIMM_PASSPHRASE_LEN];
1694c6926a2SDave Jiang };
1704c6926a2SDave Jiang 
17189fa9d8eSDave Jiang enum nvdimm_passphrase_type {
17289fa9d8eSDave Jiang 	NVDIMM_USER,
17389fa9d8eSDave Jiang 	NVDIMM_MASTER,
17489fa9d8eSDave Jiang };
17589fa9d8eSDave Jiang 
176f2989396SDave Jiang struct nvdimm_security_ops {
177d78c620aSDan Williams 	unsigned long (*get_flags)(struct nvdimm *nvdimm,
17889fa9d8eSDave Jiang 			enum nvdimm_passphrase_type pass_type);
17937833fb7SDave Jiang 	int (*freeze)(struct nvdimm *nvdimm);
1804c6926a2SDave Jiang 	int (*change_key)(struct nvdimm *nvdimm,
1814c6926a2SDave Jiang 			const struct nvdimm_key_data *old_data,
18289fa9d8eSDave Jiang 			const struct nvdimm_key_data *new_data,
18389fa9d8eSDave Jiang 			enum nvdimm_passphrase_type pass_type);
1844c6926a2SDave Jiang 	int (*unlock)(struct nvdimm *nvdimm,
1854c6926a2SDave Jiang 			const struct nvdimm_key_data *key_data);
18603b65b22SDave Jiang 	int (*disable)(struct nvdimm *nvdimm,
18703b65b22SDave Jiang 			const struct nvdimm_key_data *key_data);
18864e77c8cSDave Jiang 	int (*erase)(struct nvdimm *nvdimm,
18989fa9d8eSDave Jiang 			const struct nvdimm_key_data *key_data,
19089fa9d8eSDave Jiang 			enum nvdimm_passphrase_type pass_type);
1917d988097SDave Jiang 	int (*overwrite)(struct nvdimm *nvdimm,
1927d988097SDave Jiang 			const struct nvdimm_key_data *key_data);
1937d988097SDave Jiang 	int (*query_overwrite)(struct nvdimm *nvdimm);
194dcedadfaSDave Jiang 	int (*disable_master)(struct nvdimm *nvdimm,
195dcedadfaSDave Jiang 			      const struct nvdimm_key_data *key_data);
196f2989396SDave Jiang };
197f2989396SDave Jiang 
19848001ea5SDan Williams enum nvdimm_fwa_state {
19948001ea5SDan Williams 	NVDIMM_FWA_INVALID,
20048001ea5SDan Williams 	NVDIMM_FWA_IDLE,
20148001ea5SDan Williams 	NVDIMM_FWA_ARMED,
20248001ea5SDan Williams 	NVDIMM_FWA_BUSY,
20348001ea5SDan Williams 	NVDIMM_FWA_ARM_OVERFLOW,
20448001ea5SDan Williams };
20548001ea5SDan Williams 
20648001ea5SDan Williams enum nvdimm_fwa_trigger {
20748001ea5SDan Williams 	NVDIMM_FWA_ARM,
20848001ea5SDan Williams 	NVDIMM_FWA_DISARM,
20948001ea5SDan Williams };
21048001ea5SDan Williams 
21148001ea5SDan Williams enum nvdimm_fwa_capability {
21248001ea5SDan Williams 	NVDIMM_FWA_CAP_INVALID,
21348001ea5SDan Williams 	NVDIMM_FWA_CAP_NONE,
21448001ea5SDan Williams 	NVDIMM_FWA_CAP_QUIESCE,
21548001ea5SDan Williams 	NVDIMM_FWA_CAP_LIVE,
21648001ea5SDan Williams };
21748001ea5SDan Williams 
21848001ea5SDan Williams enum nvdimm_fwa_result {
21948001ea5SDan Williams 	NVDIMM_FWA_RESULT_INVALID,
22048001ea5SDan Williams 	NVDIMM_FWA_RESULT_NONE,
22148001ea5SDan Williams 	NVDIMM_FWA_RESULT_SUCCESS,
22248001ea5SDan Williams 	NVDIMM_FWA_RESULT_NOTSTAGED,
22348001ea5SDan Williams 	NVDIMM_FWA_RESULT_NEEDRESET,
22448001ea5SDan Williams 	NVDIMM_FWA_RESULT_FAIL,
22548001ea5SDan Williams };
22648001ea5SDan Williams 
22748001ea5SDan Williams struct nvdimm_bus_fw_ops {
22848001ea5SDan Williams 	enum nvdimm_fwa_state (*activate_state)
22948001ea5SDan Williams 		(struct nvdimm_bus_descriptor *nd_desc);
23048001ea5SDan Williams 	enum nvdimm_fwa_capability (*capability)
23148001ea5SDan Williams 		(struct nvdimm_bus_descriptor *nd_desc);
23248001ea5SDan Williams 	int (*activate)(struct nvdimm_bus_descriptor *nd_desc);
23348001ea5SDan Williams };
23448001ea5SDan Williams 
23548001ea5SDan Williams struct nvdimm_fw_ops {
23648001ea5SDan Williams 	enum nvdimm_fwa_state (*activate_state)(struct nvdimm *nvdimm);
23748001ea5SDan Williams 	enum nvdimm_fwa_result (*activate_result)(struct nvdimm *nvdimm);
23848001ea5SDan Williams 	int (*arm)(struct nvdimm *nvdimm, enum nvdimm_fwa_trigger arg);
23948001ea5SDan Williams };
24048001ea5SDan Williams 
241aa9ad44aSDave Jiang void badrange_init(struct badrange *badrange);
242aa9ad44aSDave Jiang int badrange_add(struct badrange *badrange, u64 addr, u64 length);
243aa9ad44aSDave Jiang void badrange_forget(struct badrange *badrange, phys_addr_t start,
244aa9ad44aSDave Jiang 		unsigned int len);
245aa9ad44aSDave Jiang int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr,
246aa9ad44aSDave Jiang 		u64 length);
247bc9775d8SDan Williams struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
248bc9775d8SDan Williams 		struct nvdimm_bus_descriptor *nfit_desc);
249b94d5230SDan Williams void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus);
25045def22cSDan Williams struct nvdimm_bus *to_nvdimm_bus(struct device *dev);
251f2989396SDave Jiang struct nvdimm_bus *nvdimm_to_bus(struct nvdimm *nvdimm);
252e6dfb2deSDan Williams struct nvdimm *to_nvdimm(struct device *dev);
2531f7df6f8SDan Williams struct nd_region *to_nd_region(struct device *dev);
254243f29feSDan Williams struct device *nd_region_dev(struct nd_region *nd_region);
25545def22cSDan Williams struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus);
25637b137ffSVishal Verma struct device *to_nvdimm_bus_dev(struct nvdimm_bus *nvdimm_bus);
257e6dfb2deSDan Williams const char *nvdimm_name(struct nvdimm *nvdimm);
258ba9c8dd3SDan Williams struct kobject *nvdimm_kobj(struct nvdimm *nvdimm);
259e3654ecaSDan Williams unsigned long nvdimm_cmd_mask(struct nvdimm *nvdimm);
260e6dfb2deSDan Williams void *nvdimm_provider_data(struct nvdimm *nvdimm);
261d6548ae4SDave Jiang struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
262d6548ae4SDave Jiang 		void *provider_data, const struct attribute_group **groups,
263d6548ae4SDave Jiang 		unsigned long flags, unsigned long cmd_mask, int num_flush,
264f2989396SDave Jiang 		struct resource *flush_wpq, const char *dimm_id,
265a1facc1fSDan Williams 		const struct nvdimm_security_ops *sec_ops,
266a1facc1fSDan Williams 		const struct nvdimm_fw_ops *fw_ops);
nvdimm_create(struct nvdimm_bus * nvdimm_bus,void * provider_data,const struct attribute_group ** groups,unsigned long flags,unsigned long cmd_mask,int num_flush,struct resource * flush_wpq)267d6548ae4SDave Jiang static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus,
268d6548ae4SDave Jiang 		void *provider_data, const struct attribute_group **groups,
269d6548ae4SDave Jiang 		unsigned long flags, unsigned long cmd_mask, int num_flush,
270d6548ae4SDave Jiang 		struct resource *flush_wpq)
271d6548ae4SDave Jiang {
272d6548ae4SDave Jiang 	return __nvdimm_create(nvdimm_bus, provider_data, groups, flags,
273a1facc1fSDan Williams 			cmd_mask, num_flush, flush_wpq, NULL, NULL, NULL);
274d6548ae4SDave Jiang }
275fd14602dSDan Williams void nvdimm_delete(struct nvdimm *nvdimm);
27604ad63f0SDan Williams void nvdimm_region_delete(struct nd_region *nd_region);
277d6548ae4SDave Jiang 
27862232e45SDan Williams const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
27962232e45SDan Williams const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
28062232e45SDan Williams u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
28162232e45SDan Williams 		const struct nd_cmd_desc *desc, int idx, void *buf);
28262232e45SDan Williams u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
28362232e45SDan Williams 		const struct nd_cmd_desc *desc, int idx, const u32 *in_field,
284efda1b5dSDan Williams 		const u32 *out_field, unsigned long remainder);
2854d88a97aSDan Williams int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count);
2861f7df6f8SDan Williams struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus,
2871f7df6f8SDan Williams 		struct nd_region_desc *ndr_desc);
2881f7df6f8SDan Williams struct nd_region *nvdimm_blk_region_create(struct nvdimm_bus *nvdimm_bus,
2891f7df6f8SDan Williams 		struct nd_region_desc *ndr_desc);
2901f7df6f8SDan Williams struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
2911f7df6f8SDan Williams 		struct nd_region_desc *ndr_desc);
292047fc8a1SRoss Zwisler void *nd_region_provider_data(struct nd_region *nd_region);
293047fc8a1SRoss Zwisler unsigned int nd_region_acquire_lane(struct nd_region *nd_region);
294047fc8a1SRoss Zwisler void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane);
295eaf96153SDan Williams u64 nd_fletcher64(void *addr, size_t len, bool le);
296c5d4355dSPankaj Gupta int nvdimm_flush(struct nd_region *nd_region, struct bio *bio);
297c5d4355dSPankaj Gupta int generic_nvdimm_flush(struct nd_region *nd_region);
298f284a4f2SDan Williams int nvdimm_has_flush(struct nd_region *nd_region);
2990b277961SDan Williams int nvdimm_has_cache(struct nd_region *nd_region);
3007d988097SDave Jiang int nvdimm_in_overwrite(struct nvdimm *nvdimm);
301fefc1d97SPankaj Gupta bool is_nvdimm_sync(struct nd_region *nd_region);
3025deb67f7SRobin Murphy 
nvdimm_ctl(struct nvdimm * nvdimm,unsigned int cmd,void * buf,unsigned int buf_len,int * cmd_rc)303f2989396SDave Jiang static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
304f2989396SDave Jiang 		unsigned int buf_len, int *cmd_rc)
305f2989396SDave Jiang {
306f2989396SDave Jiang 	struct nvdimm_bus *nvdimm_bus = nvdimm_to_bus(nvdimm);
307f2989396SDave Jiang 	struct nvdimm_bus_descriptor *nd_desc = to_nd_desc(nvdimm_bus);
308f2989396SDave Jiang 
309f2989396SDave Jiang 	return nd_desc->ndctl(nd_desc, nvdimm, cmd, buf, buf_len, cmd_rc);
310f2989396SDave Jiang }
311f2989396SDave Jiang 
3125deb67f7SRobin Murphy #ifdef CONFIG_ARCH_HAS_PMEM_API
3135deb67f7SRobin Murphy #define ARCH_MEMREMAP_PMEM MEMREMAP_WB
3145deb67f7SRobin Murphy void arch_wb_cache_pmem(void *addr, size_t size);
3155deb67f7SRobin Murphy void arch_invalidate_pmem(void *addr, size_t size);
3165deb67f7SRobin Murphy #else
3175deb67f7SRobin Murphy #define ARCH_MEMREMAP_PMEM MEMREMAP_WT
arch_wb_cache_pmem(void * addr,size_t size)3185deb67f7SRobin Murphy static inline void arch_wb_cache_pmem(void *addr, size_t size)
3195deb67f7SRobin Murphy {
3205deb67f7SRobin Murphy }
arch_invalidate_pmem(void * addr,size_t size)3215deb67f7SRobin Murphy static inline void arch_invalidate_pmem(void *addr, size_t size)
3225deb67f7SRobin Murphy {
3235deb67f7SRobin Murphy }
3245deb67f7SRobin Murphy #endif
3255deb67f7SRobin Murphy 
326b94d5230SDan Williams #endif /* __LIBNVDIMM_H__ */
327