Commit b3497d5d authored by Jakub Radtke's avatar Jakub Radtke Committed by Jim Harris
Browse files

nvme: add Get/Set Feature wrappers with NSID



Some features are per namespace and require a namespace ID; the existing
get/set feature functions do not allow passing NSID, so add new API
functions that do:
* spdk_nvme_ctrlr_cmd_get_feature_ns
* spdk_nvme_ctrlr_cmd_set_feature_ns

Change-Id: Ia7dc96e57badf1a56489785fb288493592b58b80
Signed-off-by: default avatarJakub Radtke <jakub.radtke@intel.com>
Reviewed-on: https://review.gerrithub.io/414706


Tested-by: default avatarSPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent caac0ed9
Loading
Loading
Loading
Loading
+56 −0
Original line number Diff line number Diff line
@@ -876,6 +876,62 @@ int spdk_nvme_ctrlr_cmd_get_feature(struct spdk_nvme_ctrlr *ctrlr,
				    void *payload, uint32_t payload_size,
				    spdk_nvme_cmd_cb cb_fn, void *cb_arg);

/**
 * \brief Get specific feature from given NVMe controller.
 *
 * \param ctrlr NVMe controller to query.
 * \param feature The feature identifier.
 * \param cdw11 as defined by the specification for this command.
 * \param payload The pointer to the payload buffer.
 * \param payload_size The size of payload buffer.
 * \param cb_fn Callback function to invoke when the feature has been retrieved.
 * \param cb_arg Argument to pass to the callback function.
 * \param ns_is The namespace identifier.
 *
 * \return 0 if successfully submitted, ENOMEM if resources could not be allocated
 * for this request
 *
 * This function is thread safe and can be called at any point while the controller
 * is attached to the SPDK NVMe driver.
 *
 * Call \ref spdk_nvme_ctrlr_process_admin_completions() to poll for completion
 * of commands submitted through this function.
 *
 * \sa spdk_nvme_ctrlr_cmd_set_feature_ns()
 */
int spdk_nvme_ctrlr_cmd_get_feature_ns(struct spdk_nvme_ctrlr *ctrlr, uint8_t feature,
				       uint32_t cdw11, void *payload, uint32_t payload_size,
				       spdk_nvme_cmd_cb cb_fn, void *cb_arg, uint32_t ns_id);

/**
 * \brief Set specific feature for the given NVMe controller and namespace ID.
 *
 * \param ctrlr NVMe controller to manipulate.
 * \param feature The feature identifier.
 * \param cdw11 as defined by the specification for this command.
 * \param cdw12 as defined by the specification for this command.
 * \param payload The pointer to the payload buffer.
 * \param payload_size The size of payload buffer.
 * \param cb_fn Callback function to invoke when the feature has been set.
 * \param cb_arg Argument to pass to the callback function.
 * \param ns_is The namespace identifier.
 *
 * \return 0 if successfully submitted, ENOMEM if resources could not be allocated
 * for this request.
 *
 * This function is thread safe and can be called at any point while the controller
 * is attached to the SPDK NVMe driver.
 *
 * Call \ref spdk_nvme_ctrlr_process_admin_completions() to poll for completion
 * of commands submitted through this function.
 *
 * \sa spdk_nvme_ctrlr_cmd_get_feature_ns()
 */
int spdk_nvme_ctrlr_cmd_set_feature_ns(struct spdk_nvme_ctrlr *ctrlr, uint8_t feature,
				       uint32_t cdw11, uint32_t cdw12, void *payload,
				       uint32_t payload_size, spdk_nvme_cmd_cb cb_fn,
				       void *cb_arg, uint32_t ns_id);

