mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
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.
This commit is contained in:
parent
f187d6dfbf
commit
4fbbe52365
1 changed files with 11 additions and 13 deletions
|
|
@ -255,10 +255,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 == NVME_GONE) /* Hot unplug. */
|
||||
|
|
@ -266,12 +265,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);
|
||||
|
|
@ -410,7 +409,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)
|
||||
|
|
@ -1536,27 +1535,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 == NVME_GONE) /* 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1633,7 +1631,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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue