nvme: asynchronous register operations
This patch introduces asynchronous versions of the ctrlr_(get|set)_reg functions. Not all transports need to define them - for those that it doesn't make sense (e.g. PCIe), the transport layer will call the synchronous API and queue the callback to be executed during the next process_completions call. Signed-off-by: Konrad Sztyber <konrad.sztyber@intel.com> Change-Id: I2e78e72b5eba58340885381cb279f3c28e7995ec Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/8607 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Reviewed-by: Aleksey Marchuk <alexeymar@mellanox.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
e72453b39f
commit
1bea880598
@ -3804,6 +3804,15 @@ struct spdk_nvme_transport_poll_group;
|
|||||||
*/
|
*/
|
||||||
void spdk_nvme_cuse_update_namespaces(struct spdk_nvme_ctrlr *ctrlr);
|
void spdk_nvme_cuse_update_namespaces(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signature for callback invoked after completing a register read/write operation.
|
||||||
|
*
|
||||||
|
* \param ctx Context passed by the user.
|
||||||
|
* \param value Value of the register, undefined in case of a failure.
|
||||||
|
* \param cpl Completion queue entry that contains the status of the command.
|
||||||
|
*/
|
||||||
|
typedef void (*spdk_nvme_reg_cb)(void *ctx, uint64_t value, const struct spdk_nvme_cpl *cpl);
|
||||||
|
|
||||||
struct nvme_request;
|
struct nvme_request;
|
||||||
|
|
||||||
struct spdk_nvme_transport;
|
struct spdk_nvme_transport;
|
||||||
@ -3831,6 +3840,18 @@ struct spdk_nvme_transport_ops {
|
|||||||
|
|
||||||
int (*ctrlr_get_reg_8)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
int (*ctrlr_get_reg_8)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
||||||
|
|
||||||
|
int (*ctrlr_set_reg_4_async)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t value,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
int (*ctrlr_set_reg_8_async)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
int (*ctrlr_get_reg_4_async)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
|
int (*ctrlr_get_reg_8_async)(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
|
||||||
uint32_t (*ctrlr_get_max_xfer_size)(struct spdk_nvme_ctrlr *ctrlr);
|
uint32_t (*ctrlr_get_max_xfer_size)(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
|
|
||||||
uint16_t (*ctrlr_get_max_sges)(struct spdk_nvme_ctrlr *ctrlr);
|
uint16_t (*ctrlr_get_max_sges)(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
|
@ -3712,6 +3712,7 @@ nvme_ctrlr_construct(struct spdk_nvme_ctrlr *ctrlr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TAILQ_INIT(&ctrlr->active_procs);
|
TAILQ_INIT(&ctrlr->active_procs);
|
||||||
|
STAILQ_INIT(&ctrlr->register_operations);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -787,6 +787,13 @@ struct spdk_nvme_ctrlr_process {
|
|||||||
STAILQ_HEAD(, spdk_nvme_ctrlr_aer_completion_list) async_events;
|
STAILQ_HEAD(, spdk_nvme_ctrlr_aer_completion_list) async_events;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct nvme_register_completion {
|
||||||
|
struct spdk_nvme_cpl cpl;
|
||||||
|
uint64_t value;
|
||||||
|
spdk_nvme_reg_cb cb_fn;
|
||||||
|
void *cb_ctx;
|
||||||
|
STAILQ_ENTRY(nvme_register_completion) stailq;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* One of these per allocated PCI device.
|
* One of these per allocated PCI device.
|
||||||
@ -938,6 +945,9 @@ struct spdk_nvme_ctrlr {
|
|||||||
unsigned int fw_size_remaining;
|
unsigned int fw_size_remaining;
|
||||||
unsigned int fw_offset;
|
unsigned int fw_offset;
|
||||||
unsigned int fw_transfer_size;
|
unsigned int fw_transfer_size;
|
||||||
|
|
||||||
|
/* Completed register operations */
|
||||||
|
STAILQ_HEAD(, nvme_register_completion) register_operations;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spdk_nvme_probe_ctx {
|
struct spdk_nvme_probe_ctx {
|
||||||
@ -1392,6 +1402,14 @@ int nvme_transport_ctrlr_set_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offse
|
|||||||
int nvme_transport_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value);
|
int nvme_transport_ctrlr_set_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value);
|
||||||
int nvme_transport_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value);
|
int nvme_transport_ctrlr_get_reg_4(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t *value);
|
||||||
int nvme_transport_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
int nvme_transport_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t *value);
|
||||||
|
int nvme_transport_ctrlr_set_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
uint32_t value, spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
int nvme_transport_ctrlr_set_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
uint64_t value, spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
int nvme_transport_ctrlr_get_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
|
int nvme_transport_ctrlr_get_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg);
|
||||||
uint32_t nvme_transport_ctrlr_get_max_xfer_size(struct spdk_nvme_ctrlr *ctrlr);
|
uint32_t nvme_transport_ctrlr_get_max_xfer_size(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
uint16_t nvme_transport_ctrlr_get_max_sges(struct spdk_nvme_ctrlr *ctrlr);
|
uint16_t nvme_transport_ctrlr_get_max_sges(struct spdk_nvme_ctrlr *ctrlr);
|
||||||
struct spdk_nvme_qpair *nvme_transport_ctrlr_create_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
|
struct spdk_nvme_qpair *nvme_transport_ctrlr_create_io_qpair(struct spdk_nvme_ctrlr *ctrlr,
|
||||||
|
@ -689,6 +689,28 @@ nvme_qpair_resubmit_requests(struct spdk_nvme_qpair *qpair, uint32_t num_request
|
|||||||
_nvme_qpair_complete_abort_queued_reqs(qpair);
|
_nvme_qpair_complete_abort_queued_reqs(qpair);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
nvme_complete_register_operations(struct spdk_nvme_qpair *qpair)
|
||||||
|
{
|
||||||
|
struct nvme_register_completion *ctx;
|
||||||
|
struct spdk_nvme_ctrlr *ctrlr = qpair->ctrlr;
|
||||||
|
STAILQ_HEAD(, nvme_register_completion) operations;
|
||||||
|
|
||||||
|
STAILQ_INIT(&operations);
|
||||||
|
nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
|
||||||
|
STAILQ_SWAP(&ctrlr->register_operations, &operations, nvme_register_completion);
|
||||||
|
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
|
||||||
|
|
||||||
|
while (!STAILQ_EMPTY(&operations)) {
|
||||||
|
ctx = STAILQ_FIRST(&operations);
|
||||||
|
STAILQ_REMOVE_HEAD(&operations, stailq);
|
||||||
|
if (ctx->cb_fn != NULL) {
|
||||||
|
ctx->cb_fn(ctx->cb_ctx, ctx->value, &ctx->cpl);
|
||||||
|
}
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
|
spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_completions)
|
||||||
{
|
{
|
||||||
@ -750,6 +772,11 @@ spdk_nvme_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_
|
|||||||
nvme_qpair_resubmit_requests(qpair, ret);
|
nvme_qpair_resubmit_requests(qpair, ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Complete any pending register operations */
|
||||||
|
if (nvme_qpair_is_admin_queue(qpair)) {
|
||||||
|
nvme_complete_register_operations(qpair);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,6 +204,113 @@ nvme_transport_ctrlr_get_reg_8(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, u
|
|||||||
return transport->ops.ctrlr_get_reg_8(ctrlr, offset, value);
|
return transport->ops.ctrlr_get_reg_8(ctrlr, offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
nvme_queue_register_operation_completion(struct spdk_nvme_ctrlr *ctrlr, uint64_t value,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_ctx)
|
||||||
|
{
|
||||||
|
struct nvme_register_completion *ctx;
|
||||||
|
|
||||||
|
ctx = calloc(1, sizeof(*ctx));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->cpl.status.sct = SPDK_NVME_SCT_GENERIC;
|
||||||
|
ctx->cpl.status.sc = SPDK_NVME_SC_SUCCESS;
|
||||||
|
ctx->cb_fn = cb_fn;
|
||||||
|
ctx->cb_ctx = cb_ctx;
|
||||||
|
ctx->value = value;
|
||||||
|
|
||||||
|
nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
|
||||||
|
STAILQ_INSERT_TAIL(&ctrlr->register_operations, ctx, stailq);
|
||||||
|
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_transport_ctrlr_set_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint32_t value,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg)
|
||||||
|
{
|
||||||
|
const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert(transport != NULL);
|
||||||
|
if (transport->ops.ctrlr_set_reg_4_async == NULL) {
|
||||||
|
rc = transport->ops.ctrlr_set_reg_4(ctrlr, offset, value);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport->ops.ctrlr_set_reg_4_async(ctrlr, offset, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_transport_ctrlr_set_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset, uint64_t value,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg)
|
||||||
|
|
||||||
|
{
|
||||||
|
const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert(transport != NULL);
|
||||||
|
if (transport->ops.ctrlr_set_reg_8_async == NULL) {
|
||||||
|
rc = transport->ops.ctrlr_set_reg_8(ctrlr, offset, value);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport->ops.ctrlr_set_reg_8_async(ctrlr, offset, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_transport_ctrlr_get_reg_4_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg)
|
||||||
|
{
|
||||||
|
const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
|
||||||
|
uint32_t value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert(transport != NULL);
|
||||||
|
if (transport->ops.ctrlr_get_reg_4_async == NULL) {
|
||||||
|
rc = transport->ops.ctrlr_get_reg_4(ctrlr, offset, &value);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport->ops.ctrlr_get_reg_4_async(ctrlr, offset, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nvme_transport_ctrlr_get_reg_8_async(struct spdk_nvme_ctrlr *ctrlr, uint32_t offset,
|
||||||
|
spdk_nvme_reg_cb cb_fn, void *cb_arg)
|
||||||
|
{
|
||||||
|
const struct spdk_nvme_transport *transport = nvme_get_transport(ctrlr->trid.trstring);
|
||||||
|
uint64_t value;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
assert(transport != NULL);
|
||||||
|
if (transport->ops.ctrlr_get_reg_8_async == NULL) {
|
||||||
|
rc = transport->ops.ctrlr_get_reg_8(ctrlr, offset, &value);
|
||||||
|
if (rc != 0) {
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nvme_queue_register_operation_completion(ctrlr, value, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return transport->ops.ctrlr_get_reg_8_async(ctrlr, offset, cb_fn, cb_arg);
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
nvme_transport_ctrlr_get_max_xfer_size(struct spdk_nvme_ctrlr *ctrlr)
|
nvme_transport_ctrlr_get_max_xfer_size(struct spdk_nvme_ctrlr *ctrlr)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user