lib/nvme: add hw support for fused operations

Change-Id: I2a184a2d60f18439947afa2d4855d51b92ed282e
Signed-off-by: Tomasz Kulasek <tomaszx.kulasek@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/476137
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Paul Luse <paul.e.luse@intel.com>
This commit is contained in:
Tomasz Kulasek 2019-11-27 07:35:18 -05:00 committed by Tomasz Zawadzki
parent 8209c8cfa0
commit 1c5d980300
3 changed files with 86 additions and 3 deletions

View File

@ -464,6 +464,16 @@ enum spdk_nvme_cc_ams {
SPDK_NVME_CC_AMS_VS = 0x7, /**< vendor specific */
};
/**
* Fused Operation
*/
enum spdk_nvme_cmd_fuse {
SPDK_NVMF_CMD_FUSE_NONE = 0x0, /**< normal operation */
SPDK_NVME_CMD_FUSE_FIRST = 0x1, /**< fused operation, first command */
SPDK_NVME_CMD_FUSE_SECOND = 0x2, /**< fused operation, second command */
/* 0x3 - reserved */
};
/**
* Data used by Set Features/Get Features \ref SPDK_NVME_FEAT_ARBITRATION
*/
@ -2821,6 +2831,10 @@ SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fw_commit) == 4, "Incorrect size");
(cpl)->status.sc == SPDK_NVME_SC_APPLICATION_TAG_CHECK_ERROR || \
(cpl)->status.sc == SPDK_NVME_SC_REFERENCE_TAG_CHECK_ERROR))
/** Set fused operation */
#define SPDK_NVME_IO_FLAGS_FUSE_FIRST (1U << 0)
#define SPDK_NVME_IO_FLAGS_FUSE_SECOND (1U << 1)
#define SPDK_NVME_IO_FLAGS_FUSE_MASK (3U << 0)
/** Enable protection information checking of the Logical Block Reference Tag field */
#define SPDK_NVME_IO_FLAGS_PRCHK_REFTAG (1U << 26)
/** Enable protection information checking of the Application Tag field */
@ -2833,7 +2847,8 @@ SPDK_STATIC_ASSERT(sizeof(struct spdk_nvme_fw_commit) == 4, "Incorrect size");
#define SPDK_NVME_IO_FLAGS_LIMITED_RETRY (1U << 31)
/** Mask of valid io flags mask */
#define SPDK_NVME_IO_FLAGS_VALID_MASK 0xFFFF0000
#define SPDK_NVME_IO_FLAGS_VALID_MASK 0xFFFF0003
#define SPDK_NVME_IO_FLAGS_CDW12_MASK 0xFFFF0000
#ifdef __cplusplus
}

View File

@ -165,8 +165,10 @@ _nvme_ns_cmd_setup_request(struct spdk_nvme_ns *ns, struct nvme_request *req,
}
}
cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
cmd->cdw12 = lba_count - 1;
cmd->cdw12 |= io_flags;
cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
cmd->cdw15 = apptag_mask;
cmd->cdw15 = (cmd->cdw15 << 16 | apptag);
@ -828,7 +830,8 @@ spdk_nvme_ns_cmd_write_zeroes(struct spdk_nvme_ns *ns, struct spdk_nvme_qpair *q
tmp_lba = (uint64_t *)&cmd->cdw10;
*tmp_lba = lba;
cmd->cdw12 = lba_count - 1;
cmd->cdw12 |= io_flags;
cmd->fuse = (io_flags & SPDK_NVME_IO_FLAGS_FUSE_MASK);
cmd->cdw12 |= (io_flags & SPDK_NVME_IO_FLAGS_CDW12_MASK);
return nvme_qpair_submit_request(qpair, req);
}

View File

@ -746,6 +746,53 @@ test_nvme_ns_cmd_comparev(void)
cleanup_after_test(&qpair);
}
static void
test_nvme_ns_cmd_compare_and_write(void)
{
struct spdk_nvme_ns ns;
struct spdk_nvme_ctrlr ctrlr;
struct spdk_nvme_qpair qpair;
int rc = 0;
uint64_t lba = 0x1000;
uint32_t lba_count = 256;
uint64_t cmd_lba;
uint32_t cmd_lba_count;
uint32_t sector_size = 512;
prepare_for_test(&ns, &ctrlr, &qpair, sector_size, 0, 128 * 1024, 0, false);
rc = spdk_nvme_ns_cmd_compare(&ns, &qpair, NULL, lba, lba_count, NULL, NULL,
SPDK_NVME_IO_FLAGS_FUSE_FIRST);
SPDK_CU_ASSERT_FATAL(rc == 0);
SPDK_CU_ASSERT_FATAL(g_request != NULL);
CU_ASSERT(g_request->cmd.opc == SPDK_NVME_OPC_COMPARE);
CU_ASSERT(g_request->cmd.fuse == SPDK_NVME_CMD_FUSE_FIRST);
CU_ASSERT(g_request->cmd.nsid == ns.id);
nvme_cmd_interpret_rw(&g_request->cmd, &cmd_lba, &cmd_lba_count);
CU_ASSERT_EQUAL(cmd_lba, lba);
CU_ASSERT_EQUAL(cmd_lba_count, lba_count);
nvme_free_request(g_request);
rc = spdk_nvme_ns_cmd_write(&ns, &qpair, NULL, lba, lba_count, NULL, NULL,
SPDK_NVME_IO_FLAGS_FUSE_SECOND);
SPDK_CU_ASSERT_FATAL(rc == 0);
SPDK_CU_ASSERT_FATAL(g_request != NULL);
CU_ASSERT(g_request->cmd.opc == SPDK_NVME_OPC_WRITE);
CU_ASSERT(g_request->cmd.fuse == SPDK_NVME_CMD_FUSE_SECOND);
CU_ASSERT(g_request->cmd.nsid == ns.id);
nvme_cmd_interpret_rw(&g_request->cmd, &cmd_lba, &cmd_lba_count);
CU_ASSERT_EQUAL(cmd_lba, lba);
CU_ASSERT_EQUAL(cmd_lba_count, lba_count);
nvme_free_request(g_request);
cleanup_after_test(&qpair);
}
static void
test_io_flags(void)
{
@ -755,6 +802,8 @@ test_io_flags(void)
void *payload;
uint64_t lba;
uint32_t lba_count;
uint64_t cmd_lba;
uint32_t cmd_lba_count;
int rc;
prepare_for_test(&ns, &ctrlr, &qpair, 512, 0, 128 * 1024, 128 * 1024, false);
@ -778,6 +827,21 @@ test_io_flags(void)
CU_ASSERT((g_request->cmd.cdw12 & SPDK_NVME_IO_FLAGS_LIMITED_RETRY) != 0);
nvme_free_request(g_request);
rc = spdk_nvme_ns_cmd_write(&ns, &qpair, payload, lba, lba_count, NULL, NULL,
SPDK_NVME_IO_FLAGS_VALID_MASK);
SPDK_CU_ASSERT_FATAL(rc == 0);
SPDK_CU_ASSERT_FATAL(g_request != NULL);
nvme_cmd_interpret_rw(&g_request->cmd, &cmd_lba, &cmd_lba_count);
CU_ASSERT_EQUAL(cmd_lba_count, lba_count);
CU_ASSERT_EQUAL(cmd_lba, lba);
CU_ASSERT_EQUAL(g_request->cmd.cdw12 & SPDK_NVME_IO_FLAGS_CDW12_MASK,
SPDK_NVME_IO_FLAGS_CDW12_MASK);
nvme_free_request(g_request);
rc = spdk_nvme_ns_cmd_write(&ns, &qpair, payload, lba, lba_count, NULL, NULL,
~SPDK_NVME_IO_FLAGS_VALID_MASK);
CU_ASSERT(rc == -EINVAL);
free(payload);
cleanup_after_test(&qpair);
}
@ -1447,6 +1511,7 @@ int main(int argc, char **argv)
|| CU_add_test(suite, "nvme_ns_cmd_writev", test_nvme_ns_cmd_writev) == NULL
|| CU_add_test(suite, "nvme_ns_cmd_write_with_md", test_nvme_ns_cmd_write_with_md) == NULL
|| CU_add_test(suite, "nvme_ns_cmd_comparev", test_nvme_ns_cmd_comparev) == NULL
|| CU_add_test(suite, "nvme_ns_cmd_compare_and_write", test_nvme_ns_cmd_compare_and_write) == NULL
|| CU_add_test(suite, "nvme_ns_cmd_compare_with_md", test_nvme_ns_cmd_compare_with_md) == NULL
) {
CU_cleanup_registry();