From acb9d2488dcc65eee6deb751d9c192fb2dc60ea5 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Wed, 1 Nov 2017 13:41:35 -0700 Subject: [PATCH] nvme: use RTD3E to determine shutdown timeout NVMe 1.2 introduced a new Identify Controller field, RTD3E ("RTD3 Entry Latency"), which allows the device to report the expected time for a normal shutdown. Use this as the timeout for the shutdown process when available instead of hard-coding 5 seconds. Change-Id: I14e7223c81ba397771cf00b49f034f25d21b6e82 Signed-off-by: Daniel Verkamp Reviewed-on: https://review.gerrithub.io/385301 Tested-by: SPDK Automated Test System Reviewed-by: Ben Walker Reviewed-by: Jim Harris Reviewed-by: Changpeng Liu --- lib/nvme/nvme_ctrlr.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index e2e5cd494..5ba32b76f 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -481,7 +481,8 @@ nvme_ctrlr_shutdown(struct spdk_nvme_ctrlr *ctrlr) { union spdk_nvme_cc_register cc; union spdk_nvme_csts_register csts; - int ms_waited = 0; + uint32_t ms_waited = 0; + uint32_t shutdown_timeout_ms; if (ctrlr->is_removed) { return; @@ -500,11 +501,19 @@ nvme_ctrlr_shutdown(struct spdk_nvme_ctrlr *ctrlr) } /* - * The NVMe spec does not define a timeout period - * for shutdown notification, so we just pick + * The NVMe specification defines RTD3E to be the time between + * setting SHN = 1 until the controller will set SHST = 10b. + * If the device doesn't report RTD3 entry latency, pick * 5 seconds as a reasonable amount of time to * wait before proceeding. */ + SPDK_DEBUGLOG(SPDK_TRACE_NVME, "RTD3E = %" PRIu32 " us\n", ctrlr->cdata.rtd3e); + shutdown_timeout_ms = (ctrlr->cdata.rtd3e + 999) / 1000; + if (shutdown_timeout_ms == 0) { + shutdown_timeout_ms = 5000; + } + SPDK_DEBUGLOG(SPDK_TRACE_NVME, "shutdown timeout = %" PRIu32 " ms\n", shutdown_timeout_ms); + do { if (nvme_ctrlr_get_csts(ctrlr, &csts)) { SPDK_ERRLOG("get_csts() failed\n"); @@ -518,7 +527,7 @@ nvme_ctrlr_shutdown(struct spdk_nvme_ctrlr *ctrlr) nvme_delay(1000); ms_waited++; - } while (ms_waited < 5000); + } while (ms_waited < shutdown_timeout_ms); SPDK_ERRLOG("did not shutdown within 5 seconds\n"); }