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/vmalloc.h>
14#include <linux/module.h>
15#include <linux/device.h>
16#include <linux/sizes.h>
17#include <linux/ndctl.h>
18#include <linux/slab.h>
19#include <linux/mm.h>
20#include <linux/nd.h>
21#include "label.h"
22#include "nd.h"
23
24static int nvdimm_probe(struct device *dev)
25{
26 struct nvdimm_drvdata *ndd;
27 int rc;
28
29 rc = nvdimm_security_setup_events(dev);
30 if (rc < 0) {
31 dev_err(dev, "security event setup failed: %d\n", rc);
32 return rc;
33 }
34
35 rc = nvdimm_check_config_data(dev);
36 if (rc) {
37 /* not required for non-aliased nvdimm, ex. NVDIMM-N */
38 if (rc == -ENOTTY)
39 rc = 0;
40 return rc;
41 }
42
43 /*
44 * The locked status bit reflects explicit status codes from the
45 * label reading commands, revalidate it each time the driver is
46 * activated and re-reads the label area.
47 */
48 nvdimm_clear_locked(dev);
49
50 ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
51 if (!ndd)
52 return -ENOMEM;
53
54 dev_set_drvdata(dev, ndd);
55 ndd->dpa.name = dev_name(dev);
56 ndd->ns_current = -1;
57 ndd->ns_next = -1;
58 ndd->dpa.start = 0;
59 ndd->dpa.end = -1;
60 ndd->dev = dev;
61 get_device(dev);
62 kref_init(&ndd->kref);
63
64 /*
65 * Attempt to unlock, if the DIMM supports security commands,
66 * otherwise the locked indication is determined by explicit
67 * status codes from the label reading commands.
68 */
69 rc = nvdimm_security_unlock(dev);
70 if (rc < 0)
71 dev_dbg(dev, "failed to unlock dimm: %d\n", rc);
72
73
74 /*
75 * EACCES failures reading the namespace label-area-properties
76 * are interpreted as the DIMM capacity being locked but the
77 * namespace labels themselves being accessible.
78 */
79 rc = nvdimm_init_nsarea(ndd);
80 if (rc == -EACCES) {
81 /*
82 * See nvdimm_namespace_common_probe() where we fail to
83 * allow namespaces to probe while the DIMM is locked,
84 * but we do allow for namespace enumeration.
85 */
86 nvdimm_set_locked(dev);
87 rc = 0;
88 }
89 if (rc)
90 goto err;
91
92 /*
93 * EACCES failures reading the namespace label-data are
94 * interpreted as the label area being locked in addition to the
95 * DIMM capacity. We fail the dimm probe to prevent regions from
96 * attempting to parse the label area.
97 */
98 rc = nd_label_data_init(ndd);
99 if (rc == -EACCES)
100 nvdimm_set_locked(dev);
101 if (rc)
102 goto err;
103
104 dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
105
106 nvdimm_bus_lock(dev);
107 if (ndd->ns_current >= 0) {
108 rc = nd_label_reserve_dpa(ndd);
109 if (rc == 0)
110 nvdimm_set_aliasing(dev);
111 }
112 nvdimm_bus_unlock(dev);
113
114 if (rc)
115 goto err;
116
117 return 0;
118
119 err:
120 put_ndd(ndd);
121 return rc;
122}
123
124static int nvdimm_remove(struct device *dev)
125{
126 struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
127
128 if (!ndd)
129 return 0;
130
131 nvdimm_bus_lock(dev);
132 dev_set_drvdata(dev, NULL);
133 nvdimm_bus_unlock(dev);
134 put_ndd(ndd);
135
136 return 0;
137}
138
139static struct nd_device_driver nvdimm_driver = {
140 .probe = nvdimm_probe,
141 .remove = nvdimm_remove,
142 .drv = {
143 .name = "nvdimm",
144 },
145 .type = ND_DRIVER_DIMM,
146};
147
148int __init nvdimm_init(void)
149{
150 return nd_driver_register(&nvdimm_driver);
151}
152
153void nvdimm_exit(void)
154{
155 driver_unregister(&nvdimm_driver.drv);
156}
157
158MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DIMM);
159