Commit e39172e7 authored by Pawel Baldysiak's avatar Pawel Baldysiak Committed by Tomasz Zawadzki
Browse files

nvmf_tgt: Add passthru handlers for firmware ops



Add custom handler for fw commit/download.
It is turned off by default, can be turned on by RPC.
It uses already existing generic passthru handler,
which makes sure that ctrlr-scope admin cmds are passthru
only for subsystem with single namespace.

Add handlers for both OPCs as one param and one handler,
since no scenario would require only one of this operation
handled as passthru.

Change-Id: I6a80cadffb860448f577a15499903962aa3a76e0
Signed-off-by: default avatarPawel Baldysiak <pawel.baldysiak@dell.com>
Reviewed-on: https://review.spdk.io/c/spdk/spdk/+/26131


Reviewed-by: default avatarAleksey Marchuk <alexeymar@nvidia.com>
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK Automated Test System <spdkbot@gmail.com>
Reviewed-by: default avatarJim Harris <jim.harris@nvidia.com>
parent 288de12a
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8592,6 +8592,7 @@ have been initialized.
 get_set_features   | Optional   | bool   | If true, enables passthru get/set_feature OPC handlers for underlying NVMe drive
 sanitize           | Optional   | bool   | If true, enables passthru sanitize OPC handlers for underlying NVMe drive
 security_send_recv | Optional   | bool   | If true, enables passthru security send/recieve OPC handlers for underlying NVMe drive
 fw_update          | Optional   | bool   | If true, enables passthru firmware download/commit OPC handlers for underlying NVMe drive
 vendor_specific    | Optional   | bool   | If true, enables passthru command handlers for underlying NVMe drive for vendor specific cmds (OPCs: 0xC0-0xFF)

#### Example
+13 −0
Original line number Diff line number Diff line
@@ -434,3 +434,16 @@ affects the other, since the whole bdev would be removed from and added back to
If a bdev is of type bdev_nvme and this underlying NVMe namespace is part of an NVM subsystem containing multiple namespaces,
then all bdevs associated with that underlying subsystem will be destroyed and re-added,
even if they are in a separate NVMe-oF subsystem that wasn't being reset. Beware of side effects.

## NVMe firmware update

NVMe firmware update process involves use of two admin commands: firmware download and firmware commit.
FW download is used only to get the FW image to the drive, then FW commit is used to tell the drive to:

1. store the FW image in particular firmware slot
2. store and activate the image after controller reset (or NSSR)
3. store and activate immediately without any reset (if NVMe drive supports that)

Drive is never unregistered from the system after FW commit.
User needs to trigger Reset/NSSR separately (in case of second option).
Please refer to firmware commit/firmware download admin command section of NVMe spec for further details.
+1 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ struct spdk_nvmf_admin_passthru_conf {
	bool get_set_features;
	bool sanitize;
	bool security_send_recv;
	bool fw_update;
	bool vendor_specific;
};

+1 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ static const struct spdk_json_object_decoder admin_passthru_decoder[] = {
	{"get_set_features", offsetof(struct spdk_nvmf_admin_passthru_conf, get_set_features), spdk_json_decode_bool, true},
	{"sanitize", offsetof(struct spdk_nvmf_admin_passthru_conf, sanitize), spdk_json_decode_bool, true},
	{"security_send_recv", offsetof(struct spdk_nvmf_admin_passthru_conf, security_send_recv), spdk_json_decode_bool, true},
	{"fw_update", offsetof(struct spdk_nvmf_admin_passthru_conf, fw_update), spdk_json_decode_bool, true},
	{"vendor_specific", offsetof(struct spdk_nvmf_admin_passthru_conf, vendor_specific), spdk_json_decode_bool, true},
};

+21 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ struct spdk_nvmf_tgt_conf g_spdk_nvmf_tgt_conf = {
	.admin_passthru.get_set_features = false,
	.admin_passthru.sanitize = false,
	.admin_passthru.security_send_recv = false,
	.admin_passthru.fw_update = false,
	.admin_passthru.vendor_specific = false
};

@@ -426,6 +427,12 @@ fixup_get_cmds_and_effects_log_page(struct spdk_nvmf_request *req)
		nvmf_log_data.admin_cmds_supported[SPDK_NVME_OPC_SECURITY_RECEIVE] =
			nvme_log_data.admin_cmds_supported[SPDK_NVME_OPC_SECURITY_RECEIVE];
	}
	if (g_spdk_nvmf_tgt_conf.admin_passthru.fw_update) {
		nvmf_log_data.admin_cmds_supported[SPDK_NVME_OPC_FIRMWARE_COMMIT] =
			nvme_log_data.admin_cmds_supported[SPDK_NVME_OPC_FIRMWARE_COMMIT];
		nvmf_log_data.admin_cmds_supported[SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD] =
			nvme_log_data.admin_cmds_supported[SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD];
	}

	/* Copy the fixed SPDK struct to the request */
	spdk_nvmf_request_copy_from_buf(req, (uint8_t *) &nvmf_log_data + offset, datalen);
@@ -560,6 +567,12 @@ fixup_identify_ctrlr(struct spdk_nvmf_request *req)
	if (g_spdk_nvmf_tgt_conf.admin_passthru.security_send_recv) {
		nvmf_cdata.oacs.security = nvme_cdata.oacs.security;
	}
	if (g_spdk_nvmf_tgt_conf.admin_passthru.fw_update) {
		nvmf_cdata.oacs.firmware = nvme_cdata.oacs.firmware;
		nvmf_cdata.frmw = nvme_cdata.frmw;
		nvmf_cdata.fwug = nvme_cdata.fwug;
		nvmf_cdata.mtfa = nvme_cdata.mtfa;
	}

	/* Copy the fixed up data back to the response */
	spdk_nvmf_request_copy_from_buf(req, &nvmf_cdata, datalen);
@@ -718,6 +731,12 @@ nvmf_tgt_advance_state(void)
				spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_SECURITY_SEND, nvmf_custom_admin_no_cb_hdlr);
				spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_SECURITY_RECEIVE, nvmf_custom_admin_no_cb_hdlr);
			}
			if (g_spdk_nvmf_tgt_conf.admin_passthru.fw_update) {
				SPDK_NOTICELOG("Custom firmware update commands handlers enabled\n");
				spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_FIRMWARE_COMMIT, nvmf_custom_admin_no_cb_hdlr);
				spdk_nvmf_set_custom_admin_cmd_hdlr(SPDK_NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD,
								    nvmf_custom_admin_no_cb_hdlr);
			}
			if (g_spdk_nvmf_tgt_conf.admin_passthru.vendor_specific) {
				int i;
				SPDK_NOTICELOG("Custom vendor specific commands handlers enabled\n");
@@ -846,6 +865,8 @@ nvmf_subsystem_write_config_json(struct spdk_json_write_ctx *w)
				   g_spdk_nvmf_tgt_conf.admin_passthru.sanitize);
	spdk_json_write_named_bool(w, "security_send_recv",
				   g_spdk_nvmf_tgt_conf.admin_passthru.security_send_recv);
	spdk_json_write_named_bool(w, "fw_update",
				   g_spdk_nvmf_tgt_conf.admin_passthru.fw_update);
	spdk_json_write_named_bool(w, "vendor_specific",
				   g_spdk_nvmf_tgt_conf.admin_passthru.vendor_specific);
	spdk_json_write_object_end(w);
Loading