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 @@ -316,6 +316,7 @@ uint32_t is_resetting; uint32_t is_initialized; uint32_t notification_sent; + uint32_t in_isr; bool is_failed; bool is_dying; 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 @@ -540,6 +540,14 @@ int done = 0; bool in_panic = dumping || SCHEDULER_STOPPED(); + /* + * If we're not panicing, make sure we're the only one here. + */ + if (__predict_true(!in_panic)) { + if (!atomic_cmpset_32(&ctrlr->in_isr, 0, 1)) + return (false); + } + /* * qpair is not enabled, likely because a controller reset is in * progress. Ignore the interrupt - any I/O that was associated with @@ -550,6 +558,7 @@ */ if (qpair->recovery_state != RECOVERY_NONE) { qpair->num_ignored++; + atomic_store_32(&ctrlr->in_isr, 0); return (false); } @@ -675,6 +684,7 @@ qpair->cq_hdbl_off, qpair->cq_head); } + atomic_store_32(&ctrlr->in_isr, 0); return (done != 0); }