Merging upstream version 2.5.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
3d70d3c76b
commit
ee6621a5b2
507 changed files with 19440 additions and 17258 deletions
|
@ -3,5 +3,6 @@ sources += [
|
|||
'plugins/ocp/ocp-nvme.c',
|
||||
'plugins/ocp/ocp-clear-fw-update-history.c',
|
||||
'plugins/ocp/ocp-smart-extended-log.c',
|
||||
'plugins/ocp/ocp-fw-activation-history.c',
|
||||
]
|
||||
|
||||
|
|
|
@ -16,6 +16,5 @@ int ocp_clear_fw_update_history(int argc, char **argv, struct command *cmd, stru
|
|||
{
|
||||
const char *desc = "OCP Clear Firmware Update History";
|
||||
|
||||
return ocp_clear_feature(argc, argv, desc,
|
||||
OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
return ocp_clear_feature(argc, argv, desc, OCP_FID_CLEAR_FW_ACTIVATION_HISTORY);
|
||||
}
|
||||
|
|
223
plugins/ocp/ocp-fw-activation-history.c
Normal file
223
plugins/ocp/ocp-fw-activation-history.c
Normal file
|
@ -0,0 +1,223 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Author: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#include "ocp-fw-activation-history.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "nvme-print.h"
|
||||
|
||||
#include "ocp-utils.h"
|
||||
|
||||
static const unsigned char ocp_fw_activation_history_guid[16] = {
|
||||
0x6D, 0x79, 0x9a, 0x76,
|
||||
0xb4, 0xda, 0xf6, 0xa3,
|
||||
0xe2, 0x4d, 0xb2, 0x8a,
|
||||
0xac, 0xf3, 0x1c, 0xd1
|
||||
};
|
||||
|
||||
struct __packed fw_activation_history_entry {
|
||||
__u8 ver_num;
|
||||
__u8 entry_length;
|
||||
__u16 reserved1;
|
||||
__u16 activation_count;
|
||||
__u64 timestamp;
|
||||
__u64 reserved2;
|
||||
__u64 power_cycle_count;
|
||||
char previous_fw[8];
|
||||
char new_fw[8];
|
||||
__u8 slot_number;
|
||||
__u8 commit_action;
|
||||
__u16 result;
|
||||
__u8 reserved3[14];
|
||||
};
|
||||
|
||||
struct __packed fw_activation_history {
|
||||
__u8 log_id;
|
||||
__u8 reserved1[3];
|
||||
__u32 valid_entries;
|
||||
struct fw_activation_history_entry entries[20];
|
||||
__u8 reserved2[2790];
|
||||
__u16 log_page_version;
|
||||
__u64 log_page_guid[2];
|
||||
};
|
||||
|
||||
static void ocp_fw_activation_history_normal(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
printf("Firmware History Log:\n");
|
||||
|
||||
printf(" %-26s%d\n", "log identifier:", fw_history->log_id);
|
||||
printf(" %-26s%d\n", "valid entries:", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
printf(" entries:\n");
|
||||
|
||||
for (int index = 0; index < fw_history->valid_entries; index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
|
||||
printf(" entry[%d]:\n", le32_to_cpu(index));
|
||||
printf(" %-22s%d\n", "version number:", entry->ver_num);
|
||||
printf(" %-22s%d\n", "entry length:", entry->entry_length);
|
||||
printf(" %-22s%d\n", "activation count:",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
printf(" %-22s%"PRIu64"\n", "timestamp:",
|
||||
le64_to_cpu(entry->timestamp));
|
||||
printf(" %-22s%"PRIu64"\n", "power cycle count:",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
printf(" %-22s%.*s\n", "previous firmware:", (int)sizeof(entry->previous_fw),
|
||||
entry->previous_fw);
|
||||
printf(" %-22s%.*s\n", "new firmware:", (int)sizeof(entry->new_fw),
|
||||
entry->new_fw);
|
||||
printf(" %-22s%d\n", "slot number:", entry->slot_number);
|
||||
printf(" %-22s%d\n", "commit action type:", entry->commit_action);
|
||||
printf(" %-22s%d\n", "result:", le16_to_cpu(entry->result));
|
||||
}
|
||||
|
||||
printf(" %-26s%d\n", "log page version:",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
printf(" %-26s0x%"PRIx64"%"PRIx64"\n", "log page guid:",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void ocp_fw_activation_history_json(const struct fw_activation_history *fw_history)
|
||||
{
|
||||
struct json_object *root = json_create_object();
|
||||
|
||||
json_object_add_value_uint(root, "log identifier", fw_history->log_id);
|
||||
json_object_add_value_uint(root, "valid entries", le32_to_cpu(fw_history->valid_entries));
|
||||
|
||||
struct json_object *entries = json_create_array();
|
||||
|
||||
for (int index = 0; index < fw_history->valid_entries; index++) {
|
||||
const struct fw_activation_history_entry *entry = &fw_history->entries[index];
|
||||
struct json_object *entry_obj = json_create_object();
|
||||
|
||||
json_object_add_value_uint(entry_obj, "version number", entry->ver_num);
|
||||
json_object_add_value_uint(entry_obj, "entry length", entry->entry_length);
|
||||
json_object_add_value_uint(entry_obj, "activation count",
|
||||
le16_to_cpu(entry->activation_count));
|
||||
json_object_add_value_uint64(entry_obj, "timestamp",
|
||||
le64_to_cpu(entry->timestamp));
|
||||
json_object_add_value_uint(entry_obj, "power cycle count",
|
||||
le64_to_cpu(entry->power_cycle_count));
|
||||
|
||||
struct json_object *fw = json_object_new_string_len(entry->previous_fw,
|
||||
sizeof(entry->previous_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "previous firmware", fw);
|
||||
|
||||
fw = json_object_new_string_len(entry->new_fw, sizeof(entry->new_fw));
|
||||
|
||||
json_object_add_value_object(entry_obj, "new firmware", fw);
|
||||
json_object_add_value_uint(entry_obj, "slot number", entry->slot_number);
|
||||
json_object_add_value_uint(entry_obj, "commit action type", entry->commit_action);
|
||||
json_object_add_value_uint(entry_obj, "result", le16_to_cpu(entry->result));
|
||||
|
||||
json_array_add_value_object(entries, entry_obj);
|
||||
}
|
||||
|
||||
json_object_add_value_array(root, "entries", entries);
|
||||
|
||||
json_object_add_value_uint(root, "log page version",
|
||||
le16_to_cpu(fw_history->log_page_version));
|
||||
|
||||
char guid[2 * sizeof(fw_history->log_page_guid) + 3] = { 0 };
|
||||
|
||||
sprintf(guid, "0x%"PRIx64"%"PRIx64"",
|
||||
le64_to_cpu(fw_history->log_page_guid[1]),
|
||||
le64_to_cpu(fw_history->log_page_guid[0]));
|
||||
json_object_add_value_string(root, "log page guid", guid);
|
||||
|
||||
json_print_object(root, NULL);
|
||||
json_free_object(root);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv, struct command *cmd,
|
||||
struct plugin *plugin)
|
||||
{
|
||||
const __u8 log_id = 0xC2;
|
||||
const char *description = "Retrieves the OCP firmware activation history log.";
|
||||
|
||||
char *format = "normal";
|
||||
|
||||
OPT_ARGS(options) = {
|
||||
OPT_FMT("output-format", 'o', &format, "output format : normal | json"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
struct nvme_dev *dev = NULL;
|
||||
int err = parse_and_open(&dev, argc, argv, description, options);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
int uuid_index = 0;
|
||||
|
||||
/*
|
||||
* Best effort attempt at uuid. Otherwise, assume no index (i.e. 0)
|
||||
* Log GUID check will ensure correctness of returned data
|
||||
*/
|
||||
ocp_get_uuid_index(dev, &uuid_index);
|
||||
|
||||
struct fw_activation_history fw_history = { 0 };
|
||||
|
||||
struct nvme_get_log_args args = {
|
||||
.lpo = 0,
|
||||
.result = NULL,
|
||||
.log = &fw_history,
|
||||
.args_size = sizeof(args),
|
||||
.fd = dev_fd(dev),
|
||||
.timeout = NVME_DEFAULT_IOCTL_TIMEOUT,
|
||||
.lid = log_id,
|
||||
.len = sizeof(fw_history),
|
||||
.nsid = NVME_NSID_ALL,
|
||||
.csi = NVME_CSI_NVM,
|
||||
.lsi = NVME_LOG_LSI_NONE,
|
||||
.lsp = 0,
|
||||
.uuidx = uuid_index,
|
||||
.rae = false,
|
||||
.ot = false,
|
||||
};
|
||||
|
||||
err = nvme_get_log(&args);
|
||||
|
||||
if (err)
|
||||
nvme_show_status(err);
|
||||
|
||||
dev_close(dev);
|
||||
|
||||
int guid_cmp_res = memcmp(fw_history.log_page_guid, ocp_fw_activation_history_guid,
|
||||
sizeof(ocp_fw_activation_history_guid));
|
||||
|
||||
if (!err && guid_cmp_res) {
|
||||
fprintf(stderr,
|
||||
"Error: Unexpected data. Log page guid does not match with expected.\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
|
||||
if (!err) {
|
||||
const enum nvme_print_flags print_flag = validate_output_format(format);
|
||||
|
||||
if (print_flag == JSON)
|
||||
ocp_fw_activation_history_json(&fw_history);
|
||||
else if (print_flag == NORMAL)
|
||||
ocp_fw_activation_history_normal(&fw_history);
|
||||
else {
|
||||
fprintf(stderr, "Error: Invalid output format.\n");
|
||||
err = -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
17
plugins/ocp/ocp-fw-activation-history.h
Normal file
17
plugins/ocp/ocp-fw-activation-history.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Copyright (c) 2022 Solidigm.
|
||||
*
|
||||
* Authors: karl.dedow@solidigm.com
|
||||
*/
|
||||
|
||||
#ifndef OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
#define OCP_FIRMWARE_ACTIVATION_HISTORY_H
|
||||
|
||||
struct command;
|
||||
struct plugin;
|
||||
|
||||
int ocp_fw_activation_history_log(int argc, char **argv,
|
||||
struct command *cmd, struct plugin *plugin);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load diff
|
@ -17,9 +17,15 @@ PLUGIN(NAME("ocp", "OCP cloud SSD extensions", NVME_VERSION),
|
|||
COMMAND_LIST(
|
||||
ENTRY("smart-add-log", "Retrieve extended SMART Information", smart_add_log)
|
||||
ENTRY("latency-monitor-log", "Get Latency Monitor Log Page", ocp_latency_monitor_log)
|
||||
ENTRY("set-latency-monitor-feature", "Set Latency Monitor feature", ocp_set_latency_monitor_feature)
|
||||
ENTRY("internal-log", "Retrieve and save internal device telemetry log", ocp_telemetry_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)
|
||||
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)
|
||||
ENTRY("error-recovery-log", "Retrieve Error Recovery Log Page", ocp_error_recovery_log)
|
||||
ENTRY("device-capability-log", "Get Device capabilities Requirements Log Page", ocp_device_capabilities_log)
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ static __u8 scao_guid[C0_GUID_LENGTH] = {
|
|||
0xC9, 0x14, 0xD5, 0xAF
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
enum {
|
||||
SCAO_PMUW = 0, /* Physical media units written */
|
||||
SCAO_PMUR = 16, /* Physical media units read */
|
||||
SCAO_BUNBR = 32, /* Bad user nand blocks raw */
|
||||
|
@ -62,7 +62,7 @@ typedef enum {
|
|||
SCAO_PSCC = 200, /* Power State Change Count */
|
||||
SCAO_LPV = 494, /* Log page version */
|
||||
SCAO_LPG = 496, /* Log page GUID */
|
||||
} SMART_CLOUD_ATTRIBUTE_OFFSETS;
|
||||
};
|
||||
|
||||
static void ocp_print_C0_log_normal(void *data)
|
||||
{
|
||||
|
@ -71,10 +71,10 @@ static void ocp_print_C0_log_normal(void *data)
|
|||
|
||||
printf("SMART Cloud Attributes :-\n");
|
||||
|
||||
printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
|
||||
printf(" Physical media units written - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUW] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
|
||||
printf(" Physical media units read - %"PRIu64" %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR + 8] & 0xFFFFFFFFFFFFFFFF),
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PMUR] & 0xFFFFFFFFFFFFFFFF));
|
||||
printf(" Bad user nand blocks - Raw %"PRIu64"\n",
|
||||
|
@ -105,7 +105,7 @@ static void ocp_print_C0_log_normal(void *data)
|
|||
(uint32_t)le32_to_cpu(*(uint32_t *)&log_data[SCAO_MNUDEC]));
|
||||
printf(" Number of Thermal throttling events %d\n",
|
||||
(__u8)log_data[SCAO_NTTE]);
|
||||
printf(" Current throttling status 0x%x\n",
|
||||
printf(" Current throttling status 0x%x\n",
|
||||
(__u8)log_data[SCAO_CTS]);
|
||||
printf(" PCIe correctable error count %"PRIu64"\n",
|
||||
(uint64_t)le64_to_cpu(*(uint64_t *)&log_data[SCAO_PCEC]));
|
||||
|
@ -286,14 +286,12 @@ static int get_c0_log_page(int fd, char *format)
|
|||
|
||||
fprintf(stderr, "ERROR : OCP : Unknown GUID in C0 Log Page data\n");
|
||||
fprintf(stderr, "ERROR : OCP : Expected GUID: 0x");
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%x", scao_guid[j]);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\nERROR : OCP : Actual GUID: 0x");
|
||||
for (j = 0; j < 16; j++) {
|
||||
for (j = 0; j < 16; j++)
|
||||
fprintf(stderr, "%x", data[SCAO_LPG + j]);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
ret = -1;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue