Index: sys/dev/nvme/nvme_ctrlr.c =================================================================== --- sys/dev/nvme/nvme_ctrlr.c +++ sys/dev/nvme/nvme_ctrlr.c @@ -1133,7 +1133,7 @@ * controller was left in when boot handed off to OS. Linux doesn't do * this, however. If we adopt that policy, see also nvme_ctrlr_resume(). */ - if (nvme_ctrlr_hw_reset(ctrlr) != 0) { + if (nvme_ctrlr_hw_reset(ctrlr) != 0 || ctrlr->fail_on_reset != 0) { fail: nvme_ctrlr_fail(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); Index: sys/dev/nvme/nvme_private.h =================================================================== --- sys/dev/nvme/nvme_private.h +++ sys/dev/nvme/nvme_private.h @@ -313,6 +313,7 @@ uint32_t is_resetting; uint32_t is_initialized; uint32_t notification_sent; + u_int fail_on_reset; bool is_failed; bool is_dying; Index: sys/dev/nvme/nvme_sysctl.c =================================================================== --- sys/dev/nvme/nvme_sysctl.c +++ sys/dev/nvme/nvme_sysctl.c @@ -277,6 +277,10 @@ CTLFLAG_RD, &qpair->num_failures, "Number of commands ending in failure after all retries"); + SYSCTL_ADD_UINT(ctrlr_ctx, que_list, OID_AUTO, "recovery", + CTLFLAG_RW, &qpair->recovery_state, 0, + "Current recovery state of the queue"); + SYSCTL_ADD_PROC(ctrlr_ctx, que_list, OID_AUTO, "dump_debug", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, qpair, 0, nvme_sysctl_dump_debug, "IU", "Dump debug data"); @@ -343,6 +347,10 @@ "reset_stats", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, ctrlr, 0, nvme_sysctl_reset_stats, "IU", "Reset statistics to zero"); + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "fail_on_reset", + CTLFLAG_RD, &ctrlr->fail_on_reset, 0, + "Pretend the next reset fails and fail the controller"); + que_tree = SYSCTL_ADD_NODE(ctrlr_ctx, ctrlr_list, OID_AUTO, "adminq", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "Admin Queue");