nvme: make ctrlr detach fully asynchronous
The controller detach had asynchronous API (with async/poll), but the register operations were synchronous, so they would block on fabrics controllers. In this patch, they're changed to their non-blocking counterparts, making the detach fully asynchronous. Signed-off-by: Jim Harris <james.r.harris@intel.com> Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: I74df12ab40a54f1d675639672e03755c89768bef Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8726 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com>
This commit is contained in:
parent
51b018da0f
commit
b6ecc37298
@ -1043,26 +1043,13 @@ spdk_nvme_ctrlr_fail(struct spdk_nvme_ctrlr *ctrlr)
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_shutdown_async(struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct nvme_ctrlr_detach_ctx *ctx)
|
||||
nvme_ctrlr_shutdown_set_cc_done(void *_ctx, uint64_t value, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
union spdk_nvme_cc_register cc;
|
||||
struct nvme_ctrlr_detach_ctx *ctx = _ctx;
|
||||
struct spdk_nvme_ctrlr *ctrlr = ctx->ctrlr;
|
||||
|
||||
if (ctrlr->is_removed) {
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (nvme_ctrlr_get_cc(ctrlr, &cc)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "get_cc() failed\n");
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
cc.bits.shn = SPDK_NVME_SHN_NORMAL;
|
||||
|
||||
if (nvme_ctrlr_set_cc(ctrlr, &cc)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "set_cc() failed\n");
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "Failed to write CC.SHN\n");
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
@ -1081,6 +1068,67 @@ nvme_ctrlr_shutdown_async(struct spdk_nvme_ctrlr *ctrlr,
|
||||
NVME_CTRLR_DEBUGLOG(ctrlr, "shutdown timeout = %" PRIu32 " ms\n", ctx->shutdown_timeout_ms);
|
||||
|
||||
ctx->shutdown_start_tsc = spdk_get_ticks();
|
||||
ctx->state = NVME_CTRLR_DETACH_CHECK_CSTS;
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_shutdown_get_cc_done(void *_ctx, uint64_t value, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct nvme_ctrlr_detach_ctx *ctx = _ctx;
|
||||
struct spdk_nvme_ctrlr *ctrlr = ctx->ctrlr;
|
||||
union spdk_nvme_cc_register cc;
|
||||
int rc;
|
||||
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "Failed to read the CC register\n");
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(value <= UINT32_MAX);
|
||||
cc.raw = (uint32_t)value;
|
||||
cc.bits.shn = SPDK_NVME_SHN_NORMAL;
|
||||
|
||||
rc = nvme_ctrlr_set_cc_async(ctrlr, cc.raw, nvme_ctrlr_shutdown_set_cc_done, ctx);
|
||||
if (rc != 0) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "Failed to write CC.SHN\n");
|
||||
ctx->shutdown_complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_shutdown_async(struct spdk_nvme_ctrlr *ctrlr,
|
||||
struct nvme_ctrlr_detach_ctx *ctx)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (ctrlr->is_removed) {
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ctx->state = NVME_CTRLR_DETACH_SET_CC;
|
||||
rc = nvme_ctrlr_get_cc_async(ctrlr, nvme_ctrlr_shutdown_get_cc_done, ctx);
|
||||
if (rc != 0) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "Failed to read the CC register\n");
|
||||
ctx->shutdown_complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nvme_ctrlr_shutdown_get_csts_done(void *_ctx, uint64_t value, const struct spdk_nvme_cpl *cpl)
|
||||
{
|
||||
struct nvme_ctrlr_detach_ctx *ctx = _ctx;
|
||||
|
||||
if (spdk_nvme_cpl_is_error(cpl)) {
|
||||
NVME_CTRLR_ERRLOG(ctx->ctrlr, "Failed to read the CSTS register\n");
|
||||
ctx->shutdown_complete = true;
|
||||
return;
|
||||
}
|
||||
|
||||
assert(value <= UINT32_MAX);
|
||||
ctx->csts.raw = (uint32_t)value;
|
||||
ctx->state = NVME_CTRLR_DETACH_GET_CSTS_DONE;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1090,13 +1138,33 @@ nvme_ctrlr_shutdown_poll_async(struct spdk_nvme_ctrlr *ctrlr,
|
||||
union spdk_nvme_csts_register csts;
|
||||
uint32_t ms_waited;
|
||||
|
||||
ms_waited = (spdk_get_ticks() - ctx->shutdown_start_tsc) * 1000 / spdk_get_ticks_hz();
|
||||
switch (ctx->state) {
|
||||
case NVME_CTRLR_DETACH_SET_CC:
|
||||
case NVME_CTRLR_DETACH_GET_CSTS:
|
||||
/* We're still waiting for the register operation to complete */
|
||||
spdk_nvme_qpair_process_completions(ctrlr->adminq, 0);
|
||||
return -EAGAIN;
|
||||
|
||||
if (nvme_ctrlr_get_csts(ctrlr, &csts)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "get_csts() failed\n");
|
||||
return -EIO;
|
||||
case NVME_CTRLR_DETACH_CHECK_CSTS:
|
||||
ctx->state = NVME_CTRLR_DETACH_GET_CSTS;
|
||||
if (nvme_ctrlr_get_csts_async(ctrlr, nvme_ctrlr_shutdown_get_csts_done, ctx)) {
|
||||
NVME_CTRLR_ERRLOG(ctrlr, "Failed to read the CSTS register\n");
|
||||
return -EIO;
|
||||
}
|
||||
return -EAGAIN;
|
||||
|
||||
case NVME_CTRLR_DETACH_GET_CSTS_DONE:
|
||||
ctx->state = NVME_CTRLR_DETACH_CHECK_CSTS;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0 && "Should never happen");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ms_waited = (spdk_get_ticks() - ctx->shutdown_start_tsc) * 1000 / spdk_get_ticks_hz();
|
||||
csts.raw = ctx->csts.raw;
|
||||
|
||||
if (csts.bits.shst == SPDK_NVME_SHST_COMPLETE) {
|
||||
NVME_CTRLR_DEBUGLOG(ctrlr, "shutdown complete in %u milliseconds\n", ms_waited);
|
||||
return 0;
|
||||
@ -4062,7 +4130,7 @@ nvme_ctrlr_destruct_poll_async(struct spdk_nvme_ctrlr *ctrlr,
|
||||
void
|
||||
nvme_ctrlr_destruct(struct spdk_nvme_ctrlr *ctrlr)
|
||||
{
|
||||
struct nvme_ctrlr_detach_ctx ctx = {};
|
||||
struct nvme_ctrlr_detach_ctx ctx = { .ctrlr = ctrlr };
|
||||
int rc;
|
||||
|
||||
nvme_ctrlr_destruct_async(ctrlr, &ctx);
|
||||
|
@ -1009,12 +1009,21 @@ struct spdk_nvme_probe_ctx {
|
||||
|
||||
typedef void (*nvme_ctrlr_detach_cb)(struct spdk_nvme_ctrlr *ctrlr);
|
||||
|
||||
enum nvme_ctrlr_detach_state {
|
||||
NVME_CTRLR_DETACH_SET_CC,
|
||||
NVME_CTRLR_DETACH_CHECK_CSTS,
|
||||
NVME_CTRLR_DETACH_GET_CSTS,
|
||||
NVME_CTRLR_DETACH_GET_CSTS_DONE,
|
||||
};
|
||||
|
||||
struct nvme_ctrlr_detach_ctx {
|
||||
struct spdk_nvme_ctrlr *ctrlr;
|
||||
nvme_ctrlr_detach_cb cb_fn;
|
||||
uint64_t shutdown_start_tsc;
|
||||
uint32_t shutdown_timeout_ms;
|
||||
bool shutdown_complete;
|
||||
enum nvme_ctrlr_detach_state state;
|
||||
union spdk_nvme_csts_register csts;
|
||||
TAILQ_ENTRY(nvme_ctrlr_detach_ctx) link;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user