/dev/dax, pmem: direct access to persistent memory
[cascardo/linux.git] / drivers / dax / dax.c
1 /*
2  * Copyright(c) 2016 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 #include <linux/pagemap.h>
14 #include <linux/module.h>
15 #include <linux/device.h>
16 #include <linux/pfn_t.h>
17 #include <linux/slab.h>
18 #include <linux/dax.h>
19 #include <linux/fs.h>
20 #include <linux/mm.h>
21
22 static int dax_major;
23 static struct class *dax_class;
24 static DEFINE_IDA(dax_minor_ida);
25
26 /**
27  * struct dax_region - mapping infrastructure for dax devices
28  * @id: kernel-wide unique region for a memory range
29  * @base: linear address corresponding to @res
30  * @kref: to pin while other agents have a need to do lookups
31  * @dev: parent device backing this region
32  * @align: allocation and mapping alignment for child dax devices
33  * @res: physical address range of the region
34  * @pfn_flags: identify whether the pfns are paged back or not
35  */
36 struct dax_region {
37         int id;
38         struct ida ida;
39         void *base;
40         struct kref kref;
41         struct device *dev;
42         unsigned int align;
43         struct resource res;
44         unsigned long pfn_flags;
45 };
46
47 /**
48  * struct dax_dev - subdivision of a dax region
49  * @region - parent region
50  * @dev - device backing the character device
51  * @kref - enable this data to be tracked in filp->private_data
52  * @id - child id in the region
53  * @num_resources - number of physical address extents in this device
54  * @res - array of physical address ranges
55  */
56 struct dax_dev {
57         struct dax_region *region;
58         struct device *dev;
59         struct kref kref;
60         int id;
61         int num_resources;
62         struct resource res[0];
63 };
64
65 static void dax_region_free(struct kref *kref)
66 {
67         struct dax_region *dax_region;
68
69         dax_region = container_of(kref, struct dax_region, kref);
70         kfree(dax_region);
71 }
72
73 void dax_region_put(struct dax_region *dax_region)
74 {
75         kref_put(&dax_region->kref, dax_region_free);
76 }
77 EXPORT_SYMBOL_GPL(dax_region_put);
78
79 static void dax_dev_free(struct kref *kref)
80 {
81         struct dax_dev *dax_dev;
82
83         dax_dev = container_of(kref, struct dax_dev, kref);
84         dax_region_put(dax_dev->region);
85         kfree(dax_dev);
86 }
87
88 static void dax_dev_put(struct dax_dev *dax_dev)
89 {
90         kref_put(&dax_dev->kref, dax_dev_free);
91 }
92
93 struct dax_region *alloc_dax_region(struct device *parent, int region_id,
94                 struct resource *res, unsigned int align, void *addr,
95                 unsigned long pfn_flags)
96 {
97         struct dax_region *dax_region;
98
99         dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL);
100
101         if (!dax_region)
102                 return NULL;
103
104         memcpy(&dax_region->res, res, sizeof(*res));
105         dax_region->pfn_flags = pfn_flags;
106         kref_init(&dax_region->kref);
107         dax_region->id = region_id;
108         ida_init(&dax_region->ida);
109         dax_region->align = align;
110         dax_region->dev = parent;
111         dax_region->base = addr;
112
113         return dax_region;
114 }
115 EXPORT_SYMBOL_GPL(alloc_dax_region);
116
117 static ssize_t size_show(struct device *dev,
118                 struct device_attribute *attr, char *buf)
119 {
120         struct dax_dev *dax_dev = dev_get_drvdata(dev);
121         unsigned long long size = 0;
122         int i;
123
124         for (i = 0; i < dax_dev->num_resources; i++)
125                 size += resource_size(&dax_dev->res[i]);
126
127         return sprintf(buf, "%llu\n", size);
128 }
129 static DEVICE_ATTR_RO(size);
130
131 static struct attribute *dax_device_attributes[] = {
132         &dev_attr_size.attr,
133         NULL,
134 };
135
136 static const struct attribute_group dax_device_attribute_group = {
137         .attrs = dax_device_attributes,
138 };
139
140 static const struct attribute_group *dax_attribute_groups[] = {
141         &dax_device_attribute_group,
142         NULL,
143 };
144
145 static void unregister_dax_dev(void *_dev)
146 {
147         struct device *dev = _dev;
148         struct dax_dev *dax_dev = dev_get_drvdata(dev);
149         struct dax_region *dax_region = dax_dev->region;
150
151         dev_dbg(dev, "%s\n", __func__);
152
153         get_device(dev);
154         device_unregister(dev);
155         ida_simple_remove(&dax_region->ida, dax_dev->id);
156         ida_simple_remove(&dax_minor_ida, MINOR(dev->devt));
157         put_device(dev);
158         dax_dev_put(dax_dev);
159 }
160
161 int devm_create_dax_dev(struct dax_region *dax_region, struct resource *res,
162                 int count)
163 {
164         struct device *parent = dax_region->dev;
165         struct dax_dev *dax_dev;
166         struct device *dev;
167         int rc, minor;
168         dev_t dev_t;
169
170         dax_dev = kzalloc(sizeof(*dax_dev) + sizeof(*res) * count, GFP_KERNEL);
171         if (!dax_dev)
172                 return -ENOMEM;
173         memcpy(dax_dev->res, res, sizeof(*res) * count);
174         dax_dev->num_resources = count;
175         kref_init(&dax_dev->kref);
176         dax_dev->region = dax_region;
177         kref_get(&dax_region->kref);
178
179         dax_dev->id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
180         if (dax_dev->id < 0) {
181                 rc = dax_dev->id;
182                 goto err_id;
183         }
184
185         minor = ida_simple_get(&dax_minor_ida, 0, 0, GFP_KERNEL);
186         if (minor < 0) {
187                 rc = minor;
188                 goto err_minor;
189         }
190
191         dev_t = MKDEV(dax_major, minor);
192         dev = device_create_with_groups(dax_class, parent, dev_t, dax_dev,
193                         dax_attribute_groups, "dax%d.%d", dax_region->id,
194                         dax_dev->id);
195         if (IS_ERR(dev)) {
196                 rc = PTR_ERR(dev);
197                 goto err_create;
198         }
199         dax_dev->dev = dev;
200
201         rc = devm_add_action(dax_region->dev, unregister_dax_dev, dev);
202         if (rc) {
203                 unregister_dax_dev(dev);
204                 return rc;
205         }
206
207         return 0;
208
209  err_create:
210         ida_simple_remove(&dax_minor_ida, minor);
211  err_minor:
212         ida_simple_remove(&dax_region->ida, dax_dev->id);
213  err_id:
214         dax_dev_put(dax_dev);
215
216         return rc;
217 }
218 EXPORT_SYMBOL_GPL(devm_create_dax_dev);
219
220 static const struct file_operations dax_fops = {
221         .llseek = noop_llseek,
222         .owner = THIS_MODULE,
223 };
224
225 static int __init dax_init(void)
226 {
227         int rc;
228
229         rc = register_chrdev(0, "dax", &dax_fops);
230         if (rc < 0)
231                 return rc;
232         dax_major = rc;
233
234         dax_class = class_create(THIS_MODULE, "dax");
235         if (IS_ERR(dax_class)) {
236                 unregister_chrdev(dax_major, "dax");
237                 return PTR_ERR(dax_class);
238         }
239
240         return 0;
241 }
242
243 static void __exit dax_exit(void)
244 {
245         class_destroy(dax_class);
246         unregister_chrdev(dax_major, "dax");
247         ida_destroy(&dax_minor_ida);
248 }
249
250 MODULE_AUTHOR("Intel Corporation");
251 MODULE_LICENSE("GPL v2");
252 subsys_initcall(dax_init);
253 module_exit(dax_exit);