Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Mar 2021 01:27:06 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org
Subject:   git: d00a723a2a5c - stable/12 - nvme: Replace potentially long DELAY() with pause().
Message-ID:  <202103240127.12O1R6VS000987@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch stable/12 has been updated by mav:

URL: https://cgit.FreeBSD.org/src/commit/?id=d00a723a2a5c1cd686fdab4b6d9c5084705d7182

commit d00a723a2a5c1cd686fdab4b6d9c5084705d7182
Author:     Alexander Motin <mav@FreeBSD.org>
AuthorDate: 2021-03-17 14:30:40 +0000
Commit:     Alexander Motin <mav@FreeBSD.org>
CommitDate: 2021-03-24 01:26:34 +0000

    nvme: Replace potentially long DELAY() with pause().
    
    In some cases like broken hardware nvme(4) may wait minutes for
    controller response before timeout.  Doing so in a tight spin loop
    made whole system unresponsive.
    
    Reviewed by:    imp
    MFC after:      1 week
    Differential Revision:  https://reviews.freebsd.org/D29309
    Sponsored by:   iXsystems, Inc.
    
    (cherry picked from commit 4fbbe523653b6d2a0186aca38224efcab941deaa)
---
 sys/dev/nvme/nvme_ctrlr.c | 24 +++++++++++-------------
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 9e4268d9f4b5..d011eec99722 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -224,10 +224,9 @@ nvme_ctrlr_fail_req_task(void *arg, int pending)
 static int
 nvme_ctrlr_wait_for_ready(struct nvme_controller *ctrlr, int desired_val)
 {
-	int ms_waited;
+	int timeout = ticks + (uint64_t)ctrlr->ready_timeout_in_ms * hz / 1000;
 	uint32_t csts;
 
-	ms_waited = 0;
 	while (1) {
 		csts = nvme_mmio_read_4(ctrlr, csts);
 		if (csts == 0xffffffff)		/* Hot unplug. */
@@ -235,12 +234,12 @@ nvme_ctrlr_wait_for_ready(struct nvme_controller *ctrlr, int desired_val)
 		if (((csts >> NVME_CSTS_REG_RDY_SHIFT) & NVME_CSTS_REG_RDY_MASK)
 		    == desired_val)
 			break;
-		if (ms_waited++ > ctrlr->ready_timeout_in_ms) {
+		if (timeout - ticks < 0) {
 			nvme_printf(ctrlr, "controller ready did not become %d "
 			    "within %d ms\n", desired_val, ctrlr->ready_timeout_in_ms);
 			return (ENXIO);
 		}
-		DELAY(1000);
+		pause("nvmerdy", 1);
 	}
 
 	return (0);
@@ -379,7 +378,7 @@ nvme_ctrlr_hw_reset(struct nvme_controller *ctrlr)
 
 	nvme_ctrlr_disable_qpairs(ctrlr);
 
-	DELAY(100*1000);
+	pause("nvmehwreset", hz / 10);
 
 	err = nvme_ctrlr_disable(ctrlr);
 	if (err != 0)
@@ -1514,27 +1513,26 @@ nvme_ctrlr_shutdown(struct nvme_controller *ctrlr)
 {
 	uint32_t	cc;
 	uint32_t	csts;
-	int		ticks = 0, timeout;
+	int		timeout;
 
 	cc = nvme_mmio_read_4(ctrlr, cc);
 	cc &= ~(NVME_CC_REG_SHN_MASK << NVME_CC_REG_SHN_SHIFT);
 	cc |= NVME_SHN_NORMAL << NVME_CC_REG_SHN_SHIFT;
 	nvme_mmio_write_4(ctrlr, cc, cc);
 
-	timeout = ctrlr->cdata.rtd3e == 0 ? 5 * hz :
-	    ((uint64_t)ctrlr->cdata.rtd3e * hz + 999999) / 1000000;
+	timeout = ticks + (ctrlr->cdata.rtd3e == 0 ? 5 * hz :
+	    ((uint64_t)ctrlr->cdata.rtd3e * hz + 999999) / 1000000);
 	while (1) {
 		csts = nvme_mmio_read_4(ctrlr, csts);
 		if (csts == 0xffffffff)		/* Hot unplug. */
 			break;
 		if (NVME_CSTS_GET_SHST(csts) == NVME_SHST_COMPLETE)
 			break;
-		if (ticks++ > timeout) {
-			nvme_printf(ctrlr, "did not complete shutdown within"
-			    " %d ticks of notification\n", timeout);
+		if (timeout - ticks < 0) {
+			nvme_printf(ctrlr, "shutdown timeout\n");
 			break;
 		}
-		pause("nvme shn", 1);
+		pause("nvmeshut", 1);
 	}
 }
 
@@ -1611,7 +1609,7 @@ nvme_ctrlr_suspend(struct nvme_controller *ctrlr)
 	 */
 	nvme_ctrlr_delete_qpairs(ctrlr);
 	nvme_ctrlr_disable_qpairs(ctrlr);
-	DELAY(100*1000);
+	pause("nvmesusp", hz / 10);
 	nvme_ctrlr_shutdown(ctrlr);
 
 	return (0);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202103240127.12O1R6VS000987>