From: Vigneshwaran Saravanan Date: Fri, 28 Apr 2023 07:12:39 +0000 (+0530) Subject: plugins/ocp: Added ocp unsupported requirements log page X-Git-Tag: v2.5~115 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=833125ae485308fb260d208610ae16d7fe306651;p=users%2Fsagi%2Fnvme-cli.git plugins/ocp: Added ocp unsupported requirements log page Reviewed-by: Karthik Balan Reviewed-by: Arunpandian J Signed-off-by: Vigneshwaran Saravanan --- diff --git a/Documentation/nvme-ocp-unsupported-reqs-log-pages.txt b/Documentation/nvme-ocp-unsupported-reqs-log-pages.txt new file mode 100644 index 00000000..65818d36 --- /dev/null +++ b/Documentation/nvme-ocp-unsupported-reqs-log-pages.txt @@ -0,0 +1,45 @@ +unsupported-reqs-log +==================== + +NAME +---- +unsupported-reqs-log - Retrieves unsupported requirements log page of given OCP +compliant device + +SYNOPSIS +-------- +[verse] +'nvme ocp unsupported-reqs-log' [--output-format= | -o ] + +DESCRIPTION +----------- +For the NVMe device given, send a unsupported-reqs-log command and +provide the unsupported requirements log page. + +The parameter is mandatory and may be either the NVMe character +device (ex: /dev/nvme0) or block device (ex: /dev/nvme0n1). + +This will only work on OCP compliant devices supporting this feature. +Results for any other device are undefined. + +On success it returns 0, error code otherwise. + +OPTIONS +------- + +-o :: +--output-format=:: + This option will set the reporting format to normal, json, or binary. + Only one output format can be used at a time. + +EXAMPLES +-------- +* Has the program issue a unsupported-reqs-log command to retrieve the 0xC5 log page. ++ +------------ +# nvme ocp unsupported-reqs-log /dev/nvme0 +------------ + +NVME +---- +Part of the nvme-user suite \ No newline at end of file diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index 60735525..7778d9ba 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -1245,6 +1245,213 @@ static int ocp_telemetry_log(int argc, char **argv, struct command *cmd, return err; } +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +/// Unsupported Requirement Log Page (LID : C5h) + +/* C5 Unsupported Requirement Log Page */ +#define C5_GUID_LENGTH 16 +#define C5_UNSUPPORTED_REQS_LEN 4096 +#define C5_UNSUPPORTED_REQS_OPCODE 0xC5 +#define C5_UNSUPPORTED_REQS_LOG_VERSION 0x1 +#define C5_NUM_UNSUPPORTED_REQ_ENTRIES 253 + +static __u8 unsupported_req_guid[C5_GUID_LENGTH] = { + 0x2F, 0x72, 0x9C, 0x0E, + 0x99, 0x23, 0x2C, 0xBB, + 0x63, 0x48, 0x32, 0xD0, + 0xB7, 0x98, 0xBB, 0xC7 +}; + +/* + * struct unsupported_requirement_log - unsupported requirement list + * @unsupported_count: Number of Unsupported Requirement IDs + * @rsvd1: Reserved + * @unsupported_req_list: Unsupported Requirements lists upto 253. + * @rsvd2: Reserved + * @log_page_version: indicates the version of the mapping this log page uses. + Shall be set to 0001h + * @log_page_guid: Shall be set to C7BB98B7D0324863BB2C23990E9C722Fh. +*/ +struct __attribute__((__packed__)) unsupported_requirement_log { + __le16 unsupported_count; + __u8 rsvd1[14]; + __u8 unsupported_req_list[C5_NUM_UNSUPPORTED_REQ_ENTRIES][16]; + __u8 rsvd2[14]; + __le16 log_page_version; + __u8 log_page_guid[C5_GUID_LENGTH]; +}; + +/*Function declaration for unsupported requirement log page(LID:C5h)*/ +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin); + +static int ocp_print_C5_log_normal(struct nvme_dev *dev, + struct unsupported_requirement_log *log_data) +{ + int j; + printf("Unsupported Requirement-C5 Log Page Data- \n"); + + printf(" Number Unsupported Req IDs : 0x%x \n", le16_to_cpu(log_data->unsupported_count)); + + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + printf(" Unsupported Requirement List %d : %s \n", j, log_data->unsupported_req_list[j]); + } + + printf(" Log Page Version : 0x%x \n", le16_to_cpu(log_data->log_page_version)); + printf(" Log page GUID : 0x"); + for (j = C5_GUID_LENGTH - 1; j >= 0; j--) { + printf("%x", log_data->log_page_guid[j]); + } + printf("\n"); + + return 0; +} + +static void ocp_print_C5_log_json(struct unsupported_requirement_log *log_data) +{ + int j; + struct json_object *root; + root = json_create_object(); + + json_object_add_value_int(root, "Number Unsupported Req IDs", le16_to_cpu(log_data->unsupported_count)); + + char unsup_req_list_str[40]; + memset((void *)unsup_req_list_str, 0, 40); + for (j = 0; j < le16_to_cpu(log_data->unsupported_count); j++) { + sprintf((char *)unsup_req_list_str, "Unsupported Requirement List %d", j); + json_object_add_value_string(root, unsup_req_list_str, (char *)log_data->unsupported_req_list[j]); + } + + json_object_add_value_int(root, "Log Page Version", le16_to_cpu(log_data->log_page_version)); + char guid_buf[C5_GUID_LENGTH]; + char *guid = guid_buf; + memset((void*)guid, 0, C5_GUID_LENGTH); + for (j = C5_GUID_LENGTH - 1; j >= 0; j--){ + guid += sprintf(guid, "%02x", log_data->log_page_guid[j]); + } + json_object_add_value_string(root, "Log page GUID", guid_buf); + + json_print_object(root, NULL); + printf("\n"); + + json_free_object(root); +} + +static void ocp_print_c5_log_binary(struct unsupported_requirement_log *log_data) +{ + return d_raw((unsigned char *)log_data, sizeof(*log_data)); +} + +static int get_c5_log_page(struct nvme_dev *dev, char *format) +{ + int ret = 0; + int fmt = -1; + __u8 *data; + int i; + struct unsupported_requirement_log *log_data; + + fmt = validate_output_format(format); + if (fmt < 0) { + fprintf(stderr, "ERROR : OCP : invalid output format\n"); + return fmt; + } + + if ((data = (__u8 *) malloc(sizeof(__u8) * C5_UNSUPPORTED_REQS_LEN)) == NULL) { + fprintf(stderr, "ERROR : OCP : malloc : %s\n", strerror(errno)); + return -1; + } + memset(data, 0, sizeof (__u8) * C5_UNSUPPORTED_REQS_LEN); + + ret = nvme_get_log_simple(dev_fd(dev), C5_UNSUPPORTED_REQS_OPCODE, + C5_UNSUPPORTED_REQS_LEN, data); + + if (ret == 0) { + log_data = (struct unsupported_requirement_log*)data; + + /* check log page version */ + if (log_data->log_page_version != C5_UNSUPPORTED_REQS_LOG_VERSION) { + fprintf(stderr, "ERROR : OCP : invalid unsupported requirement version\n"); + ret = -1; + goto out; + } + + /* check log page guid */ + /* Verify GUID matches */ + for (i=0; i<16; i++) { + if (unsupported_req_guid[i] != log_data->log_page_guid[i]) { + fprintf(stderr, "ERROR : OCP : Unknown GUID in C5 Log Page data\n"); + int j; + fprintf(stderr, "ERROR : OCP : Expected GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", unsupported_req_guid[j]); + } + fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x"); + for (j = 0; j<16; j++) { + fprintf(stderr, "%x", log_data->log_page_guid[j]); + } + fprintf(stderr, "\n"); + + ret = -1; + goto out; + } + } + + switch (fmt) { + case NORMAL: + ocp_print_C5_log_normal(dev, log_data); + break; + case JSON: + ocp_print_C5_log_json(log_data); + break; + case BINARY: + ocp_print_c5_log_binary(log_data); + break; + } + } else { + fprintf(stderr, "ERROR : OCP : Unable to read C3 data from buffer\n"); + } + +out: + free(data); + return ret; +} + + +static int ocp_unsupported_requirements_log(int argc, char **argv, struct command *cmd, + struct plugin *plugin) +{ + const char *desc = "Retrieve unsupported requirements log data."; + struct nvme_dev *dev; + int ret = 0; + + struct config { + char *output_format; + }; + + struct config cfg = { + .output_format = "normal", + }; + + OPT_ARGS(opts) = { + OPT_FMT("output-format", 'o', &cfg.output_format, "output Format: normal|json"), + OPT_END() + }; + + ret = parse_and_open(&dev, argc, argv, desc, opts); + if (ret) + return ret; + + ret = get_c5_log_page(dev, cfg.output_format); + if (ret) + fprintf(stderr, "ERROR : OCP : Failure reading the C5 Log Page, ret = %d\n", ret); + + dev_close(dev); + return ret; +} + /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// diff --git a/plugins/ocp/ocp-nvme.h b/plugins/ocp/ocp-nvme.h index a4390db8..24f91af8 100644 --- a/plugins/ocp/ocp-nvme.h +++ b/plugins/ocp/ocp-nvme.h @@ -23,6 +23,7 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION), ENTRY("eol-plp-failure-mode", "Define EOL or PLP circuitry failure mode.", eol_plp_failure_mode) ENTRY("clear-pcie-correctable-error-counters", "Clear PCIe correctable error counters", clear_pcie_corectable_error_counters) ENTRY("vs-fw-activate-history", "Get firmware activation history log", fw_activation_history_log) + ENTRY("unsupported-reqs-log", "Get Unsupported Requirements Log Page", ocp_unsupported_requirements_log) ) );