diff options
author | Dave Jiang <dave.jiang@intel.com> | 2017-04-07 15:33:31 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2017-04-12 21:56:43 -0700 |
commit | 006358b35c73ab75544fb4509483a81ef1a9c0b2 (patch) | |
tree | 9f0ac88e27f376ba6b714763def8837167518acd /drivers/nvdimm/region.c | |
parent | 802f4be6feee3f0395c26ac9717da5b15f6b8fec (diff) | |
download | linux-stable-006358b35c73ab75544fb4509483a81ef1a9c0b2.tar.gz linux-stable-006358b35c73ab75544fb4509483a81ef1a9c0b2.tar.bz2 linux-stable-006358b35c73ab75544fb4509483a81ef1a9c0b2.zip |
libnvdimm: add support for clear poison list and badblocks for device dax
Providing mechanism to clear poison list via the ndctl ND_CMD_CLEAR_ERROR
call. We will update the poison list and also the badblocks at region level
if the region is in dax mode or in pmem mode and not active. In other
words we force badblocks to be cleared through write requests if the
address is currently accessed through a block device, otherwise it can
only be done via the ioctl+dsm path.
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/region.c')
-rw-r--r-- | drivers/nvdimm/region.c | 25 |
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/nvdimm/region.c b/drivers/nvdimm/region.c index 869a886c292e..23c4307d254c 100644 --- a/drivers/nvdimm/region.c +++ b/drivers/nvdimm/region.c @@ -131,6 +131,31 @@ static void nd_region_notify(struct device *dev, enum nvdimm_event event) device_for_each_child(dev, &event, child_notify); } +int nvdimm_region_badblocks_clear(struct device *dev, void *data) +{ + struct resource *res = (struct resource *)data; + struct nd_region *nd_region; + resource_size_t ndr_end; + sector_t sector; + + /* make sure device is a region */ + if (!is_nd_pmem(dev)) + return 0; + + nd_region = to_nd_region(dev); + ndr_end = nd_region->ndr_start + nd_region->ndr_size - 1; + + /* make sure we are in the region */ + if (res->start < nd_region->ndr_start || res->end > ndr_end) + return 0; + + sector = (res->start - nd_region->ndr_start) >> 9; + badblocks_clear(&nd_region->bb, sector, resource_size(res) >> 9); + + return 0; +} +EXPORT_SYMBOL_GPL(nvdimm_region_badblocks_clear); + static struct nd_device_driver nd_region_driver = { .probe = nd_region_probe, .remove = nd_region_remove, |