From: Tokunori Ikegami <ikegami.t@gmail.com>
Date: Thu, 9 Mar 2023 17:42:53 +0000 (+0900)
Subject: plugins/ocp: Add support for EOL/PLP failure mode feature
X-Git-Tag: v2.4~36
X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=7e86bd3acf153afffc2566f76dca1b3efdbb670e;p=users%2Fsagi%2Fnvme-cli.git

plugins/ocp: Add support for EOL/PLP failure mode feature

Signed-off-by: Tokunori Ikegami <ikegami.t@gmail.com>
---

diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c
index 6b166efe..59ced1cb 100644
--- a/plugins/ocp/ocp-nvme.c
+++ b/plugins/ocp/ocp-nvme.c
@@ -805,3 +805,140 @@ static int clear_fw_update_history(int argc, char **argv,
 {
 	return ocp_clear_fw_update_history(argc, argv, cmd, plugin);
 }
+
+static const char *eol_plp_failure_mode_to_string(__u8 mode)
+{
+	switch (mode) {
+	case 1:
+		return "Read only mode (ROM)";
+	case 2:
+		return "Write through mode (WTM)";
+	case 3:
+		return "Normal mode";
+	default:
+		break;
+	}
+
+	return "Reserved";
+}
+
+static int eol_plp_failure_mode_get(struct nvme_dev *dev, const __u32 nsid,
+				    const __u8 fid, __u8 sel)
+{
+	__u32 result;
+	int err;
+
+	struct nvme_get_features_args args = {
+		.args_size	= sizeof(args),
+		.fd		= dev_fd(dev),
+		.fid		= fid,
+		.nsid		= nsid,
+		.sel		= sel,
+		.cdw11		= 0,
+		.uuidx		= 0,
+		.data_len	= 0,
+		.data		= NULL,
+		.timeout	= NVME_DEFAULT_IOCTL_TIMEOUT,
+		.result		= &result,
+	};
+
+	err = nvme_get_features(&args);
+	if (!err) {
+		printf("End of Life Behavior (feature: %#0*x): %#0*x (%s: %s)\n",
+		       fid ? 4 : 2, fid, result ? 10 : 8, result,
+		       nvme_select_to_string(sel),
+		       eol_plp_failure_mode_to_string(result));
+		if (sel == NVME_GET_FEATURES_SEL_SUPPORTED)
+			nvme_show_select_result(result);
+	} else {
+		printf("Could not get feature: %#0*x.\n", fid ? 4 : 2, fid);
+	}
+
+	return err;
+}
+
+static int eol_plp_failure_mode_set(struct nvme_dev *dev, const __u32 nsid,
+				    const __u8 fid, __u8 mode, bool save)
+{
+	__u32 result;
+	int err;
+
+	struct nvme_set_features_args args = {
+		.args_size	= sizeof(args),
+		.fd		= dev_fd(dev),
+		.fid		= fid,
+		.nsid		= nsid,
+		.cdw11		= mode << 30,
+		.cdw12		= 0,
+		.save		= save,
+		.uuidx		= 0,
+		.cdw15		= 0,
+		.data_len	= 0,
+		.data		= NULL,
+		.timeout	= NVME_DEFAULT_IOCTL_TIMEOUT,
+		.result		= &result,
+	};
+
+	err = nvme_set_features(&args);
+	if (err > 0) {
+		nvme_show_status(err);
+	} else if (err < 0) {
+		perror("Define EOL/PLP failure mode");
+		fprintf(stderr, "Command failed while parsing.\n");
+	} else {
+		printf("Successfully set mode (feature: %#0*x): %#0*x (%s: %s).\n",
+		       fid ? 4 : 2, fid, mode ? 10 : 8, mode,
+		       save ? "Save" : "Not save",
+		       eol_plp_failure_mode_to_string(mode));
+	}
+
+	return err;
+}
+
+static int eol_plp_failure_mode(int argc, char **argv, struct command *cmd,
+				struct plugin *plugin)
+{
+	const char *desc = "Define EOL or PLP circuitry failure mode.\n"\
+			   "No argument prints current mode.";
+	const char *mode = "[0-3]: default/rom/wtm/normal";
+	const char *save = "Specifies that the controller shall save the attribute";
+	const char *sel = "[0-3,8]: current/default/saved/supported/changed";
+	const __u32 nsid = 0;
+	const __u8 fid = 0xc2;
+	struct nvme_dev *dev;
+	int err;
+
+	struct config {
+		__u8 mode;
+		bool save;
+		__u8 sel;
+	};
+
+	struct config cfg = {
+		.mode = 0,
+		.save = false,
+		.sel = 0,
+	};
+
+	OPT_ARGS(opts) = {
+		OPT_BYTE("mode", 'm', &cfg.mode, mode),
+		OPT_FLAG("save", 's', &cfg.save, save),
+		OPT_BYTE("sel", 'S', &cfg.sel, sel),
+		{NULL}
+	};
+
+	err = parse_and_open(&dev, argc, argv, desc, opts);
+
+	if (err)
+		return err;
+
+	if (opts[0].seen)
+		err = eol_plp_failure_mode_set(dev, nsid, fid, cfg.mode,
+					       cfg.save);
+	else
+		err = eol_plp_failure_mode_get(dev, nsid, fid, cfg.sel);
+
+	dev_close(dev);
+
+	return err;
+}
diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h
index 16ac750c..fcc54299 100644
--- a/plugins/ocp/ocp-nvme.h
+++ b/plugins/ocp/ocp-nvme.h
@@ -18,6 +18,7 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
 		ENTRY("smart-add-log", "Retrieve extended SMART Information", ocp_smart_add_log)
 		ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
 		ENTRY("clear-fw-activate-history", "Clear firmware update history log", clear_fw_update_history)
+		ENTRY("eol-plp-failure-mode", "Define EOL or PLP circuitry failure mode.", eol_plp_failure_mode)
 	)
 );