From 5fba455d3ec67f5fdfa41b5150b360e728b6f9a6 Mon Sep 17 00:00:00 2001 From: sunshihao520 Date: Wed, 20 Jan 2021 14:53:12 +0800 Subject: [PATCH] lib/nvme: add two async API for Directive Send and Directive Receive. Add two async API for Directive Send and Directive Receive. spdk_nvme_ctrlr_cmd_directive_send; spdk_nvme_ctrlr_cmd_directive_receive; Signed-off-by: sunshihao Change-Id: Icb6974f74902df1512a5ffa9835188132634291b Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/5803 Community-CI: Broadcom CI Reviewed-by: Shuhei Matsumoto Reviewed-by: Jim Harris Tested-by: SPDK CI Jenkins --- CHANGELOG.md | 3 + include/spdk/nvme.h | 56 +++++++++++++++++++ lib/nvme/nvme_ctrlr.c | 4 ++ lib/nvme/nvme_ctrlr_cmd.c | 56 +++++++++++++++++++ lib/nvme/spdk_nvme.map | 2 + .../lib/nvme/nvme_ctrlr.c/nvme_ctrlr_ut.c | 18 ++++++ .../nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c | 41 ++++++++++++++ 7 files changed, 180 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1f8fa562c9..7b05c91eb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -42,6 +42,9 @@ Updated DPDK submodule to DPDK 20.11. Directives support was added to the NVMe driver. +Two async APIs 'spdk_nvme_ctrlr_cmd_directive_receive' and 'spdk_nvme_ctrlr_cmd_directive_send' +are added for Directive Send and Directive Receive command, respectively. + Added a new function `spdk_nvme_ctrlr_reset_subsystem` to perform a NVMe subsystem reset. Note: The NVMf target does not support the subsystem reset yet. Add a new function 'spdk_nvme_bytes_to_numd' to transfer bytes to number of diff --git a/include/spdk/nvme.h b/include/spdk/nvme.h index 043befb674..48b4cde213 100644 --- a/include/spdk/nvme.h +++ b/include/spdk/nvme.h @@ -1912,6 +1912,62 @@ int spdk_nvme_ctrlr_security_receive(struct spdk_nvme_ctrlr *ctrlr, uint8_t secp int spdk_nvme_ctrlr_security_send(struct spdk_nvme_ctrlr *ctrlr, uint8_t secp, uint16_t spsp, uint8_t nssf, void *payload, size_t size); +/** + * Receive data related to a specific Directive Type from the controller. + * + * This function is thread safe and can be called at any point after spdk_nvme_probe(). + * + * Call spdk_nvme_ctrlr_process_admin_completions() to poll for completion of + * commands submitted through this function. + * + * \param ctrlr NVMe controller to use for directive receive command submission. + * \param nsid Specific Namespace Identifier. + * \param doper Directive Operation defined in nvme_spec.h. + * \param dtype Directive Type defined in nvme_spec.h. + * \param dspec Directive Specific defined in nvme_spec.h. + * \param payload The pointer to the payload buffer. + * \param payload_size The size of payload buffer. + * \param cdw12 Command dword 12. + * \param cdw13 Command dword 13. + * \param cb_fn Callback function to invoke when the command has been completed. + * \param cb_arg Argument to pass to the callback function. + * + * \return 0 if successfully submitted, negated errno if resources could not be allocated + * for this request. + */ +int spdk_nvme_ctrlr_cmd_directive_receive(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg); + +/** + * Send data related to a specific Directive Type to the controller. + * + * This function is thread safe and can be called at any point after spdk_nvme_probe(). + * + * Call spdk_nvme_ctrlr_process_admin_completions() to poll for completion of + * commands submitted through this function. + * + * \param ctrlr NVMe controller to use for directive send command submission. + * \param nsid Specific Namespace Identifier. + * \param doper Directive Operation defined in nvme_spec.h. + * \param dtype Directive Type defined in nvme_spec.h. + * \param dspec Directive Specific defined in nvme_spec.h. + * \param payload The pointer to the payload buffer. + * \param payload_size The size of payload buffer. + * \param cdw12 Command dword 12. + * \param cdw13 Command dword 13. + * \param cb_fn Callback function to invoke when the command has been completed. + * \param cb_arg Argument to pass to the callback function. + * + * \return 0 if successfully submitted, negated errno if resources could not be allocated + * for this request. + */ +int spdk_nvme_ctrlr_cmd_directive_send(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg); + /** * Get supported flags of the controller. * diff --git a/lib/nvme/nvme_ctrlr.c b/lib/nvme/nvme_ctrlr.c index 9f03262d1c..1960b0a599 100644 --- a/lib/nvme/nvme_ctrlr.c +++ b/lib/nvme/nvme_ctrlr.c @@ -1570,6 +1570,10 @@ nvme_ctrlr_identify_done(void *arg, const struct spdk_nvme_cpl *cpl) ctrlr->flags |= SPDK_NVME_CTRLR_SECURITY_SEND_RECV_SUPPORTED; } + if (ctrlr->cdata.oacs.directives) { + ctrlr->flags |= SPDK_NVME_CTRLR_DIRECTIVES_SUPPORTED; + } + SPDK_DEBUGLOG(nvme, "fuses compare and write: %d\n", ctrlr->cdata.fuses.compare_and_write); if (ctrlr->cdata.fuses.compare_and_write) { ctrlr->flags |= SPDK_NVME_CTRLR_COMPARE_AND_WRITE_SUPPORTED; diff --git a/lib/nvme/nvme_ctrlr_cmd.c b/lib/nvme/nvme_ctrlr_cmd.c index 9412de099b..29d76f3330 100644 --- a/lib/nvme/nvme_ctrlr_cmd.c +++ b/lib/nvme/nvme_ctrlr_cmd.c @@ -965,3 +965,59 @@ nvme_ctrlr_cmd_sanitize(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, return rc; } + +static int +nvme_ctrlr_cmd_directive(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg, + uint16_t opc_type, bool host_to_ctrlr) +{ + struct nvme_request *req = NULL; + struct spdk_nvme_cmd *cmd = NULL; + int rc; + + nvme_robust_mutex_lock(&ctrlr->ctrlr_lock); + req = nvme_allocate_request_user_copy(ctrlr->adminq, payload, payload_size, + cb_fn, cb_arg, host_to_ctrlr); + if (req == NULL) { + nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock); + return -ENOMEM; + } + cmd = &req->cmd; + cmd->opc = opc_type; + cmd->nsid = nsid; + + cmd->cdw10 = (payload_size >> 2) - 1; + cmd->cdw11_bits.directive.doper = doper; + cmd->cdw11_bits.directive.dtype = dtype; + cmd->cdw11_bits.directive.dspec = dspec; + cmd->cdw12 = cdw12; + cmd->cdw13 = cdw13; + rc = nvme_ctrlr_submit_admin_request(ctrlr, req); + nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock); + + return rc; +} + +int +spdk_nvme_ctrlr_cmd_directive_send(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_ctrlr_cmd_directive(ctrlr, nsid, doper, dtype, dspec, + payload, payload_size, cdw12, cdw13, cb_fn, cb_arg, + SPDK_NVME_OPC_DIRECTIVE_SEND, true); +} + +int +spdk_nvme_ctrlr_cmd_directive_receive(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return nvme_ctrlr_cmd_directive(ctrlr, nsid, doper, dtype, dspec, + payload, payload_size, cdw12, cdw13, cb_fn, cb_arg, + SPDK_NVME_OPC_DIRECTIVE_RECEIVE, false); +} diff --git a/lib/nvme/spdk_nvme.map b/lib/nvme/spdk_nvme.map index 03215e4fcd..2ddf47eca9 100644 --- a/lib/nvme/spdk_nvme.map +++ b/lib/nvme/spdk_nvme.map @@ -74,6 +74,8 @@ spdk_nvme_ctrlr_cmd_security_send; spdk_nvme_ctrlr_security_receive; spdk_nvme_ctrlr_security_send; + spdk_nvme_ctrlr_cmd_directive_receive; + spdk_nvme_ctrlr_cmd_directive_send; spdk_nvme_ctrlr_get_flags; spdk_nvme_ctrlr_attach_ns; spdk_nvme_ctrlr_detach_ns; 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 aa1f2e90f7..3e2321d806 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 @@ -439,6 +439,24 @@ nvme_ctrlr_cmd_format(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, struct spdk_ return 0; } +int +spdk_nvme_ctrlr_cmd_directive_send(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return 0; +} + +int +spdk_nvme_ctrlr_cmd_directive_receive(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid, + uint32_t doper, uint32_t dtype, uint32_t dspec, + void *payload, uint32_t payload_size, uint32_t cdw12, + uint32_t cdw13, spdk_nvme_cmd_cb cb_fn, void *cb_arg) +{ + return 0; +} + int nvme_ctrlr_cmd_fw_commit(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_fw_commit *fw_commit, spdk_nvme_cmd_cb cb_fn, void *cb_arg) diff --git a/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c b/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c index d613d703d9..78371e74e2 100644 --- a/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c +++ b/test/unit/lib/nvme/nvme_ctrlr_cmd.c/nvme_ctrlr_cmd_ut.c @@ -61,6 +61,7 @@ uint64_t PRP_ENTRY_2 = 4096; uint32_t format_nvme_nsid = 1; uint32_t sanitize_nvme_nsid = 1; uint32_t expected_host_id_size = 0xFF; +uint32_t directive_nsid = 1; uint32_t expected_feature_ns = 2; uint32_t expected_feature_cdw10 = SPDK_NVME_FEAT_LBA_RANGE_TYPE; @@ -325,6 +326,18 @@ static void verify_nvme_sanitize(struct nvme_request *req) CU_ASSERT(req->cmd.nsid == sanitize_nvme_nsid); } +static void verify_directive_receive(struct nvme_request *req) +{ + CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_DIRECTIVE_RECEIVE); + CU_ASSERT(req->cmd.nsid == directive_nsid); +} + +static void verify_directive_send(struct nvme_request *req) +{ + CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_DIRECTIVE_SEND); + CU_ASSERT(req->cmd.nsid == directive_nsid); +} + struct nvme_request * nvme_allocate_request_user_copy(struct spdk_nvme_qpair *qpair, void *buffer, uint32_t payload_size, spdk_nvme_cmd_cb cb_fn, void *cb_arg, bool host_to_controller) @@ -723,6 +736,33 @@ test_sanitize(void) } +static void +test_directive_receive(void) +{ + DECLARE_AND_CONSTRUCT_CTRLR(); + verify_fn = verify_directive_receive; + + spdk_nvme_ctrlr_cmd_directive_receive(&ctrlr, directive_nsid, 0, 0, 0, NULL, 0, + 0, 0, NULL, NULL); +} + +static void +test_directive_send(void) +{ + DECLARE_AND_CONSTRUCT_CTRLR(); + verify_fn = verify_directive_send; + + spdk_nvme_ctrlr_cmd_directive_send(&ctrlr, directive_nsid, 0, 0, 0, NULL, 0, + 0, 0, NULL, NULL); +} + +static void +test_directive(void) +{ + test_directive_receive(); + test_directive_send(); +} + int main(int argc, char **argv) { CU_pSuite suite = NULL; @@ -752,6 +792,7 @@ int main(int argc, char **argv) CU_ADD_TEST(suite, test_fw_commit); CU_ADD_TEST(suite, test_fw_image_download); CU_ADD_TEST(suite, test_sanitize); + CU_ADD_TEST(suite, test_directive); CU_basic_set_mode(CU_BRM_VERBOSE); CU_basic_run_tests();