]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - drivers/nvdimm/namespace_devs.c
libnvdimm: support for legacy (non-aliasing) nvdimms
[mirror_ubuntu-zesty-kernel.git] / drivers / nvdimm / namespace_devs.c
CommitLineData
3d88002e
DW
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
19static 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
26static struct device_type namespace_io_device_type = {
27 .name = "nd_namespace_io",
28 .release = namespace_io_release,
29};
30
31static 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}
38static DEVICE_ATTR_RO(nstype);
39
40static struct attribute *nd_namespace_attributes[] = {
41 &dev_attr_nstype.attr,
42 NULL,
43};
44
45static struct attribute_group nd_namespace_attribute_group = {
46 .attrs = nd_namespace_attributes,
47};
48
49static const struct attribute_group *nd_namespace_attribute_groups[] = {
50 &nd_device_attribute_group,
51 &nd_namespace_attribute_group,
52 NULL,
53};
54
55static 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
84int 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}