aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-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");