Page MenuHomeFreeBSD

D60424.diff
No OneTemporary

D60424.diff

diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -29,7 +29,10 @@
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
#include <sys/module.h>
+#include <sys/reboot.h>
#include <vm/uma.h>
@@ -144,6 +147,44 @@
atomic_store_rel_int(&status->done, 1);
}
+/*
+ * The devices' shutdown methods run one after the other, and each nvme one
+ * waits for its controller to complete the shutdown notification (about a
+ * second for an enterprise drive). Send the notification to every controller
+ * here, before those methods run, so the controllers do their shutdown work
+ * at the same time and the methods only wait for what is left. The file
+ * systems are synced by then and no device has been shut down yet; the
+ * shutdown method submits no commands, so an early notification is safe.
+ */
+static void
+nvme_shutdown_all(void *arg __unused, int howto __unused)
+{
+ struct nvme_controller *ctrlr;
+ devclass_t dc;
+ device_t dev;
+ int i;
+
+ if ((dc = devclass_find("nvme")) == NULL)
+ return;
+ for (i = 0; i < devclass_get_maxunit(dc); i++) {
+ dev = devclass_get_device(dc, i);
+ if (dev == NULL || !device_is_attached(dev))
+ continue;
+ ctrlr = DEVICE2SOFTC(dev);
+ if (ctrlr->is_initialized && !ctrlr->is_failed)
+ nvme_ctrlr_shutdown_start(ctrlr);
+ }
+}
+
+static void
+nvme_shutdown_all_init(void *arg __unused)
+{
+ EVENTHANDLER_REGISTER(shutdown_final, nvme_shutdown_all, NULL,
+ SHUTDOWN_PRI_FIRST);
+}
+SYSINIT(nvme_shutdown_all, SI_SUB_DRIVERS, SI_ORDER_ANY, nvme_shutdown_all_init,
+ NULL);
+
static int
nvme_modevent(module_t mod __unused, int type __unused, void *argp __unused)
{
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -1943,17 +1943,25 @@
mtx_destroy(&ctrlr->lock);
}
+/* Send the shutdown notification; nvme_ctrlr_shutdown() waits for it. */
void
-nvme_ctrlr_shutdown(struct nvme_controller *ctrlr)
+nvme_ctrlr_shutdown_start(struct nvme_controller *ctrlr)
{
uint32_t cc;
- uint32_t csts;
- int timeout;
cc = nvme_mmio_read_4(ctrlr, cc);
cc &= ~NVMEM(NVME_CC_REG_SHN);
cc |= NVMEF(NVME_CC_REG_SHN, NVME_SHN_NORMAL);
nvme_mmio_write_4(ctrlr, cc, cc);
+}
+
+void
+nvme_ctrlr_shutdown(struct nvme_controller *ctrlr)
+{
+ uint32_t csts;
+ int timeout;
+
+ nvme_ctrlr_shutdown_start(ctrlr);
timeout = ticks + (ctrlr->cdata.rtd3e == 0 ? 5 * hz :
((uint64_t)ctrlr->cdata.rtd3e * hz + 999999) / 1000000);
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -436,6 +436,7 @@
int nvme_ctrlr_construct(struct nvme_controller *ctrlr, device_t dev);
void nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev);
+void nvme_ctrlr_shutdown_start(struct nvme_controller *ctrlr);
void nvme_ctrlr_shutdown(struct nvme_controller *ctrlr);
void nvme_ctrlr_reset(struct nvme_controller *ctrlr);
/* ctrlr defined as void * to allow use with config_intrhook. */

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 8, 11:40 PM (4 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40392974
Default Alt Text
D60424.diff (3 KB)

Event Timeline