summaryrefslogtreecommitdiffstats
path: root/drivers/dax/kmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/dax/kmem.c')
-rw-r--r--drivers/dax/kmem.c46
1 files changed, 41 insertions, 5 deletions
diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
index a02318c6d28a..3d0a7e702c94 100644
--- a/drivers/dax/kmem.c
+++ b/drivers/dax/kmem.c
@@ -66,23 +66,59 @@ int dev_dax_kmem_probe(struct device *dev)
66 new_res->name = dev_name(dev); 66 new_res->name = dev_name(dev);
67 67
68 rc = add_memory(numa_node, new_res->start, resource_size(new_res)); 68 rc = add_memory(numa_node, new_res->start, resource_size(new_res));
69 if (rc) 69 if (rc) {
70 release_resource(new_res);
71 kfree(new_res);
70 return rc; 72 return rc;
73 }
74 dev_dax->dax_kmem_res = new_res;
71 75
72 return 0; 76 return 0;
73} 77}
74 78
79#ifdef CONFIG_MEMORY_HOTREMOVE
80static int dev_dax_kmem_remove(struct device *dev)
81{
82 struct dev_dax *dev_dax = to_dev_dax(dev);
83 struct resource *res = dev_dax->dax_kmem_res;
84 resource_size_t kmem_start = res->start;
85 resource_size_t kmem_size = resource_size(res);
86 int rc;
87
88 /*
89 * We have one shot for removing memory, if some memory blocks were not
90 * offline prior to calling this function remove_memory() will fail, and
91 * there is no way to hotremove this memory until reboot because device
92 * unbind will succeed even if we return failure.
93 */
94 rc = remove_memory(dev_dax->target_node, kmem_start, kmem_size);
95 if (rc) {
96 dev_err(dev,
97 "DAX region %pR cannot be hotremoved until the next reboot\n",
98 res);
99 return rc;
100 }
101
102 /* Release and free dax resources */
103 release_resource(res);
104 kfree(res);
105 dev_dax->dax_kmem_res = NULL;
106
107 return 0;
108}
109#else
75static int dev_dax_kmem_remove(struct device *dev) 110static int dev_dax_kmem_remove(struct device *dev)
76{ 111{
77 /* 112 /*
78 * Purposely leak the request_mem_region() for the device-dax 113 * Without hotremove purposely leak the request_mem_region() for the
79 * range and return '0' to ->remove() attempts. The removal of 114 * device-dax range and return '0' to ->remove() attempts. The removal
80 * the device from the driver always succeeds, but the region 115 * of the device from the driver always succeeds, but the region is
81 * is permanently pinned as reserved by the unreleased 116 * permanently pinned as reserved by the unreleased
82 * request_mem_region(). 117 * request_mem_region().
83 */ 118 */
84 return 0; 119 return 0;
85} 120}
121#endif /* CONFIG_MEMORY_HOTREMOVE */
86 122
87static struct dax_device_driver device_dax_kmem_driver = { 123static struct dax_device_driver device_dax_kmem_driver = {
88 .drv = { 124 .drv = {