Page MenuHomeFreeBSD

D60429.diff
No OneTemporary

D60429.diff

diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -63,6 +63,7 @@
return (status);
}
+ ctrlr->start_reset_state = 1;
ctrlr->config_hook.ich_func = nvme_ctrlr_start_config_hook;
ctrlr->config_hook.ich_arg = ctrlr;
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
@@ -1159,6 +1159,48 @@
TSEXIT();
}
+/*
+ * The config hooks run one after the other in the boot thread, and the reset
+ * sleeps until the controller is ready: seconds for an enterprise drive, in
+ * series. The first hook starts the reset of every controller that is still
+ * waiting for its hook, each in that controller's taskqueue thread, and every
+ * hook waits for its own controller's reset. The rest of a hook runs as
+ * before, in the hooks' order, so the scbus and nda numbers stay the same.
+ */
+static void
+nvme_ctrlr_start_reset_task(void *arg, int pending __unused)
+{
+ struct nvme_controller *ctrlr = arg;
+
+ ctrlr->start_reset_error = nvme_ctrlr_hw_reset(ctrlr);
+ atomic_store_rel_int(&ctrlr->start_reset_state, 3);
+ wakeup(&ctrlr->start_reset_task);
+}
+
+static int
+nvme_ctrlr_start_reset(struct nvme_controller *ctrlr)
+{
+ struct nvme_controller *c;
+ devclass_t dc;
+ device_t dev;
+ int i;
+
+ dc = devclass_find("nvme");
+ for (i = 0; dc != NULL && i < devclass_get_maxunit(dc); i++) {
+ if ((dev = devclass_get_device(dc, i)) == NULL ||
+ (c = DEVICE2SOFTC(dev)) == NULL)
+ continue;
+ if (atomic_cmpset_int(&c->start_reset_state, 1, 2))
+ taskqueue_enqueue(c->taskqueue, &c->start_reset_task);
+ }
+ /* Not in the devclass (cannot happen): reset it here, as before. */
+ if (atomic_cmpset_int(&ctrlr->start_reset_state, 1, 3))
+ return (nvme_ctrlr_hw_reset(ctrlr));
+ while (atomic_load_acq_int(&ctrlr->start_reset_state) != 3)
+ tsleep(&ctrlr->start_reset_task, PRIBIO, "nvmest", hz / 100 + 1);
+ return (ctrlr->start_reset_error);
+}
+
void
nvme_ctrlr_start_config_hook(void *arg)
{
@@ -1166,7 +1208,7 @@
TSENTER();
- if (nvme_ctrlr_hw_reset(ctrlr) != 0 || ctrlr->fail_on_reset != 0) {
+ if (nvme_ctrlr_start_reset(ctrlr) != 0 || ctrlr->fail_on_reset != 0) {
nvme_ctrlr_fail(ctrlr, true);
config_intrhook_disestablish(&ctrlr->config_hook);
return;
@@ -1814,6 +1856,8 @@
ctrlr->is_resetting = 0;
ctrlr->is_initialized = false;
TASK_INIT(&ctrlr->reset_task, 0, nvme_ctrlr_reset_task, ctrlr);
+ TASK_INIT(&ctrlr->start_reset_task, 0, nvme_ctrlr_start_reset_task,
+ ctrlr);
for (int i = 0; i < NVME_MAX_ASYNC_EVENTS; i++) {
struct nvme_async_event_request *aer = &ctrlr->aer[i];
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
@@ -269,6 +269,10 @@
uint32_t queues_created;
struct task reset_task;
+ /* The reset at boot: 1 attached, 2 queued, 3 done. */
+ struct task start_reset_task;
+ volatile u_int start_reset_state;
+ int start_reset_error;
struct taskqueue *taskqueue;
/* For shared legacy interrupt. */

File Metadata

Mime Type
text/plain
Expires
Thu, Oct 8, 12:39 PM (22 h, 9 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40406632
Default Alt Text
D60429.diff (3 KB)

Event Timeline