/**
 * \brief Attach the specified namespace to controllers.
 *
+60 −0
Original line number Diff line number Diff line
@@ -340,6 +340,66 @@ spdk_nvme_ctrlr_cmd_get_feature(struct spdk_nvme_ctrlr *ctrlr, uint8_t feature,
	return rc;
}

int
spdk_nvme_ctrlr_cmd_get_feature_ns(struct spdk_nvme_ctrlr *ctrlr, uint8_t feature,
				   uint32_t cdw11, void *payload,
				   uint32_t payload_size, spdk_nvme_cmd_cb cb_fn,
				   void *cb_arg, uint32_t ns_id)
{
	struct nvme_request *req;
	struct spdk_nvme_cmd *cmd;
	int rc;

	nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
	req = nvme_allocate_request_user_copy(ctrlr->adminq, payload, payload_size, cb_fn, cb_arg,
					      false);
	if (req == NULL) {
		nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
		return -ENOMEM;
	}

	cmd = &req->cmd;
	cmd->opc = SPDK_NVME_OPC_GET_FEATURES;
	cmd->cdw10 = feature;
	cmd->cdw11 = cdw11;
	cmd->nsid = ns_id;

	rc = nvme_ctrlr_submit_admin_request(ctrlr, req);
	nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);

	return rc;
}

int spdk_nvme_ctrlr_cmd_set_feature_ns(struct spdk_nvme_ctrlr *ctrlr, uint8_t feature,
				       uint32_t cdw11, uint32_t cdw12, void *payload,
				       uint32_t payload_size, spdk_nvme_cmd_cb cb_fn,
				       void *cb_arg, uint32_t ns_id)
{
	struct nvme_request *req;
	struct spdk_nvme_cmd *cmd;
	int rc;

	nvme_robust_mutex_lock(&ctrlr->ctrlr_lock);
	req = nvme_allocate_request_user_copy(ctrlr->adminq, payload, payload_size, cb_fn, cb_arg,
					      true);
	if (req == NULL) {
		nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
		return -ENOMEM;
	}

	cmd = &req->cmd;
	cmd->opc = SPDK_NVME_OPC_SET_FEATURES;
	cmd->cdw10 = feature;
	cmd->cdw11 = cdw11;
	cmd->cdw12 = cdw12;
	cmd->nsid = ns_id;

	rc = nvme_ctrlr_submit_admin_request(ctrlr, req);
	nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);

	return rc;
}

int
nvme_ctrlr_cmd_set_num_queues(struct spdk_nvme_ctrlr *ctrlr,
			      uint32_t num_queues, spdk_nvme_cmd_cb cb_fn, void *cb_arg)
+47 −0
Original line number Diff line number Diff line
@@ -56,6 +56,11 @@ uint16_t abort_sqid = 1;
uint32_t namespace_management_nsid = 1;
uint32_t format_nvme_nsid = 1;

uint32_t expected_feature_ns = 2;
uint32_t expected_feature_cdw10 = SPDK_NVME_FEAT_LBA_RANGE_TYPE;
uint32_t expected_feature_cdw11 = 1;
uint32_t expected_feature_cdw12 = 1;

typedef void (*verify_request_fn_t)(struct nvme_request *req);
verify_request_fn_t verify_fn;

@@ -103,6 +108,15 @@ static void verify_set_feature_cmd(struct nvme_request *req)
	CU_ASSERT(req->cmd.cdw12 == feature_cdw12);
}

static void verify_set_feature_ns_cmd(struct nvme_request *req)
{
	CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_SET_FEATURES);
	CU_ASSERT(req->cmd.cdw10 == expected_feature_cdw10);
	CU_ASSERT(req->cmd.cdw11 == expected_feature_cdw11);
	CU_ASSERT(req->cmd.cdw12 == expected_feature_cdw12);
	CU_ASSERT(req->cmd.nsid == expected_feature_ns);
}

static void verify_get_feature_cmd(struct nvme_request *req)
{
	CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_FEATURES);
@@ -110,6 +124,14 @@ static void verify_get_feature_cmd(struct nvme_request *req)
	CU_ASSERT(req->cmd.cdw11 == get_feature_cdw11);
}

static void verify_get_feature_ns_cmd(struct nvme_request *req)
{
	CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_GET_FEATURES);
	CU_ASSERT(req->cmd.cdw10 == expected_feature_cdw10);
	CU_ASSERT(req->cmd.cdw11 == expected_feature_cdw11);
	CU_ASSERT(req->cmd.nsid == expected_feature_ns);
}

static void verify_abort_cmd(struct nvme_request *req)
{
	CU_ASSERT(req->cmd.opc == SPDK_NVME_OPC_ABORT);
@@ -423,6 +445,29 @@ test_set_feature_cmd(void)
	spdk_nvme_ctrlr_cmd_set_feature(&ctrlr, feature, feature_cdw11, feature_cdw12, NULL, 0, NULL, NULL);
}

static void
test_get_feature_ns_cmd(void)
{
	DECLARE_AND_CONSTRUCT_CTRLR();

	verify_fn = verify_get_feature_ns_cmd;

	spdk_nvme_ctrlr_cmd_get_feature_ns(&ctrlr, expected_feature_cdw10,
					   expected_feature_cdw11, NULL, 0,
					   NULL, NULL, expected_feature_ns);
}

static void
test_set_feature_ns_cmd(void)
{
	DECLARE_AND_CONSTRUCT_CTRLR();

	verify_fn = verify_set_feature_ns_cmd;

	spdk_nvme_ctrlr_cmd_set_feature_ns(&ctrlr, expected_feature_cdw10,
					   expected_feature_cdw11, expected_feature_cdw12,
					   NULL, 0, NULL, NULL, expected_feature_ns);
}

static void
test_get_feature_cmd(void)
@@ -574,7 +619,9 @@ int main(int argc, char **argv)
	if (
		CU_add_test(suite, "test ctrlr cmd get_log_pages", test_get_log_pages) == NULL
		|| CU_add_test(suite, "test ctrlr cmd set_feature", test_set_feature_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd set_feature_ns", test_set_feature_ns_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd get_feature", test_get_feature_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd get_feature_ns", test_get_feature_ns_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd abort_cmd", test_abort_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd io_raw_cmd", test_io_raw_cmd) == NULL
		|| CU_add_test(suite, "test ctrlr cmd io_raw_cmd_with_md", test_io_raw_cmd_with_md) == NULL