Page MenuHomeFreeBSD

D36929.id111624.diff
No OneTemporary

D36929.id111624.diff

diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -1203,20 +1203,30 @@
int status;
nvme_ctrlr_devctl_log(ctrlr, "RESET", "resetting controller");
+
+ /*
+ * Make sure that all ISRs are done before proceeding with the reset,
+ * and also keep any stray interrupts from causng damage.
+ */
+ nvme_qpair_block_isr(&ctrlr->adminq);
+ for (int i = 0; i < ctrlr->num_io_queues; i++)
+ nvme_qpair_block_isr(&ctrlr->ioq[i]);
+
status = nvme_ctrlr_hw_reset(ctrlr);
+
/*
- * Use pause instead of DELAY, so that we yield to any nvme interrupt
- * handlers on this CPU that were blocked on a qpair lock. We want
- * all nvme interrupts completed before proceeding with restarting the
- * controller.
- *
- * XXX - any way to guarantee the interrupt handlers have quiesced?
+ * Now that we've reset, allow ISRs so we can startup the controller
+ * again.
*/
- pause("nvmereset", hz / 10);
- if (status == 0)
+ nvme_qpair_unblock_isr(&ctrlr->adminq);
+ for (int i = 0; i < ctrlr->num_io_queues; i++)
+ nvme_qpair_unblock_isr(&ctrlr->ioq[i]);
+
+ if (status == 0) {
nvme_ctrlr_start(ctrlr, true);
- else
+ } else {
nvme_ctrlr_fail(ctrlr);
+ }
atomic_cmpset_32(&ctrlr->is_resetting, 1, 0);
}
diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h
--- a/sys/dev/nvme/nvme_private.h
+++ b/sys/dev/nvme/nvme_private.h
@@ -436,6 +436,8 @@
void nvme_qpair_manual_complete_request(struct nvme_qpair *qpair,
struct nvme_request *req,
uint32_t sct, uint32_t sc);
+void nvme_qpair_block_isr(struct nvme_qpair *qpair);
+void nvme_qpair_unblock_isr(struct nvme_qpair *qpair);
void nvme_admin_qpair_enable(struct nvme_qpair *qpair);
void nvme_admin_qpair_disable(struct nvme_qpair *qpair);
diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c
--- a/sys/dev/nvme/nvme_qpair.c
+++ b/sys/dev/nvme/nvme_qpair.c
@@ -532,6 +532,30 @@
nvme_free_request(req);
}
+void
+nvme_qpair_block_isr(struct nvme_qpair *qpair)
+{
+ bool in_panic = dumping || SCHEDULER_STOPPED();
+
+ /*
+ * Set that we're in the interrupt and return. This will make any
+ * interrupts that happen after this point nops.
+ */
+ if (in_panic)
+ return;
+ while (!atomic_cmpset_32(&qpair->in_isr, 0, 1))
+ pause("nvmeQB", 1);
+}
+
+void
+nvme_qpair_unblock_isr(struct nvme_qpair *qpair)
+{
+ /*
+ * Say we're out of the ISR so that the ISRs will function again.
+ */
+ atomic_store_32(&qpair->in_isr, 0);
+}
+
bool
nvme_qpair_process_completions(struct nvme_qpair *qpair)
{

File Metadata

Mime Type
text/plain
Expires
Mon, Feb 9, 9:07 AM (15 h, 5 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28561161
Default Alt Text
D36929.id111624.diff (2 KB)

Event Timeline