Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174997392
D60429.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
3 KB
Referenced Files
None
Subscribers
None
D60429.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D60429: nvme: reset the controllers in parallel at boot
Attached
Detach File
Event Timeline
Log In to Comment