]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/nvdimm/namespace_devs.c
libnvdimm, pmem: move pmem to drivers/nvdimm/
[karo-tx-linux.git] / drivers / nvdimm / namespace_devs.c
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 #include <linux/module.h>
14 #include <linux/device.h>
15 #include <linux/slab.h>
16 #include <linux/nd.h>
17 #include "nd.h"
18
19 static void namespace_io_release(struct device *dev)
20 {
21         struct nd_namespace_io *nsio = to_nd_namespace_io(dev);
22
23         kfree(nsio);
24 }
25
26 static struct device_type namespace_io_device_type = {
27         .name = "nd_namespace_io",
28         .release = namespace_io_release,
29 };
30
31 static ssize_t nstype_show(struct device *dev,
32                 struct device_attribute *attr, char *buf)
33 {
34         struct nd_region *nd_region = to_nd_region(dev->parent);
35
36         return sprintf(buf, "%d\n", nd_region_to_nstype(nd_region));
37 }
38 static DEVICE_ATTR_RO(nstype);
39
40 static struct attribute *nd_namespace_attributes[] = {
41         &dev_attr_nstype.attr,
42         NULL,
43 };
44
45 static struct attribute_group nd_namespace_attribute_group = {
46         .attrs = nd_namespace_attributes,
47 };
48
49 static const struct attribute_group *nd_namespace_attribute_groups[] = {
50         &nd_device_attribute_group,
51         &nd_namespace_attribute_group,
52         NULL,
53 };
54
55 static struct device **create_namespace_io(struct nd_region *nd_region)
56 {
57         struct nd_namespace_io *nsio;
58         struct device *dev, **devs;
59         struct resource *res;
60
61         nsio = kzalloc(sizeof(*nsio), GFP_KERNEL);
62         if (!nsio)
63                 return NULL;
64
65         devs = kcalloc(2, sizeof(struct device *), GFP_KERNEL);
66         if (!devs) {
67                 kfree(nsio);
68                 return NULL;
69         }
70
71         dev = &nsio->dev;
72         dev->type = &namespace_io_device_type;
73         dev->parent = &nd_region->dev;
74         res = &nsio->res;
75         res->name = dev_name(&nd_region->dev);
76         res->flags = IORESOURCE_MEM;
77         res->start = nd_region->ndr_start;
78         res->end = res->start + nd_region->ndr_size - 1;
79
80         devs[0] = dev;
81         return devs;
82 }
83
84 int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
85 {
86         struct device **devs = NULL;
87         int i;
88
89         *err = 0;
90         switch (nd_region_to_nstype(nd_region)) {
91         case ND_DEVICE_NAMESPACE_IO:
92                 devs = create_namespace_io(nd_region);
93                 break;
94         default:
95                 break;
96         }
97
98         if (!devs)
99                 return -ENODEV;
100
101         for (i = 0; devs[i]; i++) {
102                 struct device *dev = devs[i];
103
104                 dev_set_name(dev, "namespace%d.%d", nd_region->id, i);
105                 dev->groups = nd_namespace_attribute_groups;
106                 nd_device_register(dev);
107         }
108         kfree(devs);
109
110         return i;
111 }