git: d00a723a2a5c - stable/12 - nvme: Replace potentially long DELAY() with pause().
Alexander Motin
mav at FreeBSD.org
Wed Mar 24 01:27:06 UTC 2021
The branch stable/12 has been updated by mav:
URL: https://cgit.FreeBSD.org/src/commit/?id=d00a723a2a5c1cd686fdab4b6d9c5084705d7182
commit d00a723a2a5c1cd686fdab4b6d9c5084705d7182
Author: Alexander Motin <mav at FreeBSD.org>
AuthorDate: 2021-03-17 14:30:40 +0000
Commit: Alexander Motin <mav at 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);
More information about the dev-commits-src-all
mailing list