aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-04-07 23:02:06 -0400
committerDan Williams <dan.j.williams@intel.com>2016-04-07 23:02:06 -0400
commita390180291dd9a2392bbab4242cde712c326efc6 (patch)
tree4faabbfd699f88c03cacbbed681c4aba66a080e6 /drivers/nvdimm
parente5670563f588ed1c0603819350c0f02cec23f5c5 (diff)
libnvdimm, pfn: fix nvdimm_namespace_add_poison() vs section alignment
When section alignment padding is in effect we need to shift / truncate the range that is queried for poison by the 'start_pad' or 'end_trunc' reservations. It's easiest if we just pass in an adjusted resource range rather than deriving it from the passed in namespace. With the resource range resolution pushed out to the caller we can also push the namespace-to-region lookup to the caller and drop the implicit pmem-type assumption about the passed in namespace object. Cc: Vishal Verma <vishal.l.verma@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r--drivers/nvdimm/core.c41
-rw-r--r--drivers/nvdimm/nd.h4
-rw-r--r--drivers/nvdimm/pmem.c36
3 files changed, 51 insertions, 30 deletions
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 79646d0c3277..182a93fe3712 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -417,8 +417,8 @@ static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len)
417 set_badblock(bb, start_sector, num_sectors); 417 set_badblock(bb, start_sector, num_sectors);
418} 418}
419 419
420static void namespace_add_poison(struct list_head *poison_list, 420static void badblocks_populate(struct list_head *poison_list,
421 struct badblocks *bb, struct resource *res) 421 struct badblocks *bb, const struct resource *res)
422{ 422{
423 struct nd_poison *pl; 423 struct nd_poison *pl;
424 424
@@ -460,36 +460,35 @@ static void namespace_add_poison(struct list_head *poison_list,
460} 460}
461 461
462/** 462/**
463 * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks 463 * nvdimm_badblocks_populate() - Convert a list of poison ranges to badblocks
464 * @ndns: the namespace containing poison ranges 464 * @region: parent region of the range to interrogate
465 * @bb: badblocks instance to populate 465 * @bb: badblocks instance to populate
466 * @offset: offset at the start of the namespace before 'sector 0' 466 * @res: resource range to consider
467 * 467 *
468 * The poison list generated during NFIT initialization may contain multiple, 468 * The poison list generated during bus initialization may contain
469 * possibly overlapping ranges in the SPA (System Physical Address) space. 469 * multiple, possibly overlapping physical address ranges. Compare each
470 * Compare each of these ranges to the namespace currently being initialized, 470 * of these ranges to the resource range currently being initialized,
471 * and add badblocks to the gendisk for all matching sub-ranges 471 * and add badblocks entries for all matching sub-ranges
472 */ 472 */
473void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, 473void nvdimm_badblocks_populate(struct nd_region *nd_region,
474 struct badblocks *bb, resource_size_t offset) 474 struct badblocks *bb, const struct resource *res)
475{ 475{
476 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
477 struct nd_region *nd_region = to_nd_region(ndns->dev.parent);
478 struct nvdimm_bus *nvdimm_bus; 476 struct nvdimm_bus *nvdimm_bus;
479 struct list_head *poison_list; 477 struct list_head *poison_list;
480 struct resource res = {
481 .start = nsio->res.start + offset,
482 .end = nsio->res.end,
483 };
484 478
485 nvdimm_bus = to_nvdimm_bus(nd_region->dev.parent); 479 if (!is_nd_pmem(&nd_region->dev)) {
480 dev_WARN_ONCE(&nd_region->dev, 1,
481 "%s only valid for pmem regions\n", __func__);
482 return;
483 }
484 nvdimm_bus = walk_to_nvdimm_bus(&nd_region->dev);
486 poison_list = &nvdimm_bus->poison_list; 485 poison_list = &nvdimm_bus->poison_list;
487 486
488 nvdimm_bus_lock(&nvdimm_bus->dev); 487 nvdimm_bus_lock(&nvdimm_bus->dev);
489 namespace_add_poison(poison_list, bb, &res); 488 badblocks_populate(poison_list, bb, res);
490 nvdimm_bus_unlock(&nvdimm_bus->dev); 489 nvdimm_bus_unlock(&nvdimm_bus->dev);
491} 490}
492EXPORT_SYMBOL_GPL(nvdimm_namespace_add_poison); 491EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate);
493 492
494static int add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) 493static int add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length)
495{ 494{
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 1799bd97a9ce..875c524fafb0 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -266,8 +266,8 @@ int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns);
266int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); 266int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns);
267const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, 267const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns,
268 char *name); 268 char *name);
269void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, 269void nvdimm_badblocks_populate(struct nd_region *nd_region,
270 struct badblocks *bb, resource_size_t offset); 270 struct badblocks *bb, const struct resource *res);
271int nd_blk_region_init(struct nd_region *nd_region); 271int nd_blk_region_init(struct nd_region *nd_region);
272void __nd_iostat_start(struct bio *bio, unsigned long *start); 272void __nd_iostat_start(struct bio *bio, unsigned long *start);
273static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) 273static inline bool nd_iostat_start(struct bio *bio, unsigned long *start)
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index cc31c6f1f88e..ca304342af33 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -244,7 +244,9 @@ static void pmem_detach_disk(struct pmem_device *pmem)
244static int pmem_attach_disk(struct device *dev, 244static int pmem_attach_disk(struct device *dev,
245 struct nd_namespace_common *ndns, struct pmem_device *pmem) 245 struct nd_namespace_common *ndns, struct pmem_device *pmem)
246{ 246{
247 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
247 int nid = dev_to_node(dev); 248 int nid = dev_to_node(dev);
249 struct resource bb_res;
248 struct gendisk *disk; 250 struct gendisk *disk;
249 251
250 blk_queue_make_request(pmem->pmem_queue, pmem_make_request); 252 blk_queue_make_request(pmem->pmem_queue, pmem_make_request);
@@ -271,8 +273,17 @@ static int pmem_attach_disk(struct device *dev,
271 devm_exit_badblocks(dev, &pmem->bb); 273 devm_exit_badblocks(dev, &pmem->bb);
272 if (devm_init_badblocks(dev, &pmem->bb)) 274 if (devm_init_badblocks(dev, &pmem->bb))
273 return -ENOMEM; 275 return -ENOMEM;
274 nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset); 276 bb_res.start = nsio->res.start + pmem->data_offset;
275 277 bb_res.end = nsio->res.end;
278 if (is_nd_pfn(dev)) {
279 struct nd_pfn *nd_pfn = to_nd_pfn(dev);
280 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
281
282 bb_res.start += __le32_to_cpu(pfn_sb->start_pad);
283 bb_res.end -= __le32_to_cpu(pfn_sb->end_trunc);
284 }
285 nvdimm_badblocks_populate(to_nd_region(dev->parent), &pmem->bb,
286 &bb_res);
276 disk->bb = &pmem->bb; 287 disk->bb = &pmem->bb;
277 add_disk(disk); 288 add_disk(disk);
278 revalidate_disk(disk); 289 revalidate_disk(disk);
@@ -553,7 +564,7 @@ static int nd_pmem_probe(struct device *dev)
553 ndns->rw_bytes = pmem_rw_bytes; 564 ndns->rw_bytes = pmem_rw_bytes;
554 if (devm_init_badblocks(dev, &pmem->bb)) 565 if (devm_init_badblocks(dev, &pmem->bb))
555 return -ENOMEM; 566 return -ENOMEM;
556 nvdimm_namespace_add_poison(ndns, &pmem->bb, 0); 567 nvdimm_badblocks_populate(nd_region, &pmem->bb, &nsio->res);
557 568
558 if (is_nd_btt(dev)) { 569 if (is_nd_btt(dev)) {
559 /* btt allocates its own request_queue */ 570 /* btt allocates its own request_queue */
@@ -595,14 +606,25 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
595{ 606{
596 struct pmem_device *pmem = dev_get_drvdata(dev); 607 struct pmem_device *pmem = dev_get_drvdata(dev);
597 struct nd_namespace_common *ndns = pmem->ndns; 608 struct nd_namespace_common *ndns = pmem->ndns;
609 struct nd_region *nd_region = to_nd_region(dev->parent);
610 struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
611 struct resource res = {
612 .start = nsio->res.start + pmem->data_offset,
613 .end = nsio->res.end,
614 };
598 615
599 if (event != NVDIMM_REVALIDATE_POISON) 616 if (event != NVDIMM_REVALIDATE_POISON)
600 return; 617 return;
601 618
602 if (is_nd_btt(dev)) 619 if (is_nd_pfn(dev)) {
603 nvdimm_namespace_add_poison(ndns, &pmem->bb, 0); 620 struct nd_pfn *nd_pfn = to_nd_pfn(dev);
604 else 621 struct nd_pfn_sb *pfn_sb = nd_pfn->pfn_sb;
605 nvdimm_namespace_add_poison(ndns, &pmem->bb, pmem->data_offset); 622
623 res.start += __le32_to_cpu(pfn_sb->start_pad);
624 res.end -= __le32_to_cpu(pfn_sb->end_trunc);
625 }
626
627 nvdimm_badblocks_populate(nd_region, &pmem->bb, &res);
606} 628}
607 629
608MODULE_ALIAS("pmem"); 630MODULE_ALIAS("pmem");