From b6fccb7930d07142f9478d6d6956b632c7fa792d Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Mon, 20 Apr 2020 23:49:24 -0400 Subject: [PATCH] nvme_disk: Add an interrupt await timeout. This way, if something stalls in an unexpected way, the whole system won't just hang. Should "fix" #15874, but there is probably some other underlying problem. --- .../kernel/drivers/disk/nvme/nvme_disk.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp index cfb284ce2e..b7b67e4712 100644 --- a/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/nvme/nvme_disk.cpp @@ -389,6 +389,7 @@ static void await_status(nvme_disk_driver_info* info, struct nvme_qpair* qpair, status_t& status) { ConditionVariableEntry entry; + int timeouts = 0; while (status == EINPROGRESS) { info->interrupt.Add(&entry); @@ -397,7 +398,19 @@ await_status(nvme_disk_driver_info* info, struct nvme_qpair* qpair, status_t& st if (status != EINPROGRESS) return; - entry.Wait(); + if (entry.Wait(B_RELATIVE_TIMEOUT, 5 * 1000 * 1000) != B_OK) { + // This should never happen, as we are woken up on every interrupt + // no matter the qpair or transfer within; so if it does occur, + // that probably means the controller stalled or something. + + TRACE_ERROR("timed out waiting for interrupt!\n"); + if (timeouts++ >= 3) { + nvme_qpair_fail(qpair); + status = B_TIMED_OUT; + return; + } + } + nvme_qpair_poll(qpair, 0); } }