summaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/region.c
diff options
context:
space:
mode:
authorDave Jiang <dave.jiang@intel.com>2017-04-07 15:33:31 -0700
committerDan Williams <dan.j.williams@intel.com>2017-04-12 21:56:43 -0700
commit006358b35c73ab75544fb4509483a81ef1a9c0b2 (patch)
tree9f0ac88e27f376ba6b714763def8837167518acd /drivers/nvdimm/region.c
parent802f4be6feee3f0395c26ac9717da5b15f6b8fec (diff)
downloadlinux-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.c25
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,