diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 1d5972ec7345..e42fe7952bec 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1056,11 +1056,20 @@ nvme_ctrlr_start(void *ctrlr_arg, bool resetting) if (resetting) nvme_qpair_reset(&ctrlr->adminq); - for (i = 0; i < ctrlr->num_io_queues; i++) - nvme_qpair_reset(&ctrlr->ioq[i]); + if (ctrlr->ioq != NULL) { + for (i = 0; i < ctrlr->num_io_queues; i++) + nvme_qpair_reset(&ctrlr->ioq[i]); + } nvme_admin_qpair_enable(&ctrlr->adminq); + /* + * If it was a reset on initialization command timeout, just + * return here, letting initialization code fail gracefully. + */ + if (resetting && !ctrlr->is_initialized) + return; + if (nvme_ctrlr_identify(ctrlr) != 0) { nvme_ctrlr_fail(ctrlr); return; @@ -1115,7 +1124,6 @@ void nvme_ctrlr_start_config_hook(void *arg) { struct nvme_controller *ctrlr = arg; - int status; /* * Reset controller twice to ensure we do a transition from cc.en==1 to @@ -1123,19 +1131,15 @@ nvme_ctrlr_start_config_hook(void *arg) * 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(). */ - status = nvme_ctrlr_hw_reset(ctrlr); - if (status != 0) { + if (nvme_ctrlr_hw_reset(ctrlr) != 0) { +fail: nvme_ctrlr_fail(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); return; } - status = nvme_ctrlr_hw_reset(ctrlr); - if (status != 0) { - nvme_ctrlr_fail(ctrlr); - config_intrhook_disestablish(&ctrlr->config_hook); - return; - } + if (nvme_ctrlr_hw_reset(ctrlr) != 0) + goto fail; nvme_qpair_reset(&ctrlr->adminq); nvme_admin_qpair_enable(&ctrlr->adminq); @@ -1144,7 +1148,7 @@ nvme_ctrlr_start_config_hook(void *arg) nvme_ctrlr_construct_io_qpairs(ctrlr) == 0) nvme_ctrlr_start(ctrlr, false); else - nvme_ctrlr_fail(ctrlr); + goto fail; nvme_sysctl_initialize_ctrlr(ctrlr); config_intrhook_disestablish(&ctrlr->config_hook); @@ -1454,10 +1458,12 @@ nvme_ctrlr_destruct(struct nvme_controller *ctrlr, device_t dev) nvme_ctrlr_hmb_enable(ctrlr, false, false); nvme_ctrlr_delete_qpairs(ctrlr); } + nvme_ctrlr_hmb_free(ctrlr); + } + if (ctrlr->ioq != NULL) { for (i = 0; i < ctrlr->num_io_queues; i++) nvme_io_qpair_destroy(&ctrlr->ioq[i]); free(ctrlr->ioq, M_NVME); - nvme_ctrlr_hmb_free(ctrlr); } nvme_admin_qpair_destroy(&ctrlr->adminq);