From 7d4d22a8465f1598f59b6cd9dc4a057da5aeccf1 Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 13 Feb 2019 03:08:33 -0500 Subject: [PATCH] nvme: add a wait for completion timeout API Althrough SPDK already provides a API to users which can process runtime timeout NVMe commands, but it's nice to have another API here, SPDK NVMe driver can use it to break the endless wait. Also use the API first in the initialization process, because we don't want to add another initialization state with Intel only supported log pages. Change-Id: Ibe7cadbc59033a299a1fcf02a66e98fc4eca8100 Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/c/444353 Tested-by: SPDK CI Jenkins Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- lib/nvme/nvme.c | 27 +++++++++++++++++++ lib/nvme/nvme_ctrlr.c | 3 ++- lib/nvme/nvme_internal.h | 3 +++ .../lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c | 7 +++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/nvme/nvme.c b/lib/nvme/nvme.c index 7b313addba..abd2e3cc2a 100644 --- a/lib/nvme/nvme.c +++ b/lib/nvme/nvme.c @@ -142,6 +142,33 @@ spdk_nvme_wait_for_completion(struct spdk_nvme_qpair *qpair, return spdk_nvme_wait_for_completion_robust_lock(qpair, status, NULL); } +int +spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, + struct nvme_completion_poll_status *status, + uint64_t timeout_in_secs) +{ + uint64_t timeout_tsc = 0; + + memset(&status->cpl, 0, sizeof(status->cpl)); + status->done = false; + if (timeout_in_secs) { + timeout_tsc = spdk_get_ticks() + timeout_in_secs * spdk_get_ticks_hz(); + } + + while (status->done == false) { + spdk_nvme_qpair_process_completions(qpair, 0); + if (timeout_tsc && spdk_get_ticks() > timeout_tsc) { + break; + } + } + + if (status->done == false) { + return -EIO; + } + + return spdk_nvme_cpl_is_error(&status->cpl) ? -EIO : 0; +} + static void nvme_user_copy_cmd_complete(void *arg, const struct spdk_nvme_cpl *cpl) { diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index 280fe1e664..2982b6c5a6 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -410,7 +410,8 @@ static int nvme_ctrlr_set_intel_support_log_pages(struct spdk_nvme_ctrlr *ctrlr) return rc; } - if (spdk_nvme_wait_for_completion(ctrlr->adminq, &status)) { + if (spdk_nvme_wait_for_completion_timeout(ctrlr->adminq, &status, + ctrlr->opts.admin_timeout_ms / 1000)) { spdk_free(log_page_directory); SPDK_WARNLOG("Intel log pages not supported on Intel drive!\n"); return 0; diff --git a/lib/nvme/nvme_internal.h b/lib/nvme/nvme_internal.h index f9e458fedc..923a520bd1 100644 --- a/lib/nvme/nvme_internal.h +++ b/lib/nvme/nvme_internal.h @@ -793,6 +793,9 @@ int spdk_nvme_wait_for_completion(struct spdk_nvme_qpair *qpair, int spdk_nvme_wait_for_completion_robust_lock(struct spdk_nvme_qpair *qpair, struct nvme_completion_poll_status *status, pthread_mutex_t *robust_mutex); +int spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, + struct nvme_completion_poll_status *status, + uint64_t timeout_in_secs); struct spdk_nvme_ctrlr_process *spdk_nvme_ctrlr_get_process(struct spdk_nvme_ctrlr *ctrlr, pid_t pid); diff --git a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c index 468e15b7ec..1567896449 100644 --- a/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c @@ -293,6 +293,13 @@ spdk_nvme_wait_for_completion(struct spdk_nvme_qpair *qpair, return spdk_nvme_wait_for_completion_robust_lock(qpair, status, NULL); } +int +spdk_nvme_wait_for_completion_timeout(struct spdk_nvme_qpair *qpair, + struct nvme_completion_poll_status *status, + uint64_t timeout_in_secs) +{ + return spdk_nvme_wait_for_completion_robust_lock(qpair, status, NULL); +} int nvme_ctrlr_cmd_set_async_event_config(struct spdk_nvme_ctrlr *ctrlr,