aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-12-18 18:49:10 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-12-18 18:49:10 -0500
commit3be134e5152f08e8bd3c2afdaac723f64d93c2bb (patch)
treeba325ebb1a9f79a4a8451a8f5eaeed9cbd1c2e04
parent8421c60446290c0fef1858a806261871a40ebf76 (diff)
parentc44ef859ceff45db1c72f9ccbfae96843c4b1501 (diff)
Merge tag 'libnvdimm-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm updates from Dan Williams: "The libnvdimm pull request is relatively small this time around due to some development topics being deferred to 4.11. As for this pull request the bulk of it has been in -next for several releases leading to one late fix being added (commit 868f036fee4b ("libnvdimm: fix mishandled nvdimm_clear_poison() return value")). It has received a build success notification from the 0day-kbuild robot and passes the latest libnvdimm unit tests. Summary: - Dynamic label support: To date namespace label support has been limited to disambiguating cases where PMEM (direct load/store) and BLK (mmio aperture) accessed-capacity alias on the same DIMM. Since 4.9 added support for multiple namespaces per PMEM-region there is value to support namespace labels even in the non-aliasing case. The presence of a valid namespace index block force-enables label support when the kernel would otherwise rely on region boundaries, and permits the region to be sub-divided. - Handle media errors in namespace metadata: Complement the error handling for media errors in namespace data areas with support for clearing errors on writes, and downgrading potential machine-check exceptions to simple i/o errors on read. - Device-DAX region attributes: Add 'align', 'id', and 'size' as attributes for device-dax regions. In particular this enables userspace tooling to generically size memory mapping and i/o operations. Prevent userspace from growing assumptions / dependencies about the parent device topology for a dax region. A libnvdimm namespace may not always be the parent device of a dax region. - Various cleanups and small fixes" * tag 'libnvdimm-for-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: dax: add region 'id', 'size', and 'align' attributes libnvdimm: fix mishandled nvdimm_clear_poison() return value libnvdimm: replace mutex_is_locked() warnings with lockdep_assert_held libnvdimm, pfn: fix align attribute libnvdimm, e820: use module_platform_driver libnvdimm, namespace: use octal for permissions libnvdimm, namespace: avoid multiple sector calculations libnvdimm: remove else after return in nsio_rw_bytes() libnvdimm, namespace: fix the type of name variable libnvdimm: use consistent naming for request_mem_region() nvdimm: use the right length of "pmem" libnvdimm: check and clear poison before writing to pmem tools/testing/nvdimm: dynamic label support libnvdimm: allow a platform to force enable label support libnvdimm: use generic iostat interfaces
-rw-r--r--drivers/dax/dax.c94
-rw-r--r--drivers/dax/pmem.c3
-rw-r--r--drivers/nvdimm/claim.c46
-rw-r--r--drivers/nvdimm/core.c29
-rw-r--r--drivers/nvdimm/dimm.c2
-rw-r--r--drivers/nvdimm/dimm_devs.c7
-rw-r--r--drivers/nvdimm/e820.c12
-rw-r--r--drivers/nvdimm/label.c2
-rw-r--r--drivers/nvdimm/namespace_devs.c8
-rw-r--r--drivers/nvdimm/nd.h12
-rw-r--r--drivers/nvdimm/pfn_devs.c2
-rw-r--r--drivers/nvdimm/pmem.c21
-rw-r--r--drivers/nvdimm/region_devs.c2
-rw-r--r--tools/testing/nvdimm/test/nfit.c30
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
78static 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}
92static DEVICE_ATTR_RO(id);
93
94static 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}
109static struct device_attribute dev_attr_region_size = __ATTR(size, 0444,
110 region_size_show, NULL);
111
112static 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}
126static DEVICE_ATTR_RO(align);
127
128static 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
135static const struct attribute_group dax_region_attribute_group = {
136 .name = "dax_region",
137 .attrs = dax_region_attributes,
138};
139
140static const struct attribute_group *dax_region_attribute_groups[] = {
141 &dax_region_attribute_group,
142 NULL,
143};
144
78static struct inode *dax_alloc_inode(struct super_block *sb) 145static 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}
201EXPORT_SYMBOL_GPL(dax_region_put); 268EXPORT_SYMBOL_GPL(dax_region_put);
202 269
270static 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
203struct dax_region *alloc_dax_region(struct device *parent, int region_id, 279struct 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}
228EXPORT_SYMBOL_GPL(alloc_dax_region); 322EXPORT_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
249int devm_nsio_enable(struct device *dev, struct nd_namespace_io *nsio) 267int 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
320void __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}
333EXPORT_SYMBOL(__nd_iostat_start);
334
335void 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}
347EXPORT_SYMBOL(nd_iostat_end);
348
349static ssize_t commands_show(struct device *dev, 320static 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
187void nvdimm_set_aliasing(struct device *dev)
188{
189 struct nvdimm *nvdimm = to_nvdimm(dev);
190
191 nvdimm->flags |= NDD_ALIASING;
192}
193
187static void nvdimm_release(struct device *dev) 194static 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
87static __init int e820_pmem_init(void) 87module_platform_driver(e820_pmem_driver);
88{
89 return platform_driver_register(&e820_pmem_driver);
90}
91
92static __exit void e820_pmem_exit(void)
93{
94 platform_driver_unregister(&e820_pmem_driver);
95}
96 88
97MODULE_ALIAS("platform:e820_pmem*"); 89MODULE_ALIAS("platform:e820_pmem*");
98MODULE_LICENSE("GPL v2"); 90MODULE_LICENSE("GPL v2");
99MODULE_AUTHOR("Intel Corporation"); 91MODULE_AUTHOR("Intel Corporation");
100module_init(e820_pmem_init);
101module_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}
1135static DEVICE_ATTR(size, S_IRUGO, size_show, size_store); 1135static DEVICE_ATTR(size, 0444, size_show, size_store);
1136 1136
1137static u8 *namespace_to_uuid(struct device *dev) 1137static 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);
239long nvdimm_clear_poison(struct device *dev, phys_addr_t phys, 239long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
240 unsigned int len); 240 unsigned int len);
241void nvdimm_set_aliasing(struct device *dev);
241struct nd_btt *to_nd_btt(struct device *dev); 242struct nd_btt *to_nd_btt(struct device *dev);
242 243
243struct nd_gen_sb { 244struct 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}
383void nd_iostat_end(struct bio *bio, unsigned long start); 386static 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}
384static inline bool is_bad_pmem(struct badblocks *bb, sector_t sector, 392static 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
114static ssize_t __align_store(struct nd_pfn *nd_pfn, const char *buf) 114static 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
73static void write_pmem(void *pmem_addr, struct page *page, 76static 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
128static u32 handle[NUM_DCR] = { 128static 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
136static unsigned long dimm_fail_cmd_flags[NUM_DCR]; 137static 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
1488static int nfit_test_blk_do_io(struct nd_blk_region *ndbr, resource_size_t dpa, 1501static 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;