aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/pfn_devs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/nvdimm/pfn_devs.c')
-rw-r--r--drivers/nvdimm/pfn_devs.c100
1 files changed, 67 insertions, 33 deletions
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index e8693fe65e49..6ade2eb7615d 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright(c) 2013-2015 Intel Corporation. All rights reserved. 2 * Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify 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 5 * it under the terms of version 2 of the GNU General Public License as
@@ -54,10 +54,29 @@ struct nd_pfn *to_nd_pfn(struct device *dev)
54} 54}
55EXPORT_SYMBOL(to_nd_pfn); 55EXPORT_SYMBOL(to_nd_pfn);
56 56
57static struct nd_pfn *to_nd_pfn_safe(struct device *dev)
58{
59 /*
60 * pfn device attributes are re-used by dax device instances, so we
61 * need to be careful to correct device-to-nd_pfn conversion.
62 */
63 if (is_nd_pfn(dev))
64 return to_nd_pfn(dev);
65
66 if (is_nd_dax(dev)) {
67 struct nd_dax *nd_dax = to_nd_dax(dev);
68
69 return &nd_dax->nd_pfn;
70 }
71
72 WARN_ON(1);
73 return NULL;
74}
75
57static ssize_t mode_show(struct device *dev, 76static ssize_t mode_show(struct device *dev,
58 struct device_attribute *attr, char *buf) 77 struct device_attribute *attr, char *buf)
59{ 78{
60 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 79 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
61 80
62 switch (nd_pfn->mode) { 81 switch (nd_pfn->mode) {
63 case PFN_MODE_RAM: 82 case PFN_MODE_RAM:
@@ -72,7 +91,7 @@ static ssize_t mode_show(struct device *dev,
72static ssize_t mode_store(struct device *dev, 91static ssize_t mode_store(struct device *dev,
73 struct device_attribute *attr, const char *buf, size_t len) 92 struct device_attribute *attr, const char *buf, size_t len)
74{ 93{
75 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 94 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
76 ssize_t rc = 0; 95 ssize_t rc = 0;
77 96
78 device_lock(dev); 97 device_lock(dev);
@@ -106,7 +125,7 @@ static DEVICE_ATTR_RW(mode);
106static ssize_t align_show(struct device *dev, 125static ssize_t align_show(struct device *dev,
107 struct device_attribute *attr, char *buf) 126 struct device_attribute *attr, char *buf)
108{ 127{
109 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 128 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
110 129
111 return sprintf(buf, "%lx\n", nd_pfn->align); 130 return sprintf(buf, "%lx\n", nd_pfn->align);
112} 131}
@@ -134,7 +153,7 @@ static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf)
134static ssize_t align_store(struct device *dev, 153static ssize_t align_store(struct device *dev,
135 struct device_attribute *attr, const char *buf, size_t len) 154 struct device_attribute *attr, const char *buf, size_t len)
136{ 155{
137 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 156 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
138 ssize_t rc; 157 ssize_t rc;
139 158
140 device_lock(dev); 159 device_lock(dev);
@@ -152,7 +171,7 @@ static DEVICE_ATTR_RW(align);
152static ssize_t uuid_show(struct device *dev, 171static ssize_t uuid_show(struct device *dev,
153 struct device_attribute *attr, char *buf) 172 struct device_attribute *attr, char *buf)
154{ 173{
155 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 174 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
156 175
157 if (nd_pfn->uuid) 176 if (nd_pfn->uuid)
158 return sprintf(buf, "%pUb\n", nd_pfn->uuid); 177 return sprintf(buf, "%pUb\n", nd_pfn->uuid);
@@ -162,7 +181,7 @@ static ssize_t uuid_show(struct device *dev,
162static ssize_t uuid_store(struct device *dev, 181static ssize_t uuid_store(struct device *dev,
163 struct device_attribute *attr, const char *buf, size_t len) 182 struct device_attribute *attr, const char *buf, size_t len)
164{ 183{
165 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 184 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
166 ssize_t rc; 185 ssize_t rc;
167 186
168 device_lock(dev); 187 device_lock(dev);
@@ -178,7 +197,7 @@ static DEVICE_ATTR_RW(uuid);
178static ssize_t namespace_show(struct device *dev, 197static ssize_t namespace_show(struct device *dev,
179 struct device_attribute *attr, char *buf) 198 struct device_attribute *attr, char *buf)
180{ 199{
181 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 200 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
182 ssize_t rc; 201 ssize_t rc;
183 202
184 nvdimm_bus_lock(dev); 203 nvdimm_bus_lock(dev);
@@ -191,7 +210,7 @@ static ssize_t namespace_show(struct device *dev,
191static ssize_t namespace_store(struct device *dev, 210static ssize_t namespace_store(struct device *dev,
192 struct device_attribute *attr, const char *buf, size_t len) 211 struct device_attribute *attr, const char *buf, size_t len)
193{ 212{
194 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 213 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
195 ssize_t rc; 214 ssize_t rc;
196 215
197 device_lock(dev); 216 device_lock(dev);
@@ -209,7 +228,7 @@ static DEVICE_ATTR_RW(namespace);
209static ssize_t resource_show(struct device *dev, 228static ssize_t resource_show(struct device *dev,
210 struct device_attribute *attr, char *buf) 229 struct device_attribute *attr, char *buf)
211{ 230{
212 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 231 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
213 ssize_t rc; 232 ssize_t rc;
214 233
215 device_lock(dev); 234 device_lock(dev);
@@ -235,7 +254,7 @@ static DEVICE_ATTR_RO(resource);
235static ssize_t size_show(struct device *dev, 254static ssize_t size_show(struct device *dev,
236 struct device_attribute *attr, char *buf) 255 struct device_attribute *attr, char *buf)
237{ 256{
238 struct nd_pfn *nd_pfn = to_nd_pfn(dev); 257 struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
239 ssize_t rc; 258 ssize_t rc;
240 259
241 device_lock(dev); 260 device_lock(dev);
@@ -270,7 +289,7 @@ static struct attribute *nd_pfn_attributes[] = {
270 NULL, 289 NULL,
271}; 290};
272 291
273static struct attribute_group nd_pfn_attribute_group = { 292struct attribute_group nd_pfn_attribute_group = {
274 .attrs = nd_pfn_attributes, 293 .attrs = nd_pfn_attributes,
275}; 294};
276 295
@@ -281,15 +300,31 @@ static const struct attribute_group *nd_pfn_attribute_groups[] = {
281 NULL, 300 NULL,
282}; 301};
283 302
284static struct device *__nd_pfn_create(struct nd_region *nd_region, 303struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
285 struct nd_namespace_common *ndns) 304 struct nd_namespace_common *ndns)
286{ 305{
287 struct nd_pfn *nd_pfn; 306 struct device *dev = &nd_pfn->dev;
288 struct device *dev;
289 307
290 /* we can only create pages for contiguous ranged of pmem */ 308 if (!nd_pfn)
291 if (!is_nd_pmem(&nd_region->dev)) 309 return NULL;
310
311 nd_pfn->mode = PFN_MODE_NONE;
312 nd_pfn->align = HPAGE_SIZE;
313 dev = &nd_pfn->dev;
314 device_initialize(&nd_pfn->dev);
315 if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
316 dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n",
317 __func__, dev_name(ndns->claim));
318 put_device(dev);
292 return NULL; 319 return NULL;
320 }
321 return dev;
322}
323
324static struct nd_pfn *nd_pfn_alloc(struct nd_region *nd_region)
325{
326 struct nd_pfn *nd_pfn;
327 struct device *dev;
293 328
294 nd_pfn = kzalloc(sizeof(*nd_pfn), GFP_KERNEL); 329 nd_pfn = kzalloc(sizeof(*nd_pfn), GFP_KERNEL);
295 if (!nd_pfn) 330 if (!nd_pfn)
@@ -301,29 +336,27 @@ static struct device *__nd_pfn_create(struct nd_region *nd_region,
301 return NULL; 336 return NULL;
302 } 337 }
303 338
304 nd_pfn->mode = PFN_MODE_NONE;
305 nd_pfn->align = HPAGE_SIZE;
306 dev = &nd_pfn->dev; 339 dev = &nd_pfn->dev;
307 dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id); 340 dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
308 dev->parent = &nd_region->dev;
309 dev->type = &nd_pfn_device_type;
310 dev->groups = nd_pfn_attribute_groups; 341 dev->groups = nd_pfn_attribute_groups;
311 device_initialize(&nd_pfn->dev); 342 dev->type = &nd_pfn_device_type;
312 if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) { 343 dev->parent = &nd_region->dev;
313 dev_dbg(&ndns->dev, "%s failed, already claimed by %s\n", 344
314 __func__, dev_name(ndns->claim)); 345 return nd_pfn;
315 put_device(dev);
316 return NULL;
317 }
318 return dev;
319} 346}
320 347
321struct device *nd_pfn_create(struct nd_region *nd_region) 348struct device *nd_pfn_create(struct nd_region *nd_region)
322{ 349{
323 struct device *dev = __nd_pfn_create(nd_region, NULL); 350 struct nd_pfn *nd_pfn;
351 struct device *dev;
352
353 if (!is_nd_pmem(&nd_region->dev))
354 return NULL;
355
356 nd_pfn = nd_pfn_alloc(nd_region);
357 dev = nd_pfn_devinit(nd_pfn, NULL);
324 358
325 if (dev) 359 __nd_device_register(dev);
326 __nd_device_register(dev);
327 return dev; 360 return dev;
328} 361}
329 362
@@ -423,7 +456,8 @@ int nd_pfn_probe(struct device *dev, struct nd_namespace_common *ndns)
423 return -ENODEV; 456 return -ENODEV;
424 457
425 nvdimm_bus_lock(&ndns->dev); 458 nvdimm_bus_lock(&ndns->dev);
426 pfn_dev = __nd_pfn_create(nd_region, ndns); 459 nd_pfn = nd_pfn_alloc(nd_region);
460 pfn_dev = nd_pfn_devinit(nd_pfn, ndns);
427 nvdimm_bus_unlock(&ndns->dev); 461 nvdimm_bus_unlock(&ndns->dev);
428 if (!pfn_dev) 462 if (!pfn_dev)
429 return -ENOMEM; 463 return -ENOMEM;