aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dax
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dax')
-rw-r--r--drivers/dax/Kconfig16
-rw-r--r--drivers/dax/Makefile1
-rw-r--r--drivers/dax/kmem.c108
3 files changed, 125 insertions, 0 deletions
diff --git a/drivers/dax/Kconfig b/drivers/dax/Kconfig
index 6fc96f03920e..5ef624fe3934 100644
--- a/drivers/dax/Kconfig
+++ b/drivers/dax/Kconfig
@@ -32,6 +32,22 @@ config DEV_DAX_PMEM
32 32
33 Say M if unsure 33 Say M if unsure
34 34
35config DEV_DAX_KMEM
36 tristate "KMEM DAX: volatile-use of persistent memory"
37 default DEV_DAX
38 depends on DEV_DAX
39 depends on MEMORY_HOTPLUG # for add_memory() and friends
40 help
41 Support access to persistent memory as if it were RAM. This
42 allows easier use of persistent memory by unmodified
43 applications.
44
45 To use this feature, a DAX device must be unbound from the
46 device_dax driver (PMEM DAX) and bound to this kmem driver
47 on each boot.
48
49 Say N if unsure.
50
35config DEV_DAX_PMEM_COMPAT 51config DEV_DAX_PMEM_COMPAT
36 tristate "PMEM DAX: support the deprecated /sys/class/dax interface" 52 tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
37 depends on DEV_DAX_PMEM 53 depends on DEV_DAX_PMEM
diff --git a/drivers/dax/Makefile b/drivers/dax/Makefile
index 233bbffccbe6..81f7d54dadfb 100644
--- a/drivers/dax/Makefile
+++ b/drivers/dax/Makefile
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0 1# SPDX-License-Identifier: GPL-2.0
2obj-$(CONFIG_DAX) += dax.o 2obj-$(CONFIG_DAX) += dax.o
3obj-$(CONFIG_DEV_DAX) += device_dax.o 3obj-$(CONFIG_DEV_DAX) += device_dax.o
4obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
4 5
5dax-y := super.o 6dax-y := super.o
6dax-y += bus.o 7dax-y += bus.o
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
new file mode 100644
index 000000000000..a02318c6d28a
--- /dev/null
+++ b/drivers/dax/kmem.c
@@ -0,0 +1,108 @@
1// SPDX-License-Identifier: GPL-2.0
2/* Copyright(c) 2016-2019 Intel Corporation. All rights reserved. */
3#include <linux/memremap.h>
4#include <linux/pagemap.h>
5#include <linux/memory.h>
6#include <linux/module.h>
7#include <linux/device.h>
8#include <linux/pfn_t.h>
9#include <linux/slab.h>
10#include <linux/dax.h>
11#include <linux/fs.h>
12#include <linux/mm.h>
13#include <linux/mman.h>
14#include "dax-private.h"
15#include "bus.h"
16
17int dev_dax_kmem_probe(struct device *dev)
18{
19 struct dev_dax *dev_dax = to_dev_dax(dev);
20 struct resource *res = &dev_dax->region->res;
21 resource_size_t kmem_start;
22 resource_size_t kmem_size;
23 resource_size_t kmem_end;
24 struct resource *new_res;
25 int numa_node;
26 int rc;
27
28 /*
29 * Ensure good NUMA information for the persistent memory.
30 * Without this check, there is a risk that slow memory
31 * could be mixed in a node with faster memory, causing
32 * unavoidable performance issues.
33 */
34 numa_node = dev_dax->target_node;
35 if (numa_node < 0) {
36 dev_warn(dev, "rejecting DAX region %pR with invalid node: %d\n",
37 res, numa_node);
38 return -EINVAL;
39 }
40
41 /* Hotplug starting at the beginning of the next block: */
42 kmem_start = ALIGN(res->start, memory_block_size_bytes());
43
44 kmem_size = resource_size(res);
45 /* Adjust the size down to compensate for moving up kmem_start: */
46 kmem_size -= kmem_start - res->start;
47 /* Align the size down to cover only complete blocks: */
48 kmem_size &= ~(memory_block_size_bytes() - 1);
49 kmem_end = kmem_start + kmem_size;
50
51 /* Region is permanently reserved. Hot-remove not yet implemented. */
52 new_res = request_mem_region(kmem_start, kmem_size, dev_name(dev));
53 if (!new_res) {
54 dev_warn(dev, "could not reserve region [%pa-%pa]\n",
55 &kmem_start, &kmem_end);
56 return -EBUSY;
57 }
58
59 /*
60 * Set flags appropriate for System RAM. Leave ..._BUSY clear
61 * so that add_memory() can add a child resource. Do not
62 * inherit flags from the parent since it may set new flags
63 * unknown to us that will break add_memory() below.
64 */
65 new_res->flags = IORESOURCE_SYSTEM_RAM;
66 new_res->name = dev_name(dev);
67
68 rc = add_memory(numa_node, new_res->start, resource_size(new_res));
69 if (rc)
70 return rc;
71
72 return 0;
73}
74
75static int dev_dax_kmem_remove(struct device *dev)
76{
77 /*
78 * Purposely leak the request_mem_region() for the device-dax
79 * range and return '0' to ->remove() attempts. The removal of
80 * the device from the driver always succeeds, but the region
81 * is permanently pinned as reserved by the unreleased
82 * request_mem_region().
83 */
84 return 0;
85}
86
87static struct dax_device_driver device_dax_kmem_driver = {
88 .drv = {
89 .probe = dev_dax_kmem_probe,
90 .remove = dev_dax_kmem_remove,
91 },
92};
93
94static int __init dax_kmem_init(void)
95{
96 return dax_driver_register(&device_dax_kmem_driver);
97}
98
99static void __exit dax_kmem_exit(void)
100{
101 dax_driver_unregister(&device_dax_kmem_driver);
102}
103
104MODULE_AUTHOR("Intel Corporation");
105MODULE_LICENSE("GPL v2");
106module_init(dax_kmem_init);
107module_exit(dax_kmem_exit);
108MODULE_ALIAS_DAX_DEVICE(0);