diff --git a/cligen/gen/base.cxl.c b/cligen/gen/base.cxl.c
index ee2d6b0..2ef95d1 100644
--- a/cligen/gen/base.cxl.c
+++ b/cligen/gen/base.cxl.c
@@ -69,7 +69,7 @@ static struct cmd_struct commands[] = {
{ "write-labels", .c_fn = cmd_write_labels },
{ "id-cmd", .c_fn = cmd_identify },
{ "get-supported-logs", .c_fn = cmd_get_supported_logs },
- { "get-cel-log", .c_fn = cmd_get_cel_log },
+ { "get-log", .c_fn = cmd_get_log },
{ "get-event-interrupt-policy", .c_fn = cmd_get_event_interrupt_policy },
{ "set-event-interrupt-policy", .c_fn = cmd_set_event_interrupt_policy },
{ "get-timestamp", .c_fn = cmd_get_timestamp },
diff --git a/cligen/gen/base.memdev.c b/cligen/gen/base.memdev.c
index 56c3ebd..c5ec60e 100644
--- a/cligen/gen/base.memdev.c
+++ b/cligen/gen/base.memdev.c
@@ -668,10 +668,10 @@ int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx)
return rc >= 0 ? 0 : EXIT_FAILURE;
}
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx)
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx)
{
- int rc = memdev_action(argc, argv, ctx, action_cmd_get_cel_log, cmd_get_cel_log_options,
- "cxl get-cel-log <mem0> [<mem1>..<memN>] [<options>]");
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_log, cmd_get_log_options,
+ "cxl get-log <mem0> [<mem1>..<memN>] [<options>]");
return rc >= 0 ? 0 : EXIT_FAILURE;
}
diff --git a/cxl/builtin.h b/cxl/builtin.h
index 5775f4a..e66d027 100644
--- a/cxl/builtin.h
+++ b/cxl/builtin.h
@@ -17,7 +17,7 @@ int cmd_init_labels(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_check_labels(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_identify(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx);
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_get_event_interrupt_policy(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_set_event_interrupt_policy(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_get_timestamp(int argc, const char **argv, struct cxl_ctx *ctx);
@@ -116,4 +116,44 @@ int cmd_osa_data_read(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_dimm_spd_read(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_ddr_training_status(int argc, const char **argv, struct cxl_ctx *ctx);
int cmd_dimm_slot_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pmic_vtmon_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_margin_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_stats_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_stats_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_reboot_mode_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_curr_cxl_boot_mode_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_run(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pcie_eye_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_link_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_device_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_read_ddr_temp(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_cxl_hpa_to_dpa(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_membridge_errors(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_bw(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_latency(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_i2c_read(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_i2c_write(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_ddr_ecc_err_info(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_start_ddr_ecc_scrub(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_ecc_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_cont_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_cont_scrub_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_init_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_get_cxl_membridge_stats(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_trigger_coredump(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_err_inj_en(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_dimm_level_training_status(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_param_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_param_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_core_volt_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_core_volt_get(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_oem_err_inj_viral(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_err_inj_ll_poison(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_pci_err_inj(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_read_ltssm_states(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_page_select_set(int argc, const char **argv, struct cxl_ctx *ctx);
+int cmd_ddr_page_select_get(int argc, const char **argv, struct cxl_ctx *ctx);
#endif /* _CXL_BUILTIN_H_ */
diff --git a/cxl/cxl.c b/cxl/cxl.c
index 4b430b5..c44bb75 100644
--- a/cxl/cxl.c
+++ b/cxl/cxl.c
@@ -73,7 +73,7 @@ static struct cmd_struct commands[] = {
{ "write-labels", .c_fn = cmd_write_labels },
{ "id-cmd", .c_fn = cmd_identify },
{ "get-supported-logs", .c_fn = cmd_get_supported_logs },
- { "get-cel-log", .c_fn = cmd_get_cel_log },
+ { "get-log", .c_fn = cmd_get_log },
{ "get-event-interrupt-policy", .c_fn = cmd_get_event_interrupt_policy },
{ "set-event-interrupt-policy", .c_fn = cmd_set_event_interrupt_policy },
{ "get-timestamp", .c_fn = cmd_get_timestamp },
@@ -172,6 +172,46 @@ static struct cmd_struct commands[] = {
{ "dimm-spd-read", .c_fn = cmd_dimm_spd_read },
{ "ddr-training-status", .c_fn = cmd_ddr_training_status },
{ "dimm-slot-info", .c_fn = cmd_dimm_slot_info },
+ { "pmic-vtmon-info", .c_fn = cmd_pmic_vtmon_info },
+ { "ddr-margin-run", .c_fn = cmd_ddr_margin_run },
+ { "ddr-margin-status", .c_fn = cmd_ddr_margin_status },
+ { "ddr-margin-get", .c_fn = cmd_ddr_margin_get },
+ { "ddr-stats-run", .c_fn = cmd_ddr_stats_run },
+ { "ddr-stats-get", .c_fn = cmd_ddr_stats_get },
+ { "reboot-mode-set", .c_fn = cmd_reboot_mode_set },
+ { "curr-cxl-boot-mode-get", .c_fn = cmd_curr_cxl_boot_mode_get },
+ { "pcie-eye-run", .c_fn = cmd_pcie_eye_run },
+ { "pcie-eye-status", .c_fn = cmd_pcie_eye_status },
+ { "pcie-eye-get", .c_fn = cmd_pcie_eye_get },
+ { "get-cxl-link-status", .c_fn = cmd_get_cxl_link_status },
+ { "get-device-info", .c_fn = cmd_get_device_info },
+ { "read-ddr-temp", .c_fn = cmd_read_ddr_temp },
+ { "cxl-hpa-to-dpa", .c_fn = cmd_cxl_hpa_to_dpa },
+ { "get-cxl-membridge-errors", .c_fn = cmd_get_cxl_membridge_errors },
+ { "get-ddr-bw", .c_fn = cmd_get_ddr_bw },
+ { "get-ddr-latency", .c_fn = cmd_get_ddr_latency },
+ { "i2c-read", .c_fn = cmd_i2c_read },
+ { "i2c-write", .c_fn = cmd_i2c_write },
+ { "get-ddr-ecc-err-info", .c_fn = cmd_get_ddr_ecc_err_info },
+ { "start-ddr-ecc-scrub", .c_fn = cmd_start_ddr_ecc_scrub },
+ { "ddr-ecc-scrub-status", .c_fn = cmd_ddr_ecc_scrub_status },
+ { "ddr-cont-scrub-status", .c_fn = cmd_ddr_cont_scrub_status },
+ { "ddr-cont-scrub-set", .c_fn = cmd_ddr_cont_scrub_set },
+ { "ddr-init-status", .c_fn = cmd_ddr_init_status },
+ { "get-cxl-membridge-stats", .c_fn = cmd_get_cxl_membridge_stats },
+ { "trigger-coredump", .c_fn = cmd_trigger_coredump },
+ { "ddr-err-inj-en", .c_fn = cmd_ddr_err_inj_en },
+ { "ddr-dimm-level-training-status", .c_fn = cmd_ddr_dimm_level_training_status },
+ { "ddr-param-set", .c_fn = cmd_ddr_param_set },
+ { "ddr-param-get", .c_fn = cmd_ddr_param_get },
+ { "core-volt-set", .c_fn = cmd_core_volt_set },
+ { "core-volt-get", .c_fn = cmd_core_volt_get },
+ { "oem-err-inj-viral", .c_fn = cmd_oem_err_inj_viral },
+ { "err-inj-ll-poison", .c_fn = cmd_err_inj_ll_poison },
+ { "pci-err-inj", .c_fn = cmd_pci_err_inj },
+ { "read-ltssm-states", .c_fn = cmd_read_ltssm_states },
+ { "ddr-page-select-set", .c_fn = cmd_ddr_page_select_set },
+ { "ddr-page-select-get", .c_fn = cmd_ddr_page_select_get },
};
int main(int argc, const char **argv)
diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index ba265ed..6fcb20e 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -1471,6 +1471,7 @@ out:
}
#define CEL_UUID "0da9c0b5-bf41-4b78-8f79-96b1623b3f17"
+#define VENDOR_LOG_UUID "5e1819d9-11a9-400c-811f-d60719403d86"
struct cxl_mbox_get_log {
uuid_t uuid;
@@ -1483,13 +1484,15 @@ struct cel_entry {
__le16 effect;
} __attribute__((packed));
-CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char* uuid)
+CXL_EXPORT int cxl_memdev_get_log(struct cxl_memdev *memdev, const char* uuid, const unsigned int data_size)
{
struct cxl_cmd *cmd;
struct cxl_mbox_get_log *get_log_input;
struct cel_entry *cel_entries;
int no_cel_entries;
int rc = 0;
+ int remaining_bytes = data_size;
+ unsigned int bytes_read = 0;
if (!uuid) {
fprintf(stderr, "%s: Please specify log uuid argument\n",
@@ -1497,49 +1500,63 @@ CXL_EXPORT int cxl_memdev_get_cel_log(struct cxl_memdev *memdev, const char* uui
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",
- cxl_memdev_get_devname(memdev));
- return -ENOMEM;
- }
+ do {
+ cmd = cxl_cmd_new_generic(memdev, CXL_MEM_COMMAND_ID_GET_LOG);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_memdev_get_log returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
- get_log_input = (void *) cmd->send_cmd->in.payload;
- uuid_parse(uuid, get_log_input->uuid);
- get_log_input->offset = 0;
- get_log_input->length = cmd->memdev->payload_max;
+ get_log_input = (void *) cmd->send_cmd->in.payload;
+ uuid_parse(uuid, get_log_input->uuid);
+ get_log_input->offset = bytes_read;
+ get_log_input->length = cmd->memdev->payload_max;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
- rc = cxl_cmd_submit(cmd);
- if (rc < 0) {
- fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
- cxl_memdev_get_devname(memdev), rc, strerror(-rc));
- goto out;
- }
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
- rc = cxl_cmd_get_mbox_status(cmd);
- if (rc != 0) {
- fprintf(stderr, "%s: firmware status: %d:\n%s\n",
- cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
- rc = -ENXIO;
- goto out;
- }
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_LOG) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_LOG);
+ return -EINVAL;
+ }
- if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_LOG) {
- fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
- cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_LOG);
- return -EINVAL;
- }
+ fprintf(stdout, "payload info\n");
+ fprintf(stdout, " out size: 0x%x\n", cmd->send_cmd->out.size);
+
+ if (!strcmp(uuid, CEL_UUID)) {
+ cel_entries = (void *)cmd->send_cmd->out.payload;
+ no_cel_entries = (cmd->send_cmd->out.size)/sizeof(struct cel_entry);
+ fprintf(stdout, " no_cel_entries size: %d\n", no_cel_entries);
+ for (int e = 0; e < no_cel_entries; ++e) {
+ fprintf(stdout, " cel_entry[%d] opcode: 0x%x, effect: 0x%x\n", e,
+ le16_to_cpu(cel_entries[e].opcode),
+ le16_to_cpu(cel_entries[e].effect));
+ }
+ } else if (!strcmp(uuid, VENDOR_LOG_UUID)) {
+ fprintf(stdout, " number of received bytes = %d\n", cmd->send_cmd->out.size);
+ fprintf(stdout, "%s", (char *)cmd->send_cmd->out.payload);
+ }
- fprintf(stdout, "payload info\n");
- fprintf(stdout, " out size: 0x%x\n", cmd->send_cmd->out.size);
- cel_entries = (void *)cmd->send_cmd->out.payload;
- no_cel_entries = (cmd->send_cmd->out.size)/sizeof(struct cel_entry);
- fprintf(stdout, " no_cel_entries size: %d\n", no_cel_entries);
- for (int e = 0; e < no_cel_entries; ++e) {
- fprintf(stdout, " cel_entry[%d] opcode: 0x%x, effect: 0x%x\n", e,
- le16_to_cpu(cel_entries[e].opcode),
- le16_to_cpu(cel_entries[e].effect));
- }
+ /* keep getting the data in chunks of payload max */
+ bytes_read += cmd->send_cmd->out.size;
+ if (remaining_bytes >= cmd->send_cmd->out.size)
+ remaining_bytes -= cmd->send_cmd->out.size;
+ else
+ remaining_bytes = 0;
+ } while(remaining_bytes);
out:
cxl_cmd_unref(cmd);
return rc;
@@ -2342,6 +2359,7 @@ out:
#define CXL_MEM_COMMAND_ID_GET_FW_INFO CXL_MEM_COMMAND_ID_RAW
#define CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE 512
+#define CXL_MEM_COMMAND_ID_GET_OS_INFO_OPCODE 0xcd03
#define CXL_MEM_COMMAND_ID_GET_FW_INFO_PAYLOAD_OUT_SIZE 80
@@ -2356,7 +2374,7 @@ struct cxl_mbox_get_fw_info_out {
char slot_4_fw_rev[16];
} __attribute__((packed));
-CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
+CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev, bool is_os_img)
{
struct cxl_cmd *cmd;
struct cxl_mbox_get_fw_info_out *get_fw_info_out;
@@ -2365,8 +2383,19 @@ CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
u8 active_slot;
u8 staged_slot_mask;
u8 staged_slot;
+ int opcode;
+ char *fw_name;
+
+ //select vendor cci command if os image is specified, else default to cxl FW_INFO command
+ if (is_os_img) {
+ opcode = CXL_MEM_COMMAND_ID_GET_OS_INFO_OPCODE;
+ fw_name = "OS";
+ } else {
+ opcode = CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE;
+ fw_name = "FW";
+ }
- cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_FW_INFO_OPCODE);
+ cmd = cxl_cmd_new_raw(memdev, opcode);
if (!cmd) {
fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
cxl_memdev_get_devname(memdev));
@@ -2401,17 +2430,17 @@ CXL_EXPORT int cxl_memdev_get_fw_info(struct cxl_memdev *memdev)
staged_slot = get_fw_info_out->fw_slot_info & staged_slot_mask;
staged_slot = staged_slot>>3;
fprintf(stdout, "================================= get fw info ==================================\n");
- fprintf(stdout, "FW Slots Supported: %x\n", get_fw_info_out->fw_slots_supp);
- fprintf(stdout, "Active FW Slot: %x\n", active_slot);
+ fprintf(stdout, "%s Slots Supported: %x\n", fw_name, get_fw_info_out->fw_slots_supp);
+ fprintf(stdout, "Active %s Slot: %x\n", fw_name, active_slot);
if (staged_slot)
{
- fprintf(stdout, "Staged FW Slot: %x\n", staged_slot);
+ fprintf(stdout, "Staged %s Slot: %x\n", fw_name, staged_slot);
}
- fprintf(stdout, "FW Activation Capabilities: %x\n", get_fw_info_out->fw_activation_capas);
- fprintf(stdout, "Slot 1 FW Revision: %s\n", get_fw_info_out->slot_1_fw_rev);
- fprintf(stdout, "Slot 2 FW Revision: %s\n", get_fw_info_out->slot_2_fw_rev);
- fprintf(stdout, "Slot 3 FW Revision: %s\n", get_fw_info_out->slot_3_fw_rev);
- fprintf(stdout, "Slot 4 FW Revision: %s\n", get_fw_info_out->slot_4_fw_rev);
+ fprintf(stdout, "%s Activation Capabilities: %x\n", fw_name, get_fw_info_out->fw_activation_capas);
+ fprintf(stdout, "Slot 1 %s Revision: %s\n", fw_name, get_fw_info_out->slot_1_fw_rev);
+ fprintf(stdout, "Slot 2 %s Revision: %s\n", fw_name, get_fw_info_out->slot_2_fw_rev);
+ fprintf(stdout, "Slot 3 %s Revision: %s\n", fw_name, get_fw_info_out->slot_3_fw_rev);
+ fprintf(stdout, "Slot 4 %s Revision: %s\n", fw_name, get_fw_info_out->slot_4_fw_rev);
out:
cxl_cmd_unref(cmd);
@@ -6301,8 +6330,8 @@ struct cxl_mbox_health_counters_get_out {
__le32 cxl_mem_link_crc_errors;
__le32 cxl_io_link_lcrc_errors;
__le32 cxl_io_link_ecrc_errors;
- __le32 num_ddr_single_ecc_errors;
- __le32 num_ddr_double_ecc_errors;
+ __le32 num_ddr_correctable_ecc_errors;
+ __le32 num_ddr_uncorrectable_ecc_errors;
__le32 link_recovery_events;
__le32 time_in_throttled;
__le32 over_temperature_warning_level_exceeded;
@@ -6311,6 +6340,16 @@ struct cxl_mbox_health_counters_get_out {
__le32 rx_retry_request;
__le32 rcmd_qs0_hi_threshold_detect;
__le32 rcmd_qs1_hi_threshold_detect;
+ __le32 num_pscan_correctable_ecc_errors;
+ __le32 num_pscan_uncorrectable_ecc_errors;
+ __le32 num_ddr_dimm0_correctable_ecc_errors;
+ __le32 num_ddr_dimm0_uncorrectable_ecc_errors;
+ __le32 num_ddr_dimm1_correctable_ecc_errors;
+ __le32 num_ddr_dimm1_uncorrectable_ecc_errors;
+ __le32 num_ddr_dimm2_correctable_ecc_errors;
+ __le32 num_ddr_dimm2_uncorrectable_ecc_errors;
+ __le32 num_ddr_dimm3_correctable_ecc_errors;
+ __le32 num_ddr_dimm3_uncorrectable_ecc_errors;
} __attribute__((packed));
CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
@@ -6358,14 +6397,23 @@ CXL_EXPORT int cxl_memdev_health_counters_get(struct cxl_memdev *memdev)
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, "9: NUM_DDR_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_correctable_ecc_errors));
+ fprintf(stdout, "10: NUM_DDR_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_uncorrectable_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));
-
+ fprintf(stdout, "16: NUM_PSCAN_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_pscan_correctable_ecc_errors));
+ fprintf(stdout, "17: NUM_PSCAN_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_pscan_uncorrectable_ecc_errors));
+ fprintf(stdout, "18: NUM_DDR_DIMM0_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm0_correctable_ecc_errors));
+ fprintf(stdout, "19: NUM_DDR_DIMM0_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm0_uncorrectable_ecc_errors));
+ fprintf(stdout, "20: NUM_DDR_DIMM1_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm1_correctable_ecc_errors));
+ fprintf(stdout, "21: NUM_DDR_DIMM1_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm1_uncorrectable_ecc_errors));
+ fprintf(stdout, "22: NUM_DDR_DIMM2_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm2_correctable_ecc_errors));
+ fprintf(stdout, "23: NUM_DDR_DIMM2_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm2_uncorrectable_ecc_errors));
+ fprintf(stdout, "24: NUM_DDR_DIMM3_COR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm3_correctable_ecc_errors));
+ fprintf(stdout, "25: NUM_DDR_DIMM3_UNCOR_ECC_ERRORS = %d\n", le32_to_cpu(health_counters_get_out->num_ddr_dimm3_uncorrectable_ecc_errors));
out:
cxl_cmd_unref(cmd);
return rc;
@@ -10123,3 +10171,4373 @@ out:
cxl_cmd_unref(cmd);
return rc;
}
+
+#define MAX_PMIC 8
+#define PMIC_NAME_MAX_SIZE 20
+
+struct pmic_data {
+ char pmic_name[PMIC_NAME_MAX_SIZE];
+ float vin;
+ float vout;
+ float iout;
+ float powr;
+ float temp;
+};
+struct cxl_pmic_vtmon_info_out {
+ struct pmic_data pmic_data[MAX_PMIC];
+} __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_OPCODE 0xFB00
+#define CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_PAYLOAD_IN_SIZE 0
+
+CXL_EXPORT int cxl_memdev_pmic_vtmon_info(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_pmic_vtmon_info_out *pmic_vtmon_info;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ cinfo->size_in = CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_PMIC_VTMON_INFO);
+ return -EINVAL;
+ }
+
+ pmic_vtmon_info = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "=========================== PMIC VTMON SLOT INFO ============================\n");
+ for (int i = 0; i < MAX_PMIC; i++) {
+ fprintf(stdout, "pmic name: %s\n", pmic_vtmon_info->pmic_data[i].pmic_name);
+ fprintf(stdout, "vin: %f\n", pmic_vtmon_info->pmic_data[i].vin);
+ fprintf(stdout, "vout: %f\n", pmic_vtmon_info->pmic_data[i].vout);
+ fprintf(stdout, "iout: %f\n", pmic_vtmon_info->pmic_data[i].iout);
+ fprintf(stdout, "powr: %f\n", pmic_vtmon_info->pmic_data[i].powr);
+ fprintf(stdout, "temp: %f\n", pmic_vtmon_info->pmic_data[i].temp);
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR MARGIN */
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_OPCODE 0xFB0A
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_ddr_margin_run_in {
+ u8 slice_num;
+ u8 rd_wr_margin;
+ u8 ddr_id;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_run(struct cxl_memdev *memdev,
+ u8 slice_num, u8 rd_wr_margin, u8 ddr_id)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_ddr_margin_run_in *ddr_margin_run_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_margin_run_in = (void *) cmd->send_cmd->in.payload;
+
+ ddr_margin_run_in->slice_num = slice_num;
+ ddr_margin_run_in->rd_wr_margin = rd_wr_margin;
+ ddr_margin_run_in->ddr_id = ddr_id;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_RUN);
+ return -EINVAL;
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS_OPCODE 0xFB0B
+
+struct cxl_ddr_margin_status_out {
+ int run_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_margin_status_out *ddr_margin_status_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_MARGIN_SW_STATUS);
+ return -EINVAL;
+ }
+ ddr_margin_status_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "%s\n", ddr_margin_status_out->run_status ?
+ "DDR MARGIN IS RUNNING" : "DDR MARGIN IS NOT RUNNING/FINISHED");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW_OPCODE 0xFB0C
+
+/* MAX_NUM_ROWS per BIT_COUNT should be in Sync with the FW Mbox DDR MARGIN code */
+#define MAX_NUM_ROWS 1024
+#define MAX_MARGIN_BIT_COUNT 8
+
+struct ddr_margin_info
+{
+ uint32_t slicenumber;
+ uint32_t bitnumber;
+ int32_t vreflevel;
+ int margin_low;
+ int margin_high;
+ double min_delay_ps;
+ double max_delay_ps;
+} __attribute__((packed));;
+
+struct cxl_ddr_margin_get_sw_out
+{
+ uint32_t row_count;
+ struct ddr_margin_info ddr_margin_slice_data[MAX_NUM_ROWS * MAX_MARGIN_BIT_COUNT];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_margin_get(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_margin_get_sw_out *ddr_margin_get_sw_out;
+ int rc = 0;
+ uint32_t i;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_MARGIN_GET_SW);
+ return -EINVAL;
+ }
+ ddr_margin_get_sw_out = (struct cxl_ddr_margin_get_sw_out *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "SliceNo,bitNo, VrefLv, MinDelay, MaxDelay, MinDly(ps), MaxDly(ps)\n");
+
+ for(i = 0; i < ddr_margin_get_sw_out->row_count; i++)
+ {
+ fprintf(stdout, "%d,%d,%d,%d,%d,%3.2f,%3.2f\n",
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].slicenumber,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].bitnumber,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].vreflevel,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].margin_low,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].margin_high,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].min_delay_ps,
+ ddr_margin_get_sw_out->ddr_margin_slice_data[i].max_delay_ps);
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR STATS START */
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN_OPCODE 0xFB1B
+#define CXL_MEM_COMMAND_ID_DDR_STATS_RUN_PAYLOAD_IN_SIZE 9
+
+struct cxl_mbox_ddr_stats_run_in {
+ uint8_t ddr_id;
+ uint32_t monitor_time;
+ uint32_t loop_count;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_stats_run(struct cxl_memdev *memdev,
+ u8 ddr_id, uint32_t monitor_time, uint32_t loop_count)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_ddr_stats_run_in *ddr_stats_run_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_RUN_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_STATS_RUN_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_stats_run_in = (void *) cmd->send_cmd->in.payload;
+
+ ddr_stats_run_in->ddr_id = ddr_id;
+ ddr_stats_run_in->monitor_time = monitor_time;
+ ddr_stats_run_in->loop_count = loop_count;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_STATS_RUN) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_STATS_RUN);
+ return -EINVAL;
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_STATUS_OPCODE 0xFB1C
+
+struct cxl_ddr_stats_status_out {
+ int run_status;
+ uint32_t loop_count;
+} __attribute__((packed));
+
+/* DDR STATS STATUS */
+CXL_EXPORT int cxl_memdev_ddr_stats_status(struct cxl_memdev *memdev, int* run_status, uint32_t* loop_count)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_stats_status_out *ddr_stats_status_out;
+
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_STATS_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_STATS_STATUS);
+ return -EINVAL;
+ }
+ ddr_stats_status_out = (void *)cmd->send_cmd->out.payload;
+ *run_status = ddr_stats_status_out->run_status;
+ *loop_count = ddr_stats_status_out->loop_count;
+
+ fprintf(stdout, "%s\n", ddr_stats_status_out->run_status ?
+ "DDR STATS IS BUSY" : "DDR STATS IS NOT RUNNING/FINISHED");
+
+ fprintf(stdout, "Loop Count = %d\n", ddr_stats_status_out->loop_count);
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET_OPCODE 0xFB1D
+
+#define NUM_BANK 16
+#define NUM_CS 4
+
+struct dfi_cs_pm {
+ uint32_t mrw_cnt;
+ uint32_t refresh_cnt;
+ uint32_t act_cnt;
+ uint32_t write_cnt;
+ uint32_t read_cnt;
+ uint32_t pre_cnt;
+ uint32_t rr_cnt;
+ uint32_t ww_cnt;
+ uint32_t rw_cnt;
+} __attribute__((packed));
+
+struct dfi_cs_bank_pm {
+ uint32_t bank_act_cnt;
+ uint32_t bank_wr_cnt;
+ uint32_t bank_rd_cnt;
+ uint32_t bank_pre_cnt;
+} __attribute__((packed));
+
+struct dfi_mc_pm {
+ uint32_t cmd_queue_full_events;
+ uint32_t info_fifo_full_events;
+ uint32_t wrdata_hold_fifo_full_events;
+ uint32_t port_cmd_fifo0_full_events;
+ uint32_t port_wrresp_fifo0_full_events;
+ uint32_t port_wr_fifo0_full_events;
+ uint32_t port_rd_fifo0_full_events;
+ uint32_t port_cmd_fifo1_full_events;
+ uint32_t port_wrresp_fifo1_full_events;
+ uint32_t port_wr_fifo1_full_events;
+ uint32_t port_rd_fifo1_full_events;
+ uint32_t ecc_dataout_corrected;
+ uint32_t ecc_dataout_uncorrected;
+ uint32_t pd_ex;
+ uint32_t pd_en;
+ uint32_t srex;
+ uint32_t sren;
+ uint32_t write;
+ uint32_t read;
+ uint32_t rmw;
+ uint32_t bank_act;
+ uint32_t precharge;
+ uint32_t precharge_all;
+ uint32_t mrw;
+ uint32_t auto_ref;
+ uint32_t rw_auto_pre;
+ uint32_t zq_cal_short;
+ uint32_t zq_cal_long;
+ uint32_t same_addr_ww_collision;
+ uint32_t same_addr_wr_collision;
+ uint32_t same_addr_rw_collision;
+ uint32_t same_addr_rr_collision;
+} __attribute__((packed));
+
+struct ddr_pmon_data {
+ uint64_t fr_cnt;
+ uint32_t idle_cnt;
+ uint32_t rd_ot_cnt;
+ uint32_t wr_ot_cnt;
+ uint32_t wrd_ot_cnt;
+ uint32_t rd_cmd_cnt;
+ uint32_t rd_cmd_busy_cnt;
+ uint32_t wr_cmd_cnt;
+ uint32_t wr_cmd_busy_cnt;
+ uint32_t rd_data_cnt;
+ uint32_t rd_data_busy_cnt;
+ uint32_t wr_data_cnt;
+ uint32_t wr_data_busy_cnt;
+ uint64_t rd_avg_lat;
+ uint64_t wr_avg_lat;
+ uint32_t rd_trans_smpl_cnt;
+ uint32_t wr_trans_smpl_cnt;
+} __attribute__((packed));
+
+struct ddr_data {
+ struct ddr_pmon_data pmon;
+ struct dfi_cs_pm cs_pm[NUM_CS];
+ struct dfi_cs_bank_pm cs_bank_pm[NUM_CS][NUM_BANK];
+ struct dfi_mc_pm mc_pm;
+} __attribute__((packed));
+
+struct ddr_stats_data {
+ struct ddr_data stats;
+} __attribute__((packed));
+
+typedef struct ddr_stats_data ddr_stats_data_t;
+
+#define MAX_CXL_TRANSFER_SZ (16 * 1024)
+
+static void display_pmon_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+ uint32_t loop;
+ fprintf(stderr,"PMON STATS:\n");
+ fprintf(stderr,
+ "iteration, fr_cnt, idle_cnt, rd_ot_cnt, wr_ot_cnt, wrd_ot_cnt, "
+ "rd_cmd_cnt, rd_cmd_busy_cnt, wr_cmd_cnt, wr_cmd_busy_cnt, rd_data_cnt, "
+ "rd_data_busy_cnt, wr_data_cnt, wr_data_busy_cnt, "
+ "rd_avg_lat, wr_avg_lat, rd_trans_smpl_cnt, wr_trans_smpl_cnt\n");
+ for (loop = 0; loop < loop_count; loop++) {
+ fprintf(stderr,
+ "[%d], %lu, %u, %u, %u, %u, "
+ "%u, %u, %u, %u, %u, "
+ "%u, %u, %u, "
+ "%lu, %lu, %u, %u\n",
+ loop,
+ disp_stats->stats.pmon.fr_cnt,
+ disp_stats->stats.pmon.idle_cnt,
+ disp_stats->stats.pmon.rd_ot_cnt,
+ disp_stats->stats.pmon.wr_ot_cnt,
+ disp_stats->stats.pmon.wrd_ot_cnt,
+ disp_stats->stats.pmon.rd_cmd_cnt,
+ disp_stats->stats.pmon.rd_cmd_busy_cnt,
+ disp_stats->stats.pmon.wr_cmd_cnt,
+ disp_stats->stats.pmon.wr_cmd_busy_cnt,
+ disp_stats->stats.pmon.rd_data_cnt,
+ disp_stats->stats.pmon.rd_data_busy_cnt,
+ disp_stats->stats.pmon.wr_data_cnt,
+ disp_stats->stats.pmon.wr_data_busy_cnt,
+ disp_stats->stats.pmon.rd_avg_lat,
+ disp_stats->stats.pmon.wr_avg_lat,
+ disp_stats->stats.pmon.rd_trans_smpl_cnt,
+ disp_stats->stats.pmon.wr_trans_smpl_cnt);
+ disp_stats++;
+ }
+ fprintf(stderr,"\n");
+}
+
+static void display_cs_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+ uint32_t rank, loop;
+
+ fprintf(stderr, "CS PM STATS:\n");
+ fprintf(stderr,
+ "iteration, rank, mrw_cnt, refresh_cnt, act_cnt, write_cnt, "
+ "read_cnt, pre_cnt, rr_cnt, ww_cnt, rw_cnt\n ");
+
+ for (loop = 0; loop < loop_count; loop++) {
+ for (rank = 0; rank < NUM_CS; rank++) {
+ fprintf(stderr,
+ "[%d], %d, %u, %u, %u, %u, "
+ "%u, %u, %u, %u, %u\n",
+ loop,
+ rank,
+ disp_stats->stats.cs_pm[rank].mrw_cnt,
+ disp_stats->stats.cs_pm[rank].refresh_cnt,
+ disp_stats->stats.cs_pm[rank].act_cnt,
+ disp_stats->stats.cs_pm[rank].write_cnt,
+ disp_stats->stats.cs_pm[rank].read_cnt,
+ disp_stats->stats.cs_pm[rank].pre_cnt,
+ disp_stats->stats.cs_pm[rank].rr_cnt,
+ disp_stats->stats.cs_pm[rank].ww_cnt,
+ disp_stats->stats.cs_pm[rank].rw_cnt);
+ }
+ disp_stats++;
+ }
+ fprintf(stderr, "\n");
+}
+
+static void display_cs_bank_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+ uint32_t rank, bank, loop;
+
+ fprintf(stderr, "CS BANK STATS:\n");
+ fprintf(stderr,
+ "iteration, rank, bank, bank_act_cnt, bank_wr_cnt, bank_rd_cnt, bank_pre_cnt\n");
+ for (loop = 0; loop < loop_count; loop++) {
+ for (rank = 0; rank < NUM_CS; rank++) {
+ for (bank = 0; bank < NUM_BANK; bank++) {
+ fprintf(stderr,
+ "[%d], %d, %d, %u, %u, %u, %u\n",
+ loop,
+ rank,
+ bank,
+ disp_stats->stats.cs_bank_pm[rank][bank].bank_act_cnt,
+ disp_stats->stats.cs_bank_pm[rank][bank].bank_wr_cnt,
+ disp_stats->stats.cs_bank_pm[rank][bank].bank_rd_cnt,
+ disp_stats->stats.cs_bank_pm[rank][bank].bank_pre_cnt);
+ }
+ }
+ disp_stats++;
+ }
+ fprintf(stderr, "\n");
+}
+
+static void display_mc_pm_stats(ddr_stats_data_t* disp_stats, uint32_t loop_count) {
+ uint32_t loop;
+
+ fprintf(stderr, "PM STATS:\n");
+ fprintf(stderr,
+ "iteration, cmd_queue_full_events, info_fifo_full_events, "
+ "wrdata_hold_fifo_full_events, port_cmd_fifo0_full_events, "
+ "port_wrresp_fifo0_full_events, port_wr_fifo0_full_events, "
+ "port_rd_fifo0_full_events, port_cmd_fifo1_full_events, "
+ "port_wrresp_fifo1_full_events, port_wr_fifo1_full_events, "
+ "port_rd_fifo1_full_events, ecc_dataout_corrected, "
+ "ecc_dataout_uncorrected, pd_ex, pd_en, srex, sren, "
+ "write, read, rmw, bank_act, precharge, precharge_all, "
+ "mrw, auto_ref, rw_auto_pre, zq_cal_short, zq_cal_long, "
+ "same_addr_ww_collision, same_addr_wr_collision, "
+ "same_addr_rw_collision, same_addr_rr_collision\n");
+
+ for (loop = 0; loop < loop_count; loop++) {
+ fprintf(stderr,
+ "[%d], %u, %u, "
+ "%u, %u, "
+ "%u, %u, "
+ "%u, %u, "
+ "%u, %u, "
+ "%u, %u, "
+ "%u, %u, %u, %u, %u,"
+ "%u, %u, %u, %u, %u, %u,"
+ "%u, %u, %u, %u, %u,"
+ "%u, %u, "
+ "%u, %u\n",
+ loop,
+ disp_stats->stats.mc_pm.cmd_queue_full_events,
+ disp_stats->stats.mc_pm.info_fifo_full_events,
+ disp_stats->stats.mc_pm.wrdata_hold_fifo_full_events,
+ disp_stats->stats.mc_pm.port_cmd_fifo0_full_events,
+ disp_stats->stats.mc_pm.port_wrresp_fifo0_full_events,
+ disp_stats->stats.mc_pm.port_wr_fifo0_full_events,
+ disp_stats->stats.mc_pm.port_rd_fifo0_full_events,
+ disp_stats->stats.mc_pm.port_cmd_fifo1_full_events,
+ disp_stats->stats.mc_pm.port_wrresp_fifo1_full_events,
+ disp_stats->stats.mc_pm.port_wr_fifo1_full_events,
+ disp_stats->stats.mc_pm.port_rd_fifo1_full_events,
+ disp_stats->stats.mc_pm.ecc_dataout_corrected,
+ disp_stats->stats.mc_pm.ecc_dataout_uncorrected,
+ disp_stats->stats.mc_pm.pd_ex,
+ disp_stats->stats.mc_pm.pd_en,
+ disp_stats->stats.mc_pm.srex,
+ disp_stats->stats.mc_pm.sren,
+ disp_stats->stats.mc_pm.write,
+ disp_stats->stats.mc_pm.read,
+ disp_stats->stats.mc_pm.rmw,
+ disp_stats->stats.mc_pm.bank_act,
+ disp_stats->stats.mc_pm.precharge,
+ disp_stats->stats.mc_pm.precharge_all,
+ disp_stats->stats.mc_pm.mrw,
+ disp_stats->stats.mc_pm.auto_ref,
+ disp_stats->stats.mc_pm.rw_auto_pre,
+ disp_stats->stats.mc_pm.zq_cal_short,
+ disp_stats->stats.mc_pm.zq_cal_long,
+ disp_stats->stats.mc_pm.same_addr_ww_collision,
+ disp_stats->stats.mc_pm.same_addr_wr_collision,
+ disp_stats->stats.mc_pm.same_addr_rw_collision,
+ disp_stats->stats.mc_pm.same_addr_rr_collision);
+ disp_stats++;
+ }
+ fprintf(stderr, "\n");
+}
+
+struct cxl_ddr_stats_get_in {
+ uint32_t offset;
+ uint32_t transfer_sz;
+} __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_DDR_STATS_GET_PAYLOAD_IN_SIZE 8
+
+static int cxl_ddr_stats_get(struct cxl_memdev *memdev, unsigned char *dst, int offset, int bytes_to_cpy)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_stats_get_in *ddr_stats_get_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_STATS_GET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_STATS_GET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_stats_get_in = (void *) cmd->send_cmd->in.payload;
+ ddr_stats_get_in->offset = offset;
+ ddr_stats_get_in->transfer_sz = bytes_to_cpy;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_STATS_GET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_STATS_GET);
+ return -EINVAL;
+ }
+
+ memcpy(dst, (unsigned char*) cmd->send_cmd->out.payload, cmd->send_cmd->out.size);
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR GET STATS */
+CXL_EXPORT int cxl_memdev_ddr_stats_get(struct cxl_memdev *memdev)
+{
+ unsigned char *buf;
+ int total_bytes = 0, bytes_to_cpy = 0, bytes_copied = 0;
+ ddr_stats_data_t* ddr_stats_start;
+ int rc = 0;
+ int run_status;
+ uint32_t loop_count;
+
+ rc = cxl_memdev_ddr_stats_status(memdev, &run_status, &loop_count);
+ if (rc < 0)
+ return rc;
+
+ if (run_status)
+ return -EBUSY;
+
+ total_bytes = sizeof(ddr_stats_data_t) * loop_count;
+
+ buf =(unsigned char *)malloc(total_bytes);
+ ddr_stats_start = (ddr_stats_data_t*)buf;
+
+ while(bytes_copied < total_bytes)
+ {
+ bytes_to_cpy = (total_bytes - bytes_copied) < MAX_CXL_TRANSFER_SZ ?
+ (total_bytes - bytes_copied) : MAX_CXL_TRANSFER_SZ;
+ rc = cxl_ddr_stats_get(memdev, buf + bytes_copied, bytes_copied, bytes_to_cpy);
+ bytes_copied = bytes_copied + bytes_to_cpy;
+ if (rc < 0)
+ goto out;
+ }
+
+ display_pmon_stats(ddr_stats_start, loop_count);
+ display_cs_pm_stats(ddr_stats_start, loop_count);
+ display_cs_bank_pm_stats(ddr_stats_start, loop_count);
+ display_mc_pm_stats(ddr_stats_start, loop_count);
+out:
+ free(buf);
+ return rc;
+}
+
+/* REBOOT MODE SET */
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_OPCODE 0xFB0D
+#define CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_PAYLOAD_IN_SIZE 4
+
+#define CXL_IO_MEM_MODE 0x0
+#define CXL_IO_MODE 0xCE
+
+struct cxl_mbox_reboot_mode_set_in {
+ u8 reboot_mode;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_reboot_mode_set(struct cxl_memdev *memdev, u8 reboot_mode)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_reboot_mode_set_in *reboot_mode_set_in;
+ int rc = 0;
+
+ if ((reboot_mode != CXL_IO_MEM_MODE) && (reboot_mode != CXL_IO_MODE)) {
+ fprintf(stderr,"Invalid Reboot Mode");
+ return -EINVAL;
+ }
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_REBOOT_MODE_SET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ reboot_mode_set_in = (void *) cmd->send_cmd->in.payload;
+
+ reboot_mode_set_in->reboot_mode = reboot_mode;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_REBOOT_MODE_SET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_REBOOT_MODE_SET);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET_OPCODE 0xFB0E
+
+struct cxl_curr_cxl_boot_mode_out
+{
+ uint8_t curr_cxl_boot;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_curr_cxl_boot_mode_get(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_curr_cxl_boot_mode_out *curr_cxl_boot_mode_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_CXL_CURR_BOOT_MODE_GET);
+ return -EINVAL;
+ }
+
+ curr_cxl_boot_mode_out = (struct cxl_curr_cxl_boot_mode_out *)cmd->send_cmd->out.payload;
+ if (curr_cxl_boot_mode_out->curr_cxl_boot == CXL_IO_MEM_MODE)
+ fprintf(stdout, "CXL_IO_MEM_MODE\n");
+ else if (curr_cxl_boot_mode_out->curr_cxl_boot == CXL_IO_MODE)
+ fprintf(stdout, "CXL_IO_MODE\n");
+ else
+ fprintf(stdout, "Invalid Mode\n");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_OPCODE 0xFB02
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_pcie_eye_run_in {
+ u8 lane;
+ u8 sw_scan;
+ u8 ber;
+} __attribute__((packed));
+
+struct cxl_pcie_eye_run_out {
+ int pcie_eye_run_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_run(struct cxl_memdev *memdev,
+ u8 lane, u8 sw_scan, u8 ber)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_pcie_eye_run_in *pcie_eye_run_in;
+ struct cxl_pcie_eye_run_out *pcie_eye_run_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ pcie_eye_run_in = (void *) cmd->send_cmd->in.payload;
+
+ pcie_eye_run_in->lane = lane;
+ pcie_eye_run_in->sw_scan = sw_scan;
+ pcie_eye_run_in->ber = ber;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_PCIE_EYE_SW_RUN);
+ return -EINVAL;
+ }
+
+ pcie_eye_run_out = (void *)cmd->send_cmd->out.payload;
+ if (!pcie_eye_run_out->pcie_eye_run_status)
+ fprintf(stdout, "pcie eye is running\n");
+ else
+ fprintf(stdout, "pcie eye already running OR fault, error : %d\n",
+ pcie_eye_run_out->pcie_eye_run_status);
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS_OPCODE 0xFB03
+
+struct cxl_pcie_eye_status_out {
+ int pcie_eye_status;
+ int error;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_pcie_eye_status_out *pcie_eye_status_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_PCIE_EYE_SW_STATUS);
+ return -EINVAL;
+ }
+ pcie_eye_status_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "%s\n", pcie_eye_status_out->pcie_eye_status ?
+ "PCIE EYE SW IS RUNNING" : "PCIE EYE SW IS NOT RUNNING/FINISHED");
+ if(pcie_eye_status_out->error)
+ fprintf(stdout, "pcie eye run error %d:\n", pcie_eye_status_out->error);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW_OPCODE 0xFB04
+
+#define NUM_EYESCOPE_HORIZ_VALS 40
+#define TOTAL_EYESCOPE_HORIZ_VALS ((NUM_EYESCOPE_HORIZ_VALS * 2) + 1)
+
+struct cxl_pcie_eye_get_sw_out {
+ char pcie_eye_data[TOTAL_EYESCOPE_HORIZ_VALS + 1];
+} __attribute__((packed));
+
+struct cxl_pcie_eye_get_sw_in {
+ uint offset;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_sw(struct cxl_memdev *memdev, uint offset)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_pcie_eye_get_sw_in *pcie_eye_get_sw_in;
+ struct cxl_pcie_eye_get_sw_out *pcie_eye_get_sw_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ pcie_eye_get_sw_in = (void *) cmd->send_cmd->in.payload;
+ pcie_eye_get_sw_in->offset = offset;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_PCIE_EYE_GET_SW);
+ return -EINVAL;
+ }
+ pcie_eye_get_sw_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "%s\n", pcie_eye_get_sw_out->pcie_eye_data);
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW_OPCODE 0xFB05
+
+struct eyescope_results {
+ double merged_horizontal_eye_left;
+ double merged_horizontal_eye_right;
+ double merged_vertical_eye_top;
+ double merged_vertical_eye_bottom;
+};
+
+struct rx_settings_t {
+ int iskew_signed;
+ int qskew_signed;
+ int dlev00_signed;
+ int dlev01_signed;
+ int dlev10_signed;
+ int dlev11_signed;
+ int irphase_signed;
+ int h1po;
+ int h1no;
+ int h1pe;
+ int h1ne;
+ int h2;
+ int h3;
+ int h4;
+ int h5;
+ int h6;
+ int h7;
+ int h8;
+ int h9;
+ int aeq;
+ int vga;
+ int appmd;
+ int rxrt;
+ int shd;
+ int step;
+ int wm;
+};
+
+
+struct cxl_pcie_eye_get_hw_out {
+ struct eyescope_results eyescope_results;
+ struct rx_settings_t rx_settings_t;
+ int eyescope_request_status;
+} __attribute__((packed));
+
+
+void display_rx_setttings(struct rx_settings_t *settings);
+void display_rx_setttings(struct rx_settings_t *settings)
+{
+ fprintf(stdout, "rx_settings: \n");
+ fprintf(stdout, "dlv0123 = [%d, %d, %d, %d],", settings->dlev00_signed, settings->dlev01_signed,
+ settings->dlev10_signed, settings->dlev11_signed);
+ fprintf(stdout, "*vga, aeq = [%d, %d],", settings->vga, settings->aeq);
+ fprintf(stdout, "h2-9 = [%d, %d, %d, %d, %d, %d, %d, %d],",
+ settings->h2, settings->h3, settings->h4, settings->h5,
+ settings->h6, settings->h7, settings->h8, settings->h9);
+ fprintf(stdout, "appmd, rxrt, shd, wm = [%d, %d, 'g%d', %d],",
+ settings->appmd, settings->rxrt, settings->shd, settings->wm);
+ fprintf(stdout, "h1ne/0, pe/o = [%d %d %d %d],", settings->h1ne, settings->h1no,
+ settings->h1pe, settings->h1po);
+ fprintf(stdout, "iskw, qskw = [%d %d]", settings->iskew_signed, settings->qskew_signed);
+ fprintf(stdout, "\n");
+}
+
+void display_merged_eye_results(struct eyescope_results *eyescope_results);
+void display_merged_eye_results(struct eyescope_results *eyescope_results){
+
+ fprintf(stdout, "Merged Top (mV): %f\n",
+ eyescope_results->merged_vertical_eye_top);
+ fprintf(stdout, "Merged Bottom (mV): %f\n",
+ eyescope_results->merged_vertical_eye_bottom);
+ fprintf(stdout, "Merged Right Eye (UI): %f\n",
+ eyescope_results->merged_horizontal_eye_right);
+ fprintf(stdout, "Merged Left Eye (UI): %f\n",
+ eyescope_results->merged_horizontal_eye_left);
+}
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_hw(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_pcie_eye_get_hw_out *pcie_eye_get_hw_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_PCIE_EYE_GET_HW);
+ return -EINVAL;
+ }
+ pcie_eye_get_hw_out = (void *)cmd->send_cmd->out.payload;
+ if (pcie_eye_get_hw_out->eyescope_request_status) {
+ fprintf(stdout, "eyescope request status: PASS\n");
+ display_rx_setttings(&pcie_eye_get_hw_out->rx_settings_t);
+ display_merged_eye_results(&pcie_eye_get_hw_out->eyescope_results);
+ } else {
+ fprintf(stdout, "eyescope request status: FAIL\n");
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER_OPCODE 0xFB06
+
+struct cxl_pcie_eye_get_sw_ber_out {
+ float horiz_margin;
+ float vert_margin;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_pcie_eye_get_sw_ber(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_pcie_eye_get_sw_ber_out *pcie_eye_get_sw_ber_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed OR BER is not enabled, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_PCIE_EYE_SW_BER);
+ return -EINVAL;
+ }
+ pcie_eye_get_sw_ber_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "Extrapolation for BER at 1e-12\n");
+ if(pcie_eye_get_sw_ber_out->vert_margin > 18 && pcie_eye_get_sw_ber_out->horiz_margin > 0.2) {
+ fprintf(stdout, "Eye Height and width margins are > 0.2UI and 18mV, Test PASSED\n");
+ fprintf(stdout, "Eye width margin at 1e-12 is %f UI\n", pcie_eye_get_sw_ber_out->horiz_margin);
+ fprintf(stdout, "Eye height margin at 1e-12 is %f mV\n", pcie_eye_get_sw_ber_out->vert_margin);
+ } else {
+ fprintf(stdout, "Eye Height and width margins are not greater than 0.2UI and 18mV, Test FAILED\n");
+ }
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS_OPCODE 0xFB07
+
+char ltssm_state_name[][20] =
+{
+ "DETECT_QUIET",
+ "DETECT_ACT",
+ "POLL_ACTIVE",
+ "POLL_COMPLIANCE",
+ "POLL_CONFIG",
+ "PRE_DETECT_QUIET",
+ "DETECT_WAIT",
+ "CFG_LINKWD_START",
+ "CFG_LINKWD_ACEPT",
+ "CFG_LANENUM_WAIT",
+ "CFG_LANENUM_ACEPT",
+ "CFG_COMPLETE",
+ "CFG_IDLE",
+ "RCVRY_LOCK",
+ "RCVRY_SPEED",
+ "RCVRY_RCVRCFG",
+ "RCVRY_IDLE",
+ "L0",
+ "L0S",
+ "L123_SEND_EIDLE",
+ "L1_IDLE",
+ "L2_IDLE",
+ "L2_WAKE",
+ "DISABLED_ENTRY",
+ "DISABLED_IDLE",
+ "DISABLED",
+ "LPBK_ENTRY",
+ "LPBK_ACTIVE",
+ "LPBK_EXIT",
+ "LPBK_EXIT_TIMEOUT",
+ "HOT_RESET_ENTRY",
+ "HOT_RESET",
+ "RCVRY_EQ0",
+ "RCVRY_EQ1",
+ "RCVRY_EQ2",
+ "RCVRY_EQ3"
+};
+
+struct cxl_get_cxl_link_status_out {
+ float cxl_link_status;
+ uint32_t link_width;
+ uint32_t link_speed;
+ uint32_t ltssm_val;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_cxl_link_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_get_cxl_link_status_out *get_cxl_link_status_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_CXL_LINK_STATUS);
+ return -EINVAL;
+ }
+ get_cxl_link_status_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "Link is in CXL%0.1f mode\n", get_cxl_link_status_out->cxl_link_status);
+ fprintf(stdout, "Negotiated link width: x%d\n", get_cxl_link_status_out->link_width);
+ fprintf(stdout, "Negotiated link speed: Gen%d\n", get_cxl_link_status_out->link_speed);
+ fprintf(stdout, "ltssm state: %s, code 0x%x\n", ltssm_state_name[get_cxl_link_status_out->ltssm_val], get_cxl_link_status_out->ltssm_val);
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DEVICE_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DEVICE_INFO_OPCODE 0xFB08
+
+struct cxl_get_device_info_out {
+ uint16_t device_id;
+ uint8_t revision_id;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_device_info(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_get_device_info_out *get_device_info_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DEVICE_INFO_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DEVICE_INFO) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_DEVICE_INFO);
+ return -EINVAL;
+ }
+ get_device_info_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "Device id: 0x%x\n", get_device_info_out->device_id);
+ fprintf(stdout, "Revision id: 0x%x\n", get_device_info_out->revision_id);
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_READ_DDR_TEMP CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_READ_DDR_TEMP_OPCODE 0xC531
+#define DDR_MAX_DIMM_CNT 4
+
+struct ddr_dimm_temp_info {
+ uint8_t ddr_temp_valid;
+ uint8_t dimm_id;
+ uint8_t spd_idx;
+ uint8_t rsvd;
+ float dimm_temp;
+};
+
+struct cxl_read_ddr_temp_out {
+ struct ddr_dimm_temp_info ddr_dimm_temp_info[DDR_MAX_DIMM_CNT];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_read_ddr_temp(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_read_ddr_temp_out *read_ddr_temp_out;
+ int rc = 0;
+ int idx;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_READ_DDR_TEMP_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_READ_DDR_TEMP) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_READ_DDR_TEMP);
+ return -EINVAL;
+ }
+ read_ddr_temp_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "DDR DIMM temperature info:\n");
+ for(idx = 0; idx < DDR_MAX_DIMM_CNT; idx++) {
+ fprintf(stdout, "dimm_id : 0x%x\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].dimm_id);
+ fprintf(stdout, "spd_idx: 0x%x\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].spd_idx);
+ fprintf(stdout, "dimm temp: %f\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].dimm_temp);
+ fprintf(stdout, "ddr temperature is %s\n\n", read_ddr_temp_out->ddr_dimm_temp_info[idx].ddr_temp_valid ? "valid" : "invalid");
+ }
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_OPCODE 0xFB14
+#define CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_IN_PAYLOAD_SIZE sizeof(u64)
+
+CXL_EXPORT int cxl_memdev_cxl_hpa_to_dpa(struct cxl_memdev *memdev, u64 hpa_address)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_command_info *cinfo;
+ struct cxl_mem_query_commands *query;
+ int rc = 0;
+ u64 *dpa_address_out;
+ u64 *hpa_address_in;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA_IN_PAYLOAD_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ hpa_address_in = (void *)cmd->send_cmd->in.payload;
+ *hpa_address_in = hpa_address;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_CXL_HPA_TO_DPA);
+ return -EINVAL;
+ }
+ dpa_address_out = (void*)cmd->send_cmd->out.payload;
+ fprintf(stdout, "dpa address:0x%lx\n", *dpa_address_out);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS_OPCODE 0xFB13
+
+typedef enum {
+ WSTRB_PARITY_ERROR = 0,
+ WDATA_PARITY_ERROR,
+ RDATA_RRESP_PARITY_ERROR,
+ RDATA_RESP_RID_PARITY_ERROR,
+ RDATA_PARITY_ERROR,
+ R_RESP_PARITY_ERROR,
+ B_RESP_PARITY_ERROR,
+ AW_QOS_PARITY_ERROR,
+ AW_MISC_PARITY_ERROR,
+ AW_ID_PARITY_ERROR,
+ AW_ADDR_RANGE_PARITY_ERROR,
+ AW_ADDR_PARITY_ERROR,
+ AR_QOS_PARITY_ERROR,
+ AR_MISC_PARITY_ERROR,
+ AR_ID_PARITY_ERROR,
+ AR_ADDR_RANGE_PARITY_ERROR,
+ AR_ADDR_PARITY_ERROR,
+ AXI_B_ID_PARITY_ERROR,
+ AXI_B_PARITY_ERROR,
+ AXI_R_ID_PARITY_ERROR,
+ AXI_R_DATA_PARITY_ERROR,
+ AXI_R_PARITY_ERROR,
+ DDR_PARITY_ERROR_COUNT = 22,
+} ddr_parity_errors;
+
+char *ddr_parity_error_strings[DDR_PARITY_ERROR_COUNT] = {
+ "WSTRB_PARITY_ERROR",
+ "WDATA_PARITY_ERROR",
+ "RDATA_RRESP_PARITY_ERROR",
+ "RDATA_RESP_RID_PARITY_ERROR",
+ "RDATA_PARITY_ERROR",
+ "R_RESP_PARITY_ERROR",
+ "B_RESP_PARITY_ERROR",
+ "AW_QOS_PARITY_ERROR",
+ "AW_MISC_PARITY_ERROR",
+ "AW_ID_PARITY_ERROR",
+ "AW_ADDR_RANGE_PARITY_ERROR",
+ "AW_ADDR_PARITY_ERROR",
+ "AR_QOS_PARITY_ERROR",
+ "AR_MISC_PARITY_ERROR",
+ "AR_ID_PARITY_ERROR",
+ "AR_ADDR_RANGE_PARITY_ERROR",
+ "AR_ADDR_PARITY_ERROR",
+ "AXI_B_ID_PARITY_ERROR",
+ "AXI_B_PARITY_ERROR",
+ "AXI_R_ID_PARITY_ERROR",
+ "AXI_R_DATA_PARITY_ERROR",
+ "AXI_R_PARITY_ERROR",
+};
+
+typedef enum {
+ S2M_NDR_FIFO = 0,
+ S2M_DRC_FIFO,
+ M2S_RWD_FIFO,
+ M2S_REQ_FIFO,
+ DDR1_W_REQ_FIFO,
+ DDR1_RDATA_RESP_FIFO,
+ DDR1_R_RESP_FIFO,
+ DDR1_B_RESP_FIFO,
+ DDR1_AW_REQ_FIFO,
+ DDR1_AR_REQ_FIFO,
+ DDR0_W_REQ_FIFO,
+ DDR0_RDATA_RESP_FIFO,
+ DDR0_R_RESP_FIFO,
+ DDR0_B_RESP_FIFO,
+ DDR0_AW_REQ_FIFO,
+ DDR0_AR_REQ_FIFO,
+ FIFO_ERROR_COUNT = 16,
+} fifo_errors;
+
+char *fifo_error_strings[FIFO_ERROR_COUNT] = {
+ "S2M_NDR_FIFO",
+ "S2M_DRC_FIFO",
+ "M2S_RWD_FIFO",
+ "M2S_REQ_FIFO",
+ "DDR1_W_REQ_FIFO",
+ "DDR1_RDATA_RESP_FIFO",
+ "DDR1_R_RESP_FIFO",
+ "DDR1_B_RESP_FIFO",
+ "DDR1_AW_REQ_FIFO",
+ "DDR1_AR_REQ_FIFO",
+ "DDR0_W_REQ_FIFO",
+ "DDR0_RDATA_RESP_FIFO",
+ "DDR0_R_RESP_FIFO",
+ "DDR0_B_RESP_FIFO",
+ "DDR0_AW_REQ_FIFO",
+ "DDR0_AR_REQ_FIFO"
+};
+
+typedef enum {
+ NDR_TAG_PARITY_ERROR = 0,
+ NDR_RESP_PARITY_ERROR,
+ M2S_RWD_ECC_CHECK_ERR_MULTPL_FAIL,
+ M2S_RWD_ECC_CHECK_ERR_DETECT_FAIL,
+ M2S_REQ_ECC_CHECK_ERR_MULTPL_FAIL,
+ M2S_REQ_ECC_CHECK_ERR_DETECT_FAIL,
+ DRC_TAG_PARITY_ERROR,
+ DRC_RESP_PARITY_ERROR,
+ DRC_DATA_PARITY_ERROR,
+ AW_MST_RWD_PARITY_ERROR,
+ AR_MST_REQ_PARITY_ERROR,
+ M2S_REQ_DUP_ADDR_PARITY_ERROR,
+ M2S_RWD_DUP_ADDR_PARITY_ERROR,
+ PARITY_ERROR_COUNT = 13,
+} parity_errors;
+
+char *parity_error_strings[PARITY_ERROR_COUNT] = {
+ "NDR_TAG_PARITY_ERROR",
+ "NDR_RESP_PARITY_ERROR",
+ "M2S_RWD_ECC_CHECK_ERR_MULTPL_FAIL",
+ "M2S_RWD_ECC_CHECK_ERR_DETECT_FAIL",
+ "M2S_REQ_ECC_CHECK_ERR_MULTPL_FAIL",
+ "M2S_REQ_ECC_CHECK_ERR_DETECT_FAIL",
+ "DRC_TAG_PARITY_ERROR",
+ "DRC_RESP_PARITY_ERROR",
+ "DRC_DATA_PARITY_ERROR",
+ "AW_MST_RWD_PARITY_ERROR",
+ "AR_MST_REQ_PARITY_ERROR",
+ "M2S_REQ_DUP_ADDR_PARITY_ERROR",
+ "M2S_RWD_DUP_ADDR_PARITY_ERROR",
+};
+
+typedef enum {
+ MST_M2S_RWD_ERR_MULTPL = 0,
+ MST_M2S_RWD_ERR_DETECT,
+ MST_M2S_REQ_ERR_MULTPL,
+ MST_M2S_REQ_ERR_DETECT,
+ POISON_RECEIVED_IN_RWD,
+ RWD_ADDRESS_INVALID,
+ REQ_ADDRESS_INVALID,
+ DDR1_RRESP_ERROR,
+ DDR1_BRESP_ERROR,
+ DDR0_RRESP_ERROR,
+ DDR0_BRESP_ERROR,
+ DDR1_RPARITY_ERROR,
+ DDR1_BPARITY_ERROR,
+ DDR0_RPARITY_ERROR,
+ DDR0_BPARITY_ERROR,
+ HDM_DEC1_ERR_NOT_COMMITED,
+ RX_DEINIT_TIMEOUT,
+ TX_DEINIT_TIMEOUT,
+ VIRAL,
+ DDR0_BRESP_DEC_ERROR,
+ DDR1_BRESP_DEC_ERROR,
+ DDR0_RRESP_DEC_ERROR,
+ DDR1_RRESP_DEC_ERROR,
+ MEMBRIDGE_COMMON_ERROR_COUNT = 23
+} membridge_common_errors;
+
+char *membridge_common_error_strings[MEMBRIDGE_COMMON_ERROR_COUNT] = {
+ "MST_M2S_RWD_ERR_MULTPL",
+ "MST_M2S_RWD_ERR_DETECT",
+ "MST_M2S_REQ_ERR_MULTPL",
+ "MST_M2S_REQ_ERR_DETECT",
+ "POISON_RECEIVED_IN_RWD",
+ "RWD_ADDRESS_INVALID",
+ "REQ_ADDRESS_INVALID",
+ "DDR1_RRESP_ERROR",
+ "DDR1_BRESP_ERROR",
+ "DDR0_RRESP_ERROR",
+ "DDR0_BRESP_ERROR",
+ "DDR1_RPARITY_ERROR",
+ "DDR1_BPARITY_ERROR",
+ "DDR0_RPARITY_ERROR",
+ "DDR0_BPARITY_ERROR",
+ "HDM_DEC1_ERR_NOT_COMMITED",
+ "RX_DEINIT_TIMEOUT",
+ "TX_DEINIT_TIMEOUT",
+ "VIRAL",
+ "DDR0_BRESP_DEC_ERROR",
+ "DDR1_BRESP_DEC_ERROR",
+ "DDR0_RRESP_DEC_ERROR",
+ "DDR1_RRESP_DEC_ERROR",
+};
+
+struct cxl_membridge_errors_out {
+ uint32_t fifo_overflow;
+ uint32_t fifo_overflows[FIFO_ERROR_COUNT];
+ uint32_t fifo_underflow;
+ uint32_t fifo_underflows[FIFO_ERROR_COUNT];
+ uint32_t ddr0_parity_error;
+ uint32_t ddr0_parity_errors[DDR_PARITY_ERROR_COUNT];
+ uint32_t ddr1_parity_error;
+ uint32_t ddr1_parity_errors[DDR_PARITY_ERROR_COUNT];
+ uint32_t parity_error;
+ uint32_t parity_errors[PARITY_ERROR_COUNT];
+ uint32_t common_errors[MEMBRIDGE_COMMON_ERROR_COUNT];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_cxl_membridge_errors(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_membridge_errors_out *get_cxl_membridge_errors_out;
+ int rc = 0;
+ int idx;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS_OPCODE);
+
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_ERRORS);
+ return -EINVAL;
+ }
+
+ get_cxl_membridge_errors_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "fifo_overflow errors : %d\n", get_cxl_membridge_errors_out->fifo_overflow);
+ for(idx = 0; idx < FIFO_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->fifo_overflows[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", fifo_error_strings[idx],
+ get_cxl_membridge_errors_out->fifo_overflows[idx]);
+ }
+
+ fprintf(stdout, "fifo_underflow errors : %d\n", get_cxl_membridge_errors_out->fifo_underflow);
+ for(idx = 0; idx < FIFO_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->fifo_underflows[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", fifo_error_strings[idx],
+ get_cxl_membridge_errors_out->fifo_underflows[idx]);
+ }
+
+ fprintf(stdout, "ddr0 parity errors : %d\n", get_cxl_membridge_errors_out->ddr0_parity_error);
+ for(idx = 0; idx < DDR_PARITY_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->ddr0_parity_errors[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", ddr_parity_error_strings[idx],
+ get_cxl_membridge_errors_out->ddr0_parity_errors[idx]);
+ }
+
+ fprintf(stdout, "ddr1 parity errors : %d\n", get_cxl_membridge_errors_out->ddr1_parity_error);
+ for(idx = 0; idx < DDR_PARITY_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->ddr1_parity_errors[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", ddr_parity_error_strings[idx],
+ get_cxl_membridge_errors_out->ddr1_parity_errors[idx]);
+ }
+
+ fprintf(stdout, "membridge common errors :\n");
+ for(idx = 0; idx < MEMBRIDGE_COMMON_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->common_errors[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", membridge_common_error_strings[idx],
+ get_cxl_membridge_errors_out->common_errors[idx]);
+ }
+
+ fprintf(stdout, "parity errors : %d\n", get_cxl_membridge_errors_out->parity_error);
+ for(idx = 0; idx < PARITY_ERROR_COUNT; idx++) {
+ if (get_cxl_membridge_errors_out->parity_errors[idx] != 0)
+ fprintf(stdout, "%s : 0x%x\n", parity_error_strings[idx],
+ get_cxl_membridge_errors_out->parity_errors[idx]);
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_BW CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_BW_OPCODE 0xFB09
+
+struct cxl_get_ddr_bw_in {
+ u32 timeout;
+ u32 iterations;
+} __attribute__((packed));
+
+typedef enum {
+ DDR_CTRL0 = 0,
+ DDR_CTRL1 = 1,
+ DDR_MAX_SUBSYS,
+} ddr_subsys;
+
+struct cxl_get_ddr_bw_out {
+ float peak_bw[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_ddr_bw(struct cxl_memdev *memdev, u32 timeout, u32 iterations)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_get_ddr_bw_in *get_ddr_bw_in;
+ struct cxl_get_ddr_bw_out *get_ddr_bw_out;
+ float total_peak_bw = 0;
+ int rc = 0;
+ int i;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_BW_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ get_ddr_bw_in = (void *) cmd->send_cmd->in.payload;
+
+ get_ddr_bw_in->timeout = timeout;
+ get_ddr_bw_in->iterations = iterations;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_BW) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_DDR_BW);
+ return -EINVAL;
+ }
+ get_ddr_bw_out = (void *)cmd->send_cmd->out.payload;
+ for(i = 0; i < DDR_MAX_SUBSYS; i++) {
+ fprintf(stdout, "ddr%d peak bandwidth = %f GB/s\n", i, get_ddr_bw_out->peak_bw[i]);
+ total_peak_bw += get_ddr_bw_out->peak_bw[i];
+ }
+ fprintf(stdout, "total peak bandwidth = %f GB/s\n", total_peak_bw);
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_I2C_READ CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_I2C_READ_OPCODE 0xFB10
+#define I2C_MAX_SIZE_NUM_BYTES 128
+
+struct cxl_i2c_read_in {
+ u16 slave_addr;
+ u8 reg_addr;
+ u8 num_bytes;
+} __attribute__((packed));
+
+struct cxl_i2c_read_out {
+ char buf[I2C_MAX_SIZE_NUM_BYTES];
+ u8 num_bytes;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_i2c_read(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 num_bytes)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_i2c_read_in *i2c_read_in;
+ struct cxl_i2c_read_out *i2c_read_out;
+ int rc = 0;
+ int i;
+
+ if(num_bytes > I2C_MAX_SIZE_NUM_BYTES) {
+ fprintf(stderr, "%s: Max number of bytes supported is %d, cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), I2C_MAX_SIZE_NUM_BYTES, rc, strerror(-rc));
+ return -EINVAL;
+ }
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_I2C_READ_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ i2c_read_in = (void *) cmd->send_cmd->in.payload;
+
+ i2c_read_in->slave_addr = slave_addr;
+ i2c_read_in->reg_addr = reg_addr;
+ i2c_read_in->num_bytes= num_bytes;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_I2C_READ) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_I2C_READ);
+ return -EINVAL;
+ }
+ i2c_read_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "i2c read output:");
+ for(i = 0; i < i2c_read_out->num_bytes; i++) {
+ fprintf(stdout, "0x%x\t", i2c_read_out->buf[i]);
+ }
+ fprintf(stdout, "\n");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_I2C_WRITE CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_I2C_WRITE_OPCODE 0xFB11
+
+struct cxl_i2c_write_in {
+ u16 slave_addr;
+ u8 reg_addr;
+ u8 data;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_i2c_write(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 data)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_i2c_write_in *i2c_write_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_I2C_WRITE_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ i2c_write_in = (void *) cmd->send_cmd->in.payload;
+
+ i2c_write_in->slave_addr = slave_addr;
+ i2c_write_in->reg_addr = reg_addr;
+ i2c_write_in->data = data;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_I2C_WRITE) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_I2C_WRITE);
+ return -EINVAL;
+ }
+ fprintf(stdout, "i2c write success\n");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_LATENCY CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_LATENCY_OPCODE 0xFB12
+
+struct ddr_lat_op {
+ uint64_t readlat;
+ uint64_t writelat;
+ uint32_t rdsamplecnt;
+ uint32_t wrsamplecnt;
+ float avg_rdlatency;
+ float avg_wrlatency;
+};
+
+struct cxl_get_ddr_latency_in {
+ u32 measure_time;
+} __attribute__((packed));
+
+struct cxl_get_ddr_latency_out {
+ struct ddr_lat_op ddr_lat_op[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_get_ddr_latency(struct cxl_memdev *memdev, u32 measure_time)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_get_ddr_latency_in *get_ddr_lat_in;
+ struct cxl_get_ddr_latency_out *get_ddr_lat_out;
+ int rc = 0;
+ int ddr_id;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_LATENCY_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ get_ddr_lat_in = (void *) cmd->send_cmd->in.payload;
+
+ get_ddr_lat_in->measure_time = measure_time;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_LATENCY) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_DDR_LATENCY);
+ return -EINVAL;
+ }
+ get_ddr_lat_out = (void *)cmd->send_cmd->out.payload;
+ for(ddr_id = 0; ddr_id < DDR_MAX_SUBSYS; ddr_id++) {
+ fprintf(stdout, "\nDDR%d Latency:\n", ddr_id);
+ fprintf(stdout,
+ "readLat: %lu, rdSampleCnt: %u\n, writeLat: %lu, wrSampleCnt: %u\n",
+ get_ddr_lat_out->ddr_lat_op[ddr_id].readlat,
+ get_ddr_lat_out->ddr_lat_op[ddr_id].rdsamplecnt,
+ get_ddr_lat_out->ddr_lat_op[ddr_id].writelat,
+ get_ddr_lat_out->ddr_lat_op[ddr_id].wrsamplecnt);
+
+ fprintf(stdout, "Average Latency:\n");
+ fprintf(stdout,
+ "Avg Read Latency : %f ns \n Avg Write Latency : %f ns \n",
+ get_ddr_lat_out->ddr_lat_op[ddr_id].avg_rdlatency,
+ get_ddr_lat_out->ddr_lat_op[ddr_id].avg_wrlatency);
+ }
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO_OPCODE 0xFB0F
+
+struct ddr_parity_err {
+ uint32_t parity_crit_bit2_cnt; /* Parity error on the address/control bus*/
+ uint32_t parity_crit_bit1_cnt; /* Overlapping write data parity error */
+ uint32_t parity_crit_bit0_cnt; /* Write data parity error */
+};
+
+struct ddr_dfi_err {
+ uint32_t dfi_crit_bit5_cnt; /* DFI tINIT_COMPLETE value has timed out */
+ uint32_t dfi_crit_bit2_cnt; /* Error received from the PHY on the DFI bus */
+
+ uint32_t dfi_warn_bit1_cnt; /* DFI PHY Master Interface error has occurred */
+ uint32_t dfi_warn_bit0_cnt; /* DFI update error has occurred */
+};
+
+struct ddr_crc_err {
+ uint32_t crc_crit_bit1_cnt; /* CA Parity or a CRC error happened during CRC
+ Retry. */
+ uint32_t crc_crit_bit0_cnt; /* CRC error occurred on the write data bus */
+};
+
+struct ddr_userif_err {
+ uint32_t
+ userif_crit_bit2_cnt; /* Error occurred on the port command channel. */
+ uint32_t userif_crit_bit1_cnt; /* Multiple accesses outside the defined
+ PHYSICAL memory space have occurred. */
+ uint32_t userif_crit_bit0_cnt; /* A Memory access outside the defined PHYSICAL
+ memory space has occurred */
+};
+
+struct ddr_ecc_err {
+ uint32_t ecc_warn_bit6_cnt; /* One or more ECC writeback commands
+ could not be executed */
+ uint32_t ecc_crit_bit3_cnt; /* Multiple uncorrectable ECC events
+ have been detected */
+ uint32_t ecc_crit_bit2_cnt; /* A uncorrectable ECC event has been detected */
+ uint32_t ecc_crit_bit8_cnt; /* An ECC correctable error has been detected in a
+ scrubbing read operation */
+ uint32_t ecc_warn_bit1_cnt; /* Multiple correctable ECC events
+ have been detected */
+ uint32_t ecc_warn_bit0_cnt; /* A correctable ECC event has been detected */
+};
+
+struct ddr_controller_errors {
+ struct ddr_parity_err parity;
+ struct ddr_dfi_err dfi;
+ struct ddr_crc_err crc;
+ struct ddr_userif_err userif;
+ struct ddr_ecc_err ecc;
+};
+
+struct cxl_get_ddr_ecc_err_info_out {
+ struct ddr_controller_errors ddr_ctrl_err[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+void display_error_count(struct ddr_controller_errors *ddr_ctrl_err, ddr_subsys ddr_id);
+
+void display_error_count(struct ddr_controller_errors *ddr_ctrl_err, ddr_subsys ddr_id) {
+ if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit2_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: Parity error on the address/control bus "
+ "(parity_crit_bit2_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].parity.parity_crit_bit2_cnt);
+ }
+ if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit1_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: Overlapping write data parity error "
+ "(parity_crit_bit1_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].parity.parity_crit_bit1_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].parity.parity_crit_bit0_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: Write data parity error "
+ "(parity_crit_bit0_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].parity.parity_crit_bit0_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit5_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: DFI tINIT_COMPLETE value has timed out "
+ "(dfi_crit_bit5_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit5_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit2_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL : Error received from the PHY on the DFI bus "
+ "(dfi_crit_bit2_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].dfi.dfi_crit_bit2_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit1_cnt) {
+ fprintf(stdout,
+ "DDR-%d: WARN: DFI PHY Master Interface error has occurred "
+ "(dfi_warn_bit1_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit1_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit0_cnt) {
+ fprintf(stdout,
+ "DDR-%d: WARN: DFI update error has occurred "
+ "(dfi_warn_bit0_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].dfi.dfi_warn_bit0_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].crc.crc_crit_bit1_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: CA Parity or a CRC error happened during CRC Retry "
+ "(crc_crit_bit1_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].crc.crc_crit_bit1_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].crc.crc_crit_bit0_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: CRC error occurred on the write data bus "
+ "(crc_crit_bit0_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].crc.crc_crit_bit0_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit2_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: Error occurred on the port command channel "
+ "(userif_crit_bit2_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].userif.userif_crit_bit2_cnt);
+ }
+ if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit1_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: Multiple accesses outside the defined PHYSICAL "
+ "memory space have occurred "
+ "(userif_crit_bit1_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].userif.userif_crit_bit1_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].userif.userif_crit_bit0_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: A Memory access outside the defined PHYSICAL "
+ "memory space has occurred "
+ "(userif_crit_bit0_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].userif.userif_crit_bit0_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit6_cnt) {
+ fprintf(stdout,
+ "DDR-%d: WARN: One or more ECC writeback commands "
+ "could not be executed "
+ "(ecc_warn_bit6_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit6_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit3_cnt) {
+ fprintf(stdout,
+ "DDR-%d:FATAL: Multiple uncorrectable ECC events have been detected "
+ "(ecc_crit_bit3_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit3_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit2_cnt) {
+ fprintf(stdout,
+ "DDR-%d: FATAL: A uncorrectable ECC event has been detected "
+ "(ecc_crit_bit2_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit2_cnt);
+ }
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit8_cnt) {
+ fprintf(stdout,
+ "DDR-%d: CRIT: An ECC correctable error has been detected "
+ "in a scrubbing read operation "
+ "(ecc_crit_bit8_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_crit_bit8_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit1_cnt) {
+ fprintf(stdout,
+ "DDR-%d: WARN: Multiple correctable ECC events have been detected "
+ "(ecc_warn_bit1_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit1_cnt);
+ }
+
+ if (ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit0_cnt) {
+ fprintf(stdout,
+ "DDR-%d: WARN: A correctable ECC event has been detected "
+ "(ecc_warn_bit0_cnt= %u)\n",
+ ddr_id,
+ ddr_ctrl_err[ddr_id].ecc.ecc_warn_bit0_cnt);
+ }
+}
+
+CXL_EXPORT int cxl_memdev_get_ddr_ecc_err_info(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_get_ddr_ecc_err_info_out *get_ddr_ecc_err_info_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_DDR_ECC_ERR_INFO);
+ return -EINVAL;
+ }
+ get_ddr_ecc_err_info_out = (void *)cmd->send_cmd->out.payload;
+ display_error_count(get_ddr_ecc_err_info_out->ddr_ctrl_err, DDR_CTRL0);
+ display_error_count(get_ddr_ecc_err_info_out->ddr_ctrl_err, DDR_CTRL1);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB_OPCODE 0xFB15
+
+CXL_EXPORT int cxl_memdev_start_ddr_ecc_scrub(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_START_DDR_ECC_SCRUB);
+ return -EINVAL;
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS_OPCODE 0xFB16
+
+
+struct cxl_ddr_ecc_scrub_status_out {
+ int ecc_scrub_status[DDR_MAX_SUBSYS];
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_ecc_scrub_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_ecc_scrub_status_out *ddr_ecc_scrub_status_out;
+ int rc = 0;
+ int subsys;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_ECC_SCRUB_STATUS);
+ return -EINVAL;
+ }
+ ddr_ecc_scrub_status_out = (void *)cmd->send_cmd->out.payload;
+ for(subsys = DDR_CTRL0; subsys < DDR_MAX_SUBSYS; subsys++)
+ {
+ fprintf(stdout, "DDR-%d %s\n", subsys, ddr_ecc_scrub_status_out->ecc_scrub_status[subsys] ?
+ "ECC SCRUB IS IN PROGRESS" : "DDR SCRUB IS NOT RUNNING/FINISHED");
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR CONTINUOUS SCRUB STATUS */
+
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS_OPCODE 0xFB28
+
+struct cxl_ddr_cont_scrub_status_out {
+ uint32_t cont_scrub_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_cont_scrub_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_cont_scrub_status_out *ddr_cont_scrub_status_out;
+ int rc = 0;
+ int subsys;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_CONT_SCRUB_STATUS);
+ return -EINVAL;
+ }
+ ddr_cont_scrub_status_out = (void *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "%s\n", ddr_cont_scrub_status_out->cont_scrub_status ?
+ "CONTINUOUS SCRUB IS ON" : "CONTINUOUS SCRUB IS OFF");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR CONTINUOUS SCRUB SET */
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_OPCODE 0xFB29
+#define CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_ddr_cont_scrub_set_in {
+ uint32_t cont_scrub_status;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_cont_scrub_set(struct cxl_memdev *memdev, uint32_t cont_scrub_status)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_ddr_cont_scrub_set_in *ddr_cont_scrub_set_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_cont_scrub_set_in = (void *) cmd->send_cmd->in.payload;
+
+ ddr_cont_scrub_set_in->cont_scrub_status = cont_scrub_status;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_CONT_SRUB_SET);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_INIT_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_INIT_STATUS_OPCODE 0xFB17
+
+typedef enum {
+ DDR_INIT_INPROGRESS = 0,
+ DDR_INIT_PASSED = 1,
+ DDR_INIT_FAILED = -1,
+ DDR_INIT_FAILED_NO_CH0_DIMM0 = -2,
+ DDR_INIT_FAILED_UNKNOWN_DIMM = -3,
+} ddr_status;
+
+typedef enum {
+ CH_0 = 0,
+ CH_1 = 1,
+ CH_NA = -1,
+} f_channel_id;
+
+struct ddr_init_boot_status {
+ int8_t ddr_init_status;
+ int8_t failed_channel_id;
+ char failed_dimm_silk_screen;
+};
+
+struct cxl_ddr_init_status_out {
+struct ddr_init_boot_status init_status;
+} __packed;
+
+CXL_EXPORT int cxl_memdev_ddr_init_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_init_status_out *ddr_init_status_out;
+ int rc = 0;
+ int8_t status;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_INIT_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_INIT_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_INIT_STATUS);
+ return -EINVAL;
+ }
+ ddr_init_status_out = (void *)cmd->send_cmd->out.payload;
+ status = ddr_init_status_out->init_status.ddr_init_status;
+ switch (status)
+ {
+ case DDR_INIT_INPROGRESS:
+ fprintf(stdout, "DDR INIT IS IN PROGRESS\n");
+ break;
+ case DDR_INIT_PASSED:
+ fprintf(stdout, "DDR INIT PASSED\n");
+ break;
+ case DDR_INIT_FAILED:
+ fprintf(stdout, "DDR INIT FAILED for CH:%d DIMM:%c\n",
+ ddr_init_status_out->init_status.failed_channel_id,
+ ddr_init_status_out->init_status.failed_dimm_silk_screen);
+
+ fprintf(stdout, "RECOVERY REMEDY: REPLACE CH:%d DIMM:%c and RE-TRY\n",
+ ddr_init_status_out->init_status.failed_channel_id,
+ ddr_init_status_out->init_status.failed_dimm_silk_screen);
+ break;
+ case DDR_INIT_FAILED_NO_CH0_DIMM0:
+ fprintf(stdout, "DDR INIT FAILED. CH:%d DIMM:%c is NOT PLUGGED IN\n",
+ ddr_init_status_out->init_status.failed_channel_id,
+ ddr_init_status_out->init_status.failed_dimm_silk_screen);
+
+ fprintf(stdout, "RECOVERY REMEDY: PLUG IN CH:%d DIMM:%c\n",
+ ddr_init_status_out->init_status.failed_channel_id,
+ ddr_init_status_out->init_status.failed_dimm_silk_screen);
+ break;
+ case DDR_INIT_FAILED_UNKNOWN_DIMM:
+ fprintf(stdout, "DDR INIT FAILED. UN-SUPPORTED/UNKNOWN DIMM\n");
+ fprintf(stdout, "RECOVERY REMEDY: PLUG IN SUPPORTED DIMMs\n");
+ break;
+ default:
+ fprintf(stdout, "DDR INIT STATUS invalid\n");
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+struct cxl_cmd_membridge_stats_out {
+ // mem transaction counters
+ uint64_t m2s_req_count;
+ uint64_t m2s_rwd_count;
+ uint64_t s2m_drs_count;
+ uint64_t s2m_ndr_count;
+ // HPA logs for poison & out-of-range
+ uint64_t rwd_first_poison_hpa_log;
+ uint64_t rwd_latest_poison_hpa_log;
+ uint64_t req_first_hpa_log;
+ uint64_t rwd_first_hpa_log;
+ // correctible errors counters
+ uint32_t mst_m2s_req_corr_err_count;
+ uint32_t mst_m2s_rwd_corr_err_count;
+ // membridge fifo full/empty status
+ uint32_t fifo_full_status;
+ uint32_t fifo_empty_status;
+ // credit counters
+ uint8_t m2s_rwd_credit_count;
+ uint8_t m2s_req_credit_count;
+ uint8_t s2m_ndr_credit_count;
+ uint8_t s2m_drc_credit_count;
+ // rx state machine status 0
+ uint8_t rx_fsm_status_rx_deinit;
+ uint8_t rx_fsm_status_m2s_req;
+ uint8_t rx_fsm_status_m2s_rwd;
+ uint8_t rx_fsm_status_ddr0_ar_req;
+ uint8_t rx_fsm_status_ddr0_aw_req;
+ uint8_t rx_fsm_status_ddr0_w_req;
+ // rx state machine status 1
+ uint8_t rx_fsm_status_ddr1_ar_req;
+ uint8_t rx_fsm_status_ddr1_aw_req;
+ uint8_t rx_fsm_status_ddr1_w_req;
+ // tx state machine status 0
+ uint8_t tx_fsm_status_tx_deinit;
+ uint8_t tx_fsm_status_s2m_ndr;
+ uint8_t tx_fsm_status_s2m_drc;
+ // stat QoS TEL
+ uint8_t stat_qos_tel_dev_load_read;
+ uint8_t stat_qos_tel_dev_load_type2_read;
+ uint8_t stat_qos_tel_dev_load_write;
+ uint8_t resvd;
+} __attribute__((packed));
+
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS_OPCODE 0xFB18
+
+CXL_EXPORT int cxl_memdev_get_cxl_membridge_stats(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_cmd_membridge_stats_out *stats;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS_OPCODE);
+
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+
+ if (rc != 0) {
+ fprintf(stderr, "%s: Read failed, firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_GET_CXL_MEMBRIDGE_STATS);
+ return -EINVAL;
+ }
+
+ stats = (void *)cmd->send_cmd->out.payload;
+ // print membridge statistics info
+ fprintf(stderr, "m2s_req_count: %lu\n", stats->m2s_req_count);
+ fprintf(stderr, "m2s_rwd_count: %lu\n", stats->m2s_rwd_count);
+ fprintf(stderr, "s2m_drs_count: %lu\n", stats->s2m_drs_count);
+ fprintf(stderr, "s2m_ndr_count: %lu\n", stats->s2m_ndr_count);
+ fprintf(stderr, "rwd_first_poison_hpa: 0x%lx\n", stats->rwd_first_poison_hpa_log);
+ fprintf(stderr, "rwd_latest_poison_hpa: 0x%lx\n", stats->rwd_latest_poison_hpa_log);
+ fprintf(stderr, "req_first_hpa_log: 0x%lx\n", stats->req_first_hpa_log);
+ fprintf(stderr, "rwd_first_hpa_log: 0x%lx\n", (u64)stats->rwd_first_hpa_log);
+ fprintf(stderr, "m2s_req_corr_err_count: %u\n", stats->mst_m2s_req_corr_err_count);
+ fprintf(stderr, "m2s_rwd_corr_err_count: %u\n", stats->mst_m2s_rwd_corr_err_count);
+ fprintf(stderr, "fifo_full_status: 0x%x\n", stats->fifo_full_status);
+ fprintf(stderr, "fifo_empty_status: 0x%x\n", stats->fifo_empty_status);
+ fprintf(stderr, "m2s_rwd_credit_count: %u\n", stats->m2s_rwd_credit_count);
+ fprintf(stderr, "m2s_req_credit_count: %u\n", stats->m2s_req_credit_count);
+ fprintf(stderr, "s2m_ndr_credit_count: %u\n", stats->s2m_ndr_credit_count);
+ fprintf(stderr, "s2m_drc_credit_count: %u\n", stats->s2m_drc_credit_count);
+ fprintf(stderr, "rx_status_rx_deinit: 0x%x\n", stats->rx_fsm_status_rx_deinit);
+ fprintf(stderr, "rx_status_m2s_req: 0x%x\n", stats->rx_fsm_status_m2s_req);
+ fprintf(stderr, "rx_status_m2s_rwd: 0x%x\n", stats->rx_fsm_status_m2s_rwd);
+ fprintf(stderr, "rx_status_ddr0_ar_req: 0x%x\n", stats->rx_fsm_status_ddr0_ar_req);
+ fprintf(stderr, "rx_status_ddr0_aw_req: 0x%x\n", stats->rx_fsm_status_ddr0_aw_req);
+ fprintf(stderr, "rx_status_ddr0_w_req: 0x%x\n", stats->rx_fsm_status_ddr0_w_req);
+ fprintf(stderr, "rx_status_ddr1_ar_req: 0x%x\n", stats->rx_fsm_status_ddr1_ar_req);
+ fprintf(stderr, "rx_status_ddr1_aw_req: 0x%x\n", stats->rx_fsm_status_ddr1_aw_req);
+ fprintf(stderr, "rx_status_ddr1_w_req: 0x%x\n", stats->rx_fsm_status_ddr1_w_req);
+ fprintf(stderr, "tx_status_tx_deinit: 0x%x\n", stats->tx_fsm_status_tx_deinit);
+ fprintf(stderr, "tx_status_s2m_ndr: 0x%x\n", stats->tx_fsm_status_s2m_ndr);
+ fprintf(stderr, "tx_status_s2m_drc: 0x%x\n", stats->tx_fsm_status_s2m_drc);
+ fprintf(stderr, "qos_tel_dev_load_read: %u\n", stats->stat_qos_tel_dev_load_read);
+ fprintf(stderr, "qos_tel_dev_load_type2_read:%u\n", stats->stat_qos_tel_dev_load_type2_read);
+ fprintf(stderr, "qos_tel_dev_load_write: %u\n", stats->stat_qos_tel_dev_load_write);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP_OPCODE 0xFB1A
+
+CXL_EXPORT int cxl_memdev_trigger_coredump(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_TRIGGER_COREDUMP);
+ return -EINVAL;
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN_OPCODE 0xFB19
+
+
+struct cxl_ddr_err_inj_en_in {
+ uint32_t ddr_id;
+ uint32_t err_type;
+ uint64_t ecc_fwc_mask;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_err_inj_en(struct cxl_memdev *memdev, u32 ddr_id, u32 err_type, u64 ecc_fwc_mask)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_err_inj_en_in *ddr_err_inj_en_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_err_inj_en_in = (void *) cmd->send_cmd->in.payload;
+ ddr_err_inj_en_in->ddr_id = ddr_id;
+ ddr_err_inj_en_in->err_type = err_type;
+ ddr_err_inj_en_in->ecc_fwc_mask = ecc_fwc_mask;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_ERR_INJ_EN);
+ return -EINVAL;
+ }
+ fprintf(stderr, "Error injection enabled on DDR%d\n", ddr_id);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS_OPCODE 0xFB20
+
+#define DDR_MAX_CS 4
+#define DDR_CS_DEVICE_MAX 18
+#define DDR_REG_MAX_NIBBLE 9
+#define DDR_MAX_SLICE 9
+#define DDR_MAX_SLICE_BIT 8
+
+struct ddr_phy_pll_status {
+ uint32_t bs0_status;
+ uint32_t bs1_status;
+};
+
+struct ddr_wr_levelling_status {
+ uint32_t lower_nibble_err[DDR_REG_MAX_NIBBLE];
+ uint32_t upper_nibble_err[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_read_gate_training_status {
+ uint32_t lower_nibble_min_err[DDR_REG_MAX_NIBBLE];
+ uint32_t lower_nibble_max_err[DDR_REG_MAX_NIBBLE];
+ uint32_t upper_nibble_min_err[DDR_REG_MAX_NIBBLE];
+ uint32_t upper_nibble_max_err[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_margin_vref_data {
+ float lower_nibble_vref_low_volt[DDR_REG_MAX_NIBBLE];
+ float lower_nibble_vref_high_volt[DDR_REG_MAX_NIBBLE];
+ float upper_nibble_vref_low_volt[DDR_REG_MAX_NIBBLE];
+ float upper_nibble_vref_high_volt[DDR_REG_MAX_NIBBLE];
+};
+
+struct ddr_margin_write_dq_vref_data {
+ float vref_low_volt[DDR_CS_DEVICE_MAX];
+ float vref_high_volt[DDR_CS_DEVICE_MAX];
+};
+
+struct ddr_margin_write_dq_vref_data_cs {
+ float vref_low_volt_cs[DDR_MAX_CS][DDR_CS_DEVICE_MAX];
+ float vref_high_volt_cs[DDR_MAX_CS][DDR_CS_DEVICE_MAX];
+};
+
+struct ddr_margin_rdlvl_delay_dqs_rise_data {
+ uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_margin_rdlvl_delay_dqs_fall_data {
+ uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_margin_wrdqlvl_delay_data {
+ uint32_t te_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ uint32_t le_delay_data[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float te_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+ float le_delay_time[DDR_MAX_SLICE][DDR_MAX_SLICE_BIT];
+};
+
+struct ddr_dimm_training_status {
+ struct ddr_phy_pll_status phy_pll_status;
+ struct ddr_wr_levelling_status wr_levl_status;
+ struct ddr_read_gate_training_status rd_gate_tr_status;
+ struct ddr_margin_vref_data vref_data;
+ struct ddr_margin_write_dq_vref_data wdq_vref_data;
+ struct ddr_margin_write_dq_vref_data_cs wdq_vref_data_cs;
+ struct ddr_margin_rdlvl_delay_dqs_rise_data rddqslvl_rise_data;
+ struct ddr_margin_rdlvl_delay_dqs_fall_data rddqslvl_fall_data;
+ struct ddr_margin_wrdqlvl_delay_data wrdqlvl_delay_data;
+ uint32_t err_status;
+};
+
+struct cxl_ddr_dimm_level_training_status_out {
+ struct ddr_dimm_training_status dimm_training_status[2];
+} __attribute__((packed));
+
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_read_gate_training_status(uint32_t instance, struct ddr_read_gate_training_status* rd_gate_tr_status);
+void print_write_levelling_status(uint32_t instance, struct ddr_wr_levelling_status* wr_levl_status);
+void print_ddr_phy_pll_status(uint32_t instance, struct ddr_phy_pll_status* phy_pll_status);
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_vref_low_high(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_rdlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_margin_wrdqlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+void print_err_status(int instance, struct ddr_dimm_training_status *dimm_tr_status);
+
+/* DDR phy pll status */
+void print_ddr_phy_pll_status(uint32_t instance, struct ddr_phy_pll_status* phy_pll_status) {
+ uint32_t read_data;
+
+ read_data = phy_pll_status->bs0_status;
+ fprintf(stdout, "DDR%d PHY PLL Status: \n", instance);
+ fprintf(stdout, "\tOBS0: \n");
+ fprintf(stdout, "\t\tPLL Lock Status = %d \n", (read_data & 1));
+ fprintf(stdout, "\t\tReady = %d \n", ((read_data & 0x2) >> 1));
+ fprintf(stdout, "\t\tLock assert count = 0x%x \n", ((read_data & 0x7F8) >> 3));
+
+ read_data = phy_pll_status->bs1_status;
+ fprintf(stdout, "\tOBS1: \n");
+ fprintf(stdout, "\t\tPLL Lock Status = %d \n", (read_data & 1));
+ fprintf(stdout, "\t\tReady = %d \n", ((read_data & 0x2) >> 1));
+ fprintf(stdout, "\t\tLock assert count = 0x%x \n\n", ((read_data & 0x7F8) >> 3));
+}
+
+void print_write_levelling_status(uint32_t instance, struct ddr_wr_levelling_status* wr_levl_status) {
+ uint32_t read_data = 0;
+ int i = 0;
+
+ fprintf(stdout, "\t\tBYTE# \t\t\t\t 0 \t 1 \t 2 \t 3 \t 4 \t 5 \t 6 \t 7 \t 8\n");
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t\tLOWER NIBBLE ERROR FLAG \t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x1000)>> 12);
+ read_data = wr_levl_status->lower_nibble_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x1000)>> 12);
+
+ i = 0;
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t\tUPPER NIBBLE ERROR FLAG \t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x4000)>> 14);
+ read_data = wr_levl_status->upper_nibble_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x4000)>> 14);
+}
+
+void print_read_gate_training_status(uint32_t instance, struct ddr_read_gate_training_status* rd_gate_tr_status)
+{
+ uint32_t read_data = 0;
+ int i = 0;
+
+ fprintf(stdout, "\t\tBYTE# \t\t\t\t 0 \t 1 \t 2 \t 3 \t 4 \t 5 \t 6 \t 7 \t 8\n");
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t\tLOWER NIBBLE MIN ERROR \t\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x80)>> 7);
+ read_data = rd_gate_tr_status->lower_nibble_min_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x80)>> 7);
+
+ i = 0;
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t\tLOWER NIBBLE MAX ERROR \t\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x100)>> 8);
+ read_data = rd_gate_tr_status->lower_nibble_max_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x100)>> 8);
+
+ i = 0;
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t\tUPPER NIBBLE MIN ERROR \t\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x200)>> 9);
+ read_data = rd_gate_tr_status->upper_nibble_min_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x200)>> 9);
+
+ i = 0;
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t\tUPPER NIBBLE MAX ERROR \t\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d", (read_data & 0x400)>> 10);
+ read_data = rd_gate_tr_status->upper_nibble_max_err[i++];
+ fprintf(stdout, "\t %d\n", (read_data & 0x400)>> 10);
+}
+
+void print_ddr_training_status(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status) {
+ fprintf(stdout, "DDR%d TRAINING STATUS: \n", instance);
+ fprintf(stdout, "\tWRITE LEVELLING STATUS: \n");
+ print_write_levelling_status(instance, &dimm_tr_status->wr_levl_status);
+ fprintf(stdout, "\n\tREAD GATE TRAINING STATUS: \n");
+ print_read_gate_training_status(instance, &dimm_tr_status->rd_gate_tr_status);
+}
+
+void print_margin_vref_low_high(uint32_t instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+ int i = 0, j = 0;
+ float vref_low_volt, vref_high_volt;
+
+ fprintf(stdout, "DDR%d MARGIN VALUES:\n", instance);
+ fprintf(stdout, "\tREAD LEVEL VREF: \n");
+ fprintf(stdout, "\t\t VREF_LOW VREF_LOW_VOLT(mV) VREF_HIGH VREF_HIGH_VOLT(mV) VREF_MARGIN(mV)\n");
+ for(i=0; i<9; i++)
+ {
+ fprintf(stdout, "\t\tSlice%d Lower Nibble: ", i);
+ vref_low_volt = dimm_tr_status->vref_data.lower_nibble_vref_low_volt[i];
+ fprintf(stdout, "%04.2f ", vref_low_volt);
+ vref_high_volt = dimm_tr_status->vref_data.lower_nibble_vref_high_volt[i];
+ fprintf(stdout, "%04.2f ", vref_high_volt);
+ fprintf(stdout, "%0.2f\n", (vref_high_volt - vref_low_volt));
+
+ fprintf(stdout, "\t\tSlice%d Upper Nibble: ", i);
+ vref_low_volt = dimm_tr_status->vref_data.upper_nibble_vref_low_volt[i];
+ fprintf(stdout, "%04.2f ", vref_low_volt);
+ vref_high_volt = dimm_tr_status->vref_data.upper_nibble_vref_high_volt[i];
+ fprintf(stdout, "%04.2f ", vref_high_volt);
+ fprintf(stdout, "%0.2f\n\n", (vref_high_volt - vref_low_volt));
+ }
+ fprintf(stdout, "\tWRITE DQ LEVEL VREF: \n");
+ fprintf(stdout, "\t\t VREF_LOW VREF_LOW_VOLT(mV) VREF_HIGH VREF_HIGH_VOLT(mV) VREF_MARGIN(mV)\n");
+ for(i=0; i<18; i++)
+ {
+ fprintf(stdout, "\t\tCS0 Device%d :\t", i);
+ vref_low_volt = dimm_tr_status->wdq_vref_data.vref_low_volt[i];
+ fprintf(stdout, "%04.1f ", vref_low_volt);
+ vref_high_volt = dimm_tr_status->wdq_vref_data.vref_high_volt[i];
+ fprintf(stdout, "%04.1f ", vref_high_volt);
+ fprintf(stdout, "%0.1f \n", (vref_high_volt - vref_low_volt));
+ }
+ for(j=1; j<4; j++)
+ {
+ for(i=0; i<18; i++)
+ {
+ fprintf(stdout, "\t\tCS%d Device%d :\t", j, i);
+ vref_low_volt = dimm_tr_status->wdq_vref_data_cs.vref_low_volt_cs[j][i];
+ fprintf(stdout, "%04.1f ", vref_low_volt);
+ vref_high_volt = dimm_tr_status->wdq_vref_data_cs.vref_high_volt_cs[j][i];
+ fprintf(stdout, "%04.1f ", vref_high_volt);
+ fprintf(stdout, "%0.1f \n", (vref_high_volt - vref_low_volt));
+ }
+ fprintf(stdout, "\n");
+ }
+}
+
+void print_margin_rdlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+ uint32_t te_delay_data = 0, le_delay_data = 0;
+ int i = 0, j = 0;
+ float te_delay_time, le_delay_time;
+
+ printf("DDR%d Margin Delays: \n", instance);
+ printf("\tREAD DQSLEVEL RISE DELAY WINDOW: \n");
+ printf("\t\t TE_DATA TE_DELAY(ns) LE_DATA LE_DELAY(ns) RD_RISE_DELAY(ns)\n");
+ for(j=0; j<9; j++)
+ {
+ for(i=0; i<8; i++)
+ {
+ printf("\t\tSLICE%d BIT%d ", j, i);
+ te_delay_data = dimm_tr_status->rddqslvl_rise_data.te_delay_data[j][i];
+ printf("%d ", te_delay_data);
+ te_delay_time = dimm_tr_status->rddqslvl_rise_data.te_delay_time[j][i];
+ printf("%0.03f ", te_delay_time);
+ le_delay_data = dimm_tr_status->rddqslvl_rise_data.le_delay_data[j][i];
+ printf("%02d ", le_delay_data);
+ le_delay_time = dimm_tr_status->rddqslvl_rise_data.le_delay_time[j][i];
+ printf("%0.03f ", le_delay_time);
+ printf("%0.03f\n", (te_delay_time - le_delay_time));
+ }
+ printf("\n");
+ }
+ printf("\tREAD DQSLEVEL FALL DELAY WINDOW: \n");
+ printf("\t\t TE_DATA TE_DELAY(ns) LE_DATA LE_DELAY(ns) RD_FALL_DELAY(ns)\n");
+ for(j=0; j<9; j++)
+ {
+ for(i=0; i<8; i++)
+ {
+ printf("\t\tSLICE%d BIT%d ", j, i);
+ te_delay_data = dimm_tr_status->rddqslvl_fall_data.te_delay_data[j][i];
+ printf("%d ", te_delay_data);
+ te_delay_time = dimm_tr_status->rddqslvl_fall_data.te_delay_time[j][i];
+ printf("%0.03f ", te_delay_time);
+ le_delay_data = dimm_tr_status->rddqslvl_fall_data.le_delay_data[j][i];
+ printf("%02d ", le_delay_data);
+ le_delay_time = dimm_tr_status->rddqslvl_fall_data.le_delay_time[j][i];
+ printf("%0.03f ", le_delay_time);
+ printf("%0.03f\n", (te_delay_time - le_delay_time));
+ }
+ printf("\n");
+ }
+}
+
+void print_margin_wrdqlvl_delay_window(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+ uint32_t te_delay_data = 0, le_delay_data = 0;
+ int i = 0, j = 0;
+ float te_delay_time, le_delay_time;
+
+ printf("\tWRITE DQLEVEL DELAY WINDOW: \n");
+ printf("\t\t TE_DATA TE_DELAY(ns) LE_DATA LE_DELAY(ns) WRDQLVL_DELAY(ns)\n");
+ for(j=0; j<9; j++)
+ {
+ for(i=0; i<8; i++)
+ {
+ printf("\t\tSLICE%d BIT%d ", j, i);
+ te_delay_data = dimm_tr_status->wrdqlvl_delay_data.te_delay_data[j][i];
+ printf("%d ", te_delay_data);
+ te_delay_time = dimm_tr_status->wrdqlvl_delay_data.te_delay_time[j][i];
+ printf("%0.03f ", te_delay_time);
+ le_delay_data = dimm_tr_status->wrdqlvl_delay_data.le_delay_data[j][i];
+ printf("%02d ", le_delay_data);
+ le_delay_time = dimm_tr_status->wrdqlvl_delay_data.le_delay_time[j][i];
+ printf("%0.03f ", le_delay_time);
+ printf("%0.03f\n", (te_delay_time - le_delay_time));
+ }
+ printf("\n");
+ }
+}
+
+void print_err_status(int instance, struct ddr_dimm_training_status *dimm_tr_status)
+{
+ uint32_t read_data = dimm_tr_status->err_status;
+
+ fprintf(stdout, "DIMM %d Tranining status\n", instance);
+ fprintf(stdout, "\tWRLVL_ERR = %d\n", (read_data>>4)&0x1);
+ fprintf(stdout, "\tGTLVL_ERR = %d\n", (read_data>>3)&0x1);
+ fprintf(stdout, "\tRDLVL_ERR = %d\n", (read_data>>2)&0x1);
+ fprintf(stdout, "\tWDQLVL_ERR = %d\n", (read_data>>5)&0x1);
+ fprintf(stdout, "\tCA PARTIY ERR = %d\n", (read_data>>1)&0x1);
+}
+
+CXL_EXPORT int cxl_memdev_ddr_dimm_level_training_status(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_dimm_level_training_status_out *dimm_tr_status;
+ int rc = 0;
+ int i;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_DIMM_LEVEL_TRAINING_STATUS);
+ return -EINVAL;
+ }
+ dimm_tr_status = (void *)cmd->send_cmd->out.payload;
+ for (i = DDR_CTRL0; i < DDR_MAX_SUBSYS; i++) {
+ fprintf(stdout, "dimm:%d level training status\n", i);
+ print_ddr_phy_pll_status(i, &dimm_tr_status->dimm_training_status[i].phy_pll_status);
+ print_ddr_training_status(i, &dimm_tr_status->dimm_training_status[i]);
+ print_margin_vref_low_high(i, &dimm_tr_status->dimm_training_status[i]);
+ print_margin_rdlvl_delay_window(i, &dimm_tr_status->dimm_training_status[i]);
+ print_margin_wrdqlvl_delay_window(i, &dimm_tr_status->dimm_training_status[i]);
+ print_err_status(i, &dimm_tr_status->dimm_training_status[i]);
+ }
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR PARAM SET */
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET_OPCODE 0xFB1E
+#define CXL_MEM_COMMAND_ID_DDR_PARAM_SET_PAYLOAD_IN_SIZE 4
+
+struct ddr_interleave_options {
+ uint8_t ddr_interleave_sz;
+ uint8_t ddr_interleave_ctrl_choice;
+} __attribute__((packed));
+
+
+struct cxl_mbox_ddr_param_set_in {
+ struct ddr_interleave_options ddr_inter;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_param_set(struct cxl_memdev *memdev, u32 ddr_interleave_sz,
+ u32 ddr_interleave_ctrl_choice)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_ddr_param_set_in *ddr_param_set_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_PARAM_SET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_PARAM_SET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ ddr_param_set_in = (void *) cmd->send_cmd->in.payload;
+
+ ddr_param_set_in->ddr_inter.ddr_interleave_sz = ddr_interleave_sz;
+ ddr_param_set_in->ddr_inter.ddr_interleave_ctrl_choice = ddr_interleave_ctrl_choice;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_PARAM_SET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_PARAM_SET);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR PARAM GET */
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET_OPCODE 0xFB1F
+
+struct cxl_ddr_param_get_out
+{
+ struct ddr_interleave_options ddr_inter;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_ddr_param_get(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_ddr_param_get_out *ddr_param_get_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_CXL_DDR_PARAM_GET);
+ return -EINVAL;
+ }
+
+ ddr_param_get_out = (struct cxl_ddr_param_get_out *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "ddr_interleave_sz: %d\n", ddr_param_get_out->ddr_inter.ddr_interleave_sz);
+ fprintf(stdout, "ddr_interleave_ctrl_choice: %d\n", ddr_param_get_out->ddr_inter.ddr_interleave_ctrl_choice);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* CORE VOLTAGE SET */
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET_OPCODE 0xFB26
+#define CXL_MEM_COMMAND_ID_CORE_VOLT_SET_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_core_volt_set_in {
+ float core_volt;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_core_volt_set(struct cxl_memdev *memdev, float core_volt)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_core_volt_set_in *core_volt_set_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CORE_VOLT_SET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_CORE_VOLT_SET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ core_volt_set_in = (void *) cmd->send_cmd->in.payload;
+
+ core_volt_set_in->core_volt = core_volt;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CORE_VOLT_SET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_CORE_VOLT_SET);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* CORE VOLTAGE GET */
+#define CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET_OPCODE 0xFB27
+
+struct cxl_core_volt_get_out
+{
+ float core_volt;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_core_volt_get(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_core_volt_get_out *core_volt_get_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_CXL_CORE_VOLT_GET);
+ return -EINVAL;
+ }
+
+ core_volt_get_out = (struct cxl_core_volt_get_out *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "Core Voltage: %f V\n", core_volt_get_out->core_volt);
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_OPCODE 0xFB21
+#define CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_PAYLOAD_IN_SIZE 4
+
+struct cxl_mbox_oem_err_inj_viral_in {
+ u32 viral_type;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_oem_err_inj_viral(struct cxl_memdev *memdev,
+ u32 viral_type)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_oem_err_inj_viral_in *err_inj_viral_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ err_inj_viral_in = (void *) cmd->send_cmd->in.payload;
+
+ err_inj_viral_in->viral_type = viral_type;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_OEM_ERR_INJ_VIRAL);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_OPCODE 0xFB22
+#define CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_PAYLOAD_IN_SIZE 8
+
+struct cxl_mbox_err_inj_ll_poison_in {
+ u32 en_dis;
+ u32 ll_err_type;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_err_inj_ll_poison(struct cxl_memdev *memdev,
+ u32 en_dis, u32 ll_err_type)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_err_inj_ll_poison_in *err_inj_ll_poison_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ err_inj_ll_poison_in = (void *) cmd->send_cmd->in.payload;
+
+ err_inj_ll_poison_in->ll_err_type = ll_err_type;
+ err_inj_ll_poison_in->en_dis = en_dis;
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_ERR_INJ_LL_POISON);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ_OPCODE 0xFB25
+#define CXL_MEM_COMMAND_ID_PCI_ERR_INJ_PAYLOAD_IN_SIZE 24
+
+struct cxl_mbox_pci_err_inj_in {
+ u32 en_dis;
+ u32 err_type;
+ u32 err_subtype;
+ u32 count;
+ u32 opt_param1;
+ u32 opt_param2;
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_pci_err_inj(struct cxl_memdev *memdev,
+ u32 en_dis,
+ u32 err_type,
+ u32 err_subtype,
+ u32 count,
+ u32 opt_param1,
+ u32 opt_param2)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_pci_err_inj_in *pci_err_inj_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_PCI_ERR_INJ_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_PCI_ERR_INJ_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ pci_err_inj_in = (void *) cmd->send_cmd->in.payload;
+ pci_err_inj_in->en_dis = en_dis;
+ pci_err_inj_in->err_type = err_type;
+ pci_err_inj_in->err_subtype = err_subtype;
+ pci_err_inj_in->count = count;
+ pci_err_inj_in->opt_param1 = opt_param1;
+ pci_err_inj_in->opt_param2 = opt_param2;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_PCI_ERR_INJ) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_PCI_ERR_INJ);
+ return -EINVAL;
+ }
+
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+#define CXL_MEM_COMMAND_ID_READ_LTSSM_STATES CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_READ_LTSSM_STATES_OPCODE 0xFB01
+#define LTSSM_DUMP_SIZE 0x200
+#define LTSSM_EXPECTED_STATE 0x11
+#define LTSSM_STATE_DUMP_COUNT_MAX (LTSSM_DUMP_SIZE / 4)
+
+struct cxl_mbox_read_ltssm_states_out {
+ uint32_t ltssm_states[LTSSM_STATE_DUMP_COUNT_MAX];
+} __attribute__((packed));
+
+
+CXL_EXPORT int cxl_memdev_read_ltssm_states(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_read_ltssm_states_out *read_ltssm_states;
+ uint32_t *ltssm_val;
+ uint32_t offset = 0;
+ uint32_t curr_state;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_READ_LTSSM_STATES_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d:\n%s\n",
+ cxl_memdev_get_devname(memdev), rc, DEVICE_ERRORS[rc]);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_READ_LTSSM_STATES) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id, CXL_MEM_COMMAND_ID_READ_LTSSM_STATES);
+ return -EINVAL;
+ }
+
+ read_ltssm_states = (struct cxl_mbox_read_ltssm_states_out*)cmd->send_cmd->out.payload;
+ fprintf(stdout, "LTSSM STATE CHANGES\n");
+ ltssm_val = read_ltssm_states->ltssm_states;
+ if ((ltssm_val[offset] == ltssm_val[offset + 1]) && (ltssm_val[offset + 1] == 0x0)) {
+ fprintf(stdout, "ltssm state changes are not collected\n");
+ goto out;
+ }
+ while (offset < LTSSM_STATE_DUMP_COUNT_MAX) {
+ if ((ltssm_val[offset] == ltssm_val[offset + 1]) && (ltssm_val[offset + 1] == 0x0))
+ break;
+ curr_state = ltssm_val[offset++];
+ fprintf(stdout,
+ "ltssm state val = 0x%x, %s\n",
+ curr_state,
+ ltssm_state_name[curr_state]);
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+ return 0;
+}
+
+/* DDR PAGE SELECT SET */
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_OPCODE 0xFB2A
+#define CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_PAYLOAD_IN_SIZE 4
+
+struct page_policy_selection {
+ uint8_t page_policy_reg_val;
+} __attribute__((packed)) page_policy_select;
+
+
+struct cxl_mbox_handle_page_selection_in {
+ struct page_policy_selection pp_select;
+} __attribute__((packed));
+
+
+
+CXL_EXPORT int cxl_memdev_ddr_page_select_set(struct cxl_memdev *memdev,
+ u32 page_select_option)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_handle_page_selection_in *handle_page_selection_in;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* update payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ handle_page_selection_in = (void *) cmd->send_cmd->in.payload;
+
+ handle_page_selection_in->pp_select.page_policy_reg_val = page_select_option;
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ rc = -ENXIO;
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_DDR_PAGE_SELECT_SET);
+ return -EINVAL;
+ }
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
+
+/* DDR PAGE SELECT GET */
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET CXL_MEM_COMMAND_ID_RAW
+#define CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET_OPCODE 0xFB2B
+
+struct cxl_mbox_handle_page_selection_out {
+ struct page_policy_selection pp_select;
+} __attribute__((packed));
+
+CXL_EXPORT int cxl_memdev_ddr_page_select_get(struct cxl_memdev *memdev)
+{
+ struct cxl_cmd *cmd;
+ struct cxl_mem_query_commands *query;
+ struct cxl_command_info *cinfo;
+ struct cxl_mbox_handle_page_selection_out *handle_page_selection_out;
+ int rc = 0;
+
+ cmd = cxl_cmd_new_raw(memdev, CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET_OPCODE);
+ if (!cmd) {
+ fprintf(stderr, "%s: cxl_cmd_new_raw returned Null output\n",
+ cxl_memdev_get_devname(memdev));
+ return -ENOMEM;
+ }
+
+ query = cmd->query_cmd;
+ cinfo = &query->commands[cmd->query_idx];
+
+ /* used to force correct payload size */
+ cinfo->size_in = CXL_MEM_COMMAND_ID_LOG_INFO_PAYLOAD_IN_SIZE;
+ if (cinfo->size_in > 0) {
+ cmd->input_payload = calloc(1, cinfo->size_in);
+ if (!cmd->input_payload)
+ return -ENOMEM;
+ cmd->send_cmd->in.payload = (u64)cmd->input_payload;
+ cmd->send_cmd->in.size = cinfo->size_in;
+ }
+
+ rc = cxl_cmd_submit(cmd);
+ if (rc < 0) {
+ fprintf(stderr, "%s: cmd submission failed: %d (%s)\n",
+ cxl_memdev_get_devname(memdev), rc, strerror(-rc));
+ goto out;
+ }
+
+ rc = cxl_cmd_get_mbox_status(cmd);
+ if (rc != 0) {
+ fprintf(stderr, "%s: firmware status: %d\n",
+ cxl_memdev_get_devname(memdev), rc);
+ goto out;
+ }
+
+ if (cmd->send_cmd->id != CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET) {
+ fprintf(stderr, "%s: invalid command id 0x%x (expecting 0x%x)\n",
+ cxl_memdev_get_devname(memdev), cmd->send_cmd->id,
+ CXL_MEM_COMMAND_ID_CXL_DDR_PAGE_SELECT_GET);
+ return -EINVAL;
+ }
+
+ handle_page_selection_out = (struct cxl_mbox_handle_page_selection_out *)cmd->send_cmd->out.payload;
+ fprintf(stdout, "Page_Policy_Reg_Value is selected for %s\n", (handle_page_selection_out->pp_select.page_policy_reg_val)?"open":"close");
+
+out:
+ cxl_cmd_unref(cmd);
+ return rc;
+}
diff --git a/cxl/lib/libcxl.sym b/cxl/lib/libcxl.sym
index aaf2d65..e36b0d4 100644
--- a/cxl/lib/libcxl.sym
+++ b/cxl/lib/libcxl.sym
@@ -70,7 +70,7 @@ global:
cxl_memdev_get_lsa;
cxl_memdev_cmd_identify;
cxl_memdev_get_supported_logs;
- cxl_memdev_get_cel_log;
+ cxl_memdev_get_log;
cxl_memdev_get_event_interrupt_policy;
cxl_memdev_set_event_interrupt_policy;
cxl_memdev_get_timestamp;
@@ -169,4 +169,48 @@ global:
cxl_memdev_dimm_spd_read;
cxl_memdev_ddr_training_status;
cxl_memdev_dimm_slot_info;
+ cxl_memdev_pmic_vtmon_info;
+ cxl_memdev_ddr_margin_run;
+ cxl_memdev_ddr_margin_status;
+ cxl_memdev_ddr_margin_get;
+ cxl_memdev_ddr_stats_run;
+ cxl_memdev_ddr_stats_status;
+ cxl_memdev_ddr_stats_get;
+ cxl_memdev_reboot_mode_set;
+ cxl_memdev_curr_cxl_boot_mode_get;
+ cxl_memdev_pcie_eye_run;
+ cxl_memdev_pcie_eye_status;
+ cxl_memdev_pcie_eye_get_sw;
+ cxl_memdev_pcie_eye_get_hw;
+ cxl_memdev_pcie_eye_get_sw_ber;
+ cxl_memdev_get_cxl_link_status;
+ cxl_memdev_get_device_info;
+ cxl_memdev_read_ddr_temp;
+ cxl_memdev_cxl_hpa_to_dpa;
+ cxl_memdev_get_cxl_membridge_errors;
+ cxl_memdev_get_ddr_bw;
+ cxl_memdev_get_ddr_latency;
+ cxl_memdev_i2c_read;
+ cxl_memdev_i2c_write;
+ cxl_memdev_get_ddr_ecc_err_info;
+ cxl_memdev_start_ddr_ecc_scrub;
+ cxl_memdev_ddr_ecc_scrub_status;
+ cxl_memdev_ddr_cont_scrub_status;
+ cxl_memdev_ddr_cont_scrub_set;
+ cxl_memdev_ddr_init_status;
+ cxl_memdev_get_cxl_membridge_stats;
+ cxl_memdev_trigger_coredump;
+ cxl_memdev_ddr_err_inj_en;
+ cxl_memdev_ddr_err_inj_en;
+ cxl_memdev_ddr_dimm_level_training_status;
+ cxl_memdev_ddr_param_set;
+ cxl_memdev_ddr_param_get;
+ cxl_memdev_core_volt_set;
+ cxl_memdev_core_volt_get;
+ cxl_memdev_oem_err_inj_viral;
+ cxl_memdev_err_inj_ll_poison;
+ cxl_memdev_pci_err_inj;
+ cxl_memdev_read_ltssm_states;
+ cxl_memdev_ddr_page_select_set;
+ cxl_memdev_ddr_page_select_get;
} LIBCXL_3;
diff --git a/cxl/libcxl.h b/cxl/libcxl.h
index 6583af5..4084daa 100644
--- a/cxl/libcxl.h
+++ b/cxl/libcxl.h
@@ -3,6 +3,7 @@
#ifndef _LIBCXL_H_
#define _LIBCXL_H_
+#include <stdbool.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
@@ -57,13 +58,13 @@ int cxl_memdev_set_lsa(struct cxl_memdev *memdev, void *buf, size_t length,
size_t offset);
int cxl_memdev_cmd_identify(struct cxl_memdev *memdev);
int cxl_memdev_device_info_get(struct cxl_memdev *memdev);
-int cxl_memdev_get_fw_info(struct cxl_memdev *memdev);
+int cxl_memdev_get_fw_info(struct cxl_memdev *memdev, bool is_os_img);
int cxl_memdev_transfer_fw(struct cxl_memdev *memdev, u8 action,
u8 slot, u32 offset, int size, unsigned char *data, u32 transfer_fw_opcode);
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, const char *uuid);
+int cxl_memdev_get_log(struct cxl_memdev *memdev, const char *uuid, const unsigned int data_size);
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);
@@ -236,6 +237,51 @@ int cxl_memdev_dimm_spd_read(struct cxl_memdev *memdev, u32 spd_id,
u32 offset, u32 num_bytes);
int cxl_memdev_ddr_training_status(struct cxl_memdev *memdev);
int cxl_memdev_dimm_slot_info(struct cxl_memdev *memdev);
+int cxl_memdev_pmic_vtmon_info(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_margin_run(struct cxl_memdev *memdev, u8 slice_num, u8 rd_wr_margin, u8 ddr_id);
+int cxl_memdev_ddr_margin_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_margin_get(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_stats_run(struct cxl_memdev *memdev, u8 ddr_id,
+ u32 monitor_time, u32 loop_count);
+int cxl_memdev_ddr_stats_status(struct cxl_memdev *memdev, int* run_status, uint32_t* loop_count);
+int cxl_memdev_ddr_stats_get(struct cxl_memdev *memdev);
+int cxl_memdev_reboot_mode_set(struct cxl_memdev *memdev, u8 reboot_mode);
+int cxl_memdev_curr_cxl_boot_mode_get(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_run(struct cxl_memdev *memdev, u8 lane, u8 sw_scan, u8 ber);
+int cxl_memdev_pcie_eye_status(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_get_sw(struct cxl_memdev *memdev, uint offset);
+int cxl_memdev_pcie_eye_get_hw(struct cxl_memdev *memdev);
+int cxl_memdev_pcie_eye_get_sw_ber(struct cxl_memdev *memdev);
+int cxl_memdev_get_cxl_link_status(struct cxl_memdev *memdev);
+int cxl_memdev_get_device_info(struct cxl_memdev *memdev);
+int cxl_memdev_read_ddr_temp(struct cxl_memdev *memdev);
+int cxl_memdev_cxl_hpa_to_dpa(struct cxl_memdev *memdev, u64 hpa_address);
+int cxl_memdev_get_cxl_membridge_errors(struct cxl_memdev *memdev);
+int cxl_memdev_get_ddr_bw(struct cxl_memdev *memdev, u32 timeout, u32 iterations);
+int cxl_memdev_get_ddr_latency(struct cxl_memdev *memdev, u32 measure_time);
+int cxl_memdev_i2c_read(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 num_bytes);
+int cxl_memdev_i2c_write(struct cxl_memdev *memdev, u16 slave_addr, u8 reg_addr, u8 data);
+int cxl_memdev_get_ddr_ecc_err_info(struct cxl_memdev *memdev);
+int cxl_memdev_start_ddr_ecc_scrub(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_ecc_scrub_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_cont_scrub_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_cont_scrub_set(struct cxl_memdev *memdev, u32 cont_scrub_status);
+int cxl_memdev_ddr_init_status(struct cxl_memdev *memdev);
+int cxl_memdev_get_cxl_membridge_stats(struct cxl_memdev *memdev);
+int cxl_memdev_trigger_coredump(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_err_inj_en(struct cxl_memdev *memdev, u32 ddr_id, u32 err_type, u64 ecc_fwc_mask);
+int cxl_memdev_ddr_dimm_level_training_status(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_param_set(struct cxl_memdev *memdev, u32 ddr_interleave_sz,
+ u32 ddr_interleave_ctrl_choice);
+int cxl_memdev_ddr_param_get(struct cxl_memdev *memdev);
+int cxl_memdev_core_volt_set(struct cxl_memdev *memdev, float core_volt);
+int cxl_memdev_core_volt_get(struct cxl_memdev *memdev);
+int cxl_memdev_oem_err_inj_viral(struct cxl_memdev *memdev, u32 viral_type);
+int cxl_memdev_err_inj_ll_poison(struct cxl_memdev *memdev, u32 en_dis, u32 ll_err_type);
+int cxl_memdev_pci_err_inj(struct cxl_memdev *memdev, u32 en_dis, u32 type, u32 err, u32 count, u32 opt1, u32 opt2);
+int cxl_memdev_read_ltssm_states(struct cxl_memdev *memdev);
+int cxl_memdev_ddr_page_select_set(struct cxl_memdev *memdev, u32 page_select_option);
+int cxl_memdev_ddr_page_select_get(struct cxl_memdev *memdev);
#define cxl_memdev_foreach(ctx, memdev) \
for (memdev = cxl_memdev_get_first(ctx); \
diff --git a/cxl/memdev.c b/cxl/memdev.c
index fba1f75..2ba16d4 100644
--- a/cxl/memdev.c
+++ b/cxl/memdev.c
@@ -54,6 +54,10 @@ OPT_UINTEGER('s', "size", ¶m.len, "number of label bytes to operate"), \
OPT_UINTEGER('O', "offset", ¶m.offset, \
"offset into the label area to start operation")
+u64 hpa_address;
+#define HPA_OPTIONS() \
+OPT_U64('h', "hpa", &hpa_address, "host physical address")
+
static const struct option read_options[] = {
BASE_OPTIONS(),
LABEL_OPTIONS(),
@@ -92,9 +96,17 @@ static struct _log_uuid {
OPT_STRING('l', "log_uuid", &log_uuid.uuid, "log-uuid", \
"CEL Log UUID")
-static const struct option cmd_get_cel_log_options[] = {
+static struct _log_size {
+ u32 size;
+} log_size;
+
+#define LOG_SIZE_OPTIONS() \
+OPT_UINTEGER('s', "log_size", &log_size.size, "log-size")
+
+static const struct option cmd_get_log_options[] = {
BASE_OPTIONS(),
LOG_UUID_OPTIONS(),
+ LOG_SIZE_OPTIONS(),
OPT_END(),
};
@@ -146,6 +158,13 @@ static struct _update_fw_params {
bool verbose;
} update_fw_params;
+static struct _fw_img_params {
+ bool is_os;
+} fw_img_params;
+
+#define FW_IMG_OPTIONS() \
+OPT_BOOLEAN('z', "osimage", &fw_img_params.is_os, "select OS(a.k.a boot1) image")
+
#define UPDATE_FW_OPTIONS() \
OPT_FILENAME('f', "file", &update_fw_params.filepath, "rom-file", \
"filepath to read ROM for firmware update"), \
@@ -156,6 +175,7 @@ OPT_BOOLEAN('m', "mock", &update_fw_params.mock, "For testing purposes. Mock tra
static const struct option cmd_update_fw_options[] = {
BASE_OPTIONS(),
UPDATE_FW_OPTIONS(),
+ FW_IMG_OPTIONS(),
OPT_END(),
};
@@ -172,6 +192,7 @@ static const struct option cmd_device_info_get_options[] = {
static const struct option cmd_get_fw_info_options[] = {
BASE_OPTIONS(),
+ FW_IMG_OPTIONS(),
OPT_END(),
};
@@ -1909,6 +1930,403 @@ static const struct option cmd_dimm_slot_info_options[] = {
OPT_END(),
};
+static const struct option cmd_pmic_vtmon_info_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_margin_run_params {
+ u32 slice_num;
+ u32 rd_wr_margin;
+ u32 ddr_id;
+ bool verbose;
+} ddr_margin_run_params;
+
+#define DDR_MARGIN_RUN_OPTIONS() \
+OPT_UINTEGER('s', "slice_num", &ddr_margin_run_params.slice_num, "SLICE NUMBER"), \
+OPT_UINTEGER('m', "rd_wr_margin", &ddr_margin_run_params.rd_wr_margin, "RD/WR MARGIN"), \
+OPT_UINTEGER('i', "ddr_id", &ddr_margin_run_params.ddr_id, "DDR ID")
+
+static const struct option cmd_ddr_margin_run_options[] = {
+ BASE_OPTIONS(),
+ DDR_MARGIN_RUN_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_margin_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_margin_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_stats_run_params {
+ u32 ddr_id;
+ u32 monitor_time;
+ u32 loop_count;
+ bool verbose;
+} ddr_stats_run_params;
+
+#define DDR_STATS_RUN_OPTIONS() \
+OPT_UINTEGER('i', "ddr_id", &ddr_stats_run_params.ddr_id, "DDR ID"), \
+OPT_UINTEGER('m', "monitor_time", &ddr_stats_run_params.monitor_time, "MOINTOR TIME MSEC"), \
+OPT_UINTEGER('n', "loop_count", &ddr_stats_run_params.loop_count, "NUM ITERATION")
+
+static const struct option cmd_ddr_stats_run_options[] = {
+ BASE_OPTIONS(),
+ DDR_STATS_RUN_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_stats_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _reboot_mode_set_params {
+ u32 reboot_mode;
+ bool verbose;
+} reboot_mode_set_params;
+
+#define REBOOT_MODE_SET_OPTIONS() \
+OPT_UINTEGER('m', "reboot_mode", &reboot_mode_set_params.reboot_mode, "0:CXL-IO-MEM or 0xCE:CXL-IO")
+
+static const struct option cmd_reboot_mode_set_options[] = {
+ BASE_OPTIONS(),
+ REBOOT_MODE_SET_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_curr_cxl_boot_mode_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _pcie_eye_run_params {
+ u32 lane;
+ u32 sw_scan;
+ u32 ber;
+ bool verbose;
+} pcie_eye_run_params;
+
+#define PCIE_EYE_RUN_OPTIONS() \
+OPT_UINTEGER('l', "lane", &pcie_eye_run_params.lane, "LANE ID"), \
+OPT_UINTEGER('s', "sw_scan", &pcie_eye_run_params.sw_scan, "SW SCAN"), \
+OPT_UINTEGER('b', "ber", &pcie_eye_run_params.ber, "BER")
+
+static const struct option cmd_pcie_eye_run_options[] = {
+ BASE_OPTIONS(),
+ PCIE_EYE_RUN_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_pcie_eye_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _pcie_eye_get_params {
+ u32 sw_scan;
+ u32 ber;
+ bool verbose;
+} pcie_eye_get_params;
+
+#define PCIE_EYE_GET_OPTIONS() \
+OPT_UINTEGER('s', "sw_scan", &pcie_eye_get_params.sw_scan, "SW SCAN"), \
+OPT_UINTEGER('b', "ber", &pcie_eye_get_params.ber, "BER")
+
+static const struct option cmd_pcie_eye_get_options[] = {
+ BASE_OPTIONS(),
+ PCIE_EYE_GET_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_get_cxl_link_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_get_device_info_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_read_ddr_temp_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_cxl_hpa_to_dpa_options[] = {
+ BASE_OPTIONS(),
+ HPA_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_get_cxl_membridge_errors_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _get_ddr_bw_params {
+ u32 timeout;
+ u32 iterations;
+ bool verbose;
+} get_ddr_bw_params;
+
+#define GET_DDR_BW_OPTIONS() \
+OPT_UINTEGER('t', "temeout", &get_ddr_bw_params.timeout, "Timeout"), \
+OPT_UINTEGER('i', "iterations", &get_ddr_bw_params.iterations, "No Iterations")
+
+static const struct option cmd_get_ddr_bw_options[] = {
+ BASE_OPTIONS(),
+ GET_DDR_BW_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _get_ddr_latency_params {
+ u32 measure_time;
+ bool verbose;
+} get_ddr_latency_params;
+
+#define GET_DDR_LATENCY_OPTIONS() \
+OPT_UINTEGER('t', "measure time", &get_ddr_latency_params.measure_time, "Measure Time in msec")
+
+static const struct option cmd_get_ddr_latency_options[] = {
+ BASE_OPTIONS(),
+ GET_DDR_LATENCY_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _i2c_read_params {
+ u32 slave_addr;
+ u32 reg_addr;
+ u32 num_bytes;
+ bool verbose;
+} i2c_read_params;
+
+#define I2C_READ_OPTIONS() \
+OPT_UINTEGER('s', "slave_addr", &i2c_read_params.slave_addr, "Slave addr"), \
+OPT_UINTEGER('r', "reg_addr", &i2c_read_params.reg_addr, "Reg addr"), \
+OPT_UINTEGER('n', "num_bytes", &i2c_read_params.num_bytes, "Number of bytes")
+
+static const struct option cmd_i2c_read_options[] = {
+ BASE_OPTIONS(),
+ I2C_READ_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _i2c_write_params {
+ u32 slave_addr;
+ u32 reg_addr;
+ u32 data;
+ bool verbose;
+} i2c_write_params;
+
+#define I2C_WRITE_OPTIONS() \
+OPT_UINTEGER('s', "slave_addr", &i2c_write_params.slave_addr, "Slave addr"), \
+OPT_UINTEGER('r', "reg_addr", &i2c_write_params.reg_addr, "Reg addr"), \
+OPT_UINTEGER('d', "data", &i2c_write_params.data, "Data")
+
+static const struct option cmd_i2c_write_options[] = {
+ BASE_OPTIONS(),
+ I2C_WRITE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_get_ddr_ecc_err_info_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_start_ddr_ecc_scrub_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_ecc_scrub_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_cont_scrub_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_cont_scrub_set_params {
+ u32 cont_scrub_status;
+} ddr_cont_scrub_set_params;
+
+#define DDR_CONT_SCRUB_SET_OPTIONS() \
+OPT_UINTEGER('i', "cont_scrub_status", &ddr_cont_scrub_set_params.cont_scrub_status, "Continuous Scrub ON:1 OFF: 0")
+
+static const struct option cmd_ddr_cont_scrub_set_options[] = {
+ BASE_OPTIONS(),
+ DDR_CONT_SCRUB_SET_OPTIONS(),
+ OPT_END(),
+};
+
+
+static const struct option cmd_ddr_init_status_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_get_cxl_membridge_stats_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_trigger_coredump_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_err_inj_en_params {
+ u32 ddr_id;
+ u32 err_type;
+ u64 ecc_fwc_mask;
+ bool verbose;
+} ddr_err_inj_en_params;
+
+#define DDR_ERR_INJ_EN_OPTIONS() \
+OPT_UINTEGER('d', "ddr_id", &ddr_err_inj_en_params.ddr_id, "ddr id <0-DDR_CTRL0,1-DDR_CTRL1>"), \
+OPT_UINTEGER('t', "err_type", &ddr_err_inj_en_params.err_type, "error type\n\t\t\t0: AXI bus parity READ ADDR\n\t\t\t1: AXI bus parity WRITE ADDR\n\t\t\t2: AXI bus parity WRITE DATA\n\t\t\t3: CA bus parity\n\t\t\t4: ECC correctable\n\t\t\t5: ECC uncorrectable\n\t\t\t6: ECC SCRUB"), \
+OPT_U64('m', "ecc_fwc_mask", &ddr_err_inj_en_params.ecc_fwc_mask, "ecc fwc mask <35bit value, upto two bit set for correctable ecc error\n\t\t\tAtleast 4bits for uncoorectable ecc errors\n>")
+
+static const struct option cmd_ddr_err_inj_en_options[] = {
+ BASE_OPTIONS(),
+ DDR_ERR_INJ_EN_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_dimm_level_training_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_set_params {
+ u32 ddr_interleave_sz;
+ u32 ddr_interleave_ctrl_choice;
+} ddr_set_params;
+
+#define DDR_PARAM_SET_OPTIONS() \
+ OPT_UINTEGER('m', "ddr_interleave_sz", &ddr_set_params.ddr_interleave_sz, "Intereleave SZ is: 2 pow m. Input the value of m as the Size"), \
+ OPT_UINTEGER('n', "ddr_interleave_ctrl_choice", &ddr_set_params.ddr_interleave_ctrl_choice, "CTRL Choice: 1=DDR0 2=DDR1 3= DDR0 and DDR1")
+
+static const struct option cmd_ddr_param_set_options[] = {
+ BASE_OPTIONS(),
+ DDR_PARAM_SET_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_param_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _ddr_core_volt_set_params {
+ u32 val1;
+ u32 val2;
+ u32 val3;
+} ddr_core_volt_set_params;
+
+#define CORE_VOLT_SET_OPTIONS() \
+OPT_UINTEGER('i', "core_volt_val1", &ddr_core_volt_set_params.val1, "CORE Voltage val1.val2 val3"), \
+OPT_UINTEGER('m', "core_volt_val2", &ddr_core_volt_set_params.val2, "CORE Voltage val1.val2 val3"), \
+OPT_UINTEGER('n', "core_volt_val3", &ddr_core_volt_set_params.val3, "CORE Voltage val1.val2 val3")
+
+static const struct option cmd_core_volt_set_options[] = {
+ BASE_OPTIONS(),
+ CORE_VOLT_SET_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_core_volt_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _oem_err_inj_viral_params {
+ u32 viral_type;
+ bool verbose;
+} oem_err_inj_viral_params;
+
+#define OEM_ERR_INJ_VIRAL_OPTIONS() \
+OPT_UINTEGER('l', "viral_type", &oem_err_inj_viral_params.viral_type, "viral_type")
+
+static const struct option cmd_oem_err_inj_viral_options[] = {
+ BASE_OPTIONS(),
+ OEM_ERR_INJ_VIRAL_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _err_inj_ll_poison_params {
+ u32 en_dis;
+ u32 ll_err_type;
+ bool verbose;
+} err_inj_ll_poison_params;
+
+#define ERR_INJ_LL_POISON_OPTIONS() \
+OPT_UINTEGER('e', "en_dis", &err_inj_ll_poison_params.en_dis, "enable_disable 0=dis,1=en"), \
+OPT_UINTEGER('l', "ll_err_type", &err_inj_ll_poison_params.ll_err_type, "link level err type 0=mem-poison")
+
+static const struct option cmd_err_inj_ll_poison_options[] = {
+ BASE_OPTIONS(),
+ ERR_INJ_LL_POISON_OPTIONS(),
+ OPT_END(),
+};
+
+static struct _pci_err_in_params {
+ u32 en_dis;
+ u32 err_type;
+ u32 err_subtype;
+ u32 count;
+ u32 opt_param1;
+ u32 opt_param2;
+ bool verbose;
+} pci_err_inj_params;
+
+#define PCI_ERR_INJ_OPTIONS() \
+OPT_UINTEGER('e', "en_dis", &pci_err_inj_params.en_dis, "enable_disable:\n\t0=disable inj\n\t1=enable inj"), \
+OPT_UINTEGER('l', "err_type", &pci_err_inj_params.err_type, "err inj type Group:\n\t0:CRC ERR\n\t1:SEQ NUM ERR\n\t2:DLLP ERR\n\t3:SYMBOL ERR\n\t4:FC CREDIT ERR\n\t5:Special TLP ERR\n"), \
+OPT_UINTEGER('s', "err_subtype", &pci_err_inj_params.err_subtype, "err inj sub-type:\n\tGroup-0:<CRC Error>\n\t\t0 = TX_TLP_LCRC_ERR\n\t\t1 = TX_16B_CRC_ERR_ACK_NAK_DLLP\n\t\t2 = TX_16B_CRC_ERR_UPD_FC\n\t\t3 = TX_TLP_ECRC_ERR\n\t\t4 = TX_FCRC_ERR_TLP\n\t\t5 = TX_PARITY_TSOS_ERR\n\t\t6 = TX_PARITY_SKPOS_ERR\n\t\t8 = RX_LCRC_ERR\n\t\t11= RX_ECRC_ERR\n\n\tGroup-1:<SEQ NUM Error>\n\t\t0 = TLP_ERR_SEQNUM\n\t\t1 = ACK_NAK_DLLP_ERR_SEQNUM\n\n\tGroup-2:<DLLP Error>\n\t\t0 = ACK_NACK_DLLP\n\t\t1 = UPD_FC_DLLP\n\t\t2 = NAK_DLLP\n\n\tGroup-3:<Symbol Error>\n\t\t0 = RSVD_OR_INVRT_SYNC_HDR\n\t\t1 = COM_PAD_TS1\n\t\t2 = COM_PAD_TS2\n\t\t3 = COM_FTS\n\t\t4 = COM_IDL\n\t\t5 = END_EDB\n\t\t6 = STP_SDP\n\t\t7 = COM_SKP\n\n\tGroup-4:<FC Credit Error>\n\t\t0 = POSTED_TLP_HDR\n\t\t1 = NON_POSTED_TLP_HDR\n\t\t2 = CMPL_TLP_HDR\n\t\t4 = POSTED_TLP_DATA\n\t\t5 = NON_POSTED_TLP_DATA\n\n\tGroup-5:<Special TLP Error>\n\t\t0 = DUPLICATE_DLLP\n\t\t1 = NULLIFIED_TLP\n"), \
+OPT_UINTEGER('c', "count", &pci_err_inj_params.count, "err inj count:\n\t1-255: count of err to inject\n\t0: continuous inj until disable\n"), \
+OPT_UINTEGER('x', "opt1", &pci_err_inj_params.opt_param1, "opt1: Optional Extra args1\n\tFor Group-1:Bad Sequence Number(2s compliment in hex): Min:0x1001, Max:0xfff\n\tFor Group-4:Bad update-FC credit val(2s compliment in hex): Min:0x1001, Max:0xfff\n\tFor other Groups: Pass value '0'\n"), \
+OPT_UINTEGER('y', "opt2", &pci_err_inj_params.opt_param2, "opt2: Optional Extra args2\n\tGroup-4:<FC Credit Error>:Target VC_NUMBER: Min:0, Max:7\n\tFor other Groups:Pass value '0'\n")
+
+static const struct option cmd_pci_err_inj_options[] = {
+ BASE_OPTIONS(),
+ PCI_ERR_INJ_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_read_ltssm_states_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
+static struct page_policy_selection {
+ int page_policy_reg_val;
+} page_policy_select;
+
+#define DDR_PAGE_SELECT_SET_OPTIONS() \
+ OPT_INTEGER('p', "page_policy_reg_val", &page_policy_select.page_policy_reg_val, "Value for page policy selection")
+
+static const struct option cmd_ddr_page_select_set_options[] = {
+ BASE_OPTIONS(),
+ DDR_PAGE_SELECT_SET_OPTIONS(),
+ OPT_END(),
+};
+
+static const struct option cmd_ddr_page_select_get_options[] = {
+ BASE_OPTIONS(),
+ OPT_END(),
+};
+
static int action_cmd_clear_event_records(struct cxl_memdev *memdev, struct action_context *actx)
{
u16 record_handle;
@@ -2133,10 +2551,16 @@ static int action_cmd_update_fw(struct cxl_memdev *memdev, struct action_context
}
offset = 0;
- if (update_fw_params.hbo) {
- opcode = 0xCD01; // Pioneer vendor opcode for hbo-transfer-fw
+
+ if (fw_img_params.is_os) {
+ printf("firmware update selected for OS Image\n");
+ opcode = 0xCD04; // Vistara opcode for OS(boot1) image update
} else {
- opcode = 0x0201; // Spec defined transfer-fw
+ if (update_fw_params.hbo) {
+ opcode = 0xCD01; // Pioneer vendor opcode for hbo-transfer-fw
+ } else {
+ opcode = 0x0201; // Spec defined transfer-fw
+ }
}
for (int i = 0; i < num_blocks; i++)
@@ -2248,15 +2672,15 @@ static int action_cmd_set_event_interrupt_policy(struct cxl_memdev *memdev, stru
return cxl_memdev_set_event_interrupt_policy(memdev, interrupt_policy_params.policy);
}
-static int action_cmd_get_cel_log(struct cxl_memdev *memdev, struct action_context *actx)
+static int action_cmd_get_log(struct cxl_memdev *memdev, struct action_context *actx)
{
if (cxl_memdev_is_active(memdev)) {
- fprintf(stderr, "%s: memdev active, get_cel_log\n",
+ fprintf(stderr, "%s: memdev active, get_log\n",
cxl_memdev_get_devname(memdev));
return -EBUSY;
}
- return cxl_memdev_get_cel_log(memdev, log_uuid.uuid);
+ return cxl_memdev_get_log(memdev, log_uuid.uuid, log_size.size);
}
static int action_cmd_get_supported_logs(struct cxl_memdev *memdev, struct action_context *actx)
@@ -2358,7 +2782,7 @@ static int action_cmd_get_fw_info(struct cxl_memdev *memdev, struct action_conte
return -EBUSY;
}
- return cxl_memdev_get_fw_info(memdev);
+ return cxl_memdev_get_fw_info(memdev, fw_img_params.is_os);
}
static int action_cmd_activate_fw(struct cxl_memdev *memdev, struct action_context *actx)
@@ -3463,32 +3887,594 @@ static int action_cmd_dimm_slot_info(struct cxl_memdev *memdev, struct action_co
return cxl_memdev_dimm_slot_info(memdev);
}
-static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
+static int action_cmd_pmic_vtmon_info(struct cxl_memdev *memdev, struct action_context *actx)
{
- size_t size = param.len, read_len;
- unsigned char *buf;
- int rc;
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort pmic_vtmon_info\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
- if (cxl_memdev_is_active(memdev)) {
- fprintf(stderr, "%s is active, abort label write\n",
- cxl_memdev_get_devname(memdev));
- return -EBUSY;
- }
+ return cxl_memdev_pmic_vtmon_info(memdev);
+}
- if (!size) {
- size_t lsa_size = cxl_memdev_get_lsa_size(memdev);
+static int action_cmd_ddr_margin_run(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_margin_run\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
- fseek(actx->f_in, 0L, SEEK_END);
- size = ftell(actx->f_in);
- fseek(actx->f_in, 0L, SEEK_SET);
+ return cxl_memdev_ddr_margin_run(memdev, ddr_margin_run_params.slice_num,
+ ddr_margin_run_params.rd_wr_margin,
+ ddr_margin_run_params.ddr_id);
+}
- if (size > lsa_size) {
- fprintf(stderr,
- "File size (%zu) greater than LSA size (%zu), aborting\n",
- size, lsa_size);
- return -EINVAL;
- }
- }
+static int action_cmd_ddr_margin_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_margin_status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_margin_status(memdev);
+}
+
+static int action_cmd_ddr_margin_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ int rc = 0;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_margin_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ rc = cxl_memdev_ddr_margin_get(memdev);
+ if(rc)
+ {
+ fprintf(stderr,
+ "ddr_margin_get read failed");
+ goto abort;
+ }
+
+abort:
+ return rc;
+}
+
+static int action_cmd_ddr_stats_run(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_stats_run\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_stats_run(memdev, ddr_stats_run_params.ddr_id,
+ ddr_stats_run_params.monitor_time,
+ ddr_stats_run_params.loop_count);
+}
+
+static int action_cmd_ddr_stats_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ int rc = 0;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_stats_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ rc = cxl_memdev_ddr_stats_get(memdev);
+ if(rc)
+ {
+ fprintf(stderr,
+ "ddr_stats_get read failed");
+ goto abort;
+ }
+
+abort:
+ return rc;
+}
+
+static int action_cmd_reboot_mode_set(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort reboot mode set\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_reboot_mode_set(memdev, reboot_mode_set_params.reboot_mode);
+}
+
+static int action_cmd_curr_cxl_boot_mode_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ int rc = 0;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort curr cxl boot mode get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ rc = cxl_memdev_curr_cxl_boot_mode_get(memdev);
+ if(rc)
+ {
+ fprintf(stderr,
+ "curr_cxl_boot_mode_get failed");
+ goto abort;
+ }
+
+abort:
+ return rc;
+}
+
+static int action_cmd_pcie_eye_run(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort pcie_eye_run\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_pcie_eye_run(memdev, pcie_eye_run_params.lane,
+ pcie_eye_run_params.sw_scan,
+ pcie_eye_run_params.ber);
+}
+
+static int action_cmd_pcie_eye_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort pcie_eye_status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_pcie_eye_status(memdev);
+}
+
+static int action_cmd_pcie_eye_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ #define NUM_EYESCOPE_VERT_VALS 511
+ #define TOTAL_EYESCOPE_VERT_VALS ((NUM_EYESCOPE_VERT_VALS * 2) + 1)
+ #define VERT_SKIP 15
+
+ int rc = 0;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort pcie_eye_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ if(pcie_eye_get_params.sw_scan) {
+ for (int i = 0; i < TOTAL_EYESCOPE_VERT_VALS; i += VERT_SKIP) {
+ rc = cxl_memdev_pcie_eye_get_sw(memdev, i);
+ if (rc != 0)
+ {
+ fprintf(stderr,
+ "pcie_eye_get read failed or sw_scan not enabled\n");
+ goto abort;
+ }
+ }
+ if(pcie_eye_get_params.ber) {
+ rc = cxl_memdev_pcie_eye_get_sw_ber(memdev);
+ if (rc != 0)
+ {
+ fprintf(stderr,
+ "pcie_eye_get read failed OR BER is not enabled\n");
+ goto abort;
+ }
+ }
+ } else {
+ rc = cxl_memdev_pcie_eye_get_hw(memdev);
+ if(rc)
+ {
+ fprintf(stderr,
+ "pcie_eye_get read failed hw scan not enabled");
+ goto abort;
+ }
+ }
+abort:
+ return rc;
+}
+
+static int action_cmd_get_cxl_link_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort get_cxl_link_status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_cxl_link_status(memdev);
+}
+
+static int action_cmd_get_device_info(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort get_device_info\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_device_info(memdev);
+}
+
+static int action_cmd_read_ddr_temp(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort read_ddr_temp\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_read_ddr_temp(memdev);
+}
+
+static int action_cmd_cxl_hpa_to_dpa(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort hpa to dpa\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_cxl_hpa_to_dpa(memdev, hpa_address);
+}
+
+static int action_cmd_get_cxl_membridge_errors(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort cxl membridge errors\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_cxl_membridge_errors(memdev);
+}
+
+static int action_cmd_get_ddr_bw(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort get_ddr_bw\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_ddr_bw(memdev, get_ddr_bw_params.timeout, get_ddr_bw_params.iterations);
+}
+
+static int action_cmd_get_ddr_latency(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort get_ddr_latency\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_ddr_latency(memdev, get_ddr_latency_params.measure_time);
+}
+
+static int action_cmd_i2c_read(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort i2c_read\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_i2c_read(memdev, i2c_read_params.slave_addr, i2c_read_params.reg_addr, i2c_read_params.num_bytes);
+}
+
+static int action_cmd_i2c_write(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort i2c_write\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_i2c_write(memdev, i2c_write_params.slave_addr, i2c_write_params.reg_addr, i2c_write_params.data);
+}
+
+static int action_cmd_get_ddr_ecc_err_info(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort get-ddr-ecc-err-info\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_get_ddr_ecc_err_info(memdev);
+}
+
+static int action_cmd_start_ddr_ecc_scrub(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort start-ddr-ecc-scrub\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_start_ddr_ecc_scrub(memdev);
+}
+
+static int action_cmd_ddr_ecc_scrub_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-ecc-scrub-status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_ecc_scrub_status(memdev);
+}
+
+static int action_cmd_ddr_cont_scrub_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-cont-scrub-status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_cont_scrub_status(memdev);
+}
+
+static int action_cmd_ddr_cont_scrub_set(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-cont-scrub-set\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_cont_scrub_set(memdev,
+ ddr_cont_scrub_set_params.cont_scrub_status);
+}
+
+static int action_cmd_ddr_init_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-init-status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+ return cxl_memdev_ddr_init_status(memdev);
+}
+
+static int action_cmd_get_cxl_membridge_stats(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort cxl membridge stats\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+ return cxl_memdev_get_cxl_membridge_stats(memdev);
+}
+
+static int action_cmd_trigger_coredump(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-ecc-scrub-status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_trigger_coredump(memdev);
+}
+
+static int action_cmd_ddr_err_inj_en(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-err-inj-en\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_err_inj_en(memdev, ddr_err_inj_en_params.ddr_id, ddr_err_inj_en_params.err_type, ddr_err_inj_en_params.ecc_fwc_mask);
+}
+
+static int action_cmd_ddr_dimm_level_training_status(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr-dimm-level-training-status\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_dimm_level_training_status(memdev);
+}
+
+static int action_cmd_ddr_param_set(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_param_set\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_param_set(memdev, ddr_set_params.ddr_interleave_sz,
+ ddr_set_params.ddr_interleave_ctrl_choice);
+}
+
+static int action_cmd_ddr_param_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_param_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_param_get(memdev);
+}
+
+static int action_cmd_core_volt_set(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ float volt;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort core_volt_set\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ volt = ddr_core_volt_set_params.val1 + (ddr_core_volt_set_params.val2 / 10.0) +
+ (ddr_core_volt_set_params.val3 / 100.0);
+
+ return cxl_memdev_core_volt_set(memdev, volt);
+}
+
+static int action_cmd_core_volt_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort core_volt_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_core_volt_get(memdev);
+}
+
+static int action_cmd_oem_err_inj_viral(struct cxl_memdev *memdev, struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort oem_err_inj_viral\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_oem_err_inj_viral(memdev, oem_err_inj_viral_params.viral_type);
+}
+
+static int action_cmd_err_inj_ll_poison(struct cxl_memdev *memdev, struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort err_inj_ll_poison\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_err_inj_ll_poison(memdev, err_inj_ll_poison_params.en_dis,
+ err_inj_ll_poison_params.ll_err_type);
+}
+
+static int action_cmd_pci_err_inj(struct cxl_memdev *memdev, struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort err_inj_ll_poison\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_pci_err_inj(memdev, pci_err_inj_params.en_dis,
+ pci_err_inj_params.err_type,
+ pci_err_inj_params.err_subtype,
+ pci_err_inj_params.count,
+ pci_err_inj_params.opt_param1,
+ pci_err_inj_params.opt_param2);
+}
+
+static int action_cmd_read_ltssm_states(struct cxl_memdev *memdev, struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort read-ltssm-state-changes\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_read_ltssm_states(memdev);
+}
+
+
+static int action_cmd_ddr_page_select_set(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_param_set\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_page_select_set(memdev, page_policy_select.page_policy_reg_val);
+}
+
+static int action_cmd_ddr_page_select_get(struct cxl_memdev *memdev,
+ struct action_context *actx)
+{
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s: memdev active, abort ddr_param_get\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ return cxl_memdev_ddr_page_select_get(memdev);
+}
+
+
+static int action_write(struct cxl_memdev *memdev, struct action_context *actx)
+{
+ size_t size = param.len, read_len;
+ unsigned char *buf;
+ int rc;
+
+ if (cxl_memdev_is_active(memdev)) {
+ fprintf(stderr, "%s is active, abort label write\n",
+ cxl_memdev_get_devname(memdev));
+ return -EBUSY;
+ }
+
+ if (!size) {
+ size_t lsa_size = cxl_memdev_get_lsa_size(memdev);
+
+ fseek(actx->f_in, 0L, SEEK_END);
+ size = ftell(actx->f_in);
+ fseek(actx->f_in, 0L, SEEK_SET);
+
+ if (size > lsa_size) {
+ fprintf(stderr,
+ "File size (%zu) greater than LSA size (%zu), aborting\n",
+ size, lsa_size);
+ return -EINVAL;
+ }
+ }
buf = calloc(1, size);
if (!buf)
@@ -3707,10 +4693,10 @@ int cmd_get_supported_logs(int argc, const char **argv, struct cxl_ctx *ctx)
return rc >= 0 ? 0 : EXIT_FAILURE;
}
-int cmd_get_cel_log(int argc, const char **argv, struct cxl_ctx *ctx)
+int cmd_get_log(int argc, const char **argv, struct cxl_ctx *ctx)
{
- int rc = memdev_action(argc, argv, ctx, action_cmd_get_cel_log, cmd_get_cel_log_options,
- "cxl get-cel-log <mem0> [<mem1>..<memN>] [<options>]");
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_log, cmd_get_log_options,
+ "cxl get-log <mem0> [<mem1>..<memN>] [<options>]");
return rc >= 0 ? 0 : EXIT_FAILURE;
}
@@ -4528,3 +5514,321 @@ int cmd_dimm_slot_info(int argc, const char **argv, struct cxl_ctx *ctx)
return rc >= 0 ? 0 : EXIT_FAILURE;
}
+
+int cmd_pmic_vtmon_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_pmic_vtmon_info, cmd_pmic_vtmon_info_options,
+ "cxl pmic-vtmon-info <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_run, cmd_ddr_margin_run_options,
+ "cxl ddr-margin-run <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_status, cmd_ddr_margin_status_options,
+ "cxl ddr-margin-status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_margin_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_margin_get, cmd_ddr_margin_get_options,
+ "cxl ddr-margin-get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_stats_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_stats_run, cmd_ddr_stats_run_options,
+ "cxl ddr-stats-run <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_stats_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_stats_get, cmd_ddr_stats_get_options,
+ "cxl ddr-stats-get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_curr_cxl_boot_mode_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_curr_cxl_boot_mode_get, cmd_curr_cxl_boot_mode_get_options,
+ "cxl curr-cxl-boot-mode-get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_reboot_mode_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_reboot_mode_set, cmd_reboot_mode_set_options,
+ "cxl reboot-mode-set <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_run(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_run, cmd_pcie_eye_run_options,
+ "cxl pcie-eye-run <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_status, cmd_pcie_eye_status_options,
+ "cxl pcie-eye-status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pcie_eye_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_pcie_eye_get, cmd_pcie_eye_get_options,
+ "cxl pcie-eye-get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_link_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_link_status, cmd_get_cxl_link_status_options,
+ "cxl get_cxl_link_status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_device_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_device_info, cmd_get_device_info_options,
+ "cxl get_device_info <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_read_ddr_temp(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_read_ddr_temp, cmd_read_ddr_temp_options,
+ "cxl read_ddr_temp <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_cxl_hpa_to_dpa(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_cxl_hpa_to_dpa, cmd_cxl_hpa_to_dpa_options,
+ "cxl hpa to dpa");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_membridge_errors(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_membridge_errors, cmd_get_cxl_membridge_errors_options,
+ "cxl get_cxl_membridge_errors");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_bw(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_bw, cmd_get_ddr_bw_options,
+ "cxl get-ddr-bw <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_latency(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_latency, cmd_get_ddr_latency_options,
+ "cxl get-ddr-latency <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_i2c_read(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_i2c_read, cmd_i2c_read_options,
+ "cxl i2c-read <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_i2c_write(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_i2c_write, cmd_i2c_write_options,
+ "cxl i2c-write <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_ddr_ecc_err_info(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_ddr_ecc_err_info, cmd_get_ddr_ecc_err_info_options,
+ "cxl get-ddr-ecc-err-info <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_start_ddr_ecc_scrub(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_start_ddr_ecc_scrub, cmd_start_ddr_ecc_scrub_options,
+ "cxl start-ddr-ecc-scrub <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_ecc_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_ecc_scrub_status, cmd_ddr_ecc_scrub_status_options,
+ "cxl ddr-ecc-scrub-status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_cont_scrub_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_cont_scrub_status, cmd_ddr_cont_scrub_status_options,
+ "cxl ddr-cont-scrub-status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_cont_scrub_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_cont_scrub_set, cmd_ddr_cont_scrub_set_options,
+ "cxl core_volt_set <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_init_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_init_status, cmd_ddr_init_status_options,
+ "cxl ddr-init-status <mem0> [<mem1>..<memN>] [<options>]");
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_get_cxl_membridge_stats(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_get_cxl_membridge_stats, cmd_get_cxl_membridge_stats_options,
+ "cxl get_cxl_membridge_errors");
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_trigger_coredump(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_trigger_coredump, cmd_trigger_coredump_options,
+ "cxl trigger-coredump <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_err_inj_en(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_err_inj_en, cmd_ddr_err_inj_en_options,
+ "cxl ddr-err-inj-en <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_dimm_level_training_status(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_dimm_level_training_status, cmd_ddr_dimm_level_training_options,
+ "cxl ddr-dimm-level-training-status <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_param_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_param_set, cmd_ddr_param_set_options,
+ "cxl ddr_param_set <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_param_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_param_get, cmd_ddr_param_get_options,
+ "cxl ddr_param_get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_core_volt_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_core_volt_set, cmd_core_volt_set_options,
+ "cxl core_volt_set <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_core_volt_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_core_volt_get, cmd_core_volt_get_options,
+ "cxl core_volt_get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_oem_err_inj_viral(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_oem_err_inj_viral, cmd_oem_err_inj_viral_options,
+ "cxl oem_err_inj_viral <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_err_inj_ll_poison(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_err_inj_ll_poison, cmd_err_inj_ll_poison_options,
+ "cxl err_inj_ll_poison <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_pci_err_inj(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_pci_err_inj, cmd_pci_err_inj_options,
+ "cxl pci_err_inj <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_read_ltssm_states(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_read_ltssm_states, cmd_read_ltssm_states_options,
+ "cxl read-ltssm-state-changes <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_page_select_set(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_page_select_set, cmd_ddr_page_select_set_options,
+ "cxl ddr-page-select-set <<mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}
+
+int cmd_ddr_page_select_get(int argc, const char **argv, struct cxl_ctx *ctx)
+{
+ int rc = memdev_action(argc, argv, ctx, action_cmd_ddr_page_select_get, cmd_ddr_page_select_get_options,
+ "cxl ddr-page-select-get <mem0> [<mem1>..<memN>] [<options>]");
+
+ return rc >= 0 ? 0 : EXIT_FAILURE;
+}