diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-07-09 03:12:52 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-07-12 18:13:48 -0400 |
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) | |||
136 | return rc; | 136 | return rc; |
137 | } | 137 | } |
138 | 138 | ||
139 | static void nvdimm_bus_shutdown(struct device *dev) | ||
140 | { | ||
141 | struct nvdimm_bus *nvdimm_bus = walk_to_nvdimm_bus(dev); | ||
142 | struct nd_device_driver *nd_drv = NULL; | ||
143 | |||
144 | if (dev->driver) | ||
145 | nd_drv = to_nd_device_driver(dev->driver); | ||
146 | |||
147 | if (nd_drv && nd_drv->shutdown) { | ||
148 | nd_drv->shutdown(dev); | ||
149 | dev_dbg(&nvdimm_bus->dev, "%s.shutdown(%s)\n", | ||
150 | dev->driver->name, dev_name(dev)); | ||
151 | } | ||
152 | } | ||
153 | |||
139 | void nd_device_notify(struct device *dev, enum nvdimm_event event) | 154 | void nd_device_notify(struct device *dev, enum nvdimm_event event) |
140 | { | 155 | { |
141 | device_lock(dev); | 156 | device_lock(dev); |
@@ -214,6 +229,7 @@ static struct bus_type nvdimm_bus_type = { | |||
214 | .match = nvdimm_bus_match, | 229 | .match = nvdimm_bus_match, |
215 | .probe = nvdimm_bus_probe, | 230 | .probe = nvdimm_bus_probe, |
216 | .remove = nvdimm_bus_remove, | 231 | .remove = nvdimm_bus_remove, |
232 | .shutdown = nvdimm_bus_shutdown, | ||
217 | }; | 233 | }; |
218 | 234 | ||
219 | static ASYNC_DOMAIN_EXCLUSIVE(nd_async_domain); | 235 | 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) | |||
349 | { | 349 | { |
350 | if (is_nd_btt(dev)) | 350 | if (is_nd_btt(dev)) |
351 | nvdimm_namespace_detach_btt(to_nd_btt(dev)); | 351 | nvdimm_namespace_detach_btt(to_nd_btt(dev)); |
352 | nvdimm_flush(to_nd_region(dev->parent)); | ||
353 | |||
352 | return 0; | 354 | return 0; |
353 | } | 355 | } |
354 | 356 | ||
357 | static void nd_pmem_shutdown(struct device *dev) | ||
358 | { | ||
359 | nvdimm_flush(to_nd_region(dev->parent)); | ||
360 | } | ||
361 | |||
355 | static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) | 362 | static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) |
356 | { | 363 | { |
357 | struct pmem_device *pmem = dev_get_drvdata(dev); | 364 | struct pmem_device *pmem = dev_get_drvdata(dev); |
@@ -391,6 +398,7 @@ static struct nd_device_driver nd_pmem_driver = { | |||
391 | .probe = nd_pmem_probe, | 398 | .probe = nd_pmem_probe, |
392 | .remove = nd_pmem_remove, | 399 | .remove = nd_pmem_remove, |
393 | .notify = nd_pmem_notify, | 400 | .notify = nd_pmem_notify, |
401 | .shutdown = nd_pmem_shutdown, | ||
394 | .drv = { | 402 | .drv = { |
395 | .name = "nd_pmem", | 403 | .name = "nd_pmem", |
396 | }, | 404 | }, |
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 { | |||
26 | unsigned long type; | 26 | unsigned long type; |
27 | int (*probe)(struct device *dev); | 27 | int (*probe)(struct device *dev); |
28 | int (*remove)(struct device *dev); | 28 | int (*remove)(struct device *dev); |
29 | void (*shutdown)(struct device *dev); | ||
29 | void (*notify)(struct device *dev, enum nvdimm_event event); | 30 | void (*notify)(struct device *dev, enum nvdimm_event event); |
30 | }; | 31 | }; |
31 | 32 | ||