aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-06-29 13:34:42 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-06-29 13:34:42 -0400
commit88793e5c774ec69351ef6b5200bb59f532e41bca (patch)
tree54c4be61777ea53fde892b71e795322c5227d16e /include
parent1bc5e157ed2b4f5b206155fc772d860158acd201 (diff)
parent61031952f4c89dba1065f7a5b9419badb112554c (diff)
Merge tag 'libnvdimm-for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm
Pull libnvdimm subsystem from Dan Williams: "The libnvdimm sub-system introduces, in addition to the libnvdimm-core, 4 drivers / enabling modules: NFIT: Instantiates an "nvdimm bus" with the core and registers memory devices (NVDIMMs) enumerated by the ACPI 6.0 NFIT (NVDIMM Firmware Interface table). After registering NVDIMMs the NFIT driver then registers "region" devices. A libnvdimm-region defines an access mode and the boundaries of persistent memory media. A region may span multiple NVDIMMs that are interleaved by the hardware memory controller. In turn, a libnvdimm-region can be carved into a "namespace" device and bound to the PMEM or BLK driver which will attach a Linux block device (disk) interface to the memory. PMEM: Initially merged in v4.1 this driver for contiguous spans of persistent memory address ranges is re-worked to drive PMEM-namespaces emitted by the libnvdimm-core. In this update the PMEM driver, on x86, gains the ability to assert that writes to persistent memory have been flushed all the way through the caches and buffers in the platform to persistent media. See memcpy_to_pmem() and wmb_pmem(). BLK: This new driver enables access to persistent memory media through "Block Data Windows" as defined by the NFIT. The primary difference of this driver to PMEM is that only a small window of persistent memory is mapped into system address space at any given point in time. Per-NVDIMM windows are reprogrammed at run time, per-I/O, to access different portions of the media. BLK-mode, by definition, does not support DAX. BTT: This is a library, optionally consumed by either PMEM or BLK, that converts a byte-accessible namespace into a disk with atomic sector update semantics (prevents sector tearing on crash or power loss). The sinister aspect of sector tearing is that most applications do not know they have a atomic sector dependency. At least today's disk's rarely ever tear sectors and if they do one almost certainly gets a CRC error on access. NVDIMMs will always tear and always silently. Until an application is audited to be robust in the presence of sector-tearing the usage of BTT is recommended. Thanks to: Ross Zwisler, Jeff Moyer, Vishal Verma, Christoph Hellwig, Ingo Molnar, Neil Brown, Boaz Harrosh, Robert Elliott, Matthew Wilcox, Andy Rudoff, Linda Knippers, Toshi Kani, Nicholas Moulin, Rafael Wysocki, and Bob Moore" * tag 'libnvdimm-for-4.2' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/nvdimm: (33 commits) arch, x86: pmem api for ensuring durability of persistent memory updates libnvdimm: Add sysfs numa_node to NVDIMM devices libnvdimm: Set numa_node to NVDIMM devices acpi: Add acpi_map_pxm_to_online_node() libnvdimm, nfit: handle unarmed dimms, mark namespaces read-only pmem: flag pmem block devices as non-rotational libnvdimm: enable iostat pmem: make_request cleanups libnvdimm, pmem: fix up max_hw_sectors libnvdimm, blk: add support for blk integrity libnvdimm, btt: add support for blk integrity fs/block_dev.c: skip rw_page if bdev has integrity libnvdimm: Non-Volatile Devices tools/testing/nvdimm: libnvdimm unit test infrastructure libnvdimm, nfit, nd_blk: driver for BLK-mode access persistent memory nd_btt: atomic sector updates libnvdimm: infrastructure for btt devices libnvdimm: write blk label set libnvdimm: write pmem label set libnvdimm: blk labels and namespace instantiation ...
Diffstat (limited to 'include')
-rw-r--r--include/linux/acpi.h5
-rw-r--r--include/linux/compiler.h2
-rw-r--r--include/linux/efi.h3
-rw-r--r--include/linux/libnvdimm.h151
-rw-r--r--include/linux/nd.h151
-rw-r--r--include/linux/pmem.h152
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/ndctl.h197
8 files changed, 661 insertions, 1 deletions
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index c187817471fb..1618cdfb38c7 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -261,8 +261,13 @@ extern void acpi_osi_setup(char *str);
261extern bool acpi_osi_is_win8(void); 261extern bool acpi_osi_is_win8(void);
262 262
263#ifdef CONFIG_ACPI_NUMA 263#ifdef CONFIG_ACPI_NUMA
264int acpi_map_pxm_to_online_node(int pxm);
264int acpi_get_node(acpi_handle handle); 265int acpi_get_node(acpi_handle handle);
265#else 266#else
267static inline int acpi_map_pxm_to_online_node(int pxm)
268{
269 return 0;
270}
266static inline int acpi_get_node(acpi_handle handle) 271static inline int acpi_get_node(acpi_handle handle)
267{ 272{
268 return 0; 273 return 0;
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 05be2352fef8..26fc8bc77f85 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -21,6 +21,7 @@
21# define __rcu __attribute__((noderef, address_space(4))) 21# define __rcu __attribute__((noderef, address_space(4)))
22#else 22#else
23# define __rcu 23# define __rcu
24# define __pmem __attribute__((noderef, address_space(5)))
24#endif 25#endif
25extern void __chk_user_ptr(const volatile void __user *); 26extern void __chk_user_ptr(const volatile void __user *);
26extern void __chk_io_ptr(const volatile void __iomem *); 27extern void __chk_io_ptr(const volatile void __iomem *);
@@ -42,6 +43,7 @@ extern void __chk_io_ptr(const volatile void __iomem *);
42# define __cond_lock(x,c) (c) 43# define __cond_lock(x,c) (c)
43# define __percpu 44# define __percpu
44# define __rcu 45# define __rcu
46# define __pmem
45#endif 47#endif
46 48
47/* Indirect macros required for expanded argument pasting, eg. __LINE__. */ 49/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f19efe4eb3f..85ef051ac6fb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -85,7 +85,8 @@ typedef struct {
85#define EFI_MEMORY_MAPPED_IO 11 85#define EFI_MEMORY_MAPPED_IO 11
86#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 86#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
87#define EFI_PAL_CODE 13 87#define EFI_PAL_CODE 13
88#define EFI_MAX_MEMORY_TYPE 14 88#define EFI_PERSISTENT_MEMORY 14
89#define EFI_MAX_MEMORY_TYPE 15
89 90
90/* Attribute values: */ 91/* Attribute values: */
91#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ 92#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
new file mode 100644
index 000000000000..75e3af01ee32
--- /dev/null
+++ b/include/linux/libnvdimm.h
@@ -0,0 +1,151 @@
1/*
2 * libnvdimm - Non-volatile-memory Devices Subsystem
3 *
4 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of version 2 of the GNU General Public License as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 */
15#ifndef __LIBNVDIMM_H__
16#define __LIBNVDIMM_H__
17#include <linux/kernel.h>
18#include <linux/sizes.h>
19#include <linux/types.h>
20
21enum {
22 /* when a dimm supports both PMEM and BLK access a label is required */
23 NDD_ALIASING = 1 << 0,
24 /* unarmed memory devices may not persist writes */
25 NDD_UNARMED = 1 << 1,
26
27 /* need to set a limit somewhere, but yes, this is likely overkill */
28 ND_IOCTL_MAX_BUFLEN = SZ_4M,
29 ND_CMD_MAX_ELEM = 4,
30 ND_CMD_MAX_ENVELOPE = 16,
31 ND_CMD_ARS_STATUS_MAX = SZ_4K,
32 ND_MAX_MAPPINGS = 32,
33
34 /* mark newly adjusted resources as requiring a label update */
35 DPA_RESOURCE_ADJUSTED = 1 << 0,
36};
37
38extern struct attribute_group nvdimm_bus_attribute_group;
39extern struct attribute_group nvdimm_attribute_group;
40extern struct attribute_group nd_device_attribute_group;
41extern struct attribute_group nd_numa_attribute_group;
42extern struct attribute_group nd_region_attribute_group;
43extern struct attribute_group nd_mapping_attribute_group;
44
45struct nvdimm;
46struct nvdimm_bus_descriptor;
47typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,
48 struct nvdimm *nvdimm, unsigned int cmd, void *buf,
49 unsigned int buf_len);
50
51struct nd_namespace_label;
52struct nvdimm_drvdata;
53struct nd_mapping {
54 struct nvdimm *nvdimm;
55 struct nd_namespace_label **labels;
56 u64 start;
57 u64 size;
58 /*
59 * @ndd is for private use at region enable / disable time for
60 * get_ndd() + put_ndd(), all other nd_mapping to ndd
61 * conversions use to_ndd() which respects enabled state of the
62 * nvdimm.
63 */
64 struct nvdimm_drvdata *ndd;
65};
66
67struct nvdimm_bus_descriptor {
68 const struct attribute_group **attr_groups;
69 unsigned long dsm_mask;
70 char *provider_name;
71 ndctl_fn ndctl;
72};
73
74struct nd_cmd_desc {
75 int in_num;
76 int out_num;
77 u32 in_sizes[ND_CMD_MAX_ELEM];
78 int out_sizes[ND_CMD_MAX_ELEM];
79};
80
81struct nd_interleave_set {
82 u64 cookie;
83};
84
85struct nd_region_desc {
86 struct resource *res;
87 struct nd_mapping *nd_mapping;
88 u16 num_mappings;
89 const struct attribute_group **attr_groups;
90 struct nd_interleave_set *nd_set;
91 void *provider_data;
92 int num_lanes;
93 int numa_node;
94};
95
96struct nvdimm_bus;
97struct module;
98struct device;
99struct nd_blk_region;
100struct nd_blk_region_desc {
101 int (*enable)(struct nvdimm_bus *nvdimm_bus, struct device *dev);
102 void (*disable)(struct nvdimm_bus *nvdimm_bus, struct device *dev);
103 int (*do_io)(struct nd_blk_region *ndbr, resource_size_t dpa,
104 void *iobuf, u64 len, int rw);
105 struct nd_region_desc ndr_desc;
106};
107
108static inline struct nd_blk_region_desc *to_blk_region_desc(
109 struct nd_region_desc *ndr_desc)
110{
111 return container_of(ndr_desc, struct nd_blk_region_desc, ndr_desc);
112
113}
114
115struct nvdimm_bus *__nvdimm_bus_register(struct device *parent,
116 struct nvdimm_bus_descriptor *nfit_desc, struct module *module);
117#define nvdimm_bus_register(parent, desc) \
118 __nvdimm_bus_register(parent, desc, THIS_MODULE)
119void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus);
120struct nvdimm_bus *to_nvdimm_bus(struct device *dev);
121struct nvdimm *to_nvdimm(struct device *dev);
122struct nd_region *to_nd_region(struct device *dev);
123struct nd_blk_region *to_nd_blk_region(struct device *dev);
124struct nvdimm_bus_descriptor *to_nd_desc(struct nvdimm_bus *nvdimm_bus);
125const char *nvdimm_name(struct nvdimm *nvdimm);
126void *nvdimm_provider_data(struct nvdimm *nvdimm);
127struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus, void *provider_data,
128 const struct attribute_group **groups, unsigned long flags,
129 unsigned long *dsm_mask);
130const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
131const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
132u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
133 const struct nd_cmd_desc *desc, int idx, void *buf);
134u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
135 const struct nd_cmd_desc *desc, int idx, const u32 *in_field,
136 const u32 *out_field);
137int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count);
138struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus,
139 struct nd_region_desc *ndr_desc);
140struct nd_region *nvdimm_blk_region_create(struct nvdimm_bus *nvdimm_bus,
141 struct nd_region_desc *ndr_desc);
142struct nd_region *nvdimm_volatile_region_create(struct nvdimm_bus *nvdimm_bus,
143 struct nd_region_desc *ndr_desc);
144void *nd_region_provider_data(struct nd_region *nd_region);
145void *nd_blk_region_provider_data(struct nd_blk_region *ndbr);
146void nd_blk_region_set_provider_data(struct nd_blk_region *ndbr, void *data);
147struct nvdimm *nd_blk_region_to_dimm(struct nd_blk_region *ndbr);
148unsigned int nd_region_acquire_lane(struct nd_region *nd_region);
149void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane);
150u64 nd_fletcher64(void *addr, size_t len, bool le);
151#endif /* __LIBNVDIMM_H__ */
diff --git a/include/linux/nd.h b/include/linux/nd.h
new file mode 100644
index 000000000000..507e47c86737
--- /dev/null
+++ b/include/linux/nd.h
@@ -0,0 +1,151 @@
1/*
2 * Copyright(c) 2013-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 __LINUX_ND_H__
14#define __LINUX_ND_H__
15#include <linux/fs.h>
16#include <linux/ndctl.h>
17#include <linux/device.h>
18
19struct nd_device_driver {
20 struct device_driver drv;
21 unsigned long type;
22 int (*probe)(struct device *dev);
23 int (*remove)(struct device *dev);
24};
25
26static inline struct nd_device_driver *to_nd_device_driver(
27 struct device_driver *drv)
28{
29 return container_of(drv, struct nd_device_driver, drv);
30};
31
32/**
33 * struct nd_namespace_common - core infrastructure of a namespace
34 * @force_raw: ignore other personalities for the namespace (e.g. btt)
35 * @dev: device model node
36 * @claim: when set a another personality has taken ownership of the namespace
37 * @rw_bytes: access the raw namespace capacity with byte-aligned transfers
38 */
39struct nd_namespace_common {
40 int force_raw;
41 struct device dev;
42 struct device *claim;
43 int (*rw_bytes)(struct nd_namespace_common *, resource_size_t offset,
44 void *buf, size_t size, int rw);
45};
46
47static inline struct nd_namespace_common *to_ndns(struct device *dev)
48{
49 return container_of(dev, struct nd_namespace_common, dev);
50}
51
52/**
53 * struct nd_namespace_io - infrastructure for loading an nd_pmem instance
54 * @dev: namespace device created by the nd region driver
55 * @res: struct resource conversion of a NFIT SPA table
56 */
57struct nd_namespace_io {
58 struct nd_namespace_common common;
59 struct resource res;
60};
61
62/**
63 * struct nd_namespace_pmem - namespace device for dimm-backed interleaved memory
64 * @nsio: device and system physical address range to drive
65 * @alt_name: namespace name supplied in the dimm label
66 * @uuid: namespace name supplied in the dimm label
67 */
68struct nd_namespace_pmem {
69 struct nd_namespace_io nsio;
70 char *alt_name;
71 u8 *uuid;
72};
73
74/**
75 * struct nd_namespace_blk - namespace for dimm-bounded persistent memory
76 * @alt_name: namespace name supplied in the dimm label
77 * @uuid: namespace name supplied in the dimm label
78 * @id: ida allocated id
79 * @lbasize: blk namespaces have a native sector size when btt not present
80 * @num_resources: number of dpa extents to claim
81 * @res: discontiguous dpa extents for given dimm
82 */
83struct nd_namespace_blk {
84 struct nd_namespace_common common;
85 char *alt_name;
86 u8 *uuid;
87 int id;
88 unsigned long lbasize;
89 int num_resources;
90 struct resource **res;
91};
92
93static inline struct nd_namespace_io *to_nd_namespace_io(struct device *dev)
94{
95 return container_of(dev, struct nd_namespace_io, common.dev);
96}
97
98static inline struct nd_namespace_pmem *to_nd_namespace_pmem(struct device *dev)
99{
100 struct nd_namespace_io *nsio = to_nd_namespace_io(dev);
101
102 return container_of(nsio, struct nd_namespace_pmem, nsio);
103}
104
105static inline struct nd_namespace_blk *to_nd_namespace_blk(struct device *dev)
106{
107 return container_of(dev, struct nd_namespace_blk, common.dev);
108}
109
110/**
111 * nvdimm_read_bytes() - synchronously read bytes from an nvdimm namespace
112 * @ndns: device to read
113 * @offset: namespace-relative starting offset
114 * @buf: buffer to fill
115 * @size: transfer length
116 *
117 * @buf is up-to-date upon return from this routine.
118 */
119static inline int nvdimm_read_bytes(struct nd_namespace_common *ndns,
120 resource_size_t offset, void *buf, size_t size)
121{
122 return ndns->rw_bytes(ndns, offset, buf, size, READ);
123}
124
125/**
126 * nvdimm_write_bytes() - synchronously write bytes to an nvdimm namespace
127 * @ndns: device to read
128 * @offset: namespace-relative starting offset
129 * @buf: buffer to drain
130 * @size: transfer length
131 *
132 * NVDIMM Namepaces disks do not implement sectors internally. Depending on
133 * the @ndns, the contents of @buf may be in cpu cache, platform buffers,
134 * or on backing memory media upon return from this routine. Flushing
135 * to media is handled internal to the @ndns driver, if at all.
136 */
137static inline int nvdimm_write_bytes(struct nd_namespace_common *ndns,
138 resource_size_t offset, void *buf, size_t size)
139{
140 return ndns->rw_bytes(ndns, offset, buf, size, WRITE);
141}
142
143#define MODULE_ALIAS_ND_DEVICE(type) \
144 MODULE_ALIAS("nd:t" __stringify(type) "*")
145#define ND_DEVICE_MODALIAS_FMT "nd:t%d"
146
147int __must_check __nd_driver_register(struct nd_device_driver *nd_drv,
148 struct module *module, const char *mod_name);
149#define nd_driver_register(driver) \
150 __nd_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
151#endif /* __LINUX_ND_H__ */
diff --git a/include/linux/pmem.h b/include/linux/pmem.h
new file mode 100644
index 000000000000..d2114045a6c4
--- /dev/null
+++ b/include/linux/pmem.h
@@ -0,0 +1,152 @@
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__ */
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index c1c23f19d4a2..1ff9942718fe 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -272,6 +272,7 @@ header-y += ncp_fs.h
272header-y += ncp.h 272header-y += ncp.h
273header-y += ncp_mount.h 273header-y += ncp_mount.h
274header-y += ncp_no.h 274header-y += ncp_no.h
275header-y += ndctl.h
275header-y += neighbour.h 276header-y += neighbour.h
276header-y += netconf.h 277header-y += netconf.h
277header-y += netdevice.h 278header-y += netdevice.h
diff --git a/include/uapi/linux/ndctl.h b/include/uapi/linux/ndctl.h
new file mode 100644
index 000000000000..2b94ea2287bb
--- /dev/null
+++ b/include/uapi/linux/ndctl.h
@@ -0,0 +1,197 @@
1/*
2 * Copyright (c) 2014-2015, Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU Lesser General Public License,
6 * version 2.1, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT ANY
9 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
11 * more details.
12 */
13#ifndef __NDCTL_H__
14#define __NDCTL_H__
15
16#include <linux/types.h>
17
18struct nd_cmd_smart {
19 __u32 status;
20 __u8 data[128];
21} __packed;
22
23struct nd_cmd_smart_threshold {
24 __u32 status;
25 __u8 data[8];
26} __packed;
27
28struct nd_cmd_dimm_flags {
29 __u32 status;
30 __u32 flags;
31} __packed;
32
33struct nd_cmd_get_config_size {
34 __u32 status;
35 __u32 config_size;
36 __u32 max_xfer;
37} __packed;
38
39struct nd_cmd_get_config_data_hdr {
40 __u32 in_offset;
41 __u32 in_length;
42 __u32 status;
43 __u8 out_buf[0];
44} __packed;
45
46struct nd_cmd_set_config_hdr {
47 __u32 in_offset;
48 __u32 in_length;
49 __u8 in_buf[0];
50} __packed;
51
52struct nd_cmd_vendor_hdr {
53 __u32 opcode;
54 __u32 in_length;
55 __u8 in_buf[0];
56} __packed;
57
58struct nd_cmd_vendor_tail {
59 __u32 status;
60 __u32 out_length;
61 __u8 out_buf[0];
62} __packed;
63
64struct nd_cmd_ars_cap {
65 __u64 address;
66 __u64 length;
67 __u32 status;
68 __u32 max_ars_out;
69} __packed;
70
71struct nd_cmd_ars_start {
72 __u64 address;
73 __u64 length;
74 __u16 type;
75 __u8 reserved[6];
76 __u32 status;
77} __packed;
78
79struct nd_cmd_ars_status {
80 __u32 status;
81 __u32 out_length;
82 __u64 address;
83 __u64 length;
84 __u16 type;
85 __u32 num_records;
86 struct nd_ars_record {
87 __u32 handle;
88 __u32 flags;
89 __u64 err_address;
90 __u64 mask;
91 } __packed records[0];
92} __packed;
93
94enum {
95 ND_CMD_IMPLEMENTED = 0,
96
97 /* bus commands */
98 ND_CMD_ARS_CAP = 1,
99 ND_CMD_ARS_START = 2,
100 ND_CMD_ARS_STATUS = 3,
101
102 /* per-dimm commands */
103 ND_CMD_SMART = 1,
104 ND_CMD_SMART_THRESHOLD = 2,
105 ND_CMD_DIMM_FLAGS = 3,
106 ND_CMD_GET_CONFIG_SIZE = 4,
107 ND_CMD_GET_CONFIG_DATA = 5,
108 ND_CMD_SET_CONFIG_DATA = 6,
109 ND_CMD_VENDOR_EFFECT_LOG_SIZE = 7,
110 ND_CMD_VENDOR_EFFECT_LOG = 8,
111 ND_CMD_VENDOR = 9,
112};
113
114static inline const char *nvdimm_bus_cmd_name(unsigned cmd)
115{
116 static const char * const names[] = {
117 [ND_CMD_ARS_CAP] = "ars_cap",
118 [ND_CMD_ARS_START] = "ars_start",
119 [ND_CMD_ARS_STATUS] = "ars_status",
120 };
121
122 if (cmd < ARRAY_SIZE(names) && names[cmd])
123 return names[cmd];
124 return "unknown";
125}
126
127static inline const char *nvdimm_cmd_name(unsigned cmd)
128{
129 static const char * const names[] = {
130 [ND_CMD_SMART] = "smart",
131 [ND_CMD_SMART_THRESHOLD] = "smart_thresh",
132 [ND_CMD_DIMM_FLAGS] = "flags",
133 [ND_CMD_GET_CONFIG_SIZE] = "get_size",
134 [ND_CMD_GET_CONFIG_DATA] = "get_data",
135 [ND_CMD_SET_CONFIG_DATA] = "set_data",
136 [ND_CMD_VENDOR_EFFECT_LOG_SIZE] = "effect_size",
137 [ND_CMD_VENDOR_EFFECT_LOG] = "effect_log",
138 [ND_CMD_VENDOR] = "vendor",
139 };
140
141 if (cmd < ARRAY_SIZE(names) && names[cmd])
142 return names[cmd];
143 return "unknown";
144}
145
146#define ND_IOCTL 'N'
147
148#define ND_IOCTL_SMART _IOWR(ND_IOCTL, ND_CMD_SMART,\
149 struct nd_cmd_smart)
150
151#define ND_IOCTL_SMART_THRESHOLD _IOWR(ND_IOCTL, ND_CMD_SMART_THRESHOLD,\
152 struct nd_cmd_smart_threshold)
153
154#define ND_IOCTL_DIMM_FLAGS _IOWR(ND_IOCTL, ND_CMD_DIMM_FLAGS,\
155 struct nd_cmd_dimm_flags)
156
157#define ND_IOCTL_GET_CONFIG_SIZE _IOWR(ND_IOCTL, ND_CMD_GET_CONFIG_SIZE,\
158 struct nd_cmd_get_config_size)
159
160#define ND_IOCTL_GET_CONFIG_DATA _IOWR(ND_IOCTL, ND_CMD_GET_CONFIG_DATA,\
161 struct nd_cmd_get_config_data_hdr)
162
163#define ND_IOCTL_SET_CONFIG_DATA _IOWR(ND_IOCTL, ND_CMD_SET_CONFIG_DATA,\
164 struct nd_cmd_set_config_hdr)
165
166#define ND_IOCTL_VENDOR _IOWR(ND_IOCTL, ND_CMD_VENDOR,\
167 struct nd_cmd_vendor_hdr)
168
169#define ND_IOCTL_ARS_CAP _IOWR(ND_IOCTL, ND_CMD_ARS_CAP,\
170 struct nd_cmd_ars_cap)
171
172#define ND_IOCTL_ARS_START _IOWR(ND_IOCTL, ND_CMD_ARS_START,\
173 struct nd_cmd_ars_start)
174
175#define ND_IOCTL_ARS_STATUS _IOWR(ND_IOCTL, ND_CMD_ARS_STATUS,\
176 struct nd_cmd_ars_status)
177
178#define ND_DEVICE_DIMM 1 /* nd_dimm: container for "config data" */
179#define ND_DEVICE_REGION_PMEM 2 /* nd_region: (parent of PMEM namespaces) */
180#define ND_DEVICE_REGION_BLK 3 /* nd_region: (parent of BLK namespaces) */
181#define ND_DEVICE_NAMESPACE_IO 4 /* legacy persistent memory */
182#define ND_DEVICE_NAMESPACE_PMEM 5 /* PMEM namespace (may alias with BLK) */
183#define ND_DEVICE_NAMESPACE_BLK 6 /* BLK namespace (may alias with PMEM) */
184
185enum nd_driver_flags {
186 ND_DRIVER_DIMM = 1 << ND_DEVICE_DIMM,
187 ND_DRIVER_REGION_PMEM = 1 << ND_DEVICE_REGION_PMEM,
188 ND_DRIVER_REGION_BLK = 1 << ND_DEVICE_REGION_BLK,
189 ND_DRIVER_NAMESPACE_IO = 1 << ND_DEVICE_NAMESPACE_IO,
190 ND_DRIVER_NAMESPACE_PMEM = 1 << ND_DEVICE_NAMESPACE_PMEM,
191 ND_DRIVER_NAMESPACE_BLK = 1 << ND_DEVICE_NAMESPACE_BLK,
192};
193
194enum {
195 ND_MIN_NAMESPACE_SIZE = 0x00400000,
196};
197#endif /* __NDCTL_H__ */