update_firmware: Allow option to download and enable firmware image.

Support both SPDK_NVME_FW_COMMIT_REPLACE_IMG and SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG.
Return code will specify if conventional reset is required.
For now, return error if subsystem reset is required.

Change-Id: I41a05675a210dd0bbf170517b32ee9e05da9a797
Signed-off-by: Isaac Otsiabah <iotsiabah@us.fujitsu.com>
Reviewed-on: https://review.gerrithub.io/367287
Tested-by: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Daniel Verkamp <daniel.verkamp@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
Isaac Otsiabah 2017-06-27 16:25:32 -07:00 committed by Jim Harris
parent da1c360de1
commit 6fb1ce422e
4 changed files with 47 additions and 14 deletions

View File

@ -771,6 +771,8 @@ update_firmware_image(void)
void *fw_image;
struct dev *ctrlr;
const struct spdk_nvme_ctrlr_data *cdata;
enum spdk_nvme_fw_commit_action commit_action;
struct spdk_nvme_status status;
ctrlr = get_controller();
if (ctrlr == NULL) {
@ -836,8 +838,12 @@ update_firmware_image(void)
return;
}
rc = spdk_nvme_ctrlr_update_firmware(ctrlr->ctrlr, fw_image, size, slot);
if (rc) {
commit_action = SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG;
rc = spdk_nvme_ctrlr_update_firmware(ctrlr->ctrlr, fw_image, size, slot, commit_action, &status);
if (rc == -ENXIO && status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC &&
status.sc == SPDK_NVME_SC_FIRMWARE_REQ_CONVENTIONAL_RESET) {
printf("conventional reset is needed to enable firmware !\n");
} else if (rc) {
printf("spdk_nvme_ctrlr_update_firmware failed\n");
} else {
printf("spdk_nvme_ctrlr_update_firmware success\n");

View File

@ -771,6 +771,8 @@ int spdk_nvme_ctrlr_format(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
* \param payload The data buffer for the firmware image.
* \param size The data size will be downloaded.
* \param slot The slot that the firmware image will be committed to.
* \param commit_action The action to perform when firmware is committed.
* \param completion_status output parameter. Contains the completion status of the firmware commit operation.
*
* \return 0 if successfully submitted, ENOMEM if resources could not be allocated for this request,
* -1 if the size is not multiple of 4.
@ -778,7 +780,8 @@ int spdk_nvme_ctrlr_format(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
* This function is thread safe and can be called at any point after spdk_nvme_attach().
*/
int spdk_nvme_ctrlr_update_firmware(struct spdk_nvme_ctrlr *ctrlr, void *payload, uint32_t size,
int slot);
int slot, enum spdk_nvme_fw_commit_action commit_action,
struct spdk_nvme_status *completion_status);
/**
* \brief Get the identify namespace data as defined by the NVMe specification.

View File

@ -1683,7 +1683,7 @@ spdk_nvme_ctrlr_format(struct spdk_nvme_ctrlr *ctrlr, uint32_t nsid,
int
spdk_nvme_ctrlr_update_firmware(struct spdk_nvme_ctrlr *ctrlr, void *payload, uint32_t size,
int slot)
int slot, enum spdk_nvme_fw_commit_action commit_action, struct spdk_nvme_status *completion_status)
{
struct spdk_nvme_fw_commit fw_commit;
struct nvme_completion_poll_status status;
@ -1693,11 +1693,24 @@ spdk_nvme_ctrlr_update_firmware(struct spdk_nvme_ctrlr *ctrlr, void *payload, ui
unsigned int transfer;
void *p;
if (!completion_status) {
return -EINVAL;
}
memset(completion_status, 0, sizeof(struct spdk_nvme_status));
if (size % 4) {
SPDK_ERRLOG("spdk_nvme_ctrlr_update_firmware invalid size!\n");
return -1;
}
/* Current support only for SPDK_NVME_FW_COMMIT_REPLACE_IMG
* and SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG
*/
if ((commit_action != SPDK_NVME_FW_COMMIT_REPLACE_IMG) &&
(commit_action != SPDK_NVME_FW_COMMIT_REPLACE_AND_ENABLE_IMG)) {
SPDK_ERRLOG("spdk_nvme_ctrlr_update_firmware invalid command!\n");
return -1;
}
/* Firmware download */
size_remaining = size;
offset = 0;
@ -1730,7 +1743,7 @@ spdk_nvme_ctrlr_update_firmware(struct spdk_nvme_ctrlr *ctrlr, void *payload, ui
/* Firmware commit */
memset(&fw_commit, 0, sizeof(struct spdk_nvme_fw_commit));
fw_commit.fs = slot;
fw_commit.ca = SPDK_NVME_FW_COMMIT_REPLACE_IMG;
fw_commit.ca = commit_action;
status.done = false;
@ -1744,10 +1757,19 @@ spdk_nvme_ctrlr_update_firmware(struct spdk_nvme_ctrlr *ctrlr, void *payload, ui
spdk_nvme_qpair_process_completions(ctrlr->adminq, 0);
nvme_robust_mutex_unlock(&ctrlr->ctrlr_lock);
}
memcpy(completion_status, &status.cpl.status, sizeof(struct spdk_nvme_status));
if (spdk_nvme_cpl_is_error(&status.cpl)) {
if (status.cpl.status.sct != SPDK_NVME_SCT_COMMAND_SPECIFIC ||
status.cpl.status.sc != SPDK_NVME_SC_FIRMWARE_REQ_NVM_RESET) {
if (status.cpl.status.sct == SPDK_NVME_SCT_COMMAND_SPECIFIC &&
status.cpl.status.sc == SPDK_NVME_SC_FIRMWARE_REQ_CONVENTIONAL_RESET) {
SPDK_NOTICELOG("firmware activation requires conventional reset to be performed. !\n");
} else {
SPDK_ERRLOG("nvme_ctrlr_cmd_fw_commit failed!\n");
}
return -ENXIO;
}
}
return spdk_nvme_ctrlr_reset(ctrlr);
}

View File

@ -1401,23 +1401,25 @@ test_spdk_nvme_ctrlr_update_firmware(void)
int point_payload = 1;
int slot = 0;
int ret = 0;
struct spdk_nvme_status status;
enum spdk_nvme_fw_commit_action commit_action = SPDK_NVME_FW_COMMIT_REPLACE_IMG;
/* Set invalid size check function return value */
set_size = 5;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -1);
/* When payload is NULL but set_size < min_page_size */
set_size = 4;
ctrlr.min_page_size = 5;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -1);
/* When payload not NULL but min_page_size is 0 */
set_size = 4;
ctrlr.min_page_size = 0;
payload = &point_payload;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -1);
/* Check firmware image download when payload not NULL and min_page_size not 0 , status.cpl value is 1 */
@ -1425,7 +1427,7 @@ test_spdk_nvme_ctrlr_update_firmware(void)
set_size = 4;
ctrlr.min_page_size = 5;
payload = &point_payload;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -ENXIO);
/* Check firmware image download and set status.cpl value is 0 */
@ -1433,7 +1435,7 @@ test_spdk_nvme_ctrlr_update_firmware(void)
set_size = 4;
ctrlr.min_page_size = 5;
payload = &point_payload;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -1);
/* Check firmware commit */
@ -1443,7 +1445,7 @@ test_spdk_nvme_ctrlr_update_firmware(void)
set_size = 4;
ctrlr.min_page_size = 5;
payload = &point_payload;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == -ENXIO);
/* Set size check firmware download and firmware commit */
@ -1453,7 +1455,7 @@ test_spdk_nvme_ctrlr_update_firmware(void)
set_size = 4;
ctrlr.min_page_size = 5;
payload = &point_payload;
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot);
ret = spdk_nvme_ctrlr_update_firmware(&ctrlr, payload, set_size, slot, commit_action, &status);
CU_ASSERT(ret == 0);
}