diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index 8d39d2c..ba265ed 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -1483,7 +1483,7 @@ struct cel_entry {
__le16 effect;
} __attribute__((packed));
-CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev)
+CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char* uuid)
{
struct cxl_cmd *cmd;
struct cxl_mbox_get_log *get_log_input;
@@ -1491,6 +1491,12 @@ CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev)
int no_cel_entries;
int rc = 0;
+ if (!uuid) {
+ fprintf(stderr, "%s: Please specify log uuid argument\n",
+ cxl_memdev_get_devname(memdev));
+ return -EINVAL;
+ }
+
cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LOG);
if (!cmd) {
fprintf(stderr, "%s: cxl_memdev_get_cel_log returned Null output\n",
@@ -1499,7 +1505,7 @@ CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev)
}
get_log_input = (void *) cmd->send_cmd->in.payload;
- uuid_parse(CEL_UUID, get_log_input->uuid);
+ uuid_parse(uuid, get_log_input->uuid);
get_log_input->offset = 0;
get_log_input->length = cmd->memdev->payload_max;
@@ -2021,7 +2027,9 @@ struct cxl_dram_event_record {
u8 row[3];
__le16 column;
u8 correction_mask[0x20];
- u8 reserved[0x17];
+ u8 component_identifier[0x10];
+ u8 sub_channel;
+ u8 reserved[0x6];
} __attribute__((packed));
struct cxl_memory_module_record {
@@ -2160,6 +2168,16 @@ CXL_EXPORT int cxl_memdev_get_event_records(struct cxl_memdev *memdev, u8 event_
fprintf(stdout, "%*srow: 0x%02x%02x%02x\n", indent+2, "", dram_event->row[0],
dram_event->row[1], dram_event->row[2]);
fprintf(stdout, "%*scolumn: 0x%x\n", indent+2, "", le16_to_cpu(dram_event->column));
+ for (int i=0; i < 4; i++) {
+ fprintf(stdout, "%*scorrection mask[%d]: 0x", indent+2, "", i);
+ for (int j=0; j < 8; j++) {
+ fprintf(stdout, "%02x", dram_event->correction_mask[i*j+j]);
+ }
+ fprintf(stdout, "\n");
+ }
+ fprintf(stdout, "%*scomponent identifier: 0x%02x%02x%02x\n", indent+2, "",
+ dram_event->component_identifier[0], dram_event->component_identifier[1],
+ dram_event->component_identifier[2]);
}
}
@@ -6272,14 +6290,12 @@ out:
return 0;
}
-
#define CXL_MEM_COMMAND_ID_HEALTH_COUNTERS_GET CXL_MEM_COMMAND_ID_RAW
#define CXL_MEM_COMMAND_ID_HEALTH_COUNTERS_GET_OPCODE 52737
#define CXL_MEM_COMMAND_ID_HEALTH_COUNTERS_GET_PAYLOAD_OUT_SIZE 40
-
struct cxl_mbox_health_counters_get_out {
- __le32 temperature_threshold_exceeded;
+ __le32 critical_over_temperature_exceeded;
__le32 power_on_events;
__le32 power_on_hours;
__le32 cxl_mem_link_crc_errors;
@@ -6289,6 +6305,12 @@ struct cxl_mbox_health_counters_get_out {
__le32 num_ddr_double_ecc_errors;
__le32 link_recovery_events;
__le32 time_in_throttled;
+ __le32 over_temperature_warning_level_exceeded;
+ __le32 critical_under_temperature_exceeded;
+ __le32 under_temperature_warning_level_exceeded;
+ __le32 rx_retry_request;
+ __le32 rcmd_qs0_hi_threshold_detect;
+ __le32 rcmd_qs1_hi_threshold_detect;
} __attribute__((packed));
CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
@@ -6327,16 +6349,22 @@ CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
health_counters_get_out = (void *)cmd->send_cmd->out.payload;
fprintf(stdout, "============================= get health counters ==============================\n");
- fprintf(stdout, "Number of times temperature has exceeded threshold: %d\n", le32_to_cpu(health_counters_get_out->temperature_threshold_exceeded));
- fprintf(stdout, "Number of Power On events: %d\n", le32_to_cpu(health_counters_get_out->power_on_events));
- fprintf(stdout, "Number of Power On hours: %d\n", le32_to_cpu(health_counters_get_out->power_on_hours));
- fprintf(stdout, "Number of CXL.mem Link CRC errors: %d\n", le32_to_cpu(health_counters_get_out->cxl_mem_link_crc_errors));
- fprintf(stdout, "Number of CXL.io Link LCRC errors: %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_lcrc_errors));
- fprintf(stdout, "Number of CXL.io Link ECRC errors: %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_ecrc_errors));
- fprintf(stdout, "Number of DDR single ECC errors: %d\n", le32_to_cpu(health_counters_get_out->num_ddr_single_ecc_errors));
- fprintf(stdout, "Number of DDR double ECC errors: %d\n", le32_to_cpu(health_counters_get_out->num_ddr_double_ecc_errors));
- fprintf(stdout, "Number of Link recovery events: %d\n", le32_to_cpu(health_counters_get_out->link_recovery_events));
- fprintf(stdout, "Amount of time spent in throttled state (in seconds): %d\n", le32_to_cpu(health_counters_get_out->time_in_throttled));
+ fprintf(stdout, "0: CRITICAL_OVER_TEMPERATURE_EXCEEDED = %d\n", le32_to_cpu(health_counters_get_out->critical_over_temperature_exceeded));
+ fprintf(stdout, "1: OVER_TEMPERATURE_WARNING_LEVEL_EXCEEDED = %d\n", le32_to_cpu(health_counters_get_out->over_temperature_warning_level_exceeded));
+ fprintf(stdout, "2: CRITICAL_UNDER_TEMPERATURE_EXCEEDED = %d\n", le32_to_cpu(health_counters_get_out->critical_under_temperature_exceeded));
+ fprintf(stdout, "3: UNDER_TEMPERATURE_WARNING_LEVEL_EXCEEDED = %d\n", le32_to_cpu(health_counters_get_out->under_temperature_warning_level_exceeded));
+ fprintf(stdout, "4: POWER_ON_EVENTS = %d\n", le32_to_cpu(health_counters_get_out->power_on_events));
+ fprintf(stdout, "5: POWER_ON_HOURS = %d\n", le32_to_cpu(health_counters_get_out->power_on_hours));
+ fprintf(stdout, "6: CXL_MEM_LINK_CRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_mem_link_crc_errors));
+ fprintf(stdout, "7: CXL_IO_LINK_LCRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_lcrc_errors));
+ fprintf(stdout, "8: CXL_IO_LINK_ECRC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->cxl_io_link_ecrc_errors));
+ fprintf(stdout, "9: NUM_DDR_SINGLE_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_single_ecc_errors));
+ fprintf(stdout, "10: NUM_DDR_DOUBLE_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_double_ecc_errors));
+ fprintf(stdout, "11: LINK_RECOVERY_EVENTS = %d\n", le32_to_cpu(health_counters_get_out->link_recovery_events));
+ fprintf(stdout, "12: TIME_IN_THROTTLED = %d\n", le32_to_cpu(health_counters_get_out->time_in_throttled));
+ fprintf(stdout, "13: RX_RETRY_REQUEST = %d\n", le32_to_cpu(health_counters_get_out->rx_retry_request));
+ fprintf(stdout, "14: RCMD_QS0_HI_THRESHOLD_DETECT = %d\n", le32_to_cpu(health_counters_get_out->rcmd_qs0_hi_threshold_detect));
+ fprintf(stdout, "15: RCMD_QS1_HI_THRESHOLD_DETECT = %d\n", le32_to_cpu(health_counters_get_out->rcmd_qs1_hi_threshold_detect));
out:
cxl_cmd_unref(cmd);
@@ -9964,6 +9992,31 @@ out:
return rc;
}
+struct cxl_dimm_slot_info_out {
+ u8 num_dimm_slots;
+ u8 rsvd[3];
+ u8 slot0_spd_i2c_addr;
+ u8 slot0_channel_id;
+ u8 slot0_dimm_silk_screen;
+ u8 slot0_dimm_present;
+ u8 rsvd1[12];
+ u8 slot1_spd_i2c_addr;
+ u8 slot1_channel_id;
+ u8 slot1_dimm_silk_screen;
+ u8 slot1_dimm_present;
+ u8 rsvd2[12];
+ u8 slot2_spd_i2c_addr;
+ u8 slot2_channel_id;
+ u8 slot2_dimm_silk_screen;
+ u8 slot2_dimm_present;
+ u8 rsvd3[12];
+ u8 slot3_spd_i2c_addr;
+ u8 slot3_channel_id;
+ u8 slot3_dimm_silk_screen;
+ u8 slot3_dimm_present;
+ u8 rsvd4[12];
+} __attribute__((packed));
+
#define CXL_MEM_COMMAND_ID_DIMM_SLOT_INFO CXL_MEM_COMMAND_ID_RAW
#define CXL_MEM_COMMAND_ID_DIMM_SLOT_INFO_OPCODE 0xC520
#define CXL_MEM_COMMAND_ID_DIMM_SLOT_INFO_PAYLOAD_IN_SIZE 0
@@ -9973,10 +10026,12 @@ CXL_EXPORT int cxl_memdev_dimm_slot_info(struct cxl_memdev *memdev)
struct cxl_cmd *cmd;
struct cxl_mem_query_commands *query;
struct cxl_command_info *cinfo;
- u8 *dimm_slot_info;
+ struct cxl_dimm_slot_info_out *dimm_slot_info;
+ u8 *dimm_slots;
int rc = 0;
int offset = 0;
-
+ int indent = 2;
+ char silk_screen_char;
cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DIMM_SLOT_INFO_OPCODE);
if (!cmd) {
@@ -10018,20 +10073,52 @@ CXL_EXPORT int cxl_memdev_dimm_slot_info(struct cxl_memdev *memdev)
return -EINVAL;
}
- dimm_slot_info = (u8*)cmd->send_cmd->out.payload;
+ dimm_slot_info = (void *)cmd->send_cmd->out.payload;
+ dimm_slots = (u8*)cmd->send_cmd->out.payload;
fprintf(stdout, "=========================== DIMM SLOT INFO ============================\n");
fprintf(stdout, "Output Payload:\n");
for(int i=0; i<cmd->send_cmd->out.size; i++){
if (i % 16 == 0)
{
- fprintf(stdout, "\n%04x %02x ", i+offset, dimm_slot_info[i]);
+ fprintf(stdout, "\n%04x %02x ", i+offset, dimm_slots[i]);
}
else
{
- fprintf(stdout, "%02x ", dimm_slot_info[i]);
+ fprintf(stdout, "%02x ", dimm_slots[i]);
}
}
- fprintf(stdout, "\n");
+ fprintf(stdout, "\n\n");
+
+ // Decoding slot info data.
+ fprintf(stdout, "\n\n====== DIMM SLOTS INFO DECODE ============\n");
+
+ fprintf(stdout, "Number of DIMM Slots: %d\n", dimm_slot_info->num_dimm_slots);
+ fprintf(stdout, "DIMM SPD Index: 0\n");
+ fprintf(stdout, "%*sDIMM Present: 0x%x\n", indent+2, "", dimm_slot_info->slot0_dimm_present);
+ silk_screen_char = dimm_slot_info->slot0_dimm_silk_screen;
+ fprintf(stdout, "%*sDIMM Silk Screen: %c\n", indent+2, "", silk_screen_char);
+ fprintf(stdout, "%*sChannel ID: 0x%x\n", indent+2, "", dimm_slot_info->slot0_channel_id);
+ fprintf(stdout, "%*sI2C Address: 0x%x\n", indent+2, "", dimm_slot_info->slot0_spd_i2c_addr);
+ fprintf(stdout, "DIMM SPD Index: 1\n");
+ fprintf(stdout, "%*sDIMM Present: 0x%x\n", indent+2, "", dimm_slot_info->slot1_dimm_present);
+ silk_screen_char = dimm_slot_info->slot1_dimm_silk_screen;
+ fprintf(stdout, "%*sDIMM Silk Screen: %c\n", indent+2, "", silk_screen_char);
+ fprintf(stdout, "%*sChannel ID: 0x%x\n", indent+2, "", dimm_slot_info->slot1_channel_id);
+ fprintf(stdout, "%*sI2C Address: 0x%x\n", indent+2, "", dimm_slot_info->slot1_spd_i2c_addr);
+ fprintf(stdout, "DIMM SPD Index: 2\n");
+ fprintf(stdout, "%*sDIMM Present: 0x%x\n", indent+2, "", dimm_slot_info->slot2_dimm_present);
+ silk_screen_char = dimm_slot_info->slot2_dimm_silk_screen;
+ fprintf(stdout, "%*sDIMM Silk Screen: %c\n", indent+2, "", silk_screen_char);
+ fprintf(stdout, "%*sChannel ID: 0x%x\n", indent+2, "", dimm_slot_info->slot2_channel_id);
+ fprintf(stdout, "%*sI2C Address: 0x%x\n", indent+2, "", dimm_slot_info->slot2_spd_i2c_addr);
+ fprintf(stdout, "DIMM SPD Index: 3\n");
+ fprintf(stdout, "%*sDIMM Present: 0x%x\n", indent+2, "", dimm_slot_info->slot3_dimm_present);
+ silk_screen_char = dimm_slot_info->slot3_dimm_silk_screen;
+ fprintf(stdout, "%*sDIMM Silk Screen: %c\n", indent+2, "", silk_screen_char);
+ fprintf(stdout, "%*sChannel ID: 0x%x\n", indent+2, "", dimm_slot_info->slot3_channel_id);
+ fprintf(stdout, "%*sI2C Address: 0x%x\n", indent+2, "", dimm_slot_info->slot3_spd_i2c_addr);
+
+ fprintf(stdout, "\n\n");
out:
cxl_cmd_unref(cmd);
return rc;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index 0c24579..6583af5 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -63,7 +63,7 @@ int cxl_memdev_transfer_fw(struct cxl_memdev *memdev, u8 action,
int cxl_memdev_activate_fw(struct cxl_memdev *memdev, u8 action,
u8 slot);
int cxl_memdev_get_supported_logs(struct cxl_memdev *memdev);
-int cxl_memdev_get_cel_log(struct cxl_memdev *memdev);
+int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char *uuid);
int cxl_memdev_get_event_interrupt_policy(struct cxl_memdev *memdev);
int cxl_memdev_set_event_interrupt_policy(struct cxl_memdev *memdev, u32 int_policy);
int cxl_memdev_get_timestamp(struct cxl_memdev *memdev);
diff --git a/cxl/memdev.c b/cxl/memdev.c
index 64ba7e0..fba1f75 100644
--- a/cxl/memdev.c
+++ b/cxl/memdev.c
@@ -84,8 +84,17 @@ static const struct option cmd_get_supported_logs_options[] = {
OPT_END(),
};
+static struct _log_uuid {
+ const char* uuid;
+} log_uuid;
+
+#define LOG_UUID_OPTIONS() \
+OPT_STRING('l', "log_uuid", &log_uuid.uuid, "log-uuid", \
+ "CEL Log UUID")
+
static const struct option cmd_get_cel_log_options[] = {
BASE_OPTIONS(),
+ LOG_UUID_OPTIONS(),
OPT_END(),
};
@@ -2247,7 +2256,7 @@ static int action_cmd_get_cel_log(struct cxl_memdev *memdev, struct action_conte
return -EBUSY;
}
- return cxl_memdev_get_cel_log(memdev);
+ return cxl_memdev_get_cel_log(memdev, log_uuid.uuid);
}
static int action_cmd_get_supported_logs(struct cxl_memdev *memdev, struct action_context *actx)