@@ -408,71 +408,81 @@ static void __add_badblock_range(struct badblocks *bb, u64 ns_offset, u64 len)
408408 set_badblock (bb , start_sector , num_sectors );
409409}
410410
411- /**
412- * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks
413- * @ndns: the namespace containing poison ranges
414- * @bb: badblocks instance to populate
415- * @offset: offset at the start of the namespace before 'sector 0'
416- *
417- * The poison list generated during NFIT initialization may contain multiple,
418- * possibly overlapping ranges in the SPA (System Physical Address) space.
419- * Compare each of these ranges to the namespace currently being initialized,
420- * and add badblocks to the gendisk for all matching sub-ranges
421- */
422- void nvdimm_namespace_add_poison (struct nd_namespace_common * ndns ,
423- struct badblocks * bb , resource_size_t offset )
411+ static void namespace_add_poison (struct list_head * poison_list ,
412+ struct badblocks * bb , struct resource * res )
424413{
425- struct nd_namespace_io * nsio = to_nd_namespace_io (& ndns -> dev );
426- struct nd_region * nd_region = to_nd_region (ndns -> dev .parent );
427- struct nvdimm_bus * nvdimm_bus ;
428- struct list_head * poison_list ;
429- u64 ns_start , ns_end , ns_size ;
430414 struct nd_poison * pl ;
431415
432- ns_size = nvdimm_namespace_capacity (ndns ) - offset ;
433- ns_start = nsio -> res .start + offset ;
434- ns_end = nsio -> res .end ;
435-
436- nvdimm_bus = to_nvdimm_bus (nd_region -> dev .parent );
437- poison_list = & nvdimm_bus -> poison_list ;
438416 if (list_empty (poison_list ))
439417 return ;
440418
441419 list_for_each_entry (pl , poison_list , list ) {
442420 u64 pl_end = pl -> start + pl -> length - 1 ;
443421
444422 /* Discard intervals with no intersection */
445- if (pl_end < ns_start )
423+ if (pl_end < res -> start )
446424 continue ;
447- if (pl -> start > ns_end )
425+ if (pl -> start > res -> end )
448426 continue ;
449427 /* Deal with any overlap after start of the namespace */
450- if (pl -> start >= ns_start ) {
428+ if (pl -> start >= res -> start ) {
451429 u64 start = pl -> start ;
452430 u64 len ;
453431
454- if (pl_end <= ns_end )
432+ if (pl_end <= res -> end )
455433 len = pl -> length ;
456434 else
457- len = ns_start + ns_size - pl -> start ;
458- __add_badblock_range (bb , start - ns_start , len );
435+ len = res -> start + resource_size (res )
436+ - pl -> start ;
437+ __add_badblock_range (bb , start - res -> start , len );
459438 continue ;
460439 }
461440 /* Deal with overlap for poison starting before the namespace */
462- if (pl -> start < ns_start ) {
441+ if (pl -> start < res -> start ) {
463442 u64 len ;
464443
465- if (pl_end < ns_end )
466- len = pl -> start + pl -> length - ns_start ;
444+ if (pl_end < res -> end )
445+ len = pl -> start + pl -> length - res -> start ;
467446 else
468- len = ns_size ;
447+ len = resource_size ( res ) ;
469448 __add_badblock_range (bb , 0 , len );
470449 }
471450 }
472451}
452+
453+ /**
454+ * nvdimm_namespace_add_poison() - Convert a list of poison ranges to badblocks
455+ * @ndns: the namespace containing poison ranges
456+ * @bb: badblocks instance to populate
457+ * @offset: offset at the start of the namespace before 'sector 0'
458+ *
459+ * The poison list generated during NFIT initialization may contain multiple,
460+ * possibly overlapping ranges in the SPA (System Physical Address) space.
461+ * Compare each of these ranges to the namespace currently being initialized,
462+ * and add badblocks to the gendisk for all matching sub-ranges
463+ */
464+ void nvdimm_namespace_add_poison (struct nd_namespace_common * ndns ,
465+ struct badblocks * bb , resource_size_t offset )
466+ {
467+ struct nd_namespace_io * nsio = to_nd_namespace_io (& ndns -> dev );
468+ struct nd_region * nd_region = to_nd_region (ndns -> dev .parent );
469+ struct nvdimm_bus * nvdimm_bus ;
470+ struct list_head * poison_list ;
471+ struct resource res = {
472+ .start = nsio -> res .start + offset ,
473+ .end = nsio -> res .end ,
474+ };
475+
476+ nvdimm_bus = to_nvdimm_bus (nd_region -> dev .parent );
477+ poison_list = & nvdimm_bus -> poison_list ;
478+
479+ nvdimm_bus_lock (& nvdimm_bus -> dev );
480+ namespace_add_poison (poison_list , bb , & res );
481+ nvdimm_bus_unlock (& nvdimm_bus -> dev );
482+ }
473483EXPORT_SYMBOL_GPL (nvdimm_namespace_add_poison );
474484
475- static int __add_poison (struct nvdimm_bus * nvdimm_bus , u64 addr , u64 length )
485+ static int add_poison (struct nvdimm_bus * nvdimm_bus , u64 addr , u64 length )
476486{
477487 struct nd_poison * pl ;
478488
@@ -487,12 +497,12 @@ static int __add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length)
487497 return 0 ;
488498}
489499
490- int nvdimm_bus_add_poison (struct nvdimm_bus * nvdimm_bus , u64 addr , u64 length )
500+ static int bus_add_poison (struct nvdimm_bus * nvdimm_bus , u64 addr , u64 length )
491501{
492502 struct nd_poison * pl ;
493503
494504 if (list_empty (& nvdimm_bus -> poison_list ))
495- return __add_poison (nvdimm_bus , addr , length );
505+ return add_poison (nvdimm_bus , addr , length );
496506
497507 /*
498508 * There is a chance this is a duplicate, check for those first.
@@ -512,7 +522,18 @@ int nvdimm_bus_add_poison(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length)
512522 * as any overlapping ranges will get resolved when the list is consumed
513523 * and converted to badblocks
514524 */
515- return __add_poison (nvdimm_bus , addr , length );
525+ return add_poison (nvdimm_bus , addr , length );
526+ }
527+
528+ int nvdimm_bus_add_poison (struct nvdimm_bus * nvdimm_bus , u64 addr , u64 length )
529+ {
530+ int rc ;
531+
532+ nvdimm_bus_lock (& nvdimm_bus -> dev );
533+ rc = bus_add_poison (nvdimm_bus , addr , length );
534+ nvdimm_bus_unlock (& nvdimm_bus -> dev );
535+
536+ return rc ;
516537}
517538EXPORT_SYMBOL_GPL (nvdimm_bus_add_poison );
518539
@@ -553,7 +574,11 @@ void nvdimm_bus_unregister(struct nvdimm_bus *nvdimm_bus)
553574
554575 nd_synchronize ();
555576 device_for_each_child (& nvdimm_bus -> dev , NULL , child_unregister );
577+
578+ nvdimm_bus_lock (& nvdimm_bus -> dev );
556579 free_poison_list (& nvdimm_bus -> poison_list );
580+ nvdimm_bus_unlock (& nvdimm_bus -> dev );
581+
557582 nvdimm_bus_destroy_ndctl (nvdimm_bus );
558583
559584 device_unregister (& nvdimm_bus -> dev );
0 commit comments