aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/nvme/nvme.c
diff options
context:
space:
mode:
authorJim Harris <jimharris@FreeBSD.org>2013-03-26 21:58:38 +0000
committerJim Harris <jimharris@FreeBSD.org>2013-03-26 21:58:38 +0000
commit232e2edb6cd50465bd62b9f7cbc9fd83531c02ca (patch)
treedb8e7e98a528b185943c39f106d44bc2c0f09197 /sys/dev/nvme/nvme.c
parent3d7eb41c1b3c48bf2ac69cddd378f4e266ed6bb6 (diff)
downloadsrc-232e2edb6cd50465bd62b9f7cbc9fd83531c02ca.tar.gz
src-232e2edb6cd50465bd62b9f7cbc9fd83531c02ca.zip
Add the ability to internally mark a controller as failed, if it is unable to
start or reset. Also add a notifier for NVMe consumers for controller fail conditions and plumb this notifier for nvd(4) to destroy the associated GEOM disks when a failure occurs. This requires a bit of work to cover the races when a consumer is sending I/O requests to a controller that is transitioning to the failed state. To help cover this condition, add a task to defer completion of I/Os submitted to a failed controller, so that the consumer will still always receive its completions in a different context than the submission. Sponsored by: Intel Reviewed by: carl
Notes
Notes: svn path=/head/; revision=248767
Diffstat (limited to 'sys/dev/nvme/nvme.c')
-rw-r--r--sys/dev/nvme/nvme.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/sys/dev/nvme/nvme.c b/sys/dev/nvme/nvme.c
index 27870106bf48..afebae735ef2 100644
--- a/sys/dev/nvme/nvme.c
+++ b/sys/dev/nvme/nvme.c
@@ -44,6 +44,7 @@ struct nvme_consumer {
nvme_cons_ns_fn_t ns_fn;
nvme_cons_ctrlr_fn_t ctrlr_fn;
nvme_cons_async_fn_t async_fn;
+ nvme_cons_fail_fn_t fail_fn;
};
struct nvme_consumer nvme_consumer[NVME_MAX_CONSUMERS];
@@ -349,9 +350,23 @@ nvme_notify_async_consumers(struct nvme_controller *ctrlr,
}
}
+void
+nvme_notify_fail_consumers(struct nvme_controller *ctrlr)
+{
+ struct nvme_consumer *cons;
+ uint32_t i;
+
+ for (i = 0; i < NVME_MAX_CONSUMERS; i++) {
+ cons = &nvme_consumer[i];
+ if (cons->id != INVALID_CONSUMER_ID && cons->fail_fn != NULL)
+ cons->fail_fn(ctrlr->cons_cookie[i]);
+ }
+}
+
struct nvme_consumer *
nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn,
- nvme_cons_async_fn_t async_fn)
+ nvme_cons_async_fn_t async_fn,
+ nvme_cons_fail_fn_t fail_fn)
{
int i;
@@ -365,6 +380,7 @@ nvme_register_consumer(nvme_cons_ns_fn_t ns_fn, nvme_cons_ctrlr_fn_t ctrlr_fn,
nvme_consumer[i].ns_fn = ns_fn;
nvme_consumer[i].ctrlr_fn = ctrlr_fn;
nvme_consumer[i].async_fn = async_fn;
+ nvme_consumer[i].fail_fn = fail_fn;
nvme_notify_consumer(&nvme_consumer[i]);
return (&nvme_consumer[i]);