diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/nvdimm/core.c | 41 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 4 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 36 |
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 | ||
420 | static void namespace_add_poison(struct list_head *poison_list, | 420 | static 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 | */ |
473 | void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, | 473 | void 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 | } |
492 | EXPORT_SYMBOL_GPL(nvdimm_namespace_add_poison); | 491 | EXPORT_SYMBOL_GPL(nvdimm_badblocks_populate); |
493 | 492 | ||
494 | static int add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length) | 493 | static 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); | |||
266 | int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); | 266 | int nvdimm_namespace_detach_btt(struct nd_namespace_common *ndns); |
267 | const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, | 267 | const char *nvdimm_namespace_disk_name(struct nd_namespace_common *ndns, |
268 | char *name); | 268 | char *name); |
269 | void nvdimm_namespace_add_poison(struct nd_namespace_common *ndns, | 269 | void nvdimm_badblocks_populate(struct nd_region *nd_region, |
270 | struct badblocks *bb, resource_size_t offset); | 270 | struct badblocks *bb, const struct resource *res); |
271 | int nd_blk_region_init(struct nd_region *nd_region); | 271 | int nd_blk_region_init(struct nd_region *nd_region); |
272 | void __nd_iostat_start(struct bio *bio, unsigned long *start); | 272 | void __nd_iostat_start(struct bio *bio, unsigned long *start); |
273 | static inline bool nd_iostat_start(struct bio *bio, unsigned long *start) | 273 | static 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) | |||
244 | static int pmem_attach_disk(struct device *dev, | 244 | static 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 | ||
608 | MODULE_ALIAS("pmem"); | 630 | MODULE_ALIAS("pmem"); |