blob: 3cf50274fadb023b485fa613954b5b51af83240f [file] [log] [blame]
Dan Williams4d88a972015-05-31 14:41:48 -04001/*
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>
Dan Williams4a826c82015-06-09 16:09:36 -040021#include "label.h"
Dan Williams4d88a972015-05-31 14:41:48 -040022#include "nd.h"
23
Dan Williams4d88a972015-05-31 14:41:48 -040024static int nvdimm_probe(struct device *dev)
25{
26 struct nvdimm_drvdata *ndd;
27 int rc;
28
Dan Williams1cd73862019-01-19 08:45:56 -080029 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
Toshi Kaniaee65982016-08-16 13:08:40 -060035 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
Dave Jiang4c6926a2018-12-06 12:40:01 -080043 /*
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 */
Dan Williams08e6b3c2018-06-13 09:08:36 -070048 nvdimm_clear_locked(dev);
49
Dan Williams4d88a972015-05-31 14:41:48 -040050 ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
51 if (!ndd)
52 return -ENOMEM;
53
54 dev_set_drvdata(dev, ndd);
Dan Williams4a826c82015-06-09 16:09:36 -040055 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;
Dan Williams4d88a972015-05-31 14:41:48 -040060 ndd->dev = dev;
Dan Williamsbf9bccc2015-06-17 17:14:46 -040061 get_device(dev);
62 kref_init(&ndd->kref);
Dan Williams4d88a972015-05-31 14:41:48 -040063
Dan Williams08e6b3c2018-06-13 09:08:36 -070064 /*
Dave Jiang4c6926a2018-12-06 12:40:01 -080065 * 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)
Dan Williams37379cf2018-12-22 11:35:41 -080071 dev_dbg(dev, "failed to unlock dimm: %d\n", rc);
Dave Jiang4c6926a2018-12-06 12:40:01 -080072
73
74 /*
Dan Williams08e6b3c2018-06-13 09:08:36 -070075 * 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 */
Dan Williams4d88a972015-05-31 14:41:48 -040079 rc = nvdimm_init_nsarea(ndd);
Dan Williams08e6b3c2018-06-13 09:08:36 -070080 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 */
Dan Williams9d62ed92017-05-04 11:47:22 -070086 nvdimm_set_locked(dev);
Dan Williams08e6b3c2018-06-13 09:08:36 -070087 rc = 0;
88 }
Dan Williams4d88a972015-05-31 14:41:48 -040089 if (rc)
90 goto err;
91
Dan Williams08e6b3c2018-06-13 09:08:36 -070092 /*
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 */
Alexander Duyck2d657d12018-10-10 16:39:20 -070098 rc = nd_label_data_init(ndd);
Dan Williams4b27db72017-09-24 09:57:34 -070099 if (rc == -EACCES)
100 nvdimm_set_locked(dev);
Dan Williams4d88a972015-05-31 14:41:48 -0400101 if (rc)
102 goto err;
103
104 dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size);
105
Dan Williams4a826c82015-06-09 16:09:36 -0400106 nvdimm_bus_lock(dev);
Dan Williamsc31898c2018-04-06 11:25:38 -0700107 if (ndd->ns_current >= 0) {
108 rc = nd_label_reserve_dpa(ndd);
109 if (rc == 0)
110 nvdimm_set_aliasing(dev);
111 }
Dan Williams4a826c82015-06-09 16:09:36 -0400112 nvdimm_bus_unlock(dev);
113
114 if (rc)
115 goto err;
116
Dan Williams4d88a972015-05-31 14:41:48 -0400117 return 0;
118
119 err:
Dan Williamsbf9bccc2015-06-17 17:14:46 -0400120 put_ndd(ndd);
Dan Williams4d88a972015-05-31 14:41:48 -0400121 return rc;
122}
123
124static int nvdimm_remove(struct device *dev)
125{
126 struct nvdimm_drvdata *ndd = dev_get_drvdata(dev);
127
Toshi Kaniaee65982016-08-16 13:08:40 -0600128 if (!ndd)
129 return 0;
130
Dan Williams4a826c82015-06-09 16:09:36 -0400131 nvdimm_bus_lock(dev);
132 dev_set_drvdata(dev, NULL);
Dan Williams4a826c82015-06-09 16:09:36 -0400133 nvdimm_bus_unlock(dev);
Dan Williamsbf9bccc2015-06-17 17:14:46 -0400134 put_ndd(ndd);
Dan Williams4d88a972015-05-31 14:41:48 -0400135
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
Dan Williams3d880022015-05-31 15:02:11 -0400153void nvdimm_exit(void)
Dan Williams4d88a972015-05-31 14:41:48 -0400154{
155 driver_unregister(&nvdimm_driver.drv);
156}
157
158MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DIMM);