diff options
-rw-r--r-- | drivers/dax/dax.c | 94 | ||||
-rw-r--r-- | drivers/dax/pmem.c | 3 | ||||
-rw-r--r-- | drivers/nvdimm/claim.c | 46 | ||||
-rw-r--r-- | drivers/nvdimm/core.c | 29 | ||||
-rw-r--r-- | drivers/nvdimm/dimm.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/dimm_devs.c | 7 | ||||
-rw-r--r-- | drivers/nvdimm/e820.c | 12 | ||||
-rw-r--r-- | drivers/nvdimm/label.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 8 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 12 | ||||
-rw-r--r-- | drivers/nvdimm/pfn_devs.c | 2 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 21 | ||||
-rw-r--r-- | drivers/nvdimm/region_devs.c | 2 | ||||
-rw-r--r-- | tools/testing/nvdimm/test/nfit.c | 30 |
14 files changed, 190 insertions, 80 deletions
diff --git a/drivers/dax/dax.c b/drivers/dax/dax.c index 26ec39ddf21f..ed758b74ddf0 100644 --- a/drivers/dax/dax.c +++ b/drivers/dax/dax.c | |||
@@ -75,6 +75,73 @@ struct dax_dev { | |||
75 | struct resource res[0]; | 75 | struct resource res[0]; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | static ssize_t id_show(struct device *dev, | ||
79 | struct device_attribute *attr, char *buf) | ||
80 | { | ||
81 | struct dax_region *dax_region; | ||
82 | ssize_t rc = -ENXIO; | ||
83 | |||
84 | device_lock(dev); | ||
85 | dax_region = dev_get_drvdata(dev); | ||
86 | if (dax_region) | ||
87 | rc = sprintf(buf, "%d\n", dax_region->id); | ||
88 | device_unlock(dev); | ||
89 | |||
90 | return rc; | ||
91 | } | ||
92 | static DEVICE_ATTR_RO(id); | ||
93 | |||
94 | static ssize_t region_size_show(struct device *dev, | ||
95 | struct device_attribute *attr, char *buf) | ||
96 | { | ||
97 | struct dax_region *dax_region; | ||
98 | ssize_t rc = -ENXIO; | ||
99 | |||
100 | device_lock(dev); | ||
101 | dax_region = dev_get_drvdata(dev); | ||
102 | if (dax_region) | ||
103 | rc = sprintf(buf, "%llu\n", (unsigned long long) | ||
104 | resource_size(&dax_region->res)); | ||
105 | device_unlock(dev); | ||
106 | |||
107 | return rc; | ||
108 | } | ||
109 | static struct device_attribute dev_attr_region_size = __ATTR(size, 0444, | ||
110 | region_size_show, NULL); | ||
111 | |||
112 | static ssize_t align_show(struct device *dev, | ||
113 | struct device_attribute *attr, char *buf) | ||
114 | { | ||
115 | struct dax_region *dax_region; | ||
116 | ssize_t rc = -ENXIO; | ||
117 | |||
118 | device_lock(dev); | ||
119 | dax_region = dev_get_drvdata(dev); | ||
120 | if (dax_region) | ||
121 | rc = sprintf(buf, "%u\n", dax_region->align); | ||
122 | device_unlock(dev); | ||
123 | |||
124 | return rc; | ||
125 | } | ||
126 | static DEVICE_ATTR_RO(align); | ||
127 | |||
128 | static struct attribute *dax_region_attributes[] = { | ||
129 | &dev_attr_region_size.attr, | ||
130 | &dev_attr_align.attr, | ||
131 | &dev_attr_id.attr, | ||
132 | NULL, | ||
133 | }; | ||
134 | |||
135 | static const struct attribute_group dax_region_attribute_group = { | ||
136 | .name = "dax_region", | ||
137 | .attrs = dax_region_attributes, | ||
138 | }; | ||
139 | |||
140 | static const struct attribute_group *dax_region_attribute_groups[] = { | ||
141 | &dax_region_attribute_group, | ||
142 | NULL, | ||
143 | }; | ||
144 | |||
78 | static struct inode *dax_alloc_inode(struct super_block *sb) | 145 | static struct inode *dax_alloc_inode(struct super_block *sb) |
79 | { | 146 | { |
80 | return kmem_cache_alloc(dax_cache, GFP_KERNEL); | 147 | return kmem_cache_alloc(dax_cache, GFP_KERNEL); |
@@ -200,12 +267,31 @@ void dax_region_put(struct dax_region *dax_region) | |||
200 | } | 267 | } |
201 | EXPORT_SYMBOL_GPL(dax_region_put); | 268 | EXPORT_SYMBOL_GPL(dax_region_put); |
202 | 269 | ||
270 | static void dax_region_unregister(void *region) | ||
271 | { | ||
272 | struct dax_region *dax_region = region; | ||
273 | |||
274 | sysfs_remove_groups(&dax_region->dev->kobj, | ||
275 | dax_region_attribute_groups); | ||
276 | dax_region_put(dax_region); | ||
277 | } | ||
278 | |||
203 | struct dax_region *alloc_dax_region(struct device *parent, int region_id, | 279 | struct dax_region *alloc_dax_region(struct device *parent, int region_id, |
204 | struct resource *res, unsigned int align, void *addr, | 280 | struct resource *res, unsigned int align, void *addr, |
205 | unsigned long pfn_flags) | 281 | unsigned long pfn_flags) |
206 | { | 282 | { |
207 | struct dax_region *dax_region; | 283 | struct dax_region *dax_region; |
208 | 284 | ||
285 | /* | ||
286 | * The DAX core assumes that it can store its private data in | ||
287 | * parent->driver_data. This WARN is a reminder / safeguard for | ||
288 | * developers of device-dax drivers. | ||
289 | */ | ||
290 | if (dev_get_drvdata(parent)) { | ||
291 | dev_WARN(parent, "dax core failed to setup private data\n"); | ||
292 | return NULL; | ||
293 | } | ||
294 | |||
209 | if (!IS_ALIGNED(res->start, align) | 295 | if (!IS_ALIGNED(res->start, align) |
210 | || !IS_ALIGNED(resource_size(res), align)) | 296 | || !IS_ALIGNED(resource_size(res), align)) |
211 | return NULL; | 297 | return NULL; |
@@ -214,6 +300,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, | |||
214 | if (!dax_region) | 300 | if (!dax_region) |
215 | return NULL; | 301 | return NULL; |
216 | 302 | ||
303 | dev_set_drvdata(parent, dax_region); | ||
217 | memcpy(&dax_region->res, res, sizeof(*res)); | 304 | memcpy(&dax_region->res, res, sizeof(*res)); |
218 | dax_region->pfn_flags = pfn_flags; | 305 | dax_region->pfn_flags = pfn_flags; |
219 | kref_init(&dax_region->kref); | 306 | kref_init(&dax_region->kref); |
@@ -222,7 +309,14 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id, | |||
222 | dax_region->align = align; | 309 | dax_region->align = align; |
223 | dax_region->dev = parent; | 310 | dax_region->dev = parent; |
224 | dax_region->base = addr; | 311 | dax_region->base = addr; |
312 | if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) { | ||
313 | kfree(dax_region); | ||
314 | return NULL;; | ||
315 | } | ||
225 | 316 | ||
317 | kref_get(&dax_region->kref); | ||
318 | if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region)) | ||
319 | return NULL; | ||
226 | return dax_region; | 320 | return dax_region; |
227 | } | 321 | } |
228 | EXPORT_SYMBOL_GPL(alloc_dax_region); | 322 | EXPORT_SYMBOL_GPL(alloc_dax_region); |
diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c index 73c6ce93a0d9..033f49b31fdc 100644 --- a/drivers/dax/pmem.c +++ b/drivers/dax/pmem.c | |||
@@ -89,7 +89,8 @@ static int dax_pmem_probe(struct device *dev) | |||
89 | pfn_sb = nd_pfn->pfn_sb; | 89 | pfn_sb = nd_pfn->pfn_sb; |
90 | 90 | ||
91 | if (!devm_request_mem_region(dev, nsio->res.start, | 91 | if (!devm_request_mem_region(dev, nsio->res.start, |
92 | resource_size(&nsio->res), dev_name(dev))) { | 92 | resource_size(&nsio->res), |
93 | dev_name(&ndns->dev))) { | ||
93 | dev_warn(dev, "could not reserve region %pR\n", &nsio->res); | 94 | dev_warn(dev, "could not reserve region %pR\n", &nsio->res); |
94 | return -EBUSY; | 95 | return -EBUSY; |
95 | } | 96 | } |
diff --git a/drivers/nvdimm/claim.c b/drivers/nvdimm/claim.c index d5dc80c48b4c..b3323c0697f6 100644 --- a/drivers/nvdimm/claim.c +++ b/drivers/nvdimm/claim.c | |||
@@ -22,9 +22,8 @@ void __nd_detach_ndns(struct device *dev, struct nd_namespace_common **_ndns) | |||
22 | { | 22 | { |
23 | struct nd_namespace_common *ndns = *_ndns; | 23 | struct nd_namespace_common *ndns = *_ndns; |
24 | 24 | ||
25 | dev_WARN_ONCE(dev, !mutex_is_locked(&ndns->dev.mutex) | 25 | lockdep_assert_held(&ndns->dev.mutex); |
26 | || ndns->claim != dev, | 26 | dev_WARN_ONCE(dev, ndns->claim != dev, "%s: invalid claim\n", __func__); |
27 | "%s: invalid claim\n", __func__); | ||
28 | ndns->claim = NULL; | 27 | ndns->claim = NULL; |
29 | *_ndns = NULL; | 28 | *_ndns = NULL; |
30 | put_device(&ndns->dev); | 29 | put_device(&ndns->dev); |
@@ -49,9 +48,8 @@ bool __nd_attach_ndns(struct device *dev, struct nd_namespace_common *attach, | |||
49 | { | 48 | { |
50 | if (attach->claim) | 49 | if (attach->claim) |
51 | return false; | 50 | return false; |
52 | dev_WARN_ONCE(dev, !mutex_is_locked(&attach->dev.mutex) | 51 | lockdep_assert_held(&attach->dev.mutex); |
53 | || *_ndns, | 52 | dev_WARN_ONCE(dev, *_ndns, "%s: invalid claim\n", __func__); |
54 | "%s: invalid claim\n", __func__); | ||
55 | attach->claim = dev; | 53 | attach->claim = dev; |
56 | *_ndns = attach; | 54 | *_ndns = attach; |
57 | get_device(&attach->dev); | 55 | get_device(&attach->dev); |
@@ -226,6 +224,12 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, | |||
226 | resource_size_t offset, void *buf, size_t size, int rw) | 224 | resource_size_t offset, void *buf, size_t size, int rw) |
227 | { | 225 | { |
228 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); | 226 | struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev); |
227 | unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); | ||
228 | sector_t sector = offset >> 9; | ||
229 | int rc = 0; | ||
230 | |||
231 | if (unlikely(!size)) | ||
232 | return 0; | ||
229 | 233 | ||
230 | if (unlikely(offset + size > nsio->size)) { | 234 | if (unlikely(offset + size > nsio->size)) { |
231 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); | 235 | dev_WARN_ONCE(&ndns->dev, 1, "request out of range\n"); |
@@ -233,17 +237,31 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns, | |||
233 | } | 237 | } |
234 | 238 | ||
235 | if (rw == READ) { | 239 | if (rw == READ) { |
236 | unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512); | 240 | if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) |
237 | |||
238 | if (unlikely(is_bad_pmem(&nsio->bb, offset / 512, sz_align))) | ||
239 | return -EIO; | 241 | return -EIO; |
240 | return memcpy_from_pmem(buf, nsio->addr + offset, size); | 242 | return memcpy_from_pmem(buf, nsio->addr + offset, size); |
241 | } else { | ||
242 | memcpy_to_pmem(nsio->addr + offset, buf, size); | ||
243 | nvdimm_flush(to_nd_region(ndns->dev.parent)); | ||
244 | } | 243 | } |
245 | 244 | ||
246 | return 0; | 245 | if (unlikely(is_bad_pmem(&nsio->bb, sector, sz_align))) { |
246 | if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)) { | ||
247 | long cleared; | ||
248 | |||
249 | cleared = nvdimm_clear_poison(&ndns->dev, offset, size); | ||
250 | if (cleared < size) | ||
251 | rc = -EIO; | ||
252 | if (cleared > 0 && cleared / 512) { | ||
253 | cleared /= 512; | ||
254 | badblocks_clear(&nsio->bb, sector, cleared); | ||
255 | } | ||
256 | invalidate_pmem(nsio->addr + offset, size); | ||
257 | } else | ||
258 | rc = -EIO; | ||
259 | } | ||
260 | |||
261 | memcpy_to_pmem(nsio->addr + offset, buf, size); | ||
262 | nvdimm_flush(to_nd_region(ndns->dev.parent)); | ||
263 | |||
264 | return rc; | ||
247 | } | 265 | } |
248 | 266 | ||
249 | int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) | 267 | int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) |
@@ -253,7 +271,7 @@ int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) | |||
253 | 271 | ||
254 | nsio->size = resource_size(res); | 272 | nsio->size = resource_size(res); |
255 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | 273 | if (!devm_request_mem_region(dev, res->start, resource_size(res), |
256 | dev_name(dev))) { | 274 | dev_name(&ndns->dev))) { |
257 | dev_warn(dev, "could not reserve region %pR\n", res); | 275 | dev_warn(dev, "could not reserve region %pR\n", res); |
258 | return -EBUSY; | 276 | return -EBUSY; |
259 | } | 277 | } |
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c index 7ceba08774b6..9303cfeb8bee 100644 --- a/drivers/nvdimm/core.c +++ b/drivers/nvdimm/core.c | |||
@@ -317,35 +317,6 @@ ssize_t nd_sector_size_store(struct device *dev, const char *buf, | |||
317 | } | 317 | } |
318 | } | 318 | } |
319 | 319 | ||
320 | void __nd_iostat_start(struct bio *bio, unsigned long *start) | ||
321 | { | ||
322 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
323 | const int rw = bio_data_dir(bio); | ||
324 | int cpu = part_stat_lock(); | ||
325 | |||
326 | *start = jiffies; | ||
327 | part_round_stats(cpu, &disk->part0); | ||
328 | part_stat_inc(cpu, &disk->part0, ios[rw]); | ||
329 | part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio)); | ||
330 | part_inc_in_flight(&disk->part0, rw); | ||
331 | part_stat_unlock(); | ||
332 | } | ||
333 | EXPORT_SYMBOL(__nd_iostat_start); | ||
334 | |||
335 | void nd_iostat_end(struct bio *bio, unsigned long start) | ||
336 | { | ||
337 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
338 | unsigned long duration = jiffies - start; | ||
339 | const int rw = bio_data_dir(bio); | ||
340 | int cpu = part_stat_lock(); | ||
341 | |||
342 | part_stat_add(cpu, &disk->part0, ticks[rw], duration); | ||
343 | part_round_stats(cpu, &disk->part0); | ||
344 | part_dec_in_flight(&disk->part0, rw); | ||
345 | part_stat_unlock(); | ||
346 | } | ||
347 | EXPORT_SYMBOL(nd_iostat_end); | ||
348 | |||
349 | static ssize_t commands_show(struct device *dev, | 320 | static ssize_t commands_show(struct device *dev, |
350 | struct device_attribute *attr, char *buf) | 321 | struct device_attribute *attr, char *buf) |
351 | { | 322 | { |
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 619834e144d1..ee0b412827bf 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c | |||
@@ -64,6 +64,8 @@ static int nvdimm_probe(struct device *dev) | |||
64 | nd_label_copy(ndd, to_next_namespace_index(ndd), | 64 | nd_label_copy(ndd, to_next_namespace_index(ndd), |
65 | to_current_namespace_index(ndd)); | 65 | to_current_namespace_index(ndd)); |
66 | rc = nd_label_reserve_dpa(ndd); | 66 | rc = nd_label_reserve_dpa(ndd); |
67 | if (ndd->ns_current >= 0) | ||
68 | nvdimm_set_aliasing(dev); | ||
67 | nvdimm_bus_unlock(dev); | 69 | nvdimm_bus_unlock(dev); |
68 | 70 | ||
69 | if (rc) | 71 | if (rc) |
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c index d614493ad5ac..0eedc49e0d47 100644 --- a/drivers/nvdimm/dimm_devs.c +++ b/drivers/nvdimm/dimm_devs.c | |||
@@ -184,6 +184,13 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, | |||
184 | return rc; | 184 | return rc; |
185 | } | 185 | } |
186 | 186 | ||
187 | void nvdimm_set_aliasing(struct device *dev) | ||
188 | { | ||
189 | struct nvdimm *nvdimm = to_nvdimm(dev); | ||
190 | |||
191 | nvdimm->flags |= NDD_ALIASING; | ||
192 | } | ||
193 | |||
187 | static void nvdimm_release(struct device *dev) | 194 | static void nvdimm_release(struct device *dev) |
188 | { | 195 | { |
189 | struct nvdimm *nvdimm = to_nvdimm(dev); | 196 | struct nvdimm *nvdimm = to_nvdimm(dev); |
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c index 11ea90120542..6f9a6ffd7cde 100644 --- a/drivers/nvdimm/e820.c +++ b/drivers/nvdimm/e820.c | |||
@@ -84,18 +84,8 @@ static struct platform_driver e820_pmem_driver = { | |||
84 | }, | 84 | }, |
85 | }; | 85 | }; |
86 | 86 | ||
87 | static __init int e820_pmem_init(void) | 87 | module_platform_driver(e820_pmem_driver); |
88 | { | ||
89 | return platform_driver_register(&e820_pmem_driver); | ||
90 | } | ||
91 | |||
92 | static __exit void e820_pmem_exit(void) | ||
93 | { | ||
94 | platform_driver_unregister(&e820_pmem_driver); | ||
95 | } | ||
96 | 88 | ||
97 | MODULE_ALIAS("platform:e820_pmem*"); | 89 | MODULE_ALIAS("platform:e820_pmem*"); |
98 | MODULE_LICENSE("GPL v2"); | 90 | MODULE_LICENSE("GPL v2"); |
99 | MODULE_AUTHOR("Intel Corporation"); | 91 | MODULE_AUTHOR("Intel Corporation"); |
100 | module_init(e820_pmem_init); | ||
101 | module_exit(e820_pmem_exit); | ||
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index fac7cabe8f56..dd615345699f 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c | |||
@@ -938,7 +938,7 @@ int nd_pmem_namespace_label_update(struct nd_region *nd_region, | |||
938 | } | 938 | } |
939 | 939 | ||
940 | for_each_dpa_resource(ndd, res) | 940 | for_each_dpa_resource(ndd, res) |
941 | if (strncmp(res->name, "pmem", 3) == 0) | 941 | if (strncmp(res->name, "pmem", 4) == 0) |
942 | count++; | 942 | count++; |
943 | WARN_ON_ONCE(!count); | 943 | WARN_ON_ONCE(!count); |
944 | 944 | ||
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index abe5c6bc756c..6307088b375f 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
@@ -1132,7 +1132,7 @@ static ssize_t size_show(struct device *dev, | |||
1132 | return sprintf(buf, "%llu\n", (unsigned long long) | 1132 | return sprintf(buf, "%llu\n", (unsigned long long) |
1133 | nvdimm_namespace_capacity(to_ndns(dev))); | 1133 | nvdimm_namespace_capacity(to_ndns(dev))); |
1134 | } | 1134 | } |
1135 | static DEVICE_ATTR(size, S_IRUGO, size_show, size_store); | 1135 | static DEVICE_ATTR(size, 0444, size_show, size_store); |
1136 | 1136 | ||
1137 | static u8 *namespace_to_uuid(struct device *dev) | 1137 | static u8 *namespace_to_uuid(struct device *dev) |
1138 | { | 1138 | { |
@@ -1456,7 +1456,7 @@ static umode_t namespace_visible(struct kobject *kobj, | |||
1456 | 1456 | ||
1457 | if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { | 1457 | if (is_namespace_pmem(dev) || is_namespace_blk(dev)) { |
1458 | if (a == &dev_attr_size.attr) | 1458 | if (a == &dev_attr_size.attr) |
1459 | return S_IWUSR | S_IRUGO; | 1459 | return 0644; |
1460 | 1460 | ||
1461 | if (is_namespace_pmem(dev) && a == &dev_attr_sector_size.attr) | 1461 | if (is_namespace_pmem(dev) && a == &dev_attr_sector_size.attr) |
1462 | return 0; | 1462 | return 0; |
@@ -1653,7 +1653,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id) | |||
1653 | u64 hw_start, hw_end, pmem_start, pmem_end; | 1653 | u64 hw_start, hw_end, pmem_start, pmem_end; |
1654 | struct nd_label_ent *label_ent; | 1654 | struct nd_label_ent *label_ent; |
1655 | 1655 | ||
1656 | WARN_ON(!mutex_is_locked(&nd_mapping->lock)); | 1656 | lockdep_assert_held(&nd_mapping->lock); |
1657 | list_for_each_entry(label_ent, &nd_mapping->labels, list) { | 1657 | list_for_each_entry(label_ent, &nd_mapping->labels, list) { |
1658 | nd_label = label_ent->label; | 1658 | nd_label = label_ent->label; |
1659 | if (!nd_label) | 1659 | if (!nd_label) |
@@ -1997,7 +1997,7 @@ struct device *create_namespace_blk(struct nd_region *nd_region, | |||
1997 | struct nd_mapping *nd_mapping = &nd_region->mapping[0]; | 1997 | struct nd_mapping *nd_mapping = &nd_region->mapping[0]; |
1998 | struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); | 1998 | struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); |
1999 | struct nd_namespace_blk *nsblk; | 1999 | struct nd_namespace_blk *nsblk; |
2000 | char *name[NSLABEL_NAME_LEN]; | 2000 | char name[NSLABEL_NAME_LEN]; |
2001 | struct device *dev = NULL; | 2001 | struct device *dev = NULL; |
2002 | struct resource *res; | 2002 | struct resource *res; |
2003 | 2003 | ||
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index d3b2fca8deec..35dd75057e16 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h | |||
@@ -238,6 +238,7 @@ int nvdimm_set_config_data(struct nvdimm_drvdata *ndd, size_t offset, | |||
238 | void *buf, size_t len); | 238 | void *buf, size_t len); |
239 | long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, | 239 | long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, |
240 | unsigned int len); | 240 | unsigned int len); |
241 | void nvdimm_set_aliasing(struct device *dev); | ||
241 | struct nd_btt *to_nd_btt(struct device *dev); | 242 | struct nd_btt *to_nd_btt(struct device *dev); |
242 | 243 | ||
243 | struct nd_gen_sb { | 244 | struct nd_gen_sb { |
@@ -377,10 +378,17 @@ static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) | |||
377 | if (!blk_queue_io_stat(disk->queue)) | 378 | if (!blk_queue_io_stat(disk->queue)) |
378 | return false; | 379 | return false; |
379 | 380 | ||
380 | __nd_iostat_start(bio, start); | 381 | *start = jiffies; |
382 | generic_start_io_acct(bio_data_dir(bio), | ||
383 | bio_sectors(bio), &disk->part0); | ||
381 | return true; | 384 | return true; |
382 | } | 385 | } |
383 | void nd_iostat_end(struct bio *bio, unsigned long start); | 386 | static inline void nd_iostat_end(struct bio *bio, unsigned long start) |
387 | { | ||
388 | struct gendisk *disk = bio->bi_bdev->bd_disk; | ||
389 | |||
390 | generic_end_io_acct(bio_data_dir(bio), &disk->part0, start); | ||
391 | } | ||
384 | static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, | 392 | static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, |
385 | unsigned int len) | 393 | unsigned int len) |
386 | { | 394 | { |
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c index cea8350fbc7e..a2ac9e641aa9 100644 --- a/drivers/nvdimm/pfn_devs.c +++ b/drivers/nvdimm/pfn_devs.c | |||
@@ -108,7 +108,7 @@ static ssize_t align_show(struct device *dev, | |||
108 | { | 108 | { |
109 | struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); | 109 | struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev); |
110 | 110 | ||
111 | return sprintf(buf, "%lx\n", nd_pfn->align); | 111 | return sprintf(buf, "%ld\n", nd_pfn->align); |
112 | } | 112 | } |
113 | 113 | ||
114 | static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf) | 114 | static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf) |
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 24618431a14b..7282d7495bf1 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c | |||
@@ -53,21 +53,24 @@ static int pmem_clear_poison(struct pmem_device *pmem, phys_addr_t offset, | |||
53 | struct device *dev = to_dev(pmem); | 53 | struct device *dev = to_dev(pmem); |
54 | sector_t sector; | 54 | sector_t sector; |
55 | long cleared; | 55 | long cleared; |
56 | int rc = 0; | ||
56 | 57 | ||
57 | sector = (offset - pmem->data_offset) / 512; | 58 | sector = (offset - pmem->data_offset) / 512; |
58 | cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len); | ||
59 | 59 | ||
60 | cleared = nvdimm_clear_poison(dev, pmem->phys_addr + offset, len); | ||
61 | if (cleared < len) | ||
62 | rc = -EIO; | ||
60 | if (cleared > 0 && cleared / 512) { | 63 | if (cleared > 0 && cleared / 512) { |
61 | dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", | 64 | cleared /= 512; |
62 | __func__, (unsigned long long) sector, | 65 | dev_dbg(dev, "%s: %#llx clear %ld sector%s\n", __func__, |
63 | cleared / 512, cleared / 512 > 1 ? "s" : ""); | 66 | (unsigned long long) sector, cleared, |
64 | badblocks_clear(&pmem->bb, sector, cleared / 512); | 67 | cleared > 1 ? "s" : ""); |
65 | } else { | 68 | badblocks_clear(&pmem->bb, sector, cleared); |
66 | return -EIO; | ||
67 | } | 69 | } |
68 | 70 | ||
69 | invalidate_pmem(pmem->virt_addr + offset, len); | 71 | invalidate_pmem(pmem->virt_addr + offset, len); |
70 | return 0; | 72 | |
73 | return rc; | ||
71 | } | 74 | } |
72 | 75 | ||
73 | static void write_pmem(void *pmem_addr, struct page *page, | 76 | static void write_pmem(void *pmem_addr, struct page *page, |
@@ -270,7 +273,7 @@ static int pmem_attach_disk(struct device *dev, | |||
270 | dev_warn(dev, "unable to guarantee persistence of writes\n"); | 273 | dev_warn(dev, "unable to guarantee persistence of writes\n"); |
271 | 274 | ||
272 | if (!devm_request_mem_region(dev, res->start, resource_size(res), | 275 | if (!devm_request_mem_region(dev, res->start, resource_size(res), |
273 | dev_name(dev))) { | 276 | dev_name(&ndns->dev))) { |
274 | dev_warn(dev, "could not reserve region %pR\n", res); | 277 | dev_warn(dev, "could not reserve region %pR\n", res); |
275 | return -EBUSY; | 278 | return -EBUSY; |
276 | } | 279 | } |
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 6af5e629140c..7cd705f3247c 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c | |||
@@ -509,7 +509,7 @@ void nd_mapping_free_labels(struct nd_mapping *nd_mapping) | |||
509 | { | 509 | { |
510 | struct nd_label_ent *label_ent, *e; | 510 | struct nd_label_ent *label_ent, *e; |
511 | 511 | ||
512 | WARN_ON(!mutex_is_locked(&nd_mapping->lock)); | 512 | lockdep_assert_held(&nd_mapping->lock); |
513 | list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { | 513 | list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) { |
514 | list_del(&label_ent->list); | 514 | list_del(&label_ent->list); |
515 | kfree(label_ent); | 515 | kfree(label_ent); |
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c index 71620fa95953..45be8b55a663 100644 --- a/tools/testing/nvdimm/test/nfit.c +++ b/tools/testing/nvdimm/test/nfit.c | |||
@@ -125,12 +125,13 @@ struct nfit_test_dcr { | |||
125 | (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \ | 125 | (((node & 0xfff) << 16) | ((socket & 0xf) << 12) \ |
126 | | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf)) | 126 | | ((imc & 0xf) << 8) | ((chan & 0xf) << 4) | (dimm & 0xf)) |
127 | 127 | ||
128 | static u32 handle[NUM_DCR] = { | 128 | static u32 handle[] = { |
129 | [0] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0), | 129 | [0] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 0), |
130 | [1] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1), | 130 | [1] = NFIT_DIMM_HANDLE(0, 0, 0, 0, 1), |
131 | [2] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0), | 131 | [2] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 0), |
132 | [3] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1), | 132 | [3] = NFIT_DIMM_HANDLE(0, 0, 1, 0, 1), |
133 | [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), | 133 | [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), |
134 | [5] = NFIT_DIMM_HANDLE(1, 0, 0, 0, 0), | ||
134 | }; | 135 | }; |
135 | 136 | ||
136 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; | 137 | static unsigned long dimm_fail_cmd_flags[NUM_DCR]; |
@@ -142,6 +143,7 @@ struct nfit_test { | |||
142 | void *nfit_buf; | 143 | void *nfit_buf; |
143 | dma_addr_t nfit_dma; | 144 | dma_addr_t nfit_dma; |
144 | size_t nfit_size; | 145 | size_t nfit_size; |
146 | int dcr_idx; | ||
145 | int num_dcr; | 147 | int num_dcr; |
146 | int num_pm; | 148 | int num_pm; |
147 | void **dimm; | 149 | void **dimm; |
@@ -426,11 +428,11 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc, | |||
426 | break; | 428 | break; |
427 | case ND_CMD_GET_CONFIG_DATA: | 429 | case ND_CMD_GET_CONFIG_DATA: |
428 | rc = nfit_test_cmd_get_config_data(buf, buf_len, | 430 | rc = nfit_test_cmd_get_config_data(buf, buf_len, |
429 | t->label[i]); | 431 | t->label[i - t->dcr_idx]); |
430 | break; | 432 | break; |
431 | case ND_CMD_SET_CONFIG_DATA: | 433 | case ND_CMD_SET_CONFIG_DATA: |
432 | rc = nfit_test_cmd_set_config_data(buf, buf_len, | 434 | rc = nfit_test_cmd_set_config_data(buf, buf_len, |
433 | t->label[i]); | 435 | t->label[i - t->dcr_idx]); |
434 | break; | 436 | break; |
435 | case ND_CMD_SMART: | 437 | case ND_CMD_SMART: |
436 | rc = nfit_test_cmd_smart(buf, buf_len); | 438 | rc = nfit_test_cmd_smart(buf, buf_len); |
@@ -682,7 +684,7 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
682 | if (!t->spa_set[2]) | 684 | if (!t->spa_set[2]) |
683 | return -ENOMEM; | 685 | return -ENOMEM; |
684 | 686 | ||
685 | for (i = 0; i < NUM_DCR; i++) { | 687 | for (i = 0; i < t->num_dcr; i++) { |
686 | t->dimm[i] = test_alloc(t, DIMM_SIZE, &t->dimm_dma[i]); | 688 | t->dimm[i] = test_alloc(t, DIMM_SIZE, &t->dimm_dma[i]); |
687 | if (!t->dimm[i]) | 689 | if (!t->dimm[i]) |
688 | return -ENOMEM; | 690 | return -ENOMEM; |
@@ -699,7 +701,7 @@ static int nfit_test0_alloc(struct nfit_test *t) | |||
699 | return -ENOMEM; | 701 | return -ENOMEM; |
700 | } | 702 | } |
701 | 703 | ||
702 | for (i = 0; i < NUM_DCR; i++) { | 704 | for (i = 0; i < t->num_dcr; i++) { |
703 | t->dcr[i] = test_alloc(t, LABEL_SIZE, &t->dcr_dma[i]); | 705 | t->dcr[i] = test_alloc(t, LABEL_SIZE, &t->dcr_dma[i]); |
704 | if (!t->dcr[i]) | 706 | if (!t->dcr[i]) |
705 | return -ENOMEM; | 707 | return -ENOMEM; |
@@ -728,6 +730,7 @@ static int nfit_test1_alloc(struct nfit_test *t) | |||
728 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 | 730 | size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2 |
729 | + sizeof(struct acpi_nfit_memory_map) | 731 | + sizeof(struct acpi_nfit_memory_map) |
730 | + offsetof(struct acpi_nfit_control_region, window_size); | 732 | + offsetof(struct acpi_nfit_control_region, window_size); |
733 | int i; | ||
731 | 734 | ||
732 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); | 735 | t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); |
733 | if (!t->nfit_buf) | 736 | if (!t->nfit_buf) |
@@ -738,6 +741,13 @@ static int nfit_test1_alloc(struct nfit_test *t) | |||
738 | if (!t->spa_set[0]) | 741 | if (!t->spa_set[0]) |
739 | return -ENOMEM; | 742 | return -ENOMEM; |
740 | 743 | ||
744 | for (i = 0; i < t->num_dcr; i++) { | ||
745 | t->label[i] = test_alloc(t, LABEL_SIZE, &t->label_dma[i]); | ||
746 | if (!t->label[i]) | ||
747 | return -ENOMEM; | ||
748 | sprintf(t->label[i], "label%d", i); | ||
749 | } | ||
750 | |||
741 | t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); | 751 | t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]); |
742 | if (!t->spa_set[1]) | 752 | if (!t->spa_set[1]) |
743 | return -ENOMEM; | 753 | return -ENOMEM; |
@@ -1450,7 +1460,7 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
1450 | memdev = nfit_buf + offset; | 1460 | memdev = nfit_buf + offset; |
1451 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; | 1461 | memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; |
1452 | memdev->header.length = sizeof(*memdev); | 1462 | memdev->header.length = sizeof(*memdev); |
1453 | memdev->device_handle = 0; | 1463 | memdev->device_handle = handle[5]; |
1454 | memdev->physical_id = 0; | 1464 | memdev->physical_id = 0; |
1455 | memdev->region_id = 0; | 1465 | memdev->region_id = 0; |
1456 | memdev->range_index = 0+1; | 1466 | memdev->range_index = 0+1; |
@@ -1472,7 +1482,7 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
1472 | window_size); | 1482 | window_size); |
1473 | dcr->region_index = 0+1; | 1483 | dcr->region_index = 0+1; |
1474 | dcr_common_init(dcr); | 1484 | dcr_common_init(dcr); |
1475 | dcr->serial_number = ~0; | 1485 | dcr->serial_number = ~handle[5]; |
1476 | dcr->code = NFIT_FIC_BYTE; | 1486 | dcr->code = NFIT_FIC_BYTE; |
1477 | dcr->windows = 0; | 1487 | dcr->windows = 0; |
1478 | 1488 | ||
@@ -1483,6 +1493,9 @@ static void nfit_test1_setup(struct nfit_test *t) | |||
1483 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); | 1493 | set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en); |
1484 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); | 1494 | set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en); |
1485 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); | 1495 | set_bit(ND_CMD_CLEAR_ERROR, &acpi_desc->bus_cmd_force_en); |
1496 | set_bit(ND_CMD_GET_CONFIG_SIZE, &acpi_desc->dimm_cmd_force_en); | ||
1497 | set_bit(ND_CMD_GET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); | ||
1498 | set_bit(ND_CMD_SET_CONFIG_DATA, &acpi_desc->dimm_cmd_force_en); | ||
1486 | } | 1499 | } |
1487 | 1500 | ||
1488 | static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, | 1501 | static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, |
@@ -1886,12 +1899,15 @@ static __init int nfit_test_init(void) | |||
1886 | switch (i) { | 1899 | switch (i) { |
1887 | case 0: | 1900 | case 0: |
1888 | nfit_test->num_pm = NUM_PM; | 1901 | nfit_test->num_pm = NUM_PM; |
1902 | nfit_test->dcr_idx = 0; | ||
1889 | nfit_test->num_dcr = NUM_DCR; | 1903 | nfit_test->num_dcr = NUM_DCR; |
1890 | nfit_test->alloc = nfit_test0_alloc; | 1904 | nfit_test->alloc = nfit_test0_alloc; |
1891 | nfit_test->setup = nfit_test0_setup; | 1905 | nfit_test->setup = nfit_test0_setup; |
1892 | break; | 1906 | break; |
1893 | case 1: | 1907 | case 1: |
1894 | nfit_test->num_pm = 1; | 1908 | nfit_test->num_pm = 1; |
1909 | nfit_test->dcr_idx = NUM_DCR; | ||
1910 | nfit_test->num_dcr = 1; | ||
1895 | nfit_test->alloc = nfit_test1_alloc; | 1911 | nfit_test->alloc = nfit_test1_alloc; |
1896 | nfit_test->setup = nfit_test1_setup; | 1912 | nfit_test->setup = nfit_test1_setup; |
1897 | break; | 1913 | break; |