diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-07-09 00:12:52 -0700 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-07-12 15:13:48 -0700 |
commit | 476f848aaee466fd5d74f123fa652e757f2baeba (patch) | |
tree | d84cdd4fdb50252dfc5d1e2916b665d4f5570b76 | |
parent | 7e267a8c790edfde9b697cbe944ee566f41219c3 (diff) |
libnvdimm, pmem: flush posted-write queues on shutdown
Commit writes to media on system shutdown or pmem driver unload.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/nvdimm/bus.c | 16 | ||||
-rw-r--r-- | drivers/nvdimm/pmem.c | 8 | ||||
-rw-r--r-- | include/linux/nd.h | 1 |
3 files changed, 25 insertions, 0 deletions
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index e4882e63bece..1cc7880320fe 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -136,6 +136,21 @@ static int nvdimm_bus_remove(struct device *dev) return rc; } +static void nvdimm_bus_shutdown(struct device *dev) +{ + struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); + struct nd_device_driver *nd_drv = NULL; + + if (dev->driver) + nd_drv = to_nd_device_driver(dev->driver); + + if (nd_drv && nd_drv->shutdown) { + nd_drv->shutdown(dev); + dev_dbg(&nvdimm_bus->dev, "%s.shutdown(%s)\n", + dev->driver->name, dev_name(dev)); + } +} + void nd_device_notify(struct device *dev, enum nvdimm_event event) { device_lock(dev); @@ -214,6 +229,7 @@ static struct bus_type nvdimm_bus_type = { .match = nvdimm_bus_match, .probe = nvdimm_bus_probe, .remove = nvdimm_bus_remove, + .shutdown = nvdimm_bus_shutdown, }; static ASYNC_DOMAIN_EXCLUSIVE(nd_async_domain); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index 9d9c1beef020..8bfc6acc2e43 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -349,9 +349,16 @@ static int nd_pmem_remove(struct device *dev) { if (is_nd_btt(dev)) nvdimm_namespace_detach_btt(to_nd_btt(dev)); + nvdimm_flush(to_nd_region(dev->parent)); + return 0; } +static void nd_pmem_shutdown(struct device *dev) +{ + nvdimm_flush(to_nd_region(dev->parent)); +} + static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) { struct pmem_device *pmem = dev_get_drvdata(dev); @@ -391,6 +398,7 @@ static struct nd_device_driver nd_pmem_driver = { .probe = nd_pmem_probe, .remove = nd_pmem_remove, .notify = nd_pmem_notify, + .shutdown = nd_pmem_shutdown, .drv = { .name = "nd_pmem", }, diff --git a/include/linux/nd.h b/include/linux/nd.h index aee2761d294c..1ecd64643512 100644 --- a/include/linux/nd.h +++ b/include/linux/nd.h @@ -26,6 +26,7 @@ struct nd_device_driver { unsigned long type; int (*probe)(struct device *dev); int (*remove)(struct device *dev); + void (*shutdown)(struct device *dev); void (*notify)(struct device *dev, enum nvdimm_event event); }; |