Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144423309
D36929.id111624.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D36929.id111624.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D36929: nvme: Use ISR exclusion to make reset safer
Attached
Detach File
Event Timeline
Log In to Comment