diff options
author | jimharris <jimharris@FreeBSD.org> | 2013-03-26 18:29:04 +0000 |
---|---|---|
committer | jimharris <jimharris@FreeBSD.org> | 2013-03-26 18:29:04 +0000 |
commit | b4217411fa1a625c65c98e03e5bad55be3d04b8c (patch) | |
tree | 064ab3b12b6c88ae8ea57b68bf83944e854eec5c /sys | |
parent | 17c9d83862a537601689aa849ef3fed13ff14616 (diff) | |
download | FreeBSD-src-b4217411fa1a625c65c98e03e5bad55be3d04b8c.zip FreeBSD-src-b4217411fa1a625c65c98e03e5bad55be3d04b8c.tar.gz |
Explicitly abort a timed out command, if the ABORT command sent to the
controller indicates the command was not found.
Sponsored by: Intel
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/nvme/nvme_qpair.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c index 8abdce4..c8f4c54 100644 --- a/sys/dev/nvme/nvme_qpair.c +++ b/sys/dev/nvme/nvme_qpair.c @@ -393,12 +393,40 @@ nvme_io_qpair_destroy(struct nvme_qpair *qpair) } static void +nvme_abort_complete(void *arg, const struct nvme_completion *status) +{ + struct nvme_completion cpl; + struct nvme_tracker *tr = arg; + + /* + * If cdw0 == 1, the controller was not able to abort the command + * we requested. We still need to check the active tracker array, + * to cover race where I/O timed out at same time controller was + * completing the I/O. + */ + if (status->cdw0 == 1 && tr->qpair->act_tr[tr->cid] != NULL) { + /* + * An I/O has timed out, and the controller was unable to + * abort it for some reason. Construct a fake completion + * status, and then complete the I/O's tracker manually. + */ + printf("abort command failed, aborting command manually\n"); + memset(&cpl, 0, sizeof(cpl)); + cpl.sqid = tr->qpair->id; + cpl.cid = tr->cid; + cpl.sf_sct = NVME_SCT_GENERIC; + cpl.sf_sc = NVME_SC_ABORTED_BY_REQUEST; + nvme_qpair_complete_tracker(tr->qpair, tr, &cpl, TRUE); + } +} + +static void nvme_timeout(void *arg) { struct nvme_tracker *tr = arg; nvme_ctrlr_cmd_abort(tr->qpair->ctrlr, tr->cid, tr->qpair->id, - NULL, NULL); + nvme_abort_complete, tr); } void